Skip to content

Commit d70a2a4

Browse files
committed
Merge branch 'ionic-xdp-support'
Shannon Nelson says: ==================== ionic: add XDP support This patchset is new support in ionic for XDP processing, including basic XDP on Rx packets, TX and REDIRECT, and frags for jumbo frames. Since ionic has not yet been converted to use the page_pool APIs, this uses the simple MEM_TYPE_PAGE_ORDER0 buffering. There are plans to convert the driver in the near future. v4: - removed "inline" from short utility functions - changed to use "goto err_out" in ionic_xdp_register_rxq_info() - added "continue" to reduce nesting in ionic_xdp_queues_config() - used xdp_prog in ionic_rx_clean() to flag whether or not to sync the rx buffer after calling ionix_xdp_run() - swapped order of XDP_TX and XDP_REDIRECT cases in ionic_xdp_run() to make patch 6 a little cleaner v3: https://lore.kernel.org/netdev/[email protected]/ - removed budget==0 patch, sent it separately to net v2: https://lore.kernel.org/netdev/[email protected]/ - added calls to txq_trans_cond_update() - added a new patch to catch NAPI budget==0 v1: https://lore.kernel.org/netdev/[email protected]/ RFC: https://lore.kernel.org/netdev/[email protected]/ ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 2210c54 + 5377805 commit d70a2a4

File tree

7 files changed

+663
-38
lines changed

7 files changed

+663
-38
lines changed

drivers/net/ethernet/pensando/ionic/ionic_dev.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/mutex.h>
99
#include <linux/workqueue.h>
1010
#include <linux/skbuff.h>
11+
#include <linux/bpf_trace.h>
1112

1213
#include "ionic_if.h"
1314
#include "ionic_regs.h"
@@ -195,6 +196,11 @@ typedef void (*ionic_desc_cb)(struct ionic_queue *q,
195196
#define IONIC_PAGE_GFP_MASK (GFP_ATOMIC | __GFP_NOWARN |\
196197
__GFP_COMP | __GFP_MEMALLOC)
197198

199+
#define IONIC_XDP_MAX_LINEAR_MTU (IONIC_PAGE_SIZE - \
200+
(VLAN_ETH_HLEN + \
201+
XDP_PACKET_HEADROOM + \
202+
SKB_DATA_ALIGN(sizeof(struct skb_shared_info))))
203+
198204
struct ionic_buf_info {
199205
struct page *page;
200206
dma_addr_t dma_addr;
@@ -222,6 +228,8 @@ struct ionic_desc_info {
222228
struct ionic_buf_info bufs[MAX_SKB_FRAGS + 1];
223229
ionic_desc_cb cb;
224230
void *cb_arg;
231+
struct xdp_frame *xdpf;
232+
enum xdp_action act;
225233
};
226234

227235
#define IONIC_QUEUE_NAME_MAX_SZ 16
@@ -256,6 +264,9 @@ struct ionic_queue {
256264
struct ionic_txq_sg_desc *txq_sgl;
257265
struct ionic_rxq_sg_desc *rxq_sgl;
258266
};
267+
struct xdp_rxq_info *xdp_rxq_info;
268+
struct ionic_queue *partner;
269+
bool xdp_flush;
259270
dma_addr_t base_pa;
260271
dma_addr_t cmb_base_pa;
261272
dma_addr_t sg_base_pa;

drivers/net/ethernet/pensando/ionic/ionic_ethtool.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,11 @@ static int ionic_set_channels(struct net_device *netdev,
721721

722722
ionic_init_queue_params(lif, &qparam);
723723

724+
if ((ch->rx_count || ch->tx_count) && lif->xdp_prog) {
725+
netdev_info(lif->netdev, "Split Tx/Rx interrupts not available when using XDP\n");
726+
return -EOPNOTSUPP;
727+
}
728+
724729
if (ch->rx_count != ch->tx_count) {
725730
netdev_info(netdev, "The rx and tx count must be equal\n");
726731
return -EINVAL;

drivers/net/ethernet/pensando/ionic/ionic_lif.c

Lines changed: 190 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ static int ionic_start_queues(struct ionic_lif *lif);
4646
static void ionic_stop_queues(struct ionic_lif *lif);
4747
static void ionic_lif_queue_identify(struct ionic_lif *lif);
4848

49+
static int ionic_xdp_queues_config(struct ionic_lif *lif);
50+
static void ionic_xdp_unregister_rxq_info(struct ionic_queue *q);
51+
4952
static void ionic_dim_work(struct work_struct *work)
5053
{
5154
struct dim *dim = container_of(work, struct dim, work);
@@ -422,6 +425,7 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
422425
qcq->sg_base_pa = 0;
423426
}
424427

428+
ionic_xdp_unregister_rxq_info(&qcq->q);
425429
ionic_qcq_intr_free(lif, qcq);
426430

427431
vfree(qcq->cq.info);
@@ -862,8 +866,7 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
862866
.type = q->type,
863867
.ver = lif->qtype_info[q->type].version,
864868
.index = cpu_to_le32(q->index),
865-
.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
866-
IONIC_QINIT_F_SG),
869+
.flags = cpu_to_le16(IONIC_QINIT_F_IRQ),
867870
.intr_index = cpu_to_le16(cq->bound_intr->index),
868871
.pid = cpu_to_le16(q->pid),
869872
.ring_size = ilog2(q->num_descs),
@@ -875,6 +878,13 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
875878
};
876879
int err;
877880

881+
q->partner = &lif->txqcqs[q->index]->q;
882+
q->partner->partner = q;
883+
884+
if (!lif->xdp_prog ||
885+
(lif->xdp_prog->aux && lif->xdp_prog->aux->xdp_has_frags))
886+
ctx.cmd.q_init.flags |= cpu_to_le16(IONIC_QINIT_F_SG);
887+
878888
if (qcq->flags & IONIC_QCQ_F_CMB_RINGS) {
879889
ctx.cmd.q_init.flags |= cpu_to_le16(IONIC_QINIT_F_CMB);
880890
ctx.cmd.q_init.ring_base = cpu_to_le64(qcq->cmb_q_base_pa);
@@ -1640,6 +1650,12 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
16401650
netdev->priv_flags |= IFF_UNICAST_FLT |
16411651
IFF_LIVE_ADDR_CHANGE;
16421652

1653+
netdev->xdp_features = NETDEV_XDP_ACT_BASIC |
1654+
NETDEV_XDP_ACT_REDIRECT |
1655+
NETDEV_XDP_ACT_RX_SG |
1656+
NETDEV_XDP_ACT_NDO_XMIT |
1657+
NETDEV_XDP_ACT_NDO_XMIT_SG;
1658+
16431659
return 0;
16441660
}
16451661

@@ -1777,6 +1793,21 @@ static int ionic_start_queues_reconfig(struct ionic_lif *lif)
17771793
return err;
17781794
}
17791795

1796+
static bool ionic_xdp_is_valid_mtu(struct ionic_lif *lif, u32 mtu,
1797+
struct bpf_prog *xdp_prog)
1798+
{
1799+
if (!xdp_prog)
1800+
return true;
1801+
1802+
if (mtu <= IONIC_XDP_MAX_LINEAR_MTU)
1803+
return true;
1804+
1805+
if (xdp_prog->aux && xdp_prog->aux->xdp_has_frags)
1806+
return true;
1807+
1808+
return false;
1809+
}
1810+
17801811
static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
17811812
{
17821813
struct ionic_lif *lif = netdev_priv(netdev);
@@ -1789,8 +1820,13 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
17891820
.mtu = cpu_to_le32(new_mtu),
17901821
},
17911822
};
1823+
struct bpf_prog *xdp_prog;
17921824
int err;
17931825

1826+
xdp_prog = READ_ONCE(lif->xdp_prog);
1827+
if (!ionic_xdp_is_valid_mtu(lif, new_mtu, xdp_prog))
1828+
return -EINVAL;
1829+
17941830
err = ionic_adminq_post_wait(lif, &ctx);
17951831
if (err)
17961832
return err;
@@ -2166,6 +2202,10 @@ static int ionic_txrx_enable(struct ionic_lif *lif)
21662202
int derr = 0;
21672203
int i, err;
21682204

2205+
err = ionic_xdp_queues_config(lif);
2206+
if (err)
2207+
return err;
2208+
21692209
for (i = 0; i < lif->nxqs; i++) {
21702210
if (!(lif->rxqcqs[i] && lif->txqcqs[i])) {
21712211
dev_err(lif->ionic->dev, "%s: bad qcq %d\n", __func__, i);
@@ -2211,6 +2251,8 @@ static int ionic_txrx_enable(struct ionic_lif *lif)
22112251
derr = ionic_qcq_disable(lif, lif->rxqcqs[i], derr);
22122252
}
22132253

2254+
ionic_xdp_queues_config(lif);
2255+
22142256
return err;
22152257
}
22162258

@@ -2668,11 +2710,151 @@ static void ionic_vf_attr_replay(struct ionic_lif *lif)
26682710
ionic_vf_start(ionic);
26692711
}
26702712

2713+
static void ionic_xdp_unregister_rxq_info(struct ionic_queue *q)
2714+
{
2715+
struct xdp_rxq_info *xi;
2716+
2717+
if (!q->xdp_rxq_info)
2718+
return;
2719+
2720+
xi = q->xdp_rxq_info;
2721+
q->xdp_rxq_info = NULL;
2722+
2723+
xdp_rxq_info_unreg(xi);
2724+
kfree(xi);
2725+
}
2726+
2727+
static int ionic_xdp_register_rxq_info(struct ionic_queue *q, unsigned int napi_id)
2728+
{
2729+
struct xdp_rxq_info *rxq_info;
2730+
int err;
2731+
2732+
rxq_info = kzalloc(sizeof(*rxq_info), GFP_KERNEL);
2733+
if (!rxq_info)
2734+
return -ENOMEM;
2735+
2736+
err = xdp_rxq_info_reg(rxq_info, q->lif->netdev, q->index, napi_id);
2737+
if (err) {
2738+
dev_err(q->dev, "Queue %d xdp_rxq_info_reg failed, err %d\n",
2739+
q->index, err);
2740+
goto err_out;
2741+
}
2742+
2743+
err = xdp_rxq_info_reg_mem_model(rxq_info, MEM_TYPE_PAGE_ORDER0, NULL);
2744+
if (err) {
2745+
dev_err(q->dev, "Queue %d xdp_rxq_info_reg_mem_model failed, err %d\n",
2746+
q->index, err);
2747+
xdp_rxq_info_unreg(rxq_info);
2748+
goto err_out;
2749+
}
2750+
2751+
q->xdp_rxq_info = rxq_info;
2752+
2753+
return 0;
2754+
2755+
err_out:
2756+
kfree(rxq_info);
2757+
return err;
2758+
}
2759+
2760+
static int ionic_xdp_queues_config(struct ionic_lif *lif)
2761+
{
2762+
unsigned int i;
2763+
int err;
2764+
2765+
if (!lif->rxqcqs)
2766+
return 0;
2767+
2768+
/* There's no need to rework memory if not going to/from NULL program.
2769+
* If there is no lif->xdp_prog, there should also be no q.xdp_rxq_info
2770+
* This way we don't need to keep an *xdp_prog in every queue struct.
2771+
*/
2772+
if (!lif->xdp_prog == !lif->rxqcqs[0]->q.xdp_rxq_info)
2773+
return 0;
2774+
2775+
for (i = 0; i < lif->ionic->nrxqs_per_lif && lif->rxqcqs[i]; i++) {
2776+
struct ionic_queue *q = &lif->rxqcqs[i]->q;
2777+
2778+
if (q->xdp_rxq_info) {
2779+
ionic_xdp_unregister_rxq_info(q);
2780+
continue;
2781+
}
2782+
2783+
err = ionic_xdp_register_rxq_info(q, lif->rxqcqs[i]->napi.napi_id);
2784+
if (err) {
2785+
dev_err(lif->ionic->dev, "failed to register RX queue %d info for XDP, err %d\n",
2786+
i, err);
2787+
goto err_out;
2788+
}
2789+
}
2790+
2791+
return 0;
2792+
2793+
err_out:
2794+
for (i = 0; i < lif->ionic->nrxqs_per_lif && lif->rxqcqs[i]; i++)
2795+
ionic_xdp_unregister_rxq_info(&lif->rxqcqs[i]->q);
2796+
2797+
return err;
2798+
}
2799+
2800+
static int ionic_xdp_config(struct net_device *netdev, struct netdev_bpf *bpf)
2801+
{
2802+
struct ionic_lif *lif = netdev_priv(netdev);
2803+
struct bpf_prog *old_prog;
2804+
u32 maxfs;
2805+
2806+
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) {
2807+
#define XDP_ERR_SPLIT "XDP not available with split Tx/Rx interrupts"
2808+
NL_SET_ERR_MSG_MOD(bpf->extack, XDP_ERR_SPLIT);
2809+
netdev_info(lif->netdev, XDP_ERR_SPLIT);
2810+
return -EOPNOTSUPP;
2811+
}
2812+
2813+
if (!ionic_xdp_is_valid_mtu(lif, netdev->mtu, bpf->prog)) {
2814+
#define XDP_ERR_MTU "MTU is too large for XDP without frags support"
2815+
NL_SET_ERR_MSG_MOD(bpf->extack, XDP_ERR_MTU);
2816+
netdev_info(lif->netdev, XDP_ERR_MTU);
2817+
return -EINVAL;
2818+
}
2819+
2820+
maxfs = __le32_to_cpu(lif->identity->eth.max_frame_size) - VLAN_ETH_HLEN;
2821+
if (bpf->prog && !(bpf->prog->aux && bpf->prog->aux->xdp_has_frags))
2822+
maxfs = min_t(u32, maxfs, IONIC_XDP_MAX_LINEAR_MTU);
2823+
netdev->max_mtu = maxfs;
2824+
2825+
if (!netif_running(netdev)) {
2826+
old_prog = xchg(&lif->xdp_prog, bpf->prog);
2827+
} else {
2828+
mutex_lock(&lif->queue_lock);
2829+
ionic_stop_queues_reconfig(lif);
2830+
old_prog = xchg(&lif->xdp_prog, bpf->prog);
2831+
ionic_start_queues_reconfig(lif);
2832+
mutex_unlock(&lif->queue_lock);
2833+
}
2834+
2835+
if (old_prog)
2836+
bpf_prog_put(old_prog);
2837+
2838+
return 0;
2839+
}
2840+
2841+
static int ionic_xdp(struct net_device *netdev, struct netdev_bpf *bpf)
2842+
{
2843+
switch (bpf->command) {
2844+
case XDP_SETUP_PROG:
2845+
return ionic_xdp_config(netdev, bpf);
2846+
default:
2847+
return -EINVAL;
2848+
}
2849+
}
2850+
26712851
static const struct net_device_ops ionic_netdev_ops = {
26722852
.ndo_open = ionic_open,
26732853
.ndo_stop = ionic_stop,
26742854
.ndo_eth_ioctl = ionic_eth_ioctl,
26752855
.ndo_start_xmit = ionic_start_xmit,
2856+
.ndo_bpf = ionic_xdp,
2857+
.ndo_xdp_xmit = ionic_xdp_xmit,
26762858
.ndo_get_stats64 = ionic_get_stats64,
26772859
.ndo_set_rx_mode = ionic_ndo_set_rx_mode,
26782860
.ndo_set_features = ionic_set_features,
@@ -2755,6 +2937,8 @@ static void ionic_swap_queues(struct ionic_qcq *a, struct ionic_qcq *b)
27552937
swap(a->q.base, b->q.base);
27562938
swap(a->q.base_pa, b->q.base_pa);
27572939
swap(a->q.info, b->q.info);
2940+
swap(a->q.xdp_rxq_info, b->q.xdp_rxq_info);
2941+
swap(a->q.partner, b->q.partner);
27582942
swap(a->q_base, b->q_base);
27592943
swap(a->q_base_pa, b->q_base_pa);
27602944
swap(a->q_size, b->q_size);
@@ -3391,9 +3575,12 @@ static int ionic_lif_adminq_init(struct ionic_lif *lif)
33913575

33923576
napi_enable(&qcq->napi);
33933577

3394-
if (qcq->flags & IONIC_QCQ_F_INTR)
3578+
if (qcq->flags & IONIC_QCQ_F_INTR) {
3579+
irq_set_affinity_hint(qcq->intr.vector,
3580+
&qcq->intr.affinity_mask);
33953581
ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
33963582
IONIC_INTR_MASK_CLEAR);
3583+
}
33973584

33983585
qcq->flags |= IONIC_QCQ_F_INITED;
33993586

drivers/net/ethernet/pensando/ionic/ionic_lif.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct ionic_tx_stats {
3737
u64 dma_map_err;
3838
u64 hwstamp_valid;
3939
u64 hwstamp_invalid;
40+
u64 xdp_frames;
4041
};
4142

4243
struct ionic_rx_stats {
@@ -51,6 +52,11 @@ struct ionic_rx_stats {
5152
u64 alloc_err;
5253
u64 hwstamp_valid;
5354
u64 hwstamp_invalid;
55+
u64 xdp_drop;
56+
u64 xdp_aborted;
57+
u64 xdp_pass;
58+
u64 xdp_tx;
59+
u64 xdp_redirect;
5460
};
5561

5662
#define IONIC_QCQ_F_INITED BIT(0)
@@ -135,6 +141,12 @@ struct ionic_lif_sw_stats {
135141
u64 hw_rx_over_errors;
136142
u64 hw_rx_missed_errors;
137143
u64 hw_tx_aborted_errors;
144+
u64 xdp_drop;
145+
u64 xdp_aborted;
146+
u64 xdp_pass;
147+
u64 xdp_tx;
148+
u64 xdp_redirect;
149+
u64 xdp_frames;
138150
};
139151

140152
enum ionic_lif_state_flags {
@@ -230,6 +242,7 @@ struct ionic_lif {
230242
struct ionic_phc *phc;
231243

232244
struct dentry *dentry;
245+
struct bpf_prog *xdp_prog;
233246
};
234247

235248
struct ionic_phc {

0 commit comments

Comments
 (0)