Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

eth: fbnic: support devmem Tx

Support devmem Tx. We already use skb_frag_dma_map(), we just need
to make sure we don't try to unmap the frags. Check if frag is
unreadable and mark the ring entry.

# ./tools/testing/selftests/drivers/net/hw/devmem.py
TAP version 13
1..3
ok 1 devmem.check_rx
ok 2 devmem.check_tx
ok 3 devmem.check_tx_chunks
# Totals: pass:3 fail:0 xfail:0 xpass:0 skip:0 error:0

Acked-by: Mina Almasry <almasrymina@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Link: https://patch.msgid.link/20250916145401.1464550-1-kuba@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Jakub Kicinski and committed by
Paolo Abeni
b127e355 f6003468

+15 -1
+1
drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
··· 712 712 netdev->netdev_ops = &fbnic_netdev_ops; 713 713 netdev->stat_ops = &fbnic_stat_ops; 714 714 netdev->queue_mgmt_ops = &fbnic_queue_mgmt_ops; 715 + netdev->netmem_tx = true; 715 716 716 717 fbnic_set_ethtool_ops(netdev); 717 718
+14 -1
drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
··· 37 37 38 38 #define FBNIC_XMIT_CB(__skb) ((struct fbnic_xmit_cb *)((__skb)->cb)) 39 39 40 + #define FBNIC_XMIT_NOUNMAP ((void *)1) 41 + 40 42 static u32 __iomem *fbnic_ring_csr_base(const struct fbnic_ring *ring) 41 43 { 42 44 unsigned long csr_base = (unsigned long)ring->doorbell; ··· 317 315 unsigned int tail = ring->tail, first; 318 316 unsigned int size, data_len; 319 317 skb_frag_t *frag; 318 + bool is_net_iov; 320 319 dma_addr_t dma; 321 320 __le64 *twd; 322 321 ··· 333 330 if (size > FIELD_MAX(FBNIC_TWD_LEN_MASK)) 334 331 goto dma_error; 335 332 333 + is_net_iov = false; 336 334 dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE); 337 335 338 336 for (frag = &skb_shinfo(skb)->frags[0];; frag++) { ··· 346 342 FIELD_PREP(FBNIC_TWD_LEN_MASK, size) | 347 343 FIELD_PREP(FBNIC_TWD_TYPE_MASK, 348 344 FBNIC_TWD_TYPE_AL)); 345 + if (is_net_iov) 346 + ring->tx_buf[tail] = FBNIC_XMIT_NOUNMAP; 349 347 350 348 tail++; 351 349 tail &= ring->size_mask; ··· 361 355 if (size > FIELD_MAX(FBNIC_TWD_LEN_MASK)) 362 356 goto dma_error; 363 357 358 + is_net_iov = skb_frag_is_net_iov(frag); 364 359 dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE); 365 360 } 366 361 ··· 397 390 twd = &ring->desc[tail]; 398 391 if (tail == first) 399 392 fbnic_unmap_single_twd(dev, twd); 393 + else if (ring->tx_buf[tail] == FBNIC_XMIT_NOUNMAP) 394 + ring->tx_buf[tail] = NULL; 400 395 else 401 396 fbnic_unmap_page_twd(dev, twd); 402 397 } ··· 583 574 desc_cnt--; 584 575 585 576 while (desc_cnt--) { 586 - fbnic_unmap_page_twd(nv->dev, &ring->desc[head]); 577 + if (ring->tx_buf[head] != FBNIC_XMIT_NOUNMAP) 578 + fbnic_unmap_page_twd(nv->dev, 579 + &ring->desc[head]); 580 + else 581 + ring->tx_buf[head] = NULL; 587 582 head++; 588 583 head &= ring->size_mask; 589 584 }