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
55104MODULE_AUTHOR ("Yishai Hadas" );
56105MODULE_DESCRIPTION ("NVIDIA GPU memory plug-in" );
@@ -68,6 +117,9 @@ static void *reg_handle;
68117
69118struct 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
221316static 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