Skip to content

Commit

Permalink
net/mlx4: Add set VF default vlan ID and priority support
Browse files Browse the repository at this point in the history
Add support to ndo_set_vf_vlan in the driver. Once this call is used the vport
is considered to be in VST mode. In this mode, the PPF driver configures
Ethernet QPs created by this VF to use this vlan id and priority. Currently
RoCE isn't supported on that mode.

The special values of VID=4095 or VID=0,UP=0 are considered as VGT.

Signed-off-by: Rony Efraim <ronye@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Rony Efraim authored and David S. Miller committed Apr 27, 2013
1 parent 8f7ba3c commit 3f7fb02
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 7 deletions.
72 changes: 68 additions & 4 deletions drivers/net/ethernet/mellanox/mlx4/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1492,14 +1492,48 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,

static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
{
int port;
int port, err;
struct mlx4_vport_state *vp_admin;
struct mlx4_vport_oper_state *vp_oper;

for (port = 1; port <= MLX4_MAX_PORTS; port++) {
priv->mfunc.master.vf_oper[slave].vport[port].state =
priv->mfunc.master.vf_admin[slave].vport[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);
}
}
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;
}
}
return;
}

static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
u16 param, u8 toggle)
{
Expand All @@ -1520,6 +1554,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;
Expand Down Expand Up @@ -1566,7 +1601,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;
mlx4_master_activate_admin_state(priv, slave);
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;
Expand Down Expand Up @@ -1776,6 +1812,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
}
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;
}
Expand Down Expand Up @@ -2047,3 +2084,30 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 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);
9 changes: 9 additions & 0 deletions drivers/net/ethernet/mellanox/mlx4/en_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2036,6 +2036,14 @@ static int mlx4_en_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
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 const struct net_device_ops mlx4_netdev_ops = {
.ndo_open = mlx4_en_open,
Expand Down Expand Up @@ -2075,6 +2083,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
.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,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = mlx4_en_netpoll,
#endif
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/mellanox/mlx4/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -655,6 +656,10 @@ 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 (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);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/mellanox/mlx4/mlx4.h
Original file line number Diff line number Diff line change
Expand Up @@ -1157,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*/
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/mellanox/mlx4/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,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;
Expand Down Expand Up @@ -384,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;

Expand Down
36 changes: 36 additions & 0 deletions drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,39 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
}
}

static int update_vport_qp_param(struct mlx4_dev *dev,
struct mlx4_cmd_mailbox *inbox,
u8 slave)
{
struct mlx4_qp_context *qpc = inbox->buf + 8;
struct mlx4_vport_oper_state *vp_oper;
struct mlx4_priv *priv;
u32 qp_type;
int port;

port = (qpc->pri_path.sched_queue & 0x40) ? 2 : 1;
priv = mlx4_priv(dev);
vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];

if (MLX4_VGT != vp_oper->state.default_vlan) {
qp_type = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
if (MLX4_QP_ST_RC == qp_type)
return -EINVAL;

qpc->pri_path.vlan_index = vp_oper->vlan_idx;
qpc->pri_path.fl = (1 << 6) | (1 << 2); /* set cv bit and hide_cqe_vlan bit*/
qpc->pri_path.feup |= 1 << 3; /* set fvl bit */
qpc->pri_path.sched_queue &= 0xC7;
qpc->pri_path.sched_queue |= (vp_oper->state.default_qos) << 3;
mlx4_dbg(dev, "qp %d port %d Q 0x%x set vlan to %d vidx %d feup %x fl %x\n",
be32_to_cpu(qpc->local_qpn) & 0xffffff, port,
(int)(qpc->pri_path.sched_queue), vp_oper->state.default_vlan,
vp_oper->vlan_idx, (int)(qpc->pri_path.feup),
(int)(qpc->pri_path.fl));
}
return 0;
}

static int mpt_mask(struct mlx4_dev *dev)
{
return dev->caps.num_mpts - 1;
Expand Down Expand Up @@ -2798,6 +2831,9 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
update_pkey_index(dev, slave, inbox);
update_gid(dev, inbox, (u8)slave);
adjust_proxy_tun_qkey(dev, vhcr, qpc);
err = update_vport_qp_param(dev, inbox, slave);
if (err)
return err;

return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
}
Expand Down
2 changes: 2 additions & 0 deletions include/linux/mlx4/cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbo

u32 mlx4_comm_get_version(void);
int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac);
int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos);


#define MLX4_COMM_GET_IF_REV(cmd_chan_ver) (u8)((cmd_chan_ver) >> 8)

Expand Down
3 changes: 2 additions & 1 deletion include/linux/mlx4/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ enum {
MLX4_DEV_CAP_FLAG2_RSS_XOR = 1LL << 2,
MLX4_DEV_CAP_FLAG2_FS_EN = 1LL << 3,
MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN = 1LL << 4,
MLX4_DEV_CAP_FLAG2_TS = 1LL << 5
MLX4_DEV_CAP_FLAG2_TS = 1LL << 5,
MLX4_DEV_CAP_FLAG2_VLAN_CONTROL = 1LL << 6
};

enum {
Expand Down

0 comments on commit 3f7fb02

Please sign in to comment.