eth: fbnic: support ring size configuration

Support ethtool -g / -G. Leverage the code added for -l / -L
to alloc / stop / start / free.

Check parameters against HW min/max but also our own min/max.
Min HW queue is 16 entries, we can't deal with TWQs that small
because of the queue waking logic. Add similar contraint on RCQ
for symmetry.

We need 3 sizes on Rx, as the NIC does header-data split two separate
buffer pools:
  (1) head page ring    - how many empty pages we post for headers
  (2) payload page ring - how many empty pages we post for payloads
  (3) completion ring   - where NIC produces the Rx descriptors

Acked-by: Joe Damato <jdamato@fastly.com>
Link: https://patch.msgid.link/20250306145150.1757263-4-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2025-03-06 06:51:50 -08:00
parent bfb522f347
commit 6cbf18a05c
2 changed files with 122 additions and 0 deletions

View File

@ -191,6 +191,113 @@ static int fbnic_set_coalesce(struct net_device *netdev,
return 0;
}
static void
fbnic_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack)
{
struct fbnic_net *fbn = netdev_priv(netdev);
ring->rx_max_pending = FBNIC_QUEUE_SIZE_MAX;
ring->rx_mini_max_pending = FBNIC_QUEUE_SIZE_MAX;
ring->rx_jumbo_max_pending = FBNIC_QUEUE_SIZE_MAX;
ring->tx_max_pending = FBNIC_QUEUE_SIZE_MAX;
ring->rx_pending = fbn->rcq_size;
ring->rx_mini_pending = fbn->hpq_size;
ring->rx_jumbo_pending = fbn->ppq_size;
ring->tx_pending = fbn->txq_size;
}
static void fbnic_set_rings(struct fbnic_net *fbn,
struct ethtool_ringparam *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;
}
static int
fbnic_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack)
{
struct fbnic_net *fbn = netdev_priv(netdev);
struct fbnic_net *clone;
int err;
ring->rx_pending = roundup_pow_of_two(ring->rx_pending);
ring->rx_mini_pending = roundup_pow_of_two(ring->rx_mini_pending);
ring->rx_jumbo_pending = roundup_pow_of_two(ring->rx_jumbo_pending);
ring->tx_pending = roundup_pow_of_two(ring->tx_pending);
/* These are absolute minimums allowing the device and driver to operate
* but not necessarily guarantee reasonable performance. Settings below
* Rx queue size of 128 and BDQs smaller than 64 are likely suboptimal
* at best.
*/
if (ring->rx_pending < max(FBNIC_QUEUE_SIZE_MIN, FBNIC_RX_DESC_MIN) ||
ring->rx_mini_pending < FBNIC_QUEUE_SIZE_MIN ||
ring->rx_jumbo_pending < FBNIC_QUEUE_SIZE_MIN ||
ring->tx_pending < max(FBNIC_QUEUE_SIZE_MIN, FBNIC_TX_DESC_MIN)) {
NL_SET_ERR_MSG_MOD(extack, "requested ring size too small");
return -EINVAL;
}
if (!netif_running(netdev)) {
fbnic_set_rings(fbn, ring);
return 0;
}
clone = fbnic_clone_create(fbn);
if (!clone)
return -ENOMEM;
fbnic_set_rings(clone, ring);
err = fbnic_alloc_napi_vectors(clone);
if (err)
goto err_free_clone;
err = fbnic_alloc_resources(clone);
if (err)
goto err_free_napis;
fbnic_down_noidle(fbn);
err = fbnic_wait_all_queues_idle(fbn->fbd, true);
if (err)
goto err_start_stack;
err = fbnic_set_netif_queues(clone);
if (err)
goto err_start_stack;
/* Nothing can fail past this point */
fbnic_flush(fbn);
fbnic_clone_swap(fbn, clone);
fbnic_up(fbn);
fbnic_free_resources(clone);
fbnic_free_napi_vectors(clone);
fbnic_clone_free(clone);
return 0;
err_start_stack:
fbnic_flush(fbn);
fbnic_up(fbn);
fbnic_free_resources(clone);
err_free_napis:
fbnic_free_napi_vectors(clone);
err_free_clone:
fbnic_clone_free(clone);
return err;
}
static void fbnic_get_strings(struct net_device *dev, u32 sset, u8 *data)
{
int i;
@ -1351,6 +1458,8 @@ static const struct ethtool_ops fbnic_ethtool_ops = {
.get_regs = fbnic_get_regs,
.get_coalesce = fbnic_get_coalesce,
.set_coalesce = fbnic_set_coalesce,
.get_ringparam = fbnic_get_ringparam,
.set_ringparam = fbnic_set_ringparam,
.get_strings = fbnic_get_strings,
.get_ethtool_stats = fbnic_get_ethtool_stats,
.get_sset_count = fbnic_get_sset_count,

View File

@ -24,9 +24,22 @@ struct fbnic_net;
#define FBNIC_TX_DESC_WAKEUP (FBNIC_MAX_SKB_DESC * 2)
#define FBNIC_TX_DESC_MIN roundup_pow_of_two(FBNIC_TX_DESC_WAKEUP)
/* To receive the worst case packet we need:
* 1 descriptor for primary metadata
* + 1 descriptor for optional metadata
* + 1 descriptor for headers
* + 4 descriptors for payload
*/
#define FBNIC_MAX_RX_PKT_DESC 7
#define FBNIC_RX_DESC_MIN roundup_pow_of_two(FBNIC_MAX_RX_PKT_DESC * 2)
#define FBNIC_MAX_TXQS 128u
#define FBNIC_MAX_RXQS 128u
/* These apply to TWQs, TCQ, RCQ */
#define FBNIC_QUEUE_SIZE_MIN 16u
#define FBNIC_QUEUE_SIZE_MAX SZ_64K
#define FBNIC_TXQ_SIZE_DEFAULT 1024
#define FBNIC_HPQ_SIZE_DEFAULT 256
#define FBNIC_PPQ_SIZE_DEFAULT 256