diff options
author | Wei Hu\(Xavier\) <xavier.huwei@huawei.com> | 2017-11-28 02:10:28 -0500 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2017-12-01 14:21:27 -0500 |
commit | 378efe798ecf0e7d9730a595ef3419b046e34fb4 (patch) | |
tree | 47926cc1ac1285b1cff4d1f66d75e4d5c902a5ca | |
parent | b1c158350968d6717ec1889f07ea3a89432e8574 (diff) |
RDMA/hns: Get rid of page operation after dma_alloc_coherent
In general, dma_alloc_coherent() returns a CPU virtual address and
a DMA address, and we have no guarantee that the underlying memory
even has an associated struct page at all.
This patch gets rid of the page operation after dma_alloc_coherent,
and records the VA returned form dma_alloc_coherent in the struct
of hem in hns RoCE driver.
Fixes: 9a44353("IB/hns: Add driver files for hns RoCE driver")
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
Signed-off-by: Shaobo Xu <xushaobo2@huawei.com>
Signed-off-by: Lijun Ou <oulijun@huawei.com>
Signed-off-by: Yixian Liu <liuyixian@huawei.com>
Signed-off-by: Xiping Zhang (Francis) <zhangxiping3@huawei.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r-- | drivers/infiniband/hw/hns/hns_roce_hem.c | 25 | ||||
-rw-r--r-- | drivers/infiniband/hw/hns/hns_roce_hem.h | 1 |
2 files changed, 14 insertions, 12 deletions
diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c index 8b733a66fae5..0eeabfbee192 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hem.c +++ b/drivers/infiniband/hw/hns/hns_roce_hem.c | |||
@@ -224,6 +224,7 @@ static struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev, | |||
224 | sg_init_table(chunk->mem, HNS_ROCE_HEM_CHUNK_LEN); | 224 | sg_init_table(chunk->mem, HNS_ROCE_HEM_CHUNK_LEN); |
225 | chunk->npages = 0; | 225 | chunk->npages = 0; |
226 | chunk->nsg = 0; | 226 | chunk->nsg = 0; |
227 | memset(chunk->buf, 0, sizeof(chunk->buf)); | ||
227 | list_add_tail(&chunk->list, &hem->chunk_list); | 228 | list_add_tail(&chunk->list, &hem->chunk_list); |
228 | } | 229 | } |
229 | 230 | ||
@@ -240,8 +241,7 @@ static struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev, | |||
240 | if (!buf) | 241 | if (!buf) |
241 | goto fail; | 242 | goto fail; |
242 | 243 | ||
243 | sg_set_buf(mem, buf, PAGE_SIZE << order); | 244 | chunk->buf[chunk->npages] = buf; |
244 | WARN_ON(mem->offset); | ||
245 | sg_dma_len(mem) = PAGE_SIZE << order; | 245 | sg_dma_len(mem) = PAGE_SIZE << order; |
246 | 246 | ||
247 | ++chunk->npages; | 247 | ++chunk->npages; |
@@ -267,8 +267,8 @@ void hns_roce_free_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem *hem) | |||
267 | list_for_each_entry_safe(chunk, tmp, &hem->chunk_list, list) { | 267 | list_for_each_entry_safe(chunk, tmp, &hem->chunk_list, list) { |
268 | for (i = 0; i < chunk->npages; ++i) | 268 | for (i = 0; i < chunk->npages; ++i) |
269 | dma_free_coherent(hr_dev->dev, | 269 | dma_free_coherent(hr_dev->dev, |
270 | chunk->mem[i].length, | 270 | sg_dma_len(&chunk->mem[i]), |
271 | lowmem_page_address(sg_page(&chunk->mem[i])), | 271 | chunk->buf[i], |
272 | sg_dma_address(&chunk->mem[i])); | 272 | sg_dma_address(&chunk->mem[i])); |
273 | kfree(chunk); | 273 | kfree(chunk); |
274 | } | 274 | } |
@@ -722,11 +722,12 @@ void *hns_roce_table_find(struct hns_roce_dev *hr_dev, | |||
722 | struct hns_roce_hem_chunk *chunk; | 722 | struct hns_roce_hem_chunk *chunk; |
723 | struct hns_roce_hem_mhop mhop; | 723 | struct hns_roce_hem_mhop mhop; |
724 | struct hns_roce_hem *hem; | 724 | struct hns_roce_hem *hem; |
725 | struct page *page = NULL; | 725 | void *addr = NULL; |
726 | unsigned long mhop_obj = obj; | 726 | unsigned long mhop_obj = obj; |
727 | unsigned long obj_per_chunk; | 727 | unsigned long obj_per_chunk; |
728 | unsigned long idx_offset; | 728 | unsigned long idx_offset; |
729 | int offset, dma_offset; | 729 | int offset, dma_offset; |
730 | int length; | ||
730 | int i, j; | 731 | int i, j; |
731 | u32 hem_idx = 0; | 732 | u32 hem_idx = 0; |
732 | 733 | ||
@@ -763,25 +764,25 @@ void *hns_roce_table_find(struct hns_roce_dev *hr_dev, | |||
763 | 764 | ||
764 | list_for_each_entry(chunk, &hem->chunk_list, list) { | 765 | list_for_each_entry(chunk, &hem->chunk_list, list) { |
765 | for (i = 0; i < chunk->npages; ++i) { | 766 | for (i = 0; i < chunk->npages; ++i) { |
767 | length = sg_dma_len(&chunk->mem[i]); | ||
766 | if (dma_handle && dma_offset >= 0) { | 768 | if (dma_handle && dma_offset >= 0) { |
767 | if (sg_dma_len(&chunk->mem[i]) > | 769 | if (length > (u32)dma_offset) |
768 | (u32)dma_offset) | ||
769 | *dma_handle = sg_dma_address( | 770 | *dma_handle = sg_dma_address( |
770 | &chunk->mem[i]) + dma_offset; | 771 | &chunk->mem[i]) + dma_offset; |
771 | dma_offset -= sg_dma_len(&chunk->mem[i]); | 772 | dma_offset -= length; |
772 | } | 773 | } |
773 | 774 | ||
774 | if (chunk->mem[i].length > (u32)offset) { | 775 | if (length > (u32)offset) { |
775 | page = sg_page(&chunk->mem[i]); | 776 | addr = chunk->buf[i] + offset; |
776 | goto out; | 777 | goto out; |
777 | } | 778 | } |
778 | offset -= chunk->mem[i].length; | 779 | offset -= length; |
779 | } | 780 | } |
780 | } | 781 | } |
781 | 782 | ||
782 | out: | 783 | out: |
783 | mutex_unlock(&table->mutex); | 784 | mutex_unlock(&table->mutex); |
784 | return page ? lowmem_page_address(page) + offset : NULL; | 785 | return addr; |
785 | } | 786 | } |
786 | EXPORT_SYMBOL_GPL(hns_roce_table_find); | 787 | EXPORT_SYMBOL_GPL(hns_roce_table_find); |
787 | 788 | ||
diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.h b/drivers/infiniband/hw/hns/hns_roce_hem.h index db66db12075e..e8850d59e780 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hem.h +++ b/drivers/infiniband/hw/hns/hns_roce_hem.h | |||
@@ -78,6 +78,7 @@ struct hns_roce_hem_chunk { | |||
78 | int npages; | 78 | int npages; |
79 | int nsg; | 79 | int nsg; |
80 | struct scatterlist mem[HNS_ROCE_HEM_CHUNK_LEN]; | 80 | struct scatterlist mem[HNS_ROCE_HEM_CHUNK_LEN]; |
81 | void *buf[HNS_ROCE_HEM_CHUNK_LEN]; | ||
81 | }; | 82 | }; |
82 | 83 | ||
83 | struct hns_roce_hem { | 84 | struct hns_roce_hem { |