/* * Copyright (c) 2014 Mellanox Technologies. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include <linux/types.h> #include <linux/sched.h> #include <linux/sched/mm.h> #include <linux/sched/task.h> #include <linux/pid.h> #include <linux/slab.h> #include <linux/export.h> #include <linux/vmalloc.h> #include <linux/hugetlb.h> #include <linux/interval_tree.h> #include <linux/hmm.h> #include <linux/pagemap.h> #include <rdma/ib_umem_odp.h> #include "uverbs.h" static inline int ib_init_umem_odp(struct ib_umem_odp *umem_odp, const struct mmu_interval_notifier_ops *ops) { … } /** * ib_umem_odp_alloc_implicit - Allocate a parent implicit ODP umem * * Implicit ODP umems do not have a VA range and do not have any page lists. * They exist only to hold the per_mm reference to help the driver create * children umems. * * @device: IB device to create UMEM * @access: ib_reg_mr access flags */ struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_device *device, int access) { … } EXPORT_SYMBOL(…); /** * ib_umem_odp_alloc_child - Allocate a child ODP umem under an implicit * parent ODP umem * * @root: The parent umem enclosing the child. This must be allocated using * ib_alloc_implicit_odp_umem() * @addr: The starting userspace VA * @size: The length of the userspace VA * @ops: MMU interval ops, currently only @invalidate */ struct ib_umem_odp * ib_umem_odp_alloc_child(struct ib_umem_odp *root, unsigned long addr, size_t size, const struct mmu_interval_notifier_ops *ops) { … } EXPORT_SYMBOL(…); /** * ib_umem_odp_get - Create a umem_odp for a userspace va * * @device: IB device struct to get UMEM * @addr: userspace virtual address to start at * @size: length of region to pin * @access: IB_ACCESS_xxx flags for memory being pinned * @ops: MMU interval ops, currently only @invalidate * * The driver should use when the access flags indicate ODP memory. It avoids * pinning, instead, stores the mm for future page fault handling in * conjunction with MMU notifiers. */ struct ib_umem_odp *ib_umem_odp_get(struct ib_device *device, unsigned long addr, size_t size, int access, const struct mmu_interval_notifier_ops *ops) { … } EXPORT_SYMBOL(…); void ib_umem_odp_release(struct ib_umem_odp *umem_odp) { … } EXPORT_SYMBOL(…); /* * Map for DMA and insert a single page into the on-demand paging page tables. * * @umem: the umem to insert the page to. * @dma_index: index in the umem to add the dma to. * @page: the page struct to map and add. * @access_mask: access permissions needed for this page. * * The function returns -EFAULT if the DMA mapping operation fails. * */ static int ib_umem_odp_map_dma_single_page( struct ib_umem_odp *umem_odp, unsigned int dma_index, struct page *page, u64 access_mask) { … } /** * ib_umem_odp_map_dma_and_lock - DMA map userspace memory in an ODP MR and lock it. * * Maps the range passed in the argument to DMA addresses. * The DMA addresses of the mapped pages is updated in umem_odp->dma_list. * Upon success the ODP MR will be locked to let caller complete its device * page table update. * * Returns the number of pages mapped in success, negative error code * for failure. * @umem_odp: the umem to map and pin * @user_virt: the address from which we need to map. * @bcnt: the minimal number of bytes to pin and map. The mapping might be * bigger due to alignment, and may also be smaller in case of an error * pinning or mapping a page. The actual pages mapped is returned in * the return value. * @access_mask: bit mask of the requested access permissions for the given * range. * @fault: is faulting required for the given range */ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt, u64 bcnt, u64 access_mask, bool fault) __acquires(&umem_odp->umem_mutex) { … } EXPORT_SYMBOL(…); void ib_umem_odp_unmap_dma_pages(struct ib_umem_odp *umem_odp, u64 virt, u64 bound) { … } EXPORT_SYMBOL(…);