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,36 +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 ), GFP_KERNEL );
80- if (!umem_odp -> pfn_list )
81- return - ENOMEM ;
82-
83- umem_odp -> dma_list = kvcalloc (
84- ndmas , sizeof (* umem_odp -> dma_list ), GFP_KERNEL );
85- if (!umem_odp -> dma_list ) {
86- ret = - ENOMEM ;
87- goto out_pfn_list ;
88- }
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 ;
8979
9080 ret = mmu_interval_notifier_insert (& umem_odp -> notifier ,
9181 umem_odp -> umem .owning_mm ,
9282 start , end - start , ops );
9383 if (ret )
94- goto out_dma_list ;
84+ goto out_free_map ;
9585 }
9686
9787 return 0 ;
9888
99- out_dma_list :
100- kvfree (umem_odp -> dma_list );
101- out_pfn_list :
102- kvfree (umem_odp -> pfn_list );
89+ out_free_map :
90+ hmm_dma_map_free (dev -> dma_device , & umem_odp -> map );
10391 return ret ;
10492}
10593
@@ -262,6 +250,8 @@ EXPORT_SYMBOL(ib_umem_odp_get);
262250
263251void ib_umem_odp_release (struct ib_umem_odp * umem_odp )
264252{
253+ struct ib_device * dev = umem_odp -> umem .ibdev ;
254+
265255 /*
266256 * Ensure that no more pages are mapped in the umem.
267257 *
@@ -274,48 +264,17 @@ void ib_umem_odp_release(struct ib_umem_odp *umem_odp)
274264 ib_umem_end (umem_odp ));
275265 mutex_unlock (& umem_odp -> umem_mutex );
276266 mmu_interval_notifier_remove (& umem_odp -> notifier );
277- kvfree (umem_odp -> dma_list );
278- kvfree (umem_odp -> pfn_list );
267+ hmm_dma_map_free (dev -> dma_device , & umem_odp -> map );
279268 }
280269 put_pid (umem_odp -> tgid );
281270 kfree (umem_odp );
282271}
283272EXPORT_SYMBOL (ib_umem_odp_release );
284273
285- /*
286- * Map for DMA and insert a single page into the on-demand paging page tables.
287- *
288- * @umem: the umem to insert the page to.
289- * @dma_index: index in the umem to add the dma to.
290- * @page: the page struct to map and add.
291- * @access_mask: access permissions needed for this page.
292- *
293- * The function returns -EFAULT if the DMA mapping operation fails.
294- *
295- */
296- static int ib_umem_odp_map_dma_single_page (
297- struct ib_umem_odp * umem_odp ,
298- unsigned int dma_index ,
299- struct page * page )
300- {
301- struct ib_device * dev = umem_odp -> umem .ibdev ;
302- dma_addr_t * dma_addr = & umem_odp -> dma_list [dma_index ];
303-
304- * dma_addr = ib_dma_map_page (dev , page , 0 , 1 << umem_odp -> page_shift ,
305- DMA_BIDIRECTIONAL );
306- if (ib_dma_mapping_error (dev , * dma_addr )) {
307- * dma_addr = 0 ;
308- return - EFAULT ;
309- }
310- umem_odp -> npages ++ ;
311- return 0 ;
312- }
313-
314274/**
315275 * ib_umem_odp_map_dma_and_lock - DMA map userspace memory in an ODP MR and lock it.
316276 *
317277 * Maps the range passed in the argument to DMA addresses.
318- * The DMA addresses of the mapped pages is updated in umem_odp->dma_list.
319278 * Upon success the ODP MR will be locked to let caller complete its device
320279 * page table update.
321280 *
@@ -372,7 +331,7 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt,
372331 range .default_flags |= HMM_PFN_REQ_WRITE ;
373332 }
374333
375- range .hmm_pfns = & (umem_odp -> pfn_list [pfn_start_idx ]);
334+ range .hmm_pfns = & (umem_odp -> map . pfn_list [pfn_start_idx ]);
376335 timeout = jiffies + msecs_to_jiffies (HMM_RANGE_DEFAULT_TIMEOUT );
377336
378337retry :
@@ -423,16 +382,6 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt,
423382 __func__ , hmm_order , page_shift );
424383 break ;
425384 }
426-
427- ret = ib_umem_odp_map_dma_single_page (
428- umem_odp , dma_index ,
429- hmm_pfn_to_page (range .hmm_pfns [pfn_index ]));
430- if (ret < 0 ) {
431- ibdev_dbg (umem_odp -> umem .ibdev ,
432- "ib_umem_odp_map_dma_single_page failed with error %d\n" , ret );
433- break ;
434- }
435- range .hmm_pfns [pfn_index ] |= HMM_PFN_DMA_MAPPED ;
436385 }
437386 /* upon success lock should stay on hold for the callee */
438387 if (!ret )
@@ -452,32 +401,23 @@ EXPORT_SYMBOL(ib_umem_odp_map_dma_and_lock);
452401void ib_umem_odp_unmap_dma_pages (struct ib_umem_odp * umem_odp , u64 virt ,
453402 u64 bound )
454403{
455- dma_addr_t dma ;
456- int idx ;
457- u64 addr ;
458404 struct ib_device * dev = umem_odp -> umem .ibdev ;
405+ u64 addr ;
459406
460407 lockdep_assert_held (& umem_odp -> umem_mutex );
461408
462409 virt = max_t (u64 , virt , ib_umem_start (umem_odp ));
463410 bound = min_t (u64 , bound , ib_umem_end (umem_odp ));
464411 for (addr = virt ; addr < bound ; addr += BIT (umem_odp -> page_shift )) {
465- unsigned long pfn_idx = (addr - ib_umem_start (umem_odp )) >>
466- PAGE_SHIFT ;
467- struct page * page =
468- hmm_pfn_to_page (umem_odp -> pfn_list [pfn_idx ]);
469-
470- idx = (addr - ib_umem_start (umem_odp )) >> umem_odp -> page_shift ;
471- 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 ];
472415
473- if (!(umem_odp -> pfn_list [pfn_idx ] & HMM_PFN_VALID ))
474- goto clear ;
475- if (!(umem_odp -> pfn_list [pfn_idx ] & HMM_PFN_DMA_MAPPED ))
416+ if (!hmm_dma_unmap_pfn (dev -> dma_device , & umem_odp -> map , idx ))
476417 goto clear ;
477418
478- ib_dma_unmap_page (dev , dma , BIT (umem_odp -> page_shift ),
479- DMA_BIDIRECTIONAL );
480- 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 );
481421 struct page * head_page = compound_head (page );
482422 /*
483423 * set_page_dirty prefers being called with
@@ -492,7 +432,7 @@ void ib_umem_odp_unmap_dma_pages(struct ib_umem_odp *umem_odp, u64 virt,
492432 }
493433 umem_odp -> npages -- ;
494434clear :
495- umem_odp -> pfn_list [pfn_idx ] &= ~HMM_PFN_FLAGS ;
435+ umem_odp -> map . pfn_list [idx ] &= ~HMM_PFN_FLAGS ;
496436 }
497437}
498438EXPORT_SYMBOL (ib_umem_odp_unmap_dma_pages );
0 commit comments