Skip to content

Commit 8eeed83

Browse files
emuslndavem330
authored andcommitted
ionic: Add XDP_TX support
The XDP_TX packets get fed back into the Rx queue's partnered Tx queue as an xdp_frame. Co-developed-by: Brett Creeley <[email protected]> Signed-off-by: Brett Creeley <[email protected]> Signed-off-by: Shannon Nelson <[email protected]> Reviewed-by: Jacob Keller <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f81da39 commit 8eeed83

File tree

5 files changed

+150
-3
lines changed

5 files changed

+150
-3
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ struct ionic_desc_info {
228228
struct ionic_buf_info bufs[MAX_SKB_FRAGS + 1];
229229
ionic_desc_cb cb;
230230
void *cb_arg;
231+
struct xdp_frame *xdpf;
232+
enum xdp_action act;
231233
};
232234

233235
#define IONIC_QUEUE_NAME_MAX_SZ 16
@@ -263,6 +265,7 @@ struct ionic_queue {
263265
struct ionic_rxq_sg_desc *rxq_sgl;
264266
};
265267
struct xdp_rxq_info *xdp_rxq_info;
268+
struct ionic_queue *partner;
266269
dma_addr_t base_pa;
267270
dma_addr_t cmb_base_pa;
268271
dma_addr_t sg_base_pa;

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,9 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
878878
};
879879
int err;
880880

881+
q->partner = &lif->txqcqs[q->index]->q;
882+
q->partner->partner = q;
883+
881884
if (!lif->xdp_prog)
882885
ctx.cmd.q_init.flags |= cpu_to_le16(IONIC_QINIT_F_SG);
883886

@@ -2926,6 +2929,7 @@ static void ionic_swap_queues(struct ionic_qcq *a, struct ionic_qcq *b)
29262929
swap(a->q.base_pa, b->q.base_pa);
29272930
swap(a->q.info, b->q.info);
29282931
swap(a->q.xdp_rxq_info, b->q.xdp_rxq_info);
2932+
swap(a->q.partner, b->q.partner);
29292933
swap(a->q_base, b->q_base);
29302934
swap(a->q_base_pa, b->q_base_pa);
29312935
swap(a->q_size, b->q_size);

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

Lines changed: 4 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 {
@@ -54,6 +55,7 @@ struct ionic_rx_stats {
5455
u64 xdp_drop;
5556
u64 xdp_aborted;
5657
u64 xdp_pass;
58+
u64 xdp_tx;
5759
};
5860

5961
#define IONIC_QCQ_F_INITED BIT(0)
@@ -141,6 +143,8 @@ struct ionic_lif_sw_stats {
141143
u64 xdp_drop;
142144
u64 xdp_aborted;
143145
u64 xdp_pass;
146+
u64 xdp_tx;
147+
u64 xdp_frames;
144148
};
145149

146150
enum ionic_lif_state_flags {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ static const struct ionic_stat_desc ionic_lif_stats_desc[] = {
3030
IONIC_LIF_STAT_DESC(xdp_drop),
3131
IONIC_LIF_STAT_DESC(xdp_aborted),
3232
IONIC_LIF_STAT_DESC(xdp_pass),
33+
IONIC_LIF_STAT_DESC(xdp_tx),
34+
IONIC_LIF_STAT_DESC(xdp_frames),
3335
};
3436

3537
static const struct ionic_stat_desc ionic_port_stats_desc[] = {
@@ -138,6 +140,7 @@ static const struct ionic_stat_desc ionic_tx_stats_desc[] = {
138140
IONIC_TX_STAT_DESC(csum_none),
139141
IONIC_TX_STAT_DESC(csum),
140142
IONIC_TX_STAT_DESC(vlan_inserted),
143+
IONIC_TX_STAT_DESC(xdp_frames),
141144
};
142145

143146
static const struct ionic_stat_desc ionic_rx_stats_desc[] = {
@@ -155,6 +158,7 @@ static const struct ionic_stat_desc ionic_rx_stats_desc[] = {
155158
IONIC_RX_STAT_DESC(xdp_drop),
156159
IONIC_RX_STAT_DESC(xdp_aborted),
157160
IONIC_RX_STAT_DESC(xdp_pass),
161+
IONIC_RX_STAT_DESC(xdp_tx),
158162
};
159163

160164
#define IONIC_NUM_LIF_STATS ARRAY_SIZE(ionic_lif_stats_desc)
@@ -177,6 +181,7 @@ static void ionic_add_lif_txq_stats(struct ionic_lif *lif, int q_num,
177181
stats->tx_csum += txstats->csum;
178182
stats->tx_hwstamp_valid += txstats->hwstamp_valid;
179183
stats->tx_hwstamp_invalid += txstats->hwstamp_invalid;
184+
stats->xdp_frames += txstats->xdp_frames;
180185
}
181186

182187
static void ionic_add_lif_rxq_stats(struct ionic_lif *lif, int q_num,
@@ -194,6 +199,7 @@ static void ionic_add_lif_rxq_stats(struct ionic_lif *lif, int q_num,
194199
stats->xdp_drop += rxstats->xdp_drop;
195200
stats->xdp_aborted += rxstats->xdp_aborted;
196201
stats->xdp_pass += rxstats->xdp_pass;
202+
stats->xdp_tx += rxstats->xdp_tx;
197203
}
198204

199205
static void ionic_get_lif_stats(struct ionic_lif *lif,

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

Lines changed: 133 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@
1010
#include "ionic_lif.h"
1111
#include "ionic_txrx.h"
1212

13+
static int ionic_maybe_stop_tx(struct ionic_queue *q, int ndescs);
14+
15+
static dma_addr_t ionic_tx_map_single(struct ionic_queue *q,
16+
void *data, size_t len);
17+
18+
static void ionic_tx_clean(struct ionic_queue *q,
19+
struct ionic_desc_info *desc_info,
20+
struct ionic_cq_info *cq_info,
21+
void *cb_arg);
22+
1323
static inline void ionic_txq_post(struct ionic_queue *q, bool ring_dbell,
1424
ionic_desc_cb cb_func, void *cb_arg)
1525
{
@@ -297,6 +307,75 @@ static struct sk_buff *ionic_rx_copybreak(struct ionic_queue *q,
297307
return skb;
298308
}
299309

310+
static void ionic_xdp_tx_desc_clean(struct ionic_queue *q,
311+
struct ionic_desc_info *desc_info)
312+
{
313+
unsigned int nbufs = desc_info->nbufs;
314+
struct ionic_buf_info *buf_info;
315+
struct device *dev = q->dev;
316+
317+
if (!nbufs)
318+
return;
319+
320+
buf_info = desc_info->bufs;
321+
dma_unmap_single(dev, buf_info->dma_addr,
322+
buf_info->len, DMA_TO_DEVICE);
323+
__free_pages(buf_info->page, 0);
324+
buf_info->page = NULL;
325+
326+
desc_info->nbufs = 0;
327+
desc_info->xdpf = NULL;
328+
desc_info->act = 0;
329+
}
330+
331+
static int ionic_xdp_post_frame(struct net_device *netdev,
332+
struct ionic_queue *q, struct xdp_frame *frame,
333+
enum xdp_action act, struct page *page, int off,
334+
bool ring_doorbell)
335+
{
336+
struct ionic_desc_info *desc_info;
337+
struct ionic_buf_info *buf_info;
338+
struct ionic_tx_stats *stats;
339+
struct ionic_txq_desc *desc;
340+
size_t len = frame->len;
341+
dma_addr_t dma_addr;
342+
u64 cmd;
343+
344+
desc_info = &q->info[q->head_idx];
345+
desc = desc_info->txq_desc;
346+
buf_info = desc_info->bufs;
347+
stats = q_to_tx_stats(q);
348+
349+
dma_addr = ionic_tx_map_single(q, frame->data, len);
350+
if (dma_mapping_error(q->dev, dma_addr)) {
351+
stats->dma_map_err++;
352+
return -EIO;
353+
}
354+
buf_info->dma_addr = dma_addr;
355+
buf_info->len = len;
356+
buf_info->page = page;
357+
buf_info->page_offset = off;
358+
359+
desc_info->nbufs = 1;
360+
desc_info->xdpf = frame;
361+
desc_info->act = act;
362+
363+
cmd = encode_txq_desc_cmd(IONIC_TXQ_DESC_OPCODE_CSUM_NONE,
364+
0, 0, buf_info->dma_addr);
365+
desc->cmd = cpu_to_le64(cmd);
366+
desc->len = cpu_to_le16(len);
367+
desc->csum_start = 0;
368+
desc->csum_offset = 0;
369+
370+
stats->xdp_frames++;
371+
stats->pkts++;
372+
stats->bytes += len;
373+
374+
ionic_txq_post(q, ring_doorbell, ionic_tx_clean, NULL);
375+
376+
return 0;
377+
}
378+
300379
static bool ionic_run_xdp(struct ionic_rx_stats *stats,
301380
struct net_device *netdev,
302381
struct bpf_prog *xdp_prog,
@@ -306,6 +385,10 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
306385
{
307386
u32 xdp_action = XDP_ABORTED;
308387
struct xdp_buff xdp_buf;
388+
struct ionic_queue *txq;
389+
struct netdev_queue *nq;
390+
struct xdp_frame *xdpf;
391+
int err = 0;
309392

310393
xdp_init_buff(&xdp_buf, IONIC_PAGE_SIZE, rxq->xdp_rxq_info);
311394
xdp_prepare_buff(&xdp_buf, ionic_rx_buf_va(buf_info),
@@ -330,14 +413,51 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
330413
break;
331414

332415
case XDP_TX:
416+
xdpf = xdp_convert_buff_to_frame(&xdp_buf);
417+
if (!xdpf)
418+
goto out_xdp_abort;
419+
420+
txq = rxq->partner;
421+
nq = netdev_get_tx_queue(netdev, txq->index);
422+
__netif_tx_lock(nq, smp_processor_id());
423+
txq_trans_cond_update(nq);
424+
425+
if (netif_tx_queue_stopped(nq) ||
426+
unlikely(ionic_maybe_stop_tx(txq, 1))) {
427+
__netif_tx_unlock(nq);
428+
goto out_xdp_abort;
429+
}
430+
431+
dma_unmap_page(rxq->dev, buf_info->dma_addr,
432+
IONIC_PAGE_SIZE, DMA_FROM_DEVICE);
433+
434+
err = ionic_xdp_post_frame(netdev, txq, xdpf, XDP_TX,
435+
buf_info->page,
436+
buf_info->page_offset,
437+
true);
438+
__netif_tx_unlock(nq);
439+
if (err) {
440+
netdev_dbg(netdev, "tx ionic_xdp_post_frame err %d\n", err);
441+
goto out_xdp_abort;
442+
}
443+
stats->xdp_tx++;
444+
445+
/* the Tx completion will free the buffers */
446+
break;
447+
333448
case XDP_REDIRECT:
334449
case XDP_ABORTED:
335450
default:
336-
trace_xdp_exception(netdev, xdp_prog, xdp_action);
337-
ionic_rx_page_free(rxq, buf_info);
338-
stats->xdp_aborted++;
451+
goto out_xdp_abort;
339452
}
340453

454+
return true;
455+
456+
out_xdp_abort:
457+
trace_xdp_exception(netdev, xdp_prog, xdp_action);
458+
ionic_rx_page_free(rxq, buf_info);
459+
stats->xdp_aborted++;
460+
341461
return true;
342462
}
343463

@@ -893,6 +1013,16 @@ static void ionic_tx_clean(struct ionic_queue *q,
8931013
struct sk_buff *skb = cb_arg;
8941014
u16 qi;
8951015

1016+
if (desc_info->xdpf) {
1017+
ionic_xdp_tx_desc_clean(q->partner, desc_info);
1018+
stats->clean++;
1019+
1020+
if (unlikely(__netif_subqueue_stopped(q->lif->netdev, q->index)))
1021+
netif_wake_subqueue(q->lif->netdev, q->index);
1022+
1023+
return;
1024+
}
1025+
8961026
ionic_tx_desc_unmap_bufs(q, desc_info);
8971027

8981028
if (!skb)

0 commit comments

Comments
 (0)