4141#include <linux/hugetlb.h>
4242#include <linux/interval_tree.h>
4343#include <linux/hmm.h>
44+ #include <linux/hmm-dma.h>
4445#include <linux/pagemap.h>
4546
4647#include <rdma/ib_umem_odp.h>
5051static inline int ib_init_umem_odp (struct ib_umem_odp * umem_odp ,
5152 const struct mmu_interval_notifier_ops * ops )
5253{
54+ struct ib_device * dev = umem_odp -> umem .ibdev ;
5355 int ret ;
5456
5557 umem_odp -> umem .is_odp = 1 ;
@@ -59,7 +61,6 @@ static inline int ib_init_umem_odp(struct ib_umem_odp *umem_odp,
5961 size_t page_size = 1UL << umem_odp -> page_shift ;
6062 unsigned long start ;
6163 unsigned long end ;
62- size_t ndmas , npfns ;
6364
6465 start = ALIGN_DOWN (umem_odp -> umem .address , page_size );
6566 if (check_add_overflow (umem_odp -> umem .address ,
@@ -70,38 +71,23 @@ static inline int ib_init_umem_odp(struct ib_umem_odp *umem_odp,
7071 if (unlikely (end < page_size ))
7172 return - EOVERFLOW ;
7273
73- ndmas = (end - start ) >> umem_odp -> page_shift ;
74- if (!ndmas )
75- return - EINVAL ;
76-
77- npfns = (end - start ) >> PAGE_SHIFT ;
78- umem_odp -> pfn_list = kvcalloc (
79- npfns , sizeof (* umem_odp -> pfn_list ),
80- GFP_KERNEL | __GFP_NOWARN );
81- if (!umem_odp -> pfn_list )
82- return - ENOMEM ;
83-
84- umem_odp -> dma_list = kvcalloc (
85- ndmas , sizeof (* umem_odp -> dma_list ),
86- GFP_KERNEL | __GFP_NOWARN );
87- if (!umem_odp -> dma_list ) {
88- ret = - ENOMEM ;
89- goto out_pfn_list ;
90- }
74+ ret = hmm_dma_map_alloc (dev -> dma_device , & umem_odp -> map ,
75+ (end - start ) >> PAGE_SHIFT ,
76+ 1 << umem_odp -> page_shift );
77+ if (ret )
78+ return ret ;
9179
9280 ret = mmu_interval_notifier_insert (& umem_odp -> notifier ,
9381 umem_odp -> umem .owning_mm ,
9482 start , end - start , ops );
9583 if (ret )
96- goto out_dma_list ;
84+ goto out_free_map ;
9785 }
9886
9987 return 0 ;
10088
101- out_dma_list :
102- kvfree (umem_odp -> dma_list );
103- out_pfn_list :
104- kvfree (umem_odp -> pfn_list );
89+ out_free_map :
90+ hmm_dma_map_free (dev -> dma_device , & umem_odp -> map );
10591 return ret ;
10692}
10793
@@ -264,6 +250,8 @@ EXPORT_SYMBOL(ib_umem_odp_get);
264250
265251void ib_umem_odp_release (struct ib_umem_odp * umem_odp )
266252{
253+ struct ib_device * dev = umem_odp -> umem .ibdev ;
254+
267255 /*
268256 * Ensure that no more pages are mapped in the umem.
269257 *
@@ -276,48 +264,17 @@ void ib_umem_odp_release(struct ib_umem_odp *umem_odp)
276264 ib_umem_end (umem_odp ));
277265 mutex_unlock (& umem_odp -> umem_mutex );
278266 mmu_interval_notifier_remove (& umem_odp -> notifier );
279- kvfree (umem_odp -> dma_list );
280- kvfree (umem_odp -> pfn_list );
267+ hmm_dma_map_free (dev -> dma_device , & umem_odp -> map );
281268 }
282269 put_pid (umem_odp -> tgid );
283270 kfree (umem_odp );
284271}
285272EXPORT_SYMBOL (ib_umem_odp_release );
286273
287- /*
288- * Map for DMA and insert a single page into the on-demand paging page tables.
289- *
290- * @umem: the umem to insert the page to.
291- * @dma_index: index in the umem to add the dma to.
292- * @page: the page struct to map and add.
293- * @access_mask: access permissions needed for this page.
294- *
295- * The function returns -EFAULT if the DMA mapping operation fails.
296- *
297- */
298- static int ib_umem_odp_map_dma_single_page (
299- struct ib_umem_odp * umem_odp ,
300- unsigned int dma_index ,
301- struct page * page )
302- {
303- struct ib_device * dev = umem_odp -> umem .ibdev ;
304- dma_addr_t * dma_addr = & umem_odp -> dma_list [dma_index ];
305-
306- * dma_addr = ib_dma_map_page (dev , page , 0 , 1 << umem_odp -> page_shift ,
307- DMA_BIDIRECTIONAL );
308- if (ib_dma_mapping_error (dev , * dma_addr )) {
309- * dma_addr = 0 ;
310- return - EFAULT ;
311- }
312- umem_odp -> npages ++ ;
313- return 0 ;
314- }
315-
316274/**
317275 * ib_umem_odp_map_dma_and_lock - DMA map userspace memory in an ODP MR and lock it.
318276 *
319277 * Maps the range passed in the argument to DMA addresses.
320- * The DMA addresses of the mapped pages is updated in umem_odp->dma_list.
321278 * Upon success the ODP MR will be locked to let caller complete its device
322279 * page table update.
323280 *
@@ -374,7 +331,7 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt,
374331 range .default_flags |= HMM_PFN_REQ_WRITE ;
375332 }
376333
377- range .hmm_pfns = & (umem_odp -> pfn_list [pfn_start_idx ]);
334+ range .hmm_pfns = & (umem_odp -> map . pfn_list [pfn_start_idx ]);
378335 timeout = jiffies + msecs_to_jiffies (HMM_RANGE_DEFAULT_TIMEOUT );
379336
380337retry :
@@ -425,16 +382,6 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt,
425382 __func__ , hmm_order , page_shift );
426383 break ;
427384 }
428-
429- ret = ib_umem_odp_map_dma_single_page (
430- umem_odp , dma_index ,
431- hmm_pfn_to_page (range .hmm_pfns [pfn_index ]));
432- if (ret < 0 ) {
433- ibdev_dbg (umem_odp -> umem .ibdev ,
434- "ib_umem_odp_map_dma_single_page failed with error %d\n" , ret );
435- break ;
436- }
437- range .hmm_pfns [pfn_index ] |= HMM_PFN_DMA_MAPPED ;
438385 }
439386 /* upon success lock should stay on hold for the callee */
440387 if (!ret )
@@ -454,32 +401,23 @@ EXPORT_SYMBOL(ib_umem_odp_map_dma_and_lock);
454401void ib_umem_odp_unmap_dma_pages (struct ib_umem_odp * umem_odp , u64 virt ,
455402 u64 bound )
456403{
457- dma_addr_t dma ;
458- int idx ;
459- u64 addr ;
460404 struct ib_device * dev = umem_odp -> umem .ibdev ;
405+ u64 addr ;
461406
462407 lockdep_assert_held (& umem_odp -> umem_mutex );
463408
464409 virt = max_t (u64 , virt , ib_umem_start (umem_odp ));
465410 bound = min_t (u64 , bound , ib_umem_end (umem_odp ));
466411 for (addr = virt ; addr < bound ; addr += BIT (umem_odp -> page_shift )) {
467- unsigned long pfn_idx = (addr - ib_umem_start (umem_odp )) >>
468- PAGE_SHIFT ;
469- struct page * page =
470- hmm_pfn_to_page (umem_odp -> pfn_list [pfn_idx ]);
471-
472- idx = (addr - ib_umem_start (umem_odp )) >> umem_odp -> page_shift ;
473- dma = umem_odp -> dma_list [idx ];
412+ u64 offset = addr - ib_umem_start (umem_odp );
413+ size_t idx = offset >> umem_odp -> page_shift ;
414+ unsigned long pfn = umem_odp -> map .pfn_list [idx ];
474415
475- if (!(umem_odp -> pfn_list [pfn_idx ] & HMM_PFN_VALID ))
476- goto clear ;
477- if (!(umem_odp -> pfn_list [pfn_idx ] & HMM_PFN_DMA_MAPPED ))
416+ if (!hmm_dma_unmap_pfn (dev -> dma_device , & umem_odp -> map , idx ))
478417 goto clear ;
479418
480- ib_dma_unmap_page (dev , dma , BIT (umem_odp -> page_shift ),
481- DMA_BIDIRECTIONAL );
482- if (umem_odp -> pfn_list [pfn_idx ] & HMM_PFN_WRITE ) {
419+ if (pfn & HMM_PFN_WRITE ) {
420+ struct page * page = hmm_pfn_to_page (pfn );
483421 struct page * head_page = compound_head (page );
484422 /*
485423 * set_page_dirty prefers being called with
@@ -494,7 +432,7 @@ void ib_umem_odp_unmap_dma_pages(struct ib_umem_odp *umem_odp, u64 virt,
494432 }
495433 umem_odp -> npages -- ;
496434clear :
497- umem_odp -> pfn_list [pfn_idx ] &= ~HMM_PFN_FLAGS ;
435+ umem_odp -> map . pfn_list [idx ] &= ~HMM_PFN_FLAGS ;
498436 }
499437}
500438EXPORT_SYMBOL (ib_umem_odp_unmap_dma_pages );
0 commit comments