Netdev List
 help / color / mirror / Atom feed
* [PATCH net 3/7] sfc: add cxl support
From: alejandro.lucero-palau @ 2026-07-01 11:38 UTC (permalink / raw)
  To: netdev, kuba, davem, edumazet, pabeni, horms, dave.jiang
  Cc: Alejandro Lucero, Jonathan Cameron, Edward Cree, Alison Schofield,
	Dan Williams
In-Reply-To: <20260701113805.14072-1-alejandro.lucero-palau@amd.com>

From: Alejandro Lucero <alucerop@amd.com>

Add CXL initialization based on new CXL API for accel drivers and make
it dependent on kernel CXL configuration.

Signed-off-by: Alejandro Lucero <alucerop@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Acked-by: Edward Cree <ecree.xilinx@gmail.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Link: https://patch.msgid.link/20260630151346.31201-2-alejandro.lucero-palau@amd.com
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 drivers/net/ethernet/sfc/Kconfig      |  9 +++++
 drivers/net/ethernet/sfc/Makefile     |  1 +
 drivers/net/ethernet/sfc/efx.c        | 16 ++++++++-
 drivers/net/ethernet/sfc/efx_cxl.c    | 50 +++++++++++++++++++++++++++
 drivers/net/ethernet/sfc/efx_cxl.h    | 29 ++++++++++++++++
 drivers/net/ethernet/sfc/net_driver.h |  8 +++++
 6 files changed, 112 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/sfc/efx_cxl.c
 create mode 100644 drivers/net/ethernet/sfc/efx_cxl.h

diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index c4c43434f314..979f2801e2a8 100644
--- a/drivers/net/ethernet/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -66,6 +66,15 @@ config SFC_MCDI_LOGGING
 	  Driver-Interface) commands and responses, allowing debugging of
 	  driver/firmware interaction.  The tracing is actually enabled by
 	  a sysfs file 'mcdi_logging' under the PCI device.
+config SFC_CXL
+	bool "Solarflare SFC9100-family CXL support"
+	depends on SFC && CXL_BUS >= SFC
+	default SFC
+	help
+	  This enables SFC CXL support if the kernel is configuring CXL for
+	  using CTPIO with CXL.mem. The SFC device with CXL support and
+	  with a CXL-aware firmware can be used for minimizing latencies
+	  when sending through CTPIO.
 
 source "drivers/net/ethernet/sfc/falcon/Kconfig"
 source "drivers/net/ethernet/sfc/siena/Kconfig"
diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index d99039ec468d..bb0f1891cde6 100644
--- a/drivers/net/ethernet/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
@@ -13,6 +13,7 @@ sfc-$(CONFIG_SFC_SRIOV)	+= sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \
                            mae.o tc.o tc_bindings.o tc_counters.o \
                            tc_encap_actions.o tc_conntrack.o
 
+sfc-$(CONFIG_SFC_CXL)	+= efx_cxl.o
 obj-$(CONFIG_SFC)	+= sfc.o
 
 obj-$(CONFIG_SFC_FALCON) += falcon/
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 8f136a11d396..61cbb6cfc360 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -34,6 +34,7 @@
 #include "selftest.h"
 #include "sriov.h"
 #include "efx_devlink.h"
+#include "efx_cxl.h"
 
 #include "mcdi_port_common.h"
 #include "mcdi_pcol.h"
@@ -981,12 +982,14 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
 	efx_pci_remove_main(efx);
 
 	efx_fini_io(efx);
+
+	probe_data = container_of(efx, struct efx_probe_data, efx);
+
 	pci_dbg(efx->pci_dev, "shutdown successful\n");
 
 	efx_fini_devlink_and_unlock(efx);
 	efx_fini_struct(efx);
 	free_netdev(efx->net_dev);
-	probe_data = container_of(efx, struct efx_probe_data, efx);
 	kfree(probe_data);
 };
 
@@ -1190,6 +1193,17 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
 	if (rc)
 		goto fail2;
 
+	/* A successful cxl initialization implies a CXL region created to be
+	 * used for PIO buffers. If there is no CXL support legacy PIO buffers
+	 * defined at specific PCI BAR regions will be used. If there is CXL
+	 * support and the cxl initialization fails, the driver probe fails.
+	 */
+	rc = efx_cxl_init(probe_data);
+	if (rc) {
+		pci_err(pci_dev, "CXL initialization failed with error %d\n", rc);
+		goto fail3;
+	}
+
 	rc = efx_pci_probe_post_io(efx);
 	if (rc) {
 		/* On failure, retry once immediately.
diff --git a/drivers/net/ethernet/sfc/efx_cxl.c b/drivers/net/ethernet/sfc/efx_cxl.c
new file mode 100644
index 000000000000..be252af972ab
--- /dev/null
+++ b/drivers/net/ethernet/sfc/efx_cxl.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/****************************************************************************
+ *
+ * Driver for AMD network controllers and boards
+ * Copyright (C) 2025, Advanced Micro Devices, Inc.
+ */
+
+#include <linux/pci.h>
+
+#include "net_driver.h"
+#include "efx_cxl.h"
+
+#define EFX_CTPIO_BUFFER_SIZE	SZ_256M
+
+int efx_cxl_init(struct efx_probe_data *probe_data)
+{
+	struct efx_nic *efx = &probe_data->efx;
+	struct pci_dev *pci_dev = efx->pci_dev;
+	struct efx_cxl *cxl;
+	u16 dvsec;
+
+	/* Is the device configured with and using CXL? */
+	if (!pcie_is_cxl(pci_dev))
+		return 0;
+
+	dvsec = pci_find_dvsec_capability(pci_dev, PCI_VENDOR_ID_CXL,
+					  PCI_DVSEC_CXL_DEVICE);
+	if (!dvsec) {
+		pci_info(pci_dev, "CXL_DVSEC_PCIE_DEVICE capability not found\n");
+		return 0;
+	}
+
+	pci_dbg(pci_dev, "CXL_DVSEC_PCIE_DEVICE capability found\n");
+
+	/* Create a cxl_dev_state embedded in the cxl struct using cxl core api
+	 * specifying no mbox available.
+	 */
+	cxl = devm_cxl_dev_state_create(&pci_dev->dev, CXL_DEVTYPE_DEVMEM,
+					pci_get_dsn(pci_dev), dvsec,
+					struct efx_cxl, cxlds, false);
+
+	if (!cxl)
+		return -ENOMEM;
+
+	probe_data->cxl = cxl;
+
+	return 0;
+}
+
+MODULE_IMPORT_NS("CXL");
diff --git a/drivers/net/ethernet/sfc/efx_cxl.h b/drivers/net/ethernet/sfc/efx_cxl.h
new file mode 100644
index 000000000000..04e46278464d
--- /dev/null
+++ b/drivers/net/ethernet/sfc/efx_cxl.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/****************************************************************************
+ * Driver for AMD network controllers and boards
+ * Copyright (C) 2025, Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EFX_CXL_H
+#define EFX_CXL_H
+
+#ifdef CONFIG_SFC_CXL
+
+#include <cxl/cxl.h>
+
+struct efx_probe_data;
+
+struct efx_cxl {
+	struct cxl_dev_state cxlds;
+	struct cxl_memdev *cxlmd;
+};
+
+int efx_cxl_init(struct efx_probe_data *probe_data);
+#else
+static inline int efx_cxl_init(struct efx_probe_data *probe_data) { return 0; }
+#endif
+#endif
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index b98c259f672d..563e6a6e85f1 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1197,14 +1197,22 @@ struct efx_nic {
 	atomic_t n_rx_noskb_drops;
 };
 
+#ifdef CONFIG_SFC_CXL
+struct efx_cxl;
+#endif
+
 /**
  * struct efx_probe_data - State after hardware probe
  * @pci_dev: The PCI device
  * @efx: Efx NIC details
+ * @cxl: details of related cxl objects
  */
 struct efx_probe_data {
 	struct pci_dev *pci_dev;
 	struct efx_nic efx;
+#ifdef CONFIG_SFC_CXL
+	struct efx_cxl *cxl;
+#endif
 };
 
 static inline struct efx_nic *efx_netdev_priv(struct net_device *dev)
-- 
2.34.1


^ permalink raw reply related

* [PATCH net 4/7] sfc: Map cxl regs
From: alejandro.lucero-palau @ 2026-07-01 11:38 UTC (permalink / raw)
  To: netdev, kuba, davem, edumazet, pabeni, horms, dave.jiang
  Cc: Alejandro Lucero, Dan Williams, Jonathan Cameron, Ben Cheatham,
	Edward Cree
In-Reply-To: <20260701113805.14072-1-alejandro.lucero-palau@amd.com>

From: Alejandro Lucero <alucerop@amd.com>

Use cxl core functions for discovering and mapping CXL device registers.

Signed-off-by: Alejandro Lucero <alucerop@amd.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Ben Cheatham <benjamin.cheatham@amd.com>
Acked-by: Edward Cree <ecree.xilinx@gmail.com>
Link: https://patch.msgid.link/20260630151346.31201-3-alejandro.lucero-palau@amd.com
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 drivers/net/ethernet/sfc/efx_cxl.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/net/ethernet/sfc/efx_cxl.c b/drivers/net/ethernet/sfc/efx_cxl.c
index be252af972ab..704b0ebae937 100644
--- a/drivers/net/ethernet/sfc/efx_cxl.c
+++ b/drivers/net/ethernet/sfc/efx_cxl.c
@@ -7,6 +7,8 @@
 
 #include <linux/pci.h>
 
+#include <cxl/cxl.h>
+#include <cxl/pci.h>
 #include "net_driver.h"
 #include "efx_cxl.h"
 
@@ -18,6 +20,7 @@ int efx_cxl_init(struct efx_probe_data *probe_data)
 	struct pci_dev *pci_dev = efx->pci_dev;
 	struct efx_cxl *cxl;
 	u16 dvsec;
+	int rc;
 
 	/* Is the device configured with and using CXL? */
 	if (!pcie_is_cxl(pci_dev))
@@ -42,6 +45,29 @@ int efx_cxl_init(struct efx_probe_data *probe_data)
 	if (!cxl)
 		return -ENOMEM;
 
+	rc = cxl_pci_setup_regs(pci_dev, CXL_REGLOC_RBI_COMPONENT,
+				&cxl->cxlds.reg_map);
+	if (rc) {
+		pci_err(pci_dev, "No component registers\n");
+		return rc;
+	}
+
+	if (!cxl->cxlds.reg_map.component_map.hdm_decoder.valid) {
+		pci_err(pci_dev, "Expected HDM component register not found\n");
+		return -ENODEV;
+	}
+
+	if (!cxl->cxlds.reg_map.component_map.ras.valid) {
+		pci_err(pci_dev, "Expected RAS component register not found\n");
+		return -ENODEV;
+	}
+
+	/* Set media ready explicitly as there are neither mailbox for checking
+	 * this state nor the CXL register involved, both not mandatory for
+	 * type2.
+	 */
+	cxl->cxlds.media_ready = true;
+
 	probe_data->cxl = cxl;
 
 	return 0;
-- 
2.34.1


^ permalink raw reply related

* [PATCH net 0/7] pull request: sfc 2026-07-01
From: alejandro.lucero-palau @ 2026-07-01 11:37 UTC (permalink / raw)
  To: netdev, kuba, davem, edumazet, pabeni, horms, dave.jiang; +Cc: Alejandro Lucero

From: Alejandro Lucero <alucerop@amd.com>

Dear net maintainers,

here are the last CXL core changes for enabling CXL Type2 drivers to
initialize a CXL-capable device plus the netdev sfc driver changes using
this new CXL core Type2 support.

Please pull or let me know of any problem!

Thank you,
      Alejandro

The following changes since commit dc59e4fea9d83f03bad6bddf3fa2e52491777482:

  Linux 7.2-rc1 (2026-06-28 12:01:31 -0700)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl.git tags/sfc-net-pullrequest-20260630

for you to fetch changes up to bd6550bcdb0c0bcc6e29706ffe2e64708192342b:

  sfc: support pio mapping based on cxl (2026-06-30 15:24:16 -0700)

----------------------------------------------------------------

SFC changes for CXL type2 enabling

----------------------------------------------------------------

Alejandro Lucero (7):
  cxl: Support Type2 cxl regs mapping
  cxl: Support dpa without a mailbox
  sfc: add cxl support
  sfc: Map cxl regs
  sfc: Initialize cxl dpa
  sfc: obtain and map cxl range using devm_cxl_probe_mem
  sfc: support pio mapping based on cxl

 drivers/cxl/core/core.h               |   2 +
 drivers/cxl/core/mbox.c               |  51 +------------
 drivers/cxl/core/memdev.c             |  67 ++++++++++++++++
 drivers/cxl/core/pci.c                |   1 +
 drivers/cxl/core/port.c               |   1 +
 drivers/cxl/core/regs.c               |   1 +
 drivers/cxl/cxlpci.h                  |  12 ---
 drivers/cxl/pci.c                     |   1 +
 drivers/net/ethernet/sfc/Kconfig      |   9 +++
 drivers/net/ethernet/sfc/Makefile     |   1 +
 drivers/net/ethernet/sfc/ef10.c       |  41 ++++++++--
 drivers/net/ethernet/sfc/efx.c        |  18 ++++-
 drivers/net/ethernet/sfc/efx_cxl.c    | 105 ++++++++++++++++++++++++++
 drivers/net/ethernet/sfc/efx_cxl.h    |  32 ++++++++
 drivers/net/ethernet/sfc/net_driver.h |  10 +++
 drivers/net/ethernet/sfc/nic.h        |   3 +
 include/cxl/cxl.h                     |   2 +
 include/cxl/pci.h                     |  22 ++++++
 18 files changed, 309 insertions(+), 70 deletions(-)
 create mode 100644 drivers/net/ethernet/sfc/efx_cxl.c
 create mode 100644 drivers/net/ethernet/sfc/efx_cxl.h
 create mode 100644 include/cxl/pci.h

-- 
2.34.1


^ permalink raw reply

* [PATCH net 1/7] cxl: Support Type2 cxl regs mapping
From: alejandro.lucero-palau @ 2026-07-01 11:37 UTC (permalink / raw)
  To: netdev, kuba, davem, edumazet, pabeni, horms, dave.jiang
  Cc: Alejandro Lucero, Dan Williams, Jonathan Cameron, Ben Cheatham,
	Edward Cree
In-Reply-To: <20260701113805.14072-1-alejandro.lucero-palau@amd.com>

From: Alejandro Lucero <alucerop@amd.com>

Export cxl core functions for a Type2 driver being able to discover and
map the device registers.

Signed-off-by: Alejandro Lucero <alucerop@amd.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Ben Cheatham <benjamin.cheatham@amd.com>
Acked-by: Edward Cree <ecree.xilinx@gmail.com>
Link: https://patch.msgid.link/20260629183727.51502-2-alejandro.lucero-palau@amd.com
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 drivers/cxl/core/pci.c  |  1 +
 drivers/cxl/core/port.c |  1 +
 drivers/cxl/core/regs.c |  1 +
 drivers/cxl/cxlpci.h    | 12 ------------
 drivers/cxl/pci.c       |  1 +
 include/cxl/pci.h       | 22 ++++++++++++++++++++++
 6 files changed, 26 insertions(+), 12 deletions(-)
 create mode 100644 include/cxl/pci.h

diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index e4338fd7e01b..9d807c1a002c 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -6,6 +6,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/pci-doe.h>
+#include <cxl/pci.h>
 #include <linux/aer.h>
 #include <cxlpci.h>
 #include <cxlmem.h>
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index 1215ee4f4035..cb633e19151b 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -11,6 +11,7 @@
 #include <linux/idr.h>
 #include <linux/node.h>
 #include <cxl/einj.h>
+#include <cxl/pci.h>
 #include <cxlmem.h>
 #include <cxlpci.h>
 #include <cxl.h>
diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index 93710cf4f0a6..20c2d9fbcfe7 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -4,6 +4,7 @@
 #include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
+#include <cxl/pci.h>
 #include <cxlmem.h>
 #include <cxlpci.h>
 #include <pmu.h>
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
index b826eb53cf7b..110ec9c44f09 100644
--- a/drivers/cxl/cxlpci.h
+++ b/drivers/cxl/cxlpci.h
@@ -13,16 +13,6 @@
  */
 #define CXL_PCI_DEFAULT_MAX_VECTORS 16
 
-/* Register Block Identifier (RBI) */
-enum cxl_regloc_type {
-	CXL_REGLOC_RBI_EMPTY = 0,
-	CXL_REGLOC_RBI_COMPONENT,
-	CXL_REGLOC_RBI_VIRT,
-	CXL_REGLOC_RBI_MEMDEV,
-	CXL_REGLOC_RBI_PMU,
-	CXL_REGLOC_RBI_TYPES
-};
-
 /*
  * Table Access DOE, CDAT Read Entry Response
  *
@@ -112,6 +102,4 @@ static inline void devm_cxl_port_ras_setup(struct cxl_port *port)
 }
 #endif
 
-int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
-		       struct cxl_register_map *map);
 #endif /* __CXL_PCI_H__ */
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index 267c679b0b3c..bb892dbfdd6d 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -11,6 +11,7 @@
 #include <linux/pci.h>
 #include <linux/aer.h>
 #include <linux/io.h>
+#include <cxl/pci.h>
 #include <cxl/mailbox.h>
 #include "cxlmem.h"
 #include "cxlpci.h"
diff --git a/include/cxl/pci.h b/include/cxl/pci.h
new file mode 100644
index 000000000000..3e0000015871
--- /dev/null
+++ b/include/cxl/pci.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2020 Intel Corporation. All rights reserved. */
+
+#ifndef __CXL_CXL_PCI_H__
+#define __CXL_CXL_PCI_H__
+
+/* Register Block Identifier (RBI) */
+enum cxl_regloc_type {
+	CXL_REGLOC_RBI_EMPTY = 0,
+	CXL_REGLOC_RBI_COMPONENT,
+	CXL_REGLOC_RBI_VIRT,
+	CXL_REGLOC_RBI_MEMDEV,
+	CXL_REGLOC_RBI_PMU,
+	CXL_REGLOC_RBI_TYPES
+};
+
+struct cxl_register_map;
+struct pci_dev;
+
+int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
+		       struct cxl_register_map *map);
+#endif
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes
From: Konrad Dybcio @ 2026-07-01 10:40 UTC (permalink / raw)
  To: george.moussalem, Jens Axboe, Ulf Hansson, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
	Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
	Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Bjorn Andersson,
	Konrad Dybcio, Mathieu Poirier, Philipp Zabel
  Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
	ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
In-Reply-To: <20260629-ipq5018-bluetooth-v2-3-02770f03b6bb@outlook.com>

On 6/29/26 3:01 PM, George Moussalem via B4 Relay wrote:
> From: George Moussalem <george.moussalem@outlook.com>
> 
> The Bluetooth subsystem (BTSS) on the IPQ5018 SoC supports setting power
> modes which are required to be configured through a Secure Channel
> Manager (SCM) call to TrustZone. However, not all Trusted Execution
> Environment (QSEE) images support this call, so first check if the call
> is available.
> 
> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
> ---

I'm amazed changing this setting is a secure operation

[...]

> +/**
> + * qcom_scm_pas_set_bluetooth_power_mode() - Configure power optimization mode
> + *					     for the Bluetooth subsystem (BTSS)
> + * @pas_id:	peripheral authentication service id
> + * @val:	0x0 for normal operation, 0x4 for ECO mode

If there's just two values, maybe we should make this take a `bool eco_mode`?

> + *
> + * Return: 0 on success, negative errno on failure.
> + * Returns -EOPNOTSUPP if the firmware configuration call is unavailable.
> + */
> +int qcom_scm_pas_set_bluetooth_power_mode(u32 pas_id, u32 val)
> +{
> +	if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
> +					  QCOM_SCM_PIL_PAS_BT_PWR_MODE))
> +		return -EOPNOTSUPP;
> +
> +	return __qcom_scm_pas_set_bluetooth_power_mode(pas_id, val);

Let's just inline the whole definition here - it's single-use anyway

Konrad

^ permalink raw reply

* Re: [PATCH net-next v11 1/7] dt-bindings: phy: document the serdes PHY on sa8255p
From: Bartosz Golaszewski @ 2026-07-01 10:39 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Geert Uytterhoeven, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Andrew Lunn, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin,
	Alexandre Torgue, Giuseppe Cavallaro, Chen-Yu Tsai,
	Jernej Skrabec, Neil Armstrong, Kevin Hilman, Jerome Brunet,
	Shawn Guo, Fabio Estevam, Jan Petrous, s32, Mohd Ayaan Anwar,
	Romain Gantois, Magnus Damm, Maxime Ripard, Christophe Roullier,
	Radu Rendec, linux-arm-msm, devicetree, linux-kernel, netdev,
	linux-stm32, linux-arm-kernel, Drew Fustini, linux-sunxi,
	linux-amlogic, linux-mips, imx, linux-renesas-soc, linux-rockchip,
	sophgo, linux-riscv, Bartosz Golaszewski, Bartosz Golaszewski,
	Vinod Koul
In-Reply-To: <CAMRc=MfgAB8bc6PD-6jw_KR0uNBfH+PO2XtCeL1SUF2nCiT0xg@mail.gmail.com>

On Tue, 30 Jun 2026 15:44:16 +0200, Bartosz Golaszewski <brgl@kernel.org> said:
> On Tue, 30 Jun 2026 12:23:16 +0200, Vinod Koul <vkoul@kernel.org> said:
>> On 29-06-26, 16:51, Geert Uytterhoeven wrote:
>>> > Russell King asked me to put the PHY logic for SCMI pm domains into the PHY
>>> > driver instead of the MAC driver where it was previously. Instead of cramming
>>> > both HLOS and firmware handling into the same driver, I figured it makes more
>>> > sense to have a dedicated, cleaner driver as the two share very little code (if
>>> > any).
>>>
>>> I think you are mixing up DT bindings and driver implementation?
>>
>> Should the bindings change if we have different driver and firmware
>> implementations? Isn't binding supposed to be agnostic of
>> implementations..?
>>
>
> The way sa8255p implements SCMI is with SMC exclusively but - since even base
> support is not yet upstream -  maybe it would be possible to expose SCMI clocks
> like some platforms do and reuse the same binding.
>
> Would it make sense?
>
> Bart
>

Scratch that. The firmware on sa8255p does not expose SCMI clock protocol, we
can only use devfs with this PHY so it's either the same binding document with
different properties depending on compatible or two separate bindings. I prefer
the latter because it's cleaner.

Bartosz

^ permalink raw reply

* [PATCH] selftests: mptcp: mptcp_diag: fix stack buffer overflow in get_subflow_info()
From: Jiangshan Yi @ 2026-07-01 10:38 UTC (permalink / raw)
  To: geliang, martineau, matttbe
  Cc: davem, edumazet, kuba, pabeni, horms, shuah, netdev, mptcp,
	linux-kselftest, linux-kernel, 13667453960, Jiangshan Yi

get_subflow_info() parses the subflow address string with:

	char saddr[64], daddr[64];

	ret = sscanf(subflow_addrs, "%[^:]:%d %[^:]:%d",
		     saddr, &sport, daddr, &dport);

The subflow_addrs buffer holds up to 1024 bytes and is taken directly
from the command line ("-c" argument). The "%[^:]" conversions have no
maximum field width, so if the address substring before the ':' exceeds
63 bytes, sscanf() writes past the end of the 64-byte saddr/daddr stack
buffers. This overflows the stack, corrupting adjacent stack data such
as the saved return address, and can crash the tool or lead to
out-of-bounds writes controlled by user-supplied input.

Bound both string conversions to the destination buffer size by adding
an explicit maximum field width of 63 (leaving room for the terminating
NUL), so at most 63 bytes are written into each 64-byte buffer:

	ret = sscanf(subflow_addrs, "%63[^:]:%d %63[^:]:%d",
		     saddr, &sport, daddr, &dport);

Signed-off-by: Jiangshan Yi <yijiangshan@kylinos.cn>
---
 tools/testing/selftests/net/mptcp/mptcp_diag.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_diag.c b/tools/testing/selftests/net/mptcp/mptcp_diag.c
index 5e222ba977e4..02ac93f794fe 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_diag.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_diag.c
@@ -377,7 +377,7 @@ static void get_subflow_info(char *subflow_addrs)
 	int ret;
 	int fd;
 
-	ret = sscanf(subflow_addrs, "%[^:]:%d %[^:]:%d", saddr, &sport, daddr, &dport);
+	ret = sscanf(subflow_addrs, "%63[^:]:%d %63[^:]:%d", saddr, &sport, daddr, &dport);
 	if (ret != 4)
 		die_perror("IP PORT Pairs has style problems!");
 
-- 
2.25.1


^ permalink raw reply related

* Re: [PATCH] net: airoha: fix MIB stats collection to be lossless
From: Aniket Negi @ 2026-07-01 10:29 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-arm-kernel, linux-mediatek, netdev,
	linux-kernel, aniket.negi
In-Reply-To: <akS48y8gCJf-EmTP@lore-desk>

> Maybe better mib_prev?

Ok sure will update. mib_prev is cleaner and more concise. 
 
> Since now we do not reset the MIB counters in airoha_update_hw_stats(), we can
> get rid of the for loop there and just call airoha_dev_get_hw_stats() with the
> provided dev pointer. Even better, just rename airoha_dev_get_hw_stats() in
> airoha_update_hw_stats() and move the spinlock there. What do you think?

I am aligned with your suggestion, Since after removing MIB reset logic, there isn't need to iterate over all devs on airoha_gdm_port. This will simplify the code significantly.

I'll refactor as follows:

1. Remove the for loop in airoha_update_hw_stats()
2. Rename airoha_dev_get_hw_stats() to airoha_update_hw_stats()
3) move the spinlock into the renamed function.


Best Regards,
Aniket Negi

^ permalink raw reply

* Re: [PATCH net 8/8] ixgbe: only access vfinfo and mv_list under RCU lock
From: Corinna Vinschen @ 2026-07-01 10:15 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: anthony.l.nguyen, davem, pabeni, edumazet, andrew+netdev, netdev,
	alexander.nowlin, Corinna Vinschen
In-Reply-To: <20260523001605.1757032-1-kuba@kernel.org>

Hi Jakub, hi others,

sorry for the late reply, I was AFK for two months.

I scanned the review points and most of them raise important questions.

This mail is only to let you know that I started looking into them
and I will follow up with a new patch in the next few weeks.


Thanks,
Corinna


On May 22 17:16, Jakub Kicinski wrote:
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> ---
> ixgbe: only access vfinfo and mv_list under RCU lock
> 
> This change drops the vfs_lock spinlock in favour of RCU protection
> for adapter->vfinfo and adapter->mv_list, marking them __rcu and
> converting readers to rcu_dereference()/rcu_read_lock() and writers
> to rcu_replace_pointer()/kfree_rcu(). The goal is to address a
> crash observed when ixgbe_disable_sriov() races with
> ixgbe_service_task() / ixgbe_msg_task() readers.
> 
> > diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
> > index 9b8217523fd2..8849b9f42bf6 100644
> > --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
> > +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
> > @@ -808,10 +810,10 @@ struct ixgbe_adapter {
> >  	/* SR-IOV */
> >  	DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
> >  	unsigned int num_vfs;
> > -	struct vf_data_storage *vfinfo;
> > +	struct vf_data_storage __rcu *vfinfo;
> >  	int vf_rate_link_speed;
> >  	struct vf_macvlans vf_mvs;
> > -	struct vf_macvlans *mv_list;
> > +	struct vf_macvlans __rcu *mv_list;
> 
> [Medium]
> After this conversion, is ixgbe_handle_mdd_event() in
> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c still consistent
> with the new annotations? It contains:
> 
>     if (adapter->vfinfo && ixgbe_check_mdd_event(adapter)) {
> 
> That bare load of an __rcu pointer is not wrapped in
> rcu_read_lock() and does not use rcu_access_pointer() or
> rcu_dereference(), so sparse will flag it and the access
> bypasses the RCU discipline used elsewhere in the file. The
> commit message says RCU is used "throughout the driver" — was
> this site simply missed during the conversion?
> 
> [ ... ]
> 
> > diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> > index 2646ee6f295f..d82c7dfc6580 100644
> > --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> > +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> 
> [ ... ]
> 
> > @@ -8267,22 +8293,27 @@ static void ixgbe_watchdog_flush_tx(struct ixgbe_adapter *adapter)
> > @@ -8309,9 +8340,15 @@ static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
> >  
> >  	/* check status reg for all VFs owned by this PF */
> >  	for (vf = 0; vf < adapter->num_vfs; ++vf) {
> > -		struct pci_dev *vfdev = adapter->vfinfo[vf].vfdev;
> > +		struct vf_data_storage *vfinfo;
> > +		struct pci_dev *vfdev = NULL;
> >  		u16 status_reg;
> >  
> > +		rcu_read_lock();
> > +		vfinfo = rcu_dereference(adapter->vfinfo);
> > +		if (vfinfo)
> > +			vfdev = vfinfo[vf].vfdev;
> > +		rcu_read_unlock();
> >  		if (!vfdev)
> >  			continue;
> >  		pci_read_config_word(vfdev, PCI_STATUS, &status_reg);
> 
> [High]
> Can vfdev still be used safely after rcu_read_unlock() here?
> 
> The RCU section only protects the lifetime of the vfinfo array,
> not the lifetime of the pci_dev whose pointer was stored in it.
> ixgbe_disable_sriov() drops the reference taken by
> ixgbe_get_vfs() with pci_dev_put(vfdev) and then proceeds to
> pci_disable_sriov(), either of which can free the pci_dev
> concurrently with the subsequent pci_read_config_word() and the
> pcie_flr(vfdev) reached through ixgbe_bad_vf_abort().
> 
> Should this path take pci_dev_get(vfdev) before dropping the
> rcu_read_unlock(), and pci_dev_put() after the config-space
> access and FLR are complete?
> 
> This appears to predate this patch (the prior code dereferenced
> vfdev outside any lifetime-extending section as well), but the
> RCU conversion seems like a natural opportunity to address it.
> 
> [ ... ]
> 
> > @@ -10071,20 +10114,26 @@ static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
> >  {
> >  	struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ];
> >  	unsigned int num_vfs = adapter->num_vfs, vf;
> > +	struct vf_data_storage *vfinfo;
> >  	struct netdev_nested_priv priv;
> >  	struct upper_walk_data data;
> >  	struct net_device *upper;
> >  
> >  	/* redirect to a SRIOV VF */
> > -	for (vf = 0; vf < num_vfs; ++vf) {
> > -		upper = pci_get_drvdata(adapter->vfinfo[vf].vfdev);
> > -		if (upper->ifindex == ifindex) {
> > -			*queue = vf * __ALIGN_MASK(1, ~vmdq->mask);
> > -			*action = vf + 1;
> > -			*action <<= ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF;
> > -			return 0;
> > +	rcu_read_lock();
> > +	vfinfo = rcu_dereference(adapter->vfinfo);
> > +	if (vfinfo)
> > +		for (vf = 0; vf < num_vfs; ++vf) {
> > +			upper = pci_get_drvdata(vfinfo[vf].vfdev);
> 
> [High]
> Can the captured num_vfs and the freshly-dereferenced vfinfo
> disagree in size here?
> 
> num_vfs is sampled from adapter->num_vfs before rcu_read_lock(),
> while vfinfo is observed inside the RCU section. ixgbe_disable_sriov()
> runs under PCI device_lock (not rtnl), sets adapter->num_vfs = 0,
> and rcu_replace_pointer()s vfinfo. A subsequent
> __ixgbe_enable_sriov(N2) can publish a smaller vfinfo array of
> size N2 < num_vfs before the loop runs. The access vfinfo[vf]
> for vf >= N2 is then a heap out-of-bounds read.
> 
> Should num_vfs be sampled inside the rcu_read_lock() and bounded
> by the actual size of the published vfinfo, or should
> adapter->num_vfs be updated as part of the same rcu_assign_pointer
> publication so readers can rely on a consistent pair?
> 
> [ ... ]
> 
> > @@ -9744,15 +9781,21 @@ static int ixgbe_ndo_get_vf_stats(struct net_device *netdev, int vf,
> >  				  struct ifla_vf_stats *vf_stats)
> >  {
> >  	struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
> > +	struct vf_data_storage *vfinfo;
> >  
> >  	if (vf < 0 || vf >= adapter->num_vfs)
> >  		return -EINVAL;
> >  
> > -	vf_stats->rx_packets = adapter->vfinfo[vf].vfstats.gprc;
> > -	vf_stats->rx_bytes   = adapter->vfinfo[vf].vfstats.gorc;
> > -	vf_stats->tx_packets = adapter->vfinfo[vf].vfstats.gptc;
> > -	vf_stats->tx_bytes   = adapter->vfinfo[vf].vfstats.gotc;
> > -	vf_stats->multicast  = adapter->vfinfo[vf].vfstats.mprc;
> > +	rcu_read_lock();
> > +	vfinfo = rcu_dereference(adapter->vfinfo);
> > +	if (vfinfo) {
> > +		vf_stats->rx_packets = vfinfo[vf].vfstats.gprc;
> > +		vf_stats->rx_bytes   = vfinfo[vf].vfstats.gorc;
> > +		vf_stats->tx_packets = vfinfo[vf].vfstats.gptc;
> > +		vf_stats->tx_bytes   = vfinfo[vf].vfstats.gotc;
> > +		vf_stats->multicast  = vfinfo[vf].vfstats.mprc;
> > +	}
> > +	rcu_read_unlock();
> 
> [High]
> This pattern recurs in many of the rtnl ndo handlers (set_vf_mac,
> set_vf_spoofchk, set_vf_rss_query_en, set_vf_trust, set_vf_vlan,
> set_vf_bw, get_vf_config, get_vf_stats): the bound check
> 
>     if (vf >= adapter->num_vfs)
>         return -EINVAL;
> 
> is performed before rcu_read_lock(). Between that check and the
> later rcu_dereference, ixgbe_disable_sriov() (under PCI device_lock,
> not rtnl) can set num_vfs = 0 and __ixgbe_enable_sriov() can
> republish vfinfo at a smaller size N2.
> 
> For ixgbe_ndo_get_vf_config() the resulting OOB read is then
> memcpy'd into struct ifla_vf_info and returned to userspace via
> netlink, which would expose adjacent kernel heap. For the setter
> ndos and the mailbox-driven setters, this is an out-of-bounds
> write.
> 
> Should the vf range check be repeated against the size of the
> freshly observed vfinfo, ideally with num_vfs and vfinfo
> published together so the pair is self-consistent?
> 
> > diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
> > index 431d77da15a5..80f22a8e7af4 100644
> > --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
> > +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
> 
> [ ... ]
> 
> > @@ -206,31 +214,28 @@ int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
> >  {
> >  	unsigned int num_vfs = adapter->num_vfs, vf;
> >  	struct ixgbe_hw *hw = &adapter->hw;
> > -	unsigned long flags;
> > +	struct vf_data_storage *vfinfo;
> > +	struct vf_macvlans *mv_list;
> >  	int rss;
> >  
> > -	spin_lock_irqsave(&adapter->vfs_lock, flags);
> > -	/* set num VFs to 0 to prevent access to vfinfo */
> > +	/* set num VFs to 0 so readers bail out early */
> >  	adapter->num_vfs = 0;
> > -	spin_unlock_irqrestore(&adapter->vfs_lock, flags);
> > +
> > +	vfinfo = rcu_replace_pointer(adapter->vfinfo, NULL, 1);
> > +	mv_list = rcu_replace_pointer(adapter->mv_list, NULL, 1);
> 
> [Low]
> The lockdep predicate passed to rcu_replace_pointer() is the
> literal 1, which makes the writer-side assertion always succeed
> and provides no verification. The patch simultaneously removes
> vfs_lock and shifts to an implicit (undocumented) reliance on
> some caller serialization for the writer.
> 
> Could lockdep_is_held() of the actual writer-side lock (for
> example the PCI device_lock or rtnl_lock, whichever is intended)
> be used here so a future regression that calls
> ixgbe_disable_sriov() outside that context is caught by lockdep?
> 
> [ ... ]
> 
> > @@ -643,10 +668,16 @@ static void ixgbe_clear_vf_vlans(struct ixgbe_adapter *adapter, u32 vf)
> >  static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter,
> >  				int vf, int index, unsigned char *mac_addr)
> >  {
> > -	struct vf_macvlans *entry;
> > +	struct vf_macvlans *mv_list, *entry;
> >  	bool found = false;
> >  	int retval = 0;
> >  
> > +	lockdep_assert_in_rcu_read_lock();
> > +	/* vf_mvs entries point into the mv_list array */
> > +	mv_list = rcu_dereference(adapter->mv_list);
> > +	if (!mv_list)
> > +		return 0;
> > +
> >  	if (index <= 1) {
> >  		list_for_each_entry(entry, &adapter->vf_mvs.l, l) {
> 
> [High]
> Is non-RCU list iteration safe here while only rcu_read_lock()
> is held?
> 
> The list head &adapter->vf_mvs.l is mutated by the writer side
> without RCU-aware primitives. ixgbe_alloc_vf_macvlans() does:
> 
>     INIT_LIST_HEAD(&adapter->vf_mvs.l);
>     ...
>     list_add(&mv_list[i].l, &adapter->vf_mvs.l);
> 
> and ixgbe_disable_sriov() kfree_rcu()s mv_list but never
> reinitialises &adapter->vf_mvs.l, so on a subsequent
> re-enable the writer concurrently zeros and re-links the head
> while a reader walks it.
> 
> Should list_for_each_entry() be list_for_each_entry_rcu(), and
> the writer use INIT_LIST_HEAD_RCU() / list_add_rcu()? Otherwise
> the reader can observe torn next/prev loads or follow into
> freed/re-used entries.
> 
> [ ... ]
> 
> > @@ -780,16 +816,25 @@ static void ixgbe_vf_clear_mbx(struct ixgbe_adapter *adapter, u32 vf)
> >  static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
> >  			    int vf, unsigned char *mac_addr)
> >  {
> > +	struct vf_data_storage *vfinfo;
> >  	int retval;
> >  
> > -	ixgbe_del_mac_filter(adapter, adapter->vfinfo[vf].vf_mac_addresses, vf);
> > +	rcu_read_lock();
> > +	vfinfo = rcu_dereference(adapter->vfinfo);
> > +	if (!vfinfo) {
> > +		rcu_read_unlock();
> > +		return -EINVAL;
> > +	}
> > +
> > +	ixgbe_del_mac_filter(adapter, vfinfo[vf].vf_mac_addresses, vf);
> >  	retval = ixgbe_add_mac_filter(adapter, mac_addr, vf);
> >  	if (retval >= 0)
> > -		memcpy(adapter->vfinfo[vf].vf_mac_addresses, mac_addr,
> > +		memcpy(vfinfo[vf].vf_mac_addresses, mac_addr,
> >  		       ETH_ALEN);
> 
> [ ... ]
> 
> > @@ -1537,21 +1677,34 @@ void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter)
> >  int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
> >  {
> >  	struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
> > +	struct vf_data_storage *vfinfo;
> >  	int retval;
> >  
> >  	if (vf >= adapter->num_vfs)
> >  		return -EINVAL;
> >  
> > +	rcu_read_lock();
> > +	vfinfo = rcu_dereference(adapter->vfinfo);
> > +	if (!vfinfo) {
> > +		rcu_read_unlock();
> > +		return 0;
> > +	}
> > +
> >  	if (is_valid_ether_addr(mac)) {
> >  		dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n",
> >  			 mac, vf);
> >  		dev_info(&adapter->pdev->dev, "Reload the VF driver to make this change effective.");
> >  
> >  		retval = ixgbe_set_vf_mac(adapter, vf, mac);
> >  		if (retval >= 0) {
> > -			adapter->vfinfo[vf].pf_set_mac = true;
> > +			vfinfo[vf].pf_set_mac = true;
> 
> [High]
> Can vfinfo here and the vfinfo observed inside ixgbe_set_vf_mac()
> end up pointing at different objects?
> 
> ixgbe_ndo_set_vf_mac() captures vfinfo via its own rcu_dereference,
> then calls ixgbe_set_vf_mac() which independently does:
> 
>     rcu_read_lock();
>     vfinfo = rcu_dereference(adapter->vfinfo);
>     ...
>     memcpy(vfinfo[vf].vf_mac_addresses, mac_addr, ETH_ALEN);
> 
> Nesting rcu_read_lock() is fine, but each rcu_dereference()
> observes whatever pointer is currently published. If
> ixgbe_disable_sriov() followed by __ixgbe_enable_sriov() races
> between the two dereferences, the inner copy lands in the new
> array while the outer pf_set_mac = true write lands in the old
> array. The two pieces of state then disagree, which seems to
> break the "attempted to override administratively set MAC"
> enforcement on subsequent VF mailbox messages. If the new
> vfinfo is shorter than vf, the inner memcpy is also a heap
> out-of-bounds write.
> 
> Should ixgbe_ndo_set_vf_mac() pass its already-captured vfinfo
> into ixgbe_set_vf_mac() so both writes go to the same object,
> or otherwise structure the call so a single rcu_dereference
> covers all writes for one operation?


^ permalink raw reply

* Re: [PATCH net 1/2] vsock/virtio: collapse receive queue under memory pressure
From: Stefano Garzarella @ 2026-07-01 10:13 UTC (permalink / raw)
  To: Paolo Abeni
  Cc: netdev, Jason Wang, Jakub Kicinski, Michael S. Tsirkin, kvm,
	virtualization, Xuan Zhuo, Eric Dumazet, Simon Horman,
	linux-kernel, Stefan Hajnoczi, David S. Miller,
	Eugenio Pérez, stable, Brien Oberstein
In-Reply-To: <6a6be4b0-e02d-46ca-b8bf-c27bd681d253@redhat.com>

On Tue, Jun 30, 2026 at 11:53:04AM +0200, Paolo Abeni wrote:
>On 6/26/26 3:48 PM, Stefano Garzarella wrote:
>> From: Stefano Garzarella <sgarzare@redhat.com>
>>
>> When many small packets accumulate in the receive queue, the skb overhead
>> can exceed buf_alloc even while the payload is within bounds. This causes
>> virtio_transport_inc_rx_pkt() to reject packets, leading to connection
>> resets during large transfers under backpressure.
>>
>> The issue was reported by Brien, who has a reproducer, but it is also
>> easily reproducible with iperf-vsock [1] using a small packet size:
>>
>>   iperf3 --vsock -c $CID -l 129
>>
>> which fails immediately without this patch but with commit 059b7dbd20a6
>> ("vsock/virtio: fix potential unbounded skb queue").
>>
>> Inspired by TCP's tcp_collapse() which solves a similar problem, add
>> virtio_transport_collapse_rx_queue() that walks the receive queue and
>> re-copies data into compact linear skbs to reduce the overhead.
>>
>> The collapse is triggered from virtio_transport_recv_enqueue() when
>> virtio_transport_inc_rx_pkt() fails. A pre-scan counts the eligible bytes
>> to size each allocation precisely, avoiding waste for isolated small
>> packets. Partially consumed skbs are kept as-is to preserve
>> buf_used/fwd_cnt accounting, EOM-marked skbs to maintain SEQPACKET
>> message boundaries, and skbs already larger than the collapse target
>> because they already have a good data-to-overhead ratio.
>>
>> [1] https://github.com/stefano-garzarella/iperf-vsock
>>
>> Fixes: 059b7dbd20a6 ("vsock/virtio: fix potential unbounded skb queue")
>> Cc: stable@vger.kernel.org
>> Reported-by: Brien Oberstein <brienpub@gmail.com>
>> Closes: https://lore.kernel.org/netdev/618701dd023e$063de350$12b9a9f0$@gmail.com/
>> Tested-by: Brien Oberstein <brienpub@gmail.com>
>> Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
>> ---
>>  net/vmw_vsock/virtio_transport_common.c | 148 +++++++++++++++++++++++-
>>  1 file changed, 146 insertions(+), 2 deletions(-)
>>
>> diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
>> index 09475007165b..304ea424995d 100644
>> --- a/net/vmw_vsock/virtio_transport_common.c
>> +++ b/net/vmw_vsock/virtio_transport_common.c
>> @@ -420,6 +420,137 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
>>  	return ret;
>>  }
>>
>> +static bool virtio_transport_can_collapse(struct sk_buff *skb,
>> +					  unsigned int size)
>
>Why passing a `size` argument here? AFAICS the actual argument is always
>a constant and IMHO rightfully so.

This comes from a previous implementation where this was not constant.
With the current code, I agree that a macro should be better.

I'll fix it.

>
>> +{
>> +	/* skbs that are partially consumed, mark a SEQPACKET message boundary,
>> +	 * or are already large enough should not be collapsed: they either
>> +	 * need special accounting, carry protocol state, or already have a
>> +	 * good data-to-overhead ratio.
>> +	 */
>> +	if (VIRTIO_VSOCK_SKB_CB(skb)->offset)
>> +		return false;
>> +	if (le32_to_cpu(virtio_vsock_hdr(skb)->flags) & VIRTIO_VSOCK_SEQ_EOM)
>> +		return false;
>> +	if (skb->len >= size)
>> +		return false;
>> +	return true;
>> +}
>> +
>> +/* Iterate through the packets in the queue starting from the current skb to
>> + * count the number of bytes we can collapse.
>> + */
>> +static unsigned int
>> +virtio_transport_collapse_size(struct sk_buff *skb,
>> +			       struct sk_buff_head *queue,
>> +			       unsigned int max_size)
>> +{
>> +	unsigned int target = skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset;
>> +
>> +	while ((skb = skb_peek_next(skb, queue)) &&
>> +	       virtio_transport_can_collapse(skb, max_size)) {
>> +		unsigned int len = skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset;
>> +
>> +		if (len > max_size - target)
>> +			return target;
>> +
>> +		target += len;
>> +	}
>> +
>> +	return target;
>> +}
>> +
>> +/* Called under lock_sock when skb overhead exceeds the budget. */
>> +static void virtio_transport_collapse_rx_queue(struct virtio_vsock_sock *vvs)
>> +{
>> +	/* Use the same linear allocation threshold as virtio_vsock_alloc_skb()
>> +	 * to avoid adding pressure on the page allocator.
>> +	 */
>> +	unsigned int collapse_max = SKB_MAX_ORDER(VIRTIO_VSOCK_SKB_HEADROOM,
>> +						  PAGE_ALLOC_COSTLY_ORDER);
>> +	struct sk_buff *skb, *next_skb, *new_skb = NULL;
>> +	struct sk_buff_head new_queue;
>> +
>> +	__skb_queue_head_init(&new_queue);
>> +
>> +	skb_queue_walk_safe(&vvs->rx_queue, skb, next_skb) {
>
>If the queue is relevantly big, walking all of it may take a significant
>amount of time/cache misses and causes traffic burstines. I think you
>could add an additional stop condition, i.e. when the current queue size
>is below a reasonable threshold (allowing the current packet to be
>inserted plus some more slack).

Makes sense, any suggestion on the threshold?

I was thinking something like this: merge until we have space for at 
least 2 skbs (because for now we estimate the overhead based on the 
number of skbs, but in the future I'd like to support truesize), but 
still trying to fill collapse_max as much as possible.

Does that make sense, or should we be more aggressive?

>
>/P
>
>> +		struct virtio_vsock_hdr *hdr = virtio_vsock_hdr(skb);
>> +		u32 src_off = VIRTIO_VSOCK_SKB_CB(skb)->offset;
>> +		u32 src_len = skb->len - src_off;
>> +		bool keep = false;
>> +
>> +		if (!virtio_transport_can_collapse(skb, collapse_max)) {
>
>Minor nit, possibly something alike the following lead to more
>compact/more readable code:
>
>
>		keep = !virtio_transport_can_collapse(skb, collapse_max);
>		if (keep) {
>

Yeah, so I can remove the initialization to false. I'll change it.

>> +			/* Finalize pending collapsed skb to preserve packet
>> +			 * ordering.
>> +			 */
>> +			if (new_skb) {
>> +				__skb_queue_tail(&new_queue, new_skb);
>> +				new_skb = NULL;
>> +			}
>> +			keep = true;
>> +			goto next;
>> +		}
>> +
>> +		/* Finalize if this packet won't fit in the remaining tailroom,
>> +		 * so we can allocate a right-sized new_skb.
>> +		 */
>> +		if (new_skb && src_len > skb_tailroom(new_skb)) {
>> +			__skb_queue_tail(&new_queue, new_skb);
>> +			new_skb = NULL;
>
>Possibly introduce an helper for the above 2 statements?

Do you mean something like this?

static void virtio_transport_queue_skb(struct sk_buff_head *queue,
				       struct sk_buff **skb)
{
	__skb_queue_tail(queue, *skb);
	*skb = NULL;
}

Not sure, just for 2 places, but if you prefer it, I can change.

Thanks,
Stefano


^ permalink raw reply

* RE: [PATCH net-next 07/14] net: enetc: differentiate phylink capabilities for pseudo-MAC and standalone MAC
From: Wei Fang (OSS) @ 2026-07-01 10:12 UTC (permalink / raw)
  To: sashiko-reviews@lists.linux.dev
  Cc: imx@lists.linux.dev, Frank.Li@kernel.org, network dev
In-Reply-To: <20260701075116.900D81F00A3A@smtp.kernel.org>



Best Regards,
Wei Fang

> -----Original Message-----
> From: sashiko-bot@kernel.org <sashiko-bot@kernel.org>
> Sent: 2026年7月1日 15:51
> To: Wei Fang (OSS) <wei.fang@oss.nxp.com>
> Cc: imx@lists.linux.dev; Frank.Li@kernel.org
> Subject: Re: [PATCH net-next 07/14] net: enetc: differentiate phylink capabilities
> for pseudo-MAC and standalone MAC
> 
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to
> consider:
> - [High] Incorrect unconditional advertisement of 5G/10G MAC capabilities and
> 10GBASER/XGMII interface modes for older ENETC v1 hardware.
> --
> 
> commit afb9f1b607c70d3a6a854e15aaa034f99fb49f5c
> Author: Claudiu Manoil <claudiu.manoil@nxp.com>
> 
> net: enetc: differentiate phylink capabilities for pseudo-MAC and standalone
> MAC
> 
> The ENETC pseudo-MACs are proprietary internal links that do not implement
> any standard MII interface, so restrict their supported PHY interface modes
> to PHY_INTERFACE_MODE_INTERNAL only. This also expands the supported
> interface modes and MAC capabilities for standalone ENETC.
> 
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
> b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
> > index 3597cb81a7ccb..adf79a99a8c81 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
> 
> [ ... ]
> 
> > @@ -400,25 +400,40 @@ int enetc_phylink_create(struct enetc_ndev_priv
> *priv, struct device_node *node,
> >  {
> >  	struct enetc_pf *pf = enetc_si_priv(priv->si);
> >  	struct phylink *phylink;
> > +	unsigned long mac_caps;
> >  	int err;
> >
> >  	pf->phylink_config.dev = &priv->ndev->dev;
> >  	pf->phylink_config.type = PHYLINK_NETDEV;
> > -	pf->phylink_config.mac_capabilities = MAC_ASYM_PAUSE |
> MAC_SYM_PAUSE |
> > -		MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
> >
> >  	__set_bit(PHY_INTERFACE_MODE_INTERNAL,
> >  		  pf->phylink_config.supported_interfaces);
> > -	__set_bit(PHY_INTERFACE_MODE_SGMII,
> > -		  pf->phylink_config.supported_interfaces);
> > -	__set_bit(PHY_INTERFACE_MODE_1000BASEX,
> > -		  pf->phylink_config.supported_interfaces);
> > -	__set_bit(PHY_INTERFACE_MODE_2500BASEX,
> > -		  pf->phylink_config.supported_interfaces);
> > -	__set_bit(PHY_INTERFACE_MODE_USXGMII,
> > -		  pf->phylink_config.supported_interfaces);
> > -	phy_interface_set_rgmii(pf->phylink_config.supported_interfaces);
> >
> > +	mac_caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
> > +	if (!enetc_is_pseudo_mac(priv->si)) {
> > +		mac_caps |= MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD |
> > +			    MAC_5000FD | MAC_10000FD;
> > +
> > +		__set_bit(PHY_INTERFACE_MODE_SGMII,
> > +			  pf->phylink_config.supported_interfaces);
> > +		__set_bit(PHY_INTERFACE_MODE_1000BASEX,
> > +			  pf->phylink_config.supported_interfaces);
> > +		__set_bit(PHY_INTERFACE_MODE_2500BASEX,
> > +			  pf->phylink_config.supported_interfaces);
> > +		__set_bit(PHY_INTERFACE_MODE_USXGMII,
> > +			  pf->phylink_config.supported_interfaces);
> > +		__set_bit(PHY_INTERFACE_MODE_10GBASER,
> > +			  pf->phylink_config.supported_interfaces);
> > +		__set_bit(PHY_INTERFACE_MODE_XGMII,
> > +			  pf->phylink_config.supported_interfaces);
> 
> [Severity: High]
> Will this unconditionally enable 5G and 10G speeds for older ENETC v1
> hardware?
> 
> If a 10G capable PHY is attached via USXGMII to an ENETC v1 port, it appears
> the link will negotiate at 10Gbps instead of being capped at 2.5Gbps.
> 
> If that happens, enetc_sched_speed_set() doesn't seem to handle SPEED_5000
> or
> SPEED_10000:
> 
> drivers/net/ethernet/freescale/enetc/enetc_qos.c:enetc_sched_speed_set() {
> 	...
> 	switch (speed) {
> 	case SPEED_1000:
> 		pspeed = ENETC_PMR_PSPEED_1000M;
> 		break;
> 	case SPEED_2500:
> 		pspeed = ENETC_PMR_PSPEED_2500M;
> 		break;
> 	case SPEED_100:
> 		pspeed = ENETC_PMR_PSPEED_100M;
> 		break;
> 	case SPEED_10:
> 	default:
> 		pspeed = ENETC_PMR_PSPEED_10M;
> 	}
> 	...
> }
> 
> This would cause it to fall through to 10 Mbps and break QoS scheduling.
> 
> Additionally, enetc_mac_config() doesn't appear to have support for
> configuring the hardware for PHY_INTERFACE_MODE_10GBASER or
> PHY_INTERFACE_MODE_XGMII which are now being advertised.
> 
> Should these new capabilities be restricted to newer hardware revisions?
> 

I will remove XGMII and 10GBASER modes including the 10G and 5G speeds
as they are not supported yet in upstream.


^ permalink raw reply

* Re: [PATCH net-next v2] ipv4: igmp: remove multicast group from hash table on device destruction
From: Ido Schimmel @ 2026-07-01 10:12 UTC (permalink / raw)
  To: Yuyang Huang
  Cc: Kuniyuki Iwashima, davem, dsahern, edumazet, horms,
	jedrzej.jagielski, kuba, linux-kernel, netdev, pabeni,
	xiyou.wangcong
In-Reply-To: <CADXeF1HY0EGdFwe6DXu21BmpYUQebHLp89kQ0MpDgb_DDGSaqQ@mail.gmail.com>

On Wed, Jul 01, 2026 at 09:41:53AM +0900, Yuyang Huang wrote:
> Thanks for the advise, I will try to add a trace in v3. For more
> reference, the issue is pointed out in the following discussion:
> 
> https://lore.kernel.org/netdev/95adff35-ee56-49d3-8567-382ac17810b3@redhat.com/#t

I'm aware, but we get a lot of patches with various claims and no traces
and some of these patches are completely unnecessary / wrong. A trace
tells the reviewer that the issue is real and that the author validated
the fix. Otherwise, it is up to the reviewer to check that this is not
yet another false-positive from some tool.

^ permalink raw reply

* [PATCH nf v2] netfilter: ip6tables: mark malformed IPv6 extension headers for hotdrop
From: Zhixing Chen @ 2026-07-01 10:09 UTC (permalink / raw)
  To: Florian Westphal, Pablo Neira Ayuso
  Cc: Phil Sutter, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, netfilter-devel, coreteam, netdev,
	Zhixing Chen

The ah, hbh and rt matches check that the fixed extension header is
present, then use the header length field to derive the advertised
extension header length for matching.

For the ah match, add the missing advertised-length check. For hbh
and rt, update the existing advertised-length checks. In all three
cases, set hotdrop to true before returning false when the advertised
extension header length exceeds the available skb data.

Returning false treats the packet as a rule mismatch. Set hotdrop to
true and drop malformed packets so they cannot bypass rules intended
to drop packets with these IPv6 extension headers.

Signed-off-by: Zhixing Chen <running910@gmail.com>
---

Changes in v2:
- Set hotdrop to true before returning false for malformed packets.
- Apply the same handling to hbh and rt matches.

v1: https://lore.kernel.org/netfilter-devel/20260618125848.93550-1-running910@gmail.com/T/

---
 net/ipv6/netfilter/ip6t_ah.c  | 5 +++++
 net/ipv6/netfilter/ip6t_hbh.c | 1 +
 net/ipv6/netfilter/ip6t_rt.c  | 1 +
 3 files changed, 7 insertions(+)

diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index 70da2f2ce064..1258783ed876 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -56,6 +56,11 @@ static bool ah_mt6(const struct sk_buff *skb, struct xt_action_param *par)
 	}
 
 	hdrlen = ipv6_authlen(ah);
+	if (skb->len - ptr < hdrlen) {
+		/* Packet smaller than its length field */
+		par->hotdrop = true;
+		return false;
+	}
 
 	pr_debug("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
 	pr_debug("RES %04X ", ah->reserved);
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 450dd53846a2..6d1a5d2026a6 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -75,6 +75,7 @@ hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par)
 	hdrlen = ipv6_optlen(oh);
 	if (skb->len - ptr < hdrlen) {
 		/* Packet smaller than it's length field */
+		par->hotdrop = true;
 		return false;
 	}
 
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 5561bd9cea81..e28caca759f3 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -57,6 +57,7 @@ static bool rt_mt6(const struct sk_buff *skb, struct xt_action_param *par)
 	hdrlen = ipv6_optlen(rh);
 	if (skb->len - ptr < hdrlen) {
 		/* Pcket smaller than its length field */
+		par->hotdrop = true;
 		return false;
 	}
 
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH 5/9] ax88179_178a: Add support for ethtool pause parameter configuration
From: Maxime Chevallier @ 2026-07-01 10:04 UTC (permalink / raw)
  To: Birger Koblitz, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: linux-usb, netdev, linux-kernel
In-Reply-To: <20260701-ax88179a-v1-5-13685df67515@birger-koblitz.de>

Hi

On 7/1/26 07:42, Birger Koblitz wrote:
> The AX179A-based chips support pause parameter configuration.
> Make it available through ethtool ops.
> 
> Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
> ---
>  drivers/net/usb/ax88179_178a.c | 67 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 67 insertions(+)
> 
> diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
> index 16528d873e804fde5dcc27659048882eee1c3eaa..586c049c6f7422a853aeae5e9372ead3a6d106c5 100644
> --- a/drivers/net/usb/ax88179_178a.c
> +++ b/drivers/net/usb/ax88179_178a.c
> @@ -956,6 +956,71 @@ static int ax88179_set_link_ksettings(struct net_device *net,
>  	return mii_ethtool_set_link_ksettings(&dev->mii, cmd);
>  }
>  
> +static void ax88179a_get_pauseparam(struct net_device *net, struct ethtool_pauseparam *pause)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	struct ax88179_data *data;
> +	u16 bmcr, lcladv, rmtadv;
> +	u8 cap;
> +
> +	data = dev->driver_priv;
> +
> +	if (data->chip_version < AX_VERSION_AX88179A)
> +		return;
> +
> +	bmcr = ax88179_mdio_read(net, dev->mii.phy_id, MII_BMCR);
> +	lcladv = ax88179_mdio_read(net, dev->mii.phy_id, MII_ADVERTISE);
> +	rmtadv = ax88179_mdio_read(net, dev->mii.phy_id, MII_LPA);
> +
> +	if (!(bmcr & BMCR_ANENABLE)) {
> +		pause->autoneg = 0;
> +		pause->rx_pause = 0;
> +		pause->tx_pause = 0;
> +		return;
> +	}
> +
> +	pause->autoneg = 1;

pause autoneg is not the same as link-wide autoneg. If link autoneg is disabled,
you have to keep track on how pause autoneg was configured by user, so that this
can be re-applied when link aneg gets re-enabled.

The best way to have this correct is to use phylink, but for that you'd need to
have a proper PHY driver instead of using the mii_ API here.

> +
> +	cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
> +
> +	if (cap & FLOW_CTRL_RX)
> +		pause->rx_pause = 1;
> +
> +	if (cap & FLOW_CTRL_TX)
> +		pause->tx_pause = 1;
> +}
> +
> +static int ax88179a_set_pauseparam(struct net_device *net, struct ethtool_pauseparam *pause)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	struct ax88179_data *data;
> +	u16 old, new1, bmcr;
> +	u8 cap = 0;
> +
> +	data = dev->driver_priv;
> +
> +	if (data->chip_version < AX_VERSION_AX88179A)
> +		return -EOPNOTSUPP;
> +
> +	bmcr = ax88179_mdio_read(net, dev->mii.phy_id, MII_BMCR);
> +	if (pause->autoneg && !(bmcr & BMCR_ANENABLE))
> +		return -EINVAL;

As I said, pause autoneg can be on while linke autoneg is off. of course, the
device doesn't advertise pause, but the driver needs to keep track of what's
the pause aneg flag.

Maxime

^ permalink raw reply

* [PATCH net-next v6 1/3] net: libwx: add support for set_ringparam in wx_ethtool_ops_vf
From: Mengyuan Lou @ 2026-07-01 10:01 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, horms, kuba, pabeni, Mengyuan Lou
In-Reply-To: <20260701100145.23738-1-mengyuanlou@net-swift.com>

Add support for the set_ringparam in wx_ethtool_ops_vf,
which is used to set ring sizes for ngbevf and txgbevf.

Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
---
 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 61 +++++++++++++++++++
 drivers/net/ethernet/wangxun/libwx/wx_lib.c   |  9 +--
 drivers/net/ethernet/wangxun/libwx/wx_lib.h   |  4 +-
 .../net/ethernet/wangxun/libwx/wx_vf_common.c |  4 +-
 .../net/ethernet/wangxun/libwx/wx_vf_common.h |  2 +
 5 files changed, 72 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 5df971aca9e3..eae038df6875 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -9,6 +9,7 @@
 #include "wx_ethtool.h"
 #include "wx_hw.h"
 #include "wx_lib.h"
+#include "wx_vf_common.h"
 
 struct wx_stats {
 	char stat_string[ETH_GSTRING_LEN];
@@ -775,6 +776,65 @@ static int wx_get_link_ksettings_vf(struct net_device *netdev,
 	return 0;
 }
 
+static int wx_set_ringparam_vf(struct net_device *netdev,
+			       struct ethtool_ringparam *ring,
+			       struct kernel_ethtool_ringparam *kernel_ring,
+			       struct netlink_ext_ack *extack)
+{
+	struct wx *wx = netdev_priv(netdev);
+	u32 new_rx_count, new_tx_count;
+	struct wx_ring *temp_ring;
+	int i, err = 0;
+
+	new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
+	new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
+
+	new_rx_count = clamp_t(u32, ring->rx_pending, WX_MIN_RXD, WX_MAX_RXD);
+	new_rx_count = ALIGN(new_rx_count, WX_REQ_RX_DESCRIPTOR_MULTIPLE);
+
+	if (new_tx_count == wx->tx_ring_count &&
+	    new_rx_count == wx->rx_ring_count)
+		return 0;
+
+	mutex_lock(&wx->reset_lock);
+	set_bit(WX_STATE_RESETTING, wx->state);
+
+	if (!netif_running(wx->netdev)) {
+		for (i = 0; i < wx->num_tx_queues; i++)
+			wx->tx_ring[i]->count = new_tx_count;
+		for (i = 0; i < wx->num_rx_queues; i++)
+			wx->rx_ring[i]->count = new_rx_count;
+		wx->tx_ring_count = new_tx_count;
+		wx->rx_ring_count = new_rx_count;
+
+		goto clear_reset;
+	}
+
+	/* allocate temporary buffer to store rings in */
+	i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
+	temp_ring = kvmalloc_objs(struct wx_ring, i);
+	if (!temp_ring) {
+		err = -ENOMEM;
+		goto clear_reset;
+	}
+
+	wxvf_down(wx);
+	/* wx_set_ring() may partially apply changes before
+	 * returning an error. The error indicates that not all
+	 * requested ring parameters could be configured.
+	 */
+	err = wx_set_ring(wx, new_tx_count, new_rx_count, temp_ring);
+	if (err)
+		wx_err(wx, "failed to set ring parameters: %d", err);
+	wx_configure_vf(wx);
+	wxvf_up_complete(wx);
+	kvfree(temp_ring);
+clear_reset:
+	clear_bit(WX_STATE_RESETTING, wx->state);
+	mutex_unlock(&wx->reset_lock);
+	return err;
+}
+
 static const struct ethtool_ops wx_ethtool_ops_vf = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
 				     ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ |
@@ -782,6 +842,7 @@ static const struct ethtool_ops wx_ethtool_ops_vf = {
 	.get_drvinfo		= wx_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
 	.get_ringparam		= wx_get_ringparam,
+	.set_ringparam		= wx_set_ringparam_vf,
 	.get_msglevel		= wx_get_msglevel,
 	.get_coalesce		= wx_get_coalesce,
 	.get_ts_info		= ethtool_op_get_ts_info,
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index d042567b8128..2e5dba88d04a 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -3248,8 +3248,8 @@ netdev_features_t wx_features_check(struct sk_buff *skb,
 }
 EXPORT_SYMBOL(wx_features_check);
 
-void wx_set_ring(struct wx *wx, u32 new_tx_count,
-		 u32 new_rx_count, struct wx_ring *temp_ring)
+int wx_set_ring(struct wx *wx, u32 new_tx_count,
+		u32 new_rx_count, struct wx_ring *temp_ring)
 {
 	int i, err = 0;
 
@@ -3271,7 +3271,7 @@ void wx_set_ring(struct wx *wx, u32 new_tx_count,
 					i--;
 					wx_free_tx_resources(&temp_ring[i]);
 				}
-				return;
+				return err;
 			}
 		}
 
@@ -3299,7 +3299,7 @@ void wx_set_ring(struct wx *wx, u32 new_tx_count,
 					i--;
 					wx_free_rx_resources(&temp_ring[i]);
 				}
-				return;
+				return err;
 			}
 		}
 
@@ -3311,6 +3311,7 @@ void wx_set_ring(struct wx *wx, u32 new_tx_count,
 
 		wx->rx_ring_count = new_rx_count;
 	}
+	return 0;
 }
 EXPORT_SYMBOL(wx_set_ring);
 
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
index aed6ea8cf0d6..bc671786978e 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
@@ -36,8 +36,8 @@ netdev_features_t wx_fix_features(struct net_device *netdev,
 netdev_features_t wx_features_check(struct sk_buff *skb,
 				    struct net_device *netdev,
 				    netdev_features_t features);
-void wx_set_ring(struct wx *wx, u32 new_tx_count,
-		 u32 new_rx_count, struct wx_ring *temp_ring);
+int wx_set_ring(struct wx *wx, u32 new_tx_count,
+		u32 new_rx_count, struct wx_ring *temp_ring);
 void wx_service_event_schedule(struct wx *wx);
 void wx_service_event_complete(struct wx *wx);
 void wx_service_timer(struct timer_list *t);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
index 0d2db8d38cd5..26de78e9a69e 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
@@ -269,7 +269,7 @@ static void wxvf_irq_enable(struct wx *wx)
 	wr32(wx, WX_VXIMC, wx->eims_enable_mask);
 }
 
-static void wxvf_up_complete(struct wx *wx)
+void wxvf_up_complete(struct wx *wx)
 {
 	/* Always set the carrier off */
 	netif_carrier_off(wx->netdev);
@@ -324,7 +324,7 @@ int wxvf_open(struct net_device *netdev)
 }
 EXPORT_SYMBOL(wxvf_open);
 
-static void wxvf_down(struct wx *wx)
+void wxvf_down(struct wx *wx)
 {
 	struct net_device *netdev = wx->netdev;
 
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h
index cbbb1b178cb2..d45d5d8ac3ab 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h
@@ -15,7 +15,9 @@ void wx_set_rx_mode_vf(struct net_device *netdev);
 void wx_configure_vf(struct wx *wx);
 int wx_set_mac_vf(struct net_device *netdev, void *p);
 void wxvf_watchdog_update_link(struct wx *wx);
+void wxvf_up_complete(struct wx *wx);
 int wxvf_open(struct net_device *netdev);
+void wxvf_down(struct wx *wx);
 int wxvf_close(struct net_device *netdev);
 void wxvf_init_service(struct wx *wx);
 
-- 
2.30.1


^ permalink raw reply related

* [PATCH net-next v6 2/3] net: libwx: add support for set_coalesce in wx_ethtool_ops_vf
From: Mengyuan Lou @ 2026-07-01 10:01 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, horms, kuba, pabeni, Mengyuan Lou
In-Reply-To: <20260701100145.23738-1-mengyuanlou@net-swift.com>

Add support for set_coalesce in wx_ethtool_ops_vf, which
is used to set interrupt coalescing parameters.

Update wx_write_eitr_vf() to use the same interrupt
moderation encoding as PF devices, since PF and VF share
the same register layout. And remove the now-unused
WX_VXITR_MASK definition.

Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
---
 drivers/net/ethernet/wangxun/libwx/wx_ethtool.c |  7 ++++++-
 drivers/net/ethernet/wangxun/libwx/wx_vf.h      |  1 -
 drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c  | 13 ++++++++++++-
 3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index eae038df6875..22037f015ded 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -10,6 +10,7 @@
 #include "wx_hw.h"
 #include "wx_lib.h"
 #include "wx_vf_common.h"
+#include "wx_vf_lib.h"
 
 struct wx_stats {
 	char stat_string[ETH_GSTRING_LEN];
@@ -488,7 +489,10 @@ int wx_set_coalesce(struct net_device *netdev,
 		else
 			/* rx only or mixed */
 			q_vector->itr = rx_itr_param;
-		wx_write_eitr(q_vector);
+		if (wx->pdev->is_virtfn)
+			wx_write_eitr_vf(q_vector);
+		else
+			wx_write_eitr(q_vector);
 	}
 
 	wx_update_rsc(wx);
@@ -845,6 +849,7 @@ static const struct ethtool_ops wx_ethtool_ops_vf = {
 	.set_ringparam		= wx_set_ringparam_vf,
 	.get_msglevel		= wx_get_msglevel,
 	.get_coalesce		= wx_get_coalesce,
+	.set_coalesce		= wx_set_coalesce,
 	.get_ts_info		= ethtool_op_get_ts_info,
 	.get_link_ksettings	= wx_get_link_ksettings_vf,
 };
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf.h b/drivers/net/ethernet/wangxun/libwx/wx_vf.h
index eb6ca3fe4e97..b64a4de089f2 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf.h
@@ -41,7 +41,6 @@
 #define WX_VF_MAX_RX_QUEUES      4
 
 #define WX_VXITR(i)              (0x200 + (4 * (i))) /* i=[0,1] */
-#define WX_VXITR_MASK            GENMASK(8, 0)
 #define WX_VXITR_CNT_WDIS        BIT(31)
 #define WX_VXIVAR_MISC           0x260
 #define WX_VXIVAR(i)             (0x240 + (4 * (i))) /* i=[0,3] */
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c
index aa8be036956c..7325b475ee10 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c
@@ -16,7 +16,18 @@ void wx_write_eitr_vf(struct wx_q_vector *q_vector)
 	int v_idx = q_vector->v_idx;
 	u32 itr_reg;
 
-	itr_reg = q_vector->itr & WX_VXITR_MASK;
+	switch (wx->mac.type) {
+	case wx_mac_sp:
+		itr_reg = q_vector->itr & WX_SP_MAX_EITR;
+		break;
+	case wx_mac_aml:
+	case wx_mac_aml40:
+		itr_reg = (q_vector->itr >> 3) & WX_AML_MAX_EITR;
+		break;
+	default:
+		itr_reg = q_vector->itr & WX_EM_MAX_EITR;
+		break;
+	}
 
 	/* set the WDIS bit to not clear the timer bits and cause an
 	 * immediate assertion of the interrupt
-- 
2.30.1


^ permalink raw reply related

* [PATCH net-next v6 3/3] net: libwx: support vf per-queue statistics via ethtool -S
From: Mengyuan Lou @ 2026-07-01 10:01 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, horms, kuba, pabeni, Mengyuan Lou
In-Reply-To: <20260701100145.23738-1-mengyuanlou@net-swift.com>

Add per-queue TX/RX packet and byte counters to the VF ethtool stats
table.
Convert WX_NUM_{RX,TX}_QUEUES macros to take explicit netdev parameter.
Then replace both WX_GLOBAL_STATS_LEN and WX_STATS_LEN macros with
type-safe static helpers wx_global_stats_len() and wx_stats_len().
The stats length is now dynamically determined based on whether the
device is a VF or PF via wx_stats_len().
Add ring access protection in wx_update_stats.

Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
---
 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 71 +++++++++++++------
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    |  8 +++
 .../net/ethernet/wangxun/libwx/wx_vf_common.c |  2 +
 3 files changed, 60 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 22037f015ded..f72908630ea4 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -48,6 +48,10 @@ static const struct wx_stats wx_gstrings_stats[] = {
 	WX_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
 };
 
+static const struct wx_stats wx_gstrings_stats_vf[] = {
+	WX_STAT("non_eop_descs", non_eop_descs),
+};
+
 static const struct wx_stats wx_gstrings_fdir_stats[] = {
 	WX_STAT("fdir_match", stats.fdirmatch),
 	WX_STAT("fdir_miss", stats.fdirmiss),
@@ -63,21 +67,33 @@ static const struct wx_stats wx_gstrings_rsc_stats[] = {
  * used because we do not have a good way to get the max number of
  * rx queues with CONFIG_RPS disabled.
  */
-#define WX_NUM_RX_QUEUES netdev->num_tx_queues
-#define WX_NUM_TX_QUEUES netdev->num_tx_queues
-
-#define WX_QUEUE_STATS_LEN ( \
-		(WX_NUM_TX_QUEUES + WX_NUM_RX_QUEUES) * \
-		(sizeof(struct wx_queue_stats) / sizeof(u64)))
-#define WX_GLOBAL_STATS_LEN  ARRAY_SIZE(wx_gstrings_stats)
+#define WX_NUM_RX_QUEUES(netdev) ((netdev)->num_tx_queues)
+#define WX_NUM_TX_QUEUES(netdev) ((netdev)->num_tx_queues)
 #define WX_FDIR_STATS_LEN  ARRAY_SIZE(wx_gstrings_fdir_stats)
 #define WX_RSC_STATS_LEN  ARRAY_SIZE(wx_gstrings_rsc_stats)
-#define WX_STATS_LEN (WX_GLOBAL_STATS_LEN + WX_QUEUE_STATS_LEN)
+
+static unsigned int wx_global_stats_len(const struct wx *wx)
+{
+	return wx->pdev->is_virtfn ?
+	       ARRAY_SIZE(wx_gstrings_stats_vf) : ARRAY_SIZE(wx_gstrings_stats);
+}
+
+static unsigned int wx_stats_len(const struct wx *wx)
+{
+	struct net_device *netdev = wx->netdev;
+	unsigned int queue_stats_len;
+
+	queue_stats_len = (WX_NUM_TX_QUEUES(netdev) +
+			   WX_NUM_RX_QUEUES(netdev)) *
+			  (sizeof(struct wx_queue_stats) / sizeof(u64));
+
+	return wx_global_stats_len(wx) + queue_stats_len;
+}
 
 int wx_get_sset_count(struct net_device *netdev, int sset)
 {
 	struct wx *wx = netdev_priv(netdev);
-	int len = WX_STATS_LEN;
+	int len = wx_stats_len(wx);
 
 	switch (sset) {
 	case ETH_SS_STATS:
@@ -100,8 +116,11 @@ void wx_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
 
 	switch (stringset) {
 	case ETH_SS_STATS:
-		for (i = 0; i < WX_GLOBAL_STATS_LEN; i++)
-			ethtool_puts(&p, wx_gstrings_stats[i].stat_string);
+		for (i = 0; i < wx_global_stats_len(wx); i++)
+			if (wx->pdev->is_virtfn)
+				ethtool_puts(&p, wx_gstrings_stats_vf[i].stat_string);
+			else
+				ethtool_puts(&p, wx_gstrings_stats[i].stat_string);
 		if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) {
 			for (i = 0; i < WX_FDIR_STATS_LEN; i++)
 				ethtool_puts(&p, wx_gstrings_fdir_stats[i].stat_string);
@@ -114,7 +133,7 @@ void wx_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
 			ethtool_sprintf(&p, "tx_queue_%u_packets", i);
 			ethtool_sprintf(&p, "tx_queue_%u_bytes", i);
 		}
-		for (i = 0; i < WX_NUM_RX_QUEUES; i++) {
+		for (i = 0; i < WX_NUM_RX_QUEUES(netdev); i++) {
 			ethtool_sprintf(&p, "rx_queue_%u_packets", i);
 			ethtool_sprintf(&p, "rx_queue_%u_bytes", i);
 		}
@@ -134,10 +153,16 @@ void wx_get_ethtool_stats(struct net_device *netdev,
 
 	wx_update_stats(wx);
 
-	for (i = 0; i < WX_GLOBAL_STATS_LEN; i++) {
-		p = (char *)wx + wx_gstrings_stats[i].stat_offset;
-		data[i] = (wx_gstrings_stats[i].sizeof_stat ==
-			   sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+	for (i = 0; i < wx_global_stats_len(wx); i++) {
+		if (wx->pdev->is_virtfn) {
+			p = (char *)wx + wx_gstrings_stats_vf[i].stat_offset;
+			data[i] = (wx_gstrings_stats_vf[i].sizeof_stat ==
+				   sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+		} else {
+			p = (char *)wx + wx_gstrings_stats[i].stat_offset;
+			data[i] = (wx_gstrings_stats[i].sizeof_stat ==
+				   sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+		}
 	}
 
 	if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) {
@@ -169,7 +194,7 @@ void wx_get_ethtool_stats(struct net_device *netdev,
 		} while (u64_stats_fetch_retry(&ring->syncp, start));
 		i += 2;
 	}
-	for (j = 0; j < WX_NUM_RX_QUEUES; j++) {
+	for (j = 0; j < WX_NUM_RX_QUEUES(netdev); j++) {
 		ring = wx->rx_ring[j];
 		if (!ring) {
 			data[i++] = 0;
@@ -219,19 +244,20 @@ EXPORT_SYMBOL(wx_get_pause_stats);
 
 void wx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
 {
-	unsigned int stats_len = WX_STATS_LEN;
 	struct wx *wx = netdev_priv(netdev);
+	unsigned int stats_len;
 
+	stats_len = wx_stats_len(wx);
 	if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags))
 		stats_len += WX_FDIR_STATS_LEN;
 
 	strscpy(info->driver, wx->driver_name, sizeof(info->driver));
 	strscpy(info->fw_version, wx->eeprom_id, sizeof(info->fw_version));
 	strscpy(info->bus_info, pci_name(wx->pdev), sizeof(info->bus_info));
-	if (wx->num_tx_queues <= WX_NUM_TX_QUEUES) {
+	if (wx->num_tx_queues <= WX_NUM_TX_QUEUES(netdev)) {
 		info->n_stats = stats_len -
-				   (WX_NUM_TX_QUEUES - wx->num_tx_queues) *
-				   (sizeof(struct wx_queue_stats) / sizeof(u64)) * 2;
+				(WX_NUM_TX_QUEUES(netdev) - wx->num_tx_queues) *
+				(sizeof(struct wx_queue_stats) / sizeof(u64)) * 2;
 	} else {
 		info->n_stats = stats_len;
 	}
@@ -852,6 +878,9 @@ static const struct ethtool_ops wx_ethtool_ops_vf = {
 	.set_coalesce		= wx_set_coalesce,
 	.get_ts_info		= ethtool_op_get_ts_info,
 	.get_link_ksettings	= wx_get_link_ksettings_vf,
+	.get_sset_count		= wx_get_sset_count,
+	.get_strings		= wx_get_strings,
+	.get_ethtool_stats	= wx_get_ethtool_stats,
 };
 
 void wx_set_ethtool_ops_vf(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 260e14d5d541..349afbe60132 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -2886,6 +2886,8 @@ void wx_update_stats(struct wx *wx)
 	for (i = 0; i < wx->num_rx_queues; i++) {
 		struct wx_ring *rx_ring = wx->rx_ring[i];
 
+		if (!rx_ring)
+			continue;
 		non_eop_descs += rx_ring->rx_stats.non_eop_descs;
 		alloc_rx_buff_failed += rx_ring->rx_stats.alloc_rx_buff_failed;
 		hw_csum_rx_good += rx_ring->rx_stats.csum_good_cnt;
@@ -2911,12 +2913,17 @@ void wx_update_stats(struct wx *wx)
 	for (i = 0; i < wx->num_tx_queues; i++) {
 		struct wx_ring *tx_ring = wx->tx_ring[i];
 
+		if (!tx_ring)
+			continue;
 		restart_queue += tx_ring->tx_stats.restart_queue;
 		tx_busy += tx_ring->tx_stats.tx_busy;
 	}
 	wx->restart_queue = restart_queue;
 	wx->tx_busy = tx_busy;
 
+	if (wx->pdev->is_virtfn)
+		goto skip_hw_stats;
+
 	wx_update_xoff_rx_lfc(wx);
 
 	hwstats->gprc += rd32(wx, WX_RDM_PKT_CNT);
@@ -2956,6 +2963,7 @@ void wx_update_stats(struct wx *wx)
 		hwstats->qmprc += rd32_wrap(wx, WX_PX_MPRC(i),
 					    &wx->last_stats.qmprc[i]);
 
+skip_hw_stats:
 	spin_unlock(&wx->hw_stats_lock);
 }
 EXPORT_SYMBOL(wx_update_stats);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
index 26de78e9a69e..1d84fe35d7d9 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
@@ -5,6 +5,7 @@
 #include <linux/pci.h>
 
 #include "wx_type.h"
+#include "wx_hw.h"
 #include "wx_mbx.h"
 #include "wx_lib.h"
 #include "wx_vf.h"
@@ -409,6 +410,7 @@ static void wxvf_service_task(struct work_struct *work)
 
 	wxvf_link_config_subtask(wx);
 	wxvf_reset_subtask(wx);
+	wx_update_stats(wx);
 	wx_service_event_complete(wx);
 }
 
-- 
2.30.1


^ permalink raw reply related

* [PATCH net-next v6 0/3] net: libwx: improve VF ethtool support
From: Mengyuan Lou @ 2026-07-01 10:01 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, horms, kuba, pabeni, Mengyuan Lou

This series improves ethtool support for Wangxun VF drivers
(ngbevf and txgbevf) in libwx.

This series extends VF support by enabling:
ring parameter configuration via ethtool -G
interrupt coalescing configuration via ethtool -C
per-queue statistics reporting via ethtool -S

Patch 1 adds support for set_ringparam in wx_ethtool_ops_vf,
allowing VF users to adjust TX/RX descriptor ring sizes.
Patch 2 enables set_coalesce support for VF devices and updates
EITR programming to use the VF-specific register access helper.
Patch 3 adds VF statistics support so ethtool -S can
report useful runtime counters for VF interfaces.

Changelog:
v6:
- Patch 1:
  Clarify comments describing wx_set_ring() failure semantics.
- Patch 2:
  Expand commit message to explain VF ITR encoding changes.
- Patch 3:
  Protect ring accesses in wx_update_stats().
v5: https://lore.kernel.org/all/20260615104849.60444-1-mengyuanlou@net-swift.com
- Patch 3:
  Convert WX_NUM_{RX,TX}_QUEUES macros to take explicit netdev parameter
  as suggested by Simon Horman.
v4: https://lore.kernel.org/all/20260608103946.25786-1-mengyuanlou@net-swift.com
  sashiko: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260529075147.88398-1-mengyuanlou%40net-swift.com
- Patch 2:
  PF and VF share the same ITR value range. Update wx_write_eitr_vf() to apply
  identical range clamping as the PF path, ensuring consistent coalesce behavior
  across both device types.
- Patch 3:
  Remove wx_update_stats in wxvf_down.
  Replace both WX_GLOBAL_STATS_LEN and WX_STATS_LEN macros with type-safe
  static helpers wx_global_stats_len() and wx_stats_len().
v3: https://lore.kernel.org/all/20260529075147.88398-1-mengyuanlou@net-swift.com
- Patch 3:
  Drop netdev_stat_ops support from this patch.
v2: https://lore.kernel.org/all/20260525101115.13151-1-mengyuanlou@net-swift.com
- Patch 3:
  Remove some stats which can be replaced by standard stats defined in
  include/net/netdev_queues.h.
- Patch 1:
  Adding a return value to wx_set_ring to make wx_set_ringparam_vf can
  be passed back to userspace.
  Remove freeing and requesting of IRQs. Ring resize only updates descriptor
  resources and does not change MSI-X vector or interrupt configuration,
  so IRQs do not need to be reallocated.
v1: https://lore.kernel.org/all/20260514103405.42175-1-mengyuanlou@net-swift.com



Mengyuan Lou (3):
  net: libwx: add support for set_ringparam in wx_ethtool_ops_vf
  net: libwx: add support for set_coalesce in wx_ethtool_ops_vf
  net: libwx: support vf per-queue statistics via ethtool -S

 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 139 +++++++++++++++---
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    |   8 +
 drivers/net/ethernet/wangxun/libwx/wx_lib.c   |   9 +-
 drivers/net/ethernet/wangxun/libwx/wx_lib.h   |   4 +-
 drivers/net/ethernet/wangxun/libwx/wx_vf.h    |   1 -
 .../net/ethernet/wangxun/libwx/wx_vf_common.c |   6 +-
 .../net/ethernet/wangxun/libwx/wx_vf_common.h |   2 +
 .../net/ethernet/wangxun/libwx/wx_vf_lib.c    |  13 +-
 8 files changed, 150 insertions(+), 32 deletions(-)

-- 
2.30.1


^ permalink raw reply

* Re: [PATCH v2 2/6] Bluetooth: btqca: Add IPQ5018 support
From: Bartosz Golaszewski @ 2026-07-01  9:59 UTC (permalink / raw)
  To: george.moussalem
  Cc: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
	Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
	Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
	Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
	Mathieu Poirier, Philipp Zabel, George Moussalem via B4 Relay,
	linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
	ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
In-Reply-To: <20260629-ipq5018-bluetooth-v2-2-02770f03b6bb@outlook.com>

On Mon, 29 Jun 2026 15:01:45 +0200, George Moussalem via B4 Relay
<devnull+george.moussalem.outlook.com@kernel.org> said:
> From: George Moussalem <george.moussalem@outlook.com>
>
> Add the IPQ5018 SoC type and support for loading its firmware.
>
> The firmware tested has been taken from GPL sources of various router
> boards. Firmware files needed are:
> - qca/bt_fw_patch.mbn
> - qca/mpnv10.bin
>
> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
> ---

Acked-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>

^ permalink raw reply

* Re: [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes
From: Bartosz Golaszewski @ 2026-07-01  9:58 UTC (permalink / raw)
  To: george.moussalem
  Cc: George Moussalem via B4 Relay, linux-block, linux-kernel,
	linux-mmc, devicetree, linux-wireless, ath10k, linux-arm-msm,
	linux-bluetooth, netdev, linux-remoteproc, Jens Axboe,
	Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Johannes Berg, Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
	Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
	Saravana Kannan, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Bjorn Andersson, Konrad Dybcio, Mathieu Poirier,
	Philipp Zabel
In-Reply-To: <20260629-ipq5018-bluetooth-v2-3-02770f03b6bb@outlook.com>

On Mon, 29 Jun 2026 15:01:46 +0200, George Moussalem via B4 Relay
<devnull+george.moussalem.outlook.com@kernel.org> said:
> From: George Moussalem <george.moussalem@outlook.com>
>
> The Bluetooth subsystem (BTSS) on the IPQ5018 SoC supports setting power
> modes which are required to be configured through a Secure Channel
> Manager (SCM) call to TrustZone. However, not all Trusted Execution
> Environment (QSEE) images support this call, so first check if the call
> is available.
>
> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
> ---

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>

^ permalink raw reply

* [PATCH v3 1/1] bus: mhi: pci_generic: fix Rolling Wireless RW135R-GL and RW151 support
From: zwq2226404116 @ 2026-07-01  9:53 UTC (permalink / raw)
  To: mhi, linux-arm-msm, netdev
  Cc: mani, loic.poulain, ryazanov.s.a, andrew+netdev, davem, kuba,
	Wanquan Zhong

From: Wanquan Zhong <wanquan.zhong@fibocom.com>

bus: mhi: pci_generic: fix Rolling Wireless RW135R-GL and RW151 support

- Increase RW151 MBIM channel ring size from 4 to 32

On HP and Lenovo laptop platforms the device probes successfully and
WWAN ports are created, but pci_generic enables runtime autosuspend
(PCI D3hot/M3) after a short idle period. Resume from runtime PM leaves
the modem in MHI SYS ERROR; driver recovery (reset) fails and the device
becomes inaccessible (PCIe config space reads as 0x7f). The failure is not
self-recoverable while runtime PM remains enabled; keeping power/control=on
avoids the issue.

Set no_m3 on RW135R-GL and RW151 so probe does not enable runtime M3
autosuspend for these modules.

Power management testing (separate from runtime PM above):
- Suspend-to-RAM (S3/mem): tested on RW135R-GL and RW151; MHI/MBIM/wwan
  function after wake.
- Suspend-to-disk (hibernate): not available on the test platforms
  (/sys/power/state lacks "disk", ENODEV).

Signed-off-by: Wanquan Zhong <wanquan.zhong@fibocom.com>

---
v2 -> v3: RW151 MBIM ring size 32; disable runtime M3 (no_m3)
 drivers/bus/mhi/host/pci_generic.c | 4 +++-
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
index d598bb3b3981..d0fee7e3ba3a 100644
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -942,6 +942,7 @@ static const struct mhi_pci_dev_info mhi_rolling_rw135r_info = {
 	.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
 	.dma_data_width = 32,
 	.sideband_wake = false,
+	.no_m3 = true,
 	.mru_default = 32768,
 	.edl_trigger = true,
 };
@@ -949,8 +950,8 @@ static const struct mhi_pci_dev_info mhi_rolling_rw135r_info = {
 static const struct mhi_channel_config mhi_rolling_rw151_channels[] = {
 	MHI_CHANNEL_CONFIG_UL(4, "DIAG", 16, 1),
 	MHI_CHANNEL_CONFIG_DL(5, "DIAG", 16, 1),
-	MHI_CHANNEL_CONFIG_UL(12, "MBIM", 4, 0),
-	MHI_CHANNEL_CONFIG_DL(13, "MBIM", 4, 0),
+	MHI_CHANNEL_CONFIG_UL(12, "MBIM", 32, 0),
+	MHI_CHANNEL_CONFIG_DL(13, "MBIM", 32, 0),
 	MHI_CHANNEL_CONFIG_UL(14, "NMEA", 32, 0),
 	MHI_CHANNEL_CONFIG_DL(15, "NMEA", 32, 0),
 	MHI_CHANNEL_CONFIG_UL(32, "DUN", 32, 0),
@@ -986,6 +987,7 @@ static const struct mhi_pci_dev_info mhi_rolling_rw151_info = {
 	.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
 	.dma_data_width = 32,
 	.sideband_wake = false,
+	.no_m3 = true,
 	.mru_default = 32768,
 	.edl_trigger = true,
 };

--
2.50.0


^ permalink raw reply related

* Re: [PATCH 3/9] ax88179_178a: Add support for AX88179A MMD access
From: Maxime Chevallier @ 2026-07-01  9:53 UTC (permalink / raw)
  To: Birger Koblitz, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: linux-usb, netdev, linux-kernel
In-Reply-To: <20260701-ax88179a-v1-3-13685df67515@birger-koblitz.de>

Hi,

On 7/1/26 07:42, Birger Koblitz wrote:
> The AX88179A uses a much simpler Clause-45 MMD access interface,
> make use of this interface and abstract MMD read/write operations
> for the AX88179 and AX88179A architecture by introducing
> ax_read_mmd() and ax_write_mmd(), which in turn call the chips'
> respective implementation.
> 
> Make use of the MMD read/write functions in the link-speed and EEE
> configuration settings via ethtool in order to support the
> AX179A-based chips. The AX88279 supports EEE only at 1000MBit speed,
> the other chips require full duplex.

Please split this into smaller patches, one for the mmd accessor conversion,
one for eee, one for the new chip support, etc.

> 
> Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>

[...]

> @@ -866,34 +924,63 @@ static int ax88179_set_link_ksettings(struct net_device *net,
>  				      const struct ethtool_link_ksettings *cmd)
>  {
>  	struct usbnet *dev = netdev_priv(net);
> +	struct ax88179_data *data;
> +	int v;
> +
> +	data = dev->driver_priv;
> +
> +	/* mii_ethtool_set_link_ksettings handles unknown bits in MII_ADVERTISE
> +	 * transparently, so for the 2.5GBit link speed of the AX_VERSION_AX88279
> +	 * we just set up ADVERTISE_RESV before calling mii_ethtool_set_link_ksettings
> +	 * at least for speeds < 2500
> +	 */

ADVERTISE_RESV isn't an unknown bit, it's been added in 802.3 as ADVERTISE_XNP
for Extended Next Page, see :

commit e7a62edd34b1 ("net: phy: qcom: at803x: Use the correct bit to disable extended next page")

we shoudln't use ADVERTISE_RESV anymore in-kernel (there are a few callsites left).

As this seems to be a vendor-specific behaviour for that bit, please add a
local #define for it in this driver, to make it clear that this is a device-specific
value.

Thanks,

Maxime

^ permalink raw reply

* Re: [PATCH v4 5/5] drm/xe/sysctrl: Reuse xe_sysctrl_create_command()
From: Tauro, Riana @ 2026-07-01  9:50 UTC (permalink / raw)
  To: Raag Jadav, intel-xe, dri-devel, netdev
  Cc: simona.vetter, airlied, kuba, lijo.lazar, Hawking.Zhang, davem,
	pabeni, edumazet, dev, zachary.mckevitt, rodrigo.vivi,
	michal.wajdeczko, matthew.d.roper, mallesh.koujalagi
In-Reply-To: <20260623101043.255897-6-raag.jadav@intel.com>


On 23-06-2026 15:39, Raag Jadav wrote:
> Now that we have a helper to create sysctrl command, reuse it for
> threshold crossed events.
>
> Signed-off-by: Raag Jadav <raag.jadav@intel.com>


Looks good to me

Reviewed-by: Riana Tauro <riana.tauro@intel.com>


> ---
>   drivers/gpu/drm/xe/xe_sysctrl_event.c | 28 ++++++++-------------------
>   1 file changed, 8 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_sysctrl_event.c b/drivers/gpu/drm/xe/xe_sysctrl_event.c
> index b4d17329af6c..0547b7b39726 100644
> --- a/drivers/gpu/drm/xe/xe_sysctrl_event.c
> +++ b/drivers/gpu/drm/xe/xe_sysctrl_event.c
> @@ -49,18 +49,6 @@ static void get_pending_event(struct xe_sysctrl *sc, struct xe_sysctrl_mailbox_c
>   	} while (response->count);
>   }
>   
> -static void event_request_prepare(struct xe_device *xe, struct xe_sysctrl_app_msg_hdr *header,
> -				  struct xe_sysctrl_event_request *request)
> -{
> -	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
> -
> -	header->data = REG_FIELD_PREP(APP_HDR_GROUP_ID_MASK, XE_SYSCTRL_GROUP_GFSP) |
> -		       REG_FIELD_PREP(APP_HDR_COMMAND_MASK, XE_SYSCTRL_CMD_GET_PENDING_EVENT);
> -
> -	request->vector = xe_device_has_msix(xe) ? XE_IRQ_DEFAULT_MSIX : 0;
> -	request->fn = PCI_FUNC(pdev->devfn);
> -}
> -
>   /**
>    * xe_sysctrl_event() - Handler for System Controller events
>    * @sc: System Controller instance
> @@ -72,16 +60,16 @@ void xe_sysctrl_event(struct xe_sysctrl *sc)
>   	struct xe_sysctrl_mailbox_command command = {};
>   	struct xe_sysctrl_event_response response = {};
>   	struct xe_sysctrl_event_request request = {};
> -	struct xe_sysctrl_app_msg_hdr header = {};
> +	struct xe_device *xe = sc_to_xe(sc);
> +	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
>   
> -	xe_device_assert_mem_access(sc_to_xe(sc));
> -	event_request_prepare(sc_to_xe(sc), &header, &request);
> +	xe_device_assert_mem_access(xe);
>   
> -	command.header = header;
> -	command.data_in = &request;
> -	command.data_in_len = sizeof(request);
> -	command.data_out = &response;
> -	command.data_out_len = sizeof(response);
> +	request.vector = xe_device_has_msix(xe) ? XE_IRQ_DEFAULT_MSIX : 0;
> +	request.fn = PCI_FUNC(pdev->devfn);
> +
> +	xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_GET_PENDING_EVENT,
> +				  &request, sizeof(request), &response, sizeof(response));
>   
>   	guard(mutex)(&sc->event_lock);
>   	get_pending_event(sc, &command);

^ permalink raw reply

* Re: [PATCH net-next V4 4/6] devlink: Apply eswitch mode boot defaults
From: Jiri Pirko @ 2026-07-01  9:48 UTC (permalink / raw)
  To: Mark Bloch
  Cc: Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Andrew Lunn,
	Jonathan Corbet, Shuah Khan, netdev, linux-rdma, linux-doc
In-Reply-To: <20260629182102.245150-5-mbloch@nvidia.com>

Mon, Jun 29, 2026 at 08:20:59PM +0200, mbloch@nvidia.com wrote:
>Apply parsed devlink_eswitch_mode= defaults after devlink registration
>and after successful reload.
>
>devl_register() may still be called before the device is ready for an

How so? I would assume that driver calls devl_register only after
everything is up and running and ready. If not, isn't it a bug?


>eswitch mode change, so keep a per-devlink delayed work item and pending
>flag for the registration path. Registration queues the work, and the
>worker tries to take the devlink instance lock.
>
>If the lock is busy, the worker requeues itself with a delay.
>
>For successful reloads that performed DRIVER_REINIT, devlink_reload()
>already holds the devlink instance lock and the driver has completed
>reload_up(). Clear pending work and apply the default directly from the
>reload path instead of queueing work.
>
>If a user sets eswitch mode through netlink before the pending
>registration work runs, clear the pending flag so the queued default does
>not override that user request. Cancel pending default apply work when
>freeing the devlink instance.

These AI generated code descriptive messages are generally not very
useful :(


^ permalink raw reply

* Re: [PATCH net-next v2 2/2] tools: ynl: pyynl: pull the --family resolution logic into the lib
From: Donald Hunter @ 2026-07-01  9:46 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, sdf, gal,
	jstancek, ast
In-Reply-To: <20260701021751.3234681-3-kuba@kernel.org>

Jakub Kicinski <kuba@kernel.org> writes:

> When packaging YNL as a system level utility we added a --family
> argument which auto-resolves the full spec path from a well known
> path in /usr/share. Spelling out full YAML spec files is at this
> point only done in-tree, for example in the selftests which need
> the very latest YAML. But the selftests have their own wrapping
> classes for each family so test authors aren't really bothered
> by having to spell the paths out.
>
> Afford the same ease of use to the Python library users.
> Move the path resolution from the CLI code to the library.
> This simplifies the pyynl use by a lot:
>
>   from pyynl import YnlFamily
>
>   ynl = YnlFamily(family="netdev")
>
> Unless I'm missing a trick, resolving the /usr/share path
> is hard enough for most users to lean towards shelling out
> to ynl CLI with --output-json, which is sad.
>
> The ethtool script can now use family= instead of
> resolving the path (the helpers are removed from cli.py
> so this isn't just a cleanup).
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>

Reviewed-by: Donald Hunter <donald.hunter@gmail.com>

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox