From 102a0743326a03cd1a1202ceda21e175b7d3575c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 20 Feb 2024 01:20:52 +0000 Subject: [PATCH] add new system file --- kernel/include/rdma/ib_umem_odp.h | 180 ++++++++++++++++++++---------------------------------------- 1 files changed, 60 insertions(+), 120 deletions(-) diff --git a/kernel/include/rdma/ib_umem_odp.h b/kernel/include/rdma/ib_umem_odp.h index 381cdf5..0844c1d 100644 --- a/kernel/include/rdma/ib_umem_odp.h +++ b/kernel/include/rdma/ib_umem_odp.h @@ -1,33 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * 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. */ #ifndef IB_UMEM_ODP_H @@ -35,25 +8,19 @@ #include <rdma/ib_umem.h> #include <rdma/ib_verbs.h> -#include <linux/interval_tree.h> - -struct umem_odp_node { - u64 __subtree_last; - struct rb_node rb; -}; struct ib_umem_odp { + struct ib_umem umem; + struct mmu_interval_notifier notifier; + struct pid *tgid; + + /* An array of the pfns included in the on-demand paging umem. */ + unsigned long *pfn_list; + /* - * An array of the pages included in the on-demand paging umem. - * Indices of pages that are currently not mapped into the device will - * contain NULL. - */ - struct page **page_list; - /* - * An array of the same size as page_list, with DMA addresses mapped - * for pages the pages in page_list. The lower two bits designate - * access permissions. See ODP_READ_ALLOWED_BIT and - * ODP_WRITE_ALLOWED_BIT. + * An array with DMA addresses mapped for pfns in pfn_list. + * The lower two bits designate access permissions. + * See ODP_READ_ALLOWED_BIT and ODP_WRITE_ALLOWED_BIT. */ dma_addr_t *dma_list; /* @@ -64,33 +31,41 @@ struct mutex umem_mutex; void *private; /* for the HW driver to use. */ - /* When false, use the notifier counter in the ucontext struct. */ - bool mn_counters_active; - int notifiers_seq; - int notifiers_count; + int npages; - /* A linked list of umems that don't have private mmu notifier - * counters yet. */ - struct list_head no_private_counters; - struct ib_umem *umem; + /* + * An implicit odp umem cannot be DMA mapped, has 0 length, and serves + * only as an anchor for the driver to hold onto the per_mm. FIXME: + * This should be removed and drivers should work with the per_mm + * directly. + */ + bool is_implicit_odp; - /* Tree tracking */ - struct umem_odp_node interval_tree; - - struct completion notifier_completion; - int dying; - struct work_struct work; + unsigned int page_shift; }; -#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING +static inline struct ib_umem_odp *to_ib_umem_odp(struct ib_umem *umem) +{ + return container_of(umem, struct ib_umem_odp, umem); +} -int ib_umem_odp_get(struct ib_ucontext *context, struct ib_umem *umem, - int access); -struct ib_umem *ib_alloc_odp_umem(struct ib_ucontext *context, - unsigned long addr, - size_t size); +/* Returns the first page of an ODP umem. */ +static inline unsigned long ib_umem_start(struct ib_umem_odp *umem_odp) +{ + return umem_odp->notifier.interval_tree.start; +} -void ib_umem_odp_release(struct ib_umem *umem); +/* Returns the address of the page after the last one of an ODP umem. */ +static inline unsigned long ib_umem_end(struct ib_umem_odp *umem_odp) +{ + return umem_odp->notifier.interval_tree.last + 1; +} + +static inline size_t ib_umem_odp_num_pages(struct ib_umem_odp *umem_odp) +{ + return (ib_umem_end(umem_odp) - ib_umem_start(umem_odp)) >> + umem_odp->page_shift; +} /* * The lower 2 bits of the DMA address signal the R/W permissions for @@ -105,70 +80,35 @@ #define ODP_DMA_ADDR_MASK (~(ODP_READ_ALLOWED_BIT | ODP_WRITE_ALLOWED_BIT)) -int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 start_offset, u64 bcnt, - u64 access_mask, unsigned long current_seq); +#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING -void ib_umem_odp_unmap_dma_pages(struct ib_umem *umem, u64 start_offset, +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); +struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_device *device, + int access); +struct ib_umem_odp * +ib_umem_odp_alloc_child(struct ib_umem_odp *root_umem, unsigned long addr, + size_t size, + const struct mmu_interval_notifier_ops *ops); +void ib_umem_odp_release(struct ib_umem_odp *umem_odp); + +int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 start_offset, + u64 bcnt, u64 access_mask, bool fault); + +void ib_umem_odp_unmap_dma_pages(struct ib_umem_odp *umem_odp, u64 start_offset, u64 bound); - -typedef int (*umem_call_back)(struct ib_umem *item, u64 start, u64 end, - void *cookie); -/* - * Call the callback on each ib_umem in the range. Returns the logical or of - * the return values of the functions called. - */ -int rbt_ib_umem_for_each_in_range(struct rb_root_cached *root, - u64 start, u64 end, - umem_call_back cb, - bool blockable, void *cookie); - -/* - * Find first region intersecting with address range. - * Return NULL if not found - */ -struct ib_umem_odp *rbt_ib_umem_lookup(struct rb_root_cached *root, - u64 addr, u64 length); - -static inline int ib_umem_mmu_notifier_retry(struct ib_umem *item, - unsigned long mmu_seq) -{ - /* - * This code is strongly based on the KVM code from - * mmu_notifier_retry. Should be called with - * the relevant locks taken (item->odp_data->umem_mutex - * and the ucontext umem_mutex semaphore locked for read). - */ - - /* Do not allow page faults while the new ib_umem hasn't seen a state - * with zero notifiers yet, and doesn't have its own valid set of - * private counters. */ - if (!item->odp_data->mn_counters_active) - return 1; - - if (unlikely(item->odp_data->notifiers_count)) - return 1; - if (item->odp_data->notifiers_seq != mmu_seq) - return 1; - return 0; -} #else /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */ -static inline int ib_umem_odp_get(struct ib_ucontext *context, - struct ib_umem *umem, - int access) -{ - return -EINVAL; -} - -static inline struct ib_umem *ib_alloc_odp_umem(struct ib_ucontext *context, - unsigned long addr, - size_t size) +static inline 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) { return ERR_PTR(-EINVAL); } -static inline void ib_umem_odp_release(struct ib_umem *umem) {} +static inline void ib_umem_odp_release(struct ib_umem_odp *umem_odp) {} #endif /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */ -- Gitblit v1.6.2