aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2012-08-03 04:40:53 -0400
committerRoland Dreier <roland@purestorage.com>2012-09-30 23:33:40 -0400
commit980e90010f15362b3b02ed4875ef2758aee3de72 (patch)
tree19002a65fe83c67c8d2da8d9273094fe46380d86
parentefcd235d736ab05ef2b29d7fe1493a2f52b07b66 (diff)
mlx4_core: INIT/CLOSE port logic for IB ports in SR-IOV mode
Normally, INIT_PORT and CLOSE_PORT are invoked when special QP0 transitions to RTR, or transitions to ERR/RESET respectively. In SR-IOV mode, however, the master is also paravirtualized. This in turn requires that we not do INIT_PORT until the entire QP0 path (real QP0 and proxy QP0) is ready to receive. When the real QP0 goes down, we should indicate that the port is not active. Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c71
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/qp.c38
2 files changed, 92 insertions, 17 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index b78803937897..bf159c0fe82b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -1365,6 +1365,19 @@ out:
1365 return err; 1365 return err;
1366} 1366}
1367 1367
1368/* for IB-type ports only in SRIOV mode. Checks that both proxy QP0
1369 * and real QP0 are active, so that the paravirtualized QP0 is ready
1370 * to operate */
1371static int check_qp0_state(struct mlx4_dev *dev, int function, int port)
1372{
1373 struct mlx4_priv *priv = mlx4_priv(dev);
1374 /* irrelevant if not infiniband */
1375 if (priv->mfunc.master.qp0_state[port].proxy_qp0_active &&
1376 priv->mfunc.master.qp0_state[port].qp0_active)
1377 return 1;
1378 return 0;
1379}
1380
1368int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave, 1381int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave,
1369 struct mlx4_vhcr *vhcr, 1382 struct mlx4_vhcr *vhcr,
1370 struct mlx4_cmd_mailbox *inbox, 1383 struct mlx4_cmd_mailbox *inbox,
@@ -1381,14 +1394,29 @@ int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave,
1381 if (dev->caps.port_mask[port] == MLX4_PORT_TYPE_IB) 1394 if (dev->caps.port_mask[port] == MLX4_PORT_TYPE_IB)
1382 return -ENODEV; 1395 return -ENODEV;
1383 1396
1384 /* Enable port only if it was previously disabled */ 1397 if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) {
1385 if (!priv->mfunc.master.init_port_ref[port]) { 1398 /* Enable port only if it was previously disabled */
1386 err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT, 1399 if (!priv->mfunc.master.init_port_ref[port]) {
1387 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 1400 err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
1388 if (err) 1401 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
1389 return err; 1402 if (err)
1403 return err;
1404 }
1405 priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
1406 } else {
1407 if (slave == mlx4_master_func_num(dev)) {
1408 if (check_qp0_state(dev, slave, port) &&
1409 !priv->mfunc.master.qp0_state[port].port_active) {
1410 err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
1411 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
1412 if (err)
1413 return err;
1414 priv->mfunc.master.qp0_state[port].port_active = 1;
1415 priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
1416 }
1417 } else
1418 priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
1390 } 1419 }
1391 priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
1392 ++priv->mfunc.master.init_port_ref[port]; 1420 ++priv->mfunc.master.init_port_ref[port];
1393 return 0; 1421 return 0;
1394} 1422}
@@ -1463,13 +1491,30 @@ int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave,
1463 1491
1464 if (dev->caps.port_mask[port] == MLX4_PORT_TYPE_IB) 1492 if (dev->caps.port_mask[port] == MLX4_PORT_TYPE_IB)
1465 return -ENODEV; 1493 return -ENODEV;
1466 if (priv->mfunc.master.init_port_ref[port] == 1) { 1494
1467 err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000, 1495 if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) {
1468 MLX4_CMD_NATIVE); 1496 if (priv->mfunc.master.init_port_ref[port] == 1) {
1469 if (err) 1497 err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT,
1470 return err; 1498 1000, MLX4_CMD_NATIVE);
1499 if (err)
1500 return err;
1501 }
1502 priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
1503 } else {
1504 /* infiniband port */
1505 if (slave == mlx4_master_func_num(dev)) {
1506 if (!priv->mfunc.master.qp0_state[port].qp0_active &&
1507 priv->mfunc.master.qp0_state[port].port_active) {
1508 err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT,
1509 1000, MLX4_CMD_NATIVE);
1510 if (err)
1511 return err;
1512 priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
1513 priv->mfunc.master.qp0_state[port].port_active = 0;
1514 }
1515 } else
1516 priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
1471 } 1517 }
1472 priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
1473 --priv->mfunc.master.init_port_ref[port]; 1518 --priv->mfunc.master.init_port_ref[port];
1474 return 0; 1519 return 0;
1475} 1520}
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index b8da72b29cf7..436ef6c69add 100644
--- a/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -67,10 +67,18 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type)
67 complete(&qp->free); 67 complete(&qp->free);
68} 68}
69 69
70static int is_qp0(struct mlx4_dev *dev, struct mlx4_qp *qp) 70/* used for INIT/CLOSE port logic */
71static int is_qp0(struct mlx4_dev *dev, struct mlx4_qp *qp, int *real_qp0, int *proxy_qp0)
71{ 72{
72 return qp->qpn >= dev->caps.sqp_start && 73 /* qp0 is either the proxy qp0, or the real qp0 */
74 *proxy_qp0 = qp->qpn >= dev->caps.sqp_start &&
73 qp->qpn <= dev->caps.sqp_start + 1; 75 qp->qpn <= dev->caps.sqp_start + 1;
76
77 *real_qp0 = mlx4_is_master(dev) &&
78 qp->qpn >= dev->caps.base_sqpn &&
79 qp->qpn <= dev->caps.base_sqpn + 1;
80
81 return *real_qp0 || *proxy_qp0;
74} 82}
75 83
76static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, 84static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
@@ -122,6 +130,8 @@ static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
122 struct mlx4_priv *priv = mlx4_priv(dev); 130 struct mlx4_priv *priv = mlx4_priv(dev);
123 struct mlx4_cmd_mailbox *mailbox; 131 struct mlx4_cmd_mailbox *mailbox;
124 int ret = 0; 132 int ret = 0;
133 int real_qp0 = 0;
134 int proxy_qp0 = 0;
125 u8 port; 135 u8 port;
126 136
127 if (cur_state >= MLX4_QP_NUM_STATE || new_state >= MLX4_QP_NUM_STATE || 137 if (cur_state >= MLX4_QP_NUM_STATE || new_state >= MLX4_QP_NUM_STATE ||
@@ -133,9 +143,12 @@ static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
133 MLX4_CMD_2RST_QP, MLX4_CMD_TIME_CLASS_A, native); 143 MLX4_CMD_2RST_QP, MLX4_CMD_TIME_CLASS_A, native);
134 if (mlx4_is_master(dev) && cur_state != MLX4_QP_STATE_ERR && 144 if (mlx4_is_master(dev) && cur_state != MLX4_QP_STATE_ERR &&
135 cur_state != MLX4_QP_STATE_RST && 145 cur_state != MLX4_QP_STATE_RST &&
136 is_qp0(dev, qp)) { 146 is_qp0(dev, qp, &real_qp0, &proxy_qp0)) {
137 port = (qp->qpn & 1) + 1; 147 port = (qp->qpn & 1) + 1;
138 priv->mfunc.master.qp0_state[port].qp0_active = 0; 148 if (proxy_qp0)
149 priv->mfunc.master.qp0_state[port].proxy_qp0_active = 0;
150 else
151 priv->mfunc.master.qp0_state[port].qp0_active = 0;
139 } 152 }
140 return ret; 153 return ret;
141 } 154 }
@@ -162,6 +175,23 @@ static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
162 new_state == MLX4_QP_STATE_RST ? 2 : 0, 175 new_state == MLX4_QP_STATE_RST ? 2 : 0,
163 op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C, native); 176 op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C, native);
164 177
178 if (mlx4_is_master(dev) && is_qp0(dev, qp, &real_qp0, &proxy_qp0)) {
179 port = (qp->qpn & 1) + 1;
180 if (cur_state != MLX4_QP_STATE_ERR &&
181 cur_state != MLX4_QP_STATE_RST &&
182 new_state == MLX4_QP_STATE_ERR) {
183 if (proxy_qp0)
184 priv->mfunc.master.qp0_state[port].proxy_qp0_active = 0;
185 else
186 priv->mfunc.master.qp0_state[port].qp0_active = 0;
187 } else if (new_state == MLX4_QP_STATE_RTR) {
188 if (proxy_qp0)
189 priv->mfunc.master.qp0_state[port].proxy_qp0_active = 1;
190 else
191 priv->mfunc.master.qp0_state[port].qp0_active = 1;
192 }
193 }
194
165 mlx4_free_cmd_mailbox(dev, mailbox); 195 mlx4_free_cmd_mailbox(dev, mailbox);
166 return ret; 196 return ret;
167} 197}