Skip to content

Commit 0d14657

Browse files
TaeheeYoodavem330
authored andcommitted
net: atlantic: Implement xdp control plane
aq_xdp() is a xdp setup callback function for Atlantic driver. When XDP is attached or detached, the device will be restarted because it uses different headroom, tailroom, and page order value. If XDP enabled, it switches default page order value from 0 to 2. Because the default maximum frame size is still 2K and it needs additional area for headroom and tailroom. The total size(headroom + frame size + tailroom) is 2624. So, 1472Bytes will be always wasted for every frame. But when order-2 is used, these pages can be used 6 times with flip strategy. It means only about 106Bytes per frame will be wasted. Also, It supports xdp fragment feature. MTU can be 16K if xdp prog supports xdp fragment. If not, MTU can not exceed 2K - ETH_HLEN - ETH_FCS. And a static key is added and It will be used to call the xdp_clean handler in ->poll(). data plane implementation will be contained the followed patch. Signed-off-by: Taehee Yoo <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8ab38ed commit 0d14657

File tree

10 files changed

+177
-37
lines changed

10 files changed

+177
-37
lines changed

drivers/net/ethernet/aquantia/atlantic/aq_cfg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#define AQ_CFG_RX_HDR_SIZE 256U
4141

4242
#define AQ_CFG_RX_PAGEORDER 0U
43+
#define AQ_CFG_XDP_PAGEORDER 2U
4344

4445
/* LRO */
4546
#define AQ_CFG_IS_LRO_DEF 1U

drivers/net/ethernet/aquantia/atlantic/aq_main.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,22 @@
1414
#include "aq_ptp.h"
1515
#include "aq_filters.h"
1616
#include "aq_hw_utils.h"
17+
#include "aq_vec.h"
1718

1819
#include <linux/netdevice.h>
1920
#include <linux/module.h>
2021
#include <linux/ip.h>
2122
#include <linux/udp.h>
2223
#include <net/pkt_cls.h>
24+
#include <linux/filter.h>
2325

2426
MODULE_LICENSE("GPL v2");
2527
MODULE_AUTHOR(AQ_CFG_DRV_AUTHOR);
2628
MODULE_DESCRIPTION(AQ_CFG_DRV_DESC);
2729

30+
DEFINE_STATIC_KEY_FALSE(aq_xdp_locking_key);
31+
EXPORT_SYMBOL(aq_xdp_locking_key);
32+
2833
static const char aq_ndev_driver_name[] = AQ_CFG_DRV_NAME;
2934

3035
static const struct net_device_ops aq_ndev_ops;
@@ -126,9 +131,19 @@ static netdev_tx_t aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *nd
126131

127132
static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu)
128133
{
134+
int new_frame_size = new_mtu + ETH_HLEN + ETH_FCS_LEN;
129135
struct aq_nic_s *aq_nic = netdev_priv(ndev);
136+
struct bpf_prog *prog;
130137
int err;
131138

139+
prog = READ_ONCE(aq_nic->xdp_prog);
140+
if (prog && !prog->aux->xdp_has_frags &&
141+
new_frame_size > AQ_CFG_RX_FRAME_MAX) {
142+
netdev_err(ndev, "Illegal MTU %d for XDP prog without frags\n",
143+
ndev->mtu);
144+
return -EOPNOTSUPP;
145+
}
146+
132147
err = aq_nic_set_mtu(aq_nic, new_mtu + ETH_HLEN);
133148

134149
if (err < 0)
@@ -204,6 +219,25 @@ static int aq_ndev_set_features(struct net_device *ndev,
204219
return err;
205220
}
206221

222+
static netdev_features_t aq_ndev_fix_features(struct net_device *ndev,
223+
netdev_features_t features)
224+
{
225+
struct aq_nic_s *aq_nic = netdev_priv(ndev);
226+
struct bpf_prog *prog;
227+
228+
if (!(features & NETIF_F_RXCSUM))
229+
features &= ~NETIF_F_LRO;
230+
231+
prog = READ_ONCE(aq_nic->xdp_prog);
232+
if (prog && !prog->aux->xdp_has_frags &&
233+
aq_nic->xdp_prog && features & NETIF_F_LRO) {
234+
netdev_err(ndev, "LRO is not supported with single buffer XDP, disabling\n");
235+
features &= ~NETIF_F_LRO;
236+
}
237+
238+
return features;
239+
}
240+
207241
static int aq_ndev_set_mac_address(struct net_device *ndev, void *addr)
208242
{
209243
struct aq_nic_s *aq_nic = netdev_priv(ndev);
@@ -410,6 +444,56 @@ static int aq_ndo_setup_tc(struct net_device *dev, enum tc_setup_type type,
410444
mqprio->qopt.prio_tc_map);
411445
}
412446

447+
static int aq_xdp_setup(struct net_device *ndev, struct bpf_prog *prog,
448+
struct netlink_ext_ack *extack)
449+
{
450+
bool need_update, running = netif_running(ndev);
451+
struct aq_nic_s *aq_nic = netdev_priv(ndev);
452+
struct bpf_prog *old_prog;
453+
454+
if (prog && !prog->aux->xdp_has_frags) {
455+
if (ndev->mtu > AQ_CFG_RX_FRAME_MAX) {
456+
NL_SET_ERR_MSG_MOD(extack,
457+
"prog does not support XDP frags");
458+
return -EOPNOTSUPP;
459+
}
460+
461+
if (prog && ndev->features & NETIF_F_LRO) {
462+
netdev_err(ndev,
463+
"LRO is not supported with single buffer XDP, disabling\n");
464+
ndev->features &= ~NETIF_F_LRO;
465+
}
466+
}
467+
468+
need_update = !!aq_nic->xdp_prog != !!prog;
469+
if (running && need_update)
470+
aq_ndev_close(ndev);
471+
472+
old_prog = xchg(&aq_nic->xdp_prog, prog);
473+
if (old_prog)
474+
bpf_prog_put(old_prog);
475+
476+
if (!old_prog && prog)
477+
static_branch_inc(&aq_xdp_locking_key);
478+
else if (old_prog && !prog)
479+
static_branch_dec(&aq_xdp_locking_key);
480+
481+
if (running && need_update)
482+
return aq_ndev_open(ndev);
483+
484+
return 0;
485+
}
486+
487+
static int aq_xdp(struct net_device *dev, struct netdev_bpf *xdp)
488+
{
489+
switch (xdp->command) {
490+
case XDP_SETUP_PROG:
491+
return aq_xdp_setup(dev, xdp->prog, xdp->extack);
492+
default:
493+
return -EINVAL;
494+
}
495+
}
496+
413497
static const struct net_device_ops aq_ndev_ops = {
414498
.ndo_open = aq_ndev_open,
415499
.ndo_stop = aq_ndev_close,
@@ -418,10 +502,12 @@ static const struct net_device_ops aq_ndev_ops = {
418502
.ndo_change_mtu = aq_ndev_change_mtu,
419503
.ndo_set_mac_address = aq_ndev_set_mac_address,
420504
.ndo_set_features = aq_ndev_set_features,
505+
.ndo_fix_features = aq_ndev_fix_features,
421506
.ndo_eth_ioctl = aq_ndev_ioctl,
422507
.ndo_vlan_rx_add_vid = aq_ndo_vlan_rx_add_vid,
423508
.ndo_vlan_rx_kill_vid = aq_ndo_vlan_rx_kill_vid,
424509
.ndo_setup_tc = aq_ndo_setup_tc,
510+
.ndo_bpf = aq_xdp,
425511
};
426512

427513
static int __init aq_ndev_init_module(void)

drivers/net/ethernet/aquantia/atlantic/aq_main.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include "aq_common.h"
1313
#include "aq_nic.h"
1414

15+
DECLARE_STATIC_KEY_FALSE(aq_xdp_locking_key);
16+
1517
void aq_ndev_schedule_work(struct work_struct *work);
1618
struct net_device *aq_ndev_alloc(void);
1719

drivers/net/ethernet/aquantia/atlantic/aq_nic.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#define AQ_NIC_H
1212

1313
#include <linux/ethtool.h>
14+
#include <net/xdp.h>
15+
#include <linux/bpf.h>
1416

1517
#include "aq_common.h"
1618
#include "aq_rss.h"
@@ -128,6 +130,7 @@ struct aq_nic_s {
128130
struct aq_vec_s *aq_vec[AQ_CFG_VECS_MAX];
129131
struct aq_ring_s *aq_ring_tx[AQ_HW_QUEUES_MAX];
130132
struct aq_hw_s *aq_hw;
133+
struct bpf_prog *xdp_prog;
131134
struct net_device *ndev;
132135
unsigned int aq_vecs;
133136
unsigned int packet_filter;

drivers/net/ethernet/aquantia/atlantic/aq_ring.c

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@
77

88
/* File aq_ring.c: Definition of functions for Rx/Tx rings. */
99

10-
#include "aq_ring.h"
1110
#include "aq_nic.h"
1211
#include "aq_hw.h"
1312
#include "aq_hw_utils.h"
1413
#include "aq_ptp.h"
14+
#include "aq_vec.h"
15+
#include "aq_main.h"
1516

17+
#include <net/xdp.h>
18+
#include <linux/filter.h>
19+
#include <linux/bpf_trace.h>
1620
#include <linux/netdevice.h>
1721
#include <linux/etherdevice.h>
1822

@@ -27,9 +31,10 @@ static inline void aq_free_rxpage(struct aq_rxpage *rxpage, struct device *dev)
2731
rxpage->page = NULL;
2832
}
2933

30-
static int aq_get_rxpage(struct aq_rxpage *rxpage, unsigned int order,
31-
struct device *dev)
34+
static int aq_alloc_rxpages(struct aq_rxpage *rxpage, struct aq_ring_s *rx_ring)
3235
{
36+
struct device *dev = aq_nic_get_dev(rx_ring->aq_nic);
37+
unsigned int order = rx_ring->page_order;
3338
struct page *page;
3439
int ret = -ENOMEM;
3540
dma_addr_t daddr;
@@ -47,7 +52,7 @@ static int aq_get_rxpage(struct aq_rxpage *rxpage, unsigned int order,
4752
rxpage->page = page;
4853
rxpage->daddr = daddr;
4954
rxpage->order = order;
50-
rxpage->pg_off = 0;
55+
rxpage->pg_off = rx_ring->page_offset;
5156

5257
return 0;
5358

@@ -58,21 +63,26 @@ static int aq_get_rxpage(struct aq_rxpage *rxpage, unsigned int order,
5863
return ret;
5964
}
6065

61-
static int aq_get_rxpages(struct aq_ring_s *self, struct aq_ring_buff_s *rxbuf,
62-
int order)
66+
static int aq_get_rxpages(struct aq_ring_s *self, struct aq_ring_buff_s *rxbuf)
6367
{
68+
unsigned int order = self->page_order;
69+
u16 page_offset = self->page_offset;
70+
u16 frame_max = self->frame_max;
71+
u16 tail_size = self->tail_size;
6472
int ret;
6573

6674
if (rxbuf->rxdata.page) {
6775
/* One means ring is the only user and can reuse */
6876
if (page_ref_count(rxbuf->rxdata.page) > 1) {
6977
/* Try reuse buffer */
70-
rxbuf->rxdata.pg_off += AQ_CFG_RX_FRAME_MAX;
71-
if (rxbuf->rxdata.pg_off + AQ_CFG_RX_FRAME_MAX <=
72-
(PAGE_SIZE << order)) {
78+
rxbuf->rxdata.pg_off += frame_max + page_offset +
79+
tail_size;
80+
if (rxbuf->rxdata.pg_off + frame_max + tail_size <=
81+
(PAGE_SIZE << order)) {
7382
u64_stats_update_begin(&self->stats.rx.syncp);
7483
self->stats.rx.pg_flips++;
7584
u64_stats_update_end(&self->stats.rx.syncp);
85+
7686
} else {
7787
/* Buffer exhausted. We have other users and
7888
* should release this page and realloc
@@ -84,16 +94,15 @@ static int aq_get_rxpages(struct aq_ring_s *self, struct aq_ring_buff_s *rxbuf,
8494
u64_stats_update_end(&self->stats.rx.syncp);
8595
}
8696
} else {
87-
rxbuf->rxdata.pg_off = 0;
97+
rxbuf->rxdata.pg_off = page_offset;
8898
u64_stats_update_begin(&self->stats.rx.syncp);
8999
self->stats.rx.pg_reuses++;
90100
u64_stats_update_end(&self->stats.rx.syncp);
91101
}
92102
}
93103

94104
if (!rxbuf->rxdata.page) {
95-
ret = aq_get_rxpage(&rxbuf->rxdata, order,
96-
aq_nic_get_dev(self->aq_nic));
105+
ret = aq_alloc_rxpages(&rxbuf->rxdata, self);
97106
if (ret) {
98107
u64_stats_update_begin(&self->stats.rx.syncp);
99108
self->stats.rx.alloc_fails++;
@@ -117,6 +126,7 @@ static struct aq_ring_s *aq_ring_alloc(struct aq_ring_s *self,
117126
err = -ENOMEM;
118127
goto err_exit;
119128
}
129+
120130
self->dx_ring = dma_alloc_coherent(aq_nic_get_dev(aq_nic),
121131
self->size * self->dx_size,
122132
&self->dx_ring_pa, GFP_KERNEL);
@@ -172,11 +182,22 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
172182
self->idx = idx;
173183
self->size = aq_nic_cfg->rxds;
174184
self->dx_size = aq_nic_cfg->aq_hw_caps->rxd_size;
175-
self->page_order = fls(AQ_CFG_RX_FRAME_MAX / PAGE_SIZE +
176-
(AQ_CFG_RX_FRAME_MAX % PAGE_SIZE ? 1 : 0)) - 1;
177-
178-
if (aq_nic_cfg->rxpageorder > self->page_order)
179-
self->page_order = aq_nic_cfg->rxpageorder;
185+
self->xdp_prog = aq_nic->xdp_prog;
186+
self->frame_max = AQ_CFG_RX_FRAME_MAX;
187+
188+
/* Only order-2 is allowed if XDP is enabled */
189+
if (READ_ONCE(self->xdp_prog)) {
190+
self->page_offset = AQ_XDP_HEADROOM;
191+
self->page_order = AQ_CFG_XDP_PAGEORDER;
192+
self->tail_size = AQ_XDP_TAILROOM;
193+
} else {
194+
self->page_offset = 0;
195+
self->page_order = fls(self->frame_max / PAGE_SIZE +
196+
(self->frame_max % PAGE_SIZE ? 1 : 0)) - 1;
197+
if (aq_nic_cfg->rxpageorder > self->page_order)
198+
self->page_order = aq_nic_cfg->rxpageorder;
199+
self->tail_size = 0;
200+
}
180201

181202
self = aq_ring_alloc(self, aq_nic);
182203
if (!self) {
@@ -449,7 +470,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
449470
skb_add_rx_frag(skb, 0, buff->rxdata.page,
450471
buff->rxdata.pg_off + hdr_len,
451472
buff->len - hdr_len,
452-
AQ_CFG_RX_FRAME_MAX);
473+
self->frame_max);
453474
page_ref_inc(buff->rxdata.page);
454475
}
455476

@@ -469,7 +490,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
469490
buff_->rxdata.page,
470491
buff_->rxdata.pg_off,
471492
buff_->len,
472-
AQ_CFG_RX_FRAME_MAX);
493+
self->frame_max);
473494
page_ref_inc(buff_->rxdata.page);
474495
buff_->is_cleaned = 1;
475496

@@ -529,7 +550,6 @@ void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic)
529550

530551
int aq_ring_rx_fill(struct aq_ring_s *self)
531552
{
532-
unsigned int page_order = self->page_order;
533553
struct aq_ring_buff_s *buff = NULL;
534554
int err = 0;
535555
int i = 0;
@@ -543,9 +563,9 @@ int aq_ring_rx_fill(struct aq_ring_s *self)
543563
buff = &self->buff_ring[self->sw_tail];
544564

545565
buff->flags = 0U;
546-
buff->len = AQ_CFG_RX_FRAME_MAX;
566+
buff->len = self->frame_max;
547567

548-
err = aq_get_rxpages(self, buff, page_order);
568+
err = aq_get_rxpages(self, buff);
549569
if (err)
550570
goto err_exit;
551571

drivers/net/ethernet/aquantia/atlantic/aq_ring.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#define AQ_RING_H
1212

1313
#include "aq_common.h"
14+
#include "aq_vec.h"
15+
16+
#define AQ_XDP_HEADROOM ALIGN(max(NET_SKB_PAD, XDP_PACKET_HEADROOM), 8)
17+
#define AQ_XDP_TAILROOM SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
1418

1519
struct page;
1620
struct aq_nic_cfg_s;
@@ -51,6 +55,7 @@ struct __packed aq_ring_buff_s {
5155
struct {
5256
dma_addr_t pa_eop;
5357
struct sk_buff *skb;
58+
struct xdp_frame *xdpf;
5459
};
5560
/* TxC */
5661
struct {
@@ -132,10 +137,15 @@ struct aq_ring_s {
132137
unsigned int size; /* descriptors number */
133138
unsigned int dx_size; /* TX or RX descriptor size, */
134139
/* stored here for fater math */
135-
unsigned int page_order;
140+
u16 page_order;
141+
u16 page_offset;
142+
u16 frame_max;
143+
u16 tail_size;
136144
union aq_ring_stats_s stats;
137145
dma_addr_t dx_ring_pa;
146+
struct bpf_prog *xdp_prog;
138147
enum atl_ring_type ring_type;
148+
struct xdp_rxq_info xdp_rxq;
139149
};
140150

141151
struct aq_ring_param_s {
@@ -175,6 +185,7 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
175185
struct aq_nic_s *aq_nic,
176186
unsigned int idx,
177187
struct aq_nic_cfg_s *aq_nic_cfg);
188+
178189
int aq_ring_init(struct aq_ring_s *self, const enum atl_ring_type ring_type);
179190
void aq_ring_rx_deinit(struct aq_ring_s *self);
180191
void aq_ring_free(struct aq_ring_s *self);

0 commit comments

Comments
 (0)