2018-01-03 18:25:13 +08:00
|
|
|
/* 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);
|
2018-01-03 18:25:34 +08:00
|
|
|
|
|
|
|
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);
|
2018-04-17 22:45:26 +08:00
|
|
|
|
|
|
|
int xdp_rxq_info_reg_mem_model(struct xdp_rxq_info *xdp_rxq,
|
|
|
|
enum xdp_mem_type type, void *allocator)
|
|
|
|
{
|
|
|
|
if (type >= MEM_TYPE_MAX)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
xdp_rxq->mem.type = type;
|
|
|
|
|
|
|
|
if (allocator)
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
/* TODO: Allocate an ID that maps to allocator pointer
|
|
|
|
* See: https://www.kernel.org/doc/html/latest/core-api/idr.html
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(xdp_rxq_info_reg_mem_model);
|