Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2701c3b3 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mlxsw-IB'



Jiri Pirko says:

====================
mlxsw: Add Infiniband support for Mellanox switches

This patchset adds basic Infiniband support for SwitchX-2, Switch-IB
and Switch-IB-2 ASIC drivers.

SwitchX-2 ASIC is VPI capable, which means each port can be either
Ethernet or Infiniband. When the port is configured as Infiniband,
the Subnet Management Agent (SMA) is managed by the SwitchX-2 firmware
and not by the host. Port configuration, MTU and more are configured
remotely by the Subnet Manager (SM).

Usage:
        $ devlink port show
        pci/0000:03:00.0/1: type eth netdev eth0
        pci/0000:03:00.0/3: type eth netdev eth1
        pci/0000:03:00.0/5: type eth netdev eth2
        pci/0000:03:00.0/6: type eth netdev eth3
        pci/0000:03:00.0/8: type eth netdev eth4

        $ devlink port set pci/0000:03:00.0/1 type ib

        $ devlink port show
        pci/0000:03:00.0/1: type ib

Switch-IB (FDR) and Switch-IB-2 (EDR 100Gbs) ASICs are Infiniband-only
switches. The support provided in the mlxsw_switchib.ko driver is port
initialization only. The firmware running in the Silicon implements
the SMA.

Please note that this patchset does only very basic port initialization.
ib_device or RDMA implementations are not part of this patchset.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 27058af4 d1ba5263
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -29,6 +29,17 @@ config MLXSW_PCI
	  To compile this driver as a module, choose M here: the
	  module will be called mlxsw_pci.

config MLXSW_SWITCHIB
	tristate "Mellanox Technologies SwitchIB and SwitchIB-2 support"
	depends on MLXSW_CORE && 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
+2 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@ mlxsw_core-objs := core.o
mlxsw_core-$(CONFIG_MLXSW_CORE_HWMON) += core_hwmon.o
obj-$(CONFIG_MLXSW_PCI)		+= mlxsw_pci.o
mlxsw_pci-objs			:= pci.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
+109 −14
Original line number Diff line number Diff line
@@ -90,6 +90,23 @@ struct mlxsw_core_pcpu_stats {
	u32			port_rx_invalid;
};

struct mlxsw_core_port {
	struct devlink_port devlink_port;
	void *port_driver_priv;
	u8 local_port;
};

void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port)
{
	return mlxsw_core_port->port_driver_priv;
}
EXPORT_SYMBOL(mlxsw_core_port_driver_priv);

static bool mlxsw_core_port_check(struct mlxsw_core_port *mlxsw_core_port)
{
	return mlxsw_core_port->port_driver_priv != NULL;
}

struct mlxsw_core {
	struct mlxsw_driver *driver;
	const struct mlxsw_bus *bus;
@@ -114,6 +131,7 @@ struct mlxsw_core {
	} lag;
	struct mlxsw_res res;
	struct mlxsw_hwmon *hwmon;
	struct mlxsw_core_port ports[MLXSW_PORT_MAX_PORTS];
	unsigned long driver_priv[0];
	/* driver_priv has to be always the last item */
};
@@ -920,6 +938,21 @@ static void *__dl_port(struct devlink_port *devlink_port)
	return container_of(devlink_port, struct mlxsw_core_port, devlink_port);
}

static int mlxsw_devlink_port_type_set(struct devlink_port *devlink_port,
				       enum devlink_port_type port_type)
{
	struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->port_type_set)
		return -EOPNOTSUPP;

	return mlxsw_driver->port_type_set(mlxsw_core,
					   mlxsw_core_port->local_port,
					   port_type);
}

static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port,
					  unsigned int sb_index, u16 pool_index,
					  u32 *p_threshold)
@@ -928,7 +961,8 @@ static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_port_pool_get)
	if (!mlxsw_driver->sb_port_pool_get ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_port_pool_get(mlxsw_core_port, sb_index,
					      pool_index, p_threshold);
@@ -942,7 +976,8 @@ static int mlxsw_devlink_sb_port_pool_set(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_port_pool_set)
	if (!mlxsw_driver->sb_port_pool_set ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_port_pool_set(mlxsw_core_port, sb_index,
					      pool_index, threshold);
@@ -958,7 +993,8 @@ mlxsw_devlink_sb_tc_pool_bind_get(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_tc_pool_bind_get)
	if (!mlxsw_driver->sb_tc_pool_bind_get ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_tc_pool_bind_get(mlxsw_core_port, sb_index,
						 tc_index, pool_type,
@@ -975,7 +1011,8 @@ mlxsw_devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_tc_pool_bind_set)
	if (!mlxsw_driver->sb_tc_pool_bind_set ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_tc_pool_bind_set(mlxsw_core_port, sb_index,
						 tc_index, pool_type,
@@ -1013,7 +1050,8 @@ mlxsw_devlink_sb_occ_port_pool_get(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_occ_port_pool_get)
	if (!mlxsw_driver->sb_occ_port_pool_get ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_occ_port_pool_get(mlxsw_core_port, sb_index,
						  pool_index, p_cur, p_max);
@@ -1029,7 +1067,8 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_occ_tc_port_bind_get)
	if (!mlxsw_driver->sb_occ_tc_port_bind_get ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_occ_tc_port_bind_get(mlxsw_core_port,
						     sb_index, tc_index,
@@ -1037,6 +1076,7 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port,
}

static const struct devlink_ops mlxsw_devlink_ops = {
	.port_type_set			= mlxsw_devlink_port_type_set,
	.port_split			= mlxsw_devlink_port_split,
	.port_unsplit			= mlxsw_devlink_port_unsplit,
	.sb_pool_get			= mlxsw_devlink_sb_pool_get,
@@ -1656,28 +1696,83 @@ u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
}
EXPORT_SYMBOL(mlxsw_core_res_get);

int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core,
			 struct mlxsw_core_port *mlxsw_core_port, u8 local_port,
			 struct net_device *dev, bool split, u32 split_group)
int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port)
{
	struct devlink *devlink = priv_to_devlink(mlxsw_core);
	struct mlxsw_core_port *mlxsw_core_port =
					&mlxsw_core->ports[local_port];
	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
	int err;

	if (split)
		devlink_port_split_set(devlink_port, split_group);
	devlink_port_type_eth_set(devlink_port, dev);
	return devlink_port_register(devlink, devlink_port, local_port);
	mlxsw_core_port->local_port = local_port;
	err = devlink_port_register(devlink, devlink_port, local_port);
	if (err)
		memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
	return err;
}
EXPORT_SYMBOL(mlxsw_core_port_init);

void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port)
void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port)
{
	struct mlxsw_core_port *mlxsw_core_port =
					&mlxsw_core->ports[local_port];
	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;

	devlink_port_unregister(devlink_port);
	memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
}
EXPORT_SYMBOL(mlxsw_core_port_fini);

void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
			     void *port_driver_priv, struct net_device *dev,
			     bool split, u32 split_group)
{
	struct mlxsw_core_port *mlxsw_core_port =
					&mlxsw_core->ports[local_port];
	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;

	mlxsw_core_port->port_driver_priv = port_driver_priv;
	if (split)
		devlink_port_split_set(devlink_port, split_group);
	devlink_port_type_eth_set(devlink_port, dev);
}
EXPORT_SYMBOL(mlxsw_core_port_eth_set);

void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port,
			    void *port_driver_priv)
{
	struct mlxsw_core_port *mlxsw_core_port =
					&mlxsw_core->ports[local_port];
	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;

	mlxsw_core_port->port_driver_priv = port_driver_priv;
	devlink_port_type_ib_set(devlink_port, NULL);
}
EXPORT_SYMBOL(mlxsw_core_port_ib_set);

void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port,
			   void *port_driver_priv)
{
	struct mlxsw_core_port *mlxsw_core_port =
					&mlxsw_core->ports[local_port];
	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;

	mlxsw_core_port->port_driver_priv = port_driver_priv;
	devlink_port_type_clear(devlink_port);
}
EXPORT_SYMBOL(mlxsw_core_port_clear);

enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
						u8 local_port)
{
	struct mlxsw_core_port *mlxsw_core_port =
					&mlxsw_core->ports[local_port];
	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;

	return devlink_port->type;
}
EXPORT_SYMBOL(mlxsw_core_port_type_get);

static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core,
				    const char *buf, size_t size)
{
+15 −17
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@
#include "resources.h"

struct mlxsw_core;
struct mlxsw_core_port;
struct mlxsw_driver;
struct mlxsw_bus;
struct mlxsw_bus_info;
@@ -141,23 +142,18 @@ u8 mlxsw_core_lag_mapping_get(struct mlxsw_core *mlxsw_core,
void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core,
				  u16 lag_id, u8 local_port);

struct mlxsw_core_port {
	struct devlink_port devlink_port;
};

static inline void *
mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port)
{
	/* mlxsw_core_port is ensured to always be the first field in driver
	 * port structure.
	 */
	return mlxsw_core_port;
}

int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core,
			 struct mlxsw_core_port *mlxsw_core_port, u8 local_port,
			 struct net_device *dev, bool split, u32 split_group);
void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port);
void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port);
int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port);
void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port);
void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
			     void *port_driver_priv, struct net_device *dev,
			     bool split, u32 split_group);
void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port,
			    void *port_driver_priv);
void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port,
			   void *port_driver_priv);
enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
						u8 local_port);

int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay);

@@ -218,6 +214,8 @@ struct mlxsw_driver {
	int (*init)(struct mlxsw_core *mlxsw_core,
		    const struct mlxsw_bus_info *mlxsw_bus_info);
	void (*fini)(struct mlxsw_core *mlxsw_core);
	int (*port_type_set)(struct mlxsw_core *mlxsw_core, u8 local_port,
			     enum devlink_port_type new_type);
	int (*port_split)(struct mlxsw_core *mlxsw_core, u8 local_port,
			  unsigned int count);
	int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u8 local_port);
+2 −2
Original line number Diff line number Diff line
@@ -262,7 +262,7 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,

static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
{
	char mtcap_pl[MLXSW_REG_MTCAP_LEN];
	char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0};
	char mtmp_pl[MLXSW_REG_MTMP_LEN];
	u8 sensor_count;
	int i;
@@ -295,7 +295,7 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)

static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon)
{
	char mfcr_pl[MLXSW_REG_MFCR_LEN];
	char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0};
	enum mlxsw_reg_mfcr_pwm_frequency freq;
	unsigned int type_index;
	unsigned int num;
Loading