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

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

Merge branch 'mlx4'



Or Gerlitz says:

====================
This series adds support for the SRIOV ndo_set_vf callbacks to the mlx4 driver.

Series done against the net-next tree as of commit 37fe0660 "net:
fix address check in rtnl_fdb_del"

We have successfully tested the series on net-next, except for getting
the VF link info issue I have reported earlier today on netdev, we
see the problem for both ixgbe and mlx4 VFs. Just to make sure get
VF config is working OK with patch #6 - we have run it over 3.8.8 too.

We added to the V1 series two patches that disable HW timestamping
when running over a VF, as this isn't supported yet.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 50754d21 2cccb9e4
Loading
Loading
Loading
Loading
+200 −0
Original line number Diff line number Diff line
@@ -1490,6 +1490,69 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
	return ret;
}

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++) {
		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;
		if (MLX4_VGT != vp_admin->default_vlan) {
			err = __mlx4_register_vlan(&priv->dev, port,
						   vp_admin->default_vlan, &(vp_oper->vlan_idx));
			if (err) {
				vp_oper->vlan_idx = NO_INDX;
				mlx4_warn((&priv->dev),
					  "No vlan resorces slave %d, port %d\n",
					  slave, port);
				return err;
			}
			mlx4_dbg((&(priv->dev)), "alloc vlan %d idx  %d slave %d port %d\n",
				 (int)(vp_oper->state.default_vlan),
				 vp_oper->vlan_idx, slave, port);
		}
		if (vp_admin->spoofchk) {
			vp_oper->mac_idx = __mlx4_register_mac(&priv->dev,
							       port,
							       vp_admin->mac);
			if (0 > vp_oper->mac_idx) {
				err = vp_oper->mac_idx;
				vp_oper->mac_idx = NO_INDX;
				mlx4_warn((&priv->dev),
					  "No mac resorces slave %d, port %d\n",
					  slave, port);
				return err;
			}
			mlx4_dbg((&(priv->dev)), "alloc mac %llx idx  %d slave %d port %d\n",
				 vp_oper->state.mac, vp_oper->mac_idx, slave, port);
		}
	}
	return 0;
}

static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave)
{
	int port;
	struct mlx4_vport_oper_state *vp_oper;

	for (port = 1; port <= MLX4_MAX_PORTS; port++) {
		vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
		if (NO_INDX != vp_oper->vlan_idx) {
			__mlx4_unregister_vlan(&priv->dev,
					       port, vp_oper->vlan_idx);
			vp_oper->vlan_idx = NO_INDX;
		}
		if (NO_INDX != vp_oper->mac_idx) {
			__mlx4_unregister_mac(&priv->dev, port, vp_oper->mac_idx);
			vp_oper->mac_idx = NO_INDX;
		}
	}
	return;
}

static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
			       u16 param, u8 toggle)
{
@@ -1510,6 +1573,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
	if (cmd == MLX4_COMM_CMD_RESET) {
		mlx4_warn(dev, "Received reset from slave:%d\n", slave);
		slave_state[slave].active = false;
		mlx4_master_deactivate_admin_state(priv, slave);
		for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) {
				slave_state[slave].event_eq[i].eqn = -1;
				slave_state[slave].event_eq[i].token = 0;
@@ -1556,6 +1620,8 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
		if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2)
			goto reset_slave;
		slave_state[slave].vhcr_dma |= param;
		if (mlx4_master_activate_admin_state(priv, slave))
				goto reset_slave;
		slave_state[slave].active = true;
		mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_INIT, slave);
		break;
@@ -1732,6 +1798,18 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
		if (!priv->mfunc.master.slave_state)
			goto err_comm;

		priv->mfunc.master.vf_admin =
			kzalloc(dev->num_slaves *
				sizeof(struct mlx4_vf_admin_state), GFP_KERNEL);
		if (!priv->mfunc.master.vf_admin)
			goto err_comm_admin;

		priv->mfunc.master.vf_oper =
			kzalloc(dev->num_slaves *
				sizeof(struct mlx4_vf_oper_state), GFP_KERNEL);
		if (!priv->mfunc.master.vf_oper)
			goto err_comm_oper;

		for (i = 0; i < dev->num_slaves; ++i) {
			s_state = &priv->mfunc.master.slave_state[i];
			s_state->last_cmd = MLX4_COMM_CMD_RESET;
@@ -1752,6 +1830,10 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
					goto err_slaves;
				}
				INIT_LIST_HEAD(&s_state->mcast_filters[port]);
				priv->mfunc.master.vf_admin[i].vport[port].default_vlan = MLX4_VGT;
				priv->mfunc.master.vf_oper[i].vport[port].state.default_vlan = MLX4_VGT;
				priv->mfunc.master.vf_oper[i].vport[port].vlan_idx = NO_INDX;
				priv->mfunc.master.vf_oper[i].vport[port].mac_idx = NO_INDX;
			}
			spin_lock_init(&s_state->lock);
		}
@@ -1800,6 +1882,10 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
		for (port = 1; port <= MLX4_MAX_PORTS; port++)
			kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
	}
	kfree(priv->mfunc.master.vf_oper);
err_comm_oper:
	kfree(priv->mfunc.master.vf_admin);
err_comm_admin:
	kfree(priv->mfunc.master.slave_state);
err_comm:
	iounmap(priv->mfunc.comm);
@@ -1874,6 +1960,8 @@ void mlx4_multi_func_cleanup(struct mlx4_dev *dev)
				kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
		}
		kfree(priv->mfunc.master.slave_state);
		kfree(priv->mfunc.master.vf_admin);
		kfree(priv->mfunc.master.vf_oper);
	}

	iounmap(priv->mfunc.comm);
@@ -1984,3 +2072,115 @@ u32 mlx4_comm_get_version(void)
{
	 return ((u32) CMD_CHAN_IF_REV << 8) | (u32) CMD_CHAN_VER;
}

static int mlx4_get_slave_indx(struct mlx4_dev *dev, int vf)
{
	if ((vf < 0) || (vf >= dev->num_vfs)) {
		mlx4_err(dev, "Bad vf number:%d (number of activated vf: %d)\n", vf, dev->num_vfs);
		return -EINVAL;
	}

	return vf+1;
}

int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_vport_state *s_info;
	int slave;

	if (!mlx4_is_master(dev))
		return -EPROTONOSUPPORT;

	slave = mlx4_get_slave_indx(dev, vf);
	if (slave < 0)
		return -EINVAL;

	s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
	s_info->mac = mac;
	mlx4_info(dev, "default mac on vf %d port %d to %llX will take afect only after vf restart\n",
		  vf, port, s_info->mac);
	return 0;
}
EXPORT_SYMBOL_GPL(mlx4_set_vf_mac);

int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_vport_state *s_info;
	int slave;

	if ((!mlx4_is_master(dev)) ||
	    !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL))
		return -EPROTONOSUPPORT;

	if ((vlan > 4095) || (qos > 7))
		return -EINVAL;

	slave = mlx4_get_slave_indx(dev, vf);
	if (slave < 0)
		return -EINVAL;

	s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
	if ((0 == vlan) && (0 == qos))
		s_info->default_vlan = MLX4_VGT;
	else
		s_info->default_vlan = vlan;
	s_info->default_qos = qos;
	return 0;
}
EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan);

int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_vport_state *s_info;
	int slave;

	if ((!mlx4_is_master(dev)) ||
	    !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FSM))
		return -EPROTONOSUPPORT;

	slave = mlx4_get_slave_indx(dev, vf);
	if (slave < 0)
		return -EINVAL;

	s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
	s_info->spoofchk = setting;

	return 0;
}
EXPORT_SYMBOL_GPL(mlx4_set_vf_spoofchk);

int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_info *ivf)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_vport_state *s_info;
	int slave;

	if (!mlx4_is_master(dev))
		return -EPROTONOSUPPORT;

	slave = mlx4_get_slave_indx(dev, vf);
	if (slave < 0)
		return -EINVAL;

	s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
	ivf->vf = vf;

	/* need to convert it to a func */
	ivf->mac[0] = ((s_info->mac >> (5*8)) & 0xff);
	ivf->mac[1] = ((s_info->mac >> (4*8)) & 0xff);
	ivf->mac[2] = ((s_info->mac >> (3*8)) & 0xff);
	ivf->mac[3] = ((s_info->mac >> (2*8)) & 0xff);
	ivf->mac[4] = ((s_info->mac >> (1*8)) & 0xff);
	ivf->mac[5] = ((s_info->mac)  & 0xff);

	ivf->vlan	= s_info->default_vlan;
	ivf->qos	= s_info->default_qos;
	ivf->tx_rate	= s_info->tx_rate;
	ivf->spoofchk	= s_info->spoofchk;

	return 0;
}
EXPORT_SYMBOL_GPL(mlx4_get_vf_config);
+74 −4
Original line number Diff line number Diff line
@@ -1373,6 +1373,7 @@ static void mlx4_en_service_task(struct work_struct *work)

	mutex_lock(&mdev->state_lock);
	if (mdev->device_up) {
		if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
			mlx4_en_ptp_overflow_check(mdev);

		queue_delayed_work(mdev->workqueue, &priv->service_task,
@@ -2023,6 +2024,42 @@ static int mlx4_en_set_features(struct net_device *netdev,

}

static int mlx4_en_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
{
	struct mlx4_en_priv *en_priv = netdev_priv(dev);
	struct mlx4_en_dev *mdev = en_priv->mdev;
	u64 mac_u64 = mlx4_en_mac_to_u64(mac);

	if (!is_valid_ether_addr(mac))
		return -EINVAL;

	return mlx4_set_vf_mac(mdev->dev, en_priv->port, queue, mac_u64);
}

static int mlx4_en_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos)
{
	struct mlx4_en_priv *en_priv = netdev_priv(dev);
	struct mlx4_en_dev *mdev = en_priv->mdev;

	return mlx4_set_vf_vlan(mdev->dev, en_priv->port, vf, vlan, qos);
}

static int mlx4_en_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)
{
	struct mlx4_en_priv *en_priv = netdev_priv(dev);
	struct mlx4_en_dev *mdev = en_priv->mdev;

	return mlx4_set_vf_spoofchk(mdev->dev, en_priv->port, vf, setting);
}

static int mlx4_en_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_info *ivf)
{
	struct mlx4_en_priv *en_priv = netdev_priv(dev);
	struct mlx4_en_dev *mdev = en_priv->mdev;

	return mlx4_get_vf_config(mdev->dev, en_priv->port, vf, ivf);
}

static const struct net_device_ops mlx4_netdev_ops = {
	.ndo_open		= mlx4_en_open,
	.ndo_stop		= mlx4_en_close,
@@ -2047,6 +2084,33 @@ static const struct net_device_ops mlx4_netdev_ops = {
#endif
};

static const struct net_device_ops mlx4_netdev_ops_master = {
	.ndo_open		= mlx4_en_open,
	.ndo_stop		= mlx4_en_close,
	.ndo_start_xmit		= mlx4_en_xmit,
	.ndo_select_queue	= mlx4_en_select_queue,
	.ndo_get_stats		= mlx4_en_get_stats,
	.ndo_set_rx_mode	= mlx4_en_set_rx_mode,
	.ndo_set_mac_address	= mlx4_en_set_mac,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_change_mtu		= mlx4_en_change_mtu,
	.ndo_tx_timeout		= mlx4_en_tx_timeout,
	.ndo_vlan_rx_add_vid	= mlx4_en_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid	= mlx4_en_vlan_rx_kill_vid,
	.ndo_set_vf_mac		= mlx4_en_set_vf_mac,
	.ndo_set_vf_vlan	= mlx4_en_set_vf_vlan,
	.ndo_set_vf_spoofchk	= mlx4_en_set_vf_spoofchk,
	.ndo_get_vf_config	= mlx4_en_get_vf_config,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= mlx4_en_netpoll,
#endif
	.ndo_set_features	= mlx4_en_set_features,
	.ndo_setup_tc		= mlx4_en_setup_tc,
#ifdef CONFIG_RFS_ACCEL
	.ndo_rx_flow_steer	= mlx4_en_filter_rfs,
#endif
};

int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
			struct mlx4_en_port_profile *prof)
{
@@ -2163,6 +2227,9 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
	/*
	 * Initialize netdev entry points
	 */
	if (mlx4_is_master(priv->mdev->dev))
		dev->netdev_ops = &mlx4_netdev_ops_master;
	else
		dev->netdev_ops = &mlx4_netdev_ops;
	dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
	netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
@@ -2228,8 +2295,11 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
	}
	mlx4_en_set_default_moderation(priv);
	queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);

	if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
		queue_delayed_work(mdev->workqueue, &priv->service_task,
				   SERVICE_TASK_DELAY);

	return 0;

out:
+16 −0
Original line number Diff line number Diff line
@@ -468,6 +468,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_RSVD_XRC_OFFSET		0x66
#define QUERY_DEV_CAP_MAX_XRC_OFFSET		0x67
#define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET	0x68
#define QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET	0x70
#define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET	0x76
#define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET	0x77
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET	0x80
@@ -655,6 +656,12 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
		MLX4_GET(dev_cap->max_counters, outbox,
			 QUERY_DEV_CAP_MAX_COUNTERS_OFFSET);

	MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
	if (field32 & (1 << 26))
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL;
	if (field32 & (1 << 20))
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FSM;

	if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
		for (i = 1; i <= dev_cap->num_ports; ++i) {
			MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
@@ -784,6 +791,11 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
	flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW;
	MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);

	/* For guests, disable timestamp */
	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
	field &= 0x7f;
	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);

	/* For guests, report Blueflame disabled */
	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET);
	field &= 0x7f;
@@ -811,6 +823,7 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
			    struct mlx4_cmd_mailbox *outbox,
			    struct mlx4_cmd_info *cmd)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	u64 def_mac;
	u8 port_type;
	u16 short_field;
@@ -828,6 +841,9 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
		/* set slave default_mac address */
		MLX4_GET(def_mac, outbox->buf, QUERY_PORT_MAC_OFFSET);
		def_mac += slave << 8;
		/* if config MAC in DB use it */
		if (priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac)
			def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac;
		MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET);

		/* get port type - currently only eth is enabled */
+28 −0
Original line number Diff line number Diff line
@@ -473,6 +473,30 @@ struct mlx4_slave_state {
	enum slave_port_state port_state[MLX4_MAX_PORTS + 1];
};

#define MLX4_VGT 4095
#define NO_INDX  (-1)

struct mlx4_vport_state {
	u64 mac;
	u16 default_vlan;
	u8  default_qos;
	u32 tx_rate;
	bool spoofchk;
};

struct mlx4_vf_admin_state {
	struct mlx4_vport_state vport[MLX4_MAX_PORTS + 1];
};

struct mlx4_vport_oper_state {
	struct mlx4_vport_state state;
	int mac_idx;
	int vlan_idx;
};
struct mlx4_vf_oper_state {
	struct mlx4_vport_oper_state vport[MLX4_MAX_PORTS + 1];
};

struct slave_list {
	struct mutex mutex;
	struct list_head res_list[MLX4_NUM_OF_RESOURCE_TYPE];
@@ -503,6 +527,8 @@ struct mlx4_master_qp0_state {

struct mlx4_mfunc_master_ctx {
	struct mlx4_slave_state *slave_state;
	struct mlx4_vf_admin_state *vf_admin;
	struct mlx4_vf_oper_state *vf_oper;
	struct mlx4_master_qp0_state qp0_state[MLX4_MAX_PORTS + 1];
	int			init_port_ref[MLX4_MAX_PORTS + 1];
	u16			max_mtu[MLX4_MAX_PORTS + 1];
@@ -1131,6 +1157,8 @@ int mlx4_change_port_types(struct mlx4_dev *dev,

void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index);
int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);

int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz);
/* resource tracker functions*/
+12 −7
Original line number Diff line number Diff line
@@ -141,8 +141,9 @@ int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
		}

		if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
			/* MAC already registered, Must not have duplicates */
			err = -EEXIST;
			/* MAC already registered, increment ref count */
			err = i;
			++table->refs[i];
			goto out;
		}
	}
@@ -165,7 +166,7 @@ int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
		table->entries[free] = 0;
		goto out;
	}

	table->refs[free] = 1;
	err = free;
	++table->total;
out:
@@ -206,12 +207,16 @@ void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
	struct mlx4_mac_table *table = &info->mac_table;
	int index;

	index = find_index(dev, table, mac);

	mutex_lock(&table->mutex);
	index = find_index(dev, table, mac);

	if (validate_index(dev, table, index))
		goto out;
	if (--table->refs[index]) {
		mlx4_dbg(dev, "Have more references for index %d,"
			 "no need to modify mac table\n", index);
		goto out;
	}

	table->entries[index] = 0;
	mlx4_set_port_mac_table(dev, port, table->entries);
@@ -305,7 +310,7 @@ int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx)
}
EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan);

static int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan,
int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan,
				int *index)
{
	struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
@@ -379,7 +384,7 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
}
EXPORT_SYMBOL_GPL(mlx4_register_vlan);

static void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
{
	struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;

Loading