Skip to content

Commit a313b8b

Browse files
committed
nv_peer_mem: Bar address re-mapping for POWER
Support address remapping on Power systems and future Intel systems by using Nvidia API to map physical pages retrieved using nvidia_p2p_get_pages accessible to the HCA. The change is backward compatible that works on older systems. Signed-off-by: Feras Daoud <ferasda@mellanox.com>
1 parent 1c9baa3 commit a313b8b

1 file changed

Lines changed: 117 additions & 5 deletions

File tree

nv_peer_mem.c

Lines changed: 117 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,67 @@
3939
#include <linux/export.h>
4040
#include <linux/hugetlb.h>
4141
#include <linux/atomic.h>
42+
#include <linux/pci.h>
4243

4344

4445
#include "nv-p2p.h"
4546
#include <rdma/peer_mem.h>
4647

4748

4849
#define DRV_NAME "nv_mem"
49-
#define DRV_VERSION "1.0"
50+
#define DRV_VERSION "1.1"
5051
#define DRV_RELDATE __DATE__
5152

52-
#define peer_err(FMT, ARGS...) printk(KERN_ERR DRV_NAME " %s:%d " FMT, __FUNCTION__, __LINE__, ## ARGS)
53+
#define peer_err(FMT, ARGS...) printk(KERN_ERR DRV_NAME " %s:%d " FMT, __func__, __LINE__, ## ARGS)
5354

55+
#define INFO_ENABLE 1
56+
#define peer_info(FMT, ARGS...) \
57+
do { \
58+
if (INFO_ENABLE) \
59+
printk(KERN_INFO DRV_NAME " %s:%d " FMT, __func__, __LINE__, ## ARGS); \
60+
} while (0)
61+
62+
#ifndef NVIDIA_P2P_MAJOR_VERSION_MASK
63+
#define NVIDIA_P2P_MAJOR_VERSION_MASK 0xffff0000
64+
#endif
65+
66+
#ifndef NVIDIA_P2P_MINOR_VERSION_MASK
67+
#define NVIDIA_P2P_MINOR_VERSION_MASK 0x0000ffff
68+
#endif
69+
70+
#ifndef NVIDIA_P2P_MAJOR_VERSION
71+
#define NVIDIA_P2P_MAJOR_VERSION(v) \
72+
(((v) & NVIDIA_P2P_MAJOR_VERSION_MASK) >> 16)
73+
#endif
74+
75+
#ifndef NVIDIA_P2P_MINOR_VERSION
76+
#define NVIDIA_P2P_MINOR_VERSION(v) \
77+
(((v) & NVIDIA_P2P_MINOR_VERSION_MASK))
78+
#endif
79+
80+
/*
81+
* Note: before major version 2, struct dma_mapping had no version field,
82+
* so it is not possible to check version compatibility. In this case
83+
* let us just avoid dma mappings altogether.
84+
*/
85+
#if defined(NVIDIA_P2P_DMA_MAPPING_VERSION) && \
86+
(NVIDIA_P2P_MAJOR_VERSION(NVIDIA_P2P_DMA_MAPPING_VERSION) >= 2)
87+
#pragma message("Enable nvidia_p2p_dma_map_pages support")
88+
#define NV_DMA_MAPPING 1
89+
#else
90+
#define NV_DMA_MAPPING 0
91+
#endif
92+
93+
#ifndef NVIDIA_P2P_MAJOR_VERSION_MATCHES
94+
#define NVIDIA_P2P_MAJOR_VERSION_MATCHES(p, v) \
95+
(NVIDIA_P2P_MAJOR_VERSION((p)->version) == NVIDIA_P2P_MAJOR_VERSION(v))
96+
#endif
97+
98+
#ifndef NVIDIA_P2P_VERSION_COMPATIBLE
99+
#define NVIDIA_P2P_VERSION_COMPATIBLE(p, v) \
100+
(NVIDIA_P2P_MAJOR_VERSION_MATCHES(p, v) && \
101+
(NVIDIA_P2P_MINOR_VERSION((p)->version) >= NVIDIA_P2P_MINOR_VERSION(v)))
102+
#endif
54103

55104
MODULE_AUTHOR("Yishai Hadas");
56105
MODULE_DESCRIPTION("NVIDIA GPU memory plug-in");
@@ -68,6 +117,9 @@ static void *reg_handle;
68117

69118
struct nv_mem_context {
70119
struct nvidia_p2p_page_table *page_table;
120+
#if NV_DMA_MAPPING
121+
struct nvidia_p2p_dma_mapping *dma_mapping;
122+
#endif
71123
void *core_context;
72124
u64 page_virt_start;
73125
u64 page_virt_end;
@@ -187,18 +239,58 @@ static int nv_dma_map(struct sg_table *sg_head, void *context,
187239
(struct nv_mem_context *) context;
188240
struct nvidia_p2p_page_table *page_table = nv_mem_context->page_table;
189241

190-
if (nv_mem_context->page_table->page_size != NVIDIA_P2P_PAGE_SIZE_64KB) {
242+
if (page_table->page_size != NVIDIA_P2P_PAGE_SIZE_64KB) {
191243
peer_err("nv_dma_map -- assumption of 64KB pages failed size_id=%u\n",
192244
nv_mem_context->page_table->page_size);
193245
return -EINVAL;
194246
}
195247

248+
#if NV_DMA_MAPPING
249+
{
250+
struct nvidia_p2p_dma_mapping *dma_mapping;
251+
struct pci_dev *pdev = to_pci_dev(dma_device);
252+
253+
if (!pdev) {
254+
peer_err("nv_dma_map -- invalid pci_dev\n");
255+
return -EINVAL;
256+
}
257+
258+
ret = nvidia_p2p_dma_map_pages(pdev, page_table, &dma_mapping);
259+
if (ret) {
260+
peer_err("nv_dma_map -- error %d while calling nvidia_p2p_dma_map_pages()\n", ret);
261+
return ret;
262+
}
263+
264+
if (!NVIDIA_P2P_DMA_MAPPING_VERSION_COMPATIBLE(dma_mapping)) {
265+
peer_err("error, incompatible dma mapping version 0x%08x\n",
266+
dma_mapping->version);
267+
nvidia_p2p_dma_unmap_pages(pdev, page_table, dma_mapping);
268+
return -EINVAL;
269+
}
270+
271+
nv_mem_context->npages = dma_mapping->entries;
272+
273+
ret = sg_alloc_table(sg_head, dma_mapping->entries, GFP_KERNEL);
274+
if (ret) {
275+
nvidia_p2p_dma_unmap_pages(pdev, page_table, dma_mapping);
276+
return ret;
277+
}
278+
279+
nv_mem_context->dma_mapping = dma_mapping;
280+
nv_mem_context->sg_allocated = 1;
281+
for_each_sg(sg_head->sgl, sg, nv_mem_context->npages, i) {
282+
sg_set_page(sg, NULL, nv_mem_context->page_size, 0);
283+
sg->dma_address = dma_mapping->dma_addresses[i];
284+
sg->dma_length = nv_mem_context->page_size;
285+
}
286+
}
287+
#else
196288
nv_mem_context->npages = PAGE_ALIGN(nv_mem_context->mapped_size) >>
197289
GPU_PAGE_SHIFT;
198290

199-
if (nv_mem_context->page_table->entries != nv_mem_context->npages) {
291+
if (page_table->entries != nv_mem_context->npages) {
200292
peer_err("nv_dma_map -- unexpected number of page table entries got=%u, expected=%lu\n",
201-
nv_mem_context->page_table->entries,
293+
page_table->entries,
202294
nv_mem_context->npages);
203295
return -EINVAL;
204296
}
@@ -214,13 +306,33 @@ static int nv_dma_map(struct sg_table *sg_head, void *context,
214306
sg->dma_length = nv_mem_context->page_size;
215307
}
216308

309+
#endif
310+
217311
*nmap = nv_mem_context->npages;
312+
218313
return 0;
219314
}
220315

221316
static int nv_dma_unmap(struct sg_table *sg_head, void *context,
222317
struct device *dma_device)
223318
{
319+
struct nv_mem_context *nv_mem_context =
320+
(struct nv_mem_context *)context;
321+
322+
if (!nv_mem_context) {
323+
peer_err("nv_dma_unmap -- invalid nv_mem_context\n");
324+
return -EINVAL;
325+
}
326+
327+
#if NV_DMA_MAPPING
328+
{
329+
struct pci_dev *pdev = to_pci_dev(dma_device);
330+
if (nv_mem_context->dma_mapping)
331+
nvidia_p2p_dma_unmap_pages(pdev, nv_mem_context->page_table,
332+
nv_mem_context->dma_mapping);
333+
}
334+
#endif
335+
224336
return 0;
225337
}
226338

0 commit comments

Comments
 (0)