Skip to content

Commit 24b8c19

Browse files
committed
Merge branch '200GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue
Tony Nguyen says: ==================== idpf: XDP chapter II: convert Tx completion to libeth Alexander Lobakin says: XDP for idpf is currently 5 chapters: * convert Rx to libeth; * convert Tx completion to libeth (this); * generic XDP and XSk code changes; * actual XDP for idpf via libeth_xdp; * XSk for idpf (^). Part II does the following: * adds generic libeth Tx completion routines; * converts idpf to use generic libeth Tx comp routines; * fixes Tx queue timeouts and robustifies Tx completion in general; * fixes Tx event/descriptor flushes (writebacks). Most idpf patches again remove more lines than adds. Generic Tx completion helpers and structs are needed as libeth_xdp (Ch. III) makes use of them. WB_ON_ITR is needed since XDPSQs don't want to work without it at all. Tx queue timeouts fixes are needed since without them, it's way easier to catch a Tx timeout event when WB_ON_ITR is enabled. * '200GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue: idpf: enable WB_ON_ITR idpf: fix netdev Tx queue stop/wake idpf: refactor Tx completion routines netdevice: add netdev_tx_reset_subqueue() shorthand idpf: convert to libeth Tx buffer completion libeth: add Tx buffer completion helpers ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents b2c8a50 + 9c4a27d commit 24b8c19

File tree

8 files changed

+442
-326
lines changed

8 files changed

+442
-326
lines changed

drivers/net/ethernet/intel/idpf/idpf_dev.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,10 @@ static int idpf_intr_reg_init(struct idpf_vport *vport)
9797
intr->dyn_ctl = idpf_get_reg_addr(adapter,
9898
reg_vals[vec_id].dyn_ctl_reg);
9999
intr->dyn_ctl_intena_m = PF_GLINT_DYN_CTL_INTENA_M;
100+
intr->dyn_ctl_intena_msk_m = PF_GLINT_DYN_CTL_INTENA_MSK_M;
100101
intr->dyn_ctl_itridx_s = PF_GLINT_DYN_CTL_ITR_INDX_S;
101102
intr->dyn_ctl_intrvl_s = PF_GLINT_DYN_CTL_INTERVAL_S;
103+
intr->dyn_ctl_wb_on_itr_m = PF_GLINT_DYN_CTL_WB_ON_ITR_M;
102104

103105
spacing = IDPF_ITR_IDX_SPACING(reg_vals[vec_id].itrn_index_spacing,
104106
IDPF_PF_ITR_IDX_SPACING);

drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c

Lines changed: 50 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/* Copyright (C) 2023 Intel Corporation */
33

44
#include <net/libeth/rx.h>
5+
#include <net/libeth/tx.h>
56

67
#include "idpf.h"
78

@@ -224,6 +225,7 @@ static void idpf_tx_singleq_map(struct idpf_tx_queue *tx_q,
224225
/* record length, and DMA address */
225226
dma_unmap_len_set(tx_buf, len, size);
226227
dma_unmap_addr_set(tx_buf, dma, dma);
228+
tx_buf->type = LIBETH_SQE_FRAG;
227229

228230
/* align size to end of page */
229231
max_data += -dma & (IDPF_TX_MAX_READ_REQ_SIZE - 1);
@@ -237,14 +239,17 @@ static void idpf_tx_singleq_map(struct idpf_tx_queue *tx_q,
237239
offsets,
238240
max_data,
239241
td_tag);
240-
tx_desc++;
241-
i++;
242-
243-
if (i == tx_q->desc_count) {
242+
if (unlikely(++i == tx_q->desc_count)) {
243+
tx_buf = &tx_q->tx_buf[0];
244244
tx_desc = &tx_q->base_tx[0];
245245
i = 0;
246+
} else {
247+
tx_buf++;
248+
tx_desc++;
246249
}
247250

251+
tx_buf->type = LIBETH_SQE_EMPTY;
252+
248253
dma += max_data;
249254
size -= max_data;
250255

@@ -257,21 +262,21 @@ static void idpf_tx_singleq_map(struct idpf_tx_queue *tx_q,
257262

258263
tx_desc->qw1 = idpf_tx_singleq_build_ctob(td_cmd, offsets,
259264
size, td_tag);
260-
tx_desc++;
261-
i++;
262265

263-
if (i == tx_q->desc_count) {
266+
if (unlikely(++i == tx_q->desc_count)) {
267+
tx_buf = &tx_q->tx_buf[0];
264268
tx_desc = &tx_q->base_tx[0];
265269
i = 0;
270+
} else {
271+
tx_buf++;
272+
tx_desc++;
266273
}
267274

268275
size = skb_frag_size(frag);
269276
data_len -= size;
270277

271278
dma = skb_frag_dma_map(tx_q->dev, frag, 0, size,
272279
DMA_TO_DEVICE);
273-
274-
tx_buf = &tx_q->tx_buf[i];
275280
}
276281

277282
skb_tx_timestamp(first->skb);
@@ -282,13 +287,13 @@ static void idpf_tx_singleq_map(struct idpf_tx_queue *tx_q,
282287
tx_desc->qw1 = idpf_tx_singleq_build_ctob(td_cmd, offsets,
283288
size, td_tag);
284289

285-
IDPF_SINGLEQ_BUMP_RING_IDX(tx_q, i);
290+
first->type = LIBETH_SQE_SKB;
291+
first->rs_idx = i;
286292

287-
/* set next_to_watch value indicating a packet is present */
288-
first->next_to_watch = tx_desc;
293+
IDPF_SINGLEQ_BUMP_RING_IDX(tx_q, i);
289294

290295
nq = netdev_get_tx_queue(tx_q->netdev, tx_q->idx);
291-
netdev_tx_sent_queue(nq, first->bytecount);
296+
netdev_tx_sent_queue(nq, first->bytes);
292297

293298
idpf_tx_buf_hw_update(tx_q, i, netdev_xmit_more());
294299
}
@@ -306,8 +311,7 @@ idpf_tx_singleq_get_ctx_desc(struct idpf_tx_queue *txq)
306311
struct idpf_base_tx_ctx_desc *ctx_desc;
307312
int ntu = txq->next_to_use;
308313

309-
memset(&txq->tx_buf[ntu], 0, sizeof(struct idpf_tx_buf));
310-
txq->tx_buf[ntu].ctx_entry = true;
314+
txq->tx_buf[ntu].type = LIBETH_SQE_CTX;
311315

312316
ctx_desc = &txq->base_ctx[ntu];
313317

@@ -371,6 +375,10 @@ netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb,
371375
IDPF_TX_DESCS_FOR_CTX)) {
372376
idpf_tx_buf_hw_update(tx_q, tx_q->next_to_use, false);
373377

378+
u64_stats_update_begin(&tx_q->stats_sync);
379+
u64_stats_inc(&tx_q->q_stats.q_busy);
380+
u64_stats_update_end(&tx_q->stats_sync);
381+
374382
return NETDEV_TX_BUSY;
375383
}
376384

@@ -396,11 +404,11 @@ netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb,
396404
first->skb = skb;
397405

398406
if (tso) {
399-
first->gso_segs = offload.tso_segs;
400-
first->bytecount = skb->len + ((first->gso_segs - 1) * offload.tso_hdr_len);
407+
first->packets = offload.tso_segs;
408+
first->bytes = skb->len + ((first->packets - 1) * offload.tso_hdr_len);
401409
} else {
402-
first->bytecount = max_t(unsigned int, skb->len, ETH_ZLEN);
403-
first->gso_segs = 1;
410+
first->bytes = max_t(unsigned int, skb->len, ETH_ZLEN);
411+
first->packets = 1;
404412
}
405413
idpf_tx_singleq_map(tx_q, first, &offload);
406414

@@ -420,10 +428,15 @@ netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb,
420428
static bool idpf_tx_singleq_clean(struct idpf_tx_queue *tx_q, int napi_budget,
421429
int *cleaned)
422430
{
423-
unsigned int total_bytes = 0, total_pkts = 0;
431+
struct libeth_sq_napi_stats ss = { };
424432
struct idpf_base_tx_desc *tx_desc;
425433
u32 budget = tx_q->clean_budget;
426434
s16 ntc = tx_q->next_to_clean;
435+
struct libeth_cq_pp cp = {
436+
.dev = tx_q->dev,
437+
.ss = &ss,
438+
.napi = napi_budget,
439+
};
427440
struct idpf_netdev_priv *np;
428441
struct idpf_tx_buf *tx_buf;
429442
struct netdev_queue *nq;
@@ -441,47 +454,26 @@ static bool idpf_tx_singleq_clean(struct idpf_tx_queue *tx_q, int napi_budget,
441454
* such. We can skip this descriptor since there is no buffer
442455
* to clean.
443456
*/
444-
if (tx_buf->ctx_entry) {
445-
/* Clear this flag here to avoid stale flag values when
446-
* this buffer is used for actual data in the future.
447-
* There are cases where the tx_buf struct / the flags
448-
* field will not be cleared before being reused.
449-
*/
450-
tx_buf->ctx_entry = false;
457+
if (unlikely(tx_buf->type <= LIBETH_SQE_CTX)) {
458+
tx_buf->type = LIBETH_SQE_EMPTY;
451459
goto fetch_next_txq_desc;
452460
}
453461

454-
/* if next_to_watch is not set then no work pending */
455-
eop_desc = (struct idpf_base_tx_desc *)tx_buf->next_to_watch;
456-
if (!eop_desc)
462+
if (unlikely(tx_buf->type != LIBETH_SQE_SKB))
457463
break;
458464

459-
/* prevent any other reads prior to eop_desc */
465+
/* prevent any other reads prior to type */
460466
smp_rmb();
461467

468+
eop_desc = &tx_q->base_tx[tx_buf->rs_idx];
469+
462470
/* if the descriptor isn't done, no work yet to do */
463471
if (!(eop_desc->qw1 &
464472
cpu_to_le64(IDPF_TX_DESC_DTYPE_DESC_DONE)))
465473
break;
466474

467-
/* clear next_to_watch to prevent false hangs */
468-
tx_buf->next_to_watch = NULL;
469-
470475
/* update the statistics for this packet */
471-
total_bytes += tx_buf->bytecount;
472-
total_pkts += tx_buf->gso_segs;
473-
474-
napi_consume_skb(tx_buf->skb, napi_budget);
475-
476-
/* unmap skb header data */
477-
dma_unmap_single(tx_q->dev,
478-
dma_unmap_addr(tx_buf, dma),
479-
dma_unmap_len(tx_buf, len),
480-
DMA_TO_DEVICE);
481-
482-
/* clear tx_buf data */
483-
tx_buf->skb = NULL;
484-
dma_unmap_len_set(tx_buf, len, 0);
476+
libeth_tx_complete(tx_buf, &cp);
485477

486478
/* unmap remaining buffers */
487479
while (tx_desc != eop_desc) {
@@ -495,13 +487,7 @@ static bool idpf_tx_singleq_clean(struct idpf_tx_queue *tx_q, int napi_budget,
495487
}
496488

497489
/* unmap any remaining paged data */
498-
if (dma_unmap_len(tx_buf, len)) {
499-
dma_unmap_page(tx_q->dev,
500-
dma_unmap_addr(tx_buf, dma),
501-
dma_unmap_len(tx_buf, len),
502-
DMA_TO_DEVICE);
503-
dma_unmap_len_set(tx_buf, len, 0);
504-
}
490+
libeth_tx_complete(tx_buf, &cp);
505491
}
506492

507493
/* update budget only if we did something */
@@ -521,19 +507,19 @@ static bool idpf_tx_singleq_clean(struct idpf_tx_queue *tx_q, int napi_budget,
521507
ntc += tx_q->desc_count;
522508
tx_q->next_to_clean = ntc;
523509

524-
*cleaned += total_pkts;
510+
*cleaned += ss.packets;
525511

526512
u64_stats_update_begin(&tx_q->stats_sync);
527-
u64_stats_add(&tx_q->q_stats.packets, total_pkts);
528-
u64_stats_add(&tx_q->q_stats.bytes, total_bytes);
513+
u64_stats_add(&tx_q->q_stats.packets, ss.packets);
514+
u64_stats_add(&tx_q->q_stats.bytes, ss.bytes);
529515
u64_stats_update_end(&tx_q->stats_sync);
530516

531517
np = netdev_priv(tx_q->netdev);
532518
nq = netdev_get_tx_queue(tx_q->netdev, tx_q->idx);
533519

534520
dont_wake = np->state != __IDPF_VPORT_UP ||
535521
!netif_carrier_ok(tx_q->netdev);
536-
__netif_txq_completed_wake(nq, total_pkts, total_bytes,
522+
__netif_txq_completed_wake(nq, ss.packets, ss.bytes,
537523
IDPF_DESC_UNUSED(tx_q), IDPF_TX_WAKE_THRESH,
538524
dont_wake);
539525

@@ -1134,8 +1120,10 @@ int idpf_vport_singleq_napi_poll(struct napi_struct *napi, int budget)
11341120
&work_done);
11351121

11361122
/* If work not completed, return budget and polling will return */
1137-
if (!clean_complete)
1123+
if (!clean_complete) {
1124+
idpf_vport_intr_set_wb_on_itr(q_vector);
11381125
return budget;
1126+
}
11391127

11401128
work_done = min_t(int, work_done, budget - 1);
11411129

@@ -1144,6 +1132,8 @@ int idpf_vport_singleq_napi_poll(struct napi_struct *napi, int budget)
11441132
*/
11451133
if (likely(napi_complete_done(napi, work_done)))
11461134
idpf_vport_intr_update_itr_ena_irq(q_vector);
1135+
else
1136+
idpf_vport_intr_set_wb_on_itr(q_vector);
11471137

11481138
return work_done;
11491139
}

0 commit comments

Comments
 (0)