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 | } |