RDMA/hns: Add a group interfaces for optimizing buffers getting flow [Linux 5.3]

This Linux kernel change "RDMA/hns: Add a group interfaces for optimizing buffers getting flow" is included in the Linux 5.3 release. This change is authored by Lijun Ou <oulijun [at] huawei.com> on Sat Jun 8 14:46:09 2019 +0800. The commit for this change in Linux stable tree is 2ac0bc5 (patch).

RDMA/hns: Add a group interfaces for optimizing buffers getting flow

Currently, the code for getting umem and kmem buffers exist many files,
this patch adds a group interfaces to simplify the buffers getting flow.

Signed-off-by: Xi Wang <wangxi11@huawei.com>
Signed-off-by: Lijun Ou <oulijun@huawei.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>

There are 111 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/infiniband/hw/hns/hns_roce_alloc.c  | 99 +++++++++++++++++++++++++++++
 drivers/infiniband/hw/hns/hns_roce_device.h | 12 ++++
 2 files changed, 111 insertions(+)

diff --git a/drivers/infiniband/hw/hns/hns_roce_alloc.c b/drivers/infiniband/hw/hns/hns_roce_alloc.c
index dac058d..14fcc35 100644
--- a/drivers/infiniband/hw/hns/hns_roce_alloc.c
+++ b/drivers/infiniband/hw/hns/hns_roce_alloc.c
@@ -34,6 +34,7 @@
 #include <linux/platform_device.h>
 #include <linux/vmalloc.h>
 #include "hns_roce_device.h"
+#include <rdma/ib_umem.h>

 int hns_roce_bitmap_alloc(struct hns_roce_bitmap *bitmap, unsigned long *obj)
 {
@@ -238,6 +239,104 @@ int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
    return -ENOMEM;
 }

+int hns_roce_get_kmem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs,
+              int buf_cnt, int start, struct hns_roce_buf *buf)
+{
+   int i, end;
+   int total;
+
+   end = start + buf_cnt;
+   if (end > buf->npages) {
+       dev_err(hr_dev->dev,
+           "invalid kmem region,offset %d,buf_cnt %d,total %d!\n",
+           start, buf_cnt, buf->npages);
+       return -EINVAL;
+   }
+
+   total = 0;
+   for (i = start; i < end; i++)
+       if (buf->nbufs == 1)
+           bufs[total++] = buf->direct.map +
+                   (i << buf->page_shift);
+       else
+           bufs[total++] = buf->page_list[i].map;
+
+   return total;
+}
+
+int hns_roce_get_umem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs,
+              int buf_cnt, int start, struct ib_umem *umem,
+              int page_shift)
+{
+   struct ib_block_iter biter;
+   int total = 0;
+   int idx = 0;
+   u64 addr;
+
+   if (page_shift < PAGE_SHIFT) {
+       dev_err(hr_dev->dev, "invalid page shift %d!\n", page_shift);
+       return -EINVAL;
+   }
+
+   /* convert system page cnt to hw page cnt */
+   rdma_for_each_block(umem->sg_head.sgl, &biter, umem->nmap,
+               1 << page_shift) {
+       addr = rdma_block_iter_dma_address(&biter);
+       if (idx >= start) {
+           bufs[total++] = addr;
+           if (total >= buf_cnt)
+               goto done;
+       }
+       idx++;
+   }
+
+done:
+   return total;
+}
+
+void hns_roce_init_buf_region(struct hns_roce_buf_region *region, int hopnum,
+                 int offset, int buf_cnt)
+{
+   if (hopnum == HNS_ROCE_HOP_NUM_0)
+       region->hopnum = 0;
+   else
+       region->hopnum = hopnum;
+
+   region->offset = offset;
+   region->count = buf_cnt;
+}
+
+void hns_roce_free_buf_list(dma_addr_t **bufs, int region_cnt)
+{
+   int i;
+
+   for (i = 0; i < region_cnt; i++) {
+       kfree(bufs[i]);
+       bufs[i] = NULL;
+   }
+}
+
+int hns_roce_alloc_buf_list(struct hns_roce_buf_region *regions,
+               dma_addr_t **bufs, int region_cnt)
+{
+   struct hns_roce_buf_region *r;
+   int i;
+
+   for (i = 0; i < region_cnt; i++) {
+       r = &regions[i];
+       bufs[i] = kcalloc(r->count, sizeof(dma_addr_t), GFP_KERNEL);
+       if (!bufs[i])
+           goto err_alloc;
+   }
+
+   return 0;
+
+err_alloc:
+   hns_roce_free_buf_list(bufs, i);
+
+   return -ENOMEM;
+}
+
 void hns_roce_cleanup_bitmap(struct hns_roce_dev *hr_dev)
 {
    if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_SRQ)
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index ec2ed5c..4974c42 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -1211,6 +1211,18 @@ int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
 int hns_roce_ib_umem_write_mtt(struct hns_roce_dev *hr_dev,
                   struct hns_roce_mtt *mtt, struct ib_umem *umem);

+void hns_roce_init_buf_region(struct hns_roce_buf_region *region, int hopnum,
+                 int offset, int buf_cnt);
+int hns_roce_alloc_buf_list(struct hns_roce_buf_region *regions,
+               dma_addr_t **bufs, int count);
+void hns_roce_free_buf_list(dma_addr_t **bufs, int count);
+
+int hns_roce_get_kmem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs,
+              int buf_cnt, int start, struct hns_roce_buf *buf);
+int hns_roce_get_umem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs,
+              int buf_cnt, int start, struct ib_umem *umem,
+              int page_shift);
+
 int hns_roce_create_srq(struct ib_srq *srq,
            struct ib_srq_init_attr *srq_init_attr,
            struct ib_udata *udata);

Leave a Reply

Your email address will not be published. Required fields are marked *