18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* XDP user-space ring structure 38c2ecf20Sopenharmony_ci * Copyright(c) 2018 Intel Corporation. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/log2.h> 78c2ecf20Sopenharmony_ci#include <linux/slab.h> 88c2ecf20Sopenharmony_ci#include <linux/overflow.h> 98c2ecf20Sopenharmony_ci#include <net/xdp_sock_drv.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "xsk_queue.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistatic size_t xskq_get_ring_size(struct xsk_queue *q, bool umem_queue) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci struct xdp_umem_ring *umem_ring; 168c2ecf20Sopenharmony_ci struct xdp_rxtx_ring *rxtx_ring; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci if (umem_queue) 198c2ecf20Sopenharmony_ci return struct_size(umem_ring, desc, q->nentries); 208c2ecf20Sopenharmony_ci return struct_size(rxtx_ring, desc, q->nentries); 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistruct xsk_queue *xskq_create(u32 nentries, bool umem_queue) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci struct xsk_queue *q; 268c2ecf20Sopenharmony_ci gfp_t gfp_flags; 278c2ecf20Sopenharmony_ci size_t size; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci q = kzalloc(sizeof(*q), GFP_KERNEL); 308c2ecf20Sopenharmony_ci if (!q) 318c2ecf20Sopenharmony_ci return NULL; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci q->nentries = nentries; 348c2ecf20Sopenharmony_ci q->ring_mask = nentries - 1; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci gfp_flags = GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN | 378c2ecf20Sopenharmony_ci __GFP_COMP | __GFP_NORETRY; 388c2ecf20Sopenharmony_ci size = xskq_get_ring_size(q, umem_queue); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci q->ring = (struct xdp_ring *)__get_free_pages(gfp_flags, 418c2ecf20Sopenharmony_ci get_order(size)); 428c2ecf20Sopenharmony_ci if (!q->ring) { 438c2ecf20Sopenharmony_ci kfree(q); 448c2ecf20Sopenharmony_ci return NULL; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci return q; 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_civoid xskq_destroy(struct xsk_queue *q) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci if (!q) 538c2ecf20Sopenharmony_ci return; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci page_frag_free(q->ring); 568c2ecf20Sopenharmony_ci kfree(q); 578c2ecf20Sopenharmony_ci} 58