Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'mlxsw-next'

Ido Schimmel says:

====================
mlxsw: Various updates

This patchset contains various updates to the mlxsw driver and related
selftests.

Patches #1-#5 contain various updates to mlxsw selftests. The most
significant change is the conversion of the DCB selftests to use the new
iproute2 DCB support.

Patches #6-#9 contain mostly trivial changes to the driver itself. No
user facing changes.

Patches #10-#11 remove support for SwitchX-2 and SwitchIB ASICs that did
not see any updates in the last 4-5 years and will not see any in the
future. See individual commit messages for detailed explanation as to
why it is OK to remove these drivers from the kernel.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+83 -2402
-22
drivers/net/ethernet/mellanox/mlxsw/Kconfig
··· 49 49 To compile this driver as a module, choose M here: the 50 50 module will be called mlxsw_i2c. 51 51 52 - config MLXSW_SWITCHIB 53 - tristate "Mellanox Technologies SwitchIB and SwitchIB-2 support" 54 - depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV 55 - default m 56 - help 57 - This driver supports Mellanox Technologies SwitchIB and SwitchIB-2 58 - Infiniband Switch ASICs. 59 - 60 - To compile this driver as a module, choose M here: the 61 - module will be called mlxsw_switchib. 62 - 63 - config MLXSW_SWITCHX2 64 - tristate "Mellanox Technologies SwitchX-2 support" 65 - depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV 66 - default m 67 - help 68 - This driver supports Mellanox Technologies SwitchX-2 Ethernet 69 - Switch ASICs. 70 - 71 - To compile this driver as a module, choose M here: the 72 - module will be called mlxsw_switchx2. 73 - 74 52 config MLXSW_SPECTRUM 75 53 tristate "Mellanox Technologies Spectrum family support" 76 54 depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV && VLAN_8021Q
-4
drivers/net/ethernet/mellanox/mlxsw/Makefile
··· 8 8 mlxsw_pci-objs := pci.o 9 9 obj-$(CONFIG_MLXSW_I2C) += mlxsw_i2c.o 10 10 mlxsw_i2c-objs := i2c.o 11 - obj-$(CONFIG_MLXSW_SWITCHIB) += mlxsw_switchib.o 12 - mlxsw_switchib-objs := switchib.o 13 - obj-$(CONFIG_MLXSW_SWITCHX2) += mlxsw_switchx2.o 14 - mlxsw_switchx2-objs := switchx2.o 15 11 obj-$(CONFIG_MLXSW_SPECTRUM) += mlxsw_spectrum.o 16 12 mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \ 17 13 spectrum_switchdev.o spectrum_router.o \
+1 -1
drivers/net/ethernet/mellanox/mlxsw/core.c
··· 630 630 struct sk_buff *skb; 631 631 int err; 632 632 633 - skb = skb_copy(trans->tx_skb, GFP_KERNEL); 633 + skb = skb_clone(trans->tx_skb, GFP_KERNEL); 634 634 if (!skb) 635 635 return -ENOMEM; 636 636
-9
drivers/net/ethernet/mellanox/mlxsw/ib.h
··· 1 - /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ 2 - /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */ 3 - 4 - #ifndef _MLXSW_IB_H 5 - #define _MLXSW_IB_H 6 - 7 - #define MLXSW_IB_DEFAULT_MTU 4096 8 - 9 - #endif /* _MLXSW_IB_H */
+4
drivers/net/ethernet/mellanox/mlxsw/minimal.c
··· 234 234 static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u8 local_port, 235 235 u8 *last_module) 236 236 { 237 + unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core); 237 238 u8 module, width; 238 239 int err; 239 240 ··· 250 249 if (module == *last_module) 251 250 return 0; 252 251 *last_module = module; 252 + 253 + if (WARN_ON_ONCE(module >= max_ports)) 254 + return -EINVAL; 253 255 mlxsw_m->module_to_port[module] = ++mlxsw_m->max_ports; 254 256 255 257 return 0;
-5
drivers/net/ethernet/mellanox/mlxsw/pci.c
··· 1426 1426 unsigned long end; 1427 1427 u32 val; 1428 1428 1429 - if (id->device == PCI_DEVICE_ID_MELLANOX_SWITCHX2) { 1430 - msleep(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS); 1431 - return 0; 1432 - } 1433 - 1434 1429 /* We must wait for the HW to become responsive. */ 1435 1430 msleep(MLXSW_PCI_SW_RESET_WAIT_MSECS); 1436 1431
-3
drivers/net/ethernet/mellanox/mlxsw/pci.h
··· 6 6 7 7 #include <linux/pci.h> 8 8 9 - #define PCI_DEVICE_ID_MELLANOX_SWITCHX2 0xc738 10 9 #define PCI_DEVICE_ID_MELLANOX_SPECTRUM 0xcb84 11 10 #define PCI_DEVICE_ID_MELLANOX_SPECTRUM2 0xcf6c 12 11 #define PCI_DEVICE_ID_MELLANOX_SPECTRUM3 0xcf70 13 - #define PCI_DEVICE_ID_MELLANOX_SWITCHIB 0xcb20 14 - #define PCI_DEVICE_ID_MELLANOX_SWITCHIB2 0xcf08 15 12 16 13 #if IS_ENABLED(CONFIG_MLXSW_PCI) 17 14
+5
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
··· 2125 2125 struct mlxsw_sp *mlxsw_sp = priv; 2126 2126 struct mlxsw_sp_port *mlxsw_sp_port; 2127 2127 enum mlxsw_reg_pude_oper_status status; 2128 + unsigned int max_ports; 2128 2129 u8 local_port; 2129 2130 2131 + max_ports = mlxsw_core_max_ports(mlxsw_sp->core); 2130 2132 local_port = mlxsw_reg_pude_local_port_get(pude_pl); 2133 + 2134 + if (WARN_ON_ONCE(local_port >= max_ports)) 2135 + return; 2131 2136 mlxsw_sp_port = mlxsw_sp->ports[local_port]; 2132 2137 if (!mlxsw_sp_port) 2133 2138 return;
+3 -3
drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
··· 364 364 365 365 static u32 mlxsw_sp_hdroom_int_buf_size_get(struct mlxsw_sp *mlxsw_sp, int mtu, u32 speed) 366 366 { 367 - u32 buffsize = mlxsw_sp->sb_ops->int_buf_size_get(speed, mtu); 367 + u32 buffsize = mlxsw_sp->sb_ops->int_buf_size_get(mtu, speed); 368 368 369 369 return mlxsw_sp_bytes_cells(mlxsw_sp, buffsize) + 1; 370 370 } ··· 388 388 int i; 389 389 390 390 /* Internal buffer. */ 391 - reserve_cells = mlxsw_sp_hdroom_int_buf_size_get(mlxsw_sp, mlxsw_sp_port->max_speed, 392 - mlxsw_sp_port->max_mtu); 391 + reserve_cells = mlxsw_sp_hdroom_int_buf_size_get(mlxsw_sp, mlxsw_sp_port->max_mtu, 392 + mlxsw_sp_port->max_speed); 393 393 reserve_cells = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, reserve_cells); 394 394 hdroom->int_buf.reserve_cells = reserve_cells; 395 395
+3
drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
··· 568 568 u8 domain_number, u16 sequence_id, 569 569 u64 timestamp) 570 570 { 571 + unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core); 571 572 struct mlxsw_sp_port *mlxsw_sp_port; 572 573 struct mlxsw_sp1_ptp_key key; 573 574 u8 types; 574 575 576 + if (WARN_ON_ONCE(local_port >= max_ports)) 577 + return; 575 578 mlxsw_sp_port = mlxsw_sp->ports[local_port]; 576 579 if (!mlxsw_sp_port) 577 580 return;
+7 -2
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
··· 2282 2282 char *rauhtd_pl, 2283 2283 int ent_index) 2284 2284 { 2285 + u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); 2285 2286 struct net_device *dev; 2286 2287 struct neighbour *n; 2287 2288 __be32 dipn; ··· 2291 2290 2292 2291 mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl, ent_index, &rif, &dip); 2293 2292 2293 + if (WARN_ON_ONCE(rif >= max_rifs)) 2294 + return; 2294 2295 if (!mlxsw_sp->router->rifs[rif]) { 2295 2296 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n"); 2296 2297 return; ··· 3844 3841 bool offload_change = false; 3845 3842 u32 adj_index; 3846 3843 bool old_adj_index_valid; 3847 - int i, err2, err = 0; 3848 3844 u32 old_adj_index; 3845 + int i, err2, err; 3849 3846 3850 3847 if (!nhgi->gateway) 3851 3848 return mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp); ··· 3875 3872 return 0; 3876 3873 } 3877 3874 mlxsw_sp_nexthop_group_normalize(nhgi); 3878 - if (!nhgi->sum_norm_weight) 3875 + if (!nhgi->sum_norm_weight) { 3879 3876 /* No neigh of this group is connected so we just set 3880 3877 * the trap and let everthing flow through kernel. 3881 3878 */ 3879 + err = 0; 3882 3880 goto set_trap; 3881 + } 3883 3882 3884 3883 ecmp_size = nhgi->sum_norm_weight; 3885 3884 err = mlxsw_sp_fix_adj_grp_size(mlxsw_sp, &ecmp_size);
+4
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
··· 2520 2520 char *sfn_pl, int rec_index, 2521 2521 bool adding) 2522 2522 { 2523 + unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core); 2523 2524 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 2524 2525 struct mlxsw_sp_bridge_device *bridge_device; 2525 2526 struct mlxsw_sp_bridge_port *bridge_port; ··· 2533 2532 int err; 2534 2533 2535 2534 mlxsw_reg_sfn_mac_unpack(sfn_pl, rec_index, mac, &fid, &local_port); 2535 + 2536 + if (WARN_ON_ONCE(local_port >= max_ports)) 2537 + return; 2536 2538 mlxsw_sp_port = mlxsw_sp->ports[local_port]; 2537 2539 if (!mlxsw_sp_port) { 2538 2540 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect local port in FDB notification\n");
-595
drivers/net/ethernet/mellanox/mlxsw/switchib.c
··· 1 - // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 - /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */ 3 - 4 - #include <linux/kernel.h> 5 - #include <linux/module.h> 6 - #include <linux/types.h> 7 - #include <linux/pci.h> 8 - #include <linux/netdevice.h> 9 - #include <linux/etherdevice.h> 10 - #include <linux/slab.h> 11 - #include <linux/device.h> 12 - #include <linux/skbuff.h> 13 - #include <linux/if_vlan.h> 14 - #include <net/switchdev.h> 15 - 16 - #include "pci.h" 17 - #include "core.h" 18 - #include "reg.h" 19 - #include "port.h" 20 - #include "trap.h" 21 - #include "txheader.h" 22 - #include "ib.h" 23 - 24 - static const char mlxsw_sib_driver_name[] = "mlxsw_switchib"; 25 - static const char mlxsw_sib2_driver_name[] = "mlxsw_switchib2"; 26 - 27 - struct mlxsw_sib_port; 28 - 29 - struct mlxsw_sib { 30 - struct mlxsw_sib_port **ports; 31 - struct mlxsw_core *core; 32 - const struct mlxsw_bus_info *bus_info; 33 - u8 hw_id[ETH_ALEN]; 34 - }; 35 - 36 - struct mlxsw_sib_port { 37 - struct mlxsw_sib *mlxsw_sib; 38 - u8 local_port; 39 - struct { 40 - u8 module; 41 - } mapping; 42 - }; 43 - 44 - /* tx_v1_hdr_version 45 - * Tx header version. 46 - * Must be set to 1. 47 - */ 48 - MLXSW_ITEM32(tx_v1, hdr, version, 0x00, 28, 4); 49 - 50 - /* tx_v1_hdr_ctl 51 - * Packet control type. 52 - * 0 - Ethernet control (e.g. EMADs, LACP) 53 - * 1 - Ethernet data 54 - */ 55 - MLXSW_ITEM32(tx_v1, hdr, ctl, 0x00, 26, 2); 56 - 57 - /* tx_v1_hdr_proto 58 - * Packet protocol type. Must be set to 1 (Ethernet). 59 - */ 60 - MLXSW_ITEM32(tx_v1, hdr, proto, 0x00, 21, 3); 61 - 62 - /* tx_v1_hdr_swid 63 - * Switch partition ID. Must be set to 0. 64 - */ 65 - MLXSW_ITEM32(tx_v1, hdr, swid, 0x00, 12, 3); 66 - 67 - /* tx_v1_hdr_control_tclass 68 - * Indicates if the packet should use the control TClass and not one 69 - * of the data TClasses. 70 - */ 71 - MLXSW_ITEM32(tx_v1, hdr, control_tclass, 0x00, 6, 1); 72 - 73 - /* tx_v1_hdr_port_mid 74 - * Destination local port for unicast packets. 75 - * Destination multicast ID for multicast packets. 76 - * 77 - * Control packets are directed to a specific egress port, while data 78 - * packets are transmitted through the CPU port (0) into the switch partition, 79 - * where forwarding rules are applied. 80 - */ 81 - MLXSW_ITEM32(tx_v1, hdr, port_mid, 0x04, 16, 16); 82 - 83 - /* tx_v1_hdr_type 84 - * 0 - Data packets 85 - * 6 - Control packets 86 - */ 87 - MLXSW_ITEM32(tx_v1, hdr, type, 0x0C, 0, 4); 88 - 89 - static void 90 - mlxsw_sib_tx_v1_hdr_construct(struct sk_buff *skb, 91 - const struct mlxsw_tx_info *tx_info) 92 - { 93 - char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN); 94 - 95 - memset(txhdr, 0, MLXSW_TXHDR_LEN); 96 - 97 - mlxsw_tx_v1_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_1); 98 - mlxsw_tx_v1_hdr_ctl_set(txhdr, MLXSW_TXHDR_ETH_CTL); 99 - mlxsw_tx_v1_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH); 100 - mlxsw_tx_v1_hdr_swid_set(txhdr, 0); 101 - mlxsw_tx_v1_hdr_control_tclass_set(txhdr, 1); 102 - mlxsw_tx_v1_hdr_port_mid_set(txhdr, tx_info->local_port); 103 - mlxsw_tx_v1_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL); 104 - } 105 - 106 - static int mlxsw_sib_hw_id_get(struct mlxsw_sib *mlxsw_sib) 107 - { 108 - char spad_pl[MLXSW_REG_SPAD_LEN] = {0}; 109 - int err; 110 - 111 - err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(spad), spad_pl); 112 - if (err) 113 - return err; 114 - mlxsw_reg_spad_base_mac_memcpy_from(spad_pl, mlxsw_sib->hw_id); 115 - return 0; 116 - } 117 - 118 - static int 119 - mlxsw_sib_port_admin_status_set(struct mlxsw_sib_port *mlxsw_sib_port, 120 - bool is_up) 121 - { 122 - struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; 123 - char paos_pl[MLXSW_REG_PAOS_LEN]; 124 - 125 - mlxsw_reg_paos_pack(paos_pl, mlxsw_sib_port->local_port, 126 - is_up ? MLXSW_PORT_ADMIN_STATUS_UP : 127 - MLXSW_PORT_ADMIN_STATUS_DOWN); 128 - return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(paos), paos_pl); 129 - } 130 - 131 - static int mlxsw_sib_port_mtu_set(struct mlxsw_sib_port *mlxsw_sib_port, 132 - u16 mtu) 133 - { 134 - struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; 135 - char pmtu_pl[MLXSW_REG_PMTU_LEN]; 136 - int max_mtu; 137 - int err; 138 - 139 - mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sib_port->local_port, 0); 140 - err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(pmtu), pmtu_pl); 141 - if (err) 142 - return err; 143 - max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl); 144 - 145 - if (mtu > max_mtu) 146 - return -EINVAL; 147 - 148 - mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sib_port->local_port, mtu); 149 - return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(pmtu), pmtu_pl); 150 - } 151 - 152 - static int mlxsw_sib_port_set(struct mlxsw_sib_port *mlxsw_sib_port, u8 port) 153 - { 154 - struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; 155 - char plib_pl[MLXSW_REG_PLIB_LEN] = {0}; 156 - int err; 157 - 158 - mlxsw_reg_plib_local_port_set(plib_pl, mlxsw_sib_port->local_port); 159 - mlxsw_reg_plib_ib_port_set(plib_pl, port); 160 - err = mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(plib), plib_pl); 161 - return err; 162 - } 163 - 164 - static int mlxsw_sib_port_swid_set(struct mlxsw_sib_port *mlxsw_sib_port, 165 - u8 swid) 166 - { 167 - struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; 168 - char pspa_pl[MLXSW_REG_PSPA_LEN]; 169 - 170 - mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sib_port->local_port); 171 - return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(pspa), pspa_pl); 172 - } 173 - 174 - static int mlxsw_sib_port_module_info_get(struct mlxsw_sib *mlxsw_sib, 175 - u8 local_port, u8 *p_module, 176 - u8 *p_width) 177 - { 178 - char pmlp_pl[MLXSW_REG_PMLP_LEN]; 179 - int err; 180 - 181 - mlxsw_reg_pmlp_pack(pmlp_pl, local_port); 182 - err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(pmlp), pmlp_pl); 183 - if (err) 184 - return err; 185 - *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0); 186 - *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl); 187 - return 0; 188 - } 189 - 190 - static int mlxsw_sib_port_speed_set(struct mlxsw_sib_port *mlxsw_sib_port, 191 - u16 speed, u16 width) 192 - { 193 - struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib; 194 - char ptys_pl[MLXSW_REG_PTYS_LEN]; 195 - 196 - mlxsw_reg_ptys_ib_pack(ptys_pl, mlxsw_sib_port->local_port, speed, 197 - width); 198 - return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(ptys), ptys_pl); 199 - } 200 - 201 - static bool mlxsw_sib_port_created(struct mlxsw_sib *mlxsw_sib, u8 local_port) 202 - { 203 - return mlxsw_sib->ports[local_port] != NULL; 204 - } 205 - 206 - static int __mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port, 207 - u8 module, u8 width) 208 - { 209 - struct mlxsw_sib_port *mlxsw_sib_port; 210 - int err; 211 - 212 - mlxsw_sib_port = kzalloc(sizeof(*mlxsw_sib_port), GFP_KERNEL); 213 - if (!mlxsw_sib_port) 214 - return -ENOMEM; 215 - mlxsw_sib_port->mlxsw_sib = mlxsw_sib; 216 - mlxsw_sib_port->local_port = local_port; 217 - mlxsw_sib_port->mapping.module = module; 218 - 219 - err = mlxsw_sib_port_swid_set(mlxsw_sib_port, 0); 220 - if (err) { 221 - dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set SWID\n", 222 - mlxsw_sib_port->local_port); 223 - goto err_port_swid_set; 224 - } 225 - 226 - /* Expose the IB port number as it's front panel name */ 227 - err = mlxsw_sib_port_set(mlxsw_sib_port, module + 1); 228 - if (err) { 229 - dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set IB port\n", 230 - mlxsw_sib_port->local_port); 231 - goto err_port_ib_set; 232 - } 233 - 234 - /* Supports all speeds from SDR to FDR (bitmask) and support bus width 235 - * of 1x, 2x and 4x (3 bits bitmask) 236 - */ 237 - err = mlxsw_sib_port_speed_set(mlxsw_sib_port, 238 - MLXSW_REG_PTYS_IB_SPEED_EDR - 1, 239 - BIT(3) - 1); 240 - if (err) { 241 - dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set speed\n", 242 - mlxsw_sib_port->local_port); 243 - goto err_port_speed_set; 244 - } 245 - 246 - /* Change to the maximum MTU the device supports, the SMA will take 247 - * care of the active MTU 248 - */ 249 - err = mlxsw_sib_port_mtu_set(mlxsw_sib_port, MLXSW_IB_DEFAULT_MTU); 250 - if (err) { 251 - dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set MTU\n", 252 - mlxsw_sib_port->local_port); 253 - goto err_port_mtu_set; 254 - } 255 - 256 - err = mlxsw_sib_port_admin_status_set(mlxsw_sib_port, true); 257 - if (err) { 258 - dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to change admin state to UP\n", 259 - mlxsw_sib_port->local_port); 260 - goto err_port_admin_set; 261 - } 262 - 263 - mlxsw_core_port_ib_set(mlxsw_sib->core, mlxsw_sib_port->local_port, 264 - mlxsw_sib_port); 265 - mlxsw_sib->ports[local_port] = mlxsw_sib_port; 266 - return 0; 267 - 268 - err_port_admin_set: 269 - err_port_mtu_set: 270 - err_port_speed_set: 271 - err_port_ib_set: 272 - mlxsw_sib_port_swid_set(mlxsw_sib_port, MLXSW_PORT_SWID_DISABLED_PORT); 273 - err_port_swid_set: 274 - kfree(mlxsw_sib_port); 275 - return err; 276 - } 277 - 278 - static int mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port, 279 - u8 module, u8 width) 280 - { 281 - int err; 282 - 283 - err = mlxsw_core_port_init(mlxsw_sib->core, local_port, 284 - module + 1, false, 0, false, 0, 285 - mlxsw_sib->hw_id, sizeof(mlxsw_sib->hw_id)); 286 - if (err) { 287 - dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to init core port\n", 288 - local_port); 289 - return err; 290 - } 291 - err = __mlxsw_sib_port_create(mlxsw_sib, local_port, module, width); 292 - if (err) 293 - goto err_port_create; 294 - 295 - return 0; 296 - 297 - err_port_create: 298 - mlxsw_core_port_fini(mlxsw_sib->core, local_port); 299 - return err; 300 - } 301 - 302 - static void __mlxsw_sib_port_remove(struct mlxsw_sib *mlxsw_sib, u8 local_port) 303 - { 304 - struct mlxsw_sib_port *mlxsw_sib_port = mlxsw_sib->ports[local_port]; 305 - 306 - mlxsw_core_port_clear(mlxsw_sib->core, local_port, mlxsw_sib); 307 - mlxsw_sib->ports[local_port] = NULL; 308 - mlxsw_sib_port_admin_status_set(mlxsw_sib_port, false); 309 - mlxsw_sib_port_swid_set(mlxsw_sib_port, MLXSW_PORT_SWID_DISABLED_PORT); 310 - kfree(mlxsw_sib_port); 311 - } 312 - 313 - static void mlxsw_sib_port_remove(struct mlxsw_sib *mlxsw_sib, u8 local_port) 314 - { 315 - __mlxsw_sib_port_remove(mlxsw_sib, local_port); 316 - mlxsw_core_port_fini(mlxsw_sib->core, local_port); 317 - } 318 - 319 - static void mlxsw_sib_ports_remove(struct mlxsw_sib *mlxsw_sib) 320 - { 321 - int i; 322 - 323 - for (i = 1; i < MLXSW_PORT_MAX_IB_PORTS; i++) 324 - if (mlxsw_sib_port_created(mlxsw_sib, i)) 325 - mlxsw_sib_port_remove(mlxsw_sib, i); 326 - kfree(mlxsw_sib->ports); 327 - } 328 - 329 - static int mlxsw_sib_ports_create(struct mlxsw_sib *mlxsw_sib) 330 - { 331 - size_t alloc_size; 332 - u8 module, width; 333 - int i; 334 - int err; 335 - 336 - alloc_size = sizeof(struct mlxsw_sib_port *) * MLXSW_PORT_MAX_IB_PORTS; 337 - mlxsw_sib->ports = kzalloc(alloc_size, GFP_KERNEL); 338 - if (!mlxsw_sib->ports) 339 - return -ENOMEM; 340 - 341 - for (i = 1; i < MLXSW_PORT_MAX_IB_PORTS; i++) { 342 - err = mlxsw_sib_port_module_info_get(mlxsw_sib, i, &module, 343 - &width); 344 - if (err) 345 - goto err_port_module_info_get; 346 - if (!width) 347 - continue; 348 - err = mlxsw_sib_port_create(mlxsw_sib, i, module, width); 349 - if (err) 350 - goto err_port_create; 351 - } 352 - return 0; 353 - 354 - err_port_create: 355 - err_port_module_info_get: 356 - for (i--; i >= 1; i--) 357 - if (mlxsw_sib_port_created(mlxsw_sib, i)) 358 - mlxsw_sib_port_remove(mlxsw_sib, i); 359 - kfree(mlxsw_sib->ports); 360 - return err; 361 - } 362 - 363 - static void 364 - mlxsw_sib_pude_ib_event_func(struct mlxsw_sib_port *mlxsw_sib_port, 365 - enum mlxsw_reg_pude_oper_status status) 366 - { 367 - if (status == MLXSW_PORT_OPER_STATUS_UP) 368 - pr_info("ib link for port %d - up\n", 369 - mlxsw_sib_port->mapping.module + 1); 370 - else 371 - pr_info("ib link for port %d - down\n", 372 - mlxsw_sib_port->mapping.module + 1); 373 - } 374 - 375 - static void mlxsw_sib_pude_event_func(const struct mlxsw_reg_info *reg, 376 - char *pude_pl, void *priv) 377 - { 378 - struct mlxsw_sib *mlxsw_sib = priv; 379 - struct mlxsw_sib_port *mlxsw_sib_port; 380 - enum mlxsw_reg_pude_oper_status status; 381 - u8 local_port; 382 - 383 - local_port = mlxsw_reg_pude_local_port_get(pude_pl); 384 - mlxsw_sib_port = mlxsw_sib->ports[local_port]; 385 - if (!mlxsw_sib_port) { 386 - dev_warn(mlxsw_sib->bus_info->dev, "Port %d: Link event received for non-existent port\n", 387 - local_port); 388 - return; 389 - } 390 - 391 - status = mlxsw_reg_pude_oper_status_get(pude_pl); 392 - mlxsw_sib_pude_ib_event_func(mlxsw_sib_port, status); 393 - } 394 - 395 - static const struct mlxsw_listener mlxsw_sib_listener[] = { 396 - MLXSW_EVENTL(mlxsw_sib_pude_event_func, PUDE, EMAD), 397 - }; 398 - 399 - static int mlxsw_sib_taps_init(struct mlxsw_sib *mlxsw_sib) 400 - { 401 - int i; 402 - int err; 403 - 404 - for (i = 0; i < ARRAY_SIZE(mlxsw_sib_listener); i++) { 405 - err = mlxsw_core_trap_register(mlxsw_sib->core, 406 - &mlxsw_sib_listener[i], 407 - mlxsw_sib); 408 - if (err) 409 - goto err_rx_listener_register; 410 - } 411 - 412 - return 0; 413 - 414 - err_rx_listener_register: 415 - for (i--; i >= 0; i--) { 416 - mlxsw_core_trap_unregister(mlxsw_sib->core, 417 - &mlxsw_sib_listener[i], 418 - mlxsw_sib); 419 - } 420 - 421 - return err; 422 - } 423 - 424 - static void mlxsw_sib_traps_fini(struct mlxsw_sib *mlxsw_sib) 425 - { 426 - int i; 427 - 428 - for (i = 0; i < ARRAY_SIZE(mlxsw_sib_listener); i++) { 429 - mlxsw_core_trap_unregister(mlxsw_sib->core, 430 - &mlxsw_sib_listener[i], mlxsw_sib); 431 - } 432 - } 433 - 434 - static int mlxsw_sib_basic_trap_groups_set(struct mlxsw_core *mlxsw_core) 435 - { 436 - char htgt_pl[MLXSW_REG_HTGT_LEN]; 437 - 438 - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD, 439 - MLXSW_REG_HTGT_INVALID_POLICER, 440 - MLXSW_REG_HTGT_DEFAULT_PRIORITY, 441 - MLXSW_REG_HTGT_DEFAULT_TC); 442 - mlxsw_reg_htgt_swid_set(htgt_pl, MLXSW_PORT_SWID_ALL_SWIDS); 443 - mlxsw_reg_htgt_local_path_rdq_set(htgt_pl, 444 - MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SIB_EMAD); 445 - return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); 446 - } 447 - 448 - static int mlxsw_sib_init(struct mlxsw_core *mlxsw_core, 449 - const struct mlxsw_bus_info *mlxsw_bus_info, 450 - struct netlink_ext_ack *extack) 451 - { 452 - struct mlxsw_sib *mlxsw_sib = mlxsw_core_driver_priv(mlxsw_core); 453 - int err; 454 - 455 - mlxsw_sib->core = mlxsw_core; 456 - mlxsw_sib->bus_info = mlxsw_bus_info; 457 - 458 - err = mlxsw_sib_hw_id_get(mlxsw_sib); 459 - if (err) { 460 - dev_err(mlxsw_sib->bus_info->dev, "Failed to get switch HW ID\n"); 461 - return err; 462 - } 463 - 464 - err = mlxsw_sib_ports_create(mlxsw_sib); 465 - if (err) { 466 - dev_err(mlxsw_sib->bus_info->dev, "Failed to create ports\n"); 467 - return err; 468 - } 469 - 470 - err = mlxsw_sib_taps_init(mlxsw_sib); 471 - if (err) { 472 - dev_err(mlxsw_sib->bus_info->dev, "Failed to set traps\n"); 473 - goto err_traps_init_err; 474 - } 475 - 476 - return 0; 477 - 478 - err_traps_init_err: 479 - mlxsw_sib_ports_remove(mlxsw_sib); 480 - return err; 481 - } 482 - 483 - static void mlxsw_sib_fini(struct mlxsw_core *mlxsw_core) 484 - { 485 - struct mlxsw_sib *mlxsw_sib = mlxsw_core_driver_priv(mlxsw_core); 486 - 487 - mlxsw_sib_traps_fini(mlxsw_sib); 488 - mlxsw_sib_ports_remove(mlxsw_sib); 489 - } 490 - 491 - static const struct mlxsw_config_profile mlxsw_sib_config_profile = { 492 - .used_max_system_port = 1, 493 - .max_system_port = 48000, 494 - .used_max_ib_mc = 1, 495 - .max_ib_mc = 27, 496 - .used_max_pkey = 1, 497 - .max_pkey = 32, 498 - .swid_config = { 499 - { 500 - .used_type = 1, 501 - .type = MLXSW_PORT_SWID_TYPE_IB, 502 - } 503 - }, 504 - }; 505 - 506 - static struct mlxsw_driver mlxsw_sib_driver = { 507 - .kind = mlxsw_sib_driver_name, 508 - .priv_size = sizeof(struct mlxsw_sib), 509 - .init = mlxsw_sib_init, 510 - .fini = mlxsw_sib_fini, 511 - .basic_trap_groups_set = mlxsw_sib_basic_trap_groups_set, 512 - .txhdr_construct = mlxsw_sib_tx_v1_hdr_construct, 513 - .txhdr_len = MLXSW_TXHDR_LEN, 514 - .profile = &mlxsw_sib_config_profile, 515 - }; 516 - 517 - static struct mlxsw_driver mlxsw_sib2_driver = { 518 - .kind = mlxsw_sib2_driver_name, 519 - .priv_size = sizeof(struct mlxsw_sib), 520 - .init = mlxsw_sib_init, 521 - .fini = mlxsw_sib_fini, 522 - .basic_trap_groups_set = mlxsw_sib_basic_trap_groups_set, 523 - .txhdr_construct = mlxsw_sib_tx_v1_hdr_construct, 524 - .txhdr_len = MLXSW_TXHDR_LEN, 525 - .profile = &mlxsw_sib_config_profile, 526 - }; 527 - 528 - static const struct pci_device_id mlxsw_sib_pci_id_table[] = { 529 - {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHIB), 0}, 530 - {0, }, 531 - }; 532 - 533 - static struct pci_driver mlxsw_sib_pci_driver = { 534 - .name = mlxsw_sib_driver_name, 535 - .id_table = mlxsw_sib_pci_id_table, 536 - }; 537 - 538 - static const struct pci_device_id mlxsw_sib2_pci_id_table[] = { 539 - {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHIB2), 0}, 540 - {0, }, 541 - }; 542 - 543 - static struct pci_driver mlxsw_sib2_pci_driver = { 544 - .name = mlxsw_sib2_driver_name, 545 - .id_table = mlxsw_sib2_pci_id_table, 546 - }; 547 - 548 - static int __init mlxsw_sib_module_init(void) 549 - { 550 - int err; 551 - 552 - err = mlxsw_core_driver_register(&mlxsw_sib_driver); 553 - if (err) 554 - return err; 555 - 556 - err = mlxsw_core_driver_register(&mlxsw_sib2_driver); 557 - if (err) 558 - goto err_sib2_driver_register; 559 - 560 - err = mlxsw_pci_driver_register(&mlxsw_sib_pci_driver); 561 - if (err) 562 - goto err_sib_pci_driver_register; 563 - 564 - err = mlxsw_pci_driver_register(&mlxsw_sib2_pci_driver); 565 - if (err) 566 - goto err_sib2_pci_driver_register; 567 - 568 - return 0; 569 - 570 - err_sib2_pci_driver_register: 571 - mlxsw_pci_driver_unregister(&mlxsw_sib_pci_driver); 572 - err_sib_pci_driver_register: 573 - mlxsw_core_driver_unregister(&mlxsw_sib2_driver); 574 - err_sib2_driver_register: 575 - mlxsw_core_driver_unregister(&mlxsw_sib_driver); 576 - return err; 577 - } 578 - 579 - static void __exit mlxsw_sib_module_exit(void) 580 - { 581 - mlxsw_pci_driver_unregister(&mlxsw_sib2_pci_driver); 582 - mlxsw_pci_driver_unregister(&mlxsw_sib_pci_driver); 583 - mlxsw_core_driver_unregister(&mlxsw_sib2_driver); 584 - mlxsw_core_driver_unregister(&mlxsw_sib_driver); 585 - } 586 - 587 - module_init(mlxsw_sib_module_init); 588 - module_exit(mlxsw_sib_module_exit); 589 - 590 - MODULE_LICENSE("Dual BSD/GPL"); 591 - MODULE_AUTHOR("Elad Raz <eladr@@mellanox.com>"); 592 - MODULE_DESCRIPTION("Mellanox SwitchIB and SwitchIB-2 driver"); 593 - MODULE_ALIAS("mlxsw_switchib2"); 594 - MODULE_DEVICE_TABLE(pci, mlxsw_sib_pci_id_table); 595 - MODULE_DEVICE_TABLE(pci, mlxsw_sib2_pci_id_table);
-1691
drivers/net/ethernet/mellanox/mlxsw/switchx2.c
··· 1 - // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 - /* Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved */ 3 - 4 - #include <linux/kernel.h> 5 - #include <linux/module.h> 6 - #include <linux/types.h> 7 - #include <linux/pci.h> 8 - #include <linux/netdevice.h> 9 - #include <linux/ethtool.h> 10 - #include <linux/etherdevice.h> 11 - #include <linux/slab.h> 12 - #include <linux/device.h> 13 - #include <linux/skbuff.h> 14 - #include <linux/if_vlan.h> 15 - 16 - #include "pci.h" 17 - #include "core.h" 18 - #include "reg.h" 19 - #include "port.h" 20 - #include "trap.h" 21 - #include "txheader.h" 22 - #include "ib.h" 23 - 24 - static const char mlxsw_sx_driver_name[] = "mlxsw_switchx2"; 25 - static const char mlxsw_sx_driver_version[] = "1.0"; 26 - 27 - struct mlxsw_sx_port; 28 - 29 - struct mlxsw_sx { 30 - struct mlxsw_sx_port **ports; 31 - struct mlxsw_core *core; 32 - const struct mlxsw_bus_info *bus_info; 33 - u8 hw_id[ETH_ALEN]; 34 - }; 35 - 36 - struct mlxsw_sx_port_pcpu_stats { 37 - u64 rx_packets; 38 - u64 rx_bytes; 39 - u64 tx_packets; 40 - u64 tx_bytes; 41 - struct u64_stats_sync syncp; 42 - u32 tx_dropped; 43 - }; 44 - 45 - struct mlxsw_sx_port { 46 - struct net_device *dev; 47 - struct mlxsw_sx_port_pcpu_stats __percpu *pcpu_stats; 48 - struct mlxsw_sx *mlxsw_sx; 49 - u8 local_port; 50 - struct { 51 - u8 module; 52 - } mapping; 53 - }; 54 - 55 - /* tx_hdr_version 56 - * Tx header version. 57 - * Must be set to 0. 58 - */ 59 - MLXSW_ITEM32(tx, hdr, version, 0x00, 28, 4); 60 - 61 - /* tx_hdr_ctl 62 - * Packet control type. 63 - * 0 - Ethernet control (e.g. EMADs, LACP) 64 - * 1 - Ethernet data 65 - */ 66 - MLXSW_ITEM32(tx, hdr, ctl, 0x00, 26, 2); 67 - 68 - /* tx_hdr_proto 69 - * Packet protocol type. Must be set to 1 (Ethernet). 70 - */ 71 - MLXSW_ITEM32(tx, hdr, proto, 0x00, 21, 3); 72 - 73 - /* tx_hdr_etclass 74 - * Egress TClass to be used on the egress device on the egress port. 75 - * The MSB is specified in the 'ctclass3' field. 76 - * Range is 0-15, where 15 is the highest priority. 77 - */ 78 - MLXSW_ITEM32(tx, hdr, etclass, 0x00, 18, 3); 79 - 80 - /* tx_hdr_swid 81 - * Switch partition ID. 82 - */ 83 - MLXSW_ITEM32(tx, hdr, swid, 0x00, 12, 3); 84 - 85 - /* tx_hdr_port_mid 86 - * Destination local port for unicast packets. 87 - * Destination multicast ID for multicast packets. 88 - * 89 - * Control packets are directed to a specific egress port, while data 90 - * packets are transmitted through the CPU port (0) into the switch partition, 91 - * where forwarding rules are applied. 92 - */ 93 - MLXSW_ITEM32(tx, hdr, port_mid, 0x04, 16, 16); 94 - 95 - /* tx_hdr_ctclass3 96 - * See field 'etclass'. 97 - */ 98 - MLXSW_ITEM32(tx, hdr, ctclass3, 0x04, 14, 1); 99 - 100 - /* tx_hdr_rdq 101 - * RDQ for control packets sent to remote CPU. 102 - * Must be set to 0x1F for EMADs, otherwise 0. 103 - */ 104 - MLXSW_ITEM32(tx, hdr, rdq, 0x04, 9, 5); 105 - 106 - /* tx_hdr_cpu_sig 107 - * Signature control for packets going to CPU. Must be set to 0. 108 - */ 109 - MLXSW_ITEM32(tx, hdr, cpu_sig, 0x04, 0, 9); 110 - 111 - /* tx_hdr_sig 112 - * Stacking protocl signature. Must be set to 0xE0E0. 113 - */ 114 - MLXSW_ITEM32(tx, hdr, sig, 0x0C, 16, 16); 115 - 116 - /* tx_hdr_stclass 117 - * Stacking TClass. 118 - */ 119 - MLXSW_ITEM32(tx, hdr, stclass, 0x0C, 13, 3); 120 - 121 - /* tx_hdr_emad 122 - * EMAD bit. Must be set for EMADs. 123 - */ 124 - MLXSW_ITEM32(tx, hdr, emad, 0x0C, 5, 1); 125 - 126 - /* tx_hdr_type 127 - * 0 - Data packets 128 - * 6 - Control packets 129 - */ 130 - MLXSW_ITEM32(tx, hdr, type, 0x0C, 0, 4); 131 - 132 - static void mlxsw_sx_txhdr_construct(struct sk_buff *skb, 133 - const struct mlxsw_tx_info *tx_info) 134 - { 135 - char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN); 136 - bool is_emad = tx_info->is_emad; 137 - 138 - memset(txhdr, 0, MLXSW_TXHDR_LEN); 139 - 140 - /* We currently set default values for the egress tclass (QoS). */ 141 - mlxsw_tx_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_0); 142 - mlxsw_tx_hdr_ctl_set(txhdr, MLXSW_TXHDR_ETH_CTL); 143 - mlxsw_tx_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH); 144 - mlxsw_tx_hdr_etclass_set(txhdr, is_emad ? MLXSW_TXHDR_ETCLASS_6 : 145 - MLXSW_TXHDR_ETCLASS_5); 146 - mlxsw_tx_hdr_swid_set(txhdr, 0); 147 - mlxsw_tx_hdr_port_mid_set(txhdr, tx_info->local_port); 148 - mlxsw_tx_hdr_ctclass3_set(txhdr, MLXSW_TXHDR_CTCLASS3); 149 - mlxsw_tx_hdr_rdq_set(txhdr, is_emad ? MLXSW_TXHDR_RDQ_EMAD : 150 - MLXSW_TXHDR_RDQ_OTHER); 151 - mlxsw_tx_hdr_cpu_sig_set(txhdr, MLXSW_TXHDR_CPU_SIG); 152 - mlxsw_tx_hdr_sig_set(txhdr, MLXSW_TXHDR_SIG); 153 - mlxsw_tx_hdr_stclass_set(txhdr, MLXSW_TXHDR_STCLASS_NONE); 154 - mlxsw_tx_hdr_emad_set(txhdr, is_emad ? MLXSW_TXHDR_EMAD : 155 - MLXSW_TXHDR_NOT_EMAD); 156 - mlxsw_tx_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL); 157 - } 158 - 159 - static int mlxsw_sx_port_admin_status_set(struct mlxsw_sx_port *mlxsw_sx_port, 160 - bool is_up) 161 - { 162 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 163 - char paos_pl[MLXSW_REG_PAOS_LEN]; 164 - 165 - mlxsw_reg_paos_pack(paos_pl, mlxsw_sx_port->local_port, 166 - is_up ? MLXSW_PORT_ADMIN_STATUS_UP : 167 - MLXSW_PORT_ADMIN_STATUS_DOWN); 168 - return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(paos), paos_pl); 169 - } 170 - 171 - static int mlxsw_sx_port_oper_status_get(struct mlxsw_sx_port *mlxsw_sx_port, 172 - bool *p_is_up) 173 - { 174 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 175 - char paos_pl[MLXSW_REG_PAOS_LEN]; 176 - u8 oper_status; 177 - int err; 178 - 179 - mlxsw_reg_paos_pack(paos_pl, mlxsw_sx_port->local_port, 0); 180 - err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(paos), paos_pl); 181 - if (err) 182 - return err; 183 - oper_status = mlxsw_reg_paos_oper_status_get(paos_pl); 184 - *p_is_up = oper_status == MLXSW_PORT_ADMIN_STATUS_UP; 185 - return 0; 186 - } 187 - 188 - static int __mlxsw_sx_port_mtu_set(struct mlxsw_sx_port *mlxsw_sx_port, 189 - u16 mtu) 190 - { 191 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 192 - char pmtu_pl[MLXSW_REG_PMTU_LEN]; 193 - int max_mtu; 194 - int err; 195 - 196 - mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sx_port->local_port, 0); 197 - err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmtu), pmtu_pl); 198 - if (err) 199 - return err; 200 - max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl); 201 - 202 - if (mtu > max_mtu) 203 - return -EINVAL; 204 - 205 - mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sx_port->local_port, mtu); 206 - return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(pmtu), pmtu_pl); 207 - } 208 - 209 - static int mlxsw_sx_port_mtu_eth_set(struct mlxsw_sx_port *mlxsw_sx_port, 210 - u16 mtu) 211 - { 212 - mtu += MLXSW_TXHDR_LEN + ETH_HLEN; 213 - return __mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu); 214 - } 215 - 216 - static int mlxsw_sx_port_mtu_ib_set(struct mlxsw_sx_port *mlxsw_sx_port, 217 - u16 mtu) 218 - { 219 - return __mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu); 220 - } 221 - 222 - static int mlxsw_sx_port_ib_port_set(struct mlxsw_sx_port *mlxsw_sx_port, 223 - u8 ib_port) 224 - { 225 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 226 - char plib_pl[MLXSW_REG_PLIB_LEN] = {0}; 227 - int err; 228 - 229 - mlxsw_reg_plib_local_port_set(plib_pl, mlxsw_sx_port->local_port); 230 - mlxsw_reg_plib_ib_port_set(plib_pl, ib_port); 231 - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(plib), plib_pl); 232 - return err; 233 - } 234 - 235 - static int mlxsw_sx_port_swid_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 swid) 236 - { 237 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 238 - char pspa_pl[MLXSW_REG_PSPA_LEN]; 239 - 240 - mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sx_port->local_port); 241 - return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(pspa), pspa_pl); 242 - } 243 - 244 - static int 245 - mlxsw_sx_port_system_port_mapping_set(struct mlxsw_sx_port *mlxsw_sx_port) 246 - { 247 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 248 - char sspr_pl[MLXSW_REG_SSPR_LEN]; 249 - 250 - mlxsw_reg_sspr_pack(sspr_pl, mlxsw_sx_port->local_port); 251 - return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sspr), sspr_pl); 252 - } 253 - 254 - static int mlxsw_sx_port_module_info_get(struct mlxsw_sx *mlxsw_sx, 255 - u8 local_port, u8 *p_module, 256 - u8 *p_width) 257 - { 258 - char pmlp_pl[MLXSW_REG_PMLP_LEN]; 259 - int err; 260 - 261 - mlxsw_reg_pmlp_pack(pmlp_pl, local_port); 262 - err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmlp), pmlp_pl); 263 - if (err) 264 - return err; 265 - *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0); 266 - *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl); 267 - return 0; 268 - } 269 - 270 - static int mlxsw_sx_port_open(struct net_device *dev) 271 - { 272 - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); 273 - int err; 274 - 275 - err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, true); 276 - if (err) 277 - return err; 278 - netif_start_queue(dev); 279 - return 0; 280 - } 281 - 282 - static int mlxsw_sx_port_stop(struct net_device *dev) 283 - { 284 - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); 285 - 286 - netif_stop_queue(dev); 287 - return mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false); 288 - } 289 - 290 - static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb, 291 - struct net_device *dev) 292 - { 293 - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); 294 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 295 - struct mlxsw_sx_port_pcpu_stats *pcpu_stats; 296 - const struct mlxsw_tx_info tx_info = { 297 - .local_port = mlxsw_sx_port->local_port, 298 - .is_emad = false, 299 - }; 300 - u64 len; 301 - int err; 302 - 303 - if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) { 304 - this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped); 305 - dev_kfree_skb_any(skb); 306 - return NETDEV_TX_OK; 307 - } 308 - 309 - memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb)); 310 - 311 - if (mlxsw_core_skb_transmit_busy(mlxsw_sx->core, &tx_info)) 312 - return NETDEV_TX_BUSY; 313 - 314 - mlxsw_sx_txhdr_construct(skb, &tx_info); 315 - /* TX header is consumed by HW on the way so we shouldn't count its 316 - * bytes as being sent. 317 - */ 318 - len = skb->len - MLXSW_TXHDR_LEN; 319 - /* Due to a race we might fail here because of a full queue. In that 320 - * unlikely case we simply drop the packet. 321 - */ 322 - err = mlxsw_core_skb_transmit(mlxsw_sx->core, skb, &tx_info); 323 - 324 - if (!err) { 325 - pcpu_stats = this_cpu_ptr(mlxsw_sx_port->pcpu_stats); 326 - u64_stats_update_begin(&pcpu_stats->syncp); 327 - pcpu_stats->tx_packets++; 328 - pcpu_stats->tx_bytes += len; 329 - u64_stats_update_end(&pcpu_stats->syncp); 330 - } else { 331 - this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped); 332 - dev_kfree_skb_any(skb); 333 - } 334 - return NETDEV_TX_OK; 335 - } 336 - 337 - static int mlxsw_sx_port_change_mtu(struct net_device *dev, int mtu) 338 - { 339 - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); 340 - int err; 341 - 342 - err = mlxsw_sx_port_mtu_eth_set(mlxsw_sx_port, mtu); 343 - if (err) 344 - return err; 345 - dev->mtu = mtu; 346 - return 0; 347 - } 348 - 349 - static void 350 - mlxsw_sx_port_get_stats64(struct net_device *dev, 351 - struct rtnl_link_stats64 *stats) 352 - { 353 - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); 354 - struct mlxsw_sx_port_pcpu_stats *p; 355 - u64 rx_packets, rx_bytes, tx_packets, tx_bytes; 356 - u32 tx_dropped = 0; 357 - unsigned int start; 358 - int i; 359 - 360 - for_each_possible_cpu(i) { 361 - p = per_cpu_ptr(mlxsw_sx_port->pcpu_stats, i); 362 - do { 363 - start = u64_stats_fetch_begin_irq(&p->syncp); 364 - rx_packets = p->rx_packets; 365 - rx_bytes = p->rx_bytes; 366 - tx_packets = p->tx_packets; 367 - tx_bytes = p->tx_bytes; 368 - } while (u64_stats_fetch_retry_irq(&p->syncp, start)); 369 - 370 - stats->rx_packets += rx_packets; 371 - stats->rx_bytes += rx_bytes; 372 - stats->tx_packets += tx_packets; 373 - stats->tx_bytes += tx_bytes; 374 - /* tx_dropped is u32, updated without syncp protection. */ 375 - tx_dropped += p->tx_dropped; 376 - } 377 - stats->tx_dropped = tx_dropped; 378 - } 379 - 380 - static struct devlink_port * 381 - mlxsw_sx_port_get_devlink_port(struct net_device *dev) 382 - { 383 - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); 384 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 385 - 386 - return mlxsw_core_port_devlink_port_get(mlxsw_sx->core, 387 - mlxsw_sx_port->local_port); 388 - } 389 - 390 - static const struct net_device_ops mlxsw_sx_port_netdev_ops = { 391 - .ndo_open = mlxsw_sx_port_open, 392 - .ndo_stop = mlxsw_sx_port_stop, 393 - .ndo_start_xmit = mlxsw_sx_port_xmit, 394 - .ndo_change_mtu = mlxsw_sx_port_change_mtu, 395 - .ndo_get_stats64 = mlxsw_sx_port_get_stats64, 396 - .ndo_get_devlink_port = mlxsw_sx_port_get_devlink_port, 397 - }; 398 - 399 - static void mlxsw_sx_port_get_drvinfo(struct net_device *dev, 400 - struct ethtool_drvinfo *drvinfo) 401 - { 402 - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); 403 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 404 - 405 - strlcpy(drvinfo->driver, mlxsw_sx_driver_name, sizeof(drvinfo->driver)); 406 - strlcpy(drvinfo->version, mlxsw_sx_driver_version, 407 - sizeof(drvinfo->version)); 408 - snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), 409 - "%d.%d.%d", 410 - mlxsw_sx->bus_info->fw_rev.major, 411 - mlxsw_sx->bus_info->fw_rev.minor, 412 - mlxsw_sx->bus_info->fw_rev.subminor); 413 - strlcpy(drvinfo->bus_info, mlxsw_sx->bus_info->device_name, 414 - sizeof(drvinfo->bus_info)); 415 - } 416 - 417 - struct mlxsw_sx_port_hw_stats { 418 - char str[ETH_GSTRING_LEN]; 419 - u64 (*getter)(const char *payload); 420 - }; 421 - 422 - static const struct mlxsw_sx_port_hw_stats mlxsw_sx_port_hw_stats[] = { 423 - { 424 - .str = "a_frames_transmitted_ok", 425 - .getter = mlxsw_reg_ppcnt_a_frames_transmitted_ok_get, 426 - }, 427 - { 428 - .str = "a_frames_received_ok", 429 - .getter = mlxsw_reg_ppcnt_a_frames_received_ok_get, 430 - }, 431 - { 432 - .str = "a_frame_check_sequence_errors", 433 - .getter = mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get, 434 - }, 435 - { 436 - .str = "a_alignment_errors", 437 - .getter = mlxsw_reg_ppcnt_a_alignment_errors_get, 438 - }, 439 - { 440 - .str = "a_octets_transmitted_ok", 441 - .getter = mlxsw_reg_ppcnt_a_octets_transmitted_ok_get, 442 - }, 443 - { 444 - .str = "a_octets_received_ok", 445 - .getter = mlxsw_reg_ppcnt_a_octets_received_ok_get, 446 - }, 447 - { 448 - .str = "a_multicast_frames_xmitted_ok", 449 - .getter = mlxsw_reg_ppcnt_a_multicast_frames_xmitted_ok_get, 450 - }, 451 - { 452 - .str = "a_broadcast_frames_xmitted_ok", 453 - .getter = mlxsw_reg_ppcnt_a_broadcast_frames_xmitted_ok_get, 454 - }, 455 - { 456 - .str = "a_multicast_frames_received_ok", 457 - .getter = mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get, 458 - }, 459 - { 460 - .str = "a_broadcast_frames_received_ok", 461 - .getter = mlxsw_reg_ppcnt_a_broadcast_frames_received_ok_get, 462 - }, 463 - { 464 - .str = "a_in_range_length_errors", 465 - .getter = mlxsw_reg_ppcnt_a_in_range_length_errors_get, 466 - }, 467 - { 468 - .str = "a_out_of_range_length_field", 469 - .getter = mlxsw_reg_ppcnt_a_out_of_range_length_field_get, 470 - }, 471 - { 472 - .str = "a_frame_too_long_errors", 473 - .getter = mlxsw_reg_ppcnt_a_frame_too_long_errors_get, 474 - }, 475 - { 476 - .str = "a_symbol_error_during_carrier", 477 - .getter = mlxsw_reg_ppcnt_a_symbol_error_during_carrier_get, 478 - }, 479 - { 480 - .str = "a_mac_control_frames_transmitted", 481 - .getter = mlxsw_reg_ppcnt_a_mac_control_frames_transmitted_get, 482 - }, 483 - { 484 - .str = "a_mac_control_frames_received", 485 - .getter = mlxsw_reg_ppcnt_a_mac_control_frames_received_get, 486 - }, 487 - { 488 - .str = "a_unsupported_opcodes_received", 489 - .getter = mlxsw_reg_ppcnt_a_unsupported_opcodes_received_get, 490 - }, 491 - { 492 - .str = "a_pause_mac_ctrl_frames_received", 493 - .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_received_get, 494 - }, 495 - { 496 - .str = "a_pause_mac_ctrl_frames_xmitted", 497 - .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_transmitted_get, 498 - }, 499 - }; 500 - 501 - #define MLXSW_SX_PORT_HW_STATS_LEN ARRAY_SIZE(mlxsw_sx_port_hw_stats) 502 - 503 - static void mlxsw_sx_port_get_strings(struct net_device *dev, 504 - u32 stringset, u8 *data) 505 - { 506 - u8 *p = data; 507 - int i; 508 - 509 - switch (stringset) { 510 - case ETH_SS_STATS: 511 - for (i = 0; i < MLXSW_SX_PORT_HW_STATS_LEN; i++) { 512 - memcpy(p, mlxsw_sx_port_hw_stats[i].str, 513 - ETH_GSTRING_LEN); 514 - p += ETH_GSTRING_LEN; 515 - } 516 - break; 517 - } 518 - } 519 - 520 - static void mlxsw_sx_port_get_stats(struct net_device *dev, 521 - struct ethtool_stats *stats, u64 *data) 522 - { 523 - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); 524 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 525 - char ppcnt_pl[MLXSW_REG_PPCNT_LEN]; 526 - int i; 527 - int err; 528 - 529 - mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sx_port->local_port, 530 - MLXSW_REG_PPCNT_IEEE_8023_CNT, 0); 531 - err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ppcnt), ppcnt_pl); 532 - for (i = 0; i < MLXSW_SX_PORT_HW_STATS_LEN; i++) 533 - data[i] = !err ? mlxsw_sx_port_hw_stats[i].getter(ppcnt_pl) : 0; 534 - } 535 - 536 - static int mlxsw_sx_port_get_sset_count(struct net_device *dev, int sset) 537 - { 538 - switch (sset) { 539 - case ETH_SS_STATS: 540 - return MLXSW_SX_PORT_HW_STATS_LEN; 541 - default: 542 - return -EOPNOTSUPP; 543 - } 544 - } 545 - 546 - struct mlxsw_sx_port_link_mode { 547 - u32 mask; 548 - u32 supported; 549 - u32 advertised; 550 - u32 speed; 551 - }; 552 - 553 - static const struct mlxsw_sx_port_link_mode mlxsw_sx_port_link_mode[] = { 554 - { 555 - .mask = MLXSW_REG_PTYS_ETH_SPEED_SGMII | 556 - MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX, 557 - .supported = SUPPORTED_1000baseKX_Full, 558 - .advertised = ADVERTISED_1000baseKX_Full, 559 - .speed = 1000, 560 - }, 561 - { 562 - .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 | 563 - MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4, 564 - .supported = SUPPORTED_10000baseKX4_Full, 565 - .advertised = ADVERTISED_10000baseKX4_Full, 566 - .speed = 10000, 567 - }, 568 - { 569 - .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR | 570 - MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | 571 - MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | 572 - MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR, 573 - .supported = SUPPORTED_10000baseKR_Full, 574 - .advertised = ADVERTISED_10000baseKR_Full, 575 - .speed = 10000, 576 - }, 577 - { 578 - .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4, 579 - .supported = SUPPORTED_40000baseCR4_Full, 580 - .advertised = ADVERTISED_40000baseCR4_Full, 581 - .speed = 40000, 582 - }, 583 - { 584 - .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4, 585 - .supported = SUPPORTED_40000baseKR4_Full, 586 - .advertised = ADVERTISED_40000baseKR4_Full, 587 - .speed = 40000, 588 - }, 589 - { 590 - .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4, 591 - .supported = SUPPORTED_40000baseSR4_Full, 592 - .advertised = ADVERTISED_40000baseSR4_Full, 593 - .speed = 40000, 594 - }, 595 - { 596 - .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4, 597 - .supported = SUPPORTED_40000baseLR4_Full, 598 - .advertised = ADVERTISED_40000baseLR4_Full, 599 - .speed = 40000, 600 - }, 601 - { 602 - .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR | 603 - MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR | 604 - MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR, 605 - .speed = 25000, 606 - }, 607 - { 608 - .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR4 | 609 - MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2 | 610 - MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2, 611 - .speed = 50000, 612 - }, 613 - { 614 - .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 | 615 - MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 | 616 - MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 | 617 - MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4, 618 - .speed = 100000, 619 - }, 620 - }; 621 - 622 - #define MLXSW_SX_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sx_port_link_mode) 623 - #define MLXSW_SX_PORT_BASE_SPEED 10000 /* Mb/s */ 624 - 625 - static u32 mlxsw_sx_from_ptys_supported_port(u32 ptys_eth_proto) 626 - { 627 - if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | 628 - MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | 629 - MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 | 630 - MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 | 631 - MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 | 632 - MLXSW_REG_PTYS_ETH_SPEED_SGMII)) 633 - return SUPPORTED_FIBRE; 634 - 635 - if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR | 636 - MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 | 637 - MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 | 638 - MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 | 639 - MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX)) 640 - return SUPPORTED_Backplane; 641 - return 0; 642 - } 643 - 644 - static u32 mlxsw_sx_from_ptys_supported_link(u32 ptys_eth_proto) 645 - { 646 - u32 modes = 0; 647 - int i; 648 - 649 - for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) { 650 - if (ptys_eth_proto & mlxsw_sx_port_link_mode[i].mask) 651 - modes |= mlxsw_sx_port_link_mode[i].supported; 652 - } 653 - return modes; 654 - } 655 - 656 - static u32 mlxsw_sx_from_ptys_advert_link(u32 ptys_eth_proto) 657 - { 658 - u32 modes = 0; 659 - int i; 660 - 661 - for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) { 662 - if (ptys_eth_proto & mlxsw_sx_port_link_mode[i].mask) 663 - modes |= mlxsw_sx_port_link_mode[i].advertised; 664 - } 665 - return modes; 666 - } 667 - 668 - static void mlxsw_sx_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto, 669 - struct ethtool_link_ksettings *cmd) 670 - { 671 - u32 speed = SPEED_UNKNOWN; 672 - u8 duplex = DUPLEX_UNKNOWN; 673 - int i; 674 - 675 - if (!carrier_ok) 676 - goto out; 677 - 678 - for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) { 679 - if (ptys_eth_proto & mlxsw_sx_port_link_mode[i].mask) { 680 - speed = mlxsw_sx_port_link_mode[i].speed; 681 - duplex = DUPLEX_FULL; 682 - break; 683 - } 684 - } 685 - out: 686 - cmd->base.speed = speed; 687 - cmd->base.duplex = duplex; 688 - } 689 - 690 - static u8 mlxsw_sx_port_connector_port(u32 ptys_eth_proto) 691 - { 692 - if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | 693 - MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 | 694 - MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 | 695 - MLXSW_REG_PTYS_ETH_SPEED_SGMII)) 696 - return PORT_FIBRE; 697 - 698 - if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | 699 - MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 | 700 - MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4)) 701 - return PORT_DA; 702 - 703 - if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR | 704 - MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 | 705 - MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 | 706 - MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4)) 707 - return PORT_NONE; 708 - 709 - return PORT_OTHER; 710 - } 711 - 712 - static int 713 - mlxsw_sx_port_get_link_ksettings(struct net_device *dev, 714 - struct ethtool_link_ksettings *cmd) 715 - { 716 - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); 717 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 718 - char ptys_pl[MLXSW_REG_PTYS_LEN]; 719 - u32 eth_proto_cap; 720 - u32 eth_proto_admin; 721 - u32 eth_proto_oper; 722 - u32 supported, advertising, lp_advertising; 723 - int err; 724 - 725 - mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0, false); 726 - err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); 727 - if (err) { 728 - netdev_err(dev, "Failed to get proto"); 729 - return err; 730 - } 731 - mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap, 732 - &eth_proto_admin, &eth_proto_oper); 733 - 734 - supported = mlxsw_sx_from_ptys_supported_port(eth_proto_cap) | 735 - mlxsw_sx_from_ptys_supported_link(eth_proto_cap) | 736 - SUPPORTED_Pause | SUPPORTED_Asym_Pause; 737 - advertising = mlxsw_sx_from_ptys_advert_link(eth_proto_admin); 738 - mlxsw_sx_from_ptys_speed_duplex(netif_carrier_ok(dev), 739 - eth_proto_oper, cmd); 740 - 741 - eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap; 742 - cmd->base.port = mlxsw_sx_port_connector_port(eth_proto_oper); 743 - lp_advertising = mlxsw_sx_from_ptys_advert_link(eth_proto_oper); 744 - 745 - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, 746 - supported); 747 - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, 748 - advertising); 749 - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, 750 - lp_advertising); 751 - 752 - return 0; 753 - } 754 - 755 - static u32 mlxsw_sx_to_ptys_advert_link(u32 advertising) 756 - { 757 - u32 ptys_proto = 0; 758 - int i; 759 - 760 - for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) { 761 - if (advertising & mlxsw_sx_port_link_mode[i].advertised) 762 - ptys_proto |= mlxsw_sx_port_link_mode[i].mask; 763 - } 764 - return ptys_proto; 765 - } 766 - 767 - static u32 mlxsw_sx_to_ptys_speed(u32 speed) 768 - { 769 - u32 ptys_proto = 0; 770 - int i; 771 - 772 - for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) { 773 - if (speed == mlxsw_sx_port_link_mode[i].speed) 774 - ptys_proto |= mlxsw_sx_port_link_mode[i].mask; 775 - } 776 - return ptys_proto; 777 - } 778 - 779 - static u32 mlxsw_sx_to_ptys_upper_speed(u32 upper_speed) 780 - { 781 - u32 ptys_proto = 0; 782 - int i; 783 - 784 - for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) { 785 - if (mlxsw_sx_port_link_mode[i].speed <= upper_speed) 786 - ptys_proto |= mlxsw_sx_port_link_mode[i].mask; 787 - } 788 - return ptys_proto; 789 - } 790 - 791 - static int 792 - mlxsw_sx_port_set_link_ksettings(struct net_device *dev, 793 - const struct ethtool_link_ksettings *cmd) 794 - { 795 - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); 796 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 797 - char ptys_pl[MLXSW_REG_PTYS_LEN]; 798 - u32 speed; 799 - u32 eth_proto_new; 800 - u32 eth_proto_cap; 801 - u32 eth_proto_admin; 802 - u32 advertising; 803 - bool is_up; 804 - int err; 805 - 806 - speed = cmd->base.speed; 807 - 808 - ethtool_convert_link_mode_to_legacy_u32(&advertising, 809 - cmd->link_modes.advertising); 810 - 811 - eth_proto_new = cmd->base.autoneg == AUTONEG_ENABLE ? 812 - mlxsw_sx_to_ptys_advert_link(advertising) : 813 - mlxsw_sx_to_ptys_speed(speed); 814 - 815 - mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0, false); 816 - err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); 817 - if (err) { 818 - netdev_err(dev, "Failed to get proto"); 819 - return err; 820 - } 821 - mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin, 822 - NULL); 823 - 824 - eth_proto_new = eth_proto_new & eth_proto_cap; 825 - if (!eth_proto_new) { 826 - netdev_err(dev, "Not supported proto admin requested"); 827 - return -EINVAL; 828 - } 829 - if (eth_proto_new == eth_proto_admin) 830 - return 0; 831 - 832 - mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 833 - eth_proto_new, true); 834 - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); 835 - if (err) { 836 - netdev_err(dev, "Failed to set proto admin"); 837 - return err; 838 - } 839 - 840 - err = mlxsw_sx_port_oper_status_get(mlxsw_sx_port, &is_up); 841 - if (err) { 842 - netdev_err(dev, "Failed to get oper status"); 843 - return err; 844 - } 845 - if (!is_up) 846 - return 0; 847 - 848 - err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false); 849 - if (err) { 850 - netdev_err(dev, "Failed to set admin status"); 851 - return err; 852 - } 853 - 854 - err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, true); 855 - if (err) { 856 - netdev_err(dev, "Failed to set admin status"); 857 - return err; 858 - } 859 - 860 - return 0; 861 - } 862 - 863 - static const struct ethtool_ops mlxsw_sx_port_ethtool_ops = { 864 - .get_drvinfo = mlxsw_sx_port_get_drvinfo, 865 - .get_link = ethtool_op_get_link, 866 - .get_strings = mlxsw_sx_port_get_strings, 867 - .get_ethtool_stats = mlxsw_sx_port_get_stats, 868 - .get_sset_count = mlxsw_sx_port_get_sset_count, 869 - .get_link_ksettings = mlxsw_sx_port_get_link_ksettings, 870 - .set_link_ksettings = mlxsw_sx_port_set_link_ksettings, 871 - }; 872 - 873 - static int mlxsw_sx_hw_id_get(struct mlxsw_sx *mlxsw_sx) 874 - { 875 - char spad_pl[MLXSW_REG_SPAD_LEN] = {0}; 876 - int err; 877 - 878 - err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(spad), spad_pl); 879 - if (err) 880 - return err; 881 - mlxsw_reg_spad_base_mac_memcpy_from(spad_pl, mlxsw_sx->hw_id); 882 - return 0; 883 - } 884 - 885 - static int mlxsw_sx_port_dev_addr_get(struct mlxsw_sx_port *mlxsw_sx_port) 886 - { 887 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 888 - struct net_device *dev = mlxsw_sx_port->dev; 889 - char ppad_pl[MLXSW_REG_PPAD_LEN]; 890 - int err; 891 - 892 - mlxsw_reg_ppad_pack(ppad_pl, false, 0); 893 - err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ppad), ppad_pl); 894 - if (err) 895 - return err; 896 - mlxsw_reg_ppad_mac_memcpy_from(ppad_pl, dev->dev_addr); 897 - /* The last byte value in base mac address is guaranteed 898 - * to be such it does not overflow when adding local_port 899 - * value. 900 - */ 901 - dev->dev_addr[ETH_ALEN - 1] += mlxsw_sx_port->local_port; 902 - return 0; 903 - } 904 - 905 - static int mlxsw_sx_port_stp_state_set(struct mlxsw_sx_port *mlxsw_sx_port, 906 - u16 vid, enum mlxsw_reg_spms_state state) 907 - { 908 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 909 - char *spms_pl; 910 - int err; 911 - 912 - spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL); 913 - if (!spms_pl) 914 - return -ENOMEM; 915 - mlxsw_reg_spms_pack(spms_pl, mlxsw_sx_port->local_port); 916 - mlxsw_reg_spms_vid_pack(spms_pl, vid, state); 917 - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spms), spms_pl); 918 - kfree(spms_pl); 919 - return err; 920 - } 921 - 922 - static int mlxsw_sx_port_ib_speed_set(struct mlxsw_sx_port *mlxsw_sx_port, 923 - u16 speed, u16 width) 924 - { 925 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 926 - char ptys_pl[MLXSW_REG_PTYS_LEN]; 927 - 928 - mlxsw_reg_ptys_ib_pack(ptys_pl, mlxsw_sx_port->local_port, speed, 929 - width); 930 - return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); 931 - } 932 - 933 - static int 934 - mlxsw_sx_port_speed_by_width_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 width) 935 - { 936 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 937 - u32 upper_speed = MLXSW_SX_PORT_BASE_SPEED * width; 938 - char ptys_pl[MLXSW_REG_PTYS_LEN]; 939 - u32 eth_proto_admin; 940 - 941 - eth_proto_admin = mlxsw_sx_to_ptys_upper_speed(upper_speed); 942 - mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 943 - eth_proto_admin, true); 944 - return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); 945 - } 946 - 947 - static int 948 - mlxsw_sx_port_mac_learning_mode_set(struct mlxsw_sx_port *mlxsw_sx_port, 949 - enum mlxsw_reg_spmlr_learn_mode mode) 950 - { 951 - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; 952 - char spmlr_pl[MLXSW_REG_SPMLR_LEN]; 953 - 954 - mlxsw_reg_spmlr_pack(spmlr_pl, mlxsw_sx_port->local_port, mode); 955 - return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spmlr), spmlr_pl); 956 - } 957 - 958 - static int __mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, 959 - u8 module, u8 width) 960 - { 961 - struct mlxsw_sx_port *mlxsw_sx_port; 962 - struct net_device *dev; 963 - int err; 964 - 965 - dev = alloc_etherdev(sizeof(struct mlxsw_sx_port)); 966 - if (!dev) 967 - return -ENOMEM; 968 - SET_NETDEV_DEV(dev, mlxsw_sx->bus_info->dev); 969 - dev_net_set(dev, mlxsw_core_net(mlxsw_sx->core)); 970 - mlxsw_sx_port = netdev_priv(dev); 971 - mlxsw_sx_port->dev = dev; 972 - mlxsw_sx_port->mlxsw_sx = mlxsw_sx; 973 - mlxsw_sx_port->local_port = local_port; 974 - mlxsw_sx_port->mapping.module = module; 975 - 976 - mlxsw_sx_port->pcpu_stats = 977 - netdev_alloc_pcpu_stats(struct mlxsw_sx_port_pcpu_stats); 978 - if (!mlxsw_sx_port->pcpu_stats) { 979 - err = -ENOMEM; 980 - goto err_alloc_stats; 981 - } 982 - 983 - dev->netdev_ops = &mlxsw_sx_port_netdev_ops; 984 - dev->ethtool_ops = &mlxsw_sx_port_ethtool_ops; 985 - 986 - err = mlxsw_sx_port_dev_addr_get(mlxsw_sx_port); 987 - if (err) { 988 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Unable to get port mac address\n", 989 - mlxsw_sx_port->local_port); 990 - goto err_dev_addr_get; 991 - } 992 - 993 - netif_carrier_off(dev); 994 - 995 - dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_LLTX | NETIF_F_SG | 996 - NETIF_F_VLAN_CHALLENGED; 997 - 998 - dev->min_mtu = 0; 999 - dev->max_mtu = ETH_MAX_MTU; 1000 - 1001 - /* Each packet needs to have a Tx header (metadata) on top all other 1002 - * headers. 1003 - */ 1004 - dev->needed_headroom = MLXSW_TXHDR_LEN; 1005 - 1006 - err = mlxsw_sx_port_system_port_mapping_set(mlxsw_sx_port); 1007 - if (err) { 1008 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set system port mapping\n", 1009 - mlxsw_sx_port->local_port); 1010 - goto err_port_system_port_mapping_set; 1011 - } 1012 - 1013 - err = mlxsw_sx_port_swid_set(mlxsw_sx_port, 0); 1014 - if (err) { 1015 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set SWID\n", 1016 - mlxsw_sx_port->local_port); 1017 - goto err_port_swid_set; 1018 - } 1019 - 1020 - err = mlxsw_sx_port_speed_by_width_set(mlxsw_sx_port, width); 1021 - if (err) { 1022 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set speed\n", 1023 - mlxsw_sx_port->local_port); 1024 - goto err_port_speed_set; 1025 - } 1026 - 1027 - err = mlxsw_sx_port_mtu_eth_set(mlxsw_sx_port, ETH_DATA_LEN); 1028 - if (err) { 1029 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MTU\n", 1030 - mlxsw_sx_port->local_port); 1031 - goto err_port_mtu_set; 1032 - } 1033 - 1034 - err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false); 1035 - if (err) 1036 - goto err_port_admin_status_set; 1037 - 1038 - err = mlxsw_sx_port_stp_state_set(mlxsw_sx_port, 1039 - MLXSW_PORT_DEFAULT_VID, 1040 - MLXSW_REG_SPMS_STATE_FORWARDING); 1041 - if (err) { 1042 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set STP state\n", 1043 - mlxsw_sx_port->local_port); 1044 - goto err_port_stp_state_set; 1045 - } 1046 - 1047 - err = mlxsw_sx_port_mac_learning_mode_set(mlxsw_sx_port, 1048 - MLXSW_REG_SPMLR_LEARN_MODE_DISABLE); 1049 - if (err) { 1050 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MAC learning mode\n", 1051 - mlxsw_sx_port->local_port); 1052 - goto err_port_mac_learning_mode_set; 1053 - } 1054 - 1055 - err = register_netdev(dev); 1056 - if (err) { 1057 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to register netdev\n", 1058 - mlxsw_sx_port->local_port); 1059 - goto err_register_netdev; 1060 - } 1061 - 1062 - mlxsw_core_port_eth_set(mlxsw_sx->core, mlxsw_sx_port->local_port, 1063 - mlxsw_sx_port, dev); 1064 - mlxsw_sx->ports[local_port] = mlxsw_sx_port; 1065 - return 0; 1066 - 1067 - err_register_netdev: 1068 - err_port_mac_learning_mode_set: 1069 - err_port_stp_state_set: 1070 - err_port_admin_status_set: 1071 - err_port_mtu_set: 1072 - err_port_speed_set: 1073 - mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT); 1074 - err_port_swid_set: 1075 - err_port_system_port_mapping_set: 1076 - err_dev_addr_get: 1077 - free_percpu(mlxsw_sx_port->pcpu_stats); 1078 - err_alloc_stats: 1079 - free_netdev(dev); 1080 - return err; 1081 - } 1082 - 1083 - static int mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, 1084 - u8 module, u8 width) 1085 - { 1086 - int err; 1087 - 1088 - err = mlxsw_core_port_init(mlxsw_sx->core, local_port, 1089 - module + 1, false, 0, false, 0, 1090 - mlxsw_sx->hw_id, sizeof(mlxsw_sx->hw_id)); 1091 - if (err) { 1092 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to init core port\n", 1093 - local_port); 1094 - return err; 1095 - } 1096 - err = __mlxsw_sx_port_eth_create(mlxsw_sx, local_port, module, width); 1097 - if (err) 1098 - goto err_port_create; 1099 - 1100 - return 0; 1101 - 1102 - err_port_create: 1103 - mlxsw_core_port_fini(mlxsw_sx->core, local_port); 1104 - return err; 1105 - } 1106 - 1107 - static void __mlxsw_sx_port_eth_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) 1108 - { 1109 - struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port]; 1110 - 1111 - mlxsw_core_port_clear(mlxsw_sx->core, local_port, mlxsw_sx); 1112 - unregister_netdev(mlxsw_sx_port->dev); /* This calls ndo_stop */ 1113 - mlxsw_sx->ports[local_port] = NULL; 1114 - mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT); 1115 - free_percpu(mlxsw_sx_port->pcpu_stats); 1116 - free_netdev(mlxsw_sx_port->dev); 1117 - } 1118 - 1119 - static bool mlxsw_sx_port_created(struct mlxsw_sx *mlxsw_sx, u8 local_port) 1120 - { 1121 - return mlxsw_sx->ports[local_port] != NULL; 1122 - } 1123 - 1124 - static int __mlxsw_sx_port_ib_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, 1125 - u8 module, u8 width) 1126 - { 1127 - struct mlxsw_sx_port *mlxsw_sx_port; 1128 - int err; 1129 - 1130 - mlxsw_sx_port = kzalloc(sizeof(*mlxsw_sx_port), GFP_KERNEL); 1131 - if (!mlxsw_sx_port) 1132 - return -ENOMEM; 1133 - mlxsw_sx_port->mlxsw_sx = mlxsw_sx; 1134 - mlxsw_sx_port->local_port = local_port; 1135 - mlxsw_sx_port->mapping.module = module; 1136 - 1137 - err = mlxsw_sx_port_system_port_mapping_set(mlxsw_sx_port); 1138 - if (err) { 1139 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set system port mapping\n", 1140 - mlxsw_sx_port->local_port); 1141 - goto err_port_system_port_mapping_set; 1142 - } 1143 - 1144 - /* Adding port to Infiniband swid (1) */ 1145 - err = mlxsw_sx_port_swid_set(mlxsw_sx_port, 1); 1146 - if (err) { 1147 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set SWID\n", 1148 - mlxsw_sx_port->local_port); 1149 - goto err_port_swid_set; 1150 - } 1151 - 1152 - /* Expose the IB port number as it's front panel name */ 1153 - err = mlxsw_sx_port_ib_port_set(mlxsw_sx_port, module + 1); 1154 - if (err) { 1155 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set IB port\n", 1156 - mlxsw_sx_port->local_port); 1157 - goto err_port_ib_set; 1158 - } 1159 - 1160 - /* Supports all speeds from SDR to FDR (bitmask) and support bus width 1161 - * of 1x, 2x and 4x (3 bits bitmask) 1162 - */ 1163 - err = mlxsw_sx_port_ib_speed_set(mlxsw_sx_port, 1164 - MLXSW_REG_PTYS_IB_SPEED_EDR - 1, 1165 - BIT(3) - 1); 1166 - if (err) { 1167 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set speed\n", 1168 - mlxsw_sx_port->local_port); 1169 - goto err_port_speed_set; 1170 - } 1171 - 1172 - /* Change to the maximum MTU the device supports, the SMA will take 1173 - * care of the active MTU 1174 - */ 1175 - err = mlxsw_sx_port_mtu_ib_set(mlxsw_sx_port, MLXSW_IB_DEFAULT_MTU); 1176 - if (err) { 1177 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MTU\n", 1178 - mlxsw_sx_port->local_port); 1179 - goto err_port_mtu_set; 1180 - } 1181 - 1182 - err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, true); 1183 - if (err) { 1184 - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to change admin state to UP\n", 1185 - mlxsw_sx_port->local_port); 1186 - goto err_port_admin_set; 1187 - } 1188 - 1189 - mlxsw_core_port_ib_set(mlxsw_sx->core, mlxsw_sx_port->local_port, 1190 - mlxsw_sx_port); 1191 - mlxsw_sx->ports[local_port] = mlxsw_sx_port; 1192 - return 0; 1193 - 1194 - err_port_admin_set: 1195 - err_port_mtu_set: 1196 - err_port_speed_set: 1197 - err_port_ib_set: 1198 - mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT); 1199 - err_port_swid_set: 1200 - err_port_system_port_mapping_set: 1201 - kfree(mlxsw_sx_port); 1202 - return err; 1203 - } 1204 - 1205 - static void __mlxsw_sx_port_ib_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) 1206 - { 1207 - struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port]; 1208 - 1209 - mlxsw_core_port_clear(mlxsw_sx->core, local_port, mlxsw_sx); 1210 - mlxsw_sx->ports[local_port] = NULL; 1211 - mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false); 1212 - mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT); 1213 - kfree(mlxsw_sx_port); 1214 - } 1215 - 1216 - static void __mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) 1217 - { 1218 - enum devlink_port_type port_type = 1219 - mlxsw_core_port_type_get(mlxsw_sx->core, local_port); 1220 - 1221 - if (port_type == DEVLINK_PORT_TYPE_ETH) 1222 - __mlxsw_sx_port_eth_remove(mlxsw_sx, local_port); 1223 - else if (port_type == DEVLINK_PORT_TYPE_IB) 1224 - __mlxsw_sx_port_ib_remove(mlxsw_sx, local_port); 1225 - } 1226 - 1227 - static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) 1228 - { 1229 - __mlxsw_sx_port_remove(mlxsw_sx, local_port); 1230 - mlxsw_core_port_fini(mlxsw_sx->core, local_port); 1231 - } 1232 - 1233 - static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx) 1234 - { 1235 - int i; 1236 - 1237 - for (i = 1; i < mlxsw_core_max_ports(mlxsw_sx->core); i++) 1238 - if (mlxsw_sx_port_created(mlxsw_sx, i)) 1239 - mlxsw_sx_port_remove(mlxsw_sx, i); 1240 - kfree(mlxsw_sx->ports); 1241 - mlxsw_sx->ports = NULL; 1242 - } 1243 - 1244 - static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) 1245 - { 1246 - unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sx->core); 1247 - size_t alloc_size; 1248 - u8 module, width; 1249 - int i; 1250 - int err; 1251 - 1252 - alloc_size = sizeof(struct mlxsw_sx_port *) * max_ports; 1253 - mlxsw_sx->ports = kzalloc(alloc_size, GFP_KERNEL); 1254 - if (!mlxsw_sx->ports) 1255 - return -ENOMEM; 1256 - 1257 - for (i = 1; i < max_ports; i++) { 1258 - err = mlxsw_sx_port_module_info_get(mlxsw_sx, i, &module, 1259 - &width); 1260 - if (err) 1261 - goto err_port_module_info_get; 1262 - if (!width) 1263 - continue; 1264 - err = mlxsw_sx_port_eth_create(mlxsw_sx, i, module, width); 1265 - if (err) 1266 - goto err_port_create; 1267 - } 1268 - return 0; 1269 - 1270 - err_port_create: 1271 - err_port_module_info_get: 1272 - for (i--; i >= 1; i--) 1273 - if (mlxsw_sx_port_created(mlxsw_sx, i)) 1274 - mlxsw_sx_port_remove(mlxsw_sx, i); 1275 - kfree(mlxsw_sx->ports); 1276 - mlxsw_sx->ports = NULL; 1277 - return err; 1278 - } 1279 - 1280 - static void mlxsw_sx_pude_eth_event_func(struct mlxsw_sx_port *mlxsw_sx_port, 1281 - enum mlxsw_reg_pude_oper_status status) 1282 - { 1283 - if (status == MLXSW_PORT_OPER_STATUS_UP) { 1284 - netdev_info(mlxsw_sx_port->dev, "link up\n"); 1285 - netif_carrier_on(mlxsw_sx_port->dev); 1286 - } else { 1287 - netdev_info(mlxsw_sx_port->dev, "link down\n"); 1288 - netif_carrier_off(mlxsw_sx_port->dev); 1289 - } 1290 - } 1291 - 1292 - static void mlxsw_sx_pude_ib_event_func(struct mlxsw_sx_port *mlxsw_sx_port, 1293 - enum mlxsw_reg_pude_oper_status status) 1294 - { 1295 - if (status == MLXSW_PORT_OPER_STATUS_UP) 1296 - pr_info("ib link for port %d - up\n", 1297 - mlxsw_sx_port->mapping.module + 1); 1298 - else 1299 - pr_info("ib link for port %d - down\n", 1300 - mlxsw_sx_port->mapping.module + 1); 1301 - } 1302 - 1303 - static void mlxsw_sx_pude_event_func(const struct mlxsw_reg_info *reg, 1304 - char *pude_pl, void *priv) 1305 - { 1306 - struct mlxsw_sx *mlxsw_sx = priv; 1307 - struct mlxsw_sx_port *mlxsw_sx_port; 1308 - enum mlxsw_reg_pude_oper_status status; 1309 - enum devlink_port_type port_type; 1310 - u8 local_port; 1311 - 1312 - local_port = mlxsw_reg_pude_local_port_get(pude_pl); 1313 - mlxsw_sx_port = mlxsw_sx->ports[local_port]; 1314 - if (!mlxsw_sx_port) { 1315 - dev_warn(mlxsw_sx->bus_info->dev, "Port %d: Link event received for non-existent port\n", 1316 - local_port); 1317 - return; 1318 - } 1319 - 1320 - status = mlxsw_reg_pude_oper_status_get(pude_pl); 1321 - port_type = mlxsw_core_port_type_get(mlxsw_sx->core, local_port); 1322 - if (port_type == DEVLINK_PORT_TYPE_ETH) 1323 - mlxsw_sx_pude_eth_event_func(mlxsw_sx_port, status); 1324 - else if (port_type == DEVLINK_PORT_TYPE_IB) 1325 - mlxsw_sx_pude_ib_event_func(mlxsw_sx_port, status); 1326 - } 1327 - 1328 - static void mlxsw_sx_rx_listener_func(struct sk_buff *skb, u8 local_port, 1329 - void *priv) 1330 - { 1331 - struct mlxsw_sx *mlxsw_sx = priv; 1332 - struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port]; 1333 - struct mlxsw_sx_port_pcpu_stats *pcpu_stats; 1334 - 1335 - if (unlikely(!mlxsw_sx_port)) { 1336 - dev_warn_ratelimited(mlxsw_sx->bus_info->dev, "Port %d: skb received for non-existent port\n", 1337 - local_port); 1338 - return; 1339 - } 1340 - 1341 - skb->dev = mlxsw_sx_port->dev; 1342 - 1343 - pcpu_stats = this_cpu_ptr(mlxsw_sx_port->pcpu_stats); 1344 - u64_stats_update_begin(&pcpu_stats->syncp); 1345 - pcpu_stats->rx_packets++; 1346 - pcpu_stats->rx_bytes += skb->len; 1347 - u64_stats_update_end(&pcpu_stats->syncp); 1348 - 1349 - skb->protocol = eth_type_trans(skb, skb->dev); 1350 - netif_receive_skb(skb); 1351 - } 1352 - 1353 - static int mlxsw_sx_port_type_set(struct mlxsw_core *mlxsw_core, u8 local_port, 1354 - enum devlink_port_type new_type) 1355 - { 1356 - struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core); 1357 - u8 module, width; 1358 - int err; 1359 - 1360 - if (!mlxsw_sx->ports || !mlxsw_sx->ports[local_port]) { 1361 - dev_err(mlxsw_sx->bus_info->dev, "Port number \"%d\" does not exist\n", 1362 - local_port); 1363 - return -EINVAL; 1364 - } 1365 - 1366 - if (new_type == DEVLINK_PORT_TYPE_AUTO) 1367 - return -EOPNOTSUPP; 1368 - 1369 - __mlxsw_sx_port_remove(mlxsw_sx, local_port); 1370 - err = mlxsw_sx_port_module_info_get(mlxsw_sx, local_port, &module, 1371 - &width); 1372 - if (err) 1373 - goto err_port_module_info_get; 1374 - 1375 - if (new_type == DEVLINK_PORT_TYPE_ETH) 1376 - err = __mlxsw_sx_port_eth_create(mlxsw_sx, local_port, module, 1377 - width); 1378 - else if (new_type == DEVLINK_PORT_TYPE_IB) 1379 - err = __mlxsw_sx_port_ib_create(mlxsw_sx, local_port, module, 1380 - width); 1381 - 1382 - err_port_module_info_get: 1383 - return err; 1384 - } 1385 - 1386 - enum { 1387 - MLXSW_REG_HTGT_TRAP_GROUP_SX2_RX = 1, 1388 - MLXSW_REG_HTGT_TRAP_GROUP_SX2_CTRL = 2, 1389 - }; 1390 - 1391 - #define MLXSW_SX_RXL(_trap_id) \ 1392 - MLXSW_RXL(mlxsw_sx_rx_listener_func, _trap_id, TRAP_TO_CPU, \ 1393 - false, SX2_RX, FORWARD) 1394 - 1395 - static const struct mlxsw_listener mlxsw_sx_listener[] = { 1396 - MLXSW_EVENTL(mlxsw_sx_pude_event_func, PUDE, EMAD), 1397 - MLXSW_SX_RXL(FDB_MC), 1398 - MLXSW_SX_RXL(STP), 1399 - MLXSW_SX_RXL(LACP), 1400 - MLXSW_SX_RXL(EAPOL), 1401 - MLXSW_SX_RXL(LLDP), 1402 - MLXSW_SX_RXL(MMRP), 1403 - MLXSW_SX_RXL(MVRP), 1404 - MLXSW_SX_RXL(RPVST), 1405 - MLXSW_SX_RXL(DHCP), 1406 - MLXSW_SX_RXL(IGMP_QUERY), 1407 - MLXSW_SX_RXL(IGMP_V1_REPORT), 1408 - MLXSW_SX_RXL(IGMP_V2_REPORT), 1409 - MLXSW_SX_RXL(IGMP_V2_LEAVE), 1410 - MLXSW_SX_RXL(IGMP_V3_REPORT), 1411 - }; 1412 - 1413 - static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx) 1414 - { 1415 - char htgt_pl[MLXSW_REG_HTGT_LEN]; 1416 - int i; 1417 - int err; 1418 - 1419 - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_SX2_RX, 1420 - MLXSW_REG_HTGT_INVALID_POLICER, 1421 - MLXSW_REG_HTGT_DEFAULT_PRIORITY, 1422 - MLXSW_REG_HTGT_DEFAULT_TC); 1423 - mlxsw_reg_htgt_local_path_rdq_set(htgt_pl, 1424 - MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_RX); 1425 - 1426 - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(htgt), htgt_pl); 1427 - if (err) 1428 - return err; 1429 - 1430 - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_SX2_CTRL, 1431 - MLXSW_REG_HTGT_INVALID_POLICER, 1432 - MLXSW_REG_HTGT_DEFAULT_PRIORITY, 1433 - MLXSW_REG_HTGT_DEFAULT_TC); 1434 - mlxsw_reg_htgt_local_path_rdq_set(htgt_pl, 1435 - MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_CTRL); 1436 - 1437 - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(htgt), htgt_pl); 1438 - if (err) 1439 - return err; 1440 - 1441 - for (i = 0; i < ARRAY_SIZE(mlxsw_sx_listener); i++) { 1442 - err = mlxsw_core_trap_register(mlxsw_sx->core, 1443 - &mlxsw_sx_listener[i], 1444 - mlxsw_sx); 1445 - if (err) 1446 - goto err_listener_register; 1447 - 1448 - } 1449 - return 0; 1450 - 1451 - err_listener_register: 1452 - for (i--; i >= 0; i--) { 1453 - mlxsw_core_trap_unregister(mlxsw_sx->core, 1454 - &mlxsw_sx_listener[i], 1455 - mlxsw_sx); 1456 - } 1457 - return err; 1458 - } 1459 - 1460 - static void mlxsw_sx_traps_fini(struct mlxsw_sx *mlxsw_sx) 1461 - { 1462 - int i; 1463 - 1464 - for (i = 0; i < ARRAY_SIZE(mlxsw_sx_listener); i++) { 1465 - mlxsw_core_trap_unregister(mlxsw_sx->core, 1466 - &mlxsw_sx_listener[i], 1467 - mlxsw_sx); 1468 - } 1469 - } 1470 - 1471 - static int mlxsw_sx_flood_init(struct mlxsw_sx *mlxsw_sx) 1472 - { 1473 - char sfgc_pl[MLXSW_REG_SFGC_LEN]; 1474 - char sgcr_pl[MLXSW_REG_SGCR_LEN]; 1475 - char *sftr_pl; 1476 - int err; 1477 - 1478 - /* Configure a flooding table, which includes only CPU port. */ 1479 - sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL); 1480 - if (!sftr_pl) 1481 - return -ENOMEM; 1482 - mlxsw_reg_sftr_pack(sftr_pl, 0, 0, MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 0, 1483 - MLXSW_PORT_CPU_PORT, true); 1484 - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sftr), sftr_pl); 1485 - kfree(sftr_pl); 1486 - if (err) 1487 - return err; 1488 - 1489 - /* Flood different packet types using the flooding table. */ 1490 - mlxsw_reg_sfgc_pack(sfgc_pl, 1491 - MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST, 1492 - MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID, 1493 - MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 1494 - 0); 1495 - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl); 1496 - if (err) 1497 - return err; 1498 - 1499 - mlxsw_reg_sfgc_pack(sfgc_pl, 1500 - MLXSW_REG_SFGC_TYPE_BROADCAST, 1501 - MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID, 1502 - MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 1503 - 0); 1504 - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl); 1505 - if (err) 1506 - return err; 1507 - 1508 - mlxsw_reg_sfgc_pack(sfgc_pl, 1509 - MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP, 1510 - MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID, 1511 - MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 1512 - 0); 1513 - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl); 1514 - if (err) 1515 - return err; 1516 - 1517 - mlxsw_reg_sfgc_pack(sfgc_pl, 1518 - MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6, 1519 - MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID, 1520 - MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 1521 - 0); 1522 - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl); 1523 - if (err) 1524 - return err; 1525 - 1526 - mlxsw_reg_sfgc_pack(sfgc_pl, 1527 - MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4, 1528 - MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID, 1529 - MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 1530 - 0); 1531 - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl); 1532 - if (err) 1533 - return err; 1534 - 1535 - mlxsw_reg_sgcr_pack(sgcr_pl, true); 1536 - return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sgcr), sgcr_pl); 1537 - } 1538 - 1539 - static int mlxsw_sx_basic_trap_groups_set(struct mlxsw_core *mlxsw_core) 1540 - { 1541 - char htgt_pl[MLXSW_REG_HTGT_LEN]; 1542 - 1543 - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD, 1544 - MLXSW_REG_HTGT_INVALID_POLICER, 1545 - MLXSW_REG_HTGT_DEFAULT_PRIORITY, 1546 - MLXSW_REG_HTGT_DEFAULT_TC); 1547 - mlxsw_reg_htgt_swid_set(htgt_pl, MLXSW_PORT_SWID_ALL_SWIDS); 1548 - mlxsw_reg_htgt_local_path_rdq_set(htgt_pl, 1549 - MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_EMAD); 1550 - return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); 1551 - } 1552 - 1553 - static int mlxsw_sx_init(struct mlxsw_core *mlxsw_core, 1554 - const struct mlxsw_bus_info *mlxsw_bus_info, 1555 - struct netlink_ext_ack *extack) 1556 - { 1557 - struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core); 1558 - int err; 1559 - 1560 - mlxsw_sx->core = mlxsw_core; 1561 - mlxsw_sx->bus_info = mlxsw_bus_info; 1562 - 1563 - err = mlxsw_sx_hw_id_get(mlxsw_sx); 1564 - if (err) { 1565 - dev_err(mlxsw_sx->bus_info->dev, "Failed to get switch HW ID\n"); 1566 - return err; 1567 - } 1568 - 1569 - err = mlxsw_sx_ports_create(mlxsw_sx); 1570 - if (err) { 1571 - dev_err(mlxsw_sx->bus_info->dev, "Failed to create ports\n"); 1572 - return err; 1573 - } 1574 - 1575 - err = mlxsw_sx_traps_init(mlxsw_sx); 1576 - if (err) { 1577 - dev_err(mlxsw_sx->bus_info->dev, "Failed to set traps\n"); 1578 - goto err_listener_register; 1579 - } 1580 - 1581 - err = mlxsw_sx_flood_init(mlxsw_sx); 1582 - if (err) { 1583 - dev_err(mlxsw_sx->bus_info->dev, "Failed to initialize flood tables\n"); 1584 - goto err_flood_init; 1585 - } 1586 - 1587 - return 0; 1588 - 1589 - err_flood_init: 1590 - mlxsw_sx_traps_fini(mlxsw_sx); 1591 - err_listener_register: 1592 - mlxsw_sx_ports_remove(mlxsw_sx); 1593 - return err; 1594 - } 1595 - 1596 - static void mlxsw_sx_fini(struct mlxsw_core *mlxsw_core) 1597 - { 1598 - struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core); 1599 - 1600 - mlxsw_sx_traps_fini(mlxsw_sx); 1601 - mlxsw_sx_ports_remove(mlxsw_sx); 1602 - } 1603 - 1604 - static const struct mlxsw_config_profile mlxsw_sx_config_profile = { 1605 - .used_max_vepa_channels = 1, 1606 - .max_vepa_channels = 0, 1607 - .used_max_mid = 1, 1608 - .max_mid = 7000, 1609 - .used_max_pgt = 1, 1610 - .max_pgt = 0, 1611 - .used_max_system_port = 1, 1612 - .max_system_port = 48000, 1613 - .used_max_vlan_groups = 1, 1614 - .max_vlan_groups = 127, 1615 - .used_max_regions = 1, 1616 - .max_regions = 400, 1617 - .used_flood_tables = 1, 1618 - .max_flood_tables = 2, 1619 - .max_vid_flood_tables = 1, 1620 - .used_flood_mode = 1, 1621 - .flood_mode = 3, 1622 - .used_max_ib_mc = 1, 1623 - .max_ib_mc = 6, 1624 - .used_max_pkey = 1, 1625 - .max_pkey = 0, 1626 - .swid_config = { 1627 - { 1628 - .used_type = 1, 1629 - .type = MLXSW_PORT_SWID_TYPE_ETH, 1630 - }, 1631 - { 1632 - .used_type = 1, 1633 - .type = MLXSW_PORT_SWID_TYPE_IB, 1634 - } 1635 - }, 1636 - }; 1637 - 1638 - static struct mlxsw_driver mlxsw_sx_driver = { 1639 - .kind = mlxsw_sx_driver_name, 1640 - .priv_size = sizeof(struct mlxsw_sx), 1641 - .init = mlxsw_sx_init, 1642 - .fini = mlxsw_sx_fini, 1643 - .basic_trap_groups_set = mlxsw_sx_basic_trap_groups_set, 1644 - .txhdr_construct = mlxsw_sx_txhdr_construct, 1645 - .txhdr_len = MLXSW_TXHDR_LEN, 1646 - .profile = &mlxsw_sx_config_profile, 1647 - .port_type_set = mlxsw_sx_port_type_set, 1648 - }; 1649 - 1650 - static const struct pci_device_id mlxsw_sx_pci_id_table[] = { 1651 - {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHX2), 0}, 1652 - {0, }, 1653 - }; 1654 - 1655 - static struct pci_driver mlxsw_sx_pci_driver = { 1656 - .name = mlxsw_sx_driver_name, 1657 - .id_table = mlxsw_sx_pci_id_table, 1658 - }; 1659 - 1660 - static int __init mlxsw_sx_module_init(void) 1661 - { 1662 - int err; 1663 - 1664 - err = mlxsw_core_driver_register(&mlxsw_sx_driver); 1665 - if (err) 1666 - return err; 1667 - 1668 - err = mlxsw_pci_driver_register(&mlxsw_sx_pci_driver); 1669 - if (err) 1670 - goto err_pci_driver_register; 1671 - 1672 - return 0; 1673 - 1674 - err_pci_driver_register: 1675 - mlxsw_core_driver_unregister(&mlxsw_sx_driver); 1676 - return err; 1677 - } 1678 - 1679 - static void __exit mlxsw_sx_module_exit(void) 1680 - { 1681 - mlxsw_pci_driver_unregister(&mlxsw_sx_pci_driver); 1682 - mlxsw_core_driver_unregister(&mlxsw_sx_driver); 1683 - } 1684 - 1685 - module_init(mlxsw_sx_module_init); 1686 - module_exit(mlxsw_sx_module_exit); 1687 - 1688 - MODULE_LICENSE("Dual BSD/GPL"); 1689 - MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 1690 - MODULE_DESCRIPTION("Mellanox SwitchX-2 driver"); 1691 - MODULE_DEVICE_TABLE(pci, mlxsw_sx_pci_id_table);
+3 -1
tools/testing/selftests/drivers/net/mlxsw/port_scale.sh
··· 7 7 8 8 PORT_NUM_NETIFS=0 9 9 10 + declare -a unsplit 11 + 10 12 port_setup_prepare() 11 13 { 12 14 : ··· 22 20 devlink port unsplit $port 23 21 check_err $? "Did not unsplit $netdev" 24 22 done 23 + unsplit=() 25 24 } 26 25 27 26 split_all_ports() 28 27 { 29 28 local should_fail=$1; shift 30 - local -a unsplit 31 29 32 30 # Loop over the splittable netdevs and create tuples of netdev along 33 31 # with its width. For example:
+35 -34
tools/testing/selftests/drivers/net/mlxsw/qos_headroom.sh
··· 29 29 30 30 get_prio_pg() 31 31 { 32 - __mlnx_qos -i $swp | sed -n '/^PFC/,/^[^[:space:]]/p' | 33 - grep buffer | sed 's/ \+/ /g' | cut -d' ' -f 2- 32 + # Produces a string of numbers "<B0> <B1> ... <B7> ", where BX is number 33 + # of buffer that priority X is mapped to. 34 + dcb -j buffer show dev $swp | 35 + jq -r '[.prio_buffer | .[] | tostring + " "] | add' 34 36 } 35 37 36 38 get_prio_pfc() 37 39 { 38 - __mlnx_qos -i $swp | sed -n '/^PFC/,/^[^[:space:]]/p' | 39 - grep enabled | sed 's/ \+/ /g' | cut -d' ' -f 2- 40 + # Produces a string of numbers "<P0> <P1> ... <P7> ", where PX denotes 41 + # whether priority X has PFC enabled (the value is 1) or disabled (0). 42 + dcb -j pfc show dev $swp | 43 + jq -r '[.prio_pfc | .[] | if . then "1 " else "0 " end] | add' 40 44 } 41 45 42 46 get_prio_tc() 43 47 { 44 - __mlnx_qos -i $swp | sed -n '/^tc/,$p' | 45 - awk '/^tc/ { TC = $2 } 46 - /priority:/ { PRIO[$2]=TC } 47 - END { 48 - for (i in PRIO) 49 - printf("%d ", PRIO[i]) 50 - }' 48 + # Produces a string of numbers "<T0> <T1> ... <T7> ", where TC is number 49 + # of TC that priority X is mapped to. 50 + dcb -j ets show dev $swp | 51 + jq -r '[.prio_tc | .[] | tostring + " "] | add' 51 52 } 52 53 53 54 get_buf_size() 54 55 { 55 56 local idx=$1; shift 56 57 57 - __mlnx_qos -i $swp | grep Receive | sed 's/.*: //' | cut -d, -f $((idx + 1)) 58 + dcb -j buffer show dev $swp | jq ".buffer_size[$idx]" 58 59 } 59 60 60 61 get_tot_size() 61 62 { 62 - __mlnx_qos -i $swp | grep Receive | sed 's/.*total_size=//' 63 + dcb -j buffer show dev $swp | jq '.total_size' 63 64 } 64 65 65 66 check_prio_pg() ··· 122 121 { 123 122 RET=0 124 123 125 - __mlnx_qos -i $swp --prio_tc=0,2,4,6,1,3,5,7 > /dev/null 124 + dcb ets set dev $swp prio-tc 0:0 1:2 2:4 3:6 4:1 5:3 6:5 7:7 126 125 127 126 check_prio_pg "0 2 4 6 1 3 5 7 " 128 127 check_prio_tc "0 2 4 6 1 3 5 7 " 129 128 check_prio_pfc "0 0 0 0 0 0 0 0 " 130 129 131 - __mlnx_qos -i $swp --prio_tc=0,0,0,0,0,0,0,0 > /dev/null 130 + dcb ets set dev $swp prio-tc all:0 132 131 133 132 check_prio_pg "0 0 0 0 0 0 0 0 " 134 133 check_prio_tc "0 0 0 0 0 0 0 0 " 135 134 136 - __mlnx_qos -i $swp --prio2buffer=1,3,5,7,0,2,4,6 &> /dev/null 135 + dcb buffer set dev $swp prio-buffer 0:1 1:3 2:5 3:7 4:0 5:2 6:4 7:6 2>/dev/null 137 136 check_fail $? "prio2buffer accepted in DCB mode" 138 137 139 138 log_test "Configuring headroom through ETS" ··· 175 174 { 176 175 RET=0 177 176 178 - __mlnx_qos -i $swp --prio_tc=0,0,0,0,0,1,2,3 > /dev/null 177 + dcb ets set dev $swp prio-tc all:0 5:1 6:2 7:3 179 178 180 179 local buf0size=$(get_buf_size 0) 181 180 local buf1size=$(get_buf_size 1) ··· 194 193 195 194 RET=0 196 195 197 - __mlnx_qos -i $swp --pfc=0,0,0,0,0,1,1,1 --cable_len=0 > /dev/null 196 + dcb pfc set dev $swp prio-pfc all:off 5:on 6:on 7:on delay 0 198 197 199 198 check_prio_pg "0 0 0 0 0 1 2 3 " 200 199 check_prio_pfc "0 0 0 0 0 1 1 1 " ··· 211 210 212 211 RET=0 213 212 214 - __mlnx_qos -i $swp --pfc=0,0,0,0,0,1,1,1 --cable_len=1000 > /dev/null 213 + dcb pfc set dev $swp delay 1000 215 214 216 215 check_buf_size 0 "== $buf0size" 217 216 check_buf_size 1 "> $buf1size" ··· 222 221 223 222 RET=0 224 223 225 - __mlnx_qos -i $swp --pfc=0,0,0,0,0,0,0,0 --cable_len=0 > /dev/null 226 - __mlnx_qos -i $swp --prio_tc=0,0,0,0,0,0,0,0 > /dev/null 224 + dcb pfc set dev $swp prio-pfc all:off delay 0 225 + dcb ets set dev $swp prio-tc all:0 227 226 228 227 check_prio_pg "0 0 0 0 0 0 0 0 " 229 228 check_prio_tc "0 0 0 0 0 0 0 0 " ··· 243 242 { 244 243 RET=0 245 244 246 - __mlnx_qos -i $swp --prio_tc=0,1,2,3,4,5,6,7 > /dev/null 245 + dcb ets set dev $swp prio-tc 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 247 246 check_prio_pg "0 1 2 3 4 5 6 7 " 248 247 249 248 tc qdisc replace dev $swp root handle 1: bfifo limit 1.5M 250 249 check_prio_pg "0 0 0 0 0 0 0 0 " 251 250 252 - __mlnx_qos -i $swp --prio2buffer=1,3,5,7,0,2,4,6 > /dev/null 251 + dcb buffer set dev $swp prio-buffer 0:1 1:3 2:5 3:7 4:0 5:2 6:4 7:6 253 252 check_prio_pg "1 3 5 7 0 2 4 6 " 254 253 255 254 tc qdisc delete dev $swp root ··· 257 256 258 257 # Clean up. 259 258 tc qdisc replace dev $swp root handle 1: bfifo limit 1.5M 260 - __mlnx_qos -i $swp --prio2buffer=0,0,0,0,0,0,0,0 > /dev/null 259 + dcb buffer set dev $swp prio-buffer all:0 261 260 tc qdisc delete dev $swp root 262 - __mlnx_qos -i $swp --prio_tc=0,0,0,0,0,0,0,0 > /dev/null 261 + dcb ets set dev $swp prio-tc all:0 263 262 264 263 log_test "TC: priomap" 265 264 } ··· 271 270 272 271 RET=0 273 272 274 - __mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 &> /dev/null 273 + dcb buffer set dev $swp buffer-size all:0 0:$size 2>/dev/null 275 274 check_fail $? "buffer_size should fail before qdisc is added" 276 275 277 276 tc qdisc replace dev $swp root handle 1: bfifo limit 1.5M 278 277 279 - __mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 > /dev/null 278 + dcb buffer set dev $swp buffer-size all:0 0:$size 280 279 check_err $? "buffer_size should pass after qdisc is added" 281 280 check_buf_size 0 "== $size" "set size: " 282 281 ··· 284 283 check_buf_size 0 "== $size" "set MTU: " 285 284 mtu_restore $swp 286 285 287 - __mlnx_qos -i $swp --buffer_size=0,0,0,0,0,0,0,0 > /dev/null 286 + dcb buffer set dev $swp buffer-size all:0 288 287 289 288 # After replacing the qdisc for the same kind, buffer_size still has to 290 289 # work. 291 290 tc qdisc replace dev $swp root handle 1: bfifo limit 1M 292 291 293 - __mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 > /dev/null 292 + dcb buffer set dev $swp buffer-size all:0 0:$size 294 293 check_buf_size 0 "== $size" "post replace, set size: " 295 294 296 - __mlnx_qos -i $swp --buffer_size=0,0,0,0,0,0,0,0 > /dev/null 295 + dcb buffer set dev $swp buffer-size all:0 297 296 298 297 # Likewise after replacing for a different kind. 299 298 tc qdisc replace dev $swp root handle 2: prio bands 8 300 299 301 - __mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 > /dev/null 300 + dcb buffer set dev $swp buffer-size all:0 0:$size 302 301 check_buf_size 0 "== $size" "post replace different kind, set size: " 303 302 304 303 tc qdisc delete dev $swp root 305 304 306 - __mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 &> /dev/null 305 + dcb buffer set dev $swp buffer-size all:0 0:$size 2>/dev/null 307 306 check_fail $? "buffer_size should fail after qdisc is deleted" 308 307 309 308 log_test "TC: buffer size" ··· 364 363 tc qdisc replace dev $swp root handle 1: bfifo limit 1.5M 365 364 test_int_buf "TC: " 366 365 367 - __mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 > /dev/null 366 + dcb buffer set dev $swp buffer-size all:0 0:$size 368 367 test_int_buf "TC+buffsize: " 369 368 370 - __mlnx_qos -i $swp --buffer_size=0,0,0,0,0,0,0,0 > /dev/null 369 + dcb buffer set dev $swp buffer-size all:0 371 370 tc qdisc delete dev $swp root 372 371 } 373 372
-14
tools/testing/selftests/drivers/net/mlxsw/qos_lib.sh
··· 82 82 fi 83 83 fi 84 84 } 85 - 86 - __mlnx_qos() 87 - { 88 - local err 89 - 90 - mlnx_qos "$@" 2>/dev/null 91 - err=$? 92 - 93 - if ((err)); then 94 - echo "Error ($err) in mlnx_qos $@" >/dev/stderr 95 - fi 96 - 97 - return $err 98 - }
+12 -12
tools/testing/selftests/drivers/net/mlxsw/qos_pfc.sh
··· 171 171 # assignment. 172 172 tc qdisc replace dev $swp1 root handle 1: \ 173 173 ets bands 8 strict 8 priomap 7 6 174 - __mlnx_qos -i $swp1 --prio2buffer=0,1,0,0,0,0,0,0 >/dev/null 174 + dcb buffer set dev $swp1 prio-buffer all:0 1:1 175 175 176 176 # $swp2 177 177 # ----- ··· 209 209 # the lossless prio into a buffer of its own. Don't bother with buffer 210 210 # sizes though, there is not going to be any pressure in the "backward" 211 211 # direction. 212 - __mlnx_qos -i $swp3 --prio2buffer=0,1,0,0,0,0,0,0 >/dev/null 213 - __mlnx_qos -i $swp3 --pfc=0,1,0,0,0,0,0,0 >/dev/null 212 + dcb buffer set dev $swp3 prio-buffer all:0 1:1 213 + dcb pfc set dev $swp3 prio-pfc all:off 1:on 214 214 215 215 # $swp4 216 216 # ----- ··· 226 226 # Configure qdisc so that we can hand-tune headroom. 227 227 tc qdisc replace dev $swp4 root handle 1: \ 228 228 ets bands 8 strict 8 priomap 7 6 229 - __mlnx_qos -i $swp4 --prio2buffer=0,1,0,0,0,0,0,0 >/dev/null 230 - __mlnx_qos -i $swp4 --pfc=0,1,0,0,0,0,0,0 >/dev/null 229 + dcb buffer set dev $swp4 prio-buffer all:0 1:1 230 + dcb pfc set dev $swp4 prio-pfc all:off 1:on 231 231 # PG0 will get autoconfigured to Xoff, give PG1 arbitrarily 100K, which 232 232 # is (-2*MTU) about 80K of delay provision. 233 - __mlnx_qos -i $swp4 --buffer_size=0,$_100KB,0,0,0,0,0,0 >/dev/null 233 + dcb buffer set dev $swp4 buffer-size all:0 1:$_100KB 234 234 235 235 # bridges 236 236 # ------- ··· 273 273 # $swp4 274 274 # ----- 275 275 276 - __mlnx_qos -i $swp4 --buffer_size=0,0,0,0,0,0,0,0 >/dev/null 277 - __mlnx_qos -i $swp4 --pfc=0,0,0,0,0,0,0,0 >/dev/null 278 - __mlnx_qos -i $swp4 --prio2buffer=0,0,0,0,0,0,0,0 >/dev/null 276 + dcb buffer set dev $swp4 buffer-size all:0 277 + dcb pfc set dev $swp4 prio-pfc all:off 278 + dcb buffer set dev $swp4 prio-buffer all:0 279 279 tc qdisc del dev $swp4 root 280 280 281 281 devlink_tc_bind_pool_th_restore $swp4 1 ingress ··· 288 288 # $swp3 289 289 # ----- 290 290 291 - __mlnx_qos -i $swp3 --pfc=0,0,0,0,0,0,0,0 >/dev/null 292 - __mlnx_qos -i $swp3 --prio2buffer=0,0,0,0,0,0,0,0 >/dev/null 291 + dcb pfc set dev $swp3 prio-pfc all:off 292 + dcb buffer set dev $swp3 prio-buffer all:0 293 293 tc qdisc del dev $swp3 root 294 294 295 295 devlink_tc_bind_pool_th_restore $swp3 1 egress ··· 315 315 # $swp1 316 316 # ----- 317 317 318 - __mlnx_qos -i $swp1 --prio2buffer=0,0,0,0,0,0,0,0 >/dev/null 318 + dcb buffer set dev $swp1 prio-buffer all:0 319 319 tc qdisc del dev $swp1 root 320 320 321 321 devlink_tc_bind_pool_th_restore $swp1 1 ingress
+6 -6
tools/testing/selftests/drivers/net/mlxsw/tc_sample.sh
··· 234 234 235 235 psample_capture_start 236 236 237 - ip vrf exec v$h1 $MZ $h1 -c 3200 -d 1msec -p 64 -A 192.0.2.1 \ 237 + ip vrf exec v$h1 $MZ $h1 -c 320000 -d 100usec -p 64 -A 192.0.2.1 \ 238 238 -B $dip -t udp dp=52768,sp=42768 -q 239 239 240 240 psample_capture_stop 241 241 242 242 pkts=$(grep -e "group 1 " $CAPTURE_FILE | wc -l) 243 - pct=$((100 * (pkts - 100) / 100)) 243 + pct=$((100 * (pkts - 10000) / 10000)) 244 244 (( -25 <= pct && pct <= 25)) 245 - check_err $? "Expected 100 packets, got $pkts packets, which is $pct% off. Required accuracy is +-25%" 245 + check_err $? "Expected 10000 packets, got $pkts packets, which is $pct% off. Required accuracy is +-25%" 246 246 247 247 log_test "tc sample rate ($desc)" 248 248 ··· 587 587 588 588 psample_capture_start 589 589 590 - ip vrf exec v$h1 $MZ $h1 -c 3200 -d 1msec -p 64 -A 192.0.2.1 \ 590 + ip vrf exec v$h1 $MZ $h1 -c 320000 -d 100usec -p 64 -A 192.0.2.1 \ 591 591 -B 198.51.100.1 -t udp dp=52768,sp=42768 -q 592 592 593 593 psample_capture_stop 594 594 595 595 pkts=$(grep -e "group 1 " $CAPTURE_FILE | wc -l) 596 - pct=$((100 * (pkts - 100) / 100)) 596 + pct=$((100 * (pkts - 10000) / 10000)) 597 597 (( -25 <= pct && pct <= 25)) 598 - check_err $? "Expected 100 packets, got $pkts packets, which is $pct% off. Required accuracy is +-25%" 598 + check_err $? "Expected 10000 packets, got $pkts packets, which is $pct% off. Required accuracy is +-25%" 599 599 600 600 # Setup a filter that should not match any packet and make sure packets 601 601 # are not sampled.