Commit 25476b02 authored by Jack Morgenstein's avatar Jack Morgenstein Committed by Roland Dreier

IB/mlx4: Fix VF mac handling in RoCE

We had several problems here.  First, a race condition on QP1 mac
handling between mlx4_ib_update_qps and mlx4_ib_modify_qp, which is
fixed by taking the qp mutex in mlx4_ib_update_qps.

Also, qp->pri.smac_port was not updated in mlx4_ib_update_qps.

Last, in __mlx4_ib_modify_qp we did not properly handle the case where
the mac is zero, but port is non-zero.
Signed-off-by: default avatarJack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 3dec4878
...@@ -1667,9 +1667,11 @@ static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev, ...@@ -1667,9 +1667,11 @@ static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev,
qp = ibdev->qp1_proxy[port - 1]; qp = ibdev->qp1_proxy[port - 1];
if (qp) { if (qp) {
int new_smac_index; int new_smac_index;
u64 old_smac = qp->pri.smac; u64 old_smac;
struct mlx4_update_qp_params update_params; struct mlx4_update_qp_params update_params;
mutex_lock(&qp->mutex);
old_smac = qp->pri.smac;
if (new_smac == old_smac) if (new_smac == old_smac)
goto unlock; goto unlock;
...@@ -1684,17 +1686,20 @@ static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev, ...@@ -1684,17 +1686,20 @@ static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev,
release_mac = new_smac; release_mac = new_smac;
goto unlock; goto unlock;
} }
/* if old port was zero, no mac was yet registered for this QP */
if (qp->pri.smac_port)
release_mac = old_smac;
qp->pri.smac = new_smac; qp->pri.smac = new_smac;
qp->pri.smac_port = port;
qp->pri.smac_index = new_smac_index; qp->pri.smac_index = new_smac_index;
release_mac = old_smac;
} }
unlock: unlock:
mutex_unlock(&ibdev->qp1_proxy_lock[port - 1]);
if (release_mac != MLX4_IB_INVALID_MAC) if (release_mac != MLX4_IB_INVALID_MAC)
mlx4_unregister_mac(ibdev->dev, port, release_mac); mlx4_unregister_mac(ibdev->dev, port, release_mac);
if (qp)
mutex_unlock(&qp->mutex);
mutex_unlock(&ibdev->qp1_proxy_lock[port - 1]);
} }
static void mlx4_ib_get_dev_addr(struct net_device *dev, static void mlx4_ib_get_dev_addr(struct net_device *dev,
......
...@@ -964,9 +964,10 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, ...@@ -964,9 +964,10 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
MLX4_QP_STATE_RST, NULL, 0, 0, &qp->mqp)) MLX4_QP_STATE_RST, NULL, 0, 0, &qp->mqp))
pr_warn("modify QP %06x to RESET failed.\n", pr_warn("modify QP %06x to RESET failed.\n",
qp->mqp.qpn); qp->mqp.qpn);
if (qp->pri.smac) { if (qp->pri.smac || (!qp->pri.smac && qp->pri.smac_port)) {
mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac); mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac);
qp->pri.smac = 0; qp->pri.smac = 0;
qp->pri.smac_port = 0;
} }
if (qp->alt.smac) { if (qp->alt.smac) {
mlx4_unregister_mac(dev->dev, qp->alt.smac_port, qp->alt.smac); mlx4_unregister_mac(dev->dev, qp->alt.smac_port, qp->alt.smac);
...@@ -1325,7 +1326,8 @@ static int _mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah, ...@@ -1325,7 +1326,8 @@ static int _mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
* If one was already assigned, but the new mac differs, * If one was already assigned, but the new mac differs,
* unregister the old one and register the new one. * unregister the old one and register the new one.
*/ */
if (!smac_info->smac || smac_info->smac != smac) { if ((!smac_info->smac && !smac_info->smac_port) ||
smac_info->smac != smac) {
/* register candidate now, unreg if needed, after success */ /* register candidate now, unreg if needed, after success */
smac_index = mlx4_register_mac(dev->dev, port, smac); smac_index = mlx4_register_mac(dev->dev, port, smac);
if (smac_index >= 0) { if (smac_index >= 0) {
...@@ -1396,7 +1398,7 @@ static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev, struct mlx4_ib_qp * ...@@ -1396,7 +1398,7 @@ static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *
u64_mac = atomic64_read(&dev->iboe.mac[qp->port - 1]); u64_mac = atomic64_read(&dev->iboe.mac[qp->port - 1]);
context->pri_path.sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | ((qp->port - 1) << 6); context->pri_path.sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | ((qp->port - 1) << 6);
if (!qp->pri.smac) { if (!qp->pri.smac && !qp->pri.smac_port) {
smac_index = mlx4_register_mac(dev->dev, qp->port, u64_mac); smac_index = mlx4_register_mac(dev->dev, qp->port, u64_mac);
if (smac_index >= 0) { if (smac_index >= 0) {
qp->pri.candidate_smac_index = smac_index; qp->pri.candidate_smac_index = smac_index;
...@@ -1778,9 +1780,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, ...@@ -1778,9 +1780,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (qp->flags & MLX4_IB_QP_NETIF) if (qp->flags & MLX4_IB_QP_NETIF)
mlx4_ib_steer_qp_reg(dev, qp, 0); mlx4_ib_steer_qp_reg(dev, qp, 0);
} }
if (qp->pri.smac) { if (qp->pri.smac || (!qp->pri.smac && qp->pri.smac_port)) {
mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac); mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac);
qp->pri.smac = 0; qp->pri.smac = 0;
qp->pri.smac_port = 0;
} }
if (qp->alt.smac) { if (qp->alt.smac) {
mlx4_unregister_mac(dev->dev, qp->alt.smac_port, qp->alt.smac); mlx4_unregister_mac(dev->dev, qp->alt.smac_port, qp->alt.smac);
...@@ -1804,11 +1807,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, ...@@ -1804,11 +1807,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (err && steer_qp) if (err && steer_qp)
mlx4_ib_steer_qp_reg(dev, qp, 0); mlx4_ib_steer_qp_reg(dev, qp, 0);
kfree(context); kfree(context);
if (qp->pri.candidate_smac) { if (qp->pri.candidate_smac ||
(!qp->pri.candidate_smac && qp->pri.candidate_smac_port)) {
if (err) { if (err) {
mlx4_unregister_mac(dev->dev, qp->pri.candidate_smac_port, qp->pri.candidate_smac); mlx4_unregister_mac(dev->dev, qp->pri.candidate_smac_port, qp->pri.candidate_smac);
} else { } else {
if (qp->pri.smac) if (qp->pri.smac || (!qp->pri.smac && qp->pri.smac_port))
mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac); mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac);
qp->pri.smac = qp->pri.candidate_smac; qp->pri.smac = qp->pri.candidate_smac;
qp->pri.smac_index = qp->pri.candidate_smac_index; qp->pri.smac_index = qp->pri.candidate_smac_index;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment