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

Commit 45ba5973 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mlx4-next'



Or Gerlitz says:

====================
mlx4: Add support for single port VFs

The mlx4 Firmware && driver expose both ports of the device through one PCI function.

This can be non-optimal under virtualization schemes where the admin
would like the VF to expose one interface to the VM, etc.

This series from Matan Barak adds support for single ported VFs.

Since all the VF interaction with the firmware passes through the PF
 driver, we can emulate to the VF they have one port, and further create
a set of the VFs which act on port1 of the device and another set which
acts on port2.

Series done against net-next commit 3ab428a4 "netfilter: Add missing
vmalloc.h include to nft_hash.c"

Roland, we send this through netdev, but if you have comments, will love
to hear them.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8798998c dd41cc3b
Loading
Loading
Loading
Loading
+15 −14
Original line number Diff line number Diff line
@@ -1245,21 +1245,9 @@ out:

static int get_slave_base_gid_ix(struct mlx4_ib_dev *dev, int slave, int port)
{
	int gids;
	int vfs;

	if (rdma_port_get_link_layer(&dev->ib_dev, port) == IB_LINK_LAYER_INFINIBAND)
		return slave;

	gids = MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS;
	vfs = dev->dev->num_vfs;

	if (slave == 0)
		return 0;
	if (slave <= gids % vfs)
		return MLX4_ROCE_PF_GIDS + ((gids / vfs) + 1) * (slave - 1);

	return MLX4_ROCE_PF_GIDS + (gids % vfs) + ((gids / vfs) * (slave - 1));
	return mlx4_get_base_gid_ix(dev->dev, slave, port);
}

static void fill_in_real_sgid_index(struct mlx4_ib_dev *dev, int slave, int port,
@@ -1281,6 +1269,7 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
	struct ib_ah_attr ah_attr;
	u8 *slave_id;
	int slave;
	int port;

	/* Get slave that sent this packet */
	if (wc->src_qp < dev->dev->phys_caps.base_proxy_sqpn ||
@@ -1360,6 +1349,10 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
	if (ah_attr.ah_flags & IB_AH_GRH)
		fill_in_real_sgid_index(dev, slave, ctx->port, &ah_attr);

	port = mlx4_slave_convert_port(dev->dev, slave, ah_attr.port_num);
	if (port < 0)
		return;
	ah_attr.port_num = port;
	memcpy(ah_attr.dmac, tunnel->hdr.mac, 6);
	ah_attr.vlan_id = be16_to_cpu(tunnel->hdr.vlan);
	/* if slave have default vlan use it */
@@ -1949,7 +1942,15 @@ static int mlx4_ib_alloc_demux_ctx(struct mlx4_ib_dev *dev,
	ctx->port = port;
	ctx->ib_dev = &dev->ib_dev;

	for (i = 0; i < dev->dev->caps.sqp_demux; i++) {
	for (i = 0;
	     i < min(dev->dev->caps.sqp_demux, (u16)(dev->dev->num_vfs + 1));
	     i++) {
		struct mlx4_active_ports actv_ports =
			mlx4_get_active_ports(dev->dev, i);

		if (!test_bit(port - 1, actv_ports.ports))
			continue;

		ret = alloc_pv_object(dev, i, port, &ctx->tun[i]);
		if (ret) {
			ret = -ENOMEM;
+15 −8
Original line number Diff line number Diff line
@@ -1546,7 +1546,7 @@ static int mlx4_ib_addr_event(int event, struct net_device *event_netdev,
	iboe = &ibdev->iboe;
	spin_lock(&iboe->lock);

	for (port = 1; port <= MLX4_MAX_PORTS; ++port)
	for (port = 1; port <= ibdev->dev->caps.num_ports; ++port)
		if ((netif_is_bond_master(real_dev) &&
		     (real_dev == iboe->masters[port - 1])) ||
		     (!netif_is_bond_master(real_dev) &&
@@ -1569,14 +1569,14 @@ static u8 mlx4_ib_get_dev_port(struct net_device *dev,

	iboe = &ibdev->iboe;

	for (port = 1; port <= MLX4_MAX_PORTS; ++port)
	for (port = 1; port <= ibdev->dev->caps.num_ports; ++port)
		if ((netif_is_bond_master(real_dev) &&
		     (real_dev == iboe->masters[port - 1])) ||
		     (!netif_is_bond_master(real_dev) &&
		     (real_dev == iboe->netdevs[port - 1])))
			break;

	if ((port == 0) || (port > MLX4_MAX_PORTS))
	if ((port == 0) || (port > ibdev->dev->caps.num_ports))
		return 0;
	else
		return port;
@@ -1626,7 +1626,7 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev,
	union ib_gid gid;


	if ((port == 0) || (port > MLX4_MAX_PORTS))
	if ((port == 0) || (port > ibdev->dev->caps.num_ports))
		return;

	/* IPv4 gids */
@@ -2323,17 +2323,24 @@ static void do_slave_init(struct mlx4_ib_dev *ibdev, int slave, int do_init)
	struct mlx4_dev *dev = ibdev->dev;
	int i;
	unsigned long flags;
	struct mlx4_active_ports actv_ports;
	unsigned int ports;
	unsigned int first_port;

	if (!mlx4_is_master(dev))
		return;

	dm = kcalloc(dev->caps.num_ports, sizeof *dm, GFP_ATOMIC);
	actv_ports = mlx4_get_active_ports(dev, slave);
	ports = bitmap_weight(actv_ports.ports, dev->caps.num_ports);
	first_port = find_first_bit(actv_ports.ports, dev->caps.num_ports);

	dm = kcalloc(ports, sizeof(*dm), GFP_ATOMIC);
	if (!dm) {
		pr_err("failed to allocate memory for tunneling qp update\n");
		goto out;
	}

	for (i = 0; i < dev->caps.num_ports; i++) {
	for (i = 0; i < ports; i++) {
		dm[i] = kmalloc(sizeof (struct mlx4_ib_demux_work), GFP_ATOMIC);
		if (!dm[i]) {
			pr_err("failed to allocate memory for tunneling qp update work struct\n");
@@ -2345,9 +2352,9 @@ static void do_slave_init(struct mlx4_ib_dev *ibdev, int slave, int do_init)
		}
	}
	/* initialize or tear down tunnel QPs for the slave */
	for (i = 0; i < dev->caps.num_ports; i++) {
	for (i = 0; i < ports; i++) {
		INIT_WORK(&dm[i]->work, mlx4_ib_tunnels_update_work);
		dm[i]->port = i + 1;
		dm[i]->port = first_port + i + 1;
		dm[i]->slave = slave;
		dm[i]->do_init = do_init;
		dm[i]->dev = ibdev;
+5 −0
Original line number Diff line number Diff line
@@ -627,6 +627,7 @@ static int register_one_pkey_tree(struct mlx4_ib_dev *dev, int slave)
	int port;
	struct kobject *p, *t;
	struct mlx4_port *mport;
	struct mlx4_active_ports actv_ports;

	get_name(dev, name, slave, sizeof name);

@@ -649,7 +650,11 @@ static int register_one_pkey_tree(struct mlx4_ib_dev *dev, int slave)
		goto err_ports;
	}

	actv_ports = mlx4_get_active_ports(dev->dev, slave);

	for (port = 1; port <= dev->dev->caps.num_ports; ++port) {
		if (!test_bit(port - 1, actv_ports.ports))
			continue;
		err = add_port(dev, port, slave);
		if (err)
			goto err_add;
+126 −3
Original line number Diff line number Diff line
@@ -1643,8 +1643,16 @@ static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
	int port, err;
	struct mlx4_vport_state *vp_admin;
	struct mlx4_vport_oper_state *vp_oper;

	for (port = 1; port <= MLX4_MAX_PORTS; port++) {
	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(
			&priv->dev, slave);
	int min_port = find_first_bit(actv_ports.ports,
				      priv->dev.caps.num_ports) + 1;
	int max_port = min_port - 1 +
		bitmap_weight(actv_ports.ports, priv->dev.caps.num_ports);

	for (port = min_port; port <= max_port; port++) {
		if (!test_bit(port - 1, actv_ports.ports))
			continue;
		vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
		vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
		vp_oper->state = *vp_admin;
@@ -1685,8 +1693,17 @@ static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave
{
	int port;
	struct mlx4_vport_oper_state *vp_oper;
	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(
			&priv->dev, slave);
	int min_port = find_first_bit(actv_ports.ports,
				      priv->dev.caps.num_ports) + 1;
	int max_port = min_port - 1 +
		bitmap_weight(actv_ports.ports, priv->dev.caps.num_ports);

	for (port = 1; port <= MLX4_MAX_PORTS; port++) {

	for (port = min_port; port <= max_port; port++) {
		if (!test_bit(port - 1, actv_ports.ports))
			continue;
		vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
		if (NO_INDX != vp_oper->vlan_idx) {
			__mlx4_unregister_vlan(&priv->dev,
@@ -2234,6 +2251,112 @@ static int mlx4_get_slave_indx(struct mlx4_dev *dev, int vf)
	return vf+1;
}

int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave)
{
	if (slave < 1 || slave > dev->num_vfs) {
		mlx4_err(dev,
			 "Bad slave number:%d (number of activated slaves: %lu)\n",
			 slave, dev->num_slaves);
		return -EINVAL;
	}
	return slave - 1;
}

struct mlx4_active_ports mlx4_get_active_ports(struct mlx4_dev *dev, int slave)
{
	struct mlx4_active_ports actv_ports;
	int vf;

	bitmap_zero(actv_ports.ports, MLX4_MAX_PORTS);

	if (slave == 0) {
		bitmap_fill(actv_ports.ports, dev->caps.num_ports);
		return actv_ports;
	}

	vf = mlx4_get_vf_indx(dev, slave);
	if (vf < 0)
		return actv_ports;

	bitmap_set(actv_ports.ports, dev->dev_vfs[vf].min_port - 1,
		   min((int)dev->dev_vfs[mlx4_get_vf_indx(dev, slave)].n_ports,
		   dev->caps.num_ports));

	return actv_ports;
}
EXPORT_SYMBOL_GPL(mlx4_get_active_ports);

int mlx4_slave_convert_port(struct mlx4_dev *dev, int slave, int port)
{
	unsigned n;
	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave);
	unsigned m = bitmap_weight(actv_ports.ports, dev->caps.num_ports);

	if (port <= 0 || port > m)
		return -EINVAL;

	n = find_first_bit(actv_ports.ports, dev->caps.num_ports);
	if (port <= n)
		port = n + 1;

	return port;
}
EXPORT_SYMBOL_GPL(mlx4_slave_convert_port);

int mlx4_phys_to_slave_port(struct mlx4_dev *dev, int slave, int port)
{
	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave);
	if (test_bit(port - 1, actv_ports.ports))
		return port -
			find_first_bit(actv_ports.ports, dev->caps.num_ports);

	return -1;
}
EXPORT_SYMBOL_GPL(mlx4_phys_to_slave_port);

struct mlx4_slaves_pport mlx4_phys_to_slaves_pport(struct mlx4_dev *dev,
						   int port)
{
	unsigned i;
	struct mlx4_slaves_pport slaves_pport;

	bitmap_zero(slaves_pport.slaves, MLX4_MFUNC_MAX);

	if (port <= 0 || port > dev->caps.num_ports)
		return slaves_pport;

	for (i = 0; i < dev->num_vfs + 1; i++) {
		struct mlx4_active_ports actv_ports =
			mlx4_get_active_ports(dev, i);
		if (test_bit(port - 1, actv_ports.ports))
			set_bit(i, slaves_pport.slaves);
	}

	return slaves_pport;
}
EXPORT_SYMBOL_GPL(mlx4_phys_to_slaves_pport);

struct mlx4_slaves_pport mlx4_phys_to_slaves_pport_actv(
		struct mlx4_dev *dev,
		const struct mlx4_active_ports *crit_ports)
{
	unsigned i;
	struct mlx4_slaves_pport slaves_pport;

	bitmap_zero(slaves_pport.slaves, MLX4_MFUNC_MAX);

	for (i = 0; i < dev->num_vfs + 1; i++) {
		struct mlx4_active_ports actv_ports =
			mlx4_get_active_ports(dev, i);
		if (bitmap_equal(crit_ports->ports, actv_ports.ports,
				 dev->caps.num_ports))
			set_bit(i, slaves_pport.slaves);
	}

	return slaves_pport;
}
EXPORT_SYMBOL_GPL(mlx4_phys_to_slaves_pport_actv);

int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
+38 −10
Original line number Diff line number Diff line
@@ -271,7 +271,10 @@ enum slave_port_state mlx4_get_slave_port_state(struct mlx4_dev *dev, int slave,
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_slave_state *s_state = priv->mfunc.master.slave_state;
	if (slave >= dev->num_slaves || port > MLX4_MAX_PORTS) {
	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave);

	if (slave >= dev->num_slaves || port > dev->caps.num_ports ||
	    port <= 0 || !test_bit(port - 1, actv_ports.ports)) {
		pr_err("%s: Error: asking for slave:%d, port:%d\n",
		       __func__, slave, port);
		return SLAVE_PORT_DOWN;
@@ -285,8 +288,10 @@ static int mlx4_set_slave_port_state(struct mlx4_dev *dev, int slave, u8 port,
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_slave_state *s_state = priv->mfunc.master.slave_state;
	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave);

	if (slave >= dev->num_slaves || port > MLX4_MAX_PORTS || port == 0) {
	if (slave >= dev->num_slaves || port > dev->caps.num_ports ||
	    port <= 0 || !test_bit(port - 1, actv_ports.ports)) {
		pr_err("%s: Error: asking for slave:%d, port:%d\n",
		       __func__, slave, port);
		return -1;
@@ -300,9 +305,13 @@ static void set_all_slave_state(struct mlx4_dev *dev, u8 port, int event)
{
	int i;
	enum slave_port_gen_event gen_event;
	struct mlx4_slaves_pport slaves_pport = mlx4_phys_to_slaves_pport(dev,
									  port);

	for (i = 0; i < dev->num_slaves; i++)
		set_and_calc_slave_port_state(dev, i, port, event, &gen_event);
	for (i = 0; i < dev->num_vfs + 1; i++)
		if (test_bit(i, slaves_pport.slaves))
			set_and_calc_slave_port_state(dev, i, port,
						      event, &gen_event);
}
/**************************************************************************
	The function get as input the new event to that port,
@@ -321,12 +330,14 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,
	struct mlx4_slave_state *ctx = NULL;
	unsigned long flags;
	int ret = -1;
	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave);
	enum slave_port_state cur_state =
		mlx4_get_slave_port_state(dev, slave, port);

	*gen_event = SLAVE_PORT_GEN_EVENT_NONE;

	if (slave >= dev->num_slaves || port > MLX4_MAX_PORTS || port == 0) {
	if (slave >= dev->num_slaves || port > dev->caps.num_ports ||
	    port <= 0 || !test_bit(port - 1, actv_ports.ports)) {
		pr_err("%s: Error: asking for slave:%d, port:%d\n",
		       __func__, slave, port);
		return ret;
@@ -542,15 +553,19 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
				       be64_to_cpu(eqe->event.cmd.out_param));
			break;

		case MLX4_EVENT_TYPE_PORT_CHANGE:
		case MLX4_EVENT_TYPE_PORT_CHANGE: {
			struct mlx4_slaves_pport slaves_port;
			port = be32_to_cpu(eqe->event.port_change.port) >> 28;
			slaves_port = mlx4_phys_to_slaves_pport(dev, port);
			if (eqe->subtype == MLX4_PORT_CHANGE_SUBTYPE_DOWN) {
				mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_DOWN,
						    port);
				mlx4_priv(dev)->sense.do_sense_port[port] = 1;
				if (!mlx4_is_master(dev))
					break;
				for (i = 0; i < dev->num_slaves; i++) {
				for (i = 0; i < dev->num_vfs + 1; i++) {
					if (!test_bit(i, slaves_port.slaves))
						continue;
					if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) {
						if (i == mlx4_master_func_num(dev))
							continue;
@@ -558,8 +573,13 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
							 " to slave: %d, port:%d\n",
							 __func__, i, port);
						s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state;
						if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state)
						if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) {
							eqe->event.port_change.port =
								cpu_to_be32(
								(be32_to_cpu(eqe->event.port_change.port) & 0xFFFFFFF)
								| (mlx4_phys_to_slave_port(dev, i, port) << 28));
							mlx4_slave_event(dev, i, eqe);
						}
					} else {  /* IB port */
						set_and_calc_slave_port_state(dev, i, port,
									      MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN,
@@ -580,13 +600,20 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
				if (!mlx4_is_master(dev))
					break;
				if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH)
					for (i = 0; i < dev->num_slaves; i++) {
					for (i = 0; i < dev->num_vfs + 1; i++) {
						if (!test_bit(i, slaves_port.slaves))
							continue;
						if (i == mlx4_master_func_num(dev))
							continue;
						s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state;
						if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state)
						if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) {
							eqe->event.port_change.port =
								cpu_to_be32(
								(be32_to_cpu(eqe->event.port_change.port) & 0xFFFFFFF)
								| (mlx4_phys_to_slave_port(dev, i, port) << 28));
							mlx4_slave_event(dev, i, eqe);
						}
					}
				else /* IB port */
					/* port-up event will be sent to a slave when the
					 * slave's alias-guid is set. This is done in alias_GUID.c
@@ -594,6 +621,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
					set_all_slave_state(dev, port, MLX4_DEV_EVENT_PORT_UP);
			}
			break;
		}

		case MLX4_EVENT_TYPE_CQ_ERROR:
			mlx4_warn(dev, "CQ %s on CQN %06x\n",
Loading