2018-05-02 14:01:24 +03:00
// SPDX-License-Identifier: GPL-2.0
/* XDP user-space ring structure
* Copyright ( c ) 2018 Intel Corporation .
*/
2018-09-07 11:18:46 +03:00
# include <linux/log2.h>
2018-05-02 14:01:24 +03:00
# include <linux/slab.h>
2018-09-07 11:18:46 +03:00
# include <linux/overflow.h>
2023-02-16 11:30:47 +03:00
# include <linux/vmalloc.h>
2020-05-20 22:20:51 +03:00
# include <net/xdp_sock_drv.h>
2018-05-02 14:01:24 +03:00
# include "xsk_queue.h"
2019-12-19 15:39:31 +03:00
static size_t xskq_get_ring_size ( struct xsk_queue * q , bool umem_queue )
2018-05-02 14:01:24 +03:00
{
2019-12-19 15:39:31 +03:00
struct xdp_umem_ring * umem_ring ;
struct xdp_rxtx_ring * rxtx_ring ;
2018-05-02 14:01:24 +03:00
2019-12-19 15:39:31 +03:00
if ( umem_queue )
return struct_size ( umem_ring , desc , q - > nentries ) ;
return struct_size ( rxtx_ring , desc , q - > nentries ) ;
2018-05-02 14:01:25 +03:00
}
struct xsk_queue * xskq_create ( u32 nentries , bool umem_queue )
2018-05-02 14:01:24 +03:00
{
struct xsk_queue * q ;
size_t size ;
q = kzalloc ( sizeof ( * q ) , GFP_KERNEL ) ;
if ( ! q )
return NULL ;
q - > nentries = nentries ;
q - > ring_mask = nentries - 1 ;
2019-12-19 15:39:31 +03:00
size = xskq_get_ring_size ( q , umem_queue ) ;
2023-10-07 10:51:49 +03:00
/* size which is overflowing or close to SIZE_MAX will become 0 in
* PAGE_ALIGN ( ) , checking SIZE_MAX is enough due to the previous
* is_power_of_2 ( ) , the rest will be handled by vmalloc_user ( )
*/
if ( unlikely ( size = = SIZE_MAX ) ) {
kfree ( q ) ;
return NULL ;
}
2023-02-16 11:30:47 +03:00
size = PAGE_ALIGN ( size ) ;
2018-05-02 14:01:24 +03:00
2023-02-16 11:30:47 +03:00
q - > ring = vmalloc_user ( size ) ;
2018-05-02 14:01:24 +03:00
if ( ! q - > ring ) {
kfree ( q ) ;
return NULL ;
}
2023-02-16 11:30:47 +03:00
q - > ring_vmalloc_size = size ;
2018-05-02 14:01:24 +03:00
return q ;
}
void xskq_destroy ( struct xsk_queue * q )
{
if ( ! q )
return ;
2023-02-16 11:30:47 +03:00
vfree ( q - > ring ) ;
2018-05-02 14:01:24 +03:00
kfree ( q ) ;
}