aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei Hu\(Xavier\) <xavier.huwei@huawei.com>2017-11-28 02:10:28 -0500
committerJason Gunthorpe <jgg@mellanox.com>2017-12-01 14:21:27 -0500
commit378efe798ecf0e7d9730a595ef3419b046e34fb4 (patch)
tree47926cc1ac1285b1cff4d1f66d75e4d5c902a5ca
parentb1c158350968d6717ec1889f07ea3a89432e8574 (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.c25
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hem.h1
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
782out: 783out:
783 mutex_unlock(&table->mutex); 784 mutex_unlock(&table->mutex);
784 return page ? lowmem_page_address(page) + offset : NULL; 785 return addr;
785} 786}
786EXPORT_SYMBOL_GPL(hns_roce_table_find); 787EXPORT_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
83struct hns_roce_hem { 84struct hns_roce_hem {