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 14static 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 24struct 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 59void xskq_destroy(struct xsk_queue *q) 60{ 61 if (!q) 62 return; 63 64 vfree(q->ring); 65 kfree(q); 66} 67