hc
2025-02-14 bbb9540dc49f70f6b703d1c8d1b85fa5f602d86e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/*
 * Copyright (c) 2007 Cisco Systems.  All rights reserved.
 */
 
#ifndef IB_UMEM_H
#define IB_UMEM_H
 
#include <linux/list.h>
#include <linux/scatterlist.h>
#include <linux/workqueue.h>
#include <rdma/ib_verbs.h>
 
struct ib_ucontext;
struct ib_umem_odp;
 
struct ib_umem {
   struct ib_device       *ibdev;
   struct mm_struct       *owning_mm;
   u64 iova;
   size_t            length;
   unsigned long        address;
   u32 writable : 1;
   u32 is_odp : 1;
   struct work_struct    work;
   struct sg_table sg_head;
   int             nmap;
   unsigned int    sg_nents;
};
 
/* Returns the offset of the umem start relative to the first page. */
static inline int ib_umem_offset(struct ib_umem *umem)
{
   return umem->address & ~PAGE_MASK;
}
 
static inline size_t ib_umem_num_dma_blocks(struct ib_umem *umem,
                       unsigned long pgsz)
{
   return (size_t)((ALIGN(umem->iova + umem->length, pgsz) -
            ALIGN_DOWN(umem->iova, pgsz))) /
          pgsz;
}
 
static inline size_t ib_umem_num_pages(struct ib_umem *umem)
{
   return ib_umem_num_dma_blocks(umem, PAGE_SIZE);
}
 
static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter,
                       struct ib_umem *umem,
                       unsigned long pgsz)
{
   __rdma_block_iter_start(biter, umem->sg_head.sgl, umem->nmap, pgsz);
}
 
/**
 * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
 * @umem: umem to iterate over
 * @pgsz: Page size to split the list into
 *
 * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
 * returned DMA blocks will be aligned to pgsz and span the range:
 * ALIGN_DOWN(umem->address, pgsz) to ALIGN(umem->address + umem->length, pgsz)
 *
 * Performs exactly ib_umem_num_dma_blocks() iterations.
 */
#define rdma_umem_for_each_dma_block(umem, biter, pgsz)                        \
   for (__rdma_umem_block_iter_start(biter, umem, pgsz);                  \
        __rdma_block_iter_next(biter);)
 
#ifdef CONFIG_INFINIBAND_USER_MEM
 
struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
               size_t size, int access);
void ib_umem_release(struct ib_umem *umem);
int ib_umem_copy_from(void *dst, struct ib_umem *umem, size_t offset,
             size_t length);
unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
                    unsigned long pgsz_bitmap,
                    unsigned long virt);
 
#else /* CONFIG_INFINIBAND_USER_MEM */
 
#include <linux/err.h>
 
static inline struct ib_umem *ib_umem_get(struct ib_device *device,
                     unsigned long addr, size_t size,
                     int access)
{
   return ERR_PTR(-EINVAL);
}
static inline void ib_umem_release(struct ib_umem *umem) { }
static inline int ib_umem_copy_from(void *dst, struct ib_umem *umem, size_t offset,
                         size_t length) {
   return -EINVAL;
}
static inline unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
                          unsigned long pgsz_bitmap,
                          unsigned long virt)
{
   return 0;
}
 
#endif /* CONFIG_INFINIBAND_USER_MEM */
 
#endif /* IB_UMEM_H */