Skip to content

Commit

Permalink
IB/mlx4: Fix error flow when sending mads under SRIOV
Browse files Browse the repository at this point in the history
Fix mad send error flow to prevent double freeing address handles,
and leaking tx_ring entries when SRIOV is active.

If ib_mad_post_send fails, the address handle pointer in the tx_ring entry
must be set to NULL (or there will be a double-free) and tx_tail must be
incremented (or there will be a leak of tx_ring entries).
The tx_ring is handled the same way in the send-completion handler.

Fixes: 37bfc7c ("IB/mlx4: SR-IOV multiplex and demultiplex MADs")
Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Reviewed-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
  • Loading branch information
Yishai Hadas authored and Doug Ledford committed Jun 23, 2016
1 parent f2940e2 commit a610060
Showing 1 changed file with 18 additions and 6 deletions.
24 changes: 18 additions & 6 deletions drivers/infiniband/hw/mlx4/mad.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
tun_tx_ix = (++tun_qp->tx_ix_head) & (MLX4_NUM_TUNNEL_BUFS - 1);
spin_unlock(&tun_qp->tx_lock);
if (ret)
goto out;
goto end;

tun_mad = (struct mlx4_rcv_tunnel_mad *) (tun_qp->tx_ring[tun_tx_ix].buf.addr);
if (tun_qp->tx_ring[tun_tx_ix].ah)
Expand Down Expand Up @@ -596,9 +596,15 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
wr.wr.send_flags = IB_SEND_SIGNALED;

ret = ib_post_send(src_qp, &wr.wr, &bad_wr);
out:
if (ret)
ib_destroy_ah(ah);
if (!ret)
return 0;
out:
spin_lock(&tun_qp->tx_lock);
tun_qp->tx_ix_tail++;
spin_unlock(&tun_qp->tx_lock);
tun_qp->tx_ring[tun_tx_ix].ah = NULL;
end:
ib_destroy_ah(ah);
return ret;
}

Expand Down Expand Up @@ -1326,9 +1332,15 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,


ret = ib_post_send(send_qp, &wr.wr, &bad_wr);
if (!ret)
return 0;

spin_lock(&sqp->tx_lock);
sqp->tx_ix_tail++;
spin_unlock(&sqp->tx_lock);
sqp->tx_ring[wire_tx_ix].ah = NULL;
out:
if (ret)
ib_destroy_ah(ah);
ib_destroy_ah(ah);
return ret;
}

Expand Down

0 comments on commit a610060

Please sign in to comment.