Commit 0a6eac24 authored by Rony Efraim's avatar Rony Efraim Committed by David S. Miller

net/mlx4_core: Add HW enforcement to VF link state

When the firmware supports the UPDATE_QP command, if the VF link is disabled,
block all QPs opened by the VF, by programming the UPDATE_QP command to drop
all RX & TX traffic to/from these QPs. Operates only in VST mode.
Signed-off-by: default avatarRony Efraim <ronye@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b01978ca
...@@ -1521,6 +1521,10 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, ...@@ -1521,6 +1521,10 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
return ret; return ret;
} }
static int calculate_transition(u16 oper_vlan, u16 admin_vlan)
{
return (2 * (oper_vlan == MLX4_VGT) + (admin_vlan == MLX4_VGT));
}
int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv, int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv,
int slave, int port) int slave, int port)
...@@ -1528,16 +1532,37 @@ int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv, ...@@ -1528,16 +1532,37 @@ int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv,
struct mlx4_vport_oper_state *vp_oper; struct mlx4_vport_oper_state *vp_oper;
struct mlx4_vport_state *vp_admin; struct mlx4_vport_state *vp_admin;
struct mlx4_vf_immed_vlan_work *work; struct mlx4_vf_immed_vlan_work *work;
struct mlx4_dev *dev = &(priv->dev);
int err; int err;
int admin_vlan_ix = NO_INDX; int admin_vlan_ix = NO_INDX;
enum mlx4_vlan_transition vlan_trans;
vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port]; vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
if (vp_oper->state.default_vlan == vp_admin->default_vlan && if (vp_oper->state.default_vlan == vp_admin->default_vlan &&
vp_oper->state.default_qos == vp_admin->default_qos) vp_oper->state.default_qos == vp_admin->default_qos &&
vp_oper->state.link_state == vp_admin->link_state)
return 0; return 0;
vlan_trans = calculate_transition(vp_oper->state.default_vlan,
vp_admin->default_vlan);
if (!(priv->mfunc.master.slave_state[slave].active &&
dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP &&
vlan_trans == MLX4_VLAN_TRANSITION_VST_VST)) {
/* even if the UPDATE_QP command isn't supported, we still want
* to set this VF link according to the admin directive
*/
vp_oper->state.link_state = vp_admin->link_state;
return -1;
}
mlx4_dbg(dev, "updating immediately admin params slave %d port %d\n",
slave, port);
mlx4_dbg(dev, "vlan %d QoS %d link down %d\n", vp_admin->default_vlan,
vp_admin->default_qos, vp_admin->link_state);
work = kzalloc(sizeof(*work), GFP_KERNEL); work = kzalloc(sizeof(*work), GFP_KERNEL);
if (!work) if (!work)
return -ENOMEM; return -ENOMEM;
...@@ -1572,6 +1597,10 @@ int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv, ...@@ -1572,6 +1597,10 @@ int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv,
vp_oper->state.default_vlan = vp_admin->default_vlan; vp_oper->state.default_vlan = vp_admin->default_vlan;
vp_oper->state.default_qos = vp_admin->default_qos; vp_oper->state.default_qos = vp_admin->default_qos;
vp_oper->state.link_state = vp_admin->link_state;
if (vp_admin->link_state == IFLA_VF_LINK_STATE_DISABLE)
work->flags |= MLX4_VF_IMMED_VLAN_FLAG_LINK_DISABLE;
/* iterate over QPs owned by this slave, using UPDATE_QP */ /* iterate over QPs owned by this slave, using UPDATE_QP */
work->port = port; work->port = port;
...@@ -2201,10 +2230,6 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac) ...@@ -2201,10 +2230,6 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac)
} }
EXPORT_SYMBOL_GPL(mlx4_set_vf_mac); EXPORT_SYMBOL_GPL(mlx4_set_vf_mac);
static int calculate_transition(u16 oper_vlan, u16 admin_vlan)
{
return (2 * (oper_vlan == MLX4_VGT) + (admin_vlan == MLX4_VGT));
}
int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos) int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
{ {
...@@ -2212,7 +2237,6 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos) ...@@ -2212,7 +2237,6 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
struct mlx4_vport_oper_state *vf_oper; struct mlx4_vport_oper_state *vf_oper;
struct mlx4_vport_state *vf_admin; struct mlx4_vport_state *vf_admin;
int slave; int slave;
enum mlx4_vlan_transition vlan_trans;
if ((!mlx4_is_master(dev)) || if ((!mlx4_is_master(dev)) ||
!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL)) !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL))
...@@ -2234,16 +2258,10 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos) ...@@ -2234,16 +2258,10 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
vf_admin->default_vlan = vlan; vf_admin->default_vlan = vlan;
vf_admin->default_qos = qos; vf_admin->default_qos = qos;
vlan_trans = calculate_transition(vf_oper->state.default_vlan, if (mlx4_master_immediate_activate_vlan_qos(priv, slave, port))
vf_admin->default_vlan); mlx4_info(dev,
"updating vf %d port %d config will take effect on next VF restart\n",
if (priv->mfunc.master.slave_state[slave].active &&
dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP &&
vlan_trans == MLX4_VLAN_TRANSITION_VST_VST) {
mlx4_info(dev, "updating vf %d port %d config params immediately\n",
vf, port); vf, port);
mlx4_master_immediate_activate_vlan_qos(priv, slave, port);
}
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan); EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan);
...@@ -2307,7 +2325,6 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat ...@@ -2307,7 +2325,6 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat
{ {
struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_vport_state *s_info; struct mlx4_vport_state *s_info;
struct mlx4_vport_oper_state *vp_oper;
int slave; int slave;
u8 link_stat_event; u8 link_stat_event;
...@@ -2337,14 +2354,16 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat ...@@ -2337,14 +2354,16 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat
link_state, slave, port); link_state, slave, port);
return -EINVAL; return -EINVAL;
}; };
/* update the admin & oper state on the link state */
s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
s_info->link_state = link_state; s_info->link_state = link_state;
vp_oper->state.link_state = link_state;
/* send event */ /* send event */
mlx4_gen_port_state_change_eqe(dev, slave, port, link_stat_event); mlx4_gen_port_state_change_eqe(dev, slave, port, link_stat_event);
if (mlx4_master_immediate_activate_vlan_qos(priv, slave, port))
mlx4_dbg(dev,
"updating vf %d port %d no link state HW enforcment\n",
vf, port);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(mlx4_set_vf_link_state); EXPORT_SYMBOL_GPL(mlx4_set_vf_link_state);
...@@ -574,6 +574,7 @@ struct mlx4_cmd { ...@@ -574,6 +574,7 @@ struct mlx4_cmd {
enum { enum {
MLX4_VF_IMMED_VLAN_FLAG_VLAN = 1 << 0, MLX4_VF_IMMED_VLAN_FLAG_VLAN = 1 << 0,
MLX4_VF_IMMED_VLAN_FLAG_QOS = 1 << 1, MLX4_VF_IMMED_VLAN_FLAG_QOS = 1 << 1,
MLX4_VF_IMMED_VLAN_FLAG_LINK_DISABLE = 1 << 2,
}; };
struct mlx4_vf_immed_vlan_work { struct mlx4_vf_immed_vlan_work {
struct work_struct work; struct work_struct work;
......
...@@ -384,7 +384,17 @@ static int update_vport_qp_param(struct mlx4_dev *dev, ...@@ -384,7 +384,17 @@ static int update_vport_qp_param(struct mlx4_dev *dev,
/* force strip vlan by clear vsd */ /* force strip vlan by clear vsd */
qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN); qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN);
if (0 != vp_oper->state.default_vlan) {
if (vp_oper->state.link_state == IFLA_VF_LINK_STATE_DISABLE &&
dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP) {
qpc->pri_path.vlan_control =
MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED |
MLX4_VLAN_CTRL_ETH_TX_BLOCK_UNTAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
} else if (0 != vp_oper->state.default_vlan) {
qpc->pri_path.vlan_control = qpc->pri_path.vlan_control =
MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED | MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |
...@@ -4002,8 +4012,14 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work) ...@@ -4002,8 +4012,14 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)
mailbox = mlx4_alloc_cmd_mailbox(dev); mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox)) if (IS_ERR(mailbox))
goto out; goto out;
if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_LINK_DISABLE) /* block all */
if (!work->vlan_id) vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED |
MLX4_VLAN_CTRL_ETH_TX_BLOCK_UNTAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
else if (!work->vlan_id)
vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED; MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
else else
......
...@@ -152,6 +152,8 @@ enum { /* fl */ ...@@ -152,6 +152,8 @@ enum { /* fl */
}; };
enum { /* vlan_control */ enum { /* vlan_control */
MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED = 1 << 6, MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED = 1 << 6,
MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED = 1 << 5, /* 802.1p priority tag */
MLX4_VLAN_CTRL_ETH_TX_BLOCK_UNTAGGED = 1 << 4,
MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED = 1 << 2, MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED = 1 << 2,
MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED = 1 << 1, /* 802.1p priority tag */ MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED = 1 << 1, /* 802.1p priority tag */
MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED = 1 << 0 MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED = 1 << 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment