]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
RDMA/hns: Bugfix for posting multiple srq work request
authorLijun Ou <oulijun@huawei.com>
Thu, 30 May 2019 15:55:53 +0000 (23:55 +0800)
committerJason Gunthorpe <jgg@mellanox.com>
Fri, 31 May 2019 19:11:02 +0000 (16:11 -0300)
When the user submits more than 32 work request to a srq queue
at a time, it needs to find the corresponding number of entries
in the bitmap in the idx queue. However, the original lookup
function named ffs only processes 32 bits of the array element,
When the number of srq wqe issued exceeds 32, the ffs will only
process the lower 32 bits of the elements, it will not be able
to get the correct wqe index for srq wqe.

Signed-off-by: Xi Wang <wangxi11@huawei.com>
Signed-off-by: Lijun Ou <oulijun@huawei.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/hw/hns/hns_roce_device.h
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/hns/hns_roce_srq.c

index d6e8b446fc5783343000866aa9d8a2356b3796fa..ce23338831eb69d7b545a1f7e600b5e8a268c2bd 100644 (file)
@@ -489,7 +489,7 @@ struct hns_roce_idx_que {
        u32                             buf_size;
        struct ib_umem                  *umem;
        struct hns_roce_mtt             mtt;
-       u64                             *bitmap;
+       unsigned long                   *bitmap;
 };
 
 struct hns_roce_srq {
index 7fcec998618ad09f6f6512c76ef582047f4e81ac..ac017c24b200f902475a35fde14ac33c9c5d91e6 100644 (file)
@@ -2340,15 +2340,10 @@ static void *get_srq_wqe(struct hns_roce_srq *srq, int n)
 
 static void hns_roce_free_srq_wqe(struct hns_roce_srq *srq, int wqe_index)
 {
-       u32 bitmap_num;
-       int bit_num;
-
        /* always called with interrupts disabled. */
        spin_lock(&srq->lock);
 
-       bitmap_num = wqe_index / (sizeof(u64) * 8);
-       bit_num = wqe_index % (sizeof(u64) * 8);
-       srq->idx_que.bitmap[bitmap_num] |= (1ULL << bit_num);
+       bitmap_clear(srq->idx_que.bitmap, wqe_index, 1);
        srq->tail++;
 
        spin_unlock(&srq->lock);
@@ -5977,18 +5972,19 @@ out:
        return ret;
 }
 
-static int find_empty_entry(struct hns_roce_idx_que *idx_que)
+static int find_empty_entry(struct hns_roce_idx_que *idx_que,
+                           unsigned long size)
 {
-       int bit_num;
-       int i;
+       int wqe_idx;
 
-       /* bitmap[i] is set zero if all bits are allocated */
-       for (i = 0; idx_que->bitmap[i] == 0; ++i)
-               ;
-       bit_num = ffs(idx_que->bitmap[i]);
-       idx_que->bitmap[i] &= ~(1ULL << (bit_num - 1));
+       if (unlikely(bitmap_full(idx_que->bitmap, size)))
+               return -ENOSPC;
+
+       wqe_idx = find_first_zero_bit(idx_que->bitmap, size);
+
+       bitmap_set(idx_que->bitmap, wqe_idx, 1);
 
-       return i * BITS_PER_LONG_LONG + (bit_num - 1);
+       return wqe_idx;
 }
 
 static void fill_idx_queue(struct hns_roce_idx_que *idx_que,
@@ -6034,7 +6030,13 @@ static int hns_roce_v2_post_srq_recv(struct ib_srq *ibsrq,
                        break;
                }
 
-               wqe_idx = find_empty_entry(&srq->idx_que);
+               wqe_idx = find_empty_entry(&srq->idx_que, srq->max);
+               if (wqe_idx < 0) {
+                       ret = -ENOMEM;
+                       *bad_wr = wr;
+                       break;
+               }
+
                fill_idx_queue(&srq->idx_que, ind, wqe_idx);
                wqe = get_srq_wqe(srq, wqe_idx);
                dseg = (struct hns_roce_v2_wqe_data_seg *)wqe;
index ad15b41da30a542cbab919ee016c9eea3bc6e4e8..c222f243953adc4b8a9d8fd9947df98678456ac2 100644 (file)
@@ -181,28 +181,19 @@ static int hns_roce_create_idx_que(struct ib_pd *pd, struct hns_roce_srq *srq,
 {
        struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
        struct hns_roce_idx_que *idx_que = &srq->idx_que;
-       u32 bitmap_num;
-       int i;
 
-       bitmap_num = HNS_ROCE_ALOGN_UP(srq->max, 8 * sizeof(u64));
-
-       idx_que->bitmap = kcalloc(1, bitmap_num / 8, GFP_KERNEL);
+       idx_que->bitmap = bitmap_zalloc(srq->max, GFP_KERNEL);
        if (!idx_que->bitmap)
                return -ENOMEM;
 
-       bitmap_num = bitmap_num / (8 * sizeof(u64));
-
        idx_que->buf_size = srq->idx_que.buf_size;
 
        if (hns_roce_buf_alloc(hr_dev, idx_que->buf_size, (1 << page_shift) * 2,
                               &idx_que->idx_buf, page_shift)) {
-               kfree(idx_que->bitmap);
+               bitmap_free(idx_que->bitmap);
                return -ENOMEM;
        }
 
-       for (i = 0; i < bitmap_num; i++)
-               idx_que->bitmap[i] = ~(0UL);
-
        return 0;
 }
 
@@ -395,7 +386,7 @@ err_idx_mtt:
 err_create_idx:
        hns_roce_buf_free(hr_dev, srq->idx_que.buf_size,
                          &srq->idx_que.idx_buf);
-       kfree(srq->idx_que.bitmap);
+       bitmap_free(srq->idx_que.bitmap);
 
 err_srq_mtt:
        hns_roce_mtt_cleanup(hr_dev, &srq->mtt);