提交 38d28c1f 编写于 作者: S Shunfeng Yang 提交者: Yang Yingliang

RDMA/hns: Bugfix for posting multiple srq work request

mainline inclusion
from mainline-v5.3
commit 97545b10
category: bugfix
bugzilla: NA
CVE: NA

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: NShunfeng Yang <yangshunfeng2@huawei.com>
Signed-off-by: NYangyang Li <liyangyang20@huawei.com>
Reviewed-by: Nchunzhi hu <huchunzhi@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 abaff721
...@@ -3039,15 +3039,10 @@ static void *get_srq_wqe(struct hns_roce_srq *srq, int n) ...@@ -3039,15 +3039,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) 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. */ /* always called with interrupts disabled. */
spin_lock(&srq->lock); spin_lock(&srq->lock);
bitmap_num = wqe_index / BITS_PER_LONG_LONG; bitmap_clear(srq->idx_que.bitmap, wqe_index, 1);
bit_num = wqe_index % BITS_PER_LONG_LONG;
srq->idx_que.bitmap[bitmap_num] |= (1ULL << bit_num);
srq->idx_que.tail++; srq->idx_que.tail++;
spin_unlock(&srq->lock); spin_unlock(&srq->lock);
...@@ -7043,18 +7038,19 @@ int hns_roce_srqwq_overflow(struct hns_roce_srq *srq, int nreq) ...@@ -7043,18 +7038,19 @@ int hns_roce_srqwq_overflow(struct hns_roce_srq *srq, int nreq)
return cur + nreq >= srq->max - 1; return cur + nreq >= srq->max - 1;
} }
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 wqe_idx;
int i;
/* bitmap[i] is set zero if all bits are allocated */ if (unlikely(bitmap_full(idx_que->bitmap, size)))
for (i = 0; idx_que->bitmap[i] == 0; ++i) return -ENOSPC;
;
bit_num = __ffs64(idx_que->bitmap[i]) + 1; wqe_idx = find_first_zero_bit(idx_que->bitmap, size);
idx_que->bitmap[i] &= ~(1ULL << (bit_num - 1));
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, static void fill_idx_queue(struct hns_roce_idx_que *idx_que,
...@@ -7112,7 +7108,13 @@ static int hns_roce_v2_post_srq_recv(struct ib_srq *ibsrq, ...@@ -7112,7 +7108,13 @@ static int hns_roce_v2_post_srq_recv(struct ib_srq *ibsrq,
break; 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); fill_idx_queue(&srq->idx_que, ind, wqe_idx);
wqe = get_srq_wqe(srq, wqe_idx); wqe = get_srq_wqe(srq, wqe_idx);
dseg = (struct hns_roce_v2_wqe_data_seg *)wqe; dseg = (struct hns_roce_v2_wqe_data_seg *)wqe;
......
...@@ -312,29 +312,22 @@ static int hns_roce_create_idx_que(struct ib_pd *pd, struct hns_roce_srq *srq, ...@@ -312,29 +312,22 @@ 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_dev *hr_dev = to_hr_dev(pd->device);
struct hns_roce_idx_que *idx_que = &srq->idx_que; struct hns_roce_idx_que *idx_que = &srq->idx_que;
struct hns_roce_buf *kbuf; struct hns_roce_buf *kbuf;
u32 bitmap_num;
int i;
idx_que->entry_sz = HNS_ROCE_IDX_QUE_ENTRY_SZ; idx_que->entry_sz = HNS_ROCE_IDX_QUE_ENTRY_SZ;
bitmap_num = HNS_ROCE_ALIGN_UP(srq->max, BITS_PER_LONG_LONG);
idx_que->bitmap = kcalloc(1, bitmap_num / BITS_PER_BYTE, GFP_KERNEL); idx_que->bitmap = bitmap_zalloc(srq->max, GFP_KERNEL);
if (!idx_que->bitmap) if (!idx_que->bitmap)
return -ENOMEM; return -ENOMEM;
bitmap_num = bitmap_num / BITS_PER_LONG_LONG;
idx_que->buf_size = srq->max * idx_que->entry_sz; idx_que->buf_size = srq->max * idx_que->entry_sz;
kbuf = hns_roce_buf_alloc(hr_dev, idx_que->buf_size, page_shift, 0); kbuf = hns_roce_buf_alloc(hr_dev, idx_que->buf_size, page_shift, 0);
if (IS_ERR(kbuf)) { if (IS_ERR(kbuf)) {
kfree(idx_que->bitmap); bitmap_free(idx_que->bitmap);
return -ENOMEM; return -ENOMEM;
} }
idx_que->idx_buf = kbuf; idx_que->idx_buf = kbuf;
for (i = 0; i < bitmap_num; i++)
idx_que->bitmap[i] = ~(0UL);
idx_que->head = 0; idx_que->head = 0;
idx_que->tail = 0; idx_que->tail = 0;
...@@ -405,7 +398,7 @@ static int create_kernel_srq(struct ib_pd *pd, struct hns_roce_srq *srq, ...@@ -405,7 +398,7 @@ static int create_kernel_srq(struct ib_pd *pd, struct hns_roce_srq *srq,
err_kernel_create_idx: err_kernel_create_idx:
hns_roce_buf_free(hr_dev, srq->idx_que.idx_buf); hns_roce_buf_free(hr_dev, srq->idx_que.idx_buf);
kfree(srq->idx_que.bitmap); bitmap_free(srq->idx_que.bitmap);
err_kernel_srq_mtt: err_kernel_srq_mtt:
hns_roce_mtt_cleanup(hr_dev, &srq->mtt); hns_roce_mtt_cleanup(hr_dev, &srq->mtt);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册