]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
eth: fbnic: Add support for HDS configuration
authorMohsin Bashir <mohsin.bashr@gmail.com>
Wed, 13 Aug 2025 22:13:11 +0000 (15:13 -0700)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 19 Aug 2025 08:51:16 +0000 (10:51 +0200)
Add support for configuring the header data split threshold.
For fbnic, the tcp data split support is enabled all the time.

Fbnic supports a maximum buffer size of 4KB. However, the reservation
for the headroom, tailroom, and padding reduce the max header size
accordingly.

  ethtool_hds -g eth0
  Ring parameters for eth0:
  Pre-set maximums:
  ...
  HDS thresh: 3584
  Current hardware settings:
  ...
  HDS thresh: 1536

Verify hds tests in ksft-net-drv are passing

  ksft-net-drv]# ./drivers/net/hds.py
  TAP version 13
  1..13
  ok 1 hds.get_hds
  ok 2 hds.get_hds_thresh
  ok 3 hds.set_hds_disable # SKIP disabling of HDS not supported by ...
  ...
  ...
  ok 12 hds.ioctl_set_xdp
  ok 13 hds.ioctl_enabled_set_xdp
  \# Totals: pass:12 fail:0 xfail:0 xpass:0 skip:1 error:0

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Mohsin Bashir <mohsin.bashr@gmail.com>
Link: https://patch.msgid.link/20250813221319.3367670-2-mohsin.bashr@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
drivers/net/ethernet/meta/fbnic/fbnic_txrx.h

index 461c8661eb934da21d51c8862698879ab76e0948..569ddd767f9d0f3ce1c1d597d40fd3cc5b120bc8 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright (c) Meta Platforms, Inc. and affiliates. */
 
 #include <linux/ethtool.h>
+#include <linux/ethtool_netlink.h>
 #include <linux/netdevice.h>
 #include <linux/pci.h>
 #include <net/ipv6.h>
@@ -160,6 +161,7 @@ static void fbnic_clone_swap_cfg(struct fbnic_net *orig,
        swap(clone->num_rx_queues, orig->num_rx_queues);
        swap(clone->num_tx_queues, orig->num_tx_queues);
        swap(clone->num_napi, orig->num_napi);
+       swap(clone->hds_thresh, orig->hds_thresh);
 }
 
 static void fbnic_aggregate_vector_counters(struct fbnic_net *fbn,
@@ -277,15 +279,21 @@ fbnic_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
        ring->rx_mini_pending = fbn->hpq_size;
        ring->rx_jumbo_pending = fbn->ppq_size;
        ring->tx_pending = fbn->txq_size;
+
+       kernel_ring->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_ENABLED;
+       kernel_ring->hds_thresh_max = FBNIC_HDS_THRESH_MAX;
+       kernel_ring->hds_thresh = fbn->hds_thresh;
 }
 
 static void fbnic_set_rings(struct fbnic_net *fbn,
-                           struct ethtool_ringparam *ring)
+                           struct ethtool_ringparam *ring,
+                           struct kernel_ethtool_ringparam *kernel_ring)
 {
        fbn->rcq_size = ring->rx_pending;
        fbn->hpq_size = ring->rx_mini_pending;
        fbn->ppq_size = ring->rx_jumbo_pending;
        fbn->txq_size = ring->tx_pending;
+       fbn->hds_thresh = kernel_ring->hds_thresh;
 }
 
 static int
@@ -316,8 +324,13 @@ fbnic_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
                return -EINVAL;
        }
 
+       if (kernel_ring->tcp_data_split == ETHTOOL_TCP_DATA_SPLIT_DISABLED) {
+               NL_SET_ERR_MSG_MOD(extack, "Cannot disable TCP data split");
+               return -EINVAL;
+       }
+
        if (!netif_running(netdev)) {
-               fbnic_set_rings(fbn, ring);
+               fbnic_set_rings(fbn, ring, kernel_ring);
                return 0;
        }
 
@@ -325,7 +338,7 @@ fbnic_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
        if (!clone)
                return -ENOMEM;
 
-       fbnic_set_rings(clone, ring);
+       fbnic_set_rings(clone, ring, kernel_ring);
 
        err = fbnic_alloc_napi_vectors(clone);
        if (err)
@@ -1678,6 +1691,8 @@ fbnic_get_rmon_stats(struct net_device *netdev,
 static const struct ethtool_ops fbnic_ethtool_ops = {
        .supported_coalesce_params      = ETHTOOL_COALESCE_USECS |
                                          ETHTOOL_COALESCE_RX_MAX_FRAMES,
+       .supported_ring_params          = ETHTOOL_RING_USE_TCP_DATA_SPLIT |
+                                         ETHTOOL_RING_USE_HDS_THRS,
        .rxfh_max_num_contexts          = FBNIC_RPC_RSS_TBL_COUNT,
        .get_drvinfo                    = fbnic_get_drvinfo,
        .get_regs_len                   = fbnic_get_regs_len,
index e67e99487a271c77a762f53e97c094682a9468ea..a7eb7a367b98309d67c7338472736fa9d785531e 100644 (file)
@@ -695,6 +695,10 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd)
        fbn->rx_usecs = FBNIC_RX_USECS_DEFAULT;
        fbn->rx_max_frames = FBNIC_RX_FRAMES_DEFAULT;
 
+       /* Initialize the hds_thresh */
+       netdev->cfg->hds_thresh = FBNIC_HDS_THRESH_DEFAULT;
+       fbn->hds_thresh = FBNIC_HDS_THRESH_DEFAULT;
+
        default_queues = netif_get_num_default_rss_queues();
        if (default_queues > fbd->max_num_queues)
                default_queues = fbd->max_num_queues;
index 86576ae042625b5e8dcc20f1cdbdb7a11c1e2913..04c5c7ed6c3a447612bff75e5277c073d8c2a971 100644 (file)
@@ -31,6 +31,8 @@ struct fbnic_net {
        u32 ppq_size;
        u32 rcq_size;
 
+       u32 hds_thresh;
+
        u16 rx_usecs;
        u16 tx_usecs;
 
index f9543d03485fe124f64832297815b3e539cea1a4..7c69f6381d9e97a545d78e336c4e8439905afc88 100644 (file)
@@ -2232,13 +2232,22 @@ static void fbnic_enable_rcq(struct fbnic_napi_vector *nv,
 {
        struct fbnic_net *fbn = netdev_priv(nv->napi.dev);
        u32 log_size = fls(rcq->size_mask);
-       u32 rcq_ctl;
+       u32 hds_thresh = fbn->hds_thresh;
+       u32 rcq_ctl = 0;
 
        fbnic_config_drop_mode_rcq(nv, rcq);
 
-       rcq_ctl = FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_PADLEN_MASK, FBNIC_RX_PAD) |
-                  FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_MAX_HDR_MASK,
-                             FBNIC_RX_MAX_HDR) |
+       /* Force lower bound on MAX_HEADER_BYTES. Below this, all frames should
+        * be split at L4. It would also result in the frames being split at
+        * L2/L3 depending on the frame size.
+        */
+       if (fbn->hds_thresh < FBNIC_HDR_BYTES_MIN) {
+               rcq_ctl = FBNIC_QUEUE_RDE_CTL0_EN_HDR_SPLIT;
+               hds_thresh = FBNIC_HDR_BYTES_MIN;
+       }
+
+       rcq_ctl |= FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_PADLEN_MASK, FBNIC_RX_PAD) |
+                  FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_MAX_HDR_MASK, hds_thresh) |
                   FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_PAYLD_OFF_MASK,
                              FBNIC_RX_PAYLD_OFFSET) |
                   FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_PAYLD_PG_CL_MASK,
index 34693596e5eb698f09c78b30f7829d465211e576..7d27712d54625c3a7c39b9e89fa23109637a266c 100644 (file)
@@ -53,7 +53,6 @@ struct fbnic_net;
 #define FBNIC_RX_HROOM \
        (ALIGN(FBNIC_RX_TROOM + NET_SKB_PAD, 128) - FBNIC_RX_TROOM)
 #define FBNIC_RX_PAD                   0
-#define FBNIC_RX_MAX_HDR               (1536 - FBNIC_RX_PAD)
 #define FBNIC_RX_PAYLD_OFFSET          0
 #define FBNIC_RX_PAYLD_PG_CL           0
 
@@ -61,6 +60,12 @@ struct fbnic_net;
 #define FBNIC_RING_F_CTX               BIT(1)
 #define FBNIC_RING_F_STATS             BIT(2)  /* Ring's stats may be used */
 
+#define FBNIC_HDS_THRESH_MAX \
+       (4096 - FBNIC_RX_HROOM - FBNIC_RX_TROOM - FBNIC_RX_PAD)
+#define FBNIC_HDS_THRESH_DEFAULT \
+       (1536 - FBNIC_RX_PAD)
+#define FBNIC_HDR_BYTES_MIN            128
+
 struct fbnic_pkt_buff {
        struct xdp_buff buff;
        ktime_t hwtstamp;