1 // SPDX-License-Identifier: GPL-2.0 2 /* XDP user-space ring structure 3 * Copyright(c) 2018 Intel Corporation. 4 */ 5 6 #include <linux/log2.h> 7 #include <linux/slab.h> 8 #include <linux/overflow.h> 9 #include <linux/vmalloc.h> 10 #include <net/xdp_sock_drv.h> 11 12 #include "xsk_queue.h" 13 14 static size_t xskq_get_ring_size(struct xsk_queue *q, bool umem_queue) 15 { 16 struct xdp_umem_ring *umem_ring; 17 struct xdp_rxtx_ring *rxtx_ring; 18 19 if (umem_queue) 20 return struct_size(umem_ring, desc, q->nentries); 21 return struct_size(rxtx_ring, desc, q->nentries); 22 } 23 24 struct xsk_queue *xskq_create(u32 nentries, bool umem_queue) 25 { 26 struct xsk_queue *q; 27 size_t size; 28 29 q = kzalloc(sizeof(*q), GFP_KERNEL); 30 if (!q) 31 return NULL; 32 33 q->nentries = nentries; 34 q->ring_mask = nentries - 1; 35 36 size = xskq_get_ring_size(q, umem_queue); 37 38 /* size which is overflowing or close to SIZE_MAX will become 0 in 39 * PAGE_ALIGN(), checking SIZE_MAX is enough due to the previous 40 * is_power_of_2(), the rest will be handled by vmalloc_user() 41 */ 42 if (unlikely(size == SIZE_MAX)) { 43 kfree(q); 44 return NULL; 45 } 46 47 size = PAGE_ALIGN(size); 48 49 q->ring = vmalloc_user(size); 50 if (!q->ring) { 51 kfree(q); 52 return NULL; 53 } 54 55 q->ring_vmalloc_size = size; 56 return q; 57 } 58 59 void xskq_destroy(struct xsk_queue *q) 60 { 61 if (!q) 62 return; 63 64 vfree(q->ring); 65 kfree(q); 66 } 67