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>
This commit is contained in:
David S. Miller 2021-05-17 15:15:47 -07:00
commit 609c8ae879
19 changed files with 83 additions and 2402 deletions

View File

@ -49,28 +49,6 @@ config MLXSW_I2C
To compile this driver as a module, choose M here: the
module will be called mlxsw_i2c.
config MLXSW_SWITCHIB
tristate "Mellanox Technologies SwitchIB and SwitchIB-2 support"
depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV
default m
help
This driver supports Mellanox Technologies SwitchIB and SwitchIB-2
Infiniband Switch ASICs.
To compile this driver as a module, choose M here: the
module will be called mlxsw_switchib.
config MLXSW_SWITCHX2
tristate "Mellanox Technologies SwitchX-2 support"
depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV
default m
help
This driver supports Mellanox Technologies SwitchX-2 Ethernet
Switch ASICs.
To compile this driver as a module, choose M here: the
module will be called mlxsw_switchx2.
config MLXSW_SPECTRUM
tristate "Mellanox Technologies Spectrum family support"
depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV && VLAN_8021Q

View File

@ -8,10 +8,6 @@ obj-$(CONFIG_MLXSW_PCI) += mlxsw_pci.o
mlxsw_pci-objs := pci.o
obj-$(CONFIG_MLXSW_I2C) += mlxsw_i2c.o
mlxsw_i2c-objs := i2c.o
obj-$(CONFIG_MLXSW_SWITCHIB) += mlxsw_switchib.o
mlxsw_switchib-objs := switchib.o
obj-$(CONFIG_MLXSW_SWITCHX2) += mlxsw_switchx2.o
mlxsw_switchx2-objs := switchx2.o
obj-$(CONFIG_MLXSW_SPECTRUM) += mlxsw_spectrum.o
mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \
spectrum_switchdev.o spectrum_router.o \

View File

@ -630,7 +630,7 @@ static int mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core,
struct sk_buff *skb;
int err;
skb = skb_copy(trans->tx_skb, GFP_KERNEL);
skb = skb_clone(trans->tx_skb, GFP_KERNEL);
if (!skb)
return -ENOMEM;

View File

@ -1,9 +0,0 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
/* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
#ifndef _MLXSW_IB_H
#define _MLXSW_IB_H
#define MLXSW_IB_DEFAULT_MTU 4096
#endif /* _MLXSW_IB_H */

View File

@ -234,6 +234,7 @@ static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u8 local_port)
static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u8 local_port,
u8 *last_module)
{
unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core);
u8 module, width;
int err;
@ -249,6 +250,9 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u8 local_port,
if (module == *last_module)
return 0;
*last_module = module;
if (WARN_ON_ONCE(module >= max_ports))
return -EINVAL;
mlxsw_m->module_to_port[module] = ++mlxsw_m->max_ports;
return 0;

View File

@ -1426,11 +1426,6 @@ static int mlxsw_pci_sys_ready_wait(struct mlxsw_pci *mlxsw_pci,
unsigned long end;
u32 val;
if (id->device == PCI_DEVICE_ID_MELLANOX_SWITCHX2) {
msleep(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS);
return 0;
}
/* We must wait for the HW to become responsive. */
msleep(MLXSW_PCI_SW_RESET_WAIT_MSECS);

View File

@ -6,12 +6,9 @@
#include <linux/pci.h>
#define PCI_DEVICE_ID_MELLANOX_SWITCHX2 0xc738
#define PCI_DEVICE_ID_MELLANOX_SPECTRUM 0xcb84
#define PCI_DEVICE_ID_MELLANOX_SPECTRUM2 0xcf6c
#define PCI_DEVICE_ID_MELLANOX_SPECTRUM3 0xcf70
#define PCI_DEVICE_ID_MELLANOX_SWITCHIB 0xcb20
#define PCI_DEVICE_ID_MELLANOX_SWITCHIB2 0xcf08
#if IS_ENABLED(CONFIG_MLXSW_PCI)

View File

@ -2125,9 +2125,14 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
struct mlxsw_sp *mlxsw_sp = priv;
struct mlxsw_sp_port *mlxsw_sp_port;
enum mlxsw_reg_pude_oper_status status;
unsigned int max_ports;
u8 local_port;
max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
local_port = mlxsw_reg_pude_local_port_get(pude_pl);
if (WARN_ON_ONCE(local_port >= max_ports))
return;
mlxsw_sp_port = mlxsw_sp->ports[local_port];
if (!mlxsw_sp_port)
return;

View File

@ -364,7 +364,7 @@ static u16 mlxsw_sp_hdroom_buf_delay_get(const struct mlxsw_sp *mlxsw_sp,
static u32 mlxsw_sp_hdroom_int_buf_size_get(struct mlxsw_sp *mlxsw_sp, int mtu, u32 speed)
{
u32 buffsize = mlxsw_sp->sb_ops->int_buf_size_get(speed, mtu);
u32 buffsize = mlxsw_sp->sb_ops->int_buf_size_get(mtu, speed);
return mlxsw_sp_bytes_cells(mlxsw_sp, buffsize) + 1;
}
@ -388,8 +388,8 @@ void mlxsw_sp_hdroom_bufs_reset_sizes(struct mlxsw_sp_port *mlxsw_sp_port,
int i;
/* Internal buffer. */
reserve_cells = mlxsw_sp_hdroom_int_buf_size_get(mlxsw_sp, mlxsw_sp_port->max_speed,
mlxsw_sp_port->max_mtu);
reserve_cells = mlxsw_sp_hdroom_int_buf_size_get(mlxsw_sp, mlxsw_sp_port->max_mtu,
mlxsw_sp_port->max_speed);
reserve_cells = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, reserve_cells);
hdroom->int_buf.reserve_cells = reserve_cells;

View File

@ -568,10 +568,13 @@ void mlxsw_sp1_ptp_got_timestamp(struct mlxsw_sp *mlxsw_sp, bool ingress,
u8 domain_number, u16 sequence_id,
u64 timestamp)
{
unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
struct mlxsw_sp_port *mlxsw_sp_port;
struct mlxsw_sp1_ptp_key key;
u8 types;
if (WARN_ON_ONCE(local_port >= max_ports))
return;
mlxsw_sp_port = mlxsw_sp->ports[local_port];
if (!mlxsw_sp_port)
return;

View File

@ -2282,6 +2282,7 @@ static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
char *rauhtd_pl,
int ent_index)
{
u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
struct net_device *dev;
struct neighbour *n;
__be32 dipn;
@ -2290,6 +2291,8 @@ static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl, ent_index, &rif, &dip);
if (WARN_ON_ONCE(rif >= max_rifs))
return;
if (!mlxsw_sp->router->rifs[rif]) {
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n");
return;
@ -3841,8 +3844,8 @@ mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
bool offload_change = false;
u32 adj_index;
bool old_adj_index_valid;
int i, err2, err = 0;
u32 old_adj_index;
int i, err2, err;
if (!nhgi->gateway)
return mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
@ -3872,11 +3875,13 @@ mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
return 0;
}
mlxsw_sp_nexthop_group_normalize(nhgi);
if (!nhgi->sum_norm_weight)
if (!nhgi->sum_norm_weight) {
/* No neigh of this group is connected so we just set
* the trap and let everthing flow through kernel.
*/
err = 0;
goto set_trap;
}
ecmp_size = nhgi->sum_norm_weight;
err = mlxsw_sp_fix_adj_grp_size(mlxsw_sp, &ecmp_size);

View File

@ -2520,6 +2520,7 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
char *sfn_pl, int rec_index,
bool adding)
{
unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
struct mlxsw_sp_bridge_device *bridge_device;
struct mlxsw_sp_bridge_port *bridge_port;
@ -2532,6 +2533,9 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
int err;
mlxsw_reg_sfn_mac_unpack(sfn_pl, rec_index, mac, &fid, &local_port);
if (WARN_ON_ONCE(local_port >= max_ports))
return;
mlxsw_sp_port = mlxsw_sp->ports[local_port];
if (!mlxsw_sp_port) {
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect local port in FDB notification\n");

View File

@ -1,595 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
/* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/skbuff.h>
#include <linux/if_vlan.h>
#include <net/switchdev.h>
#include "pci.h"
#include "core.h"
#include "reg.h"
#include "port.h"
#include "trap.h"
#include "txheader.h"
#include "ib.h"
static const char mlxsw_sib_driver_name[] = "mlxsw_switchib";
static const char mlxsw_sib2_driver_name[] = "mlxsw_switchib2";
struct mlxsw_sib_port;
struct mlxsw_sib {
struct mlxsw_sib_port **ports;
struct mlxsw_core *core;
const struct mlxsw_bus_info *bus_info;
u8 hw_id[ETH_ALEN];
};
struct mlxsw_sib_port {
struct mlxsw_sib *mlxsw_sib;
u8 local_port;
struct {
u8 module;
} mapping;
};
/* tx_v1_hdr_version
* Tx header version.
* Must be set to 1.
*/
MLXSW_ITEM32(tx_v1, hdr, version, 0x00, 28, 4);
/* tx_v1_hdr_ctl
* Packet control type.
* 0 - Ethernet control (e.g. EMADs, LACP)
* 1 - Ethernet data
*/
MLXSW_ITEM32(tx_v1, hdr, ctl, 0x00, 26, 2);
/* tx_v1_hdr_proto
* Packet protocol type. Must be set to 1 (Ethernet).
*/
MLXSW_ITEM32(tx_v1, hdr, proto, 0x00, 21, 3);
/* tx_v1_hdr_swid
* Switch partition ID. Must be set to 0.
*/
MLXSW_ITEM32(tx_v1, hdr, swid, 0x00, 12, 3);
/* tx_v1_hdr_control_tclass
* Indicates if the packet should use the control TClass and not one
* of the data TClasses.
*/
MLXSW_ITEM32(tx_v1, hdr, control_tclass, 0x00, 6, 1);
/* tx_v1_hdr_port_mid
* Destination local port for unicast packets.
* Destination multicast ID for multicast packets.
*
* Control packets are directed to a specific egress port, while data
* packets are transmitted through the CPU port (0) into the switch partition,
* where forwarding rules are applied.
*/
MLXSW_ITEM32(tx_v1, hdr, port_mid, 0x04, 16, 16);
/* tx_v1_hdr_type
* 0 - Data packets
* 6 - Control packets
*/
MLXSW_ITEM32(tx_v1, hdr, type, 0x0C, 0, 4);
static void
mlxsw_sib_tx_v1_hdr_construct(struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info)
{
char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN);
memset(txhdr, 0, MLXSW_TXHDR_LEN);
mlxsw_tx_v1_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_1);
mlxsw_tx_v1_hdr_ctl_set(txhdr, MLXSW_TXHDR_ETH_CTL);
mlxsw_tx_v1_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH);
mlxsw_tx_v1_hdr_swid_set(txhdr, 0);
mlxsw_tx_v1_hdr_control_tclass_set(txhdr, 1);
mlxsw_tx_v1_hdr_port_mid_set(txhdr, tx_info->local_port);
mlxsw_tx_v1_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL);
}
static int mlxsw_sib_hw_id_get(struct mlxsw_sib *mlxsw_sib)
{
char spad_pl[MLXSW_REG_SPAD_LEN] = {0};
int err;
err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(spad), spad_pl);
if (err)
return err;
mlxsw_reg_spad_base_mac_memcpy_from(spad_pl, mlxsw_sib->hw_id);
return 0;
}
static int
mlxsw_sib_port_admin_status_set(struct mlxsw_sib_port *mlxsw_sib_port,
bool is_up)
{
struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
char paos_pl[MLXSW_REG_PAOS_LEN];
mlxsw_reg_paos_pack(paos_pl, mlxsw_sib_port->local_port,
is_up ? MLXSW_PORT_ADMIN_STATUS_UP :
MLXSW_PORT_ADMIN_STATUS_DOWN);
return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(paos), paos_pl);
}
static int mlxsw_sib_port_mtu_set(struct mlxsw_sib_port *mlxsw_sib_port,
u16 mtu)
{
struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
char pmtu_pl[MLXSW_REG_PMTU_LEN];
int max_mtu;
int err;
mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sib_port->local_port, 0);
err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(pmtu), pmtu_pl);
if (err)
return err;
max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl);
if (mtu > max_mtu)
return -EINVAL;
mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sib_port->local_port, mtu);
return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(pmtu), pmtu_pl);
}
static int mlxsw_sib_port_set(struct mlxsw_sib_port *mlxsw_sib_port, u8 port)
{
struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
char plib_pl[MLXSW_REG_PLIB_LEN] = {0};
int err;
mlxsw_reg_plib_local_port_set(plib_pl, mlxsw_sib_port->local_port);
mlxsw_reg_plib_ib_port_set(plib_pl, port);
err = mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(plib), plib_pl);
return err;
}
static int mlxsw_sib_port_swid_set(struct mlxsw_sib_port *mlxsw_sib_port,
u8 swid)
{
struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
char pspa_pl[MLXSW_REG_PSPA_LEN];
mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sib_port->local_port);
return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(pspa), pspa_pl);
}
static int mlxsw_sib_port_module_info_get(struct mlxsw_sib *mlxsw_sib,
u8 local_port, u8 *p_module,
u8 *p_width)
{
char pmlp_pl[MLXSW_REG_PMLP_LEN];
int err;
mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(pmlp), pmlp_pl);
if (err)
return err;
*p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
*p_width = mlxsw_reg_pmlp_width_get(pmlp_pl);
return 0;
}
static int mlxsw_sib_port_speed_set(struct mlxsw_sib_port *mlxsw_sib_port,
u16 speed, u16 width)
{
struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
char ptys_pl[MLXSW_REG_PTYS_LEN];
mlxsw_reg_ptys_ib_pack(ptys_pl, mlxsw_sib_port->local_port, speed,
width);
return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(ptys), ptys_pl);
}
static bool mlxsw_sib_port_created(struct mlxsw_sib *mlxsw_sib, u8 local_port)
{
return mlxsw_sib->ports[local_port] != NULL;
}
static int __mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port,
u8 module, u8 width)
{
struct mlxsw_sib_port *mlxsw_sib_port;
int err;
mlxsw_sib_port = kzalloc(sizeof(*mlxsw_sib_port), GFP_KERNEL);
if (!mlxsw_sib_port)
return -ENOMEM;
mlxsw_sib_port->mlxsw_sib = mlxsw_sib;
mlxsw_sib_port->local_port = local_port;
mlxsw_sib_port->mapping.module = module;
err = mlxsw_sib_port_swid_set(mlxsw_sib_port, 0);
if (err) {
dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set SWID\n",
mlxsw_sib_port->local_port);
goto err_port_swid_set;
}
/* Expose the IB port number as it's front panel name */
err = mlxsw_sib_port_set(mlxsw_sib_port, module + 1);
if (err) {
dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set IB port\n",
mlxsw_sib_port->local_port);
goto err_port_ib_set;
}
/* Supports all speeds from SDR to FDR (bitmask) and support bus width
* of 1x, 2x and 4x (3 bits bitmask)
*/
err = mlxsw_sib_port_speed_set(mlxsw_sib_port,
MLXSW_REG_PTYS_IB_SPEED_EDR - 1,
BIT(3) - 1);
if (err) {
dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set speed\n",
mlxsw_sib_port->local_port);
goto err_port_speed_set;
}
/* Change to the maximum MTU the device supports, the SMA will take
* care of the active MTU
*/
err = mlxsw_sib_port_mtu_set(mlxsw_sib_port, MLXSW_IB_DEFAULT_MTU);
if (err) {
dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set MTU\n",
mlxsw_sib_port->local_port);
goto err_port_mtu_set;
}
err = mlxsw_sib_port_admin_status_set(mlxsw_sib_port, true);
if (err) {
dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to change admin state to UP\n",
mlxsw_sib_port->local_port);
goto err_port_admin_set;
}
mlxsw_core_port_ib_set(mlxsw_sib->core, mlxsw_sib_port->local_port,
mlxsw_sib_port);
mlxsw_sib->ports[local_port] = mlxsw_sib_port;
return 0;
err_port_admin_set:
err_port_mtu_set:
err_port_speed_set:
err_port_ib_set:
mlxsw_sib_port_swid_set(mlxsw_sib_port, MLXSW_PORT_SWID_DISABLED_PORT);
err_port_swid_set:
kfree(mlxsw_sib_port);
return err;
}
static int mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port,
u8 module, u8 width)
{
int err;
err = mlxsw_core_port_init(mlxsw_sib->core, local_port,
module + 1, false, 0, false, 0,
mlxsw_sib->hw_id, sizeof(mlxsw_sib->hw_id));
if (err) {
dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to init core port\n",
local_port);
return err;
}
err = __mlxsw_sib_port_create(mlxsw_sib, local_port, module, width);
if (err)
goto err_port_create;
return 0;
err_port_create:
mlxsw_core_port_fini(mlxsw_sib->core, local_port);
return err;
}
static void __mlxsw_sib_port_remove(struct mlxsw_sib *mlxsw_sib, u8 local_port)
{
struct mlxsw_sib_port *mlxsw_sib_port = mlxsw_sib->ports[local_port];
mlxsw_core_port_clear(mlxsw_sib->core, local_port, mlxsw_sib);
mlxsw_sib->ports[local_port] = NULL;
mlxsw_sib_port_admin_status_set(mlxsw_sib_port, false);
mlxsw_sib_port_swid_set(mlxsw_sib_port, MLXSW_PORT_SWID_DISABLED_PORT);
kfree(mlxsw_sib_port);
}
static void mlxsw_sib_port_remove(struct mlxsw_sib *mlxsw_sib, u8 local_port)
{
__mlxsw_sib_port_remove(mlxsw_sib, local_port);
mlxsw_core_port_fini(mlxsw_sib->core, local_port);
}
static void mlxsw_sib_ports_remove(struct mlxsw_sib *mlxsw_sib)
{
int i;
for (i = 1; i < MLXSW_PORT_MAX_IB_PORTS; i++)
if (mlxsw_sib_port_created(mlxsw_sib, i))
mlxsw_sib_port_remove(mlxsw_sib, i);
kfree(mlxsw_sib->ports);
}
static int mlxsw_sib_ports_create(struct mlxsw_sib *mlxsw_sib)
{
size_t alloc_size;
u8 module, width;
int i;
int err;
alloc_size = sizeof(struct mlxsw_sib_port *) * MLXSW_PORT_MAX_IB_PORTS;
mlxsw_sib->ports = kzalloc(alloc_size, GFP_KERNEL);
if (!mlxsw_sib->ports)
return -ENOMEM;
for (i = 1; i < MLXSW_PORT_MAX_IB_PORTS; i++) {
err = mlxsw_sib_port_module_info_get(mlxsw_sib, i, &module,
&width);
if (err)
goto err_port_module_info_get;
if (!width)
continue;
err = mlxsw_sib_port_create(mlxsw_sib, i, module, width);
if (err)
goto err_port_create;
}
return 0;
err_port_create:
err_port_module_info_get:
for (i--; i >= 1; i--)
if (mlxsw_sib_port_created(mlxsw_sib, i))
mlxsw_sib_port_remove(mlxsw_sib, i);
kfree(mlxsw_sib->ports);
return err;
}
static void
mlxsw_sib_pude_ib_event_func(struct mlxsw_sib_port *mlxsw_sib_port,
enum mlxsw_reg_pude_oper_status status)
{
if (status == MLXSW_PORT_OPER_STATUS_UP)
pr_info("ib link for port %d - up\n",
mlxsw_sib_port->mapping.module + 1);
else
pr_info("ib link for port %d - down\n",
mlxsw_sib_port->mapping.module + 1);
}
static void mlxsw_sib_pude_event_func(const struct mlxsw_reg_info *reg,
char *pude_pl, void *priv)
{
struct mlxsw_sib *mlxsw_sib = priv;
struct mlxsw_sib_port *mlxsw_sib_port;
enum mlxsw_reg_pude_oper_status status;
u8 local_port;
local_port = mlxsw_reg_pude_local_port_get(pude_pl);
mlxsw_sib_port = mlxsw_sib->ports[local_port];
if (!mlxsw_sib_port) {
dev_warn(mlxsw_sib->bus_info->dev, "Port %d: Link event received for non-existent port\n",
local_port);
return;
}
status = mlxsw_reg_pude_oper_status_get(pude_pl);
mlxsw_sib_pude_ib_event_func(mlxsw_sib_port, status);
}
static const struct mlxsw_listener mlxsw_sib_listener[] = {
MLXSW_EVENTL(mlxsw_sib_pude_event_func, PUDE, EMAD),
};
static int mlxsw_sib_taps_init(struct mlxsw_sib *mlxsw_sib)
{
int i;
int err;
for (i = 0; i < ARRAY_SIZE(mlxsw_sib_listener); i++) {
err = mlxsw_core_trap_register(mlxsw_sib->core,
&mlxsw_sib_listener[i],
mlxsw_sib);
if (err)
goto err_rx_listener_register;
}
return 0;
err_rx_listener_register:
for (i--; i >= 0; i--) {
mlxsw_core_trap_unregister(mlxsw_sib->core,
&mlxsw_sib_listener[i],
mlxsw_sib);
}
return err;
}
static void mlxsw_sib_traps_fini(struct mlxsw_sib *mlxsw_sib)
{
int i;
for (i = 0; i < ARRAY_SIZE(mlxsw_sib_listener); i++) {
mlxsw_core_trap_unregister(mlxsw_sib->core,
&mlxsw_sib_listener[i], mlxsw_sib);
}
}
static int mlxsw_sib_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
{
char htgt_pl[MLXSW_REG_HTGT_LEN];
mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
MLXSW_REG_HTGT_INVALID_POLICER,
MLXSW_REG_HTGT_DEFAULT_PRIORITY,
MLXSW_REG_HTGT_DEFAULT_TC);
mlxsw_reg_htgt_swid_set(htgt_pl, MLXSW_PORT_SWID_ALL_SWIDS);
mlxsw_reg_htgt_local_path_rdq_set(htgt_pl,
MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SIB_EMAD);
return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
}
static int mlxsw_sib_init(struct mlxsw_core *mlxsw_core,
const struct mlxsw_bus_info *mlxsw_bus_info,
struct netlink_ext_ack *extack)
{
struct mlxsw_sib *mlxsw_sib = mlxsw_core_driver_priv(mlxsw_core);
int err;
mlxsw_sib->core = mlxsw_core;
mlxsw_sib->bus_info = mlxsw_bus_info;
err = mlxsw_sib_hw_id_get(mlxsw_sib);
if (err) {
dev_err(mlxsw_sib->bus_info->dev, "Failed to get switch HW ID\n");
return err;
}
err = mlxsw_sib_ports_create(mlxsw_sib);
if (err) {
dev_err(mlxsw_sib->bus_info->dev, "Failed to create ports\n");
return err;
}
err = mlxsw_sib_taps_init(mlxsw_sib);
if (err) {
dev_err(mlxsw_sib->bus_info->dev, "Failed to set traps\n");
goto err_traps_init_err;
}
return 0;
err_traps_init_err:
mlxsw_sib_ports_remove(mlxsw_sib);
return err;
}
static void mlxsw_sib_fini(struct mlxsw_core *mlxsw_core)
{
struct mlxsw_sib *mlxsw_sib = mlxsw_core_driver_priv(mlxsw_core);
mlxsw_sib_traps_fini(mlxsw_sib);
mlxsw_sib_ports_remove(mlxsw_sib);
}
static const struct mlxsw_config_profile mlxsw_sib_config_profile = {
.used_max_system_port = 1,
.max_system_port = 48000,
.used_max_ib_mc = 1,
.max_ib_mc = 27,
.used_max_pkey = 1,
.max_pkey = 32,
.swid_config = {
{
.used_type = 1,
.type = MLXSW_PORT_SWID_TYPE_IB,
}
},
};
static struct mlxsw_driver mlxsw_sib_driver = {
.kind = mlxsw_sib_driver_name,
.priv_size = sizeof(struct mlxsw_sib),
.init = mlxsw_sib_init,
.fini = mlxsw_sib_fini,
.basic_trap_groups_set = mlxsw_sib_basic_trap_groups_set,
.txhdr_construct = mlxsw_sib_tx_v1_hdr_construct,
.txhdr_len = MLXSW_TXHDR_LEN,
.profile = &mlxsw_sib_config_profile,
};
static struct mlxsw_driver mlxsw_sib2_driver = {
.kind = mlxsw_sib2_driver_name,
.priv_size = sizeof(struct mlxsw_sib),
.init = mlxsw_sib_init,
.fini = mlxsw_sib_fini,
.basic_trap_groups_set = mlxsw_sib_basic_trap_groups_set,
.txhdr_construct = mlxsw_sib_tx_v1_hdr_construct,
.txhdr_len = MLXSW_TXHDR_LEN,
.profile = &mlxsw_sib_config_profile,
};
static const struct pci_device_id mlxsw_sib_pci_id_table[] = {
{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHIB), 0},
{0, },
};
static struct pci_driver mlxsw_sib_pci_driver = {
.name = mlxsw_sib_driver_name,
.id_table = mlxsw_sib_pci_id_table,
};
static const struct pci_device_id mlxsw_sib2_pci_id_table[] = {
{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHIB2), 0},
{0, },
};
static struct pci_driver mlxsw_sib2_pci_driver = {
.name = mlxsw_sib2_driver_name,
.id_table = mlxsw_sib2_pci_id_table,
};
static int __init mlxsw_sib_module_init(void)
{
int err;
err = mlxsw_core_driver_register(&mlxsw_sib_driver);
if (err)
return err;
err = mlxsw_core_driver_register(&mlxsw_sib2_driver);
if (err)
goto err_sib2_driver_register;
err = mlxsw_pci_driver_register(&mlxsw_sib_pci_driver);
if (err)
goto err_sib_pci_driver_register;
err = mlxsw_pci_driver_register(&mlxsw_sib2_pci_driver);
if (err)
goto err_sib2_pci_driver_register;
return 0;
err_sib2_pci_driver_register:
mlxsw_pci_driver_unregister(&mlxsw_sib_pci_driver);
err_sib_pci_driver_register:
mlxsw_core_driver_unregister(&mlxsw_sib2_driver);
err_sib2_driver_register:
mlxsw_core_driver_unregister(&mlxsw_sib_driver);
return err;
}
static void __exit mlxsw_sib_module_exit(void)
{
mlxsw_pci_driver_unregister(&mlxsw_sib2_pci_driver);
mlxsw_pci_driver_unregister(&mlxsw_sib_pci_driver);
mlxsw_core_driver_unregister(&mlxsw_sib2_driver);
mlxsw_core_driver_unregister(&mlxsw_sib_driver);
}
module_init(mlxsw_sib_module_init);
module_exit(mlxsw_sib_module_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Elad Raz <eladr@@mellanox.com>");
MODULE_DESCRIPTION("Mellanox SwitchIB and SwitchIB-2 driver");
MODULE_ALIAS("mlxsw_switchib2");
MODULE_DEVICE_TABLE(pci, mlxsw_sib_pci_id_table);
MODULE_DEVICE_TABLE(pci, mlxsw_sib2_pci_id_table);

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,8 @@
PORT_NUM_NETIFS=0
declare -a unsplit
port_setup_prepare()
{
:
@ -20,12 +22,12 @@ port_cleanup()
devlink port unsplit $port
check_err $? "Did not unsplit $netdev"
done
unsplit=()
}
split_all_ports()
{
local should_fail=$1; shift
local -a unsplit
# Loop over the splittable netdevs and create tuples of netdev along
# with its width. For example:

View File

@ -29,37 +29,38 @@ cleanup()
get_prio_pg()
{
__mlnx_qos -i $swp | sed -n '/^PFC/,/^[^[:space:]]/p' |
grep buffer | sed 's/ \+/ /g' | cut -d' ' -f 2-
# Produces a string of numbers "<B0> <B1> ... <B7> ", where BX is number
# of buffer that priority X is mapped to.
dcb -j buffer show dev $swp |
jq -r '[.prio_buffer | .[] | tostring + " "] | add'
}
get_prio_pfc()
{
__mlnx_qos -i $swp | sed -n '/^PFC/,/^[^[:space:]]/p' |
grep enabled | sed 's/ \+/ /g' | cut -d' ' -f 2-
# Produces a string of numbers "<P0> <P1> ... <P7> ", where PX denotes
# whether priority X has PFC enabled (the value is 1) or disabled (0).
dcb -j pfc show dev $swp |
jq -r '[.prio_pfc | .[] | if . then "1 " else "0 " end] | add'
}
get_prio_tc()
{
__mlnx_qos -i $swp | sed -n '/^tc/,$p' |
awk '/^tc/ { TC = $2 }
/priority:/ { PRIO[$2]=TC }
END {
for (i in PRIO)
printf("%d ", PRIO[i])
}'
# Produces a string of numbers "<T0> <T1> ... <T7> ", where TC is number
# of TC that priority X is mapped to.
dcb -j ets show dev $swp |
jq -r '[.prio_tc | .[] | tostring + " "] | add'
}
get_buf_size()
{
local idx=$1; shift
__mlnx_qos -i $swp | grep Receive | sed 's/.*: //' | cut -d, -f $((idx + 1))
dcb -j buffer show dev $swp | jq ".buffer_size[$idx]"
}
get_tot_size()
{
__mlnx_qos -i $swp | grep Receive | sed 's/.*total_size=//'
dcb -j buffer show dev $swp | jq '.total_size'
}
check_prio_pg()
@ -121,18 +122,18 @@ test_dcb_ets()
{
RET=0
__mlnx_qos -i $swp --prio_tc=0,2,4,6,1,3,5,7 > /dev/null
dcb ets set dev $swp prio-tc 0:0 1:2 2:4 3:6 4:1 5:3 6:5 7:7
check_prio_pg "0 2 4 6 1 3 5 7 "
check_prio_tc "0 2 4 6 1 3 5 7 "
check_prio_pfc "0 0 0 0 0 0 0 0 "
__mlnx_qos -i $swp --prio_tc=0,0,0,0,0,0,0,0 > /dev/null
dcb ets set dev $swp prio-tc all:0
check_prio_pg "0 0 0 0 0 0 0 0 "
check_prio_tc "0 0 0 0 0 0 0 0 "
__mlnx_qos -i $swp --prio2buffer=1,3,5,7,0,2,4,6 &> /dev/null
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
check_fail $? "prio2buffer accepted in DCB mode"
log_test "Configuring headroom through ETS"
@ -174,7 +175,7 @@ test_pfc()
{
RET=0
__mlnx_qos -i $swp --prio_tc=0,0,0,0,0,1,2,3 > /dev/null
dcb ets set dev $swp prio-tc all:0 5:1 6:2 7:3
local buf0size=$(get_buf_size 0)
local buf1size=$(get_buf_size 1)
@ -193,7 +194,7 @@ test_pfc()
RET=0
__mlnx_qos -i $swp --pfc=0,0,0,0,0,1,1,1 --cable_len=0 > /dev/null
dcb pfc set dev $swp prio-pfc all:off 5:on 6:on 7:on delay 0
check_prio_pg "0 0 0 0 0 1 2 3 "
check_prio_pfc "0 0 0 0 0 1 1 1 "
@ -210,7 +211,7 @@ test_pfc()
RET=0
__mlnx_qos -i $swp --pfc=0,0,0,0,0,1,1,1 --cable_len=1000 > /dev/null
dcb pfc set dev $swp delay 1000
check_buf_size 0 "== $buf0size"
check_buf_size 1 "> $buf1size"
@ -221,8 +222,8 @@ test_pfc()
RET=0
__mlnx_qos -i $swp --pfc=0,0,0,0,0,0,0,0 --cable_len=0 > /dev/null
__mlnx_qos -i $swp --prio_tc=0,0,0,0,0,0,0,0 > /dev/null
dcb pfc set dev $swp prio-pfc all:off delay 0
dcb ets set dev $swp prio-tc all:0
check_prio_pg "0 0 0 0 0 0 0 0 "
check_prio_tc "0 0 0 0 0 0 0 0 "
@ -242,13 +243,13 @@ test_tc_priomap()
{
RET=0
__mlnx_qos -i $swp --prio_tc=0,1,2,3,4,5,6,7 > /dev/null
dcb ets set dev $swp prio-tc 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
check_prio_pg "0 1 2 3 4 5 6 7 "
tc qdisc replace dev $swp root handle 1: bfifo limit 1.5M
check_prio_pg "0 0 0 0 0 0 0 0 "
__mlnx_qos -i $swp --prio2buffer=1,3,5,7,0,2,4,6 > /dev/null
dcb buffer set dev $swp prio-buffer 0:1 1:3 2:5 3:7 4:0 5:2 6:4 7:6
check_prio_pg "1 3 5 7 0 2 4 6 "
tc qdisc delete dev $swp root
@ -256,9 +257,9 @@ test_tc_priomap()
# Clean up.
tc qdisc replace dev $swp root handle 1: bfifo limit 1.5M
__mlnx_qos -i $swp --prio2buffer=0,0,0,0,0,0,0,0 > /dev/null
dcb buffer set dev $swp prio-buffer all:0
tc qdisc delete dev $swp root
__mlnx_qos -i $swp --prio_tc=0,0,0,0,0,0,0,0 > /dev/null
dcb ets set dev $swp prio-tc all:0
log_test "TC: priomap"
}
@ -270,12 +271,12 @@ test_tc_sizes()
RET=0
__mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 &> /dev/null
dcb buffer set dev $swp buffer-size all:0 0:$size 2>/dev/null
check_fail $? "buffer_size should fail before qdisc is added"
tc qdisc replace dev $swp root handle 1: bfifo limit 1.5M
__mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 > /dev/null
dcb buffer set dev $swp buffer-size all:0 0:$size
check_err $? "buffer_size should pass after qdisc is added"
check_buf_size 0 "== $size" "set size: "
@ -283,26 +284,26 @@ test_tc_sizes()
check_buf_size 0 "== $size" "set MTU: "
mtu_restore $swp
__mlnx_qos -i $swp --buffer_size=0,0,0,0,0,0,0,0 > /dev/null
dcb buffer set dev $swp buffer-size all:0
# After replacing the qdisc for the same kind, buffer_size still has to
# work.
tc qdisc replace dev $swp root handle 1: bfifo limit 1M
__mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 > /dev/null
dcb buffer set dev $swp buffer-size all:0 0:$size
check_buf_size 0 "== $size" "post replace, set size: "
__mlnx_qos -i $swp --buffer_size=0,0,0,0,0,0,0,0 > /dev/null
dcb buffer set dev $swp buffer-size all:0
# Likewise after replacing for a different kind.
tc qdisc replace dev $swp root handle 2: prio bands 8
__mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 > /dev/null
dcb buffer set dev $swp buffer-size all:0 0:$size
check_buf_size 0 "== $size" "post replace different kind, set size: "
tc qdisc delete dev $swp root
__mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 &> /dev/null
dcb buffer set dev $swp buffer-size all:0 0:$size 2>/dev/null
check_fail $? "buffer_size should fail after qdisc is deleted"
log_test "TC: buffer size"
@ -363,10 +364,10 @@ test_tc_int_buf()
tc qdisc replace dev $swp root handle 1: bfifo limit 1.5M
test_int_buf "TC: "
__mlnx_qos -i $swp --buffer_size=$size,0,0,0,0,0,0,0 > /dev/null
dcb buffer set dev $swp buffer-size all:0 0:$size
test_int_buf "TC+buffsize: "
__mlnx_qos -i $swp --buffer_size=0,0,0,0,0,0,0,0 > /dev/null
dcb buffer set dev $swp buffer-size all:0
tc qdisc delete dev $swp root
}

View File

@ -82,17 +82,3 @@ bail_on_lldpad()
fi
fi
}
__mlnx_qos()
{
local err
mlnx_qos "$@" 2>/dev/null
err=$?
if ((err)); then
echo "Error ($err) in mlnx_qos $@" >/dev/stderr
fi
return $err
}

View File

@ -171,7 +171,7 @@ switch_create()
# assignment.
tc qdisc replace dev $swp1 root handle 1: \
ets bands 8 strict 8 priomap 7 6
__mlnx_qos -i $swp1 --prio2buffer=0,1,0,0,0,0,0,0 >/dev/null
dcb buffer set dev $swp1 prio-buffer all:0 1:1
# $swp2
# -----
@ -209,8 +209,8 @@ switch_create()
# the lossless prio into a buffer of its own. Don't bother with buffer
# sizes though, there is not going to be any pressure in the "backward"
# direction.
__mlnx_qos -i $swp3 --prio2buffer=0,1,0,0,0,0,0,0 >/dev/null
__mlnx_qos -i $swp3 --pfc=0,1,0,0,0,0,0,0 >/dev/null
dcb buffer set dev $swp3 prio-buffer all:0 1:1
dcb pfc set dev $swp3 prio-pfc all:off 1:on
# $swp4
# -----
@ -226,11 +226,11 @@ switch_create()
# Configure qdisc so that we can hand-tune headroom.
tc qdisc replace dev $swp4 root handle 1: \
ets bands 8 strict 8 priomap 7 6
__mlnx_qos -i $swp4 --prio2buffer=0,1,0,0,0,0,0,0 >/dev/null
__mlnx_qos -i $swp4 --pfc=0,1,0,0,0,0,0,0 >/dev/null
dcb buffer set dev $swp4 prio-buffer all:0 1:1
dcb pfc set dev $swp4 prio-pfc all:off 1:on
# PG0 will get autoconfigured to Xoff, give PG1 arbitrarily 100K, which
# is (-2*MTU) about 80K of delay provision.
__mlnx_qos -i $swp4 --buffer_size=0,$_100KB,0,0,0,0,0,0 >/dev/null
dcb buffer set dev $swp4 buffer-size all:0 1:$_100KB
# bridges
# -------
@ -273,9 +273,9 @@ switch_destroy()
# $swp4
# -----
__mlnx_qos -i $swp4 --buffer_size=0,0,0,0,0,0,0,0 >/dev/null
__mlnx_qos -i $swp4 --pfc=0,0,0,0,0,0,0,0 >/dev/null
__mlnx_qos -i $swp4 --prio2buffer=0,0,0,0,0,0,0,0 >/dev/null
dcb buffer set dev $swp4 buffer-size all:0
dcb pfc set dev $swp4 prio-pfc all:off
dcb buffer set dev $swp4 prio-buffer all:0
tc qdisc del dev $swp4 root
devlink_tc_bind_pool_th_restore $swp4 1 ingress
@ -288,8 +288,8 @@ switch_destroy()
# $swp3
# -----
__mlnx_qos -i $swp3 --pfc=0,0,0,0,0,0,0,0 >/dev/null
__mlnx_qos -i $swp3 --prio2buffer=0,0,0,0,0,0,0,0 >/dev/null
dcb pfc set dev $swp3 prio-pfc all:off
dcb buffer set dev $swp3 prio-buffer all:0
tc qdisc del dev $swp3 root
devlink_tc_bind_pool_th_restore $swp3 1 egress
@ -315,7 +315,7 @@ switch_destroy()
# $swp1
# -----
__mlnx_qos -i $swp1 --prio2buffer=0,0,0,0,0,0,0,0 >/dev/null
dcb buffer set dev $swp1 prio-buffer all:0
tc qdisc del dev $swp1 root
devlink_tc_bind_pool_th_restore $swp1 1 ingress

View File

@ -234,15 +234,15 @@ __tc_sample_rate_test()
psample_capture_start
ip vrf exec v$h1 $MZ $h1 -c 3200 -d 1msec -p 64 -A 192.0.2.1 \
ip vrf exec v$h1 $MZ $h1 -c 320000 -d 100usec -p 64 -A 192.0.2.1 \
-B $dip -t udp dp=52768,sp=42768 -q
psample_capture_stop
pkts=$(grep -e "group 1 " $CAPTURE_FILE | wc -l)
pct=$((100 * (pkts - 100) / 100))
pct=$((100 * (pkts - 10000) / 10000))
(( -25 <= pct && pct <= 25))
check_err $? "Expected 100 packets, got $pkts packets, which is $pct% off. Required accuracy is +-25%"
check_err $? "Expected 10000 packets, got $pkts packets, which is $pct% off. Required accuracy is +-25%"
log_test "tc sample rate ($desc)"
@ -587,15 +587,15 @@ __tc_sample_acl_rate_test()
psample_capture_start
ip vrf exec v$h1 $MZ $h1 -c 3200 -d 1msec -p 64 -A 192.0.2.1 \
ip vrf exec v$h1 $MZ $h1 -c 320000 -d 100usec -p 64 -A 192.0.2.1 \
-B 198.51.100.1 -t udp dp=52768,sp=42768 -q
psample_capture_stop
pkts=$(grep -e "group 1 " $CAPTURE_FILE | wc -l)
pct=$((100 * (pkts - 100) / 100))
pct=$((100 * (pkts - 10000) / 10000))
(( -25 <= pct && pct <= 25))
check_err $? "Expected 100 packets, got $pkts packets, which is $pct% off. Required accuracy is +-25%"
check_err $? "Expected 10000 packets, got $pkts packets, which is $pct% off. Required accuracy is +-25%"
# Setup a filter that should not match any packet and make sure packets
# are not sampled.