aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}