RDMA/umem: Separate implicit ODP initialization from explicit ODP

Create separate functions for the implicit ODP initialization
which is different from the explicit ODP initialization.

Tested-by: Jens Axboe <axboe@kernel.dk>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
This commit is contained in:
Leon Romanovsky
2025-05-12 06:06:55 -04:00
committed by Leon Romanovsky
parent 1efe8c0670
commit 15a9f67e28
+44 -43
View File
@@ -48,41 +48,44 @@
#include "uverbs.h"
static inline int ib_init_umem_odp(struct ib_umem_odp *umem_odp,
const struct mmu_interval_notifier_ops *ops)
static void ib_init_umem_implicit_odp(struct ib_umem_odp *umem_odp)
{
umem_odp->is_implicit_odp = 1;
umem_odp->umem.is_odp = 1;
mutex_init(&umem_odp->umem_mutex);
}
static int ib_init_umem_odp(struct ib_umem_odp *umem_odp,
const struct mmu_interval_notifier_ops *ops)
{
struct ib_device *dev = umem_odp->umem.ibdev;
size_t page_size = 1UL << umem_odp->page_shift;
unsigned long start;
unsigned long end;
int ret;
umem_odp->umem.is_odp = 1;
mutex_init(&umem_odp->umem_mutex);
if (!umem_odp->is_implicit_odp) {
size_t page_size = 1UL << umem_odp->page_shift;
unsigned long start;
unsigned long end;
start = ALIGN_DOWN(umem_odp->umem.address, page_size);
if (check_add_overflow(umem_odp->umem.address,
(unsigned long)umem_odp->umem.length, &end))
return -EOVERFLOW;
end = ALIGN(end, page_size);
if (unlikely(end < page_size))
return -EOVERFLOW;
start = ALIGN_DOWN(umem_odp->umem.address, page_size);
if (check_add_overflow(umem_odp->umem.address,
(unsigned long)umem_odp->umem.length,
&end))
return -EOVERFLOW;
end = ALIGN(end, page_size);
if (unlikely(end < page_size))
return -EOVERFLOW;
ret = hmm_dma_map_alloc(dev->dma_device, &umem_odp->map,
(end - start) >> PAGE_SHIFT,
1 << umem_odp->page_shift);
if (ret)
return ret;
ret = hmm_dma_map_alloc(dev->dma_device, &umem_odp->map,
(end - start) >> PAGE_SHIFT,
1 << umem_odp->page_shift);
if (ret)
return ret;
ret = mmu_interval_notifier_insert(&umem_odp->notifier,
umem_odp->umem.owning_mm,
start, end - start, ops);
if (ret)
goto out_free_map;
}
ret = mmu_interval_notifier_insert(&umem_odp->notifier,
umem_odp->umem.owning_mm, start,
end - start, ops);
if (ret)
goto out_free_map;
return 0;
@@ -106,7 +109,6 @@ struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_device *device,
{
struct ib_umem *umem;
struct ib_umem_odp *umem_odp;
int ret;
if (access & IB_ACCESS_HUGETLB)
return ERR_PTR(-EINVAL);
@@ -118,16 +120,10 @@ struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_device *device,
umem->ibdev = device;
umem->writable = ib_access_writable(access);
umem->owning_mm = current->mm;
umem_odp->is_implicit_odp = 1;
umem_odp->page_shift = PAGE_SHIFT;
umem_odp->tgid = get_task_pid(current->group_leader, PIDTYPE_PID);
ret = ib_init_umem_odp(umem_odp, NULL);
if (ret) {
put_pid(umem_odp->tgid);
kfree(umem_odp);
return ERR_PTR(ret);
}
ib_init_umem_implicit_odp(umem_odp);
return umem_odp;
}
EXPORT_SYMBOL(ib_umem_odp_alloc_implicit);
@@ -248,7 +244,7 @@ err_put_pid:
}
EXPORT_SYMBOL(ib_umem_odp_get);
void ib_umem_odp_release(struct ib_umem_odp *umem_odp)
static void ib_umem_odp_free(struct ib_umem_odp *umem_odp)
{
struct ib_device *dev = umem_odp->umem.ibdev;
@@ -258,14 +254,19 @@ void ib_umem_odp_release(struct ib_umem_odp *umem_odp)
* It is the driver's responsibility to ensure, before calling us,
* that the hardware will not attempt to access the MR any more.
*/
if (!umem_odp->is_implicit_odp) {
mutex_lock(&umem_odp->umem_mutex);
ib_umem_odp_unmap_dma_pages(umem_odp, ib_umem_start(umem_odp),
ib_umem_end(umem_odp));
mutex_unlock(&umem_odp->umem_mutex);
mmu_interval_notifier_remove(&umem_odp->notifier);
hmm_dma_map_free(dev->dma_device, &umem_odp->map);
}
mutex_lock(&umem_odp->umem_mutex);
ib_umem_odp_unmap_dma_pages(umem_odp, ib_umem_start(umem_odp),
ib_umem_end(umem_odp));
mutex_unlock(&umem_odp->umem_mutex);
mmu_interval_notifier_remove(&umem_odp->notifier);
hmm_dma_map_free(dev->dma_device, &umem_odp->map);
}
void ib_umem_odp_release(struct ib_umem_odp *umem_odp)
{
if (!umem_odp->is_implicit_odp)
ib_umem_odp_free(umem_odp);
put_pid(umem_odp->tgid);
kfree(umem_odp);
}