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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'eth-fbnic-fix-and-improve-header-data-split-configuration'

Bobby Eshleman says:

====================
eth: fbnic: fix and improve header/data split configuration

This series fixes TCP HDS configuration in the fbnic driver and adds a
devmem selftest for the intended behavior.

The issues fixed include setting the correct CSR for EN_HDR_SPLIT,
adjusting the hds threshold clamp to avoid long headers overflowing into
the payload page, and configuring the device to use L4/L3/L2 header
boundaries when present by programming the DMA hint bit unconditionally
for all steering rule types.

Prior to these fixes, small payloads fail devmem.check_rx_hds().

Testing:

IFC0=enp1s0
IFC1=eth0

export REMOTE_TYPE=netns
export REMOTE_ARGS=ns-remote
export NETIF=$IFC0
export LOCAL_V4=192.0.3.1
export REMOTE_V4=192.0.3.2
sysctl -w net.ipv6.conf.$IFC0.keep_addr_on_down=1

./tools/testing/selftests/drivers/net/hw/devmem.py

TAP version 13
1..4
ok 1 devmem.check_rx
ok 2 devmem.check_tx
ok 3 devmem.check_tx_chunks
ok 4 devmem.check_rx_hds

To: Alexander Duyck <alexanderduyck@fb.com>
To: Jakub Kicinski <kuba@kernel.org>
To: kernel-team@meta.com
To: Andrew Lunn <andrew+netdev@lunn.ch>
To: David S. Miller <davem@davemloft.net>
To: Eric Dumazet <edumazet@google.com>
To: Paolo Abeni <pabeni@redhat.com>
To: Mohsin Bashir <mohsin.bashr@gmail.com>
To: Shuah Khan <shuah@kernel.org>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org

Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
====================

Link: https://patch.msgid.link/20260211-fbnic-tcp-hds-fixes-v1-0-55d050e6f606@meta.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+48 -17
+3
drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
··· 1145 1145 return -EINVAL; 1146 1146 } 1147 1147 1148 + dest |= FIELD_PREP(FBNIC_RPC_ACT_TBL0_DMA_HINT, 1149 + FBNIC_RCD_HDR_AL_DMA_HINT_L4); 1150 + 1148 1151 /* Write action table values */ 1149 1152 act_tcam->dest = dest; 1150 1153 act_tcam->rss_en_mask = fbnic_flow_hash_2_rss_en_mask(fbn, hash_idx);
+2 -3
drivers/net/ethernet/meta/fbnic/fbnic_rpc.c
··· 338 338 else if (tstamp_mask & (1u << flow_type)) 339 339 dest |= FBNIC_RPC_ACT_TBL0_TS_ENA; 340 340 341 - if (act1_value[flow_type] & FBNIC_RPC_TCAM_ACT1_L4_VALID) 342 - dest |= FIELD_PREP(FBNIC_RPC_ACT_TBL0_DMA_HINT, 343 - FBNIC_RCD_HDR_AL_DMA_HINT_L4); 341 + dest |= FIELD_PREP(FBNIC_RPC_ACT_TBL0_DMA_HINT, 342 + FBNIC_RCD_HDR_AL_DMA_HINT_L4); 344 343 345 344 rss_en_mask = fbnic_flow_hash_2_rss_en_mask(fbn, flow_type); 346 345
+14 -11
drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
··· 2591 2591 } 2592 2592 2593 2593 static void fbnic_config_drop_mode_rcq(struct fbnic_napi_vector *nv, 2594 - struct fbnic_ring *rcq, bool tx_pause) 2594 + struct fbnic_ring *rcq, bool tx_pause, 2595 + bool hdr_split) 2595 2596 { 2596 2597 struct fbnic_net *fbn = netdev_priv(nv->napi.dev); 2597 2598 u32 drop_mode, rcq_ctl; ··· 2605 2604 /* Specify packet layout */ 2606 2605 rcq_ctl = FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_DROP_MODE_MASK, drop_mode) | 2607 2606 FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_MIN_HROOM_MASK, FBNIC_RX_HROOM) | 2608 - FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_MIN_TROOM_MASK, FBNIC_RX_TROOM); 2607 + FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_MIN_TROOM_MASK, FBNIC_RX_TROOM) | 2608 + FIELD_PREP(FBNIC_QUEUE_RDE_CTL0_EN_HDR_SPLIT, hdr_split); 2609 2609 2610 2610 fbnic_ring_wr32(rcq, FBNIC_QUEUE_RDE_CTL0, rcq_ctl); 2611 2611 } 2612 2612 2613 - void fbnic_config_drop_mode(struct fbnic_net *fbn, bool tx_pause) 2613 + void fbnic_config_drop_mode(struct fbnic_net *fbn, bool txp) 2614 2614 { 2615 + bool hds; 2615 2616 int i, t; 2617 + 2618 + hds = fbn->hds_thresh < FBNIC_HDR_BYTES_MIN; 2616 2619 2617 2620 for (i = 0; i < fbn->num_napi; i++) { 2618 2621 struct fbnic_napi_vector *nv = fbn->napi[i]; ··· 2624 2619 for (t = 0; t < nv->rxt_count; t++) { 2625 2620 struct fbnic_q_triad *qt = &nv->qt[nv->txt_count + t]; 2626 2621 2627 - fbnic_config_drop_mode_rcq(nv, &qt->cmpl, tx_pause); 2622 + fbnic_config_drop_mode_rcq(nv, &qt->cmpl, txp, hds); 2628 2623 } 2629 2624 } 2630 2625 } ··· 2675 2670 { 2676 2671 struct fbnic_net *fbn = netdev_priv(nv->napi.dev); 2677 2672 u32 log_size = fls(rcq->size_mask); 2678 - u32 hds_thresh = fbn->hds_thresh; 2679 2673 u32 rcq_ctl = 0; 2680 - 2681 - fbnic_config_drop_mode_rcq(nv, rcq, fbn->tx_pause); 2674 + bool hdr_split; 2675 + u32 hds_thresh; 2682 2676 2683 2677 /* Force lower bound on MAX_HEADER_BYTES. Below this, all frames should 2684 2678 * be split at L4. It would also result in the frames being split at 2685 2679 * L2/L3 depending on the frame size. 2686 2680 */ 2687 - if (fbn->hds_thresh < FBNIC_HDR_BYTES_MIN) { 2688 - rcq_ctl = FBNIC_QUEUE_RDE_CTL0_EN_HDR_SPLIT; 2689 - hds_thresh = FBNIC_HDR_BYTES_MIN; 2690 - } 2681 + hdr_split = fbn->hds_thresh < FBNIC_HDR_BYTES_MIN; 2682 + fbnic_config_drop_mode_rcq(nv, rcq, fbn->tx_pause, hdr_split); 2691 2683 2684 + hds_thresh = max(fbn->hds_thresh, FBNIC_HDR_BYTES_MIN); 2692 2685 rcq_ctl |= FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_PADLEN_MASK, FBNIC_RX_PAD) | 2693 2686 FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_MAX_HDR_MASK, hds_thresh) | 2694 2687 FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_PAYLD_OFF_MASK,
+1 -1
drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
··· 66 66 (4096 - FBNIC_RX_HROOM - FBNIC_RX_TROOM - FBNIC_RX_PAD) 67 67 #define FBNIC_HDS_THRESH_DEFAULT \ 68 68 (1536 - FBNIC_RX_PAD) 69 - #define FBNIC_HDR_BYTES_MIN 128 69 + #define FBNIC_HDR_BYTES_MIN 256 70 70 71 71 struct fbnic_pkt_buff { 72 72 struct xdp_buff buff;
+18 -1
tools/testing/selftests/drivers/net/hw/devmem.py
··· 63 63 ksft_eq(socat.stdout.strip(), "hello\nworld") 64 64 65 65 66 + def check_rx_hds(cfg) -> None: 67 + """Test HDS splitting across payload sizes.""" 68 + require_devmem(cfg) 69 + 70 + for size in [1, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]: 71 + port = rand_port() 72 + listen_cmd = f"{cfg.bin_local} -L -l -f {cfg.ifname} -s {cfg.addr} -p {port}" 73 + 74 + with bkg(listen_cmd, exit_wait=True) as ncdevmem: 75 + wait_port_listen(port) 76 + cmd(f"dd if=/dev/zero bs={size} count=1 2>/dev/null | " + 77 + f"socat -b {size} -u - TCP{cfg.addr_ipver}:{cfg.baddr}:{port},nodelay", 78 + host=cfg.remote, shell=True) 79 + 80 + ksft_eq(ncdevmem.ret, 0, f"HDS failed for payload size {size}") 81 + 82 + 66 83 def main() -> None: 67 84 with NetDrvEpEnv(__file__) as cfg: 68 85 cfg.bin_local = path.abspath(path.dirname(__file__) + "/ncdevmem") 69 86 cfg.bin_remote = cfg.remote.deploy(cfg.bin_local) 70 87 71 - ksft_run([check_rx, check_tx, check_tx_chunks], 88 + ksft_run([check_rx, check_tx, check_tx_chunks, check_rx_hds], 72 89 args=(cfg, )) 73 90 ksft_exit() 74 91
+10 -1
tools/testing/selftests/drivers/net/hw/ncdevmem.c
··· 98 98 static unsigned int dmabuf_id; 99 99 static uint32_t tx_dmabuf_id; 100 100 static int waittime_ms = 500; 101 + static bool fail_on_linear; 101 102 102 103 /* System state loaded by current_config_load() */ 103 104 #define MAX_FLOWS 8 ··· 976 975 "SCM_DEVMEM_LINEAR. dmabuf_cmsg->frag_size=%u\n", 977 976 dmabuf_cmsg->frag_size); 978 977 978 + if (fail_on_linear) { 979 + pr_err("received SCM_DEVMEM_LINEAR but --fail-on-linear (-L) set"); 980 + goto err_close_client; 981 + } 982 + 979 983 continue; 980 984 } 981 985 ··· 1404 1398 int is_server = 0, opt; 1405 1399 int ret, err = 1; 1406 1400 1407 - while ((opt = getopt(argc, argv, "ls:c:p:v:q:t:f:z:")) != -1) { 1401 + while ((opt = getopt(argc, argv, "Lls:c:p:v:q:t:f:z:")) != -1) { 1408 1402 switch (opt) { 1403 + case 'L': 1404 + fail_on_linear = true; 1405 + break; 1409 1406 case 'l': 1410 1407 is_server = 1; 1411 1408 break;