mlxsw: reg: Add XM Direct Register

The XMDR allows direct access to the XM device via the switch.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jiri Pirko 2020-12-14 13:30:27 +02:00 committed by Jakub Kicinski
parent 22f07b86d4
commit be6ba3b61e

View File

@ -8469,11 +8469,278 @@ mlxsw_reg_rmft2_ipv6_pack(char *payload, bool v, u16 offset, u16 virtual_router,
mlxsw_reg_rmft2_sip6_mask_memcpy_to(payload, (void *)&sip6_mask);
}
/* Note that XRALXX register position violates the rule of ordering register
* definition by the ID. However, XRALXX pack helpers are using RALXX pack
* helpers, RALXX registers have higher IDs.
/* Note that XMDR and XRALXX register positions violate the rule of ordering
* register definitions by the ID. However, XRALXX pack helpers are
* using RALXX pack helpers, RALXX registers have higher IDs.
* Also XMDR is using RALUE enums.
*/
/* XMDR - XM Direct Register
* -------------------------
* The XMDR allows direct access to the XM device via the switch.
* Working in synchronous mode. FW waits for response from the XLT
* for each command. FW acks the XMDR accordingly.
*/
#define MLXSW_REG_XMDR_ID 0x7803
#define MLXSW_REG_XMDR_BASE_LEN 0x20
#define MLXSW_REG_XMDR_TRANS_LEN 0x80
#define MLXSW_REG_XMDR_LEN (MLXSW_REG_XMDR_BASE_LEN + \
MLXSW_REG_XMDR_TRANS_LEN)
MLXSW_REG_DEFINE(xmdr, MLXSW_REG_XMDR_ID, MLXSW_REG_XMDR_LEN);
/* reg_xmdr_bulk_entry
* Bulk_entry
* 0: Last entry - immediate flush of XRT-cache
* 1: Bulk entry - do not flush the XRT-cache
* Access: OP
*/
MLXSW_ITEM32(reg, xmdr, bulk_entry, 0x04, 8, 1);
/* reg_xmdr_num_rec
* Number of records for Direct access to XM
* Supported: 0..4 commands (except NOP which is a filler)
* 0 commands is reserved when bulk_entry = 1.
* 0 commands is allowed when bulk_entry = 0 for immediate XRT-cache flush.
* Access: OP
*/
MLXSW_ITEM32(reg, xmdr, num_rec, 0x04, 0, 4);
/* reg_xmdr_reply_vect
* Reply Vector
* Bit i for command index i+1
* values per bit:
* 0: failed
* 1: succeeded
* e.g. if commands 1, 2, 4 succeeded and command 3 failed then binary
* value will be 0b1011
* Access: RO
*/
MLXSW_ITEM_BIT_ARRAY(reg, xmdr, reply_vect, 0x08, 4, 1);
static inline void mlxsw_reg_xmdr_pack(char *payload, bool bulk_entry)
{
MLXSW_REG_ZERO(xmdr, payload);
mlxsw_reg_xmdr_bulk_entry_set(payload, bulk_entry);
}
enum mlxsw_reg_xmdr_c_cmd_id {
MLXSW_REG_XMDR_C_CMD_ID_LT_ROUTE_V4 = 0x30,
MLXSW_REG_XMDR_C_CMD_ID_LT_ROUTE_V6 = 0x31,
};
#define MLXSW_REG_XMDR_C_LT_ROUTE_V4_LEN 32
#define MLXSW_REG_XMDR_C_LT_ROUTE_V6_LEN 48
/* reg_xmdr_c_cmd_id
*/
MLXSW_ITEM32(reg, xmdr_c, cmd_id, 0x00, 24, 8);
/* reg_xmdr_c_seq_number
*/
MLXSW_ITEM32(reg, xmdr_c, seq_number, 0x00, 12, 12);
enum mlxsw_reg_xmdr_c_ltr_op {
/* Activity is set */
MLXSW_REG_XMDR_C_LTR_OP_WRITE = 0,
/* There is no update mask. All fields are updated. */
MLXSW_REG_XMDR_C_LTR_OP_UPDATE = 1,
MLXSW_REG_XMDR_C_LTR_OP_DELETE = 2,
};
/* reg_xmdr_c_ltr_op
* Operation.
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_op, 0x04, 24, 8);
/* reg_xmdr_c_ltr_trap_action
* Trap action.
* Values are defined in enum mlxsw_reg_ralue_trap_action.
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_trap_action, 0x04, 20, 4);
enum mlxsw_reg_xmdr_c_ltr_trap_id_num {
MLXSW_REG_XMDR_C_LTR_TRAP_ID_NUM_RTR_INGRESS0,
MLXSW_REG_XMDR_C_LTR_TRAP_ID_NUM_RTR_INGRESS1,
MLXSW_REG_XMDR_C_LTR_TRAP_ID_NUM_RTR_INGRESS2,
MLXSW_REG_XMDR_C_LTR_TRAP_ID_NUM_RTR_INGRESS3,
};
/* reg_xmdr_c_ltr_trap_id_num
* Trap-ID number.
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_trap_id_num, 0x04, 16, 4);
/* reg_xmdr_c_ltr_virtual_router
* Virtual Router ID.
* Range is 0..cap_max_virtual_routers-1
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_virtual_router, 0x04, 0, 16);
/* reg_xmdr_c_ltr_prefix_len
* Number of bits in the prefix of the LPM route.
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_prefix_len, 0x08, 24, 8);
/* reg_xmdr_c_ltr_bmp_len
* The best match prefix length in the case that there is no match for
* longer prefixes.
* If (entry_type != MARKER_ENTRY), bmp_len must be equal to prefix_len
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_bmp_len, 0x08, 16, 8);
/* reg_xmdr_c_ltr_entry_type
* Entry type.
* Values are defined in enum mlxsw_reg_ralue_entry_type.
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_entry_type, 0x08, 4, 4);
enum mlxsw_reg_xmdr_c_ltr_action_type {
MLXSW_REG_XMDR_C_LTR_ACTION_TYPE_LOCAL,
MLXSW_REG_XMDR_C_LTR_ACTION_TYPE_REMOTE,
MLXSW_REG_XMDR_C_LTR_ACTION_TYPE_IP2ME,
};
/* reg_xmdr_c_ltr_action_type
* Action Type.
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_action_type, 0x08, 0, 4);
/* reg_xmdr_c_ltr_erif
* Egress Router Interface.
* Only relevant in case of LOCAL action.
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_erif, 0x10, 0, 16);
/* reg_xmdr_c_ltr_adjacency_index
* Points to the first entry of the group-based ECMP.
* Only relevant in case of REMOTE action.
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_adjacency_index, 0x10, 0, 24);
#define MLXSW_REG_XMDR_C_LTR_POINTER_TO_TUNNEL_DISABLED_MAGIC 0xFFFFFF
/* reg_xmdr_c_ltr_pointer_to_tunnel
* Only relevant in case of IP2ME action.
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_pointer_to_tunnel, 0x10, 0, 24);
/* reg_xmdr_c_ltr_ecmp_size
* Amount of sequential entries starting
* from the adjacency_index (the number of ECMPs).
* The valid range is 1-64, 512, 1024, 2048 and 4096.
* Only relevant in case of REMOTE action.
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_ecmp_size, 0x14, 0, 32);
/* reg_xmdr_c_ltr_dip*
* The prefix of the route or of the marker that the object of the LPM
* is compared with. The most significant bits of the dip are the prefix.
* The least significant bits must be '0' if the prefix_len is smaller
* than 128 for IPv6 or smaller than 32 for IPv4.
*/
MLXSW_ITEM32(reg, xmdr_c, ltr_dip4, 0x1C, 0, 32);
MLXSW_ITEM_BUF(reg, xmdr_c, ltr_dip6, 0x1C, 16);
static inline void
mlxsw_reg_xmdr_c_ltr_pack(char *xmdr_payload, unsigned int trans_offset,
enum mlxsw_reg_xmdr_c_cmd_id cmd_id, u16 seq_number,
enum mlxsw_reg_xmdr_c_ltr_op op, u16 virtual_router,
u8 prefix_len)
{
char *payload = xmdr_payload + MLXSW_REG_XMDR_BASE_LEN + trans_offset;
u8 num_rec = mlxsw_reg_xmdr_num_rec_get(xmdr_payload);
mlxsw_reg_xmdr_num_rec_set(xmdr_payload, num_rec + 1);
mlxsw_reg_xmdr_c_cmd_id_set(payload, cmd_id);
mlxsw_reg_xmdr_c_seq_number_set(payload, seq_number);
mlxsw_reg_xmdr_c_ltr_op_set(payload, op);
mlxsw_reg_xmdr_c_ltr_virtual_router_set(payload, virtual_router);
mlxsw_reg_xmdr_c_ltr_prefix_len_set(payload, prefix_len);
mlxsw_reg_xmdr_c_ltr_entry_type_set(payload,
MLXSW_REG_RALUE_ENTRY_TYPE_ROUTE_ENTRY);
mlxsw_reg_xmdr_c_ltr_bmp_len_set(payload, prefix_len);
}
static inline unsigned int
mlxsw_reg_xmdr_c_ltr_pack4(char *xmdr_payload, unsigned int trans_offset,
u16 seq_number, enum mlxsw_reg_xmdr_c_ltr_op op,
u16 virtual_router, u8 prefix_len, u32 *dip)
{
char *payload = xmdr_payload + MLXSW_REG_XMDR_BASE_LEN + trans_offset;
mlxsw_reg_xmdr_c_ltr_pack(xmdr_payload, trans_offset,
MLXSW_REG_XMDR_C_CMD_ID_LT_ROUTE_V4,
seq_number, op, virtual_router, prefix_len);
if (dip)
mlxsw_reg_xmdr_c_ltr_dip4_set(payload, *dip);
return MLXSW_REG_XMDR_C_LT_ROUTE_V4_LEN;
}
static inline unsigned int
mlxsw_reg_xmdr_c_ltr_pack6(char *xmdr_payload, unsigned int trans_offset,
u16 seq_number, enum mlxsw_reg_xmdr_c_ltr_op op,
u16 virtual_router, u8 prefix_len, const void *dip)
{
char *payload = xmdr_payload + MLXSW_REG_XMDR_BASE_LEN + trans_offset;
mlxsw_reg_xmdr_c_ltr_pack(xmdr_payload, trans_offset,
MLXSW_REG_XMDR_C_CMD_ID_LT_ROUTE_V6,
seq_number, op, virtual_router, prefix_len);
if (dip)
mlxsw_reg_xmdr_c_ltr_dip6_memcpy_to(payload, dip);
return MLXSW_REG_XMDR_C_LT_ROUTE_V6_LEN;
}
static inline void
mlxsw_reg_xmdr_c_ltr_act_remote_pack(char *xmdr_payload, unsigned int trans_offset,
enum mlxsw_reg_ralue_trap_action trap_action,
enum mlxsw_reg_xmdr_c_ltr_trap_id_num trap_id_num,
u32 adjacency_index, u16 ecmp_size)
{
char *payload = xmdr_payload + MLXSW_REG_XMDR_BASE_LEN + trans_offset;
mlxsw_reg_xmdr_c_ltr_action_type_set(payload, MLXSW_REG_XMDR_C_LTR_ACTION_TYPE_REMOTE);
mlxsw_reg_xmdr_c_ltr_trap_action_set(payload, trap_action);
mlxsw_reg_xmdr_c_ltr_trap_id_num_set(payload, trap_id_num);
mlxsw_reg_xmdr_c_ltr_adjacency_index_set(payload, adjacency_index);
mlxsw_reg_xmdr_c_ltr_ecmp_size_set(payload, ecmp_size);
}
static inline void
mlxsw_reg_xmdr_c_ltr_act_local_pack(char *xmdr_payload, unsigned int trans_offset,
enum mlxsw_reg_ralue_trap_action trap_action,
enum mlxsw_reg_xmdr_c_ltr_trap_id_num trap_id_num, u16 erif)
{
char *payload = xmdr_payload + MLXSW_REG_XMDR_BASE_LEN + trans_offset;
mlxsw_reg_xmdr_c_ltr_action_type_set(payload, MLXSW_REG_XMDR_C_LTR_ACTION_TYPE_LOCAL);
mlxsw_reg_xmdr_c_ltr_trap_action_set(payload, trap_action);
mlxsw_reg_xmdr_c_ltr_trap_id_num_set(payload, trap_id_num);
mlxsw_reg_xmdr_c_ltr_erif_set(payload, erif);
}
static inline void mlxsw_reg_xmdr_c_ltr_act_ip2me_pack(char *xmdr_payload,
unsigned int trans_offset)
{
char *payload = xmdr_payload + MLXSW_REG_XMDR_BASE_LEN + trans_offset;
mlxsw_reg_xmdr_c_ltr_action_type_set(payload, MLXSW_REG_XMDR_C_LTR_ACTION_TYPE_IP2ME);
mlxsw_reg_xmdr_c_ltr_pointer_to_tunnel_set(payload,
MLXSW_REG_XMDR_C_LTR_POINTER_TO_TUNNEL_DISABLED_MAGIC);
}
static inline void mlxsw_reg_xmdr_c_ltr_act_ip2me_tun_pack(char *xmdr_payload,
unsigned int trans_offset,
u32 pointer_to_tunnel)
{
char *payload = xmdr_payload + MLXSW_REG_XMDR_BASE_LEN + trans_offset;
mlxsw_reg_xmdr_c_ltr_action_type_set(payload, MLXSW_REG_XMDR_C_LTR_ACTION_TYPE_IP2ME);
mlxsw_reg_xmdr_c_ltr_pointer_to_tunnel_set(payload, pointer_to_tunnel);
}
/* XRALTA - XM Router Algorithmic LPM Tree Allocation Register
* -----------------------------------------------------------
* The XRALTA is used to allocate the XLT LPM trees.
@ -11487,6 +11754,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
MLXSW_REG(rigr2),
MLXSW_REG(recr2),
MLXSW_REG(rmft2),
MLXSW_REG(xmdr),
MLXSW_REG(xralta),
MLXSW_REG(xralst),
MLXSW_REG(xraltb),