| From b0ffeb537f3a726931d962ab6d03e34a2f070ea4 Mon Sep 17 00:00:00 2001 |
| From: Slava Shwartsman <slavash@mellanox.com> |
| Date: Sun, 3 Jul 2016 15:28:19 +0300 |
| Subject: IB/mlx5: Fix iteration overrun in GSI qps |
| |
| From: Slava Shwartsman <slavash@mellanox.com> |
| |
| commit b0ffeb537f3a726931d962ab6d03e34a2f070ea4 upstream. |
| |
| Number of outstanding_pi may overflow and as a result may indicate that |
| there are no elements in the queue. The effect of doing this is that the |
| MAD layer will get stuck waiting for completions. The MAD layer will |
| think that the QP is full - because it didn't receive these completions. |
| |
| This fix changes it so the outstanding_pi number is increased |
| with 32-bit wraparound and is not limited to max_send_wr so |
| that the difference between outstanding_pi and outstanding_ci will |
| really indicate the number of outstanding completions. |
| |
| Fixes: ea6dc2036224 ('IB/mlx5: Reorder GSI completions') |
| Signed-off-by: Slava Shwartsman <slavash@mellanox.com> |
| Signed-off-by: Leon Romanovsky <leon@kernel.org> |
| Reviewed-by: Haggai Eran <haggaie@mellanox.com> |
| Reviewed-by: Sagi Grimberg <sagi@grimberg.me> |
| Signed-off-by: Doug Ledford <dledford@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/infiniband/hw/mlx5/gsi.c | 19 ++++++------------- |
| 1 file changed, 6 insertions(+), 13 deletions(-) |
| |
| --- a/drivers/infiniband/hw/mlx5/gsi.c |
| +++ b/drivers/infiniband/hw/mlx5/gsi.c |
| @@ -69,15 +69,6 @@ static bool mlx5_ib_deth_sqpn_cap(struct |
| return MLX5_CAP_GEN(dev->mdev, set_deth_sqpn); |
| } |
| |
| -static u32 next_outstanding(struct mlx5_ib_gsi_qp *gsi, u32 index) |
| -{ |
| - return ++index % gsi->cap.max_send_wr; |
| -} |
| - |
| -#define for_each_outstanding_wr(gsi, index) \ |
| - for (index = gsi->outstanding_ci; index != gsi->outstanding_pi; \ |
| - index = next_outstanding(gsi, index)) |
| - |
| /* Call with gsi->lock locked */ |
| static void generate_completions(struct mlx5_ib_gsi_qp *gsi) |
| { |
| @@ -85,8 +76,9 @@ static void generate_completions(struct |
| struct mlx5_ib_gsi_wr *wr; |
| u32 index; |
| |
| - for_each_outstanding_wr(gsi, index) { |
| - wr = &gsi->outstanding_wrs[index]; |
| + for (index = gsi->outstanding_ci; index != gsi->outstanding_pi; |
| + index++) { |
| + wr = &gsi->outstanding_wrs[index % gsi->cap.max_send_wr]; |
| |
| if (!wr->completed) |
| break; |
| @@ -430,8 +422,9 @@ static int mlx5_ib_add_outstanding_wr(st |
| return -ENOMEM; |
| } |
| |
| - gsi_wr = &gsi->outstanding_wrs[gsi->outstanding_pi]; |
| - gsi->outstanding_pi = next_outstanding(gsi, gsi->outstanding_pi); |
| + gsi_wr = &gsi->outstanding_wrs[gsi->outstanding_pi % |
| + gsi->cap.max_send_wr]; |
| + gsi->outstanding_pi++; |
| |
| if (!wc) { |
| memset(&gsi_wr->wc, 0, sizeof(gsi_wr->wc)); |