aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx4/cmd.c
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2013-06-27 12:05:21 -0400
committerDavid S. Miller <davem@davemloft.net>2013-07-01 16:10:22 -0400
commitb01978cacfd7e3a4ca703b0e48f2e18de8865df5 (patch)
tree73beae91335dbcf4a4129b3970be68f1082aff0b /drivers/net/ethernet/mellanox/mlx4/cmd.c
parent4e144d3a807d6d2aa03d2cb234d88ef1a140e8c3 (diff)
net/mlx4_core: Dynamic VST to VST vlan/qos changes
Within VST mode, enable modifying the vlan and/or qos for a VF without requiring unbind/rebind. This requires firmware which supports the UPDATE_QP command. (If the command is not available, we fall back to requiring unbind/bind to activate these changes). To avoid race conditions with modify-qp on QPs that are affected by update-qp, this operation is performed on the comm_wq. If the update operation succeeds for all the necessary QPs, a vlan_unregister is performed for the abandoned vlan id. Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/cmd.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c122
1 files changed, 117 insertions, 5 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index df04c8206ebe..7b927891dc35 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -112,6 +112,14 @@ enum {
112 GO_BIT_TIMEOUT_MSECS = 10000 112 GO_BIT_TIMEOUT_MSECS = 10000
113}; 113};
114 114
115enum mlx4_vlan_transition {
116 MLX4_VLAN_TRANSITION_VST_VST = 0,
117 MLX4_VLAN_TRANSITION_VST_VGT = 1,
118 MLX4_VLAN_TRANSITION_VGT_VST = 2,
119 MLX4_VLAN_TRANSITION_VGT_VGT = 3,
120};
121
122
115struct mlx4_cmd_context { 123struct mlx4_cmd_context {
116 struct completion done; 124 struct completion done;
117 int result; 125 int result;
@@ -792,6 +800,15 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave,
792 vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); 800 vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
793} 801}
794 802
803int MLX4_CMD_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
804 struct mlx4_vhcr *vhcr,
805 struct mlx4_cmd_mailbox *inbox,
806 struct mlx4_cmd_mailbox *outbox,
807 struct mlx4_cmd_info *cmd)
808{
809 return -EPERM;
810}
811
795int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, 812int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave,
796 struct mlx4_vhcr *vhcr, 813 struct mlx4_vhcr *vhcr,
797 struct mlx4_cmd_mailbox *inbox, 814 struct mlx4_cmd_mailbox *inbox,
@@ -1226,6 +1243,15 @@ static struct mlx4_cmd_info cmd_info[] = {
1226 .wrapper = mlx4_GEN_QP_wrapper 1243 .wrapper = mlx4_GEN_QP_wrapper
1227 }, 1244 },
1228 { 1245 {
1246 .opcode = MLX4_CMD_UPDATE_QP,
1247 .has_inbox = false,
1248 .has_outbox = false,
1249 .out_is_imm = false,
1250 .encode_slave_id = false,
1251 .verify = NULL,
1252 .wrapper = MLX4_CMD_UPDATE_QP_wrapper
1253 },
1254 {
1229 .opcode = MLX4_CMD_CONF_SPECIAL_QP, 1255 .opcode = MLX4_CMD_CONF_SPECIAL_QP,
1230 .has_inbox = false, 1256 .has_inbox = false,
1231 .has_outbox = false, 1257 .has_outbox = false,
@@ -1495,6 +1521,72 @@ out:
1495 return ret; 1521 return ret;
1496} 1522}
1497 1523
1524
1525int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv,
1526 int slave, int port)
1527{
1528 struct mlx4_vport_oper_state *vp_oper;
1529 struct mlx4_vport_state *vp_admin;
1530 struct mlx4_vf_immed_vlan_work *work;
1531 int err;
1532 int admin_vlan_ix = NO_INDX;
1533
1534 vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
1535 vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
1536
1537 if (vp_oper->state.default_vlan == vp_admin->default_vlan &&
1538 vp_oper->state.default_qos == vp_admin->default_qos)
1539 return 0;
1540
1541 work = kzalloc(sizeof(*work), GFP_KERNEL);
1542 if (!work)
1543 return -ENOMEM;
1544
1545 if (vp_oper->state.default_vlan != vp_admin->default_vlan) {
1546 err = __mlx4_register_vlan(&priv->dev, port,
1547 vp_admin->default_vlan,
1548 &admin_vlan_ix);
1549 if (err) {
1550 mlx4_warn((&priv->dev),
1551 "No vlan resources slave %d, port %d\n",
1552 slave, port);
1553 return err;
1554 }
1555 work->flags |= MLX4_VF_IMMED_VLAN_FLAG_VLAN;
1556 mlx4_dbg((&(priv->dev)),
1557 "alloc vlan %d idx %d slave %d port %d\n",
1558 (int)(vp_admin->default_vlan),
1559 admin_vlan_ix, slave, port);
1560 }
1561
1562 /* save original vlan ix and vlan id */
1563 work->orig_vlan_id = vp_oper->state.default_vlan;
1564 work->orig_vlan_ix = vp_oper->vlan_idx;
1565
1566 /* handle new qos */
1567 if (vp_oper->state.default_qos != vp_admin->default_qos)
1568 work->flags |= MLX4_VF_IMMED_VLAN_FLAG_QOS;
1569
1570 if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN)
1571 vp_oper->vlan_idx = admin_vlan_ix;
1572
1573 vp_oper->state.default_vlan = vp_admin->default_vlan;
1574 vp_oper->state.default_qos = vp_admin->default_qos;
1575
1576 /* iterate over QPs owned by this slave, using UPDATE_QP */
1577 work->port = port;
1578 work->slave = slave;
1579 work->qos = vp_oper->state.default_qos;
1580 work->vlan_id = vp_oper->state.default_vlan;
1581 work->vlan_ix = vp_oper->vlan_idx;
1582 work->priv = priv;
1583 INIT_WORK(&work->work, mlx4_vf_immed_vlan_work_handler);
1584 queue_work(priv->mfunc.master.comm_wq, &work->work);
1585
1586 return 0;
1587}
1588
1589
1498static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave) 1590static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
1499{ 1591{
1500 int port, err; 1592 int port, err;
@@ -2109,11 +2201,18 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac)
2109} 2201}
2110EXPORT_SYMBOL_GPL(mlx4_set_vf_mac); 2202EXPORT_SYMBOL_GPL(mlx4_set_vf_mac);
2111 2203
2204static int calculate_transition(u16 oper_vlan, u16 admin_vlan)
2205{
2206 return (2 * (oper_vlan == MLX4_VGT) + (admin_vlan == MLX4_VGT));
2207}
2208
2112int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos) 2209int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
2113{ 2210{
2114 struct mlx4_priv *priv = mlx4_priv(dev); 2211 struct mlx4_priv *priv = mlx4_priv(dev);
2115 struct mlx4_vport_state *s_info; 2212 struct mlx4_vport_oper_state *vf_oper;
2213 struct mlx4_vport_state *vf_admin;
2116 int slave; 2214 int slave;
2215 enum mlx4_vlan_transition vlan_trans;
2117 2216
2118 if ((!mlx4_is_master(dev)) || 2217 if ((!mlx4_is_master(dev)) ||
2119 !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL)) 2218 !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL))
@@ -2126,12 +2225,25 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
2126 if (slave < 0) 2225 if (slave < 0)
2127 return -EINVAL; 2226 return -EINVAL;
2128 2227
2129 s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; 2228 vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
2229 vf_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
2230
2130 if ((0 == vlan) && (0 == qos)) 2231 if ((0 == vlan) && (0 == qos))
2131 s_info->default_vlan = MLX4_VGT; 2232 vf_admin->default_vlan = MLX4_VGT;
2132 else 2233 else
2133 s_info->default_vlan = vlan; 2234 vf_admin->default_vlan = vlan;
2134 s_info->default_qos = qos; 2235 vf_admin->default_qos = qos;
2236
2237 vlan_trans = calculate_transition(vf_oper->state.default_vlan,
2238 vf_admin->default_vlan);
2239
2240 if (priv->mfunc.master.slave_state[slave].active &&
2241 dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP &&
2242 vlan_trans == MLX4_VLAN_TRANSITION_VST_VST) {
2243 mlx4_info(dev, "updating vf %d port %d config params immediately\n",
2244 vf, port);
2245 mlx4_master_immediate_activate_vlan_qos(priv, slave, port);
2246 }
2135 return 0; 2247 return 0;
2136} 2248}
2137EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan); 2249EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan);