aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/xdp_sock.h7
-rw-r--r--net/xdp/xdp_umem.c15
-rw-r--r--net/xdp/xdp_umem.h3
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
23struct xdp_umem_page {
24 void *addr;
25};
26
23struct xdp_umem { 27struct 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);
69out: 72out:
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
218out_account: 231out_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
11static inline char *xdp_umem_get_data(struct xdp_umem *umem, u64 addr) 11static 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
17bool xdp_umem_validate_queues(struct xdp_umem *umem); 16bool xdp_umem_validate_queues(struct xdp_umem *umem);