1*6bf9d8f6SLeon Romanovsky /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 28ada2c1cSShachar Raindel /* 38ada2c1cSShachar Raindel * Copyright (c) 2014 Mellanox Technologies. All rights reserved. 48ada2c1cSShachar Raindel */ 58ada2c1cSShachar Raindel 68ada2c1cSShachar Raindel #ifndef IB_UMEM_ODP_H 78ada2c1cSShachar Raindel #define IB_UMEM_ODP_H 88ada2c1cSShachar Raindel 98ada2c1cSShachar Raindel #include <rdma/ib_umem.h> 10882214e2SHaggai Eran #include <rdma/ib_verbs.h> 11882214e2SHaggai Eran 128ada2c1cSShachar Raindel struct ib_umem_odp { 1341b4deeaSJason Gunthorpe struct ib_umem umem; 14f25a546eSJason Gunthorpe struct mmu_interval_notifier notifier; 15f25a546eSJason Gunthorpe struct pid *tgid; 16c9990ab3SJason Gunthorpe 178ada2c1cSShachar Raindel /* 188ada2c1cSShachar Raindel * An array of the pages included in the on-demand paging umem. 198ada2c1cSShachar Raindel * Indices of pages that are currently not mapped into the device will 208ada2c1cSShachar Raindel * contain NULL. 218ada2c1cSShachar Raindel */ 228ada2c1cSShachar Raindel struct page **page_list; 238ada2c1cSShachar Raindel /* 248ada2c1cSShachar Raindel * An array of the same size as page_list, with DMA addresses mapped 258ada2c1cSShachar Raindel * for pages the pages in page_list. The lower two bits designate 268ada2c1cSShachar Raindel * access permissions. See ODP_READ_ALLOWED_BIT and 278ada2c1cSShachar Raindel * ODP_WRITE_ALLOWED_BIT. 288ada2c1cSShachar Raindel */ 298ada2c1cSShachar Raindel dma_addr_t *dma_list; 308ada2c1cSShachar Raindel /* 318ada2c1cSShachar Raindel * The umem_mutex protects the page_list and dma_list fields of an ODP 32882214e2SHaggai Eran * umem, allowing only a single thread to map/unmap pages. The mutex 33882214e2SHaggai Eran * also protects access to the mmu notifier counters. 348ada2c1cSShachar Raindel */ 358ada2c1cSShachar Raindel struct mutex umem_mutex; 368ada2c1cSShachar Raindel void *private; /* for the HW driver to use. */ 37882214e2SHaggai Eran 38d10bcf94SShiraz Saleem int npages; 39882214e2SHaggai Eran 40fd7dbf03SJason Gunthorpe /* 41fd7dbf03SJason Gunthorpe * An implicit odp umem cannot be DMA mapped, has 0 length, and serves 42fd7dbf03SJason Gunthorpe * only as an anchor for the driver to hold onto the per_mm. FIXME: 43fd7dbf03SJason Gunthorpe * This should be removed and drivers should work with the per_mm 44fd7dbf03SJason Gunthorpe * directly. 45fd7dbf03SJason Gunthorpe */ 46fd7dbf03SJason Gunthorpe bool is_implicit_odp; 47fd7dbf03SJason Gunthorpe 48d2183c6fSJason Gunthorpe unsigned int page_shift; 498ada2c1cSShachar Raindel }; 508ada2c1cSShachar Raindel 51b5231b01SJason Gunthorpe static inline struct ib_umem_odp *to_ib_umem_odp(struct ib_umem *umem) 52b5231b01SJason Gunthorpe { 5341b4deeaSJason Gunthorpe return container_of(umem, struct ib_umem_odp, umem); 54b5231b01SJason Gunthorpe } 55b5231b01SJason Gunthorpe 56d2183c6fSJason Gunthorpe /* Returns the first page of an ODP umem. */ 57d2183c6fSJason Gunthorpe static inline unsigned long ib_umem_start(struct ib_umem_odp *umem_odp) 58d2183c6fSJason Gunthorpe { 59f25a546eSJason Gunthorpe return umem_odp->notifier.interval_tree.start; 60d2183c6fSJason Gunthorpe } 61d2183c6fSJason Gunthorpe 62d2183c6fSJason Gunthorpe /* Returns the address of the page after the last one of an ODP umem. */ 63d2183c6fSJason Gunthorpe static inline unsigned long ib_umem_end(struct ib_umem_odp *umem_odp) 64d2183c6fSJason Gunthorpe { 65f25a546eSJason Gunthorpe return umem_odp->notifier.interval_tree.last + 1; 66d2183c6fSJason Gunthorpe } 67d2183c6fSJason Gunthorpe 68d2183c6fSJason Gunthorpe static inline size_t ib_umem_odp_num_pages(struct ib_umem_odp *umem_odp) 69d2183c6fSJason Gunthorpe { 70d2183c6fSJason Gunthorpe return (ib_umem_end(umem_odp) - ib_umem_start(umem_odp)) >> 71d2183c6fSJason Gunthorpe umem_odp->page_shift; 72d2183c6fSJason Gunthorpe } 73d2183c6fSJason Gunthorpe 7413859d5dSLeon Romanovsky /* 7513859d5dSLeon Romanovsky * The lower 2 bits of the DMA address signal the R/W permissions for 7613859d5dSLeon Romanovsky * the entry. To upgrade the permissions, provide the appropriate 7713859d5dSLeon Romanovsky * bitmask to the map_dma_pages function. 7813859d5dSLeon Romanovsky * 7913859d5dSLeon Romanovsky * Be aware that upgrading a mapped address might result in change of 8013859d5dSLeon Romanovsky * the DMA address for the page. 8113859d5dSLeon Romanovsky */ 8213859d5dSLeon Romanovsky #define ODP_READ_ALLOWED_BIT (1<<0ULL) 8313859d5dSLeon Romanovsky #define ODP_WRITE_ALLOWED_BIT (1<<1ULL) 8413859d5dSLeon Romanovsky 8513859d5dSLeon Romanovsky #define ODP_DMA_ADDR_MASK (~(ODP_READ_ALLOWED_BIT | ODP_WRITE_ALLOWED_BIT)) 8613859d5dSLeon Romanovsky 878ada2c1cSShachar Raindel #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING 888ada2c1cSShachar Raindel 89f25a546eSJason Gunthorpe struct ib_umem_odp * 90c320e527SMoni Shoua ib_umem_odp_get(struct ib_device *device, unsigned long addr, size_t size, 91f25a546eSJason Gunthorpe int access, const struct mmu_interval_notifier_ops *ops); 92c320e527SMoni Shoua struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_device *device, 93f20bef6aSJason Gunthorpe int access); 94f25a546eSJason Gunthorpe struct ib_umem_odp * 95f25a546eSJason Gunthorpe ib_umem_odp_alloc_child(struct ib_umem_odp *root_umem, unsigned long addr, 96f25a546eSJason Gunthorpe size_t size, 97f25a546eSJason Gunthorpe const struct mmu_interval_notifier_ops *ops); 98b5231b01SJason Gunthorpe void ib_umem_odp_release(struct ib_umem_odp *umem_odp); 998ada2c1cSShachar Raindel 100b5231b01SJason Gunthorpe int ib_umem_odp_map_dma_pages(struct ib_umem_odp *umem_odp, u64 start_offset, 101b5231b01SJason Gunthorpe u64 bcnt, u64 access_mask, 102b5231b01SJason Gunthorpe unsigned long current_seq); 1038ada2c1cSShachar Raindel 104b5231b01SJason Gunthorpe void ib_umem_odp_unmap_dma_pages(struct ib_umem_odp *umem_odp, u64 start_offset, 1058ada2c1cSShachar Raindel u64 bound); 1068ada2c1cSShachar Raindel 1078ada2c1cSShachar Raindel #else /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */ 1088ada2c1cSShachar Raindel 109f25a546eSJason Gunthorpe static inline struct ib_umem_odp * 110c320e527SMoni Shoua ib_umem_odp_get(struct ib_device *device, unsigned long addr, size_t size, 111f25a546eSJason Gunthorpe int access, const struct mmu_interval_notifier_ops *ops) 1128ada2c1cSShachar Raindel { 113261dc53fSJason Gunthorpe return ERR_PTR(-EINVAL); 1148ada2c1cSShachar Raindel } 1158ada2c1cSShachar Raindel 116b5231b01SJason Gunthorpe static inline void ib_umem_odp_release(struct ib_umem_odp *umem_odp) {} 1178ada2c1cSShachar Raindel 1188ada2c1cSShachar Raindel #endif /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */ 1198ada2c1cSShachar Raindel 1208ada2c1cSShachar Raindel #endif /* IB_UMEM_ODP_H */ 121