diff options
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.c | 71 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/qp.c | 38 |
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 */ | ||
| 1371 | static 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 | |||
| 1368 | int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave, | 1381 | int 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 | ||
| 70 | static int is_qp0(struct mlx4_dev *dev, struct mlx4_qp *qp) | 70 | /* used for INIT/CLOSE port logic */ |
| 71 | static 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 | ||
| 76 | static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, | 84 | static 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 | } |
