diff options
-rw-r--r-- | include/net/xdp_sock.h | 7 | ||||
-rw-r--r-- | net/xdp/xdp_umem.c | 15 | ||||
-rw-r--r-- | net/xdp/xdp_umem.h | 3 |
3 files changed, 21 insertions, 4 deletions
diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h index 3a6cd88f179d..caf343a7e224 100644 --- a/include/net/xdp_sock.h +++ b/include/net/xdp_sock.h | |||
@@ -20,10 +20,14 @@ struct xdp_umem_props { | |||
20 | u64 size; | 20 | u64 size; |
21 | }; | 21 | }; |
22 | 22 | ||
23 | struct xdp_umem_page { | ||
24 | void *addr; | ||
25 | }; | ||
26 | |||
23 | struct xdp_umem { | 27 | struct xdp_umem { |
24 | struct xsk_queue *fq; | 28 | struct xsk_queue *fq; |
25 | struct xsk_queue *cq; | 29 | struct xsk_queue *cq; |
26 | struct page **pgs; | 30 | struct xdp_umem_page *pages; |
27 | struct xdp_umem_props props; | 31 | struct xdp_umem_props props; |
28 | u32 headroom; | 32 | u32 headroom; |
29 | u32 chunk_size_nohr; | 33 | u32 chunk_size_nohr; |
@@ -32,6 +36,7 @@ struct xdp_umem { | |||
32 | unsigned long address; | 36 | unsigned long address; |
33 | refcount_t users; | 37 | refcount_t users; |
34 | struct work_struct work; | 38 | struct work_struct work; |
39 | struct page **pgs; | ||
35 | u32 npgs; | 40 | u32 npgs; |
36 | }; | 41 | }; |
37 | 42 | ||
diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index 2793a503223e..aca826011f6c 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c | |||
@@ -65,6 +65,9 @@ static void xdp_umem_release(struct xdp_umem *umem) | |||
65 | goto out; | 65 | goto out; |
66 | 66 | ||
67 | mmput(mm); | 67 | mmput(mm); |
68 | kfree(umem->pages); | ||
69 | umem->pages = NULL; | ||
70 | |||
68 | xdp_umem_unaccount_pages(umem); | 71 | xdp_umem_unaccount_pages(umem); |
69 | out: | 72 | out: |
70 | kfree(umem); | 73 | kfree(umem); |
@@ -155,7 +158,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) | |||
155 | u32 chunk_size = mr->chunk_size, headroom = mr->headroom; | 158 | u32 chunk_size = mr->chunk_size, headroom = mr->headroom; |
156 | unsigned int chunks, chunks_per_page; | 159 | unsigned int chunks, chunks_per_page; |
157 | u64 addr = mr->addr, size = mr->len; | 160 | u64 addr = mr->addr, size = mr->len; |
158 | int size_chk, err; | 161 | int size_chk, err, i; |
159 | 162 | ||
160 | if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) { | 163 | if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) { |
161 | /* Strictly speaking we could support this, if: | 164 | /* Strictly speaking we could support this, if: |
@@ -213,6 +216,16 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) | |||
213 | err = xdp_umem_pin_pages(umem); | 216 | err = xdp_umem_pin_pages(umem); |
214 | if (err) | 217 | if (err) |
215 | goto out_account; | 218 | goto out_account; |
219 | |||
220 | umem->pages = kcalloc(umem->npgs, sizeof(*umem->pages), GFP_KERNEL); | ||
221 | if (!umem->pages) { | ||
222 | err = -ENOMEM; | ||
223 | goto out_account; | ||
224 | } | ||
225 | |||
226 | for (i = 0; i < umem->npgs; i++) | ||
227 | umem->pages[i].addr = page_address(umem->pgs[i]); | ||
228 | |||
216 | return 0; | 229 | return 0; |
217 | 230 | ||
218 | out_account: | 231 | out_account: |
diff --git a/net/xdp/xdp_umem.h b/net/xdp/xdp_umem.h index 9433e8af650a..40e8fa4a92af 100644 --- a/net/xdp/xdp_umem.h +++ b/net/xdp/xdp_umem.h | |||
@@ -10,8 +10,7 @@ | |||
10 | 10 | ||
11 | static inline char *xdp_umem_get_data(struct xdp_umem *umem, u64 addr) | 11 | static inline char *xdp_umem_get_data(struct xdp_umem *umem, u64 addr) |
12 | { | 12 | { |
13 | return page_address(umem->pgs[addr >> PAGE_SHIFT]) + | 13 | return umem->pages[addr >> PAGE_SHIFT].addr + (addr & (PAGE_SIZE - 1)); |
14 | (addr & (PAGE_SIZE - 1)); | ||
15 | } | 14 | } |
16 | 15 | ||
17 | bool xdp_umem_validate_queues(struct xdp_umem *umem); | 16 | bool xdp_umem_validate_queues(struct xdp_umem *umem); |