From nobody Fri Sep 25 16:02:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5837D497B81; Fri, 25 Sep 2026 10:44:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790333073; cv=none; b=TB1YqI7/Ts4seD8M27e47u0DG5bLcn5UPFCq6W3jhlKPxzoVjZcLLptmJQqosDV5qx0oYjERn7EezlyaaWRGsOcuZHVj5CaxPBSZVSGzi3IhykXtMxqJw957HH14dII/uT98ywTIRde7Yg5Bm1XHKSQ/3bsYolpjcdb3s29jtHM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790333073; c=relaxed/simple; bh=l4lEHtXc4NJ5CVRMIB62osTQZ32j68YNqwvl2VjT9jk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=JB/UjSyQ1cnb8NTv8ArFn+BO83yg67NFF0+0N7sv0DXDBdF9dFPz03GaZT2GNlD9GxzaI6hyAp689sAVE5U5uWuY0+pSFjo1V7rPL83KjC3Jf9EhBS7rxCtLS9mMe93SYvAdoDgM7Shj7P8SYdnbBLOrN8vvY2Wy0ovGJMA67OM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XlSogdAs; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XlSogdAs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 41D981F00893; Fri, 25 Sep 2026 10:44:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790333072; bh=ob/SIDsox2KlTMYpTA0q+vfVttmUhJCJS4TF5rdRdQU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=XlSogdAsNFLrM1q2oPOO06YnZW06BFX3kwNONx4OvmG1uCm6PQar2zdrMBqSrF8Tq 3K5DbWvd3V+4T+vhQTwgbtWay0KsHL3yyy4UHwe6ObQDCiD5H3UOpU5moFZH4Ggfv1 R98Kd2HAwpDmAk9ZNEzVBOsOwTymvDH7mrkHhwy0nyrmEyy1Y07C6qrnp+DPqZhg2d yKZwOP8c3R75ExIDj2FsKzkpLTuGAg1z1UjOEY6eChG7IKflfXPiiy4djRFojTE2IT k3ja/LaplA7MykaltfHsjo6CT6E+WSGOA0B9V0BQ5zbav04sBeUBmlwPMc1BnODr3w HslnI73QN26ng== From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= To: Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Daniel Borkmann Cc: "Mike Marciniszyn (Meta)" , Mohsin Bashir , Stanislav Fomichev , Bobby Eshleman , Dimitri Daskalakis , Weiming Shi , Maxime Chevallier , Jacob Keller , Breno Leitao , Tao Cui , Pavel Begunkov , David Wei , =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= Subject: [PATCH net-next v4 1/5] net: Add netdev_config helpers Date: Fri, 25 Sep 2026 12:44:08 +0200 Message-ID: <20260925104417.2325213-2-bjorn@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260925104417.2325213-1-bjorn@kernel.org> References: <20260925104417.2325213-1-bjorn@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Jakub Kicinski netdev_config manipulation will become slightly more complicated soon and will be used by both ethtool and the queue API. Encapsulate the logic in helper functions. Signed-off-by: Jakub Kicinski Signed-off-by: Bj=C3=B6rn T=C3=B6pel Reviewed-by: Breno Leitao --- net/core/dev.c | 7 ++----- net/core/dev.h | 5 +++++ net/core/netdev_config.c | 37 +++++++++++++++++++++++++++++++++++++ net/ethtool/netlink.c | 15 +++++++-------- 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index f660fccfc0db..9f4441624350 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -12206,10 +12206,8 @@ struct net_device *alloc_netdev_mqs(int sizeof_pri= v, const char *name, if (!dev->ethtool) goto free_all; =20 - dev->cfg =3D kzalloc_obj(*dev->cfg, GFP_KERNEL_ACCOUNT); - if (!dev->cfg) + if (netdev_alloc_config(dev)) goto free_all; - dev->cfg_pending =3D dev->cfg; =20 dev->num_napi_configs =3D maxqs; napi_config_sz =3D array_size(maxqs, sizeof(*dev->napi_config)); @@ -12281,8 +12279,7 @@ void free_netdev(struct net_device *dev) return; } =20 - WARN_ON(dev->cfg !=3D dev->cfg_pending); - kfree(dev->cfg); + netdev_free_config(dev); kfree(dev->ethtool); netif_free_tx_queues(dev); netif_free_rx_queues(dev); diff --git a/net/core/dev.h b/net/core/dev.h index 04fb0e9a571e..6d8dbf556269 100644 --- a/net/core/dev.h +++ b/net/core/dev.h @@ -102,6 +102,11 @@ extern struct rw_semaphore dev_addr_sem; extern struct list_head net_todo_list; void netdev_run_todo(void); =20 +int netdev_alloc_config(struct net_device *dev); +void __netdev_free_config(struct netdev_config *cfg); +void netdev_free_config(struct net_device *dev); +int netdev_reconfig_start(struct net_device *dev); + int netdev_queue_config_validate(struct net_device *dev, int rxq_idx, struct netdev_queue_config *qcfg, struct netlink_ext_ack *extack); diff --git a/net/core/netdev_config.c b/net/core/netdev_config.c index f14af365d5cd..b101341e3251 100644 --- a/net/core/netdev_config.c +++ b/net/core/netdev_config.c @@ -6,6 +6,43 @@ =20 #include "dev.h" =20 +int netdev_alloc_config(struct net_device *dev) +{ + struct netdev_config *cfg; + + cfg =3D kzalloc_obj(*dev->cfg, GFP_KERNEL_ACCOUNT); + if (!cfg) + return -ENOMEM; + + dev->cfg =3D cfg; + dev->cfg_pending =3D cfg; + return 0; +} + +void __netdev_free_config(struct netdev_config *cfg) +{ + kfree(cfg); +} + +void netdev_free_config(struct net_device *dev) +{ + WARN_ON(dev->cfg !=3D dev->cfg_pending); + __netdev_free_config(dev->cfg); +} + +int netdev_reconfig_start(struct net_device *dev) +{ + struct netdev_config *cfg; + + WARN_ON(dev->cfg !=3D dev->cfg_pending); + cfg =3D kmemdup(dev->cfg, sizeof(*dev->cfg), GFP_KERNEL_ACCOUNT); + if (!cfg) + return -ENOMEM; + + dev->cfg_pending =3D cfg; + return 0; +} + static int netdev_nop_validate_qcfg(struct net_device *dev, struct netdev_queue_config *qcfg, struct netlink_ext_ack *extack) diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 1af395b54330..383e911f50f7 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -11,6 +11,8 @@ #include "module_fw.h" #include "netlink.h" =20 +#include "../core/dev.h" + static struct genl_family ethtool_genl_family; =20 static bool ethnl_ok __read_mostly; @@ -934,12 +936,9 @@ static int ethnl_default_set_doit(struct sk_buff *skb,= struct genl_info *info) if (need_rtnl) rtnl_lock(); netdev_lock_ops(dev); - dev->cfg_pending =3D kmemdup(dev->cfg, sizeof(*dev->cfg), - GFP_KERNEL_ACCOUNT); - if (!dev->cfg_pending) { - ret =3D -ENOMEM; - goto out_tie_cfg; - } + ret =3D netdev_reconfig_start(dev); + if (ret) + goto out_unlock; =20 ret =3D ethnl_ops_begin(dev); if (ret < 0) @@ -958,9 +957,9 @@ static int ethnl_default_set_doit(struct sk_buff *skb, = struct genl_info *info) out_ops: ethnl_ops_complete(dev); out_free_cfg: - kfree(dev->cfg_pending); -out_tie_cfg: + __netdev_free_config(dev->cfg_pending); dev->cfg_pending =3D dev->cfg; +out_unlock: netdev_unlock_ops(dev); if (need_rtnl) rtnl_unlock(); --=20 2.55.0 From nobody Fri Sep 25 16:02:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC044478E57; Fri, 25 Sep 2026 10:44:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790333079; cv=none; b=m/eQZGAtlH+ETKQcCCyY+DZyzZbcIiC0unsHMomSnLjGH0OHwm8IgTc0yWGctxrdePPtm6F/G3FyiN+Uuxk1L08rXQDM/szH3ugab4S2EsQbNBndXn+IaYZoH6B3rcfa8k7Sx1c93t1mW0n+trw3yzgTqHfaFdQO2l+5Wq0MZxs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790333079; c=relaxed/simple; bh=ucAkxgh3DJzOzWNeLTYB05ZB9/DJrjFiLA8e/+cr4lk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=GAOlaYdRUTGwCpVHPgizBQd7avPkWTdv4pYOea8qjJ8kvG1Rm33d+5on/ujrboqmFijdv3QDcqrAvTBQn8hyyzTBwnx77juVgOSq8w38zmWO2u4uWhm6XS53wCDdHb2cXoXTHXG9Zkjy0yptH8oF1zr7VGDnssiPUoo3igMAUY8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ihFGON+5; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ihFGON+5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9D7661F000FF; Fri, 25 Sep 2026 10:44:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790333077; bh=rRf0/go5i3thyarbdT7//grfOcOQ/yWyuJboNkE1+pQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ihFGON+5QILd/bAbGhzNhmjYeaiGmudSe6Y8kJO+7ZBEqA67n5FQjgrpBIRFx97nc P9mCCDDsCX3hmJWIkPOuMYVTIYzCczHZpCKtqvIzb9AGJSPhA+oeF6d4qPqzj7G9J3 eo6VnpVI1MSBuvzoRDjtZNQAeA5txnRty8243W/FPendptQg3YsnuKnI9COFoI7kCz F4UK1qRH35gcKV40gryEGwi+yos73fmV0QSgfoQSRcT75bDnuSp/K24TZa4037x3VG zmp3VLHj/IiAurFH3ZRQYtagqFw/v1KhRHPhsl9QJ9nwKrh+els+rprzEudcfXvwio Fu8RrF+aDpXTw== From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= To: Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Daniel Borkmann Cc: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= , "Mike Marciniszyn (Meta)" , Mohsin Bashir , Stanislav Fomichev , Bobby Eshleman , Dimitri Daskalakis , Weiming Shi , Maxime Chevallier , Jacob Keller , Breno Leitao , Tao Cui , Pavel Begunkov , David Wei Subject: [PATCH net-next v4 2/5] fbnic: Track BDQ device-page geometry per ring Date: Fri, 25 Sep 2026 12:44:09 +0200 Message-ID: <20260925104417.2325213-3-bjorn@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260925104417.2325213-1-bjorn@kernel.org> References: <20260925104417.2325213-1-bjorn@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable fbnic derives the BDQ buffer layout from PAGE_SIZE. That decides at build time how a posted page is split into 4 KiB device pages, and uses the same completion decoding for HPQ and PPQ. That is wrong once the queues use different posted-page sizes; completions must be decoded with the geometry of the queue that produced them. Keep PAGE_SIZE as the posted-page size for both queues in this change, so the descriptor format and runtime behavior stay unchanged. Signed-off-by: Bj=C3=B6rn T=C3=B6pel Reviewed-by: Breno Leitao --- drivers/net/ethernet/meta/fbnic/fbnic_csr.h | 34 ++------ .../net/ethernet/meta/fbnic/fbnic_debugfs.c | 5 +- drivers/net/ethernet/meta/fbnic/fbnic_txrx.c | 83 ++++++++++++------- drivers/net/ethernet/meta/fbnic/fbnic_txrx.h | 6 ++ 4 files changed, 72 insertions(+), 56 deletions(-) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h b/drivers/net/ethe= rnet/meta/fbnic/fbnic_csr.h index baba3471bf5a..cbb25d11638c 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h @@ -109,34 +109,19 @@ enum { =20 /* Rx Buffer Descriptor Format * - * The layout of this can vary depending on the page size of the system. + * Buffer descriptors describe 4 KiB device pages. A posted page larger th= an + * 4 KiB is represented by consecutive device-page descriptors. * - * If the page size is 4K then the layout will simply consist of ID for - * the 16 most significant bits, and the lower 46 are essentially the page - * address with the lowest 12 bits being reserved 0 due to the fact that - * a page will be aligned. - * - * If the page size is larger than 4K then the lower n bits of the ID and - * page address will be reserved for the fragment ID. This fragment will - * be 4K in size and will be used to index both the DMA address and the ID - * by the same amount. + * The address field stores the 4 KiB-aligned DMA address. The ID field st= ores + * the software page ID, with the low n bits used as the device-page ID wh= en a + * posted page spans multiple device pages. The driver increments both the + * address and ID by one device page for each descriptor belonging to a po= sted + * page. */ #define FBNIC_BD_DESC_ADDR_MASK DESC_GENMASK(45, 12) #define FBNIC_BD_DESC_ID_MASK DESC_GENMASK(63, 48) -#define FBNIC_BD_FRAG_SIZE \ +#define FBNIC_BD_PAGE_SIZE \ (FBNIC_BD_DESC_ADDR_MASK & ~(FBNIC_BD_DESC_ADDR_MASK - 1)) -#define FBNIC_BD_FRAG_COUNT \ - (PAGE_SIZE / FBNIC_BD_FRAG_SIZE) -#define FBNIC_BD_FRAG_ADDR_MASK \ - (FBNIC_BD_DESC_ADDR_MASK & \ - ~(FBNIC_BD_DESC_ADDR_MASK * FBNIC_BD_FRAG_COUNT)) -#define FBNIC_BD_FRAG_ID_MASK \ - (FBNIC_BD_DESC_ID_MASK & \ - ~(FBNIC_BD_DESC_ID_MASK * FBNIC_BD_FRAG_COUNT)) -#define FBNIC_BD_PAGE_ADDR_MASK \ - (FBNIC_BD_DESC_ADDR_MASK & ~FBNIC_BD_FRAG_ADDR_MASK) -#define FBNIC_BD_PAGE_ID_MASK \ - (FBNIC_BD_DESC_ID_MASK & ~FBNIC_BD_FRAG_ID_MASK) =20 /* Rx Completion Queue Descriptors */ #define FBNIC_RCD_TYPE_MASK DESC_GENMASK(62, 61) @@ -151,9 +136,6 @@ enum { =20 /* Address/Length Completion Descriptors */ #define FBNIC_RCD_AL_BUFF_ID_MASK DESC_GENMASK(15, 0) -#define FBNIC_RCD_AL_BUFF_FRAG_MASK (FBNIC_BD_FRAG_COUNT - 1) -#define FBNIC_RCD_AL_BUFF_PAGE_MASK \ - (FBNIC_RCD_AL_BUFF_ID_MASK & ~FBNIC_RCD_AL_BUFF_FRAG_MASK) #define FBNIC_RCD_AL_BUFF_LEN_MASK DESC_GENMASK(28, 16) #define FBNIC_RCD_AL_BUFF_OFF_MASK DESC_GENMASK(43, 32) #define FBNIC_RCD_AL_PAGE_FIN DESC_BIT(60) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_debugfs.c b/drivers/net/= ethernet/meta/fbnic/fbnic_debugfs.c index 6edfa0aa69f1..f9e879be254d 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_debugfs.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_debugfs.c @@ -181,8 +181,8 @@ static int fbnic_dbg_tcq_desc_seq_show(struct seq_file = *s, void *v) static int fbnic_dbg_bdq_desc_seq_show(struct seq_file *s, void *v) { struct fbnic_ring *ring =3D s->private; + unsigned int i, desc_count; char hdr[80]; - int i; =20 /* Generate header on first entry */ fbnic_dbg_ring_show(s); @@ -197,7 +197,8 @@ static int fbnic_dbg_bdq_desc_seq_show(struct seq_file = *s, void *v) return 0; } =20 - for (i =3D 0; i < (ring->size_mask + 1) * FBNIC_BD_FRAG_COUNT; i++) { + desc_count =3D (ring->size_mask + 1) * fbnic_bd_page_count(ring); + for (i =3D 0; i < desc_count; i++) { u64 bd =3D le64_to_cpu(ring->desc[i]); =20 seq_printf(s, "%04x %#04llx %#014llx\n", i, diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/eth= ernet/meta/fbnic/fbnic_txrx.c index b41ff7c88a0a..6b24733dc606 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c @@ -896,19 +896,31 @@ static void fbnic_clean_bdq(struct fbnic_ring *ring, = unsigned int hw_head, ring->head =3D head; } =20 +static u16 fbnic_rcd_bd_idx(const struct fbnic_ring *bdq, u64 rcd) +{ + return FIELD_GET(FBNIC_RCD_AL_BUFF_ID_MASK, rcd) >> bdq->bd_page_shift; +} + +static unsigned int fbnic_rcd_bd_page_offset(const struct fbnic_ring *bdq, + u64 rcd) +{ + u16 id =3D FIELD_GET(FBNIC_RCD_AL_BUFF_ID_MASK, rcd); + u16 page_id =3D id & (fbnic_bd_page_count(bdq) - 1); + + return page_id * FBNIC_BD_PAGE_SIZE; +} + static void fbnic_bd_prep(struct fbnic_ring *bdq, u16 id, netmem_ref netme= m) { - __le64 *bdq_desc =3D &bdq->desc[id * FBNIC_BD_FRAG_COUNT]; + __le64 *bdq_desc =3D &bdq->desc[id * fbnic_bd_page_count(bdq)]; dma_addr_t dma =3D page_pool_get_dma_addr_netmem(netmem); - u64 bd, i =3D FBNIC_BD_FRAG_COUNT; + u64 bd, i =3D fbnic_bd_page_count(bdq); =20 - bd =3D (FBNIC_BD_PAGE_ADDR_MASK & dma) | - FIELD_PREP(FBNIC_BD_PAGE_ID_MASK, id); + bd =3D (FBNIC_BD_DESC_ADDR_MASK & dma) | + FIELD_PREP(FBNIC_BD_DESC_ID_MASK, (u64)id << bdq->bd_page_shift); =20 - /* In the case that a page size is larger than 4K we will map a - * single page to multiple fragments. The fragments will be - * FBNIC_BD_FRAG_COUNT in size and the lower n bits will be use - * to indicate the individual fragment IDs. + /* Posted pages larger than 4 KiB use consecutive device-page IDs in + * the low bits of the software page ID. */ do { *bdq_desc =3D cpu_to_le64(bd); @@ -953,7 +965,7 @@ static void fbnic_fill_bdq(struct fbnic_ring *bdq) /* Force DMA writes to flush before writing to tail */ dma_wmb(); =20 - writel(i * FBNIC_BD_FRAG_COUNT, bdq->doorbell); + writel(i * fbnic_bd_page_count(bdq), bdq->doorbell); } } =20 @@ -984,26 +996,27 @@ static void fbnic_pkt_prepare(struct fbnic_napi_vecto= r *nv, u64 rcd, struct fbnic_pkt_buff *pkt, struct fbnic_q_triad *qt) { - unsigned int hdr_pg_idx =3D FIELD_GET(FBNIC_RCD_AL_BUFF_PAGE_MASK, rcd); unsigned int hdr_pg_off =3D FIELD_GET(FBNIC_RCD_AL_BUFF_OFF_MASK, rcd); - struct page *page =3D fbnic_page_pool_get_head(qt, hdr_pg_idx); unsigned int len =3D FIELD_GET(FBNIC_RCD_AL_BUFF_LEN_MASK, rcd); + unsigned int hdr_pg_idx =3D fbnic_rcd_bd_idx(&qt->sub0, rcd); unsigned int frame_sz, hdr_pg_start, hdr_pg_end, headroom; unsigned char *hdr_start; + struct page *page; =20 /* data_hard_start should always be NULL when this is called */ WARN_ON_ONCE(pkt->buff.data_hard_start); =20 + page =3D fbnic_page_pool_get_head(qt, hdr_pg_idx); + /* Short-cut the end calculation if we know page is fully consumed */ hdr_pg_end =3D FIELD_GET(FBNIC_RCD_AL_PAGE_FIN, rcd) ? - FBNIC_BD_FRAG_SIZE : fbnic_hdr_pg_end(hdr_pg_off, len); + FBNIC_BD_PAGE_SIZE : fbnic_hdr_pg_end(hdr_pg_off, len); hdr_pg_start =3D fbnic_hdr_pg_start(hdr_pg_off); =20 headroom =3D hdr_pg_off - hdr_pg_start + FBNIC_RX_PAD; frame_sz =3D hdr_pg_end - hdr_pg_start; xdp_init_buff(&pkt->buff, frame_sz, &qt->xdp_rxq); - hdr_pg_start +=3D (FBNIC_RCD_AL_BUFF_FRAG_MASK & rcd) * - FBNIC_BD_FRAG_SIZE; + hdr_pg_start +=3D fbnic_rcd_bd_page_offset(&qt->sub0, rcd); =20 /* Sync DMA buffer */ dma_sync_single_range_for_cpu(nv->dev, page_pool_get_dma_addr(page), @@ -1024,18 +1037,19 @@ static void fbnic_add_rx_frag(struct fbnic_napi_vec= tor *nv, u64 rcd, struct fbnic_pkt_buff *pkt, struct fbnic_q_triad *qt) { - unsigned int pg_idx =3D FIELD_GET(FBNIC_RCD_AL_BUFF_PAGE_MASK, rcd); unsigned int pg_off =3D FIELD_GET(FBNIC_RCD_AL_BUFF_OFF_MASK, rcd); unsigned int len =3D FIELD_GET(FBNIC_RCD_AL_BUFF_LEN_MASK, rcd); - netmem_ref netmem =3D fbnic_page_pool_get_data(qt, pg_idx); + unsigned int pg_idx =3D fbnic_rcd_bd_idx(&qt->sub1, rcd); unsigned int truesize; + netmem_ref netmem; bool added; =20 - truesize =3D FIELD_GET(FBNIC_RCD_AL_PAGE_FIN, rcd) ? - FBNIC_BD_FRAG_SIZE - pg_off : ALIGN(len, 128); + netmem =3D fbnic_page_pool_get_data(qt, pg_idx); =20 - pg_off +=3D (FBNIC_RCD_AL_BUFF_FRAG_MASK & rcd) * - FBNIC_BD_FRAG_SIZE; + truesize =3D FIELD_GET(FBNIC_RCD_AL_PAGE_FIN, rcd) ? + FBNIC_BD_PAGE_SIZE - pg_off : ALIGN(len, 128); + + pg_off +=3D fbnic_rcd_bd_page_offset(&qt->sub1, rcd); =20 /* Sync DMA buffer */ page_pool_dma_sync_netmem_for_cpu(qt->sub1.page_pool, netmem, @@ -1283,12 +1297,12 @@ static int fbnic_clean_rcq(struct fbnic_napi_vector= *nv, =20 switch (FIELD_GET(FBNIC_RCD_TYPE_MASK, rcd)) { case FBNIC_RCD_TYPE_HDR_AL: - head0 =3D FIELD_GET(FBNIC_RCD_AL_BUFF_PAGE_MASK, rcd); + head0 =3D fbnic_rcd_bd_idx(&qt->sub0, rcd); fbnic_pkt_prepare(nv, rcd, pkt, qt); =20 break; case FBNIC_RCD_TYPE_PAY_AL: - head1 =3D FIELD_GET(FBNIC_RCD_AL_BUFF_PAGE_MASK, rcd); + head1 =3D fbnic_rcd_bd_idx(&qt->sub1, rcd); fbnic_add_rx_frag(nv, rcd, pkt, qt); =20 break; @@ -1629,6 +1643,16 @@ fbnic_alloc_qt_page_pools(struct fbnic_net *fbn, str= uct fbnic_q_triad *qt, return PTR_ERR(pp); } =20 +static u8 fbnic_bdq_page_shift(u32 page_size) +{ + return ilog2(page_size / FBNIC_BD_PAGE_SIZE); +} + +static void fbnic_bdq_set_page_size(struct fbnic_ring *bdq, u32 page_size) +{ + bdq->bd_page_shift =3D fbnic_bdq_page_shift(page_size); +} + static void fbnic_ring_init(struct fbnic_ring *ring, u32 __iomem *doorbell, int q_idx, u8 flags) { @@ -1636,6 +1660,7 @@ static void fbnic_ring_init(struct fbnic_ring *ring, = u32 __iomem *doorbell, ring->doorbell =3D doorbell; ring->q_idx =3D q_idx; ring->flags =3D flags; + fbnic_bdq_set_page_size(ring, PAGE_SIZE); ring->deferred_head =3D -1; } =20 @@ -1920,12 +1945,12 @@ static int fbnic_alloc_rx_ring_desc(struct fbnic_ne= t *fbn, =20 switch (rxr->doorbell - fbnic_ring_csr_base(rxr)) { case FBNIC_QUEUE_BDQ_HPQ_TAIL: - rxq_size =3D fbn->hpq_size / FBNIC_BD_FRAG_COUNT; - desc_size *=3D FBNIC_BD_FRAG_COUNT; + rxq_size =3D fbn->hpq_size / fbnic_bd_page_count(rxr); + desc_size *=3D fbnic_bd_page_count(rxr); break; case FBNIC_QUEUE_BDQ_PPQ_TAIL: - rxq_size =3D fbn->ppq_size / FBNIC_BD_FRAG_COUNT; - desc_size *=3D FBNIC_BD_FRAG_COUNT; + rxq_size =3D fbn->ppq_size / fbnic_bd_page_count(rxr); + desc_size *=3D fbnic_bd_page_count(rxr); break; case FBNIC_QUEUE_RCQ_HEAD: rxq_size =3D fbn->rcq_size; @@ -2592,7 +2617,7 @@ static void fbnic_enable_bdq(struct fbnic_ring *hpq, = struct fbnic_ring *ppq) hpq->tail =3D 0; hpq->head =3D 0; =20 - log_size =3D fls(hpq->size_mask) + ilog2(FBNIC_BD_FRAG_COUNT); + log_size =3D fls(hpq->size_mask) + hpq->bd_page_shift; =20 /* Store descriptor ring address and size */ fbnic_ring_wr32(hpq, FBNIC_QUEUE_BDQ_HPQ_BAL, lower_32_bits(hpq->dma)); @@ -2604,7 +2629,7 @@ static void fbnic_enable_bdq(struct fbnic_ring *hpq, = struct fbnic_ring *ppq) if (!ppq->size_mask) goto write_ctl; =20 - log_size =3D fls(ppq->size_mask) + ilog2(FBNIC_BD_FRAG_COUNT); + log_size =3D fls(ppq->size_mask) + ppq->bd_page_shift; =20 /* Add enabling of PPQ to BDQ control */ bdq_ctl |=3D FBNIC_QUEUE_BDQ_CTL_PPQ_ENABLE; @@ -2908,8 +2933,10 @@ static int fbnic_queue_mem_alloc(struct net_device *= dev, =20 fbnic_ring_init(&qt->sub0, real->sub0.doorbell, real->sub0.q_idx, real->sub0.flags); + qt->sub0.bd_page_shift =3D real->sub0.bd_page_shift; fbnic_ring_init(&qt->sub1, real->sub1.doorbell, real->sub1.q_idx, real->sub1.flags); + qt->sub1.bd_page_shift =3D real->sub1.bd_page_shift; fbnic_ring_init(&qt->cmpl, real->cmpl.doorbell, real->cmpl.q_idx, real->cmpl.flags); =20 diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h b/drivers/net/eth= ernet/meta/fbnic/fbnic_txrx.h index 66c287a5404a..4e1852f94696 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h @@ -131,6 +131,7 @@ struct fbnic_ring { u16 size_mask; /* Size of ring in descriptors - 1 */ u8 q_idx; /* Logical netdev ring index */ u8 flags; /* Ring flags (FBNIC_RING_F_*) */ + u8 bd_page_shift; /* BDQ: ilog2(page_size / 4096) */ =20 u32 head, tail; /* Head/Tail of ring */ =20 @@ -177,6 +178,11 @@ struct fbnic_napi_vector { =20 extern const struct netdev_queue_mgmt_ops fbnic_queue_mgmt_ops; =20 +static inline u16 fbnic_bd_page_count(const struct fbnic_ring *bdq) +{ + return 1U << bdq->bd_page_shift; +} + netdev_tx_t fbnic_xmit_frame(struct sk_buff *skb, struct net_device *dev); netdev_features_t fbnic_features_check(struct sk_buff *skb, struct net_device *dev, --=20 2.55.0 From nobody Fri Sep 25 16:02:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 51B9449BD74; Fri, 25 Sep 2026 10:44:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790333085; cv=none; b=tTIlyIoh2Ii6ahHnokEd5B9BZhaalJZ6wWl30JmCVuuecwykdSbS5zn3PqRD60SwAn3b1ref2YbTlyrAogg2qWga8e9Ch9N8iT8e/Mx7pT4QbEUWi/nknSwfY5DI3WNPlPkZvYYTn9UHDbsTNYvjKIqnphBGsuwNKVa5xB+Anfs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790333085; c=relaxed/simple; bh=iG9pj2skUPsyU6b7NBpL1pv7/4ug4kNEbH0MDRK1Pec=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Hva1g+YeiT8V3f5Tp9W5H5euxx9zsPsdN36aOfmyYFBuEoh5KcBeZEbWj341x2jbpE9Qxq7XyJ8WQ6y/2R8HD+Il4CLROj8aXAVcXEWnQL4a6gn9uP+O7G4iD5X7E0CqkghTh2rw9mHIDixVWbB4NnZPd3gurkOvi2Gegbyc/jA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OFuVSrvl; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="OFuVSrvl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 055E51F00898; Fri, 25 Sep 2026 10:44:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790333082; bh=iUyPXoJpUEDluulVmxI/gLZCd5rb6XTn+DDtS0T8Ssg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=OFuVSrvlfVrFxiuJC1+ImHrcJztJ5IhV9bbwMasEzBgXT/oDPzJ//zVlMhRBPY08w fWPYLsemB21s4DVqbnSqrVSkifpaM/8/Mc6Hss2hVxd95+wZn3g/yLBA4RRHs6qPiI oKs+uo/VdoYugbgo8bsmXifppU6Hj0brgRbIHIT1BfGo/HVRBC09Rb/WRpbinxb7Im zNZ+ZzOdHGHSx8S1LzcOdWcQNIlU5H5KrSOTcMg8DH2M9Rjs9/9+Za19hpMjKLmRJd QZqkcNvZ5Dmnpp5SjrJCkDK4YLjcHqfBMWJGQbeNznIimL8lU139xE9lyfQxgFi5aD Q+f4Cq9N9DrqA== From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= To: Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Daniel Borkmann Cc: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= , "Mike Marciniszyn (Meta)" , Mohsin Bashir , Stanislav Fomichev , Bobby Eshleman , Dimitri Daskalakis , Weiming Shi , Maxime Chevallier , Jacob Keller , Breno Leitao , Tao Cui , Pavel Begunkov , David Wei Subject: [PATCH net-next v4 3/5] net: Revalidate queue config for ringparam changes Date: Fri, 25 Sep 2026 12:44:10 +0200 Message-ID: <20260925104417.2325213-4-bjorn@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260925104417.2325213-1-bjorn@kernel.org> References: <20260925104417.2325213-1-bjorn@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Memory-provider queue configuration is validated when the provider is bound. A later ethtool ring change may invalidate it because drivers can size queue memory from both ring depth and RX page size. The fbnic consumer is added in the following patch. Keep configured RX ring depths in netdev_config and stage proposed values in cfg_pending. Validate every RX queue before calling the driver. Each check validates the device defaults, then any queue memory-provider override. Commit the values only after the driver accepts them. Drivers which consume stored ring depths through queue configuration must initialize every RX depth before registering the netdev. Stored values override callback defaults, including when zero. The callback receives a rendered configuration rather than a queue ID. Validation should depend on the configuration, not queue identity. Checking defaults also covers the case where every queue has a memory-provider override. Drivers may normalize ring depths when applying them. Require the validation callback to use the same normalization. Drivers must report the applied depths through the ethtool_ringparam argument so the core records the result. Use the same transaction for ioctl and netlink. Drivers without ndo_validate_qcfg skip the new validation. Link: https://lore.kernel.org/all/20250421222827.283737-14-kuba@kernel.org/ Signed-off-by: Bj=C3=B6rn T=C3=B6pel --- include/linux/ethtool.h | 4 ++- include/net/netdev_queues.h | 56 ++++++++++++++++++++++++++++++++----- net/core/dev.h | 2 ++ net/core/netdev_config.c | 38 +++++++++++++++++++++++-- net/ethtool/common.c | 8 ++++++ net/ethtool/common.h | 2 ++ net/ethtool/ioctl.c | 24 ++++++++++++++-- net/ethtool/rings.c | 13 ++++++++- 8 files changed, 133 insertions(+), 14 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c4c9ce038611..c3a41fbd5426 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -1025,7 +1025,9 @@ struct kernel_ethtool_ts_info { * types should be set in @supported_coalesce_params. * Returns a negative error code or zero. * @get_ringparam: Report ring sizes - * @set_ringparam: Set ring sizes. Returns a negative error code or zero. + * @set_ringparam: Set ring sizes. The &struct ethtool_ringparam argument = is + * also an output; drivers which normalize requested sizes must update it + * with the applied sizes. Returns a negative error code or zero. * @get_pause_stats: Report pause frame statistics. Drivers must not zero * statistics which they don't report. The stats structure is initialized * to ETHTOOL_STAT_NOT_SET indicating driver does not report statistics. diff --git a/include/net/netdev_queues.h b/include/net/netdev_queues.h index 70c9fe9e83cc..c5335e935b7d 100644 --- a/include/net/netdev_queues.h +++ b/include/net/netdev_queues.h @@ -4,18 +4,56 @@ =20 #include =20 +/** + * struct netdev_ring_config - accepted RX ring depth configuration + * @rx_pending: Size of the regular RX ring. + * @rx_mini_pending: Size of the RX mini ring. + * @rx_jumbo_pending: Size of the RX jumbo ring. + * + * This stores only persistent configuration values. Capability fields, + * such as max ring sizes, are reported by drivers but are not part of the + * accepted configuration. + * + * These values are only used for queue-configuration validation today. + * Drivers which normalize ring sizes must update the struct ethtool_ringp= aram + * passed to set_ringparam() with the applied sizes. + */ +struct netdev_ring_config { + u32 rx_pending; + u32 rx_mini_pending; + u32 rx_jumbo_pending; +}; + /** * struct netdev_config - queue-related configuration for a netdev * @hds_thresh: HDS Threshold value. * @hds_config: HDS value from userspace. + * @rings: Accepted RX ring depths. + * + * Direct values, such as @hds_thresh and @rings, hold the accepted + * configuration and always override callback-provided defaults, including + * when zero. Drivers which use @rings for queue rendering must initialize + * every RX ring depth before registering the netdev. */ struct netdev_config { u32 hds_thresh; u8 hds_config; + + struct netdev_ring_config rings; }; =20 +/** + * struct netdev_queue_config - rendered configuration for an RX queue + * @rx_page_size: Size of one RX page-pool allocation. + * @rx_ring_size: Configured size of the regular RX ring. + * @rx_mini_ring_size: Configured size of the RX mini ring. + * @rx_jumbo_ring_size: Configured size of the RX jumbo ring. + */ struct netdev_queue_config { u32 rx_page_size; + u32 rx_ring_size; + u32 rx_mini_ring_size; + u32 rx_jumbo_ring_size; }; =20 /* See the netdev.yaml spec for definition of each statistic */ @@ -139,16 +177,20 @@ enum { * @ndo_queue_get_dma_dev: Get dma device for zero-copy operations to be u= sed * for this queue. Return NULL on error. * - * @ndo_default_qcfg: (Optional) Populate queue config struct with default= s. - * Queue config structs are passed to this helper before - * the user-requested settings are applied. + * @ndo_default_qcfg: (Optional) Populate queue config with defaults. Queue + * config structs are passed to this helper before the + * user-requested settings are applied. Ring depths from + * dev->cfg override these defaults. Drivers which consume + * them must initialize dev->cfg->rings before registering + * the netdev. * * @ndo_validate_qcfg: (Optional) Check if queue config is supported. * Called when configuration affecting a queue may be - * changing, either due to NIC-wide config, or config - * scoped to the queue at a specified index. - * When NIC-wide config is changed the callback will - * be invoked for all queues. + * changing. When NIC-wide config is changed the + * callback will be invoked for the defaults and all + * queue overrides. Drivers which normalize device-wide + * values when applying them must use the same + * normalization during validation. * * @ndo_queue_create: Create a new RX queue on a virtual device that will * be paired with a physical device's queue via leasing. diff --git a/net/core/dev.h b/net/core/dev.h index 6d8dbf556269..985396cc833a 100644 --- a/net/core/dev.h +++ b/net/core/dev.h @@ -110,6 +110,8 @@ int netdev_reconfig_start(struct net_device *dev); int netdev_queue_config_validate(struct net_device *dev, int rxq_idx, struct netdev_queue_config *qcfg, struct netlink_ext_ack *extack); +int netdev_queue_config_revalidate(struct net_device *dev, + struct netlink_ext_ack *extack); =20 bool netif_rxq_has_mp(struct net_device *dev, unsigned int rxq_idx); bool netif_rxq_is_leased(struct net_device *dev, unsigned int rxq_idx); diff --git a/net/core/netdev_config.c b/net/core/netdev_config.c index b101341e3251..1975de42a60d 100644 --- a/net/core/netdev_config.c +++ b/net/core/netdev_config.c @@ -50,6 +50,15 @@ static int netdev_nop_validate_qcfg(struct net_device *d= ev, return 0; } =20 +static void netdev_qcfg_apply_dev(struct netdev_queue_config *qcfg, + const struct netdev_config *cfg) +{ + /* Device config overrides callback-provided fallbacks. */ + qcfg->rx_ring_size =3D cfg->rings.rx_pending; + qcfg->rx_mini_ring_size =3D cfg->rings.rx_mini_pending; + qcfg->rx_jumbo_ring_size =3D cfg->rings.rx_jumbo_pending; +} + static int __netdev_queue_config(struct net_device *dev, int rxq_idx, struct netdev_queue_config *qcfg, struct netlink_ext_ack *extack, @@ -70,6 +79,7 @@ static int __netdev_queue_config(struct net_device *dev, = int rxq_idx, /* Get defaults from the driver, in case user config not set */ if (dev->queue_mgmt_ops->ndo_default_qcfg) dev->queue_mgmt_ops->ndo_default_qcfg(dev, qcfg); + netdev_qcfg_apply_dev(qcfg, dev->cfg_pending); err =3D validate_cb(dev, qcfg, extack); if (err) return err; @@ -91,9 +101,11 @@ static int __netdev_queue_config(struct net_device *dev= , int rxq_idx, * @rxq_idx: index of the queue of interest * @qcfg: queue configuration struct (output) * - * Render the configuration for a given queue. This helper should be used - * by drivers which support queue configuration to retrieve config for - * a particular queue. + * Render the configuration for a given queue. During a configuration + * transaction this includes the proposed device-wide values in + * @dev->cfg_pending; otherwise @dev->cfg_pending points to the accepted + * configuration. This helper should be used by drivers which support queue + * configuration to retrieve config for a particular queue. * * @qcfg is an output parameter and is always fully initialized by this * function. Some values may not be set by the user, drivers may either @@ -113,3 +125,23 @@ int netdev_queue_config_validate(struct net_device *de= v, int rxq_idx, { return __netdev_queue_config(dev, rxq_idx, qcfg, extack, true); } + +int netdev_queue_config_revalidate(struct net_device *dev, + struct netlink_ext_ack *extack) +{ + const struct netdev_queue_mgmt_ops *qops =3D dev->queue_mgmt_ops; + struct netdev_queue_config qcfg; + unsigned int i; + int err; + + if (!qops || !qops->ndo_validate_qcfg) + return 0; + + for (i =3D 0; i < dev->real_num_rx_queues; i++) { + err =3D netdev_queue_config_validate(dev, i, &qcfg, extack); + if (err) + return err; + } + + return 0; +} diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 23db40618fed..ed1df37090ce 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -956,6 +956,14 @@ void ethtool_ringparam_get_cfg(struct net_device *dev, kparam->hds_thresh =3D dev->cfg->hds_thresh; } =20 +void ethtool_ringparam_set_cfg(struct netdev_config *cfg, + const struct ethtool_ringparam *param) +{ + cfg->rings.rx_pending =3D param->rx_pending; + cfg->rings.rx_mini_pending =3D param->rx_mini_pending; + cfg->rings.rx_jumbo_pending =3D param->rx_jumbo_pending; +} + static void ethtool_init_tsinfo(struct kernel_ethtool_ts_info *info) { memset(info, 0, sizeof(*info)); diff --git a/net/ethtool/common.h b/net/ethtool/common.h index ae32e7fdb563..b062e99e89db 100644 --- a/net/ethtool/common.h +++ b/net/ethtool/common.h @@ -53,6 +53,8 @@ void ethtool_ringparam_get_cfg(struct net_device *dev, struct ethtool_ringparam *param, struct kernel_ethtool_ringparam *kparam, struct netlink_ext_ack *extack); +void ethtool_ringparam_set_cfg(struct netdev_config *cfg, + const struct ethtool_ringparam *param); =20 int ethtool_get_rx_ring_count(struct net_device *dev); =20 diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 4b0bc503f930..dad5a5412f48 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -35,6 +35,7 @@ #include =20 #include "common.h" +#include "../core/dev.h" =20 /* State held across locks and calls for commands which have devlink fallb= ack */ struct ethtool_devlink_compat { @@ -2239,10 +2240,29 @@ static int ethtool_set_ringparam(struct net_device = *dev, void __user *useraddr) ringparam.tx_pending > max.tx_max_pending) return -EINVAL; =20 + ret =3D netdev_reconfig_start(dev); + if (ret) + return ret; + + ethtool_ringparam_set_cfg(dev->cfg_pending, &ringparam); + + ret =3D netdev_queue_config_revalidate(dev, NULL); + if (ret) + goto out_free_cfg; + ret =3D dev->ethtool_ops->set_ringparam(dev, &ringparam, &kernel_ringparam, NULL); - if (!ret) - ethtool_notify(dev, ETHTOOL_MSG_RINGS_NTF); + if (ret) + goto out_free_cfg; + + /* Capture ring depth adjustments reported by the driver. */ + ethtool_ringparam_set_cfg(dev->cfg_pending, &ringparam); + swap(dev->cfg, dev->cfg_pending); + ethtool_notify(dev, ETHTOOL_MSG_RINGS_NTF); + +out_free_cfg: + __netdev_free_config(dev->cfg_pending); + dev->cfg_pending =3D dev->cfg; return ret; } =20 diff --git a/net/ethtool/rings.c b/net/ethtool/rings.c index 9054c89c5d7b..e3810c0320e3 100644 --- a/net/ethtool/rings.c +++ b/net/ethtool/rings.c @@ -4,6 +4,7 @@ =20 #include "common.h" #include "netlink.h" +#include "../core/dev.h" =20 struct rings_req_info { struct ethnl_req_info base; @@ -299,10 +300,20 @@ ethnl_set_rings(struct ethnl_req_info *req_info, stru= ct genl_info *info) =20 dev->cfg_pending->hds_config =3D kernel_ringparam.tcp_data_split; dev->cfg_pending->hds_thresh =3D kernel_ringparam.hds_thresh; + ethtool_ringparam_set_cfg(dev->cfg_pending, &ringparam); + + ret =3D netdev_queue_config_revalidate(dev, info->extack); + if (ret) + return ret; =20 ret =3D dev->ethtool_ops->set_ringparam(dev, &ringparam, &kernel_ringparam, info->extack); - return ret < 0 ? ret : 1; + if (ret < 0) + return ret; + + /* Capture ring depth adjustments reported by the driver. */ + ethtool_ringparam_set_cfg(dev->cfg_pending, &ringparam); + return 1; } =20 const struct ethnl_request_ops ethnl_rings_request_ops =3D { --=20 2.55.0 From nobody Fri Sep 25 16:02:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 89619478E57; Fri, 25 Sep 2026 10:44:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790333090; cv=none; b=PIjzItqO8/Sv/lRAjFX5Z2OWuOv21vDjKlNXM9jVF4KXer207MWxqCui443Aji27sFwg7tRWJj19UqwUK3DLdB2O/v6NCpOM9euoJjUwvN1lXSrCXh2dlYA6P18p0OhuMXPbwvwserp6P26LcaWyKA72OmCul/E5Am2KCkJCF2k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790333090; c=relaxed/simple; bh=bukgcmFxRyIa940oVf187GQS0N05+B2vpYir7skAgZ0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Hh0geSIXQL2QxfXCCrjZVLjsv9PVJr3I9KBqiMDyY3jOrALkUZdWkmcbudEVc3AVpWgElMvB/ZBolMtJM7ZHJ0b0n7EDcOMw+FxvlmsS9HeYBriiDzFiKX7L4dVqo4CNrQW7og9NQGmNle/oCbnRGzAD1pCuKT3PmY60uwNmyt8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YlKsSUwn; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YlKsSUwn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 61B481F0089B; Fri, 25 Sep 2026 10:44:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790333088; bh=G2cKGKDFcn8sSbsEWzEh734s0pO8SbN++gWyiRJld6c=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=YlKsSUwnbrjEWsTpBi6VHc9Uh504JhZHB2Ex8OMk/I4a6N0ZzStlU0fCfhbbb4JsN +zHyUDYQLeLlitBbIjF8PDnhXNJvy1OhxzawslHf3UIzhH78o/zkotiQGXZBVit49+ RIeGuc3BdJ9aEDaeJofujmWJ+KTV5XyOTO/FLq2XCNTOYYH4ns5dLHYw+JhgLTnuoo eBM/dERPElXRrMc3AWFPXPLkkfuaMSZwCqo+hPwIGfSXh/gi1YBpPrhH6gPIFqRCKu WzvuMcjK99+F8OkYhdOy9+tP0ai18C2nzTBMeng2ZiLrWaaRrqmQRnXEG5T/oHZQdf rmpCmOQy82/gg== From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= To: Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Daniel Borkmann Cc: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= , "Mike Marciniszyn (Meta)" , Mohsin Bashir , Stanislav Fomichev , Bobby Eshleman , Dimitri Daskalakis , Weiming Shi , Maxime Chevallier , Jacob Keller , Breno Leitao , Tao Cui , Pavel Begunkov , David Wei Subject: [PATCH net-next v4 4/5] fbnic: Support larger memory-provider RX pages Date: Fri, 25 Sep 2026 12:44:11 +0200 Message-ID: <20260925104417.2325213-5-bjorn@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260925104417.2325213-1-bjorn@kernel.org> References: <20260925104417.2325213-1-bjorn@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Memory providers can set the receive page size for a queue through QCFG_RX_PAGE_SIZE. fbnic creates PAGE_SIZE PPQ page-pool allocations, so larger rx_buf_len values are not reflected in the PPQ BDQ geometry. Use the rendered rx_page_size for PPQ allocations and completion decoding. The NIC still consumes 4 KiB device pages; a larger PPQ page is represented by consecutive device-page descriptors, and completion IDs decode to offsets within the same netmem allocation. Validate rx_page_size against fbnic's fragment-reference budget, device-page geometry, and rendered PPQ depth. The page size must be a power-of-two of at least one device page, its worst-case payload fragment count must fit the page-pool reference bias, and the PPQ must retain usable software depth after expansion. Signed-off-by: Bj=C3=B6rn T=C3=B6pel --- .../net/ethernet/meta/fbnic/fbnic_netdev.c | 4 + drivers/net/ethernet/meta/fbnic/fbnic_txrx.c | 96 +++++++++++++++++-- drivers/net/ethernet/meta/fbnic/fbnic_txrx.h | 1 + 3 files changed, 92 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/e= thernet/meta/fbnic/fbnic_netdev.c index 10bf99be3f24..8a6703afca38 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c @@ -773,6 +773,10 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev= *fbd) fbn->ppq_size =3D FBNIC_PPQ_SIZE_DEFAULT; fbn->rcq_size =3D FBNIC_RCQ_SIZE_DEFAULT; =20 + netdev->cfg->rings.rx_pending =3D fbn->rcq_size; + netdev->cfg->rings.rx_mini_pending =3D fbn->hpq_size; + netdev->cfg->rings.rx_jumbo_pending =3D fbn->ppq_size; + fbn->tx_usecs =3D FBNIC_TX_USECS_DEFAULT; fbn->rx_usecs =3D FBNIC_RX_USECS_DEFAULT; fbn->rx_max_frames =3D FBNIC_RX_FRAMES_DEFAULT; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/eth= ernet/meta/fbnic/fbnic_txrx.c index 6b24733dc606..c62d885a678a 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c @@ -1047,7 +1047,8 @@ static void fbnic_add_rx_frag(struct fbnic_napi_vecto= r *nv, u64 rcd, netmem =3D fbnic_page_pool_get_data(qt, pg_idx); =20 truesize =3D FIELD_GET(FBNIC_RCD_AL_PAGE_FIN, rcd) ? - FBNIC_BD_PAGE_SIZE - pg_off : ALIGN(len, 128); + FBNIC_BD_PAGE_SIZE - pg_off : + ALIGN(len, FBNIC_RX_PAYLD_ALIGN); =20 pg_off +=3D fbnic_rcd_bd_page_offset(&qt->sub1, rcd); =20 @@ -1055,6 +1056,9 @@ static void fbnic_add_rx_frag(struct fbnic_napi_vecto= r *nv, u64 rcd, page_pool_dma_sync_netmem_for_cpu(qt->sub1.page_pool, netmem, pg_off, truesize); =20 + /* Consecutive device-page completions from one PPQ page are adjacent + * ranges in the same netmem. + */ added =3D xdp_buff_add_frag(&pkt->buff, netmem, pg_off, len, truesize); if (unlikely(!added)) { pkt->add_frag_failed =3D true; @@ -1590,7 +1594,7 @@ void fbnic_free_napi_vectors(struct fbnic_net *fbn) =20 static int fbnic_alloc_qt_page_pools(struct fbnic_net *fbn, struct fbnic_q_triad *qt, - unsigned int rxq_idx) + unsigned int rxq_idx, u32 rx_page_size) { struct page_pool_params pp_params =3D { .order =3D 0, @@ -1625,6 +1629,8 @@ fbnic_alloc_qt_page_pools(struct fbnic_net *fbn, stru= ct fbnic_q_triad *qt, =20 qt->sub0.page_pool =3D pp; if (netif_rxq_has_unreadable_mp(fbn->netdev, rxq_idx)) { + pp_params.order =3D get_order(rx_page_size); + pp_params.max_len =3D rx_page_size; pp_params.flags |=3D PP_FLAG_ALLOW_UNREADABLE_NETMEM; pp_params.dma_dir =3D DMA_FROM_DEVICE; =20 @@ -2054,15 +2060,18 @@ static int fbnic_alloc_tx_qt_resources(struct fbnic= _net *fbn, =20 static int fbnic_alloc_rx_qt_resources(struct fbnic_net *fbn, struct fbnic_napi_vector *nv, - struct fbnic_q_triad *qt) + struct fbnic_q_triad *qt, + u32 rx_page_size) { struct device *dev =3D fbn->netdev->dev.parent; int err; =20 - err =3D fbnic_alloc_qt_page_pools(fbn, qt, qt->cmpl.q_idx); + err =3D fbnic_alloc_qt_page_pools(fbn, qt, qt->cmpl.q_idx, rx_page_size); if (err) return err; =20 + fbnic_bdq_set_page_size(&qt->sub1, rx_page_size); + err =3D xdp_rxq_info_reg(&qt->xdp_rxq, fbn->netdev, qt->sub0.q_idx, nv->napi.napi_id); if (err) @@ -2123,7 +2132,11 @@ static int fbnic_alloc_nv_resources(struct fbnic_net= *fbn, =20 /* Allocate Rx Resources */ for (j =3D 0; j < nv->rxt_count; j++, i++) { - err =3D fbnic_alloc_rx_qt_resources(fbn, nv, &nv->qt[i]); + struct netdev_queue_config qcfg; + + netdev_queue_config(fbn->netdev, nv->qt[i].cmpl.q_idx, &qcfg); + err =3D fbnic_alloc_rx_qt_resources(fbn, nv, &nv->qt[i], + qcfg.rx_page_size); if (err) goto free_qt_resources; } @@ -2918,7 +2931,8 @@ static int fbnic_queue_mem_alloc(struct net_device *d= ev, struct fbnic_napi_vector *nv; =20 if (!netif_running(dev)) - return fbnic_alloc_qt_page_pools(fbn, qt, idx); + return fbnic_alloc_qt_page_pools(fbn, qt, idx, + qcfg->rx_page_size); =20 /* A failed PCIe recovery or resume can leave the datapath torn down * while netif_running() is still true. This ndo runs before @@ -2933,14 +2947,75 @@ static int fbnic_queue_mem_alloc(struct net_device = *dev, =20 fbnic_ring_init(&qt->sub0, real->sub0.doorbell, real->sub0.q_idx, real->sub0.flags); - qt->sub0.bd_page_shift =3D real->sub0.bd_page_shift; fbnic_ring_init(&qt->sub1, real->sub1.doorbell, real->sub1.q_idx, real->sub1.flags); - qt->sub1.bd_page_shift =3D real->sub1.bd_page_shift; fbnic_ring_init(&qt->cmpl, real->cmpl.doorbell, real->cmpl.q_idx, real->cmpl.flags); =20 - return fbnic_alloc_rx_qt_resources(fbn, nv, qt); + return fbnic_alloc_rx_qt_resources(fbn, nv, qt, qcfg->rx_page_size); +} + +static void fbnic_default_qcfg(struct net_device *dev, + struct netdev_queue_config *qcfg) +{ + qcfg->rx_page_size =3D PAGE_SIZE; +} + +static int fbnic_validate_qcfg(struct net_device *dev, + struct netdev_queue_config *qcfg, + struct netlink_ext_ack *extack) +{ + u32 bd_page_count, ppq_entries, frag_count; + u32 rx_page_size =3D qcfg->rx_page_size; + u32 ppq_size; + + if (!qcfg->rx_jumbo_ring_size) { + NL_SET_ERR_MSG_MOD(extack, + "rx-jumbo ring size must be nonzero"); + return -EINVAL; + } + + ppq_size =3D roundup_pow_of_two(qcfg->rx_jumbo_ring_size); + + if (!is_power_of_2(rx_page_size)) { + NL_SET_ERR_MSG_MOD(extack, + "rx_page_size must be a power of 2"); + return -EINVAL; + } + + if (rx_page_size < FBNIC_BD_PAGE_SIZE) { + NL_SET_ERR_MSG_MOD(extack, + "rx_page_size must be at least 4K"); + return -EINVAL; + } + + /* Payload fragments occupy multiples of FBNIC_RX_PAYLD_ALIGN bytes. + * Keep at least one reference in the bias until fbnic_clean_bdq() + * observes a completion from a subsequent allocation. + */ + frag_count =3D rx_page_size / FBNIC_RX_PAYLD_ALIGN; + if (frag_count >=3D FBNIC_PAGECNT_BIAS_MAX) { + NL_SET_ERR_MSG_MOD(extack, + "rx_page_size can produce too many fragments"); + return -EINVAL; + } + + bd_page_count =3D rx_page_size / FBNIC_BD_PAGE_SIZE; + ppq_entries =3D ppq_size / bd_page_count; + /* The PPQ is sized in 4 KiB device pages. One software entry tracks + * each page-pool allocation. In addition to the unused entry for + * empty/full accounting, cleanup retains the current allocation + * until a completion identifies a subsequent allocation. A two-entry + * ring can only post one allocation and cannot make progress. + * Require at least four entries, since ring sizes are powers of two. + */ + if (ppq_entries < 4) { + NL_SET_ERR_MSG_MOD(extack, + "rx-jumbo ring size too small for rx_page_size"); + return -EINVAL; + } + + return 0; } =20 static void fbnic_queue_mem_free(struct net_device *dev, void *qmem) @@ -3042,4 +3117,7 @@ const struct netdev_queue_mgmt_ops fbnic_queue_mgmt_o= ps =3D { .ndo_queue_mem_free =3D fbnic_queue_mem_free, .ndo_queue_start =3D fbnic_queue_start, .ndo_queue_stop =3D fbnic_queue_stop, + .ndo_default_qcfg =3D fbnic_default_qcfg, + .ndo_validate_qcfg =3D fbnic_validate_qcfg, + .supported_params =3D QCFG_RX_PAGE_SIZE, }; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h b/drivers/net/eth= ernet/meta/fbnic/fbnic_txrx.h index 4e1852f94696..6ee3cce3d942 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h @@ -65,6 +65,7 @@ struct fbnic_net; #define FBNIC_RX_HROOM \ (ALIGN(FBNIC_RX_TROOM + FBNIC_RX_HROOM_PAD, 128) - FBNIC_RX_TROOM) #define FBNIC_RX_PAD 0 +#define FBNIC_RX_PAYLD_ALIGN 128 #define FBNIC_RX_PAYLD_OFFSET 0 #define FBNIC_RX_PAYLD_PG_CL 0 =20 --=20 2.55.0 From nobody Fri Sep 25 16:02:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E53EE49B5CD; Fri, 25 Sep 2026 10:44:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790333095; cv=none; b=sVkrZa6pbvCAu9znDzSQHhMhKcQ39bI15vQJeRDkVUOqG6N+NpFLQOg58ZpeMLtlabArHI0REDq61kKij5IQWPFyYAiil0wTNiquDRepPlQ/22V91/VXWKnQNaxNxkR5LVTvvOTSxdOwt7SribtRdsHIMCH/gA/mKCcNsLOajRk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790333095; c=relaxed/simple; bh=qXEOEIA2jN/P8gXV5Njt3pBToPrw4adpGj9iLkIM/BI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ub7aXLQ7rKPDEahffuwEDizIbYFAcd4Jd3YQYT1XtpHTzbxm/mYQN6D9DvHZSNRuzLofkQQEh27Yfl8iUHSoRIclsklKpJ4jAz0k5eDMVhvqsojsZgoRXxJU5l8GWe1GagsqO6MDCo9BgVUSFHwb4p064H/uvIug5fE3BEfg4iU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YsthqgIx; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YsthqgIx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BD8441F000FF; Fri, 25 Sep 2026 10:44:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790333093; bh=bleqDftiMRX6Ent78Vjw7qsXiSNenO0yuWkNjJTX5qs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=YsthqgIxKB1L4nya2S52A9yDGKyQscnFVpgu11Kx8HaC2dVTuypl1jjO6aS97DOoQ bEFZ1s/z426iKPfHW9UB7cvoPTP/qyEbFJjha0jSKhUILyBkFyMUrb7tiuGOFkaHtU yvbrXIJQbe8bXOT9GPkjTt6zNFBnI+ZQS59gKVFepWk5+srXt/k3NI+qmmLcxqPzE2 Z0tlbeTfDGlnAl5nfM2dkrMd2e9v9pJlHtmaXiU7FLr37VsOfdI/2n2lven6yRjiPB EbdlYxK5tQducoLuRN1+svRuoHlIcwzaUV6vcJ/Y2t3Vx6O1tYsSDxPjs7zdWmVWMq USu/lT6gGqsag== From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= To: Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Daniel Borkmann Cc: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= , "Mike Marciniszyn (Meta)" , Mohsin Bashir , Stanislav Fomichev , Bobby Eshleman , Dimitri Daskalakis , Weiming Shi , Maxime Chevallier , Jacob Keller , Breno Leitao , Tao Cui , Pavel Begunkov , David Wei Subject: [PATCH net-next v4 5/5] selftests: drv-net: Request larger zcrx buffers Date: Fri, 25 Sep 2026 12:44:12 +0200 Message-ID: <20260925104417.2325213-6-bjorn@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260925104417.2325213-1-bjorn@kernel.org> References: <20260925104417.2325213-1-bjorn@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The large-chunk test always requests two base pages. On interfaces with a large MTU, that may not exceed two maximum-sized frames. Request a power-of-two buffer larger than twice the MTU. This makes the existing rx_buf_len check and data-integrity traffic exercise the larger layout. Signed-off-by: Bj=C3=B6rn T=C3=B6pel Tested-by: Breno Leitao --- tools/testing/selftests/drivers/net/hw/iou-zcrx.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/drivers/net/hw/iou-zcrx.py b/tools/tes= ting/selftests/drivers/net/hw/iou-zcrx.py index c833535d8a03..5047fdb56005 100755 --- a/tools/testing/selftests/drivers/net/hw/iou-zcrx.py +++ b/tools/testing/selftests/drivers/net/hw/iou-zcrx.py @@ -221,9 +221,13 @@ def test_zcrx_large_chunks(cfg) -> None: =20 single(cfg) page_size =3D resource.getpagesize() + mtu =3D cfg.dev["mtu"] nr_pages =3D 2 + while nr_pages * page_size <=3D 2 * mtu: + nr_pages *=3D 2 rx_buf_len =3D nr_pages * page_size - rx_cmd =3D f"{cfg.bin_local} -s -p {cfg.port} -i {cfg.ifname} -q {cfg.= target} -x {nr_pages}" + rx_cmd =3D (f"{cfg.bin_local} -s -p {cfg.port} -i {cfg.ifname} " + f"-q {cfg.target} -x {nr_pages}") tx_cmd =3D f"{cfg.bin_remote} -c -h {cfg.addr_v['6']} -p {cfg.port} -l= 12840" =20 probe =3D cmd(rx_cmd + " -d", fail=3DFalse) --=20 2.55.0