|
2 | 2 | /* Copyright(c) 2018 Intel Corporation. */ |
3 | 3 |
|
4 | 4 | #include <linux/bpf_trace.h> |
| 5 | +#include <linux/stringify.h> |
5 | 6 | #include <net/xdp_sock_drv.h> |
6 | 7 | #include <net/xdp.h> |
7 | 8 |
|
@@ -381,58 +382,102 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget) |
381 | 382 | return failure ? budget : (int)total_rx_packets; |
382 | 383 | } |
383 | 384 |
|
384 | | -/** |
385 | | - * i40e_xmit_zc - Performs zero-copy Tx AF_XDP |
386 | | - * @xdp_ring: XDP Tx ring |
387 | | - * @budget: NAPI budget |
388 | | - * |
389 | | - * Returns true if the work is finished. |
390 | | - **/ |
391 | | -static bool i40e_xmit_zc(struct i40e_ring *xdp_ring, unsigned int budget) |
| 385 | +static void i40e_xmit_pkt(struct i40e_ring *xdp_ring, struct xdp_desc *desc, |
| 386 | + unsigned int *total_bytes) |
392 | 387 | { |
393 | | - unsigned int sent_frames = 0, total_bytes = 0; |
394 | | - struct i40e_tx_desc *tx_desc = NULL; |
395 | | - struct i40e_tx_buffer *tx_bi; |
396 | | - struct xdp_desc desc; |
| 388 | + struct i40e_tx_desc *tx_desc; |
397 | 389 | dma_addr_t dma; |
398 | 390 |
|
399 | | - while (budget-- > 0) { |
400 | | - if (!xsk_tx_peek_desc(xdp_ring->xsk_pool, &desc)) |
401 | | - break; |
| 391 | + dma = xsk_buff_raw_get_dma(xdp_ring->xsk_pool, desc->addr); |
| 392 | + xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_pool, dma, desc->len); |
402 | 393 |
|
403 | | - dma = xsk_buff_raw_get_dma(xdp_ring->xsk_pool, desc.addr); |
404 | | - xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_pool, dma, |
405 | | - desc.len); |
| 394 | + tx_desc = I40E_TX_DESC(xdp_ring, xdp_ring->next_to_use++); |
| 395 | + tx_desc->buffer_addr = cpu_to_le64(dma); |
| 396 | + tx_desc->cmd_type_offset_bsz = build_ctob(I40E_TX_DESC_CMD_ICRC | I40E_TX_DESC_CMD_EOP, |
| 397 | + 0, desc->len, 0); |
406 | 398 |
|
407 | | - tx_bi = &xdp_ring->tx_bi[xdp_ring->next_to_use]; |
408 | | - tx_bi->bytecount = desc.len; |
| 399 | + *total_bytes += desc->len; |
| 400 | +} |
409 | 401 |
|
410 | | - tx_desc = I40E_TX_DESC(xdp_ring, xdp_ring->next_to_use); |
411 | | - tx_desc->buffer_addr = cpu_to_le64(dma); |
412 | | - tx_desc->cmd_type_offset_bsz = |
413 | | - build_ctob(I40E_TX_DESC_CMD_ICRC |
414 | | - | I40E_TX_DESC_CMD_EOP, |
415 | | - 0, desc.len, 0); |
| 402 | +static void i40e_xmit_pkt_batch(struct i40e_ring *xdp_ring, struct xdp_desc *desc, |
| 403 | + unsigned int *total_bytes) |
| 404 | +{ |
| 405 | + u16 ntu = xdp_ring->next_to_use; |
| 406 | + struct i40e_tx_desc *tx_desc; |
| 407 | + dma_addr_t dma; |
| 408 | + u32 i; |
416 | 409 |
|
417 | | - sent_frames++; |
418 | | - total_bytes += tx_bi->bytecount; |
| 410 | + loop_unrolled_for(i = 0; i < PKTS_PER_BATCH; i++) { |
| 411 | + dma = xsk_buff_raw_get_dma(xdp_ring->xsk_pool, desc[i].addr); |
| 412 | + xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_pool, dma, desc[i].len); |
419 | 413 |
|
420 | | - xdp_ring->next_to_use++; |
421 | | - if (xdp_ring->next_to_use == xdp_ring->count) |
422 | | - xdp_ring->next_to_use = 0; |
| 414 | + tx_desc = I40E_TX_DESC(xdp_ring, ntu++); |
| 415 | + tx_desc->buffer_addr = cpu_to_le64(dma); |
| 416 | + tx_desc->cmd_type_offset_bsz = build_ctob(I40E_TX_DESC_CMD_ICRC | |
| 417 | + I40E_TX_DESC_CMD_EOP, |
| 418 | + 0, desc[i].len, 0); |
| 419 | + |
| 420 | + *total_bytes += desc[i].len; |
423 | 421 | } |
424 | 422 |
|
425 | | - if (tx_desc) { |
426 | | - /* Request an interrupt for the last frame and bump tail ptr. */ |
427 | | - tx_desc->cmd_type_offset_bsz |= (I40E_TX_DESC_CMD_RS << |
428 | | - I40E_TXD_QW1_CMD_SHIFT); |
429 | | - i40e_xdp_ring_update_tail(xdp_ring); |
| 423 | + xdp_ring->next_to_use = ntu; |
| 424 | +} |
| 425 | + |
| 426 | +static void i40e_fill_tx_hw_ring(struct i40e_ring *xdp_ring, struct xdp_desc *descs, u32 nb_pkts, |
| 427 | + unsigned int *total_bytes) |
| 428 | +{ |
| 429 | + u32 batched, leftover, i; |
| 430 | + |
| 431 | + batched = nb_pkts & ~(PKTS_PER_BATCH - 1); |
| 432 | + leftover = nb_pkts & (PKTS_PER_BATCH - 1); |
| 433 | + for (i = 0; i < batched; i += PKTS_PER_BATCH) |
| 434 | + i40e_xmit_pkt_batch(xdp_ring, &descs[i], total_bytes); |
| 435 | + for (i = batched; i < batched + leftover; i++) |
| 436 | + i40e_xmit_pkt(xdp_ring, &descs[i], total_bytes); |
| 437 | +} |
430 | 438 |
|
431 | | - xsk_tx_release(xdp_ring->xsk_pool); |
432 | | - i40e_update_tx_stats(xdp_ring, sent_frames, total_bytes); |
| 439 | +static void i40e_set_rs_bit(struct i40e_ring *xdp_ring) |
| 440 | +{ |
| 441 | + u16 ntu = xdp_ring->next_to_use ? xdp_ring->next_to_use - 1 : xdp_ring->count - 1; |
| 442 | + struct i40e_tx_desc *tx_desc; |
| 443 | + |
| 444 | + tx_desc = I40E_TX_DESC(xdp_ring, ntu); |
| 445 | + tx_desc->cmd_type_offset_bsz |= (I40E_TX_DESC_CMD_RS << I40E_TXD_QW1_CMD_SHIFT); |
| 446 | +} |
| 447 | + |
| 448 | +/** |
| 449 | + * i40e_xmit_zc - Performs zero-copy Tx AF_XDP |
| 450 | + * @xdp_ring: XDP Tx ring |
| 451 | + * @budget: NAPI budget |
| 452 | + * |
| 453 | + * Returns true if the work is finished. |
| 454 | + **/ |
| 455 | +static bool i40e_xmit_zc(struct i40e_ring *xdp_ring, unsigned int budget) |
| 456 | +{ |
| 457 | + struct xdp_desc *descs = xdp_ring->xsk_descs; |
| 458 | + u32 nb_pkts, nb_processed = 0; |
| 459 | + unsigned int total_bytes = 0; |
| 460 | + |
| 461 | + nb_pkts = xsk_tx_peek_release_desc_batch(xdp_ring->xsk_pool, descs, budget); |
| 462 | + if (!nb_pkts) |
| 463 | + return false; |
| 464 | + |
| 465 | + if (xdp_ring->next_to_use + nb_pkts >= xdp_ring->count) { |
| 466 | + nb_processed = xdp_ring->count - xdp_ring->next_to_use; |
| 467 | + i40e_fill_tx_hw_ring(xdp_ring, descs, nb_processed, &total_bytes); |
| 468 | + xdp_ring->next_to_use = 0; |
433 | 469 | } |
434 | 470 |
|
435 | | - return !!budget; |
| 471 | + i40e_fill_tx_hw_ring(xdp_ring, &descs[nb_processed], nb_pkts - nb_processed, |
| 472 | + &total_bytes); |
| 473 | + |
| 474 | + /* Request an interrupt for the last frame and bump tail ptr. */ |
| 475 | + i40e_set_rs_bit(xdp_ring); |
| 476 | + i40e_xdp_ring_update_tail(xdp_ring); |
| 477 | + |
| 478 | + i40e_update_tx_stats(xdp_ring, nb_pkts, total_bytes); |
| 479 | + |
| 480 | + return true; |
436 | 481 | } |
437 | 482 |
|
438 | 483 | /** |
|
0 commit comments