diff options
Diffstat (limited to 'net/core/xdp.c')
| -rw-r--r-- | net/core/xdp.c | 73 | 
1 files changed, 73 insertions, 0 deletions
diff --git a/net/core/xdp.c b/net/core/xdp.c new file mode 100644 index 000000000000..097a0f74e004 --- /dev/null +++ b/net/core/xdp.c @@ -0,0 +1,73 @@ +/* net/core/xdp.c + * + * Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc. + * Released under terms in GPL version 2.  See COPYING. + */ +#include <linux/types.h> +#include <linux/mm.h> + +#include <net/xdp.h> + +#define REG_STATE_NEW		0x0 +#define REG_STATE_REGISTERED	0x1 +#define REG_STATE_UNREGISTERED	0x2 +#define REG_STATE_UNUSED	0x3 + +void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq) +{ +	/* Simplify driver cleanup code paths, allow unreg "unused" */ +	if (xdp_rxq->reg_state == REG_STATE_UNUSED) +		return; + +	WARN(!(xdp_rxq->reg_state == REG_STATE_REGISTERED), "Driver BUG"); + +	xdp_rxq->reg_state = REG_STATE_UNREGISTERED; +	xdp_rxq->dev = NULL; +} +EXPORT_SYMBOL_GPL(xdp_rxq_info_unreg); + +static void xdp_rxq_info_init(struct xdp_rxq_info *xdp_rxq) +{ +	memset(xdp_rxq, 0, sizeof(*xdp_rxq)); +} + +/* Returns 0 on success, negative on failure */ +int xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq, +		     struct net_device *dev, u32 queue_index) +{ +	if (xdp_rxq->reg_state == REG_STATE_UNUSED) { +		WARN(1, "Driver promised not to register this"); +		return -EINVAL; +	} + +	if (xdp_rxq->reg_state == REG_STATE_REGISTERED) { +		WARN(1, "Missing unregister, handled but fix driver"); +		xdp_rxq_info_unreg(xdp_rxq); +	} + +	if (!dev) { +		WARN(1, "Missing net_device from driver"); +		return -ENODEV; +	} + +	/* State either UNREGISTERED or NEW */ +	xdp_rxq_info_init(xdp_rxq); +	xdp_rxq->dev = dev; +	xdp_rxq->queue_index = queue_index; + +	xdp_rxq->reg_state = REG_STATE_REGISTERED; +	return 0; +} +EXPORT_SYMBOL_GPL(xdp_rxq_info_reg); + +void xdp_rxq_info_unused(struct xdp_rxq_info *xdp_rxq) +{ +	xdp_rxq->reg_state = REG_STATE_UNUSED; +} +EXPORT_SYMBOL_GPL(xdp_rxq_info_unused); + +bool xdp_rxq_info_is_reg(struct xdp_rxq_info *xdp_rxq) +{ +	return (xdp_rxq->reg_state == REG_STATE_REGISTERED); +} +EXPORT_SYMBOL_GPL(xdp_rxq_info_is_reg);  |