Skip to content

Commit 3c0bf13

Browse files
brettcreeleykuba-moo
authored andcommitted
ionic: Allow XDP program to be hot swapped
Using examples of other driver(s), add the ability to hot-swap an XDP program without having to reconfigure the queues. To prevent the q->xdp_prog to be read/written more than once use READ_ONCE() and WRITE_ONCE() on the q->xdp_prog. The q->xdp_prog was being checked in multiple different for loops in the hot path. The change to allow xdp_prog hot swapping created the possibility for many READ_ONCE(q->xdp_prog) calls during a single napi callback. Refactor the Rx napi handling to allow a previous READ_ONCE(q->xdp_prog) (or NULL for hwstamp_rxq) to be passed into the relevant functions. Also, move other Rx related hotpath handling into the newly created ionic_rx_cq_service() function to reduce the scope of the xdp_prog local variable and put all Rx handling in one function similar to Tx. Signed-off-by: Brett Creeley <[email protected]> Signed-off-by: Shannon Nelson <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent ac8813c commit 3c0bf13

File tree

3 files changed

+52
-22
lines changed

3 files changed

+52
-22
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,7 +1074,7 @@ int ionic_lif_create_hwstamp_rxq(struct ionic_lif *lif)
10741074
goto err_qcq_init;
10751075

10761076
if (test_bit(IONIC_LIF_F_UP, lif->state)) {
1077-
ionic_rx_fill(&rxq->q);
1077+
ionic_rx_fill(&rxq->q, NULL);
10781078
err = ionic_qcq_enable(rxq);
10791079
if (err)
10801080
goto err_qcq_enable;
@@ -2190,7 +2190,8 @@ static int ionic_txrx_enable(struct ionic_lif *lif)
21902190
goto err_out;
21912191
}
21922192

2193-
ionic_rx_fill(&lif->rxqcqs[i]->q);
2193+
ionic_rx_fill(&lif->rxqcqs[i]->q,
2194+
READ_ONCE(lif->rxqcqs[i]->q.xdp_prog));
21942195
err = ionic_qcq_enable(lif->rxqcqs[i]);
21952196
if (err)
21962197
goto err_out;
@@ -2203,7 +2204,7 @@ static int ionic_txrx_enable(struct ionic_lif *lif)
22032204
}
22042205

22052206
if (lif->hwstamp_rxq) {
2206-
ionic_rx_fill(&lif->hwstamp_rxq->q);
2207+
ionic_rx_fill(&lif->hwstamp_rxq->q, NULL);
22072208
err = ionic_qcq_enable(lif->hwstamp_rxq);
22082209
if (err)
22092210
goto err_out_hwstamp_rx;
@@ -2746,7 +2747,7 @@ static void ionic_xdp_rxqs_prog_update(struct ionic_lif *lif)
27462747
for (i = 0; i < lif->ionic->nrxqs_per_lif && lif->rxqcqs[i]; i++) {
27472748
struct ionic_queue *q = &lif->rxqcqs[i]->q;
27482749

2749-
q->xdp_prog = xdp_prog;
2750+
WRITE_ONCE(q->xdp_prog, xdp_prog);
27502751
}
27512752
}
27522753

@@ -2777,6 +2778,9 @@ static int ionic_xdp_config(struct net_device *netdev, struct netdev_bpf *bpf)
27772778

27782779
if (!netif_running(netdev)) {
27792780
old_prog = xchg(&lif->xdp_prog, bpf->prog);
2781+
} else if (lif->xdp_prog && bpf->prog) {
2782+
old_prog = xchg(&lif->xdp_prog, bpf->prog);
2783+
ionic_xdp_rxqs_prog_update(lif);
27802784
} else {
27812785
struct ionic_queue_params qparams;
27822786

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

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,8 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
602602

603603
static void ionic_rx_clean(struct ionic_queue *q,
604604
struct ionic_rx_desc_info *desc_info,
605-
struct ionic_rxq_comp *comp)
605+
struct ionic_rxq_comp *comp,
606+
struct bpf_prog *xdp_prog)
606607
{
607608
struct net_device *netdev = q->lif->netdev;
608609
struct ionic_qcq *qcq = q_to_qcq(q);
@@ -631,8 +632,8 @@ static void ionic_rx_clean(struct ionic_queue *q,
631632
stats->pkts++;
632633
stats->bytes += len;
633634

634-
if (q->xdp_prog) {
635-
if (ionic_run_xdp(stats, netdev, q->xdp_prog, q, desc_info->bufs, len))
635+
if (xdp_prog) {
636+
if (ionic_run_xdp(stats, netdev, xdp_prog, q, desc_info->bufs, len))
636637
return;
637638
synced = true;
638639
headroom = XDP_PACKET_HEADROOM;
@@ -718,7 +719,7 @@ static void ionic_rx_clean(struct ionic_queue *q,
718719
napi_gro_frags(&qcq->napi);
719720
}
720721

721-
bool ionic_rx_service(struct ionic_cq *cq)
722+
static bool __ionic_rx_service(struct ionic_cq *cq, struct bpf_prog *xdp_prog)
722723
{
723724
struct ionic_rx_desc_info *desc_info;
724725
struct ionic_queue *q = cq->bound_q;
@@ -740,11 +741,16 @@ bool ionic_rx_service(struct ionic_cq *cq)
740741
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
741742

742743
/* clean the related q entry, only one per qc completion */
743-
ionic_rx_clean(q, desc_info, comp);
744+
ionic_rx_clean(q, desc_info, comp, xdp_prog);
744745

745746
return true;
746747
}
747748

749+
bool ionic_rx_service(struct ionic_cq *cq)
750+
{
751+
return __ionic_rx_service(cq, NULL);
752+
}
753+
748754
static inline void ionic_write_cmb_desc(struct ionic_queue *q,
749755
void *desc)
750756
{
@@ -755,7 +761,7 @@ static inline void ionic_write_cmb_desc(struct ionic_queue *q,
755761
memcpy_toio(&q->cmb_txq[q->head_idx], desc, sizeof(q->cmb_txq[0]));
756762
}
757763

758-
void ionic_rx_fill(struct ionic_queue *q)
764+
void ionic_rx_fill(struct ionic_queue *q, struct bpf_prog *xdp_prog)
759765
{
760766
struct net_device *netdev = q->lif->netdev;
761767
struct ionic_rx_desc_info *desc_info;
@@ -783,7 +789,7 @@ void ionic_rx_fill(struct ionic_queue *q)
783789

784790
len = netdev->mtu + VLAN_ETH_HLEN;
785791

786-
if (q->xdp_prog) {
792+
if (xdp_prog) {
787793
/* Always alloc the full size buffer, but only need
788794
* the actual frag_len in the descriptor
789795
* XDP uses space in the first buffer, so account for
@@ -964,6 +970,32 @@ static void ionic_xdp_do_flush(struct ionic_cq *cq)
964970
}
965971
}
966972

973+
static unsigned int ionic_rx_cq_service(struct ionic_cq *cq,
974+
unsigned int work_to_do)
975+
{
976+
struct ionic_queue *q = cq->bound_q;
977+
unsigned int work_done = 0;
978+
struct bpf_prog *xdp_prog;
979+
980+
if (work_to_do == 0)
981+
return 0;
982+
983+
xdp_prog = READ_ONCE(q->xdp_prog);
984+
while (__ionic_rx_service(cq, xdp_prog)) {
985+
if (cq->tail_idx == cq->num_descs - 1)
986+
cq->done_color = !cq->done_color;
987+
988+
cq->tail_idx = (cq->tail_idx + 1) & (cq->num_descs - 1);
989+
990+
if (++work_done >= work_to_do)
991+
break;
992+
}
993+
ionic_rx_fill(q, xdp_prog);
994+
ionic_xdp_do_flush(cq);
995+
996+
return work_done;
997+
}
998+
967999
int ionic_rx_napi(struct napi_struct *napi, int budget)
9681000
{
9691001
struct ionic_qcq *qcq = napi_to_qcq(napi);
@@ -974,12 +1006,8 @@ int ionic_rx_napi(struct napi_struct *napi, int budget)
9741006
if (unlikely(!budget))
9751007
return budget;
9761008

977-
work_done = ionic_cq_service(cq, budget,
978-
ionic_rx_service, NULL, NULL);
1009+
work_done = ionic_rx_cq_service(cq, budget);
9791010

980-
ionic_rx_fill(cq->bound_q);
981-
982-
ionic_xdp_do_flush(cq);
9831011
if (work_done < budget && napi_complete_done(napi, work_done)) {
9841012
ionic_dim_update(qcq, IONIC_LIF_F_RX_DIM_INTR);
9851013
flags |= IONIC_INTR_CRED_UNMASK;
@@ -1020,12 +1048,8 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget)
10201048
if (unlikely(!budget))
10211049
return budget;
10221050

1023-
rx_work_done = ionic_cq_service(rxcq, budget,
1024-
ionic_rx_service, NULL, NULL);
1025-
1026-
ionic_rx_fill(rxcq->bound_q);
1051+
rx_work_done = ionic_rx_cq_service(rxcq, budget);
10271052

1028-
ionic_xdp_do_flush(rxcq);
10291053
if (rx_work_done < budget && napi_complete_done(napi, rx_work_done)) {
10301054
ionic_dim_update(rxqcq, 0);
10311055
flags |= IONIC_INTR_CRED_UNMASK;

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
#ifndef _IONIC_TXRX_H_
55
#define _IONIC_TXRX_H_
66

7+
struct bpf_prog;
8+
79
void ionic_tx_flush(struct ionic_cq *cq);
810

9-
void ionic_rx_fill(struct ionic_queue *q);
11+
void ionic_rx_fill(struct ionic_queue *q, struct bpf_prog *xdp_prog);
1012
void ionic_rx_empty(struct ionic_queue *q);
1113
void ionic_tx_empty(struct ionic_queue *q);
1214
int ionic_rx_napi(struct napi_struct *napi, int budget);

0 commit comments

Comments
 (0)