| From a6100603a4a87fc436199362bdb81cb849faaf6e Mon Sep 17 00:00:00 2001 |
| From: Yishai Hadas <yishaih@mellanox.com> |
| Date: Wed, 22 Jun 2016 17:27:29 +0300 |
| Subject: IB/mlx4: Fix error flow when sending mads under SRIOV |
| |
| From: Yishai Hadas <yishaih@mellanox.com> |
| |
| commit a6100603a4a87fc436199362bdb81cb849faaf6e upstream. |
| |
| 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: 37bfc7c1e83f ("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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/infiniband/hw/mlx4/mad.c | 24 ++++++++++++++++++------ |
| 1 file changed, 18 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/infiniband/hw/mlx4/mad.c |
| +++ b/drivers/infiniband/hw/mlx4/mad.c |
| @@ -526,7 +526,7 @@ int mlx4_ib_send_to_slave(struct mlx4_ib |
| 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) |
| @@ -595,9 +595,15 @@ int mlx4_ib_send_to_slave(struct mlx4_ib |
| 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; |
| } |
| |
| @@ -1278,9 +1284,15 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_ |
| |
| |
| 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; |
| } |
| |