diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/cmd.h | 30 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core.c | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core.h | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/minimal.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/pci.c | 33 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/reg.h | 670 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 857 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h | 75 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum_router_xm.c | 812 |
11 files changed, 244 insertions, 2266 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile index 1a465fd5d8b3..c57e293cca25 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Makefile +++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile @@ -12,7 +12,6 @@ mlxsw_i2c-objs := i2c.o obj-$(CONFIG_MLXSW_SPECTRUM) += mlxsw_spectrum.o mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \ spectrum_switchdev.o spectrum_router.o \ - spectrum_router_xm.o \ spectrum1_kvdl.o spectrum2_kvdl.o \ spectrum_kvdl.o \ spectrum_acl_tcam.o spectrum_acl_ctcam.o \ diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index 51b260d54237..91f68fb0b420 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -343,23 +343,6 @@ static inline int mlxsw_cmd_boardinfo(struct mlxsw_core *mlxsw_core, 0, 0, false, out_mbox, MLXSW_CMD_MBOX_SIZE); } -/* cmd_mbox_xm_num_local_ports - * Number of local_ports connected to the xm. - * Each local port is a 4x - * Spectrum-2/3: 25G - * Spectrum-4: 50G - */ -MLXSW_ITEM32(cmd_mbox, boardinfo, xm_num_local_ports, 0x00, 4, 3); - -/* cmd_mbox_xm_exists - * An XM (eXtanded Mezanine, e.g. used for the XLT) is connected on the board. - */ -MLXSW_ITEM32(cmd_mbox, boardinfo, xm_exists, 0x00, 0, 1); - -/* cmd_mbox_xm_local_port_entry - */ -MLXSW_ITEM_BIT_ARRAY(cmd_mbox, boardinfo, xm_local_port_entry, 0x04, 4, 8); - /* cmd_mbox_boardinfo_intapin * When PCIe interrupt messages are being used, this value is used for clearing * an interrupt. When using MSI-X, this register is not used. @@ -674,12 +657,6 @@ MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_double_size, 0x0C, 26, 1); */ MLXSW_ITEM32(cmd_mbox, config_profile, set_cqe_version, 0x08, 0, 1); -/* cmd_mbox_config_set_kvh_xlt_cache_mode - * Capability bit. Setting a bit to 1 configures the profile - * according to the mailbox contents. - */ -MLXSW_ITEM32(cmd_mbox, config_profile, set_kvh_xlt_cache_mode, 0x08, 3, 1); - /* cmd_mbox_config_profile_max_vepa_channels * Maximum number of VEPA channels per port (0 through 16) * 0 - multi-channel VEPA is disabled @@ -806,13 +783,6 @@ MLXSW_ITEM32(cmd_mbox, config_profile, adaptive_routing_group_cap, 0x4C, 0, 16); */ MLXSW_ITEM32(cmd_mbox, config_profile, arn, 0x50, 31, 1); -/* cmd_mbox_config_profile_kvh_xlt_cache_mode - * KVH XLT cache mode: - * 0 - XLT can use all KVH as best-effort - * 1 - XLT cache uses 1/2 KVH - */ -MLXSW_ITEM32(cmd_mbox, config_profile, kvh_xlt_cache_mode, 0x50, 8, 4); - /* cmd_mbox_config_kvd_linear_size * KVD Linear Size * Valid for Spectrum only diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index fc52832241b3..ab1cebf227fb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -3151,18 +3151,6 @@ mlxsw_core_port_linecard_get(struct mlxsw_core *mlxsw_core, return mlxsw_core_port->linecard; } -bool mlxsw_core_port_is_xm(const struct mlxsw_core *mlxsw_core, u16 local_port) -{ - const struct mlxsw_bus_info *bus_info = mlxsw_core->bus_info; - int i; - - for (i = 0; i < bus_info->xm_local_ports_count; i++) - if (bus_info->xm_local_ports[i] == local_port) - return true; - return false; -} -EXPORT_SYMBOL(mlxsw_core_port_is_xm); - void mlxsw_core_ports_remove_selected(struct mlxsw_core *mlxsw_core, bool (*selector)(void *priv, u16 local_port), void *priv) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index c2a891287047..d1e8b8b8d0c1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -261,7 +261,6 @@ mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core, struct mlxsw_linecard * mlxsw_core_port_linecard_get(struct mlxsw_core *mlxsw_core, u16 local_port); -bool mlxsw_core_port_is_xm(const struct mlxsw_core *mlxsw_core, u16 local_port); void mlxsw_core_ports_remove_selected(struct mlxsw_core *mlxsw_core, bool (*selector)(void *priv, u16 local_port), @@ -296,8 +295,7 @@ struct mlxsw_config_profile { used_max_pkey:1, used_ar_sec:1, used_adaptive_routing_group_cap:1, - used_kvd_sizes:1, - used_kvh_xlt_cache_mode:1; + used_kvd_sizes:1; u8 max_vepa_channels; u16 max_mid; u16 max_pgt; @@ -319,7 +317,6 @@ struct mlxsw_config_profile { u32 kvd_linear_size; u8 kvd_hash_single_parts; u8 kvd_hash_double_parts; - u8 kvh_xlt_cache_mode; struct mlxsw_swid_config swid_config[MLXSW_CONFIG_PROFILE_SWID_COUNT]; }; @@ -478,8 +475,6 @@ struct mlxsw_fw_rev { u16 can_reset_minor; }; -#define MLXSW_BUS_INFO_XM_LOCAL_PORTS_MAX 4 - struct mlxsw_bus_info { const char *device_kind; const char *device_name; @@ -488,10 +483,7 @@ struct mlxsw_bus_info { u8 vsd[MLXSW_CMD_BOARDINFO_VSD_LEN]; u8 psid[MLXSW_CMD_BOARDINFO_PSID_LEN]; u8 low_frequency:1, - read_frc_capable:1, - xm_exists:1; - u8 xm_local_ports_count; - u8 xm_local_ports[MLXSW_BUS_INFO_XM_LOCAL_PORTS_MAX]; + read_frc_capable:1; }; struct mlxsw_hwmon; diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index d9660d4cce96..d9bf584234a6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -359,8 +359,7 @@ static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) /* Create port objects for each valid entry */ devl_lock(devlink); for (i = 0; i < mlxsw_m->max_ports; i++) { - if (mlxsw_m->module_to_port[i] > 0 && - !mlxsw_core_port_is_xm(mlxsw_m->core, i)) { + if (mlxsw_m->module_to_port[i] > 0) { err = mlxsw_m_port_create(mlxsw_m, mlxsw_m->module_to_port[i], i); diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index f91dde4df152..8dd2479c7937 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1252,12 +1252,6 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mlxsw_cmd_mbox_config_profile_kvd_hash_double_size_set(mbox, MLXSW_RES_GET(res, KVD_DOUBLE_SIZE)); } - if (profile->used_kvh_xlt_cache_mode) { - mlxsw_cmd_mbox_config_profile_set_kvh_xlt_cache_mode_set( - mbox, 1); - mlxsw_cmd_mbox_config_profile_kvh_xlt_cache_mode_set( - mbox, profile->kvh_xlt_cache_mode); - } for (i = 0; i < MLXSW_CONFIG_PROFILE_SWID_COUNT; i++) mlxsw_pci_config_profile_swid_config(mlxsw_pci, mbox, i, @@ -1271,30 +1265,6 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, return mlxsw_cmd_config_profile_set(mlxsw_pci->core, mbox); } -static int mlxsw_pci_boardinfo_xm_process(struct mlxsw_pci *mlxsw_pci, - struct mlxsw_bus_info *bus_info, - char *mbox) -{ - int count = mlxsw_cmd_mbox_boardinfo_xm_num_local_ports_get(mbox); - int i; - - if (!mlxsw_cmd_mbox_boardinfo_xm_exists_get(mbox)) - return 0; - - bus_info->xm_exists = true; - - if (count > MLXSW_BUS_INFO_XM_LOCAL_PORTS_MAX) { - dev_err(&mlxsw_pci->pdev->dev, "Invalid number of XM local ports\n"); - return -EINVAL; - } - bus_info->xm_local_ports_count = count; - for (i = 0; i < count; i++) - bus_info->xm_local_ports[i] = - mlxsw_cmd_mbox_boardinfo_xm_local_port_entry_get(mbox, - i); - return 0; -} - static int mlxsw_pci_boardinfo(struct mlxsw_pci *mlxsw_pci, char *mbox) { struct mlxsw_bus_info *bus_info = &mlxsw_pci->bus_info; @@ -1306,8 +1276,7 @@ static int mlxsw_pci_boardinfo(struct mlxsw_pci *mlxsw_pci, char *mbox) return err; mlxsw_cmd_mbox_boardinfo_vsd_memcpy_from(mbox, bus_info->vsd); mlxsw_cmd_mbox_boardinfo_psid_memcpy_from(mbox, bus_info->psid); - - return mlxsw_pci_boardinfo_xm_process(mlxsw_pci, bus_info, mbox); + return 0; } static int mlxsw_pci_fw_area_init(struct mlxsw_pci *mlxsw_pci, char *mbox, diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 93af6c974ece..d830a35755a8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -7848,11 +7848,10 @@ static inline void mlxsw_reg_ralue_pack4(char *payload, enum mlxsw_reg_ralxx_protocol protocol, enum mlxsw_reg_ralue_op op, u16 virtual_router, u8 prefix_len, - u32 *dip) + u32 dip) { mlxsw_reg_ralue_pack(payload, protocol, op, virtual_router, prefix_len); - if (dip) - mlxsw_reg_ralue_dip4_set(payload, *dip); + mlxsw_reg_ralue_dip4_set(payload, dip); } static inline void mlxsw_reg_ralue_pack6(char *payload, @@ -7862,8 +7861,7 @@ static inline void mlxsw_reg_ralue_pack6(char *payload, const void *dip) { mlxsw_reg_ralue_pack(payload, protocol, op, virtual_router, prefix_len); - if (dip) - mlxsw_reg_ralue_dip6_memcpy_to(payload, dip); + mlxsw_reg_ralue_dip6_memcpy_to(payload, dip); } static inline void @@ -8926,658 +8924,6 @@ 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); } -/* RXLTE - Router XLT Enable Register - * ---------------------------------- - * The RXLTE enables XLT (eXtended Lookup Table) LPM lookups if a capable - * XM is present on the system. - */ - -#define MLXSW_REG_RXLTE_ID 0x8050 -#define MLXSW_REG_RXLTE_LEN 0x0C - -MLXSW_REG_DEFINE(rxlte, MLXSW_REG_RXLTE_ID, MLXSW_REG_RXLTE_LEN); - -/* reg_rxlte_virtual_router - * Virtual router ID associated with the router interface. - * Range is 0..cap_max_virtual_routers-1 - * Access: Index - */ -MLXSW_ITEM32(reg, rxlte, virtual_router, 0x00, 0, 16); - -enum mlxsw_reg_rxlte_protocol { - MLXSW_REG_RXLTE_PROTOCOL_IPV4, - MLXSW_REG_RXLTE_PROTOCOL_IPV6, -}; - -/* reg_rxlte_protocol - * Access: Index - */ -MLXSW_ITEM32(reg, rxlte, protocol, 0x04, 0, 4); - -/* reg_rxlte_lpm_xlt_en - * Access: RW - */ -MLXSW_ITEM32(reg, rxlte, lpm_xlt_en, 0x08, 0, 1); - -static inline void mlxsw_reg_rxlte_pack(char *payload, u16 virtual_router, - enum mlxsw_reg_rxlte_protocol protocol, - bool lpm_xlt_en) -{ - MLXSW_REG_ZERO(rxlte, payload); - mlxsw_reg_rxlte_virtual_router_set(payload, virtual_router); - mlxsw_reg_rxlte_protocol_set(payload, protocol); - mlxsw_reg_rxlte_lpm_xlt_en_set(payload, lpm_xlt_en); -} - -/* RXLTM - Router XLT M select Register - * ------------------------------------ - * The RXLTM configures and selects the M for the XM lookups. - */ - -#define MLXSW_REG_RXLTM_ID 0x8051 -#define MLXSW_REG_RXLTM_LEN 0x14 - -MLXSW_REG_DEFINE(rxltm, MLXSW_REG_RXLTM_ID, MLXSW_REG_RXLTM_LEN); - -/* reg_rxltm_m0_val_v6 - * Global M0 value For IPv6. - * Range 0..128 - * Access: RW - */ -MLXSW_ITEM32(reg, rxltm, m0_val_v6, 0x10, 16, 8); - -/* reg_rxltm_m0_val_v4 - * Global M0 value For IPv4. - * Range 0..32 - * Access: RW - */ -MLXSW_ITEM32(reg, rxltm, m0_val_v4, 0x10, 0, 6); - -static inline void mlxsw_reg_rxltm_pack(char *payload, u8 m0_val_v4, u8 m0_val_v6) -{ - MLXSW_REG_ZERO(rxltm, payload); - mlxsw_reg_rxltm_m0_val_v6_set(payload, m0_val_v6); - mlxsw_reg_rxltm_m0_val_v4_set(payload, m0_val_v4); -} - -/* RLCMLD - Router LPM Cache ML Delete Register - * -------------------------------------------- - * The RLCMLD register is used to bulk delete the XLT-LPM cache ML entries. - * This can be used by SW when L is increased or decreased, thus need to - * remove entries with old ML values. - */ - -#define MLXSW_REG_RLCMLD_ID 0x8055 -#define MLXSW_REG_RLCMLD_LEN 0x30 - -MLXSW_REG_DEFINE(rlcmld, MLXSW_REG_RLCMLD_ID, MLXSW_REG_RLCMLD_LEN); - -enum mlxsw_reg_rlcmld_select { - MLXSW_REG_RLCMLD_SELECT_ML_ENTRIES, - MLXSW_REG_RLCMLD_SELECT_M_ENTRIES, - MLXSW_REG_RLCMLD_SELECT_M_AND_ML_ENTRIES, -}; - -/* reg_rlcmld_select - * Which entries to delete. - * Access: Index - */ -MLXSW_ITEM32(reg, rlcmld, select, 0x00, 16, 2); - -enum mlxsw_reg_rlcmld_filter_fields { - MLXSW_REG_RLCMLD_FILTER_FIELDS_BY_PROTOCOL = 0x04, - MLXSW_REG_RLCMLD_FILTER_FIELDS_BY_VIRTUAL_ROUTER = 0x08, - MLXSW_REG_RLCMLD_FILTER_FIELDS_BY_DIP = 0x10, -}; - -/* reg_rlcmld_filter_fields - * If a bit is '0' then the relevant field is ignored. - * Access: Index - */ -MLXSW_ITEM32(reg, rlcmld, filter_fields, 0x00, 0, 8); - -enum mlxsw_reg_rlcmld_protocol { - MLXSW_REG_RLCMLD_PROTOCOL_UC_IPV4, - MLXSW_REG_RLCMLD_PROTOCOL_UC_IPV6, -}; - -/* reg_rlcmld_protocol - * Access: Index - */ -MLXSW_ITEM32(reg, rlcmld, protocol, 0x08, 0, 4); - -/* reg_rlcmld_virtual_router - * Virtual router ID. - * Range is 0..cap_max_virtual_routers-1 - * Access: Index - */ -MLXSW_ITEM32(reg, rlcmld, virtual_router, 0x0C, 0, 16); - -/* reg_rlcmld_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. - * Access: Index - */ -MLXSW_ITEM32(reg, rlcmld, dip4, 0x1C, 0, 32); -MLXSW_ITEM_BUF(reg, rlcmld, dip6, 0x10, 16); - -/* reg_rlcmld_dip_mask - * per bit: - * 0: no match - * 1: match - * Access: Index - */ -MLXSW_ITEM32(reg, rlcmld, dip_mask4, 0x2C, 0, 32); -MLXSW_ITEM_BUF(reg, rlcmld, dip_mask6, 0x20, 16); - -static inline void __mlxsw_reg_rlcmld_pack(char *payload, - enum mlxsw_reg_rlcmld_select select, - enum mlxsw_reg_rlcmld_protocol protocol, - u16 virtual_router) -{ - u8 filter_fields = MLXSW_REG_RLCMLD_FILTER_FIELDS_BY_PROTOCOL | - MLXSW_REG_RLCMLD_FILTER_FIELDS_BY_VIRTUAL_ROUTER | - MLXSW_REG_RLCMLD_FILTER_FIELDS_BY_DIP; - - MLXSW_REG_ZERO(rlcmld, payload); - mlxsw_reg_rlcmld_select_set(payload, select); - mlxsw_reg_rlcmld_filter_fields_set(payload, filter_fields); - mlxsw_reg_rlcmld_protocol_set(payload, protocol); - mlxsw_reg_rlcmld_virtual_router_set(payload, virtual_router); -} - -static inline void mlxsw_reg_rlcmld_pack4(char *payload, - enum mlxsw_reg_rlcmld_select select, - u16 virtual_router, - u32 dip, u32 dip_mask) -{ - __mlxsw_reg_rlcmld_pack(payload, select, - MLXSW_REG_RLCMLD_PROTOCOL_UC_IPV4, - virtual_router); - mlxsw_reg_rlcmld_dip4_set(payload, dip); - mlxsw_reg_rlcmld_dip_mask4_set(payload, dip_mask); -} - -static inline void mlxsw_reg_rlcmld_pack6(char *payload, - enum mlxsw_reg_rlcmld_select select, - u16 virtual_router, - const void *dip, const void *dip_mask) -{ - __mlxsw_reg_rlcmld_pack(payload, select, - MLXSW_REG_RLCMLD_PROTOCOL_UC_IPV6, - virtual_router); - mlxsw_reg_rlcmld_dip6_memcpy_to(payload, dip); - mlxsw_reg_rlcmld_dip_mask6_memcpy_to(payload, dip_mask); -} - -/* RLPMCE - Router LPM Cache Enable Register - * ----------------------------------------- - * Allows disabling the LPM cache. Can be changed on the fly. - */ - -#define MLXSW_REG_RLPMCE_ID 0x8056 -#define MLXSW_REG_RLPMCE_LEN 0x4 - -MLXSW_REG_DEFINE(rlpmce, MLXSW_REG_RLPMCE_ID, MLXSW_REG_RLPMCE_LEN); - -/* reg_rlpmce_flush - * Flush: - * 0: do not flush the cache (default) - * 1: flush (clear) the cache - * Access: WO - */ -MLXSW_ITEM32(reg, rlpmce, flush, 0x00, 4, 1); - -/* reg_rlpmce_disable - * LPM cache: - * 0: enabled (default) - * 1: disabled - * Access: RW - */ -MLXSW_ITEM32(reg, rlpmce, disable, 0x00, 0, 1); - -static inline void mlxsw_reg_rlpmce_pack(char *payload, bool flush, - bool disable) -{ - MLXSW_REG_ZERO(rlpmce, payload); - mlxsw_reg_rlpmce_flush_set(payload, flush); - mlxsw_reg_rlpmce_disable_set(payload, disable); -} - -/* Note that XLTQ, XMDR, XRMT 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. XLRQ and XRMT are just put alongside with the - * related registers. - */ - -/* XLTQ - XM Lookup Table Query Register - * ------------------------------------- - */ -#define MLXSW_REG_XLTQ_ID 0x7802 -#define MLXSW_REG_XLTQ_LEN 0x2C - -MLXSW_REG_DEFINE(xltq, MLXSW_REG_XLTQ_ID, MLXSW_REG_XLTQ_LEN); - -enum mlxsw_reg_xltq_xm_device_id { - MLXSW_REG_XLTQ_XM_DEVICE_ID_UNKNOWN, - MLXSW_REG_XLTQ_XM_DEVICE_ID_XLT = 0xCF71, -}; - -/* reg_xltq_xm_device_id - * XM device ID. - * Access: RO - */ -MLXSW_ITEM32(reg, xltq, xm_device_id, 0x04, 0, 16); - -/* reg_xltq_xlt_cap_ipv4_lpm - * Access: RO - */ -MLXSW_ITEM32(reg, xltq, xlt_cap_ipv4_lpm, 0x10, 0, 1); - -/* reg_xltq_xlt_cap_ipv6_lpm - * Access: RO - */ -MLXSW_ITEM32(reg, xltq, xlt_cap_ipv6_lpm, 0x10, 1, 1); - -/* reg_xltq_cap_xlt_entries - * Number of XLT entries - * Note: SW must not fill more than 80% in order to avoid overflow - * Access: RO - */ -MLXSW_ITEM32(reg, xltq, cap_xlt_entries, 0x20, 0, 32); - -/* reg_xltq_cap_xlt_mtable - * XLT M-Table max size - * Access: RO - */ -MLXSW_ITEM32(reg, xltq, cap_xlt_mtable, 0x24, 0, 32); - -static inline void mlxsw_reg_xltq_pack(char *payload) -{ - MLXSW_REG_ZERO(xltq, payload); -} - -static inline void mlxsw_reg_xltq_unpack(char *payload, u16 *xm_device_id, bool *xlt_cap_ipv4_lpm, - bool *xlt_cap_ipv6_lpm, u32 *cap_xlt_entries, - u32 *cap_xlt_mtable) -{ - *xm_device_id = mlxsw_reg_xltq_xm_device_id_get(payload); - *xlt_cap_ipv4_lpm = mlxsw_reg_xltq_xlt_cap_ipv4_lpm_get(payload); - *xlt_cap_ipv6_lpm = mlxsw_reg_xltq_xlt_cap_ipv6_lpm_get(payload); - *cap_xlt_entries = mlxsw_reg_xltq_cap_xlt_entries_get(payload); - *cap_xlt_mtable = mlxsw_reg_xltq_cap_xlt_mtable_get(payload); -} - -/* 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); -} - -/* XRMT - XM Router M Table Register - * --------------------------------- - * The XRMT configures the M-Table for the XLT-LPM. - */ -#define MLXSW_REG_XRMT_ID 0x7810 -#define MLXSW_REG_XRMT_LEN 0x14 - -MLXSW_REG_DEFINE(xrmt, MLXSW_REG_XRMT_ID, MLXSW_REG_XRMT_LEN); - -/* reg_xrmt_index - * Index in M-Table. - * Range 0..cap_xlt_mtable-1 - * Access: Index - */ -MLXSW_ITEM32(reg, xrmt, index, 0x04, 0, 20); - -/* reg_xrmt_l0_val - * Access: RW - */ -MLXSW_ITEM32(reg, xrmt, l0_val, 0x10, 24, 8); - -static inline void mlxsw_reg_xrmt_pack(char *payload, u32 index, u8 l0_val) -{ - MLXSW_REG_ZERO(xrmt, payload); - mlxsw_reg_xrmt_index_set(payload, index); - mlxsw_reg_xrmt_l0_val_set(payload, l0_val); -} - -/* XRALTA - XM Router Algorithmic LPM Tree Allocation Register - * ----------------------------------------------------------- - * The XRALTA is used to allocate the XLT LPM trees. - * - * This register embeds original RALTA register. - */ -#define MLXSW_REG_XRALTA_ID 0x7811 -#define MLXSW_REG_XRALTA_LEN 0x08 -#define MLXSW_REG_XRALTA_RALTA_OFFSET 0x04 - -MLXSW_REG_DEFINE(xralta, MLXSW_REG_XRALTA_ID, MLXSW_REG_XRALTA_LEN); - -static inline void mlxsw_reg_xralta_pack(char *payload, bool alloc, - enum mlxsw_reg_ralxx_protocol protocol, - u8 tree_id) -{ - char *ralta_payload = payload + MLXSW_REG_XRALTA_RALTA_OFFSET; - - MLXSW_REG_ZERO(xralta, payload); - mlxsw_reg_ralta_pack(ralta_payload, alloc, protocol, tree_id); -} - -/* XRALST - XM Router Algorithmic LPM Structure Tree Register - * ---------------------------------------------------------- - * The XRALST is used to set and query the structure of an XLT LPM tree. - * - * This register embeds original RALST register. - */ -#define MLXSW_REG_XRALST_ID 0x7812 -#define MLXSW_REG_XRALST_LEN 0x108 -#define MLXSW_REG_XRALST_RALST_OFFSET 0x04 - -MLXSW_REG_DEFINE(xralst, MLXSW_REG_XRALST_ID, MLXSW_REG_XRALST_LEN); - -static inline void mlxsw_reg_xralst_pack(char *payload, u8 root_bin, u8 tree_id) -{ - char *ralst_payload = payload + MLXSW_REG_XRALST_RALST_OFFSET; - - MLXSW_REG_ZERO(xralst, payload); - mlxsw_reg_ralst_pack(ralst_payload, root_bin, tree_id); -} - -static inline void mlxsw_reg_xralst_bin_pack(char *payload, u8 bin_number, - u8 left_child_bin, - u8 right_child_bin) -{ - char *ralst_payload = payload + MLXSW_REG_XRALST_RALST_OFFSET; - - mlxsw_reg_ralst_bin_pack(ralst_payload, bin_number, left_child_bin, - right_child_bin); -} - -/* XRALTB - XM Router Algorithmic LPM Tree Binding Register - * -------------------------------------------------------- - * The XRALTB register is used to bind virtual router and protocol - * to an allocated LPM tree. - * - * This register embeds original RALTB register. - */ -#define MLXSW_REG_XRALTB_ID 0x7813 -#define MLXSW_REG_XRALTB_LEN 0x08 -#define MLXSW_REG_XRALTB_RALTB_OFFSET 0x04 - -MLXSW_REG_DEFINE(xraltb, MLXSW_REG_XRALTB_ID, MLXSW_REG_XRALTB_LEN); - -static inline void mlxsw_reg_xraltb_pack(char *payload, u16 virtual_router, - enum mlxsw_reg_ralxx_protocol protocol, - u8 tree_id) -{ - char *raltb_payload = payload + MLXSW_REG_XRALTB_RALTB_OFFSET; - - MLXSW_REG_ZERO(xraltb, payload); - mlxsw_reg_raltb_pack(raltb_payload, virtual_router, protocol, tree_id); -} - /* MFCR - Management Fan Control Register * -------------------------------------- * This register controls the settings of the Fan Speed PWM mechanism. @@ -13084,16 +12430,6 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(rigr2), MLXSW_REG(recr2), MLXSW_REG(rmft2), - MLXSW_REG(rxlte), - MLXSW_REG(rxltm), - MLXSW_REG(rlcmld), - MLXSW_REG(rlpmce), - MLXSW_REG(xltq), - MLXSW_REG(xmdr), - MLXSW_REG(xrmt), - MLXSW_REG(xralta), - MLXSW_REG(xralst), - MLXSW_REG(xraltb), MLXSW_REG(mfcr), MLXSW_REG(mfsc), MLXSW_REG(mfsm), diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index cafd206e8d7e..c949005f56dc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2105,9 +2105,6 @@ static int mlxsw_sp_port_module_info_init(struct mlxsw_sp *mlxsw_sp) return -ENOMEM; for (i = 1; i < max_ports; i++) { - if (mlxsw_core_port_is_xm(mlxsw_sp->core, i)) - continue; - port_mapping = &mlxsw_sp->port_mapping[i]; err = mlxsw_sp_port_module_info_get(mlxsw_sp, i, port_mapping); if (err) @@ -3410,8 +3407,6 @@ static const struct mlxsw_config_profile mlxsw_sp2_config_profile = { .max_ib_mc = 0, .used_max_pkey = 1, .max_pkey = 0, - .used_kvh_xlt_cache_mode = 1, - .kvh_xlt_cache_mode = 1, .swid_config = { { .used_type = 1, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 9dbb573d53ea..e3f52019cbcb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -443,65 +443,12 @@ struct mlxsw_sp_fib_entry_decap { u32 tunnel_index; }; -static struct mlxsw_sp_fib_entry_priv * -mlxsw_sp_fib_entry_priv_create(const struct mlxsw_sp_router_ll_ops *ll_ops) -{ - struct mlxsw_sp_fib_entry_priv *priv; - - if (!ll_ops->fib_entry_priv_size) - /* No need to have priv */ - return NULL; - - priv = kzalloc(sizeof(*priv) + ll_ops->fib_entry_priv_size, GFP_KERNEL); - if (!priv) - return ERR_PTR(-ENOMEM); - refcount_set(&priv->refcnt, 1); - return priv; -} - -static void -mlxsw_sp_fib_entry_priv_destroy(struct mlxsw_sp_fib_entry_priv *priv) -{ - kfree(priv); -} - -static void mlxsw_sp_fib_entry_priv_hold(struct mlxsw_sp_fib_entry_priv *priv) -{ - refcount_inc(&priv->refcnt); -} - -static void mlxsw_sp_fib_entry_priv_put(struct mlxsw_sp_fib_entry_priv *priv) -{ - if (!priv || !refcount_dec_and_test(&priv->refcnt)) - return; - mlxsw_sp_fib_entry_priv_destroy(priv); -} - -static void mlxsw_sp_fib_entry_op_ctx_priv_hold(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct mlxsw_sp_fib_entry_priv *priv) -{ - if (!priv) - return; - mlxsw_sp_fib_entry_priv_hold(priv); - list_add(&priv->list, &op_ctx->fib_entry_priv_list); -} - -static void mlxsw_sp_fib_entry_op_ctx_priv_put_all(struct mlxsw_sp_fib_entry_op_ctx *op_ctx) -{ - struct mlxsw_sp_fib_entry_priv *priv, *tmp; - - list_for_each_entry_safe(priv, tmp, &op_ctx->fib_entry_priv_list, list) - mlxsw_sp_fib_entry_priv_put(priv); - INIT_LIST_HEAD(&op_ctx->fib_entry_priv_list); -} - struct mlxsw_sp_fib_entry { struct mlxsw_sp_fib_node *fib_node; enum mlxsw_sp_fib_entry_type type; struct list_head nexthop_group_node; struct mlxsw_sp_nexthop_group *nh_group; struct mlxsw_sp_fib_entry_decap decap; /* Valid for decap entries. */ - struct mlxsw_sp_fib_entry_priv *priv; }; struct mlxsw_sp_fib4_entry { @@ -537,7 +484,6 @@ struct mlxsw_sp_fib { struct mlxsw_sp_vr *vr; struct mlxsw_sp_lpm_tree *lpm_tree; enum mlxsw_sp_l3proto proto; - const struct mlxsw_sp_router_ll_ops *ll_ops; }; struct mlxsw_sp_vr { @@ -551,45 +497,16 @@ struct mlxsw_sp_vr { refcount_t ul_rif_refcnt; }; -static int mlxsw_sp_router_ll_basic_init(struct mlxsw_sp *mlxsw_sp, u16 vr_id, - enum mlxsw_sp_l3proto proto) -{ - return 0; -} - -static int mlxsw_sp_router_ll_basic_ralta_write(struct mlxsw_sp *mlxsw_sp, char *xralta_pl) -{ - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), - xralta_pl + MLXSW_REG_XRALTA_RALTA_OFFSET); -} - -static int mlxsw_sp_router_ll_basic_ralst_write(struct mlxsw_sp *mlxsw_sp, char *xralst_pl) -{ - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), - xralst_pl + MLXSW_REG_XRALST_RALST_OFFSET); -} - -static int mlxsw_sp_router_ll_basic_raltb_write(struct mlxsw_sp *mlxsw_sp, char *xraltb_pl) -{ - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), - xraltb_pl + MLXSW_REG_XRALTB_RALTB_OFFSET); -} - static const struct rhashtable_params mlxsw_sp_fib_ht_params; static struct mlxsw_sp_fib *mlxsw_sp_fib_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr, enum mlxsw_sp_l3proto proto) { - const struct mlxsw_sp_router_ll_ops *ll_ops = mlxsw_sp->router->proto_ll_ops[proto]; struct mlxsw_sp_lpm_tree *lpm_tree; struct mlxsw_sp_fib *fib; int err; - err = ll_ops->init(mlxsw_sp, vr->id, proto); - if (err) - return ERR_PTR(err); - lpm_tree = mlxsw_sp->router->lpm.proto_trees[proto]; fib = kzalloc(sizeof(*fib), GFP_KERNEL); if (!fib) @@ -601,7 +518,6 @@ static struct mlxsw_sp_fib *mlxsw_sp_fib_create(struct mlxsw_sp *mlxsw_sp, fib->proto = proto; fib->vr = vr; fib->lpm_tree = lpm_tree; - fib->ll_ops = ll_ops; mlxsw_sp_lpm_tree_hold(lpm_tree); err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, lpm_tree->id); if (err) @@ -640,36 +556,33 @@ mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp) } static int mlxsw_sp_lpm_tree_alloc(struct mlxsw_sp *mlxsw_sp, - const struct mlxsw_sp_router_ll_ops *ll_ops, struct mlxsw_sp_lpm_tree *lpm_tree) { - char xralta_pl[MLXSW_REG_XRALTA_LEN]; + char ralta_pl[MLXSW_REG_RALTA_LEN]; - mlxsw_reg_xralta_pack(xralta_pl, true, - (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto, - lpm_tree->id); - return ll_ops->ralta_write(mlxsw_sp, xralta_pl); + mlxsw_reg_ralta_pack(ralta_pl, true, + (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto, + lpm_tree->id); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl); } static void mlxsw_sp_lpm_tree_free(struct mlxsw_sp *mlxsw_sp, - const struct mlxsw_sp_router_ll_ops *ll_ops, struct mlxsw_sp_lpm_tree *lpm_tree) { - char xralta_pl[MLXSW_REG_XRALTA_LEN]; + char ralta_pl[MLXSW_REG_RALTA_LEN]; - mlxsw_reg_xralta_pack(xralta_pl, false, - (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto, - lpm_tree->id); - ll_ops->ralta_write(mlxsw_sp, xralta_pl); + mlxsw_reg_ralta_pack(ralta_pl, false, + (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto, + lpm_tree->id); + mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl); } static int mlxsw_sp_lpm_tree_left_struct_set(struct mlxsw_sp *mlxsw_sp, - const struct mlxsw_sp_router_ll_ops *ll_ops, struct mlxsw_sp_prefix_usage *prefix_usage, struct mlxsw_sp_lpm_tree *lpm_tree) { - char xralst_pl[MLXSW_REG_XRALST_LEN]; + char ralst_pl[MLXSW_REG_RALST_LEN]; u8 root_bin = 0; u8 prefix; u8 last_prefix = MLXSW_REG_RALST_BIN_NO_CHILD; @@ -677,20 +590,19 @@ mlxsw_sp_lpm_tree_left_struct_set(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) root_bin = prefix; - mlxsw_reg_xralst_pack(xralst_pl, root_bin, lpm_tree->id); + mlxsw_reg_ralst_pack(ralst_pl, root_bin, lpm_tree->id); mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) { if (prefix == 0) continue; - mlxsw_reg_xralst_bin_pack(xralst_pl, prefix, last_prefix, - MLXSW_REG_RALST_BIN_NO_CHILD); + mlxsw_reg_ralst_bin_pack(ralst_pl, prefix, last_prefix, + MLXSW_REG_RALST_BIN_NO_CHILD); last_prefix = prefix; } - return ll_ops->ralst_write(mlxsw_sp, xralst_pl); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl); } static struct mlxsw_sp_lpm_tree * mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp, - const struct mlxsw_sp_router_ll_ops *ll_ops, struct mlxsw_sp_prefix_usage *prefix_usage, enum mlxsw_sp_l3proto proto) { @@ -701,11 +613,12 @@ mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp, if (!lpm_tree) return ERR_PTR(-EBUSY); lpm_tree->proto = proto; - err = mlxsw_sp_lpm_tree_alloc(mlxsw_sp, ll_ops, lpm_tree); + err = mlxsw_sp_lpm_tree_alloc(mlxsw_sp, lpm_tree); if (err) return ERR_PTR(err); - err = mlxsw_sp_lpm_tree_left_struct_set(mlxsw_sp, ll_ops, prefix_usage, lpm_tree); + err = mlxsw_sp_lpm_tree_left_struct_set(mlxsw_sp, prefix_usage, + lpm_tree); if (err) goto err_left_struct_set; memcpy(&lpm_tree->prefix_usage, prefix_usage, @@ -716,15 +629,14 @@ mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp, return lpm_tree; err_left_struct_set: - mlxsw_sp_lpm_tree_free(mlxsw_sp, ll_ops, lpm_tree); + mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree); return ERR_PTR(err); } static void mlxsw_sp_lpm_tree_destroy(struct mlxsw_sp *mlxsw_sp, - const struct mlxsw_sp_router_ll_ops *ll_ops, struct mlxsw_sp_lpm_tree *lpm_tree) { - mlxsw_sp_lpm_tree_free(mlxsw_sp, ll_ops, lpm_tree); + mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree); } static struct mlxsw_sp_lpm_tree * @@ -732,7 +644,6 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_prefix_usage *prefix_usage, enum mlxsw_sp_l3proto proto) { - const struct mlxsw_sp_router_ll_ops *ll_ops = mlxsw_sp->router->proto_ll_ops[proto]; struct mlxsw_sp_lpm_tree *lpm_tree; int i; @@ -746,7 +657,7 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp, return lpm_tree; } } - return mlxsw_sp_lpm_tree_create(mlxsw_sp, ll_ops, prefix_usage, proto); + return mlxsw_sp_lpm_tree_create(mlxsw_sp, prefix_usage, proto); } static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree) @@ -757,11 +668,8 @@ static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree) static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_lpm_tree *lpm_tree) { - const struct mlxsw_sp_router_ll_ops *ll_ops = - mlxsw_sp->router->proto_ll_ops[lpm_tree->proto]; - if (--lpm_tree->ref_count == 0) - mlxsw_sp_lpm_tree_destroy(mlxsw_sp, ll_ops, lpm_tree); + mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree); } #define MLXSW_SP_LPM_TREE_MIN 1 /* tree 0 is reserved */ @@ -851,23 +759,23 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_fib *fib, u8 tree_id) { - char xraltb_pl[MLXSW_REG_XRALTB_LEN]; + char raltb_pl[MLXSW_REG_RALTB_LEN]; - mlxsw_reg_xraltb_pack(xraltb_pl, fib->vr->id, - (enum mlxsw_reg_ralxx_protocol) fib->proto, - tree_id); - return fib->ll_ops->raltb_write(mlxsw_sp, xraltb_pl); + mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id, + (enum mlxsw_reg_ralxx_protocol) fib->proto, + tree_id); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl); } static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_fib *fib) { - char xraltb_pl[MLXSW_REG_XRALTB_LEN]; + char raltb_pl[MLXSW_REG_RALTB_LEN]; /* Bind to tree 0 which is default */ - mlxsw_reg_xraltb_pack(xraltb_pl, fib->vr->id, - (enum mlxsw_reg_ralxx_protocol) fib->proto, 0); - return fib->ll_ops->raltb_write(mlxsw_sp, xraltb_pl); + mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id, + (enum mlxsw_reg_ralxx_protocol) fib->proto, 0); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl); } static u32 mlxsw_sp_fix_tb_id(u32 tb_id) @@ -5778,14 +5686,13 @@ mlxsw_sp_fib_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_fib_entry_hw_flags_refresh(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fib_entry *fib_entry, - enum mlxsw_sp_fib_entry_op op) + enum mlxsw_reg_ralue_op op) { switch (op) { - case MLXSW_SP_FIB_ENTRY_OP_WRITE: - case MLXSW_SP_FIB_ENTRY_OP_UPDATE: + case MLXSW_REG_RALUE_OP_WRITE_WRITE: mlxsw_sp_fib_entry_hw_flags_set(mlxsw_sp, fib_entry); break; - case MLXSW_SP_FIB_ENTRY_OP_DELETE: + case MLXSW_REG_RALUE_OP_WRITE_DELETE: mlxsw_sp_fib_entry_hw_flags_clear(mlxsw_sp, fib_entry); break; default: @@ -5793,140 +5700,39 @@ mlxsw_sp_fib_entry_hw_flags_refresh(struct mlxsw_sp *mlxsw_sp, } } -struct mlxsw_sp_fib_entry_op_ctx_basic { - char ralue_pl[MLXSW_REG_RALUE_LEN]; -}; - static void -mlxsw_sp_router_ll_basic_fib_entry_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - enum mlxsw_sp_l3proto proto, - enum mlxsw_sp_fib_entry_op op, - u16 virtual_router, u8 prefix_len, - unsigned char *addr, - struct mlxsw_sp_fib_entry_priv *priv) +mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl, + const struct mlxsw_sp_fib_entry *fib_entry, + enum mlxsw_reg_ralue_op op) { - struct mlxsw_sp_fib_entry_op_ctx_basic *op_ctx_basic = (void *) op_ctx->ll_priv; - enum mlxsw_reg_ralxx_protocol ralxx_proto; - char *ralue_pl = op_ctx_basic->ralue_pl; - enum mlxsw_reg_ralue_op ralue_op; - - ralxx_proto = (enum mlxsw_reg_ralxx_protocol) proto; + struct mlxsw_sp_fib *fib = fib_entry->fib_node->fib; + enum mlxsw_reg_ralxx_protocol proto; + u32 *p_dip; - switch (op) { - case MLXSW_SP_FIB_ENTRY_OP_WRITE: - case MLXSW_SP_FIB_ENTRY_OP_UPDATE: - ralue_op = MLXSW_REG_RALUE_OP_WRITE_WRITE; - break; - case MLXSW_SP_FIB_ENTRY_OP_DELETE: - ralue_op = MLXSW_REG_RALUE_OP_WRITE_DELETE; - break; - default: - WARN_ON_ONCE(1); - return; - } + proto = (enum mlxsw_reg_ralxx_protocol) fib->proto; - switch (proto) { + switch (fib->proto) { case MLXSW_SP_L3_PROTO_IPV4: - mlxsw_reg_ralue_pack4(ralue_pl, ralxx_proto, ralue_op, - virtual_router, prefix_len, (u32 *) addr); + p_dip = (u32 *) fib_entry->fib_node->key.addr; + mlxsw_reg_ralue_pack4(ralue_pl, proto, op, fib->vr->id, + fib_entry->fib_node->key.prefix_len, + *p_dip); break; case MLXSW_SP_L3_PROTO_IPV6: - mlxsw_reg_ralue_pack6(ralue_pl, ralxx_proto, ralue_op, - virtual_router, prefix_len, addr); + mlxsw_reg_ralue_pack6(ralue_pl, proto, op, fib->vr->id, + fib_entry->fib_node->key.prefix_len, + fib_entry->fib_node->key.addr); break; } } -static void -mlxsw_sp_router_ll_basic_fib_entry_act_remote_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - enum mlxsw_reg_ralue_trap_action trap_action, - u16 trap_id, u32 adjacency_index, u16 ecmp_size) -{ - struct mlxsw_sp_fib_entry_op_ctx_basic *op_ctx_basic = (void *) op_ctx->ll_priv; - - mlxsw_reg_ralue_act_remote_pack(op_ctx_basic->ralue_pl, trap_action, - trap_id, adjacency_index, ecmp_size); -} - -static void -mlxsw_sp_router_ll_basic_fib_entry_act_local_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - enum mlxsw_reg_ralue_trap_action trap_action, - u16 trap_id, u16 local_erif) -{ - struct mlxsw_sp_fib_entry_op_ctx_basic *op_ctx_basic = (void *) op_ctx->ll_priv; - - mlxsw_reg_ralue_act_local_pack(op_ctx_basic->ralue_pl, trap_action, - trap_id, local_erif); -} - -static void -mlxsw_sp_router_ll_basic_fib_entry_act_ip2me_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx) -{ - struct mlxsw_sp_fib_entry_op_ctx_basic *op_ctx_basic = (void *) op_ctx->ll_priv; - - mlxsw_reg_ralue_act_ip2me_pack(op_ctx_basic->ralue_pl); -} - -static void -mlxsw_sp_router_ll_basic_fib_entry_act_ip2me_tun_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - u32 tunnel_ptr) -{ - struct mlxsw_sp_fib_entry_op_ctx_basic *op_ctx_basic = (void *) op_ctx->ll_priv; - - mlxsw_reg_ralue_act_ip2me_tun_pack(op_ctx_basic->ralue_pl, tunnel_ptr); -} - -static int -mlxsw_sp_router_ll_basic_fib_entry_commit(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - bool *postponed_for_bulk) -{ - struct mlxsw_sp_fib_entry_op_ctx_basic *op_ctx_basic = (void *) op_ctx->ll_priv; - - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), - op_ctx_basic->ralue_pl); -} - -static bool -mlxsw_sp_router_ll_basic_fib_entry_is_committed(struct mlxsw_sp_fib_entry_priv *priv) -{ - return true; -} - -static void mlxsw_sp_fib_entry_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct mlxsw_sp_fib_entry *fib_entry, - enum mlxsw_sp_fib_entry_op op) -{ - struct mlxsw_sp_fib *fib = fib_entry->fib_node->fib; - - mlxsw_sp_fib_entry_op_ctx_priv_hold(op_ctx, fib_entry->priv); - fib->ll_ops->fib_entry_pack(op_ctx, fib->proto, op, fib->vr->id, - fib_entry->fib_node->key.prefix_len, - fib_entry->fib_node->key.addr, - fib_entry->priv); -} - -static int mlxsw_sp_fib_entry_commit(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - const struct mlxsw_sp_router_ll_ops *ll_ops) -{ - bool postponed_for_bulk = false; - int err; - - err = ll_ops->fib_entry_commit(mlxsw_sp, op_ctx, &postponed_for_bulk); - if (!postponed_for_bulk) - mlxsw_sp_fib_entry_op_ctx_priv_put_all(op_ctx); - return err; -} - static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry *fib_entry, - enum mlxsw_sp_fib_entry_op op) + enum mlxsw_reg_ralue_op op) { - const struct mlxsw_sp_router_ll_ops *ll_ops = fib_entry->fib_node->fib->ll_ops; struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group; struct mlxsw_sp_nexthop_group_info *nhgi = nh_group->nhgi; + char ralue_pl[MLXSW_REG_RALUE_LEN]; enum mlxsw_reg_ralue_trap_action trap_action; u16 trap_id = 0; u32 adjacency_index = 0; @@ -5949,20 +5755,19 @@ static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp, trap_id = MLXSW_TRAP_ID_RTR_INGRESS0; } - mlxsw_sp_fib_entry_pack(op_ctx, fib_entry, op); - ll_ops->fib_entry_act_remote_pack(op_ctx, trap_action, trap_id, - adjacency_index, ecmp_size); - return mlxsw_sp_fib_entry_commit(mlxsw_sp, op_ctx, ll_ops); + mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op); + mlxsw_reg_ralue_act_remote_pack(ralue_pl, trap_action, trap_id, + adjacency_index, ecmp_size); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); } static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry *fib_entry, - enum mlxsw_sp_fib_entry_op op) + enum mlxsw_reg_ralue_op op) { - const struct mlxsw_sp_router_ll_ops *ll_ops = fib_entry->fib_node->fib->ll_ops; struct mlxsw_sp_rif *rif = fib_entry->nh_group->nhgi->nh_rif; enum mlxsw_reg_ralue_trap_action trap_action; + char ralue_pl[MLXSW_REG_RALUE_LEN]; u16 trap_id = 0; u16 rif_index = 0; @@ -5974,64 +5779,61 @@ static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp, trap_id = MLXSW_TRAP_ID_RTR_INGRESS0; } - mlxsw_sp_fib_entry_pack(op_ctx, fib_entry, op); - ll_ops->fib_entry_act_local_pack(op_ctx, trap_action, trap_id, rif_index); - return mlxsw_sp_fib_entry_commit(mlxsw_sp, op_ctx, ll_ops); + mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op); + mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id, + rif_index); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); } static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry *fib_entry, - enum mlxsw_sp_fib_entry_op op) + enum mlxsw_reg_ralue_op op) { - const struct mlxsw_sp_router_ll_ops *ll_ops = fib_entry->fib_node->fib->ll_ops; + char ralue_pl[MLXSW_REG_RALUE_LEN]; - mlxsw_sp_fib_entry_pack(op_ctx, fib_entry, op); - ll_ops->fib_entry_act_ip2me_pack(op_ctx); - return mlxsw_sp_fib_entry_commit(mlxsw_sp, op_ctx, ll_ops); + mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op); + mlxsw_reg_ralue_act_ip2me_pack(ralue_pl); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); } static int mlxsw_sp_fib_entry_op_blackhole(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry *fib_entry, - enum mlxsw_sp_fib_entry_op op) + enum mlxsw_reg_ralue_op op) { - const struct mlxsw_sp_router_ll_ops *ll_ops = fib_entry->fib_node->fib->ll_ops; enum mlxsw_reg_ralue_trap_action trap_action; + char ralue_pl[MLXSW_REG_RALUE_LEN]; trap_action = MLXSW_REG_RALUE_TRAP_ACTION_DISCARD_ERROR; - mlxsw_sp_fib_entry_pack(op_ctx, fib_entry, op); - ll_ops->fib_entry_act_local_pack(op_ctx, trap_action, 0, 0); - return mlxsw_sp_fib_entry_commit(mlxsw_sp, op_ctx, ll_ops); + mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op); + mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, 0, 0); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); } static int mlxsw_sp_fib_entry_op_unreachable(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry *fib_entry, - enum mlxsw_sp_fib_entry_op op) + enum mlxsw_reg_ralue_op op) { - const struct mlxsw_sp_router_ll_ops *ll_ops = fib_entry->fib_node->fib->ll_ops; enum mlxsw_reg_ralue_trap_action trap_action; + char ralue_pl[MLXSW_REG_RALUE_LEN]; u16 trap_id; trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP; trap_id = MLXSW_TRAP_ID_RTR_INGRESS1; - mlxsw_sp_fib_entry_pack(op_ctx, fib_entry, op); - ll_ops->fib_entry_act_local_pack(op_ctx, trap_action, trap_id, 0); - return mlxsw_sp_fib_entry_commit(mlxsw_sp, op_ctx, ll_ops); + mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op); + mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id, 0); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); } static int mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry *fib_entry, - enum mlxsw_sp_fib_entry_op op) + enum mlxsw_reg_ralue_op op) { - const struct mlxsw_sp_router_ll_ops *ll_ops = fib_entry->fib_node->fib->ll_ops; struct mlxsw_sp_ipip_entry *ipip_entry = fib_entry->decap.ipip_entry; const struct mlxsw_sp_ipip_ops *ipip_ops; + char ralue_pl[MLXSW_REG_RALUE_LEN]; int err; if (WARN_ON(!ipip_entry)) @@ -6043,55 +5845,54 @@ mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp, if (err) return err; - mlxsw_sp_fib_entry_pack(op_ctx, fib_entry, op); - ll_ops->fib_entry_act_ip2me_tun_pack(op_ctx, - fib_entry->decap.tunnel_index); - return mlxsw_sp_fib_entry_commit(mlxsw_sp, op_ctx, ll_ops); + mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op); + mlxsw_reg_ralue_act_ip2me_tun_pack(ralue_pl, + fib_entry->decap.tunnel_index); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); } static int mlxsw_sp_fib_entry_op_nve_decap(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry *fib_entry, - enum mlxsw_sp_fib_entry_op op) + enum mlxsw_reg_ralue_op op) { - const struct mlxsw_sp_router_ll_ops *ll_ops = fib_entry->fib_node->fib->ll_ops; + char ralue_pl[MLXSW_REG_RALUE_LEN]; - mlxsw_sp_fib_entry_pack(op_ctx, fib_entry, op); - ll_ops->fib_entry_act_ip2me_tun_pack(op_ctx, - fib_entry->decap.tunnel_index); - return mlxsw_sp_fib_entry_commit(mlxsw_sp, op_ctx, ll_ops); + mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op); + mlxsw_reg_ralue_act_ip2me_tun_pack(ralue_pl, + fib_entry->decap.tunnel_index); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); } static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry *fib_entry, - enum mlxsw_sp_fib_entry_op op) + enum mlxsw_reg_ralue_op op) { switch (fib_entry->type) { case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE: - return mlxsw_sp_fib_entry_op_remote(mlxsw_sp, op_ctx, fib_entry, op); + return mlxsw_sp_fib_entry_op_remote(mlxsw_sp, fib_entry, op); case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL: - return mlxsw_sp_fib_entry_op_local(mlxsw_sp, op_ctx, fib_entry, op); + return mlxsw_sp_fib_entry_op_local(mlxsw_sp, fib_entry, op); case MLXSW_SP_FIB_ENTRY_TYPE_TRAP: - return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, op_ctx, fib_entry, op); + return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op); case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE: - return mlxsw_sp_fib_entry_op_blackhole(mlxsw_sp, op_ctx, fib_entry, op); + return mlxsw_sp_fib_entry_op_blackhole(mlxsw_sp, fib_entry, op); case MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE: - return mlxsw_sp_fib_entry_op_unreachable(mlxsw_sp, op_ctx, fib_entry, op); + return mlxsw_sp_fib_entry_op_unreachable(mlxsw_sp, fib_entry, + op); case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP: - return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp, op_ctx, fib_entry, op); + return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp, + fib_entry, op); case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP: - return mlxsw_sp_fib_entry_op_nve_decap(mlxsw_sp, op_ctx, fib_entry, op); + return mlxsw_sp_fib_entry_op_nve_decap(mlxsw_sp, fib_entry, op); } return -EINVAL; } static int mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry *fib_entry, - enum mlxsw_sp_fib_entry_op op) + enum mlxsw_reg_ralue_op op) { - int err = __mlxsw_sp_fib_entry_op(mlxsw_sp, op_ctx, fib_entry, op); + int err = __mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, op); if (err) return err; @@ -6101,35 +5902,18 @@ static int mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp, return err; } -static int __mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct mlxsw_sp_fib_entry *fib_entry, - bool is_new) -{ - return mlxsw_sp_fib_entry_op(mlxsw_sp, op_ctx, fib_entry, - is_new ? MLXSW_SP_FIB_ENTRY_OP_WRITE : - MLXSW_SP_FIB_ENTRY_OP_UPDATE); -} - static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fib_entry *fib_entry) { - struct mlxsw_sp_fib_entry_op_ctx *op_ctx = mlxsw_sp->router->ll_op_ctx; - - mlxsw_sp_fib_entry_op_ctx_clear(op_ctx); - return __mlxsw_sp_fib_entry_update(mlxsw_sp, op_ctx, fib_entry, false); + return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, + MLXSW_REG_RALUE_OP_WRITE_WRITE); } static int mlxsw_sp_fib_entry_del(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry *fib_entry) { - const struct mlxsw_sp_router_ll_ops *ll_ops = fib_entry->fib_node->fib->ll_ops; - - if (!ll_ops->fib_entry_is_committed(fib_entry->priv)) - return 0; - return mlxsw_sp_fib_entry_op(mlxsw_sp, op_ctx, fib_entry, - MLXSW_SP_FIB_ENTRY_OP_DELETE); + return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, + MLXSW_REG_RALUE_OP_WRITE_DELETE); } static int @@ -6224,12 +6008,6 @@ mlxsw_sp_fib4_entry_create(struct mlxsw_sp *mlxsw_sp, return ERR_PTR(-ENOMEM); fib_entry = &fib4_entry->common; - fib_entry->priv = mlxsw_sp_fib_entry_priv_create(fib_node->fib->ll_ops); - if (IS_ERR(fib_entry->priv)) { - err = PTR_ERR(fib_entry->priv); - goto err_fib_entry_priv_create; - } - err = mlxsw_sp_nexthop4_group_get(mlxsw_sp, fib_entry, fen_info->fi); if (err) goto err_nexthop4_group_get; @@ -6258,8 +6036,6 @@ err_fib4_entry_type_set: err_nexthop_group_vr_link: mlxsw_sp_nexthop4_group_put(mlxsw_sp, &fib4_entry->common); err_nexthop4_group_get: - mlxsw_sp_fib_entry_priv_put(fib_entry->priv); -err_fib_entry_priv_create: kfree(fib4_entry); return ERR_PTR(err); } @@ -6274,7 +6050,6 @@ static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_nexthop_group_vr_unlink(fib4_entry->common.nh_group, fib_node->fib); mlxsw_sp_nexthop4_group_put(mlxsw_sp, &fib4_entry->common); - mlxsw_sp_fib_entry_priv_put(fib4_entry->common.priv); kfree(fib4_entry); } @@ -6512,16 +6287,14 @@ static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp, } static int mlxsw_sp_fib_node_entry_link(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry *fib_entry) { struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node; - bool is_new = !fib_node->fib_entry; int err; fib_node->fib_entry = fib_entry; - err = __mlxsw_sp_fib_entry_update(mlxsw_sp, op_ctx, fib_entry, is_new); + err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry); if (err) goto err_fib_entry_update; @@ -6532,25 +6305,14 @@ err_fib_entry_update: return err; } -static int __mlxsw_sp_fib_node_entry_unlink(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct mlxsw_sp_fib_entry *fib_entry) +static void +mlxsw_sp_fib_node_entry_unlink(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_fib_entry *fib_entry) { struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node; - int err; - err = mlxsw_sp_fib_entry_del(mlxsw_sp, op_ctx, fib_entry); + mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry); fib_node->fib_entry = NULL; - return err; -} - -static void mlxsw_sp_fib_node_entry_unlink(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry *fib_entry) -{ - struct mlxsw_sp_fib_entry_op_ctx *op_ctx = mlxsw_sp->router->ll_op_ctx; - - mlxsw_sp_fib_entry_op_ctx_clear(op_ctx); - __mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, op_ctx, fib_entry); } static bool mlxsw_sp_fib4_allow_replace(struct mlxsw_sp_fib4_entry *fib4_entry) @@ -6572,7 +6334,6 @@ static bool mlxsw_sp_fib4_allow_replace(struct mlxsw_sp_fib4_entry *fib4_entry) static int mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, const struct fib_entry_notifier_info *fen_info) { struct mlxsw_sp_fib4_entry *fib4_entry, *fib4_replaced; @@ -6607,7 +6368,7 @@ mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp, } replaced = fib_node->fib_entry; - err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, op_ctx, &fib4_entry->common); + err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib4_entry->common); if (err) { dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n"); goto err_fib_node_entry_link; @@ -6632,23 +6393,20 @@ err_fib4_entry_create: return err; } -static int mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct fib_entry_notifier_info *fen_info) +static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp, + struct fib_entry_notifier_info *fen_info) { struct mlxsw_sp_fib4_entry *fib4_entry; struct mlxsw_sp_fib_node *fib_node; - int err; fib4_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info); if (!fib4_entry) - return 0; + return; fib_node = fib4_entry->common.fib_node; - err = __mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, op_ctx, &fib4_entry->common); + mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib4_entry->common); mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry); mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); - return err; } static bool mlxsw_sp_fib6_rt_should_ignore(const struct fib6_info *rt) @@ -6946,9 +6704,9 @@ static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, nh_grp); } -static int mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct mlxsw_sp_fib6_entry *fib6_entry) +static int +mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_fib6_entry *fib6_entry) { struct mlxsw_sp_nexthop_group *old_nh_grp = fib6_entry->common.nh_group; struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node; @@ -6971,8 +6729,7 @@ static int mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp, * currently associated with it in the device's table is that * of the old group. Start using the new one instead. */ - err = __mlxsw_sp_fib_entry_update(mlxsw_sp, op_ctx, - &fib6_entry->common, false); + err = mlxsw_sp_fib_entry_update(mlxsw_sp, &fib6_entry->common); if (err) goto err_fib_entry_update; @@ -6996,7 +6753,6 @@ err_nexthop6_group_get: static int mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib6_entry *fib6_entry, struct fib6_info **rt_arr, unsigned int nrt6) { @@ -7014,7 +6770,7 @@ mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp *mlxsw_sp, fib6_entry->nrt6++; } - err = mlxsw_sp_nexthop6_group_update(mlxsw_sp, op_ctx, fib6_entry); + err = mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry); if (err) goto err_rt6_unwind; @@ -7033,7 +6789,6 @@ err_rt6_unwind: static void mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib6_entry *fib6_entry, struct fib6_info **rt_arr, unsigned int nrt6) { @@ -7051,7 +6806,7 @@ mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_rt6_destroy(mlxsw_sp_rt6); } - mlxsw_sp_nexthop6_group_update(mlxsw_sp, op_ctx, fib6_entry); + mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry); } static int @@ -7137,12 +6892,6 @@ mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp, return ERR_PTR(-ENOMEM); fib_entry = &fib6_entry->common; - fib_entry->priv = mlxsw_sp_fib_entry_priv_create(fib_node->fib->ll_ops); - if (IS_ERR(fib_entry->priv)) { - err = PTR_ERR(fib_entry->priv); - goto err_fib_entry_priv_create; - } - INIT_LIST_HEAD(&fib6_entry->rt6_list); for (i = 0; i < nrt6; i++) { @@ -7184,8 +6933,6 @@ err_rt6_unwind: list_del(&mlxsw_sp_rt6->list); mlxsw_sp_rt6_destroy(mlxsw_sp_rt6); } - mlxsw_sp_fib_entry_priv_put(fib_entry->priv); -err_fib_entry_priv_create: kfree(fib6_entry); return ERR_PTR(err); } @@ -7208,7 +6955,6 @@ static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common); mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry); WARN_ON(fib6_entry->nrt6); - mlxsw_sp_fib_entry_priv_put(fib6_entry->common.priv); kfree(fib6_entry); } @@ -7266,8 +7012,8 @@ static bool mlxsw_sp_fib6_allow_replace(struct mlxsw_sp_fib6_entry *fib6_entry) } static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct fib6_info **rt_arr, unsigned int nrt6) + struct fib6_info **rt_arr, + unsigned int nrt6) { struct mlxsw_sp_fib6_entry *fib6_entry, *fib6_replaced; struct mlxsw_sp_fib_entry *replaced; @@ -7306,7 +7052,7 @@ static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp, } replaced = fib_node->fib_entry; - err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, op_ctx, &fib6_entry->common); + err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib6_entry->common); if (err) goto err_fib_node_entry_link; @@ -7330,8 +7076,8 @@ err_fib6_entry_create: } static int mlxsw_sp_router_fib6_append(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct fib6_info **rt_arr, unsigned int nrt6) + struct fib6_info **rt_arr, + unsigned int nrt6) { struct mlxsw_sp_fib6_entry *fib6_entry; struct mlxsw_sp_fib_node *fib_node; @@ -7359,7 +7105,8 @@ static int mlxsw_sp_router_fib6_append(struct mlxsw_sp *mlxsw_sp, fib6_entry = container_of(fib_node->fib_entry, struct mlxsw_sp_fib6_entry, common); - err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, op_ctx, fib6_entry, rt_arr, nrt6); + err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt_arr, + nrt6); if (err) goto err_fib6_entry_nexthop_add; @@ -7370,17 +7117,16 @@ err_fib6_entry_nexthop_add: return err; } -static int mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct fib6_info **rt_arr, unsigned int nrt6) +static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp, + struct fib6_info **rt_arr, + unsigned int nrt6) { struct mlxsw_sp_fib6_entry *fib6_entry; struct mlxsw_sp_fib_node *fib_node; struct fib6_info *rt = rt_arr[0]; - int err; if (mlxsw_sp_fib6_rt_should_ignore(rt)) - return 0; + return; /* Multipath routes are first added to the FIB trie and only then * notified. If we vetoed the addition, we will get a delete @@ -7389,22 +7135,22 @@ static int mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp, */ fib6_entry = mlxsw_sp_fib6_entry_lookup(mlxsw_sp, rt); if (!fib6_entry) - return 0; + return; /* If not all the nexthops are deleted, then only reduce the nexthop * group. */ if (nrt6 != fib6_entry->nrt6) { - mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp, op_ctx, fib6_entry, rt_arr, nrt6); - return 0; + mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp, fib6_entry, rt_arr, + nrt6); + return; } fib_node = fib6_entry->common.fib_node; - err = __mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, op_ctx, &fib6_entry->common); + mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib6_entry->common); mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry); mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); - return err; } static struct mlxsw_sp_mr_table * @@ -7557,15 +7303,15 @@ static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp) } } -struct mlxsw_sp_fib6_event { +struct mlxsw_sp_fib6_event_work { struct fib6_info **rt_arr; unsigned int nrt6; }; -struct mlxsw_sp_fib_event { - struct list_head list; /* node in fib queue */ +struct mlxsw_sp_fib_event_work { + struct work_struct work; union { - struct mlxsw_sp_fib6_event fib6_event; + struct mlxsw_sp_fib6_event_work fib6_work; struct fib_entry_notifier_info fen_info; struct fib_rule_notifier_info fr_info; struct fib_nh_notifier_info fnh_info; @@ -7574,12 +7320,11 @@ struct mlxsw_sp_fib_event { }; struct mlxsw_sp *mlxsw_sp; unsigned long event; - int family; }; static int -mlxsw_sp_router_fib6_event_init(struct mlxsw_sp_fib6_event *fib6_event, - struct fib6_entry_notifier_info *fen6_info) +mlxsw_sp_router_fib6_work_init(struct mlxsw_sp_fib6_event_work *fib6_work, + struct fib6_entry_notifier_info *fen6_info) { struct fib6_info *rt = fen6_info->rt; struct fib6_info **rt_arr; @@ -7593,8 +7338,8 @@ mlxsw_sp_router_fib6_event_init(struct mlxsw_sp_fib6_event *fib6_event, if (!rt_arr) return -ENOMEM; - fib6_event->rt_arr = rt_arr; - fib6_event->nrt6 = nrt6; + fib6_work->rt_arr = rt_arr; + fib6_work->nrt6 = nrt6; rt_arr[0] = rt; fib6_info_hold(rt); @@ -7616,242 +7361,182 @@ mlxsw_sp_router_fib6_event_init(struct mlxsw_sp_fib6_event *fib6_event, } static void -mlxsw_sp_router_fib6_event_fini(struct mlxsw_sp_fib6_event *fib6_event) +mlxsw_sp_router_fib6_work_fini(struct mlxsw_sp_fib6_event_work *fib6_work) { int i; - for (i = 0; i < fib6_event->nrt6; i++) - mlxsw_sp_rt6_release(fib6_event->rt_arr[i]); - kfree(fib6_event->rt_arr); + for (i = 0; i < fib6_work->nrt6; i++) + mlxsw_sp_rt6_release(fib6_work->rt_arr[i]); + kfree(fib6_work->rt_arr); } -static void mlxsw_sp_router_fib4_event_process(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct mlxsw_sp_fib_event *fib_event) +static void mlxsw_sp_router_fib4_event_work(struct work_struct *work) { + struct mlxsw_sp_fib_event_work *fib_work = + container_of(work, struct mlxsw_sp_fib_event_work, work); + struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp; int err; + mutex_lock(&mlxsw_sp->router->lock); mlxsw_sp_span_respin(mlxsw_sp); - switch (fib_event->event) { + switch (fib_work->event) { case FIB_EVENT_ENTRY_REPLACE: - err = mlxsw_sp_router_fib4_replace(mlxsw_sp, op_ctx, &fib_event->fen_info); + err = mlxsw_sp_router_fib4_replace(mlxsw_sp, + &fib_work->fen_info); if (err) { - mlxsw_sp_fib_entry_op_ctx_priv_put_all(op_ctx); dev_warn(mlxsw_sp->bus_info->dev, "FIB replace failed.\n"); mlxsw_sp_fib4_offload_failed_flag_set(mlxsw_sp, - &fib_event->fen_info); + &fib_work->fen_info); } - fib_info_put(fib_event->fen_info.fi); + fib_info_put(fib_work->fen_info.fi); break; case FIB_EVENT_ENTRY_DEL: - err = mlxsw_sp_router_fib4_del(mlxsw_sp, op_ctx, &fib_event->fen_info); - if (err) - mlxsw_sp_fib_entry_op_ctx_priv_put_all(op_ctx); - fib_info_put(fib_event->fen_info.fi); + mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info); + fib_info_put(fib_work->fen_info.fi); break; case FIB_EVENT_NH_ADD: case FIB_EVENT_NH_DEL: - mlxsw_sp_nexthop4_event(mlxsw_sp, fib_event->event, fib_event->fnh_info.fib_nh); - fib_info_put(fib_event->fnh_info.fib_nh->nh_parent); + mlxsw_sp_nexthop4_event(mlxsw_sp, fib_work->event, + fib_work->fnh_info.fib_nh); + fib_info_put(fib_work->fnh_info.fib_nh->nh_parent); break; } + mutex_unlock(&mlxsw_sp->router->lock); + kfree(fib_work); } -static void mlxsw_sp_router_fib6_event_process(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct mlxsw_sp_fib_event *fib_event) +static void mlxsw_sp_router_fib6_event_work(struct work_struct *work) { - struct mlxsw_sp_fib6_event *fib6_event = &fib_event->fib6_event; + struct mlxsw_sp_fib_event_work *fib_work = + container_of(work, struct mlxsw_sp_fib_event_work, work); + struct mlxsw_sp_fib6_event_work *fib6_work = &fib_work->fib6_work; + struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp; int err; + mutex_lock(&mlxsw_sp->router->lock); mlxsw_sp_span_respin(mlxsw_sp); - switch (fib_event->event) { + switch (fib_work->event) { case FIB_EVENT_ENTRY_REPLACE: - err = mlxsw_sp_router_fib6_replace(mlxsw_sp, op_ctx, fib_event->fib6_event.rt_arr, - fib_event->fib6_event.nrt6); + err = mlxsw_sp_router_fib6_replace(mlxsw_sp, + fib6_work->rt_arr, + fib6_work->nrt6); if (err) { - mlxsw_sp_fib_entry_op_ctx_priv_put_all(op_ctx); dev_warn(mlxsw_sp->bus_info->dev, "FIB replace failed.\n"); mlxsw_sp_fib6_offload_failed_flag_set(mlxsw_sp, - fib6_event->rt_arr, - fib6_event->nrt6); + fib6_work->rt_arr, + fib6_work->nrt6); } - mlxsw_sp_router_fib6_event_fini(&fib_event->fib6_event); + mlxsw_sp_router_fib6_work_fini(fib6_work); break; case FIB_EVENT_ENTRY_APPEND: - err = mlxsw_sp_router_fib6_append(mlxsw_sp, op_ctx, fib_event->fib6_event.rt_arr, - fib_event->fib6_event.nrt6); + err = mlxsw_sp_router_fib6_append(mlxsw_sp, + fib6_work->rt_arr, + fib6_work->nrt6); if (err) { - mlxsw_sp_fib_entry_op_ctx_priv_put_all(op_ctx); dev_warn(mlxsw_sp->bus_info->dev, "FIB append failed.\n"); mlxsw_sp_fib6_offload_failed_flag_set(mlxsw_sp, - fib6_event->rt_arr, - fib6_event->nrt6); + fib6_work->rt_arr, + fib6_work->nrt6); } - mlxsw_sp_router_fib6_event_fini(&fib_event->fib6_event); + mlxsw_sp_router_fib6_work_fini(fib6_work); break; case FIB_EVENT_ENTRY_DEL: - err = mlxsw_sp_router_fib6_del(mlxsw_sp, op_ctx, fib_event->fib6_event.rt_arr, - fib_event->fib6_event.nrt6); - if (err) - mlxsw_sp_fib_entry_op_ctx_priv_put_all(op_ctx); - mlxsw_sp_router_fib6_event_fini(&fib_event->fib6_event); + mlxsw_sp_router_fib6_del(mlxsw_sp, + fib6_work->rt_arr, + fib6_work->nrt6); + mlxsw_sp_router_fib6_work_fini(fib6_work); break; } + mutex_unlock(&mlxsw_sp->router->lock); + kfree(fib_work); } -static void mlxsw_sp_router_fibmr_event_process(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_event *fib_event) +static void mlxsw_sp_router_fibmr_event_work(struct work_struct *work) { + struct mlxsw_sp_fib_event_work *fib_work = + container_of(work, struct mlxsw_sp_fib_event_work, work); + struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp; bool replace; int err; rtnl_lock(); mutex_lock(&mlxsw_sp->router->lock); - switch (fib_event->event) { + switch (fib_work->event) { case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_ADD: - replace = fib_event->event == FIB_EVENT_ENTRY_REPLACE; + replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE; - err = mlxsw_sp_router_fibmr_add(mlxsw_sp, &fib_event->men_info, replace); + err = mlxsw_sp_router_fibmr_add(mlxsw_sp, &fib_work->men_info, + replace); if (err) dev_warn(mlxsw_sp->bus_info->dev, "MR entry add failed.\n"); - mr_cache_put(fib_event->men_info.mfc); + mr_cache_put(fib_work->men_info.mfc); break; case FIB_EVENT_ENTRY_DEL: - mlxsw_sp_router_fibmr_del(mlxsw_sp, &fib_event->men_info); - mr_cache_put(fib_event->men_info.mfc); + mlxsw_sp_router_fibmr_del(mlxsw_sp, &fib_work->men_info); + mr_cache_put(fib_work->men_info.mfc); break; case FIB_EVENT_VIF_ADD: err = mlxsw_sp_router_fibmr_vif_add(mlxsw_sp, - &fib_event->ven_info); + &fib_work->ven_info); if (err) dev_warn(mlxsw_sp->bus_info->dev, "MR VIF add failed.\n"); - dev_put(fib_event->ven_info.dev); + dev_put(fib_work->ven_info.dev); break; case FIB_EVENT_VIF_DEL: - mlxsw_sp_router_fibmr_vif_del(mlxsw_sp, &fib_event->ven_info); - dev_put(fib_event->ven_info.dev); + mlxsw_sp_router_fibmr_vif_del(mlxsw_sp, + &fib_work->ven_info); + dev_put(fib_work->ven_info.dev); break; } mutex_unlock(&mlxsw_sp->router->lock); rtnl_unlock(); + kfree(fib_work); } -static void mlxsw_sp_router_fib_event_work(struct work_struct *work) -{ - struct mlxsw_sp_router *router = container_of(work, struct mlxsw_sp_router, fib_event_work); - struct mlxsw_sp_fib_entry_op_ctx *op_ctx = router->ll_op_ctx; - struct mlxsw_sp *mlxsw_sp = router->mlxsw_sp; - struct mlxsw_sp_fib_event *next_fib_event; - struct mlxsw_sp_fib_event *fib_event; - int last_family = AF_UNSPEC; - LIST_HEAD(fib_event_queue); - - spin_lock_bh(&router->fib_event_queue_lock); - list_splice_init(&router->fib_event_queue, &fib_event_queue); - spin_unlock_bh(&router->fib_event_queue_lock); - - /* Router lock is held here to make sure per-instance - * operation context is not used in between FIB4/6 events - * processing. - */ - mutex_lock(&router->lock); - mlxsw_sp_fib_entry_op_ctx_clear(op_ctx); - list_for_each_entry_safe(fib_event, next_fib_event, - &fib_event_queue, list) { - /* Check if the next entry in the queue exists and it is - * of the same type (family and event) as the currect one. - * In that case it is permitted to do the bulking - * of multiple FIB entries to a single register write. - */ - op_ctx->bulk_ok = !list_is_last(&fib_event->list, &fib_event_queue) && - fib_event->family == next_fib_event->family && - fib_event->event == next_fib_event->event; - op_ctx->event = fib_event->event; - - /* In case family of this and the previous entry are different, context - * reinitialization is going to be needed now, indicate that. - * Note that since last_family is initialized to AF_UNSPEC, this is always - * going to happen for the first entry processed in the work. - */ - if (fib_event->family != last_family) - op_ctx->initialized = false; - - switch (fib_event->family) { - case AF_INET: - mlxsw_sp_router_fib4_event_process(mlxsw_sp, op_ctx, - fib_event); - break; - case AF_INET6: - mlxsw_sp_router_fib6_event_process(mlxsw_sp, op_ctx, - fib_event); - break; - case RTNL_FAMILY_IP6MR: - case RTNL_FAMILY_IPMR: - /* Unlock here as inside FIBMR the lock is taken again - * under RTNL. The per-instance operation context - * is not used by FIBMR. - */ - mutex_unlock(&router->lock); - mlxsw_sp_router_fibmr_event_process(mlxsw_sp, - fib_event); - mutex_lock(&router->lock); - break; - default: - WARN_ON_ONCE(1); - } - last_family = fib_event->family; - kfree(fib_event); - cond_resched(); - } - WARN_ON_ONCE(!list_empty(&router->ll_op_ctx->fib_entry_priv_list)); - mutex_unlock(&router->lock); -} - -static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event *fib_event, +static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work, struct fib_notifier_info *info) { struct fib_entry_notifier_info *fen_info; struct fib_nh_notifier_info *fnh_info; - switch (fib_event->event) { + switch (fib_work->event) { case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_DEL: fen_info = container_of(info, struct fib_entry_notifier_info, info); - fib_event->fen_info = *fen_info; + fib_work->fen_info = *fen_info; /* Take reference on fib_info to prevent it from being - * freed while event is queued. Release it afterwards. + * freed while work is queued. Release it afterwards. */ - fib_info_hold(fib_event->fen_info.fi); + fib_info_hold(fib_work->fen_info.fi); break; case FIB_EVENT_NH_ADD: case FIB_EVENT_NH_DEL: fnh_info = container_of(info, struct fib_nh_notifier_info, info); - fib_event->fnh_info = *fnh_info; - fib_info_hold(fib_event->fnh_info.fib_nh->nh_parent); + fib_work->fnh_info = *fnh_info; + fib_info_hold(fib_work->fnh_info.fib_nh->nh_parent); break; } } -static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event *fib_event, +static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work, struct fib_notifier_info *info) { struct fib6_entry_notifier_info *fen6_info; int err; - switch (fib_event->event) { + switch (fib_work->event) { case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_APPEND: case FIB_EVENT_ENTRY_DEL: fen6_info = container_of(info, struct fib6_entry_notifier_info, info); - err = mlxsw_sp_router_fib6_event_init(&fib_event->fib6_event, - fen6_info); + err = mlxsw_sp_router_fib6_work_init(&fib_work->fib6_work, + fen6_info); if (err) return err; break; @@ -7861,20 +7546,20 @@ static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event *fib_event, } static void -mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event *fib_event, +mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event_work *fib_work, struct fib_notifier_info *info) { - switch (fib_event->event) { + switch (fib_work->event) { case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_ADD: case FIB_EVENT_ENTRY_DEL: - memcpy(&fib_event->men_info, info, sizeof(fib_event->men_info)); - mr_cache_hold(fib_event->men_info.mfc); + memcpy(&fib_work->men_info, info, sizeof(fib_work->men_info)); + mr_cache_hold(fib_work->men_info.mfc); break; case FIB_EVENT_VIF_ADD: case FIB_EVENT_VIF_DEL: - memcpy(&fib_event->ven_info, info, sizeof(fib_event->ven_info)); - dev_hold(fib_event->ven_info.dev); + memcpy(&fib_work->ven_info, info, sizeof(fib_work->ven_info)); + dev_hold(fib_work->ven_info.dev); break; } } @@ -7928,7 +7613,7 @@ static int mlxsw_sp_router_fib_rule_event(unsigned long event, static int mlxsw_sp_router_fib_event(struct notifier_block *nb, unsigned long event, void *ptr) { - struct mlxsw_sp_fib_event *fib_event; + struct mlxsw_sp_fib_event_work *fib_work; struct fib_notifier_info *info = ptr; struct mlxsw_sp_router *router; int err; @@ -7960,39 +7645,37 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb, break; } - fib_event = kzalloc(sizeof(*fib_event), GFP_ATOMIC); - if (!fib_event) + fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC); + if (!fib_work) return NOTIFY_BAD; - fib_event->mlxsw_sp = router->mlxsw_sp; - fib_event->event = event; - fib_event->family = info->family; + fib_work->mlxsw_sp = router->mlxsw_sp; + fib_work->event = event; switch (info->family) { case AF_INET: - mlxsw_sp_router_fib4_event(fib_event, info); + INIT_WORK(&fib_work->work, mlxsw_sp_router_fib4_event_work); + mlxsw_sp_router_fib4_event(fib_work, info); break; case AF_INET6: - err = mlxsw_sp_router_fib6_event(fib_event, info); + INIT_WORK(&fib_work->work, mlxsw_sp_router_fib6_event_work); + err = mlxsw_sp_router_fib6_event(fib_work, info); if (err) goto err_fib_event; break; case RTNL_FAMILY_IP6MR: case RTNL_FAMILY_IPMR: - mlxsw_sp_router_fibmr_event(fib_event, info); + INIT_WORK(&fib_work->work, mlxsw_sp_router_fibmr_event_work); + mlxsw_sp_router_fibmr_event(fib_work, info); break; } - /* Enqueue the event and trigger the work */ - spin_lock_bh(&router->fib_event_queue_lock); - list_add_tail(&fib_event->list, &router->fib_event_queue); - spin_unlock_bh(&router->fib_event_queue_lock); - mlxsw_core_schedule_work(&router->fib_event_work); + mlxsw_core_schedule_work(&fib_work->work); return NOTIFY_DONE; err_fib_event: - kfree(fib_event); + kfree(fib_work); return NOTIFY_BAD; } @@ -10533,46 +10216,6 @@ static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl); } -static const struct mlxsw_sp_router_ll_ops mlxsw_sp_router_ll_basic_ops = { - .init = mlxsw_sp_router_ll_basic_init, - .ralta_write = mlxsw_sp_router_ll_basic_ralta_write, - .ralst_write = mlxsw_sp_router_ll_basic_ralst_write, - .raltb_write = mlxsw_sp_router_ll_basic_raltb_write, - .fib_entry_op_ctx_size = sizeof(struct mlxsw_sp_fib_entry_op_ctx_basic), - .fib_entry_pack = mlxsw_sp_router_ll_basic_fib_entry_pack, - .fib_entry_act_remote_pack = mlxsw_sp_router_ll_basic_fib_entry_act_remote_pack, - .fib_entry_act_local_pack = mlxsw_sp_router_ll_basic_fib_entry_act_local_pack, - .fib_entry_act_ip2me_pack = mlxsw_sp_router_ll_basic_fib_entry_act_ip2me_pack, - .fib_entry_act_ip2me_tun_pack = mlxsw_sp_router_ll_basic_fib_entry_act_ip2me_tun_pack, - .fib_entry_commit = mlxsw_sp_router_ll_basic_fib_entry_commit, - .fib_entry_is_committed = mlxsw_sp_router_ll_basic_fib_entry_is_committed, -}; - -static int mlxsw_sp_router_ll_op_ctx_init(struct mlxsw_sp_router *router) -{ - size_t max_size = 0; - int i; - - for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++) { - size_t size = router->proto_ll_ops[i]->fib_entry_op_ctx_size; - - if (size > max_size) - max_size = size; - } - router->ll_op_ctx = kzalloc(sizeof(*router->ll_op_ctx) + max_size, - GFP_KERNEL); - if (!router->ll_op_ctx) - return -ENOMEM; - INIT_LIST_HEAD(&router->ll_op_ctx->fib_entry_priv_list); - return 0; -} - -static void mlxsw_sp_router_ll_op_ctx_fini(struct mlxsw_sp_router *router) -{ - WARN_ON(!list_empty(&router->ll_op_ctx->fib_entry_priv_list)); - kfree(router->ll_op_ctx); -} - static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp) { u16 lb_rif_index; @@ -10646,23 +10289,9 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, if (err) goto err_router_ops_init; - err = mlxsw_sp_router_xm_init(mlxsw_sp); - if (err) - goto err_xm_init; - - router->proto_ll_ops[MLXSW_SP_L3_PROTO_IPV4] = mlxsw_sp_router_xm_ipv4_is_supported(mlxsw_sp) ? - &mlxsw_sp_router_ll_xm_ops : - &mlxsw_sp_router_ll_basic_ops; - router->proto_ll_ops[MLXSW_SP_L3_PROTO_IPV6] = &mlxsw_sp_router_ll_basic_ops; - - err = mlxsw_sp_router_ll_op_ctx_init(router); - if (err) - goto err_ll_op_ctx_init; - INIT_LIST_HEAD(&mlxsw_sp->router->nh_res_grp_list); INIT_DELAYED_WORK(&mlxsw_sp->router->nh_grp_activity_dw, mlxsw_sp_nh_grp_activity_work); - INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_neighs_list); err = __mlxsw_sp_router_init(mlxsw_sp); if (err) @@ -10715,10 +10344,6 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, if (err) goto err_dscp_init; - INIT_WORK(&router->fib_event_work, mlxsw_sp_router_fib_event_work); - INIT_LIST_HEAD(&router->fib_event_queue); - spin_lock_init(&router->fib_event_queue_lock); - router->inetaddr_nb.notifier_call = mlxsw_sp_inetaddr_event; err = register_inetaddr_notifier(&router->inetaddr_nb); if (err) @@ -10773,7 +10398,6 @@ err_register_inet6addr_notifier: unregister_inetaddr_notifier(&router->inetaddr_nb); err_register_inetaddr_notifier: mlxsw_core_flush_owq(); - WARN_ON(!list_empty(&router->fib_event_queue)); err_dscp_init: err_mp_hash_init: mlxsw_sp_neigh_fini(mlxsw_sp); @@ -10797,10 +10421,6 @@ err_rifs_init: __mlxsw_sp_router_fini(mlxsw_sp); err_router_init: cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw); - mlxsw_sp_router_ll_op_ctx_fini(router); -err_ll_op_ctx_init: - mlxsw_sp_router_xm_fini(mlxsw_sp); -err_xm_init: err_router_ops_init: mutex_destroy(&mlxsw_sp->router->lock); kfree(mlxsw_sp->router); @@ -10819,7 +10439,6 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb); unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb); mlxsw_core_flush_owq(); - WARN_ON(!list_empty(&mlxsw_sp->router->fib_event_queue)); mlxsw_sp_neigh_fini(mlxsw_sp); mlxsw_sp_lb_rif_fini(mlxsw_sp); mlxsw_sp_vrs_fini(mlxsw_sp); @@ -10831,8 +10450,6 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) mlxsw_sp_rifs_fini(mlxsw_sp); __mlxsw_sp_router_fini(mlxsw_sp); cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw); - mlxsw_sp_router_ll_op_ctx_fini(mlxsw_sp->router); - mlxsw_sp_router_xm_fini(mlxsw_sp); mutex_destroy(&mlxsw_sp->router->lock); kfree(mlxsw_sp->router); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h index 37411b74c3e6..f7510be1cf2d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h @@ -15,27 +15,6 @@ struct mlxsw_sp_router_nve_decap { u8 valid:1; }; -struct mlxsw_sp_fib_entry_op_ctx { - u8 bulk_ok:1, /* Indicate to the low-level op it is ok to bulk - * the actual entry with the one that is the next - * in queue. - */ - initialized:1; /* Bit that the low-level op sets in case - * the context priv is initialized. - */ - struct list_head fib_entry_priv_list; - unsigned long event; - unsigned long ll_priv[]; -}; - -static inline void -mlxsw_sp_fib_entry_op_ctx_clear(struct mlxsw_sp_fib_entry_op_ctx *op_ctx) -{ - WARN_ON_ONCE(!list_empty(&op_ctx->fib_entry_priv_list)); - memset(op_ctx, 0, sizeof(*op_ctx)); - INIT_LIST_HEAD(&op_ctx->fib_entry_priv_list); -} - struct mlxsw_sp_router { struct mlxsw_sp *mlxsw_sp; struct mlxsw_sp_rif **rifs; @@ -72,14 +51,8 @@ struct mlxsw_sp_router { const struct mlxsw_sp_ipip_ops **ipip_ops_arr; struct mlxsw_sp_router_nve_decap nve_decap_config; struct mutex lock; /* Protects shared router resources */ - struct work_struct fib_event_work; - struct list_head fib_event_queue; - spinlock_t fib_event_queue_lock; /* Protects fib event queue list */ - /* One set of ops for each protocol: IPv4 and IPv6 */ - const struct mlxsw_sp_router_ll_ops *proto_ll_ops[MLXSW_SP_L3_PROTO_MAX]; struct mlxsw_sp_fib_entry_op_ctx *ll_op_ctx; u16 lb_rif_index; - struct mlxsw_sp_router_xm *xm; const struct mlxsw_sp_adj_grp_size_range *adj_grp_size_ranges; size_t adj_grp_size_ranges_count; struct delayed_work nh_grp_activity_dw; @@ -89,48 +62,6 @@ struct mlxsw_sp_router { u32 adj_trap_index; }; -struct mlxsw_sp_fib_entry_priv { - refcount_t refcnt; - struct list_head list; /* Member in op_ctx->fib_entry_priv_list */ - unsigned long priv[]; -}; - -enum mlxsw_sp_fib_entry_op { - MLXSW_SP_FIB_ENTRY_OP_WRITE, - MLXSW_SP_FIB_ENTRY_OP_UPDATE, - MLXSW_SP_FIB_ENTRY_OP_DELETE, -}; - -/* Low-level router ops. Basically this is to handle the different - * register sets to work with ordinary and XM trees and FIB entries. - */ -struct mlxsw_sp_router_ll_ops { - int (*init)(struct mlxsw_sp *mlxsw_sp, u16 vr_id, - enum mlxsw_sp_l3proto proto); - int (*ralta_write)(struct mlxsw_sp *mlxsw_sp, char *xralta_pl); - int (*ralst_write)(struct mlxsw_sp *mlxsw_sp, char *xralst_pl); - int (*raltb_write)(struct mlxsw_sp *mlxsw_sp, char *xraltb_pl); - size_t fib_entry_op_ctx_size; - size_t fib_entry_priv_size; - void (*fib_entry_pack)(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - enum mlxsw_sp_l3proto proto, enum mlxsw_sp_fib_entry_op op, - u16 virtual_router, u8 prefix_len, unsigned char *addr, - struct mlxsw_sp_fib_entry_priv *priv); - void (*fib_entry_act_remote_pack)(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - enum mlxsw_reg_ralue_trap_action trap_action, - u16 trap_id, u32 adjacency_index, u16 ecmp_size); - void (*fib_entry_act_local_pack)(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - enum mlxsw_reg_ralue_trap_action trap_action, - u16 trap_id, u16 local_erif); - void (*fib_entry_act_ip2me_pack)(struct mlxsw_sp_fib_entry_op_ctx *op_ctx); - void (*fib_entry_act_ip2me_tun_pack)(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - u32 tunnel_ptr); - int (*fib_entry_commit)(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - bool *postponed_for_bulk); - bool (*fib_entry_is_committed)(struct mlxsw_sp_fib_entry_priv *priv); -}; - struct mlxsw_sp_rif_ipip_lb; struct mlxsw_sp_rif_ipip_lb_config { enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt; @@ -232,10 +163,4 @@ int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp); struct net_device * mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev); -extern const struct mlxsw_sp_router_ll_ops mlxsw_sp_router_ll_xm_ops; - -int mlxsw_sp_router_xm_init(struct mlxsw_sp *mlxsw_sp); -void mlxsw_sp_router_xm_fini(struct mlxsw_sp *mlxsw_sp); -bool mlxsw_sp_router_xm_ipv4_is_supported(const struct mlxsw_sp *mlxsw_sp); - #endif /* _MLXSW_ROUTER_H_*/ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router_xm.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router_xm.c deleted file mode 100644 index d213af723a2a..000000000000 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router_xm.c +++ /dev/null @@ -1,812 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 -/* Copyright (c) 2020 Mellanox Technologies. All rights reserved */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/rhashtable.h> - -#include "spectrum.h" -#include "core.h" -#include "reg.h" -#include "spectrum_router.h" - -#define MLXSW_SP_ROUTER_XM_M_VAL 16 - -static const u8 mlxsw_sp_router_xm_m_val[] = { - [MLXSW_SP_L3_PROTO_IPV4] = MLXSW_SP_ROUTER_XM_M_VAL, - [MLXSW_SP_L3_PROTO_IPV6] = 0, /* Currently unused. */ -}; - -#define MLXSW_SP_ROUTER_XM_L_VAL_MAX 16 - -struct mlxsw_sp_router_xm { - bool ipv4_supported; - bool ipv6_supported; - unsigned int entries_size; - struct rhashtable ltable_ht; - struct rhashtable flush_ht; /* Stores items about to be flushed from cache */ - unsigned int flush_count; - bool flush_all_mode; -}; - -struct mlxsw_sp_router_xm_ltable_node { - struct rhash_head ht_node; /* Member of router_xm->ltable_ht */ - u16 mindex; - u8 current_lvalue; - refcount_t refcnt; - unsigned int lvalue_ref[MLXSW_SP_ROUTER_XM_L_VAL_MAX + 1]; -}; - -static const struct rhashtable_params mlxsw_sp_router_xm_ltable_ht_params = { - .key_offset = offsetof(struct mlxsw_sp_router_xm_ltable_node, mindex), - .head_offset = offsetof(struct mlxsw_sp_router_xm_ltable_node, ht_node), - .key_len = sizeof(u16), - .automatic_shrinking = true, -}; - -struct mlxsw_sp_router_xm_flush_info { - bool all; - enum mlxsw_sp_l3proto proto; - u16 virtual_router; - u8 prefix_len; - unsigned char addr[sizeof(struct in6_addr)]; -}; - -struct mlxsw_sp_router_xm_fib_entry { - bool committed; - struct mlxsw_sp_router_xm_ltable_node *ltable_node; /* Parent node */ - u16 mindex; /* Store for processing from commit op */ - u8 lvalue; - struct mlxsw_sp_router_xm_flush_info flush_info; -}; - -#define MLXSW_SP_ROUTE_LL_XM_ENTRIES_MAX \ - (MLXSW_REG_XMDR_TRANS_LEN / MLXSW_REG_XMDR_C_LT_ROUTE_V4_LEN) - -struct mlxsw_sp_fib_entry_op_ctx_xm { - bool initialized; - char xmdr_pl[MLXSW_REG_XMDR_LEN]; - unsigned int trans_offset; /* Offset of the current command within one - * transaction of XMDR register. - */ - unsigned int trans_item_len; /* The current command length. This is used - * to advance 'trans_offset' when the next - * command is appended. - */ - unsigned int entries_count; - struct mlxsw_sp_router_xm_fib_entry *entries[MLXSW_SP_ROUTE_LL_XM_ENTRIES_MAX]; -}; - -static int mlxsw_sp_router_ll_xm_init(struct mlxsw_sp *mlxsw_sp, u16 vr_id, - enum mlxsw_sp_l3proto proto) -{ - char rxlte_pl[MLXSW_REG_RXLTE_LEN]; - - mlxsw_reg_rxlte_pack(rxlte_pl, vr_id, - (enum mlxsw_reg_rxlte_protocol) proto, true); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rxlte), rxlte_pl); -} - -static int mlxsw_sp_router_ll_xm_ralta_write(struct mlxsw_sp *mlxsw_sp, char *xralta_pl) -{ - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(xralta), xralta_pl); -} - -static int mlxsw_sp_router_ll_xm_ralst_write(struct mlxsw_sp *mlxsw_sp, char *xralst_pl) -{ - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(xralst), xralst_pl); -} - -static int mlxsw_sp_router_ll_xm_raltb_write(struct mlxsw_sp *mlxsw_sp, char *xraltb_pl) -{ - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(xraltb), xraltb_pl); -} - -static u16 mlxsw_sp_router_ll_xm_mindex_get4(const u32 addr) -{ - /* Currently the M-index is set to linear mode. That means it is defined - * as 16 MSB of IP address. - */ - return addr >> MLXSW_SP_ROUTER_XM_L_VAL_MAX; -} - -static u16 mlxsw_sp_router_ll_xm_mindex_get6(const unsigned char *addr) -{ - WARN_ON_ONCE(1); - return 0; /* currently unused */ -} - -static void mlxsw_sp_router_ll_xm_op_ctx_check_init(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - struct mlxsw_sp_fib_entry_op_ctx_xm *op_ctx_xm) -{ - if (op_ctx->initialized) - return; - op_ctx->initialized = true; - - mlxsw_reg_xmdr_pack(op_ctx_xm->xmdr_pl, true); - op_ctx_xm->trans_offset = 0; - op_ctx_xm->entries_count = 0; -} - -static void mlxsw_sp_router_ll_xm_fib_entry_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - enum mlxsw_sp_l3proto proto, - enum mlxsw_sp_fib_entry_op op, - u16 virtual_router, u8 prefix_len, - unsigned char *addr, - struct mlxsw_sp_fib_entry_priv *priv) -{ - struct mlxsw_sp_fib_entry_op_ctx_xm *op_ctx_xm = (void *) op_ctx->ll_priv; - struct mlxsw_sp_router_xm_fib_entry *fib_entry = (void *) priv->priv; - struct mlxsw_sp_router_xm_flush_info *flush_info; - enum mlxsw_reg_xmdr_c_ltr_op xmdr_c_ltr_op; - unsigned int len; - - mlxsw_sp_router_ll_xm_op_ctx_check_init(op_ctx, op_ctx_xm); - - switch (op) { - case MLXSW_SP_FIB_ENTRY_OP_WRITE: - xmdr_c_ltr_op = MLXSW_REG_XMDR_C_LTR_OP_WRITE; - break; - case MLXSW_SP_FIB_ENTRY_OP_UPDATE: - xmdr_c_ltr_op = MLXSW_REG_XMDR_C_LTR_OP_UPDATE; - break; - case MLXSW_SP_FIB_ENTRY_OP_DELETE: - xmdr_c_ltr_op = MLXSW_REG_XMDR_C_LTR_OP_DELETE; - break; - default: - WARN_ON_ONCE(1); - return; - } - - switch (proto) { - case MLXSW_SP_L3_PROTO_IPV4: - len = mlxsw_reg_xmdr_c_ltr_pack4(op_ctx_xm->xmdr_pl, op_ctx_xm->trans_offset, - op_ctx_xm->entries_count, xmdr_c_ltr_op, - virtual_router, prefix_len, (u32 *) addr); - fib_entry->mindex = mlxsw_sp_router_ll_xm_mindex_get4(*((u32 *) addr)); - break; - case MLXSW_SP_L3_PROTO_IPV6: - len = mlxsw_reg_xmdr_c_ltr_pack6(op_ctx_xm->xmdr_pl, op_ctx_xm->trans_offset, - op_ctx_xm->entries_count, xmdr_c_ltr_op, - virtual_router, prefix_len, addr); - fib_entry->mindex = mlxsw_sp_router_ll_xm_mindex_get6(addr); - break; - default: - WARN_ON_ONCE(1); - return; - } - if (!op_ctx_xm->trans_offset) - op_ctx_xm->trans_item_len = len; - else - WARN_ON_ONCE(op_ctx_xm->trans_item_len != len); - - op_ctx_xm->entries[op_ctx_xm->entries_count] = fib_entry; - - fib_entry->lvalue = prefix_len > mlxsw_sp_router_xm_m_val[proto] ? - prefix_len - mlxsw_sp_router_xm_m_val[proto] : 0; - - flush_info = &fib_entry->flush_info; - flush_info->proto = proto; - flush_info->virtual_router = virtual_router; - flush_info->prefix_len = prefix_len; - if (addr) - memcpy(flush_info->addr, addr, sizeof(flush_info->addr)); - else - memset(flush_info->addr, 0, sizeof(flush_info->addr)); -} - -static void -mlxsw_sp_router_ll_xm_fib_entry_act_remote_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - enum mlxsw_reg_ralue_trap_action trap_action, - u16 trap_id, u32 adjacency_index, u16 ecmp_size) -{ - struct mlxsw_sp_fib_entry_op_ctx_xm *op_ctx_xm = (void *) op_ctx->ll_priv; - - mlxsw_reg_xmdr_c_ltr_act_remote_pack(op_ctx_xm->xmdr_pl, op_ctx_xm->trans_offset, - trap_action, trap_id, adjacency_index, ecmp_size); -} - -static void -mlxsw_sp_router_ll_xm_fib_entry_act_local_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - enum mlxsw_reg_ralue_trap_action trap_action, - u16 trap_id, u16 local_erif) -{ - struct mlxsw_sp_fib_entry_op_ctx_xm *op_ctx_xm = (void *) op_ctx->ll_priv; - - mlxsw_reg_xmdr_c_ltr_act_local_pack(op_ctx_xm->xmdr_pl, op_ctx_xm->trans_offset, - trap_action, trap_id, local_erif); -} - -static void -mlxsw_sp_router_ll_xm_fib_entry_act_ip2me_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx) -{ - struct mlxsw_sp_fib_entry_op_ctx_xm *op_ctx_xm = (void *) op_ctx->ll_priv; - - mlxsw_reg_xmdr_c_ltr_act_ip2me_pack(op_ctx_xm->xmdr_pl, op_ctx_xm->trans_offset); -} - -static void -mlxsw_sp_router_ll_xm_fib_entry_act_ip2me_tun_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - u32 tunnel_ptr) -{ - struct mlxsw_sp_fib_entry_op_ctx_xm *op_ctx_xm = (void *) op_ctx->ll_priv; - - mlxsw_reg_xmdr_c_ltr_act_ip2me_tun_pack(op_ctx_xm->xmdr_pl, op_ctx_xm->trans_offset, - tunnel_ptr); -} - -static struct mlxsw_sp_router_xm_ltable_node * -mlxsw_sp_router_xm_ltable_node_get(struct mlxsw_sp_router_xm *router_xm, u16 mindex) -{ - struct mlxsw_sp_router_xm_ltable_node *ltable_node; - int err; - - ltable_node = rhashtable_lookup_fast(&router_xm->ltable_ht, &mindex, - mlxsw_sp_router_xm_ltable_ht_params); - if (ltable_node) { - refcount_inc(<able_node->refcnt); - return ltable_node; - } - ltable_node = kzalloc(sizeof(*ltable_node), GFP_KERNEL); - if (!ltable_node) - return ERR_PTR(-ENOMEM); - ltable_node->mindex = mindex; - refcount_set(<able_node->refcnt, 1); - - err = rhashtable_insert_fast(&router_xm->ltable_ht, <able_node->ht_node, - mlxsw_sp_router_xm_ltable_ht_params); - if (err) - goto err_insert; - - return ltable_node; - -err_insert: - kfree(ltable_node); - return ERR_PTR(err); -} - -static void mlxsw_sp_router_xm_ltable_node_put(struct mlxsw_sp_router_xm *router_xm, - struct mlxsw_sp_router_xm_ltable_node *ltable_node) -{ - if (!refcount_dec_and_test(<able_node->refcnt)) - return; - rhashtable_remove_fast(&router_xm->ltable_ht, <able_node->ht_node, - mlxsw_sp_router_xm_ltable_ht_params); - kfree(ltable_node); -} - -static int mlxsw_sp_router_xm_ltable_lvalue_set(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_router_xm_ltable_node *ltable_node) -{ - char xrmt_pl[MLXSW_REG_XRMT_LEN]; - - mlxsw_reg_xrmt_pack(xrmt_pl, ltable_node->mindex, ltable_node->current_lvalue); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(xrmt), xrmt_pl); -} - -struct mlxsw_sp_router_xm_flush_node { - struct rhash_head ht_node; /* Member of router_xm->flush_ht */ - struct list_head list; - struct mlxsw_sp_router_xm_flush_info flush_info; - struct delayed_work dw; - struct mlxsw_sp *mlxsw_sp; - unsigned long start_jiffies; - unsigned int reuses; /* By how many flush calls this was reused. */ - refcount_t refcnt; -}; - -static const struct rhashtable_params mlxsw_sp_router_xm_flush_ht_params = { - .key_offset = offsetof(struct mlxsw_sp_router_xm_flush_node, flush_info), - .head_offset = offsetof(struct mlxsw_sp_router_xm_flush_node, ht_node), - .key_len = sizeof(struct mlxsw_sp_router_xm_flush_info), - .automatic_shrinking = true, -}; - -static struct mlxsw_sp_router_xm_flush_node * -mlxsw_sp_router_xm_cache_flush_node_create(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_router_xm_flush_info *flush_info) -{ - struct mlxsw_sp_router_xm *router_xm = mlxsw_sp->router->xm; - struct mlxsw_sp_router_xm_flush_node *flush_node; - int err; - - flush_node = kzalloc(sizeof(*flush_node), GFP_KERNEL); - if (!flush_node) - return ERR_PTR(-ENOMEM); - - flush_node->flush_info = *flush_info; - err = rhashtable_insert_fast(&router_xm->flush_ht, &flush_node->ht_node, - mlxsw_sp_router_xm_flush_ht_params); - if (err) { - kfree(flush_node); - return ERR_PTR(err); - } - router_xm->flush_count++; - flush_node->mlxsw_sp = mlxsw_sp; - flush_node->start_jiffies = jiffies; - refcount_set(&flush_node->refcnt, 1); - return flush_node; -} - -static void -mlxsw_sp_router_xm_cache_flush_node_hold(struct mlxsw_sp_router_xm_flush_node *flush_node) -{ - if (!flush_node) - return; - refcount_inc(&flush_node->refcnt); -} - -static void -mlxsw_sp_router_xm_cache_flush_node_put(struct mlxsw_sp_router_xm_flush_node *flush_node) -{ - if (!flush_node || !refcount_dec_and_test(&flush_node->refcnt)) - return; - kfree(flush_node); -} - -static void -mlxsw_sp_router_xm_cache_flush_node_destroy(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_router_xm_flush_node *flush_node) -{ - struct mlxsw_sp_router_xm *router_xm = mlxsw_sp->router->xm; - - router_xm->flush_count--; - rhashtable_remove_fast(&router_xm->flush_ht, &flush_node->ht_node, - mlxsw_sp_router_xm_flush_ht_params); - mlxsw_sp_router_xm_cache_flush_node_put(flush_node); -} - -static u32 mlxsw_sp_router_xm_flush_mask4(u8 prefix_len) -{ - return GENMASK(31, 32 - prefix_len); -} - -static unsigned char *mlxsw_sp_router_xm_flush_mask6(u8 prefix_len) -{ - static unsigned char mask[sizeof(struct in6_addr)]; - - memset(mask, 0, sizeof(mask)); - memset(mask, 0xff, prefix_len / 8); - mask[prefix_len / 8] = GENMASK(8, 8 - prefix_len % 8); - return mask; -} - -#define MLXSW_SP_ROUTER_XM_CACHE_PARALLEL_FLUSHES_LIMIT 15 -#define MLXSW_SP_ROUTER_XM_CACHE_FLUSH_ALL_MIN_REUSES 15 -#define MLXSW_SP_ROUTER_XM_CACHE_DELAY 50 /* usecs */ -#define MLXSW_SP_ROUTER_XM_CACHE_MAX_WAIT (MLXSW_SP_ROUTER_XM_CACHE_DELAY * 10) - -static void mlxsw_sp_router_xm_cache_flush_work(struct work_struct *work) -{ - struct mlxsw_sp_router_xm_flush_info *flush_info; - struct mlxsw_sp_router_xm_flush_node *flush_node; - char rlcmld_pl[MLXSW_REG_RLCMLD_LEN]; - enum mlxsw_reg_rlcmld_select select; - struct mlxsw_sp *mlxsw_sp; - u32 addr4; - int err; - - flush_node = container_of(work, struct mlxsw_sp_router_xm_flush_node, - dw.work); - mlxsw_sp = flush_node->mlxsw_sp; - flush_info = &flush_node->flush_info; - - if (flush_info->all) { - char rlpmce_pl[MLXSW_REG_RLPMCE_LEN]; - - mlxsw_reg_rlpmce_pack(rlpmce_pl, true, false); - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rlpmce), - rlpmce_pl); - if (err) - dev_err(mlxsw_sp->bus_info->dev, "Failed to flush XM cache\n"); - - if (flush_node->reuses < - MLXSW_SP_ROUTER_XM_CACHE_FLUSH_ALL_MIN_REUSES) - /* Leaving flush-all mode. */ - mlxsw_sp->router->xm->flush_all_mode = false; - goto out; - } - - select = MLXSW_REG_RLCMLD_SELECT_M_AND_ML_ENTRIES; - - switch (flush_info->proto) { - case MLXSW_SP_L3_PROTO_IPV4: - addr4 = *((u32 *) flush_info->addr); - addr4 &= mlxsw_sp_router_xm_flush_mask4(flush_info->prefix_len); - - /* In case the flush prefix length is bigger than M-value, - * it makes no sense to flush M entries. So just flush - * the ML entries. - */ - if (flush_info->prefix_len > MLXSW_SP_ROUTER_XM_M_VAL) - select = MLXSW_REG_RLCMLD_SELECT_ML_ENTRIES; - - mlxsw_reg_rlcmld_pack4(rlcmld_pl, select, - flush_info->virtual_router, addr4, - mlxsw_sp_router_xm_flush_mask4(flush_info->prefix_len)); - break; - case MLXSW_SP_L3_PROTO_IPV6: - mlxsw_reg_rlcmld_pack6(rlcmld_pl, select, - flush_info->virtual_router, flush_info->addr, - mlxsw_sp_router_xm_flush_mask6(flush_info->prefix_len)); - break; - default: - WARN_ON(true); - goto out; - } - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rlcmld), rlcmld_pl); - if (err) - dev_err(mlxsw_sp->bus_info->dev, "Failed to flush XM cache\n"); - -out: - mlxsw_sp_router_xm_cache_flush_node_destroy(mlxsw_sp, flush_node); -} - -static bool -mlxsw_sp_router_xm_cache_flush_may_cancel(struct mlxsw_sp_router_xm_flush_node *flush_node) -{ - unsigned long max_wait = usecs_to_jiffies(MLXSW_SP_ROUTER_XM_CACHE_MAX_WAIT); - unsigned long delay = usecs_to_jiffies(MLXSW_SP_ROUTER_XM_CACHE_DELAY); - - /* In case there is the same flushing work pending, check - * if we can consolidate with it. We can do it up to MAX_WAIT. - * Cancel the delayed work. If the work was still pending. - */ - if (time_is_before_jiffies(flush_node->start_jiffies + max_wait - delay) && - cancel_delayed_work_sync(&flush_node->dw)) - return true; - return false; -} - -static int -mlxsw_sp_router_xm_cache_flush_schedule(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_router_xm_flush_info *flush_info) -{ - unsigned long delay = usecs_to_jiffies(MLXSW_SP_ROUTER_XM_CACHE_DELAY); - struct mlxsw_sp_router_xm_flush_info flush_all_info = {.all = true}; - struct mlxsw_sp_router_xm *router_xm = mlxsw_sp->router->xm; - struct mlxsw_sp_router_xm_flush_node *flush_node; - - /* Check if the queued number of flushes reached critical amount after - * which it is better to just flush the whole cache. - */ - if (router_xm->flush_count == MLXSW_SP_ROUTER_XM_CACHE_PARALLEL_FLUSHES_LIMIT) - /* Entering flush-all mode. */ - router_xm->flush_all_mode = true; - - if (router_xm->flush_all_mode) - flush_info = &flush_all_info; - - rcu_read_lock(); - flush_node = rhashtable_lookup_fast(&router_xm->flush_ht, flush_info, - mlxsw_sp_router_xm_flush_ht_params); - /* Take a reference so the object is not freed before possible - * delayed work cancel could be done. - */ - mlxsw_sp_router_xm_cache_flush_node_hold(flush_node); - rcu_read_unlock(); - - if (flush_node && mlxsw_sp_router_xm_cache_flush_may_cancel(flush_node)) { - flush_node->reuses++; - mlxsw_sp_router_xm_cache_flush_node_put(flush_node); - /* Original work was within wait period and was canceled. - * That means that the reference is still held and the - * flush_node_put() call above did not free the flush_node. - * Reschedule it with fresh delay. - */ - goto schedule_work; - } else { - mlxsw_sp_router_xm_cache_flush_node_put(flush_node); - } - - flush_node = mlxsw_sp_router_xm_cache_flush_node_create(mlxsw_sp, flush_info); - if (IS_ERR(flush_node)) - return PTR_ERR(flush_node); - INIT_DELAYED_WORK(&flush_node->dw, mlxsw_sp_router_xm_cache_flush_work); - -schedule_work: - mlxsw_core_schedule_dw(&flush_node->dw, delay); - return 0; -} - -static int -mlxsw_sp_router_xm_ml_entry_add(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_router_xm_fib_entry *fib_entry) -{ - struct mlxsw_sp_router_xm *router_xm = mlxsw_sp->router->xm; - struct mlxsw_sp_router_xm_ltable_node *ltable_node; - u8 lvalue = fib_entry->lvalue; - int err; - - ltable_node = mlxsw_sp_router_xm_ltable_node_get(router_xm, - fib_entry->mindex); - if (IS_ERR(ltable_node)) - return PTR_ERR(ltable_node); - if (lvalue > ltable_node->current_lvalue) { - /* The L-value is bigger then the one currently set, update. */ - ltable_node->current_lvalue = lvalue; - err = mlxsw_sp_router_xm_ltable_lvalue_set(mlxsw_sp, - ltable_node); - if (err) - goto err_lvalue_set; - - /* The L value for prefix/M is increased. - * Therefore, all entries in M and ML caches matching - * {prefix/M, proto, VR} need to be flushed. Set the flush - * prefix length to M to achieve that. - */ - fib_entry->flush_info.prefix_len = MLXSW_SP_ROUTER_XM_M_VAL; - } - - ltable_node->lvalue_ref[lvalue]++; - fib_entry->ltable_node = ltable_node; - - return 0; - -err_lvalue_set: - mlxsw_sp_router_xm_ltable_node_put(router_xm, ltable_node); - return err; -} - -static void -mlxsw_sp_router_xm_ml_entry_del(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_router_xm_fib_entry *fib_entry) -{ - struct mlxsw_sp_router_xm_ltable_node *ltable_node = - fib_entry->ltable_node; - struct mlxsw_sp_router_xm *router_xm = mlxsw_sp->router->xm; - u8 lvalue = fib_entry->lvalue; - - ltable_node->lvalue_ref[lvalue]--; - if (lvalue == ltable_node->current_lvalue && lvalue && - !ltable_node->lvalue_ref[lvalue]) { - u8 new_lvalue = lvalue - 1; - - /* Find the biggest L-value left out there. */ - while (new_lvalue > 0 && !ltable_node->lvalue_ref[lvalue]) - new_lvalue--; - - ltable_node->current_lvalue = new_lvalue; - mlxsw_sp_router_xm_ltable_lvalue_set(mlxsw_sp, ltable_node); - - /* The L value for prefix/M is decreased. - * Therefore, all entries in M and ML caches matching - * {prefix/M, proto, VR} need to be flushed. Set the flush - * prefix length to M to achieve that. - */ - fib_entry->flush_info.prefix_len = MLXSW_SP_ROUTER_XM_M_VAL; - } - mlxsw_sp_router_xm_ltable_node_put(router_xm, ltable_node); -} - -static int -mlxsw_sp_router_xm_ml_entries_add(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx_xm *op_ctx_xm) -{ - struct mlxsw_sp_router_xm_fib_entry *fib_entry; - int err; - int i; - - for (i = 0; i < op_ctx_xm->entries_count; i++) { - fib_entry = op_ctx_xm->entries[i]; - err = mlxsw_sp_router_xm_ml_entry_add(mlxsw_sp, fib_entry); - if (err) - goto rollback; - } - return 0; - -rollback: - for (i--; i >= 0; i--) { - fib_entry = op_ctx_xm->entries[i]; - mlxsw_sp_router_xm_ml_entry_del(mlxsw_sp, fib_entry); - } - return err; -} - -static void -mlxsw_sp_router_xm_ml_entries_del(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx_xm *op_ctx_xm) -{ - struct mlxsw_sp_router_xm_fib_entry *fib_entry; - int i; - - for (i = 0; i < op_ctx_xm->entries_count; i++) { - fib_entry = op_ctx_xm->entries[i]; - mlxsw_sp_router_xm_ml_entry_del(mlxsw_sp, fib_entry); - } -} - -static void -mlxsw_sp_router_xm_ml_entries_cache_flush(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx_xm *op_ctx_xm) -{ - struct mlxsw_sp_router_xm_fib_entry *fib_entry; - int err; - int i; - - for (i = 0; i < op_ctx_xm->entries_count; i++) { - fib_entry = op_ctx_xm->entries[i]; - err = mlxsw_sp_router_xm_cache_flush_schedule(mlxsw_sp, - &fib_entry->flush_info); - if (err) - dev_err(mlxsw_sp->bus_info->dev, "Failed to flush XM cache\n"); - } -} - -static int mlxsw_sp_router_ll_xm_fib_entry_commit(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_fib_entry_op_ctx *op_ctx, - bool *postponed_for_bulk) -{ - struct mlxsw_sp_fib_entry_op_ctx_xm *op_ctx_xm = (void *) op_ctx->ll_priv; - struct mlxsw_sp_router_xm_fib_entry *fib_entry; - u8 num_rec; - int err; - int i; - - op_ctx_xm->trans_offset += op_ctx_xm->trans_item_len; - op_ctx_xm->entries_count++; - - /* Check if bulking is possible and there is still room for another - * FIB entry record. The size of 'trans_item_len' is either size of IPv4 - * command or size of IPv6 command. Not possible to mix those in a - * single XMDR write. - */ - if (op_ctx->bulk_ok && - op_ctx_xm->trans_offset + op_ctx_xm->trans_item_len <= MLXSW_REG_XMDR_TRANS_LEN) { - if (postponed_for_bulk) - *postponed_for_bulk = true; - return 0; - } - - if (op_ctx->event == FIB_EVENT_ENTRY_REPLACE) { - /* The L-table is updated inside. It has to be done before - * the prefix is inserted. - */ - err = mlxsw_sp_router_xm_ml_entries_add(mlxsw_sp, op_ctx_xm); - if (err) - goto out; - } - - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(xmdr), op_ctx_xm->xmdr_pl); - if (err) - goto out; - num_rec = mlxsw_reg_xmdr_num_rec_get(op_ctx_xm->xmdr_pl); - if (num_rec > op_ctx_xm->entries_count) { - dev_err(mlxsw_sp->bus_info->dev, "Invalid XMDR number of records\n"); - err = -EIO; - goto out; - } - for (i = 0; i < num_rec; i++) { - if (!mlxsw_reg_xmdr_reply_vect_get(op_ctx_xm->xmdr_pl, i)) { - dev_err(mlxsw_sp->bus_info->dev, "Command send over XMDR failed\n"); - err = -EIO; - goto out; - } else { - fib_entry = op_ctx_xm->entries[i]; - fib_entry->committed = true; - } - } - - if (op_ctx->event == FIB_EVENT_ENTRY_DEL) - /* The L-table is updated inside. It has to be done after - * the prefix was removed. - */ - mlxsw_sp_router_xm_ml_entries_del(mlxsw_sp, op_ctx_xm); - - /* At the very end, do the XLT cache flushing to evict stale - * M and ML cache entries after prefixes were inserted/removed. - */ - mlxsw_sp_router_xm_ml_entries_cache_flush(mlxsw_sp, op_ctx_xm); - -out: - /* Next pack call is going to do reinitialization */ - op_ctx->initialized = false; - return err; -} - -static bool mlxsw_sp_router_ll_xm_fib_entry_is_committed(struct mlxsw_sp_fib_entry_priv *priv) -{ - struct mlxsw_sp_router_xm_fib_entry *fib_entry = (void *) priv->priv; - - return fib_entry->committed; -} - -const struct mlxsw_sp_router_ll_ops mlxsw_sp_router_ll_xm_ops = { - .init = mlxsw_sp_router_ll_xm_init, - .ralta_write = mlxsw_sp_router_ll_xm_ralta_write, - .ralst_write = mlxsw_sp_router_ll_xm_ralst_write, - .raltb_write = mlxsw_sp_router_ll_xm_raltb_write, - .fib_entry_op_ctx_size = sizeof(struct mlxsw_sp_fib_entry_op_ctx_xm), - .fib_entry_priv_size = sizeof(struct mlxsw_sp_router_xm_fib_entry), - .fib_entry_pack = mlxsw_sp_router_ll_xm_fib_entry_pack, - .fib_entry_act_remote_pack = mlxsw_sp_router_ll_xm_fib_entry_act_remote_pack, - .fib_entry_act_local_pack = mlxsw_sp_router_ll_xm_fib_entry_act_local_pack, - .fib_entry_act_ip2me_pack = mlxsw_sp_router_ll_xm_fib_entry_act_ip2me_pack, - .fib_entry_act_ip2me_tun_pack = mlxsw_sp_router_ll_xm_fib_entry_act_ip2me_tun_pack, - .fib_entry_commit = mlxsw_sp_router_ll_xm_fib_entry_commit, - .fib_entry_is_committed = mlxsw_sp_router_ll_xm_fib_entry_is_committed, -}; - -#define MLXSW_SP_ROUTER_XM_MINDEX_SIZE (64 * 1024) - -int mlxsw_sp_router_xm_init(struct mlxsw_sp *mlxsw_sp) -{ - struct mlxsw_sp_router_xm *router_xm; - char rxltm_pl[MLXSW_REG_RXLTM_LEN]; - char xltq_pl[MLXSW_REG_XLTQ_LEN]; - u32 mindex_size; - u16 device_id; - int err; - - if (!mlxsw_sp->bus_info->xm_exists) - return 0; - - router_xm = kzalloc(sizeof(*router_xm), GFP_KERNEL); - if (!router_xm) - return -ENOMEM; - - mlxsw_reg_xltq_pack(xltq_pl); - err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(xltq), xltq_pl); - if (err) - goto err_xltq_query; - mlxsw_reg_xltq_unpack(xltq_pl, &device_id, &router_xm->ipv4_supported, - &router_xm->ipv6_supported, &router_xm->entries_size, &mindex_size); - - if (device_id != MLXSW_REG_XLTQ_XM_DEVICE_ID_XLT) { - dev_err(mlxsw_sp->bus_info->dev, "Invalid XM device id\n"); - err = -EINVAL; - goto err_device_id_check; - } - - if (mindex_size != MLXSW_SP_ROUTER_XM_MINDEX_SIZE) { - dev_err(mlxsw_sp->bus_info->dev, "Unexpected M-index size\n"); - err = -EINVAL; - goto err_mindex_size_check; - } - - mlxsw_reg_rxltm_pack(rxltm_pl, mlxsw_sp_router_xm_m_val[MLXSW_SP_L3_PROTO_IPV4], - mlxsw_sp_router_xm_m_val[MLXSW_SP_L3_PROTO_IPV6]); - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rxltm), rxltm_pl); - if (err) - goto err_rxltm_write; - - err = rhashtable_init(&router_xm->ltable_ht, &mlxsw_sp_router_xm_ltable_ht_params); - if (err) - goto err_ltable_ht_init; - - err = rhashtable_init(&router_xm->flush_ht, &mlxsw_sp_router_xm_flush_ht_params); - if (err) - goto err_flush_ht_init; - - mlxsw_sp->router->xm = router_xm; - return 0; - -err_flush_ht_init: - rhashtable_destroy(&router_xm->ltable_ht); -err_ltable_ht_init: -err_rxltm_write: -err_mindex_size_check: -err_device_id_check: -err_xltq_query: - kfree(router_xm); - return err; -} - -void mlxsw_sp_router_xm_fini(struct mlxsw_sp *mlxsw_sp) -{ - struct mlxsw_sp_router_xm *router_xm = mlxsw_sp->router->xm; - - if (!mlxsw_sp->bus_info->xm_exists) - return; - - rhashtable_destroy(&router_xm->flush_ht); - rhashtable_destroy(&router_xm->ltable_ht); - kfree(router_xm); -} - -bool mlxsw_sp_router_xm_ipv4_is_supported(const struct mlxsw_sp *mlxsw_sp) -{ - struct mlxsw_sp_router_xm *router_xm = mlxsw_sp->router->xm; - - return router_xm && router_xm->ipv4_supported; -} |