Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH v4 4/6] pds_core: add PLDM component info display
From: Simon Horman @ 2026-06-15 16:08 UTC (permalink / raw)
  To: nikhil.rao
  Cc: Simon Horman, netdev, brett.creeley, andrew+netdev, davem,
	edumazet, kuba, pabeni, eric.joyner
In-Reply-To: <20260614050052.1048328-5-nikhil.rao@amd.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/

Simon says: This review seems to be a bit of a mixed bag.
            I've annotated the issues it raises that I'd appreciate
	    you looking over, and the rest, which I don't feel fall
	    in that category.
---
pds_core: add PLDM component info display

This patch reports per-component firmware versions through devlink info on
v2+ devices, replacing the single fw running version with names derived
from the firmware-supplied component list and slot/flag fields.

Simon says: I'm not particularly concerned about the issue raised below -
            I'm forwarding this review because of others raised further down.

[Low]
Before going to the diff, this patch immediately renames user-visible
component names introduced in the immediately preceding commit in the
same series ("pds_core: add PLDM firmware update support via devlink
flash"):

  fw.mainfw      -> fw
  fw.mainfw.gold -> fw.gold

Could these two patches be folded together (or reordered) so the series
introduces the final naming once?  Anyone bisecting between the two
commits would land on the obsolete names.

> diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c
> index 3b763ee1715e..2f40b97affd6 100644
> --- a/drivers/net/ethernet/amd/pds_core/devlink.c
> +++ b/drivers/net/ethernet/amd/pds_core/devlink.c
> @@ -93,14 +93,105 @@ int pdsc_dl_flash_update(struct devlink *dl,
>  	return pdsc_firmware_update(pdsc, params, extack);
>  }
>  
> +static int pdsc_dl_report_component(struct devlink_info_req *req,
> +				    struct pds_core_fw_component_info *info)
> +{
> +	enum devlink_info_version_type ver_type;
> +	u16 flags = le16_to_cpu(info->flags);
> +	char *ver = info->version;
> +	const char *name;
> +	char buf[32];
> +
> +	/* Main firmware is reported as generic "fw" */
> +	if (info->component_type == PDS_CORE_FW_TYPE_MAIN) {
> +		if (info->slot_id == PDS_CORE_FW_SLOT_GOLD)
> +			snprintf(buf, sizeof(buf), "fw.gold");
> +		else
> +			snprintf(buf, sizeof(buf), "fw");
> +	} else {
> +		name = pdsc_fw_type_to_name(info->component_type);
> +		if (!name)
> +			return 0;

Simon says: Ditto

[Low]
When firmware reports a component_type that pdsc_fw_type_names[] does
not know about, this returns 0 and silently drops the entry.  Should
this at least dev_warn_once() so a newer firmware advertising a new
component type does not vanish from devlink output without any
operator-visible signal?

> +
> +		if (info->slot_id == PDS_CORE_FW_SLOT_GOLD)
> +			snprintf(buf, sizeof(buf), "fw.%s.gold", name);
> +		else
> +			snprintf(buf, sizeof(buf), "fw.%s", name);
> +	}

Simon says: And this one seems intentional, so I think
            this portion of the review can be ignored.

[Low]
This branch appends ".gold" to any non-MAIN component when slot_id ==
PDS_CORE_FW_SLOT_GOLD, which produces names like fw.bootloader.gold,
fw.uboot.gold and fw.cpld.gold.  The Documentation table updated in
this same patch only lists fw.gold as the stored variant, and the
example output only mentions fw.uboot.gold.

Should the gold suffix be restricted to MAIN, or should the
documentation table be expanded to cover any component_type also
appearing as a .gold variant?

> +
> +	ver_type = DEVLINK_INFO_VERSION_TYPE_NONE;
> +	if (flags & PDS_CORE_FW_COMPONENT_INFO_F_UPDATE_BY_NAME)
> +		ver_type = DEVLINK_INFO_VERSION_TYPE_COMPONENT;
> +
> +	if (flags & PDS_CORE_FW_COMPONENT_INFO_F_FIXED) {

[ ... ]

> +	return 0;
> +}
> +
> +static int pdsc_dl_component_info_get(struct devlink *dl,
> +				      struct devlink_info_req *req,
> +				      struct netlink_ext_ack *extack)
> +{
> +	struct pds_core_component_list_info *list_info;
> +	struct pdsc *pdsc = devlink_priv(dl);
> +	u8 num_components;
> +	int err;
> +	int i;
> +
> +	if (!pdsc->fw_components.num_components) {
> +		err = pdsc_get_component_info(pdsc);
> +		if (err) {
> +			dev_err(pdsc->dev, "Failed to get component_info %pe\n",
> +				ERR_PTR(err));
> +			return err;
> +		}
> +	}

Simon says: ditto

[Medium, Medium]
Two questions about the cache check above.

First, pdsc_get_component_info() has a branch that returns 0 without
populating num_components when firmware reports
comp.get_component_info.ver == 0:

  if (comp.get_component_info.ver == 0) {
          dev_warn_once(pdsc->dev,
                        "Incompatible get_component_info version %u ...\n",
                        comp.get_component_info.ver);
          err = 0;
          goto out;
  }

Since pdsc->fw_components.num_components stays 0 on this path, every
subsequent devlink dev info request re-enters pdsc_get_component_info()
and runs through kmalloc / kzalloc(PDS_PAGE_SIZE) / dma_map_single() /
a full devcmd round-trip with pdsc->devcmd_timeout * 2 under
devcmd_lock / dma_unmap_single().  dev_warn_once() suppresses the
warning after the first hit, so the repetition is invisible.  Should
there be an "unsupported" sentinel that prevents re-querying once v0
firmware is detected?


Simon says: However, the issue flagged below seems to warrant
            investigation in the context of this patch-set.

Second, pdsc->fw_components is only invalidated at the end of
pdsc_firmware_update() ("pdsc->fw_components.num_components = 0;").
If firmware versions change through any other path (FW recovery via
health_work, PCI reset via pci_reset_work, side-channel upgrade) the
cached list stays around and devlink dev info reports stale versions.
Should those reset paths also clear pdsc->fw_components?

> +
> +	list_info = &pdsc->fw_components;
> +	num_components = min_t(u16, list_info->num_components,
> +			       le16_to_cpu(pdsc->dev_ident.max_fw_slots));

Simon says: Likewise, the one below seems to warrant investigation too.

[Medium]
num_components has already been bounded against
PDS_CORE_FW_COMPONENT_LIST_LEN inside pdsc_get_component_info().
max_fw_slots looks like a slot count (gold/main-a/main-b), but the
component list also contains cpld/bootloader/uboot/etc.  If firmware
reports six components on a three-slot device, this min_t() silently
truncates legitimate component entries from the devlink output.

Is this cap intentional, and if so should truncation be logged?  If
not, can the cap simply be dropped?

> +	for (i = 0; i < num_components; i++) {
> +		err = pdsc_dl_report_component(req, &list_info->info[i]);
> +		if (err)
> +			return err;
> +	}
> +
> +	return 0;
> +}
> +
>  static char *fw_slotnames[] = {
>  	"fw.goldfw",
>  	"fw.mainfwa",
>  	"fw.mainfwb",
>  };
>  
> -int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
> -		     struct netlink_ext_ack *extack)
> +static int pdsc_dl_fw_list_info_get(struct devlink *dl,
> +				    struct devlink_info_req *req,
> +				    struct netlink_ext_ack *extack)
>  {

[ ... ]

> @@ -134,12 +225,49 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
>  			return err;
>  	}
>  
> +	return 0;
> +}
> +
> +static int pdsc_dl_info_get_v1(struct devlink *dl,
> +			       struct devlink_info_req *req,
> +			       struct netlink_ext_ack *extack)
> +{
> +	struct pdsc *pdsc = devlink_priv(dl);
> +	int err;
> +
> +	err = pdsc_dl_fw_list_info_get(dl, req, extack);
> +	if (err)
> +		dev_warn_once(pdsc->dev, "Failed to get fw list: %pe\n",
> +			      ERR_PTR(err));

Simon says: Again, the one below seems to warrant investigation.

[Medium]
Pre-patch, devlink_info_version_stored_put() failures inside the fw
list loop returned to the devlink layer immediately.  After this
refactor, pdsc_dl_fw_list_info_get() returns the error but
pdsc_dl_info_get_v1() converts it to dev_warn_once() and continues to
append the running fw version and the ASIC fields.

Does this mean a mid-loop failure (for example -EMSGSIZE from netlink
attribute append) is now masked, leaving a partially populated devlink
info reply that gets reported as success?

> +
> +	/* Version 1: report fw from dev_info (running only) */
>  	err = devlink_info_version_running_put(req,
>  					       DEVLINK_INFO_VERSION_GENERIC_FW,
>  					       pdsc->dev_info.fw_version);
>  	if (err)
>  		return err;
>  
> +	return 0;
> +}
> +
> +int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
> +		     struct netlink_ext_ack *extack)
> +{
> +	struct pdsc *pdsc = devlink_priv(dl);
> +	char buf[32];
> +	int err;
> +
> +	if (pdsc->dev_ident.version >= PDS_CORE_IDENTITY_VERSION_2) {
> +		err = pdsc_dl_component_info_get(dl, req, extack);
> +		if (err)
> +			dev_warn_once(pdsc->dev, "Failed to get component info: %pe\n",
> +				      ERR_PTR(err));
> +	} else {
> +		err = pdsc_dl_info_get_v1(dl, req, extack);
> +		if (err)
> +			return err;
> +	}

Simon says: but this one seems to be more a question of style that substance.

[Medium]
On v2+ devices, errors from pdsc_dl_component_info_get() are swallowed
into dev_warn_once() and the function falls through to the ASIC
fields.  Pre-patch behavior always reported pdsc->dev_info.fw_version
via DEVLINK_INFO_VERSION_GENERIC_FW.

After this change, transient failures inside pdsc_get_component_info()
(DMA mapping failure, -ENOMEM, the -ETIMEDOUT/-EAGAIN deferred-DMA
path, the v0-firmware return-0-without-populating branch, the
num_components > LIST_LEN -ENOMEM branch), or even firmware enumerating
components without setting PDS_CORE_FW_COMPONENT_INFO_F_RUNNING on the
MAIN component, cause devlink dev info to show only asic.id, asic.rev
and the serial number with no firmware version reported at all.

Could the v2 path either retain the unconditional running fw fallback
from dev_info.fw_version, or fall through to pdsc_dl_info_get_v1() on
failure, so devlink info never silently loses the fw running version?

Also, since dev_warn_once() suppresses the warning across the lifetime
of the device, callers cannot tell that the netlink reply is partial:
a partially populated message gets the ASIC fields appended and is
reported as success.

> +
>  	snprintf(buf, sizeof(buf), "0x%x", pdsc->dev_info.asic_type);
>  	err = devlink_info_version_fixed_put(req,
>  					     DEVLINK_INFO_VERSION_GENERIC_ASIC_ID,

^ permalink raw reply

* Re: [PATCH 0/5] vmsplice: fix some problems in my previous vmsplice patchset
From: David Hildenbrand (Arm) @ 2026-06-15 16:16 UTC (permalink / raw)
  To: Askar Safin, linux-fsdevel, Christian Brauner, Alexander Viro,
	Jan Kara
  Cc: linux-kernel, linux-mm, linux-api, netdev, fuse-devel, ltp,
	Linus Torvalds, Matthew Wilcox, Jens Axboe, Christoph Hellwig,
	David Howells, Andrew Morton, Pedro Falcato, Miklos Szeredi,
	Andy Lutomirski, Collin Funk, David Laight, Stefan Metzmacher,
	Steven Rostedt, The 8472, Willy Tarreau, Joanne Koong, patches,
	Joanne Koong
In-Reply-To: <20260606061031.3744880-1-safinaskar@gmail.com>

On 6/6/26 08:10, Askar Safin wrote:
> This patchset is for VFS. Of course, it depends on my previous vmsplice
> patchset.
> 
> I fix some problems in my previous patchset.
> 
> 1. Fix problem with CLASS(fd, f)(fd). See first patch for details.
> This is probably not so important, but I fix it anyway.
> 
> 2. Change "unsigned long" back to "int". See second patch for details.
> Again, this is probably not important, but I want to fix this anyway.
> 
> 3. Fix that LTP vmsplice01 bug.
> 
> See patches for details.
> 
> Please, run that LTP vmsplice01 test again.

How to proceed with this patch set given that, as Joanne explains [1], libfuse
seems to modify the data in the page after splicing, so really depending on
vmsplice() reading data that we update through the page tables -- the page
actually being pinned.

IIUC, reverting the patch might be required. Or maybe Christian can still simply
drop the topic branch entirely.

[1]
https://lore.kernel.org/r/CAJnrk1Y9egYizkx1H9K0cqxSYuB+7vLvQbV7Tf4C5eHFqnnC-A@mail.gmail.com


-- 
Cheers,

David

^ permalink raw reply

* Re: [PATCH RESEND 1/6] sock: add sock_kzalloc helper
From: Jakub Kicinski @ 2026-06-15 16:15 UTC (permalink / raw)
  To: Thorsten Blum
  Cc: Herbert Xu, David S. Miller, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Simon Horman, linux-crypto,
	linux-kernel, netdev
In-Reply-To: <ai7JfHTFgFt6YN_K@linux.dev>

On Sun, 14 Jun 2026 17:32:12 +0200 Thorsten Blum wrote:
> Gentle ping? Patch 1/6 still needs an ack from netdev maintainers.

Perhaps other maintainers shared my feeling that this is a waste of
time.

^ permalink raw reply

* Re: [PATCH net-next v7 0/5] net: wangxun: timeout and error
From: Jakub Kicinski @ 2026-06-15 16:12 UTC (permalink / raw)
  To: Jiawen Wu
  Cc: netdev, Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Richard Cochran, Russell King, Aleksandr Loktionov,
	Jacob Keller, Michal Swiatkowski, Simon Horman, Kees Cook,
	Greg Kroah-Hartman, Thomas Gleixner, Breno Leitao, Larysa Zaremba,
	Uwe Kleine-König (The Capable Hub), Fabio Baltieri
In-Reply-To: <20260615065016.21672-1-jiawenwu@trustnetic.com>

On Mon, 15 Jun 2026 14:50:11 +0800 Jiawen Wu wrote:
> It is about adding the Tx timeout process and pci_error_handlers.
> When a PCIe error occurs, the txgbe device is able to recover on platform
> that support AER interrupt. And for Tx timeout, the txgbe driver can
> recover the device by reset process.
> 
> For ngbe devices, due to the absence of the current function, it cannot
> br fully recovered once there is a PCIe error or Tx timeout. Its
> function will be completed in the future.

net-next is closed, please repost after the merge window
-- 
pw-bot: defer

^ permalink raw reply

* Re: net: netdev-genl: NETDEV_A_NAPI_PID is the init-ns pid, not the caller's
From: Jakub Kicinski @ 2026-06-15 16:12 UTC (permalink / raw)
  To: Maoyi Xie
  Cc: David S . Miller, Eric Dumazet, Paolo Abeni, Amritha Nambiar,
	Simon Horman, David Wei, Stanislav Fomichev, Samiullah Khawaja,
	netdev, linux-kernel
In-Reply-To: <20260615070152.1211050-1-maoyixie.tju@gmail.com>

On Mon, 15 Jun 2026 15:01:52 +0800 Maoyi Xie wrote:
> Hi all,
> 
> I noticed something in netdev_nl_napi_fill_one() and would appreciate
> your view on whether it is a real problem.
> 
> It reports the NAPI kthread pid like this:
> 
> 	if (napi->thread) {
> 		pid = task_pid_nr(napi->thread);
> 		if (nla_put_u32(rsp, NETDEV_A_NAPI_PID, pid))
> 
> task_pid_nr() returns the pid in the initial pid namespace. It is put
> into NETDEV_A_NAPI_PID without any translation to the caller's pid
> namespace.
> 
> NETDEV_CMD_NAPI_GET has no GENL_ADMIN_PERM and the family is netnsok.
> So a caller in a child pid namespace can read it. That caller then sees
> the kthread's global pid. The kthread is not in that namespace, so the
> value there should be 0.
> 
> This looks like the same case as commit 3799c2570982 ("io_uring/fdinfo:
> translate SqThread PID through caller's pid_ns").
> 
> I checked it with a small reproducer and a fix. From a child pid
> namespace the reproducer reads the kthread's global pid. With the fix it
> reads 0. I am not sure how much this matters in practice. I would
> appreciate it if you could let me know whether it is worth a fix. I am
> happy to send the patch.

Please send a patch, we should try to obey the PID namespace, indeed.

^ permalink raw reply

* Re: [PATCH net-next v7 12/12] net: airoha: add phylink support
From: Benjamin Larsson @ 2026-06-15 16:07 UTC (permalink / raw)
  To: Christian Marangi, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Simon Horman, Jonathan Corbet, Shuah Khan,
	Lorenzo Bianconi, Heiner Kallweit, Russell King, Saravana Kannan,
	Philipp Zabel, Nathan Chancellor, Nick Desaulniers, Bill Wendling,
	Justin Stitt, netdev, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-mediatek, llvm
In-Reply-To: <20260615122950.22281-13-ansuelsmth@gmail.com>

Hi.

On 15/06/2026 14:29, Christian Marangi wrote:
> Add phylink support for each GDM port. For GDM1 add the internal interface
> mode as the only supported mode. For GDM2/3/4 add the required
> configuration of the PCS to make the external PHY or attached SFP cage
> work.
>
> These needs to be defined in the GDM port node using the pcs-handle
> property.
>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> ---
>   drivers/net/ethernet/airoha/Kconfig       |   1 +
>   drivers/net/ethernet/airoha/airoha_eth.c  | 161 +++++++++++++++++++++-
>   drivers/net/ethernet/airoha/airoha_eth.h  |   3 +
>   drivers/net/ethernet/airoha/airoha_regs.h |  12 ++
>   4 files changed, 176 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/airoha/Kconfig b/drivers/net/ethernet/airoha/Kconfig
> index ad3ce501e7a5..38dcc76e5998 100644
> --- a/drivers/net/ethernet/airoha/Kconfig
> +++ b/drivers/net/ethernet/airoha/Kconfig
> @@ -20,6 +20,7 @@ config NET_AIROHA
>   	depends on NET_DSA || !NET_DSA
>   	select NET_AIROHA_NPU
>   	select PAGE_POOL
> +	select PHYLINK
>   	help
>   	  This driver supports the gigabit ethernet MACs in the
>   	  Airoha SoC family.
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 5f1a118875fb..9a42fb991bd7 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -8,6 +8,7 @@
>   #include <linux/of_reserved_mem.h>
>   #include <linux/platform_device.h>
>   #include <linux/tcp.h>
> +#include <linux/pcs/pcs.h>
>   #include <linux/u64_stats_sync.h>
>   #include <net/dst_metadata.h>
>   #include <net/page_pool/helpers.h>
> @@ -1810,6 +1811,14 @@ static int airoha_dev_open(struct net_device *netdev)
>   	u32 cur_len, pse_port = FE_PSE_PORT_PPE1;
>   	struct airoha_qdma *qdma = dev->qdma;
>   
> +	err = phylink_of_phy_connect(dev->phylink, netdev->dev.of_node, 0);
> +	if (err) {
> +		netdev_err(netdev, "could not attach PHY: %d\n", err);
> +		return err;
> +	}
> +
> +	phylink_start(dev->phylink);
> +
>   	netif_tx_start_all_queues(netdev);
>   	err = airoha_set_vip_for_gdm_port(dev, true);
>   	if (err)
> @@ -1907,6 +1916,9 @@ static int airoha_dev_stop(struct net_device *netdev)
>   		}
>   	}
>   
> +	phylink_stop(dev->phylink);
> +	phylink_disconnect_phy(dev->phylink);
> +
>   	return 0;
>   }
>   
> @@ -3168,6 +3180,151 @@ bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
>   	return false;
>   }
>   
> +/* Nothing to do in MAC, everything is handled in PCS */
> +static void airoha_mac_config(struct phylink_config *config, unsigned int mode,
> +			      const struct phylink_link_state *state)
> +{
> +}
> +
> +static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy,
> +			       unsigned int mode, phy_interface_t interface,
> +			       int speed, int duplex, bool tx_pause, bool rx_pause)
> +{
> +	struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev,
> +						  phylink_config);
> +	struct airoha_gdm_port *port = dev->port;
> +	struct airoha_eth *eth = dev->eth;
> +	u32 frag_size_tx, frag_size_rx;
> +	u32 mask, val;
> +
> +	/* TX/RX frag is configured only for GDM4 */
> +	if (port->id != AIROHA_GDM4_IDX)
> +		return;
> +
> +	switch (speed) {
> +	case SPEED_10000:
> +	case SPEED_5000:
> +		frag_size_tx = 8;
> +		frag_size_rx = 8;
> +		break;
> +	case SPEED_2500:
> +		frag_size_tx = 2;
> +		frag_size_rx = 1;
> +		break;
> +	default:
> +		frag_size_tx = 1;
> +		frag_size_rx = 0;
> +	}
> +
> +	/* Configure TX/RX frag based on speed */
> +	if (dev->nbq == 1) {
> +		mask = GDMA4_SGMII1_TX_FRAG_SIZE_MASK;

Can the naming be consistently GDM4 without the A?

MvH

Benjamin Larsson


^ permalink raw reply

* Re: [PATCH net-next v5 0/3] net: libwx: improve VF ethtool support
From: Jakub Kicinski @ 2026-06-15 16:07 UTC (permalink / raw)
  To: Mengyuan Lou; +Cc: netdev, jiawenwu, duanqiangwen, horms, pabeni
In-Reply-To: <20260615104849.60444-1-mengyuanlou@net-swift.com>

On Mon, 15 Jun 2026 18:48:46 +0800 Mengyuan Lou wrote:
> This series improves ethtool support for Wangxun VF drivers
> (ngbevf and txgbevf) in libwx.

net-next is closed, please repost after the merge window
-- 
pw-bot: cr

^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next 3/6] ice: extract function to allocate aggregator info structure
From: Rinitha, SX @ 2026-06-15 16:05 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN, netdev@vger.kernel.org,
	Nguyen, Anthony L
  Cc: Kitszel, Przemyslaw, Loktionov, Aleksandr, Keller, Jacob E,
	Loktionov, Aleksandr
In-Reply-To: <20260601-jk-cleanup-vsi-aggregator-nodes-v1-3-36d6ecbe5ede@intel.com>

> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Jacob Keller
> Sent: 02 June 2026 05:44
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>; netdev@vger.kernel.org; Nguyen, Anthony L <anthony.l.nguyen@intel.com>
> Cc: Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>; Keller, Jacob E <jacob.e.keller@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-next 3/6] ice: extract function to allocate aggregator info structure
>
> Add a new ice_alloc_agg_info() helper function which allocates an aggregator info structure with an ID between min_id and max_id, inserting it into the agg_list xarray. Use this function in ice_sched_cfg_agg().
>
> This is done in preparation of refactoring the aggregator node ID logic in ice_set_agg_vsi().
>
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> ---
> drivers/net/ethernet/intel/ice/ice_sched.c | 74 +++++++++++++++++++++---------
> 1 file changed, 52 insertions(+), 22 deletions(-)
>

Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)

^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next 4/6] ice: remove ice_agg_node wrapper structure
From: Rinitha, SX @ 2026-06-15 16:05 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN, netdev@vger.kernel.org,
	Nguyen, Anthony L
  Cc: Kitszel, Przemyslaw, Loktionov, Aleksandr, Keller, Jacob E,
	Loktionov, Aleksandr
In-Reply-To: <20260601-jk-cleanup-vsi-aggregator-nodes-v1-4-36d6ecbe5ede@intel.com>

> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Jacob Keller
> Sent: 02 June 2026 05:44
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>; netdev@vger.kernel.org; Nguyen, Anthony L <anthony.l.nguyen@intel.com>
> Cc: Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>; Keller, Jacob E <jacob.e.keller@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-next 4/6] ice: remove ice_agg_node wrapper structure
>
> The ice_set_agg_vsi() function has bespoke logic for identifying a suitable aggregator node to use for a VSI. The main goal of the function is to ensure that various types of VSIs do not share aggregator nodes. It uses fixed size arrays of struct ice_agg_node in the PF structure to keep track of which aggregator nodes are currently used.
>
> The scheduler code already keeps track of almost all of this information via the ice_sched_agg_info structures. It doesn't make sense to store similar information in two places. Indeed, this leaves open the possibility that the two have conflicting data.
>
> The recent change to refactor the aggregator info to an xarray allows lookup via index. This enables reworking the logic in ice_set_agg_vsi() and removal of the ice_agg_node wrapper structure.
>
> Introduce ice_cfg_vsi_agg() in ice_sched.c. This function will locate a suitable aggregator node between the provided minimum and maximum ID. If no node exists, it will allocate a new one. It will then configure the node and move the VSI into the node immediately.
>
> We do not free a newly allocated node if the device fails to configure the scheduler. The node will continue to exist within the aggregator node xarray list, and be reused in the future when another VSI is configured.
>
> This is similar to the logic used before, but now integrated better into the scheduler code. It also occurs all in a single critical section of the scheduler lock, rather than being split between multiple lock/unlock rounds.
>
> Remove the ice_agg_node arrays and structure, and all of its related code including the bespoke logic in ice_set_agg_vsi() as well as the associated cleanup in ice_vsi_decfg() and ice_pf_dis_all_vsi(). The logic in
> ice_pf_dis_all_vsi() is questionable anyways, since it reset the num_vsis count without clearing the valid flag or the agg_node pointers in the VSI structures. With the refactor, the VSI count for each aggregator node now always matches with what the scheduler actually has configured.
>
> Only the VF logic actually uses the previously stored aggregator node data.
> To avoid use-after-free issues, don't store a pointer to the aggregator node. Instead, store just the ID of the associated node. Update
> ice_vf_rebuild_aggregator_node_cfg() to use ice_cfg_vsi_agg() instead of using ice_move_vsi_to_agg(). This ensures that the node will be created if it was ever removed for any reason. Store the agg_id in the VSI structure using a signed 64-bit value to allow storing -1 in the case where no aggregator node was configured.
>
> This refactor drops the arrays in the ice_pf structure, reducing its size by 1152 bytes, or ~5% of the structures size.
>
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> ---
> drivers/net/ethernet/intel/ice/ice.h        |  23 ++----
> drivers/net/ethernet/intel/ice/ice_sched.h  |   5 ++
> drivers/net/ethernet/intel/ice/ice_lib.c    | 114 +++++-----------------------
> drivers/net/ethernet/intel/ice/ice_main.c   |   7 --
> drivers/net/ethernet/intel/ice/ice_sched.c  | 102 +++++++++++++++++++++++++  drivers/net/ethernet/intel/ice/ice_vf_lib.c |  22 +++---
> 6 files changed, 140 insertions(+), 133 deletions(-)
>

Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)

^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next 1/6] ice: convert hw->agg_list from linked list to xarray
From: Rinitha, SX @ 2026-06-15 16:05 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN, netdev@vger.kernel.org,
	Nguyen, Anthony L
  Cc: Kitszel, Przemyslaw, Loktionov, Aleksandr, Keller, Jacob E,
	Loktionov, Aleksandr
In-Reply-To: <20260601-jk-cleanup-vsi-aggregator-nodes-v1-1-36d6ecbe5ede@intel.com>

> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Jacob Keller
> Sent: 02 June 2026 05:44
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>; netdev@vger.kernel.org; Nguyen, Anthony L <anthony.l.nguyen@intel.com>
> Cc: Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>; Keller, Jacob E <jacob.e.keller@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-next 1/6] ice: convert hw->agg_list from linked list to xarray
>
> The scheduler code saves information about the aggregator nodes in a linked list in the hw->agg_list structure. This choice of data structure is not ideal. Indeed, several places in the code iterate the list searching to see if a given ID is present.
>
> Convert the linked list into an xarray. Where possible, simplify aggregator info lookup to use xa_load instead of iterating over all the entries.
> 
> Switching to xarray data structure better matches the existing usage pattern. In addition, it prepares the code to allow removal of the ice_agg_node wrapping structure used by ice_vsi, which will be completed in following changes.
>
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> ---
> drivers/net/ethernet/intel/ice/ice_sched.h  |  1 -
> drivers/net/ethernet/intel/ice/ice_type.h   |  2 +-
> drivers/net/ethernet/intel/ice/ice_common.c |  4 +-  drivers/net/ethernet/intel/ice/ice_sched.c  | 58 ++++++++++++-----------------
> 4 files changed, 27 insertions(+), 38 deletions(-)
>

Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)

^ permalink raw reply

* Re: [PATCH net-next v2] net: dsa: yt921x: Add limited ACL flow statistics support
From: Jakub Kicinski @ 2026-06-15 16:05 UTC (permalink / raw)
  To: David Yang
  Cc: netdev, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Paolo Abeni, linux-kernel
In-Reply-To: <20260615130356.1150110-1-mmyangfl@gmail.com>

On Mon, 15 Jun 2026 21:03:53 +0800 David Yang wrote:
> The yt921x supports flow statistics, which might be used to implement
> .cls_flower_stats(). However, the number of flow counter are limited,
> and you must choose between byte mode or packet mode. As there is no
> interface for statistics preference for now, we pick one on our own
> initiative.

net-next is closed, please repost after the merge window
-- 
pw-bot: defer

^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next 2/6] ice: count number of VSIS in agg_vsi_list
From: Rinitha, SX @ 2026-06-15 16:05 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN, netdev@vger.kernel.org,
	Nguyen, Anthony L
  Cc: Kitszel, Przemyslaw, Loktionov, Aleksandr, Keller, Jacob E,
	Loktionov, Aleksandr
In-Reply-To: <20260601-jk-cleanup-vsi-aggregator-nodes-v1-2-36d6ecbe5ede@intel.com>

> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Jacob Keller
> Sent: 02 June 2026 05:44
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>; netdev@vger.kernel.org; Nguyen, Anthony L <anthony.l.nguyen@intel.com>
> Cc: Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>; Keller, Jacob E <jacob.e.keller@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-next 2/6] ice: count number of VSIS in agg_vsi_list
>
> The ice_sched_agg_info structure maintains a list of VSIs associated with the aggregator node. A following change is going to refactor logic from ice_lib.c, and remove the ice_agg_node wrapper structure. Doing so will require keeping track of how many VSIs are on a given aggregator node.
>
> To simplify this tracking, add a member to the ice_sched_agg_info structure which counts the number of VSIs using the node. Increment it when adding a VSI to the list, and decrement when removing the VSI from the list. This will avoid the need to iterate the agg_vsi_list to determine this information.
>
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> ---
> drivers/net/ethernet/intel/ice/ice_sched.h | 1 +  drivers/net/ethernet/intel/ice/ice_sched.c | 7 +++++++
> 2 files changed, 8 insertions(+)
>

Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)

^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next 5/6] ice: remove unused aggregator node functions
From: Rinitha, SX @ 2026-06-15 16:05 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN, netdev@vger.kernel.org,
	Nguyen, Anthony L
  Cc: Kitszel, Przemyslaw, Loktionov, Aleksandr, Keller, Jacob E,
	Loktionov, Aleksandr
In-Reply-To: <20260601-jk-cleanup-vsi-aggregator-nodes-v1-5-36d6ecbe5ede@intel.com>

> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Jacob Keller
> Sent: 02 June 2026 05:44
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>; netdev@vger.kernel.org; Nguyen, Anthony L <anthony.l.nguyen@intel.com>
> Cc: Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>; Keller, Jacob E <jacob.e.keller@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-next 5/6] ice: remove unused aggregator node functions
>
> With the introduction of ice_cfg_vsi_agg(), the ice_cfg_agg() and
> ice_move_vsi_to_agg() functions are no longer used. Remove them.
>
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> ---
> drivers/net/ethernet/intel/ice/ice_sched.h |  6 ----  drivers/net/ethernet/intel/ice/ice_sched.c | 50 ------------------------------
> 2 files changed, 56 deletions(-)
>

Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)

^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next 6/6] ice: refactor ice_sched_cfg_agg to take agg_info pointer
From: Rinitha, SX @ 2026-06-15 16:04 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN, netdev@vger.kernel.org,
	Nguyen, Anthony L
  Cc: Kitszel, Przemyslaw, Loktionov, Aleksandr, Keller, Jacob E,
	Loktionov, Aleksandr
In-Reply-To: <20260601-jk-cleanup-vsi-aggregator-nodes-v1-6-36d6ecbe5ede@intel.com>

> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Jacob Keller
> Sent: 02 June 2026 05:44
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>; netdev@vger.kernel.org; Nguyen, Anthony L <anthony.l.nguyen@intel.com>
> Cc: Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>; Keller, Jacob E <jacob.e.keller@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-next 6/6] ice: refactor ice_sched_cfg_agg to take agg_info pointer
>
> The ice_sched_cfg_agg() function is called with an aggregator ID and type.
> It performs a lookup of the aggregator info structure by ID. If the lookup fails, it calls ice_alloc_agg_info to allocate a new aggregator structure for that ID.
>
> This behavior used to make sense when ice_cfg_agg() was exported and intended to create a new aggregator node for a specific ID. This is no longer true, and all three callers of ice_sched_cfg_agg() already have a valid agg_info structure.
>
> Refactor the function to take the agg_info pointer directly, dropping the unnecessary lookup and allocation fallback. This simplifies the function, and keeps its scope targeted at traffic class configuration.
>
> This removes essentially dead code, and prevents the need for adding additional error cleanup for failures that are impossible.
>
> Suggested-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> ---
> drivers/net/ethernet/intel/ice/ice_sched.c | 49 ++++++++++--------------------
> 1 file changed, 16 insertions(+), 33 deletions(-)
>

Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)

^ permalink raw reply

* Re: [PATCH net-next v12 00/10] net: phy_port: SFP modules representation and phy_port listing
From: Jakub Kicinski @ 2026-06-15 16:04 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: davem, Andrew Lunn, Eric Dumazet, Paolo Abeni, Russell King,
	Heiner Kallweit, netdev, linux-kernel, thomas.petazzoni,
	Christophe Leroy, Herve Codina, Florian Fainelli, Vladimir Oltean,
	Köry Maincent, Marek Behún, Oleksij Rempel,
	Nicolò Veronese, Simon Horman, mwojtas, Romain Gantois,
	Daniel Golle, Dimitri Fedrau, Frank Wunderlich
In-Reply-To: <20260615153907.862987-1-maxime.chevallier@bootlin.com>

On Mon, 15 Jun 2026 17:38:56 +0200 Maxime Chevallier wrote:
> Here's V12 for the phy_port netlink interface.

net-next is closed, deferring

^ permalink raw reply

* Re: [RESEND PATCH v1] net: dsa: motorcomm: add yt92xx dsa driver
From: Andrew Lunn @ 2026-06-15 15:56 UTC (permalink / raw)
  To: Kyle Switch
  Cc: mmyangfl, olteanv, davem, edumazet, kuba, pabeni, horms, netdev,
	linux-kernel, ming.xu, xiaolin.xu, jianmin.wang, de.ge
In-Reply-To: <20260615111235.3544282-1-kyle.switch@motor-comm.com>

On Mon, Jun 15, 2026 at 07:12:35PM +0800, Kyle Switch wrote:
> Add yt92xx dsa driver supports yt921x and yt922x switch series.
> To support more switch series in the future (e.g., yt923x), the most common configurations are abstracted into switch operation interfaces, due to yt921x and yt922x share similar register layouts and operational logic.
> 
> - Merge drivers/net/dsa/yt921x.c and the new yt922x support into a
>   unified yt92xx.c driver.
> 
> - Add support for yt922x, which can operate with either 4 bytes or
>   8 bytes DSA tag.
> 
> - Not change yt921x behaviour but use common switch apis

You should comment about why you resent.

Also, you should of waited 24 hours.

https://www.kernel.org/doc/html/latest/process/maintainer-netdev.html

Anyway, please don't send it yet again until you have broken it up
into lots of smaller patches.

You also have a lot of work to do to bring this code up to Mainline
standards. Please spend some time looking at other DSA drivers, and
network drivers. Anything your driver does which no other driver does,
is probably wrong. Please start with a small patchset with just the
core code, enough to have the ports act as independent interfaces,
nothing more. You can then submit further patchsets for offloading
bridges, statistics, trunks, ptp etc.

    Andrew

---
pw-bot: cr

^ permalink raw reply

* net-next is CLOSED
From: Jakub Kicinski @ 2026-06-15 15:53 UTC (permalink / raw)
  To: netdev

Hi!

net-next is closed. There are 350 patches in patchwork.
I suspect I can get thru around 100 today, and that will be it.
So if you have a negative reviewer score or posted after Linus
tagged final - expect getting the usual form letter about deferral.

^ permalink raw reply

* Re: [PATCH net-next v5 4/4] net: phy: realtek: load firmware for RTL8261C_CG
From: Andrew Lunn @ 2026-06-15 15:51 UTC (permalink / raw)
  To: javen
  Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, freddy_gu, nb,
	netdev, linux-kernel, daniel, vladimir.oltean
In-Reply-To: <20260615090817.429-5-javen_xu@realsil.com.cn>

On Mon, Jun 15, 2026 at 05:08:16PM +0800, javen wrote:
> From: Javen Xu <javen_xu@realsil.com.cn>
> 
> This patch adds support for loading firmware. Download some parameters
> for RTL8261C_CG.
> 
> Signed-off-by: Javen Xu <javen_xu@realsil.com.cn>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply

* Re: [PATCH net-next v5 3/4] net: phy: realtek: add support for RTL8261C_CG
From: Andrew Lunn @ 2026-06-15 15:49 UTC (permalink / raw)
  To: javen
  Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, freddy_gu, nb,
	netdev, linux-kernel, daniel, vladimir.oltean
In-Reply-To: <20260615090817.429-4-javen_xu@realsil.com.cn>

On Mon, Jun 15, 2026 at 05:08:15PM +0800, javen wrote:
> From: Javen Xu <javen_xu@realsil.com.cn>
> 
> This patch adds support for Realtek phy chip RTL8261C_CG. Its PHY ID is
> 0x001cc898.
> 
> Signed-off-by: Javen Xu <javen_xu@realsil.com.cn>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply

* Re: [PATCH net-next v5 2/4] net: phy: c45: add genphy_c45_config_master_slave()
From: Andrew Lunn @ 2026-06-15 15:47 UTC (permalink / raw)
  To: javen
  Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, freddy_gu, nb,
	netdev, linux-kernel, daniel, vladimir.oltean
In-Reply-To: <20260615090817.429-3-javen_xu@realsil.com.cn>

On Mon, Jun 15, 2026 at 05:08:14PM +0800, javen wrote:
> From: Javen Xu <javen_xu@realsil.com.cn>
> 
> Add a generic helper to configure forced master/slave mode for Clause 45
> PHYs using the 10GBASE-T AN control register.
> 
> Signed-off-by: Javen Xu <javen_xu@realsil.com.cn>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply

* [PATCH net-next v12 10/10] Documentation: networking: Update the phy_port infrastructure description
From: Maxime Chevallier @ 2026-06-15 15:39 UTC (permalink / raw)
  To: davem, Andrew Lunn, Jakub Kicinski, Eric Dumazet, Paolo Abeni,
	Russell King, Heiner Kallweit
  Cc: Maxime Chevallier, netdev, linux-kernel, thomas.petazzoni,
	Christophe Leroy, Herve Codina, Florian Fainelli, Vladimir Oltean,
	Köry Maincent, Marek Behún, Oleksij Rempel,
	Nicolò Veronese, Simon Horman, mwojtas, Romain Gantois,
	Daniel Golle, Dimitri Fedrau, Frank Wunderlich
In-Reply-To: <20260615153907.862987-1-maxime.chevallier@bootlin.com>

With SFP now properly supported with phy_port, add some details in the
documentation. Fix a typo along the way (driver -> driven).

Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
 Documentation/networking/phy-port.rst | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/Documentation/networking/phy-port.rst b/Documentation/networking/phy-port.rst
index 6e28d9094bce..73ea06db0fd9 100644
--- a/Documentation/networking/phy-port.rst
+++ b/Documentation/networking/phy-port.rst
@@ -99,13 +99,29 @@ will eventually be able to report its own ksettings::
             (_____)-----| Port |
                         +------+
 
+SFP ports
+=========
+
+SFP interfaces involve 2 distinct components, each represented by
+a :c:type:`struct phy_port <phy_port>` instance :
+
+ - The SFP cage itself is a :c:type:`struct phy_port <phy_port>`. It's special
+   in that it's not an MDI interface, but rather a hot-pluggable MII.
+   The :c:type:`struct phy_port <phy_port>` associated to it lists the different
+   MII interfaces we can use on the cage.
+
+ - The SFP module, when inserted, will also be associated to a
+   :c:type:`struct phy_port <phy_port>`, that represents the various linkmodes
+   that it gives access to. The module's :c:type:`struct phy_port <phy_port>`
+   doesn't supersedes the cage's port, it references it through
+   the :c:type:`struct phy_port <phy_port>`. :c:member:`upstream_port` field.
+
 Next steps
 ==========
 
-As of writing this documentation, only ports controlled by PHY devices are
-supported. The next steps will be to add the Netlink API to expose these
-to userspace and add support for raw ports (controlled by some firmware, and directly
-managed by the NIC driver).
+As of writing this documentation, the port's presence and information can only
+be queried, and it's not possible to change any of the port's settings or select
+which one should be used.
 
 Another parallel task is the introduction of a MII muxing framework to allow the
-control of non-PHY driver multi-port setups.
+control of non-PHY driven multi-port setups.
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next v12 09/10] net: ethtool: Introduce ethtool command to list ports
From: Maxime Chevallier @ 2026-06-15 15:39 UTC (permalink / raw)
  To: davem, Andrew Lunn, Jakub Kicinski, Eric Dumazet, Paolo Abeni,
	Russell King, Heiner Kallweit
  Cc: Maxime Chevallier, netdev, linux-kernel, thomas.petazzoni,
	Christophe Leroy, Herve Codina, Florian Fainelli, Vladimir Oltean,
	Köry Maincent, Marek Behún, Oleksij Rempel,
	Nicolò Veronese, Simon Horman, mwojtas, Romain Gantois,
	Daniel Golle, Dimitri Fedrau, Frank Wunderlich
In-Reply-To: <20260615153907.862987-1-maxime.chevallier@bootlin.com>

Expose the phy_port information to userspace, so that we can know how
many ports are available on a given interface, as well as their
capabilities. For MDI ports, we report the list of supported linkmodes
based on what the PHY that drives this port says.
For MII ports, i.e. empty SFP cages, we report the MII linkmodes that we
can output on this port.

Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
 MAINTAINERS           |   1 +
 net/ethtool/Makefile  |   2 +-
 net/ethtool/netlink.c |  25 +++
 net/ethtool/netlink.h |   9 +
 net/ethtool/port.c    | 373 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 409 insertions(+), 1 deletion(-)
 create mode 100644 net/ethtool/port.c

diff --git a/MAINTAINERS b/MAINTAINERS
index cc1dde0c9067..147f867d1097 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18584,6 +18584,7 @@ F:	Documentation/devicetree/bindings/net/ethernet-connector.yaml
 F:	Documentation/networking/phy-port.rst
 F:	drivers/net/phy/phy_port.c
 F:	include/linux/phy_port.h
+F:	net/ethtool/port.c
 K:	struct\s+phy_port|phy_port_
 
 NETWORKING [GENERAL]
diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
index 629c10916670..9b5b09670008 100644
--- a/net/ethtool/Makefile
+++ b/net/ethtool/Makefile
@@ -9,4 +9,4 @@ ethtool_nl-y	:= netlink.o bitset.o strset.o linkinfo.o linkmodes.o rss.o \
 		   channels.o coalesce.o pause.o eee.o tsinfo.o cabletest.o \
 		   tunnels.o fec.o eeprom.o stats.o phc_vclocks.o mm.o \
 		   module.o cmis_fw_update.o cmis_cdb.o pse-pd.o plca.o \
-		   phy.o tsconfig.o mse.o
+		   phy.o tsconfig.o mse.o port.o
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 1af395b54330..c076c07d0a08 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -26,6 +26,8 @@ static u32 ethnl_bcast_seq;
 			     ETHTOOL_FLAG_OMIT_REPLY)
 #define ETHTOOL_FLAGS_STATS (ETHTOOL_FLAGS_BASIC | ETHTOOL_FLAG_STATS)
 
+char phy_interface_names[PHY_INTERFACE_MODE_MAX][ETH_GSTRING_LEN] __ro_after_init;
+
 const struct nla_policy ethnl_header_policy[] = {
 	[ETHTOOL_A_HEADER_DEV_INDEX]	= { .type = NLA_U32 },
 	[ETHTOOL_A_HEADER_DEV_NAME]	= { .type = NLA_NUL_STRING,
@@ -431,6 +433,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
 	[ETHTOOL_MSG_TSCONFIG_SET]	= &ethnl_tsconfig_request_ops,
 	[ETHTOOL_MSG_PHY_GET]		= &ethnl_phy_request_ops,
 	[ETHTOOL_MSG_MSE_GET]		= &ethnl_mse_request_ops,
+	[ETHTOOL_MSG_PORT_GET]		= &ethnl_port_request_ops,
 };
 
 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -1572,6 +1575,15 @@ static const struct genl_ops ethtool_genl_ops[] = {
 		.policy = ethnl_mse_get_policy,
 		.maxattr = ARRAY_SIZE(ethnl_mse_get_policy) - 1,
 	},
+	{
+		.cmd	= ETHTOOL_MSG_PORT_GET,
+		.doit	= ethnl_default_doit,
+		.start	= ethnl_port_dump_start,
+		.dumpit	= ethnl_port_dumpit,
+		.done	= ethnl_port_dump_done,
+		.policy = ethnl_port_get_policy,
+		.maxattr = ARRAY_SIZE(ethnl_port_get_policy) - 1,
+	},
 };
 
 static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
@@ -1594,10 +1606,23 @@ static struct genl_family ethtool_genl_family __ro_after_init = {
 
 /* module setup */
 
+static void __init ethnl_phy_names_populate(void)
+{
+	const char *name;
+	int i;
+
+	for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) {
+		name = phy_modes(i);
+		strscpy(phy_interface_names[i], name, ETH_GSTRING_LEN);
+	}
+}
+
 static int __init ethnl_init(void)
 {
 	int ret;
 
+	ethnl_phy_names_populate();
+
 	ret = genl_register_family(&ethtool_genl_family);
 	if (WARN(ret < 0, "ethtool: genetlink family registration failed"))
 		return ret;
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 4ca2eca2e94b..ff83f110cc70 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -5,11 +5,15 @@
 
 #include <linux/ethtool_netlink.h>
 #include <linux/netdevice.h>
+#include <linux/phy.h>
 #include <net/genetlink.h>
 #include <net/sock.h>
 
 struct ethnl_req_info;
 
+extern char phy_interface_names[PHY_INTERFACE_MODE_MAX][ETH_GSTRING_LEN];
+
+u32 ethnl_bcast_seq_next(void);
 int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
 			       const struct nlattr *nest, struct net *net,
 			       struct netlink_ext_ack *extack,
@@ -446,6 +450,7 @@ extern const struct ethnl_request_ops ethnl_mm_request_ops;
 extern const struct ethnl_request_ops ethnl_phy_request_ops;
 extern const struct ethnl_request_ops ethnl_tsconfig_request_ops;
 extern const struct ethnl_request_ops ethnl_mse_request_ops;
+extern const struct ethnl_request_ops ethnl_port_request_ops;
 
 extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1];
 extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1];
@@ -502,6 +507,7 @@ extern const struct nla_policy ethnl_phy_get_policy[ETHTOOL_A_PHY_HEADER + 1];
 extern const struct nla_policy ethnl_tsconfig_get_policy[ETHTOOL_A_TSCONFIG_HEADER + 1];
 extern const struct nla_policy ethnl_tsconfig_set_policy[ETHTOOL_A_TSCONFIG_MAX + 1];
 extern const struct nla_policy ethnl_mse_get_policy[ETHTOOL_A_MSE_HEADER + 1];
+extern const struct nla_policy ethnl_port_get_policy[ETHTOOL_A_PORT_ID + 1];
 
 int ethnl_set_features(struct sk_buff *skb, struct genl_info *info);
 int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info);
@@ -517,6 +523,9 @@ int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
 int ethnl_tsinfo_done(struct netlink_callback *cb);
 int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info);
 int ethnl_rss_delete_doit(struct sk_buff *skb, struct genl_info *info);
+int ethnl_port_dump_start(struct netlink_callback *cb);
+int ethnl_port_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
+int ethnl_port_dump_done(struct netlink_callback *cb);
 
 extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN];
 extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN];
diff --git a/net/ethtool/port.c b/net/ethtool/port.c
new file mode 100644
index 000000000000..7bca2662e41f
--- /dev/null
+++ b/net/ethtool/port.c
@@ -0,0 +1,373 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2026 Bootlin
+ */
+#include <linux/phy.h>
+#include <linux/phy_link_topology.h>
+#include <linux/phy_port.h>
+#include <net/netdev_lock.h>
+
+#include "bitset.h"
+#include "common.h"
+#include "netlink.h"
+
+struct port_req_info {
+	struct ethnl_req_info base;
+	u32 port_id;
+};
+
+struct port_reply_data {
+	struct ethnl_reply_data	base;
+	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
+	DECLARE_PHY_INTERFACE_MASK(interfaces);
+	u32 port_id;
+	bool mii;
+	bool sfp;
+	u32 upstream_port;
+};
+
+#define PORT_REQINFO(__req_base) \
+	container_of(__req_base, struct port_req_info, base)
+
+#define PORT_REPDATA(__reply_base) \
+	container_of(__reply_base, struct port_reply_data, base)
+
+const struct nla_policy ethnl_port_get_policy[ETHTOOL_A_PORT_ID + 1] = {
+	[ETHTOOL_A_PORT_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
+	[ETHTOOL_A_PORT_ID] = NLA_POLICY_MIN(NLA_U32, 1),
+};
+
+static int port_parse_request(struct ethnl_req_info *req_info,
+			      const struct genl_info *info,
+			      struct nlattr **tb,
+			      struct netlink_ext_ack *extack)
+{
+	struct port_req_info *request = PORT_REQINFO(req_info);
+
+	if (GENL_REQ_ATTR_CHECK(info, ETHTOOL_A_PORT_ID))
+		return -EINVAL;
+
+	request->port_id = nla_get_u32(tb[ETHTOOL_A_PORT_ID]);
+
+	return 0;
+}
+
+static int port_prepare_data(const struct ethnl_req_info *req_info,
+			     struct ethnl_reply_data *reply_data,
+			     const struct genl_info *info)
+{
+	struct port_reply_data *reply = PORT_REPDATA(reply_data);
+	struct port_req_info *request = PORT_REQINFO(req_info);
+	struct phy_port *port;
+
+	/* RTNL must be held while holding a ref to the phy_port. Here, caller
+	 * holds RTNL.
+	 */
+	port = phy_link_topo_get_port(req_info->dev, request->port_id);
+	if (!port)
+		return -ENODEV;
+
+	linkmode_copy(reply->supported, port->supported);
+	phy_interface_copy(reply->interfaces, port->interfaces);
+	reply->port_id = port->id;
+	reply->mii = port->is_mii;
+	reply->sfp = port->is_sfp;
+	reply->upstream_port = port->upstream_port;
+
+	return 0;
+}
+
+static int port_reply_size(const struct ethnl_req_info *req_info,
+			   const struct ethnl_reply_data *reply_data)
+{
+	bool compact = req_info->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
+	struct port_reply_data *reply = PORT_REPDATA(reply_data);
+	size_t size = 0;
+	int ret;
+
+	/* ETHTOOL_A_PORT_ID */
+	size += nla_total_size(sizeof(u32));
+
+	if (!reply->mii) {
+		/* ETHTOOL_A_PORT_SUPPORTED_MODES */
+		ret = ethnl_bitset_size(reply->supported, NULL,
+					__ETHTOOL_LINK_MODE_MASK_NBITS,
+					link_mode_names, compact);
+		if (ret < 0)
+			return ret;
+
+		size += ret;
+	} else {
+		/* ETHTOOL_A_PORT_SUPPORTED_INTERFACES */
+		ret = ethnl_bitset_size(reply->interfaces, NULL,
+					PHY_INTERFACE_MODE_MAX,
+					phy_interface_names, compact);
+		if (ret < 0)
+			return ret;
+
+		size += ret;
+	}
+
+	/* ETHTOOL_A_PORT_TYPE */
+	size += nla_total_size(sizeof(u32));
+
+	/* ETHTOOL_A_PORT_UPSTREAM_PORT */
+	if (reply->upstream_port)
+		size += nla_total_size(sizeof(u32));
+
+	return size;
+}
+
+static int port_fill_reply(struct sk_buff *skb,
+			   const struct ethnl_req_info *req_info,
+			   const struct ethnl_reply_data *reply_data)
+{
+	bool compact = req_info->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
+	struct port_reply_data *reply = PORT_REPDATA(reply_data);
+	int ret, port_type = ETHTOOL_PORT_TYPE_MDI;
+
+	if (nla_put_u32(skb, ETHTOOL_A_PORT_ID, reply->port_id))
+		return -EMSGSIZE;
+
+	if (!reply->mii) {
+		ret = ethnl_put_bitset(skb, ETHTOOL_A_PORT_SUPPORTED_MODES,
+				       reply->supported, NULL,
+				       __ETHTOOL_LINK_MODE_MASK_NBITS,
+				       link_mode_names, compact);
+		if (ret < 0)
+			return ret;
+	} else {
+		ret = ethnl_put_bitset(skb, ETHTOOL_A_PORT_SUPPORTED_INTERFACES,
+				       reply->interfaces, NULL,
+				       PHY_INTERFACE_MODE_MAX,
+				       phy_interface_names, compact);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (reply->mii || reply->sfp)
+		port_type = ETHTOOL_PORT_TYPE_SFP;
+
+	if (nla_put_u32(skb, ETHTOOL_A_PORT_TYPE, port_type))
+		return -EMSGSIZE;
+
+	if (reply->upstream_port &&
+	    nla_put_u32(skb, ETHTOOL_A_PORT_UPSTREAM_PORT,
+			reply->upstream_port))
+		return -EMSGSIZE;
+
+	return 0;
+}
+
+struct port_dump_ctx {
+	struct port_req_info	*req_info;
+	struct port_reply_data	*reply_data;
+	unsigned long		ifindex;
+	unsigned long		pos_portid;
+};
+
+static struct port_dump_ctx *
+port_dump_ctx_get(struct netlink_callback *cb)
+{
+	return (struct port_dump_ctx *)cb->ctx;
+}
+
+int ethnl_port_dump_start(struct netlink_callback *cb)
+{
+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
+	struct port_dump_ctx *ctx = port_dump_ctx_get(cb);
+	struct nlattr **tb = info->info.attrs;
+	struct port_reply_data *reply_data;
+	struct port_req_info *req_info;
+	int ret;
+
+	BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
+
+	req_info = kzalloc_obj(*req_info);
+	if (!req_info)
+		return -ENOMEM;
+
+	reply_data = kmalloc_obj(*reply_data);
+	if (!reply_data) {
+		ret = -ENOMEM;
+		goto free_req_info;
+	}
+
+	ret = ethnl_parse_header_dev_get(&req_info->base, tb[ETHTOOL_A_PORT_HEADER],
+					 genl_info_net(&info->info),
+					 info->info.extack, false);
+	if (ret < 0)
+		goto free_rep_data;
+
+	ctx->ifindex = 0;
+
+	/* For filtered DUMP requests, let's just store the ifindex. We'll check
+	 * again if the netdev is still there when looping over the netdev list
+	 * in the DUMP loop.
+	 */
+	if (req_info->base.dev) {
+		ctx->ifindex = req_info->base.dev->ifindex;
+		netdev_put(req_info->base.dev, &req_info->base.dev_tracker);
+		req_info->base.dev = NULL;
+	}
+
+	ctx->req_info = req_info;
+	ctx->reply_data = reply_data;
+
+	return 0;
+
+free_rep_data:
+	kfree(reply_data);
+free_req_info:
+	kfree(req_info);
+
+	return ret;
+}
+
+static int port_dump_one(struct sk_buff *skb, struct net_device *dev,
+			 struct netlink_callback *cb)
+{
+	struct port_dump_ctx *ctx = port_dump_ctx_get(cb);
+	void *ehdr;
+	int ret;
+
+	ehdr = ethnl_dump_put(skb, cb, ETHTOOL_MSG_PORT_GET_REPLY);
+	if (!ehdr)
+		return -EMSGSIZE;
+
+	memset(ctx->reply_data, 0, sizeof(struct port_reply_data));
+	ctx->reply_data->base.dev = dev;
+
+	rtnl_lock();
+	netdev_lock_ops(dev);
+
+	ret = port_prepare_data(&ctx->req_info->base, &ctx->reply_data->base,
+				genl_info_dump(cb));
+
+	netdev_unlock_ops(dev);
+	rtnl_unlock();
+
+	if (ret < 0)
+		goto out;
+
+	ret = ethnl_fill_reply_header(skb, dev, ETHTOOL_A_PORT_HEADER);
+	if (ret < 0)
+		goto out;
+
+	ret = port_fill_reply(skb, &ctx->req_info->base, &ctx->reply_data->base);
+
+out:
+	ctx->reply_data->base.dev = NULL;
+	if (ret < 0)
+		genlmsg_cancel(skb, ehdr);
+	else
+		genlmsg_end(skb, ehdr);
+
+	return ret;
+}
+
+static int port_dump_one_dev(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct port_dump_ctx *ctx = port_dump_ctx_get(cb);
+	struct net_device *dev;
+	struct phy_port *port;
+	int ret;
+
+	dev = ctx->req_info->base.dev;
+
+	if (!dev->link_topo)
+		return 0;
+
+	xa_for_each_start(&dev->link_topo->ports, ctx->pos_portid, port,
+			  ctx->pos_portid) {
+		ctx->req_info->port_id = ctx->pos_portid;
+
+		ret = port_dump_one(skb, dev, cb);
+		if (ret)
+			return ret;
+	}
+
+	ctx->pos_portid = 0;
+
+	return 0;
+}
+
+static int port_dump_all_dev(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct port_dump_ctx *ctx = port_dump_ctx_get(cb);
+	struct net *net = sock_net(skb->sk);
+	netdevice_tracker dev_tracker;
+	struct net_device *dev;
+	int ret = 0;
+
+	rcu_read_lock();
+	for_each_netdev_dump(net, dev, ctx->ifindex) {
+		netdev_hold(dev, &dev_tracker, GFP_ATOMIC);
+		rcu_read_unlock();
+
+		ctx->req_info->base.dev = dev;
+		ret = port_dump_one_dev(skb, cb);
+
+		rcu_read_lock();
+		netdev_put(dev, &dev_tracker);
+		ctx->req_info->base.dev = NULL;
+
+		if (ret)
+			break;
+
+		ret = 0;
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+
+int ethnl_port_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
+	struct port_dump_ctx *ctx = port_dump_ctx_get(cb);
+	int ret = 0;
+
+	if (ctx->ifindex) {
+		netdevice_tracker dev_tracker;
+		struct net_device *dev;
+
+		dev = netdev_get_by_index(genl_info_net(&info->info),
+					  ctx->ifindex, &dev_tracker,
+					  GFP_KERNEL);
+		if (!dev)
+			return -ENODEV;
+
+		ctx->req_info->base.dev = dev;
+		ret = port_dump_one_dev(skb, cb);
+
+		netdev_put(dev, &dev_tracker);
+	} else {
+		ret = port_dump_all_dev(skb, cb);
+	}
+
+	return ret;
+}
+
+int ethnl_port_dump_done(struct netlink_callback *cb)
+{
+	struct port_dump_ctx *ctx = port_dump_ctx_get(cb);
+
+	kfree(ctx->req_info);
+	kfree(ctx->reply_data);
+
+	return 0;
+}
+
+const struct ethnl_request_ops ethnl_port_request_ops = {
+	.request_cmd		= ETHTOOL_MSG_PORT_GET,
+	.reply_cmd		= ETHTOOL_MSG_PORT_GET_REPLY,
+	.hdr_attr		= ETHTOOL_A_PORT_HEADER,
+	.req_info_size		= sizeof(struct port_req_info),
+	.reply_data_size	= sizeof(struct port_reply_data),
+
+	.parse_request		= port_parse_request,
+	.prepare_data		= port_prepare_data,
+	.reply_size		= port_reply_size,
+	.fill_reply		= port_fill_reply,
+};
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next v12 08/10] netlink: specs: Add ethernet port listing with ethtool
From: Maxime Chevallier @ 2026-06-15 15:39 UTC (permalink / raw)
  To: davem, Andrew Lunn, Jakub Kicinski, Eric Dumazet, Paolo Abeni,
	Russell King, Heiner Kallweit
  Cc: Maxime Chevallier, netdev, linux-kernel, thomas.petazzoni,
	Christophe Leroy, Herve Codina, Florian Fainelli, Vladimir Oltean,
	Köry Maincent, Marek Behún, Oleksij Rempel,
	Nicolò Veronese, Simon Horman, mwojtas, Romain Gantois,
	Daniel Golle, Dimitri Fedrau, Frank Wunderlich
In-Reply-To: <20260615153907.862987-1-maxime.chevallier@bootlin.com>

Ethernet network interfaces may have more than one front-facing port.
The phy_port infrastructure was introduced to keep track of
these ports, and allow userspace to know about the presence and
capability of these ports. Add a ethnl netlink message to report this
information.

Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
 Documentation/netlink/specs/ethtool.yaml      | 50 +++++++++++++++++++
 Documentation/networking/ethtool-netlink.rst  | 34 +++++++++++++
 .../uapi/linux/ethtool_netlink_generated.h    | 19 +++++++
 3 files changed, 103 insertions(+)

diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml
index 5dd4d1b5d94b..d1151af335ca 100644
--- a/Documentation/netlink/specs/ethtool.yaml
+++ b/Documentation/netlink/specs/ethtool.yaml
@@ -210,6 +210,10 @@ definitions:
       -
         name: discard
         value: 31
+  -
+    name: port-type
+    type: enum
+    entries: [mdi, sfp]
 
 attribute-sets:
   -
@@ -1905,6 +1909,32 @@ attribute-sets:
         name: link
         type: nest
         nested-attributes: mse-snapshot
+  -
+    name: port
+    attr-cnt-name: --ethtool-a-port-cnt
+    attributes:
+      -
+        name: header
+        type: nest
+        nested-attributes: header
+      -
+        name: id
+        type: u32
+      -
+        name: supported-modes
+        type: nest
+        nested-attributes: bitset
+      -
+        name: supported-interfaces
+        type: nest
+        nested-attributes: bitset
+      -
+        name: type
+        type: u32
+        enum: port-type
+      -
+        name: upstream-port
+        type: u32
 
 operations:
   enum-model: directional
@@ -2859,6 +2889,26 @@ operations:
             - worst-channel
             - link
       dump: *mse-get-op
+    -
+      name: port-get
+      doc: Get ports attached to an interface
+
+      attribute-set: port
+
+      do: &port-get-op
+        request:
+          attributes:
+            - header
+            - id
+        reply:
+          attributes:
+            - header
+            - id
+            - supported-modes
+            - supported-interfaces
+            - type
+            - upstream-port
+      dump: *port-get-op
 
 mcast-groups:
   list:
diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst
index e92abf45faf5..b4326c89b075 100644
--- a/Documentation/networking/ethtool-netlink.rst
+++ b/Documentation/networking/ethtool-netlink.rst
@@ -2537,6 +2537,39 @@ Within each channel nest, only the metrics supported by the PHY will be present.
 See ``struct phy_mse_snapshot`` kernel documentation in
 ``include/linux/phy.h``.
 
+PORT_GET
+========
+
+Retrieve information about the physical connection points of a network device,
+referred to as "ports". User needs to specify a PORT_ID for the DO operation,
+in which case the DO request returns information about that specific port.
+
+As there can be more than one port, the DUMP operation can be used to list the
+ports present on a given interface, by passing an interface index or name in
+the dump request.
+
+Request contents:
+
+  ===================================== ======  ===============================
+  ``ETHTOOL_A_PORT_HEADER``             nested  request header
+  ``ETHTOOL_A_PORT_ID``                 u32     port id
+  ===================================== ======  ===============================
+
+Kernel response contents:
+
+  ======================================= ======  =============================
+  ``ETHTOOL_A_PORT_HEADER``               nested  request header
+  ``ETHTOOL_A_PORT_ID``                   u32     the port's unique identifier,
+                                                  per netdevice.
+  ``ETHTOOL_A_PORT_SUPPORTED_MODES``      bitset  bitset of supported linkmodes
+  ``ETHTOOL_A_PORT_SUPPORTED_INTERFACES`` bitset  bitset of supported MII
+                                                  interfaces
+  ``ETHTOOL_A_PORT_TYPE``                 u32     the port type
+  ``ETHTOOL_A_PORT_UPSTREAM_PORT``        u32     If any, the index of the MII
+                                                  port that feeds into this
+                                                  port.
+  ======================================= ======  =============================
+
 Request translation
 ===================
 
@@ -2647,4 +2680,5 @@ are netlink only.
   n/a                                 ``ETHTOOL_MSG_PHY_GET``
   ``SIOCGHWTSTAMP``                   ``ETHTOOL_MSG_TSCONFIG_GET``
   ``SIOCSHWTSTAMP``                   ``ETHTOOL_MSG_TSCONFIG_SET``
+  n/a                                 ``ETHTOOL_MSG_PORT_GET``
   =================================== =====================================
diff --git a/include/uapi/linux/ethtool_netlink_generated.h b/include/uapi/linux/ethtool_netlink_generated.h
index 8134baf7860f..f9d8794eabc1 100644
--- a/include/uapi/linux/ethtool_netlink_generated.h
+++ b/include/uapi/linux/ethtool_netlink_generated.h
@@ -78,6 +78,11 @@ enum ethtool_pse_event {
 	ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR = 64,
 };
 
+enum ethtool_port_type {
+	ETHTOOL_PORT_TYPE_MDI,
+	ETHTOOL_PORT_TYPE_SFP,
+};
+
 enum {
 	ETHTOOL_A_HEADER_UNSPEC,
 	ETHTOOL_A_HEADER_DEV_INDEX,
@@ -840,6 +845,18 @@ enum {
 	ETHTOOL_A_MSE_MAX = (__ETHTOOL_A_MSE_CNT - 1)
 };
 
+enum {
+	ETHTOOL_A_PORT_HEADER = 1,
+	ETHTOOL_A_PORT_ID,
+	ETHTOOL_A_PORT_SUPPORTED_MODES,
+	ETHTOOL_A_PORT_SUPPORTED_INTERFACES,
+	ETHTOOL_A_PORT_TYPE,
+	ETHTOOL_A_PORT_UPSTREAM_PORT,
+
+	__ETHTOOL_A_PORT_CNT,
+	ETHTOOL_A_PORT_MAX = (__ETHTOOL_A_PORT_CNT - 1)
+};
+
 enum {
 	ETHTOOL_MSG_USER_NONE = 0,
 	ETHTOOL_MSG_STRSET_GET = 1,
@@ -893,6 +910,7 @@ enum {
 	ETHTOOL_MSG_RSS_CREATE_ACT,
 	ETHTOOL_MSG_RSS_DELETE_ACT,
 	ETHTOOL_MSG_MSE_GET,
+	ETHTOOL_MSG_PORT_GET,
 
 	__ETHTOOL_MSG_USER_CNT,
 	ETHTOOL_MSG_USER_MAX = (__ETHTOOL_MSG_USER_CNT - 1)
@@ -954,6 +972,7 @@ enum {
 	ETHTOOL_MSG_RSS_CREATE_NTF,
 	ETHTOOL_MSG_RSS_DELETE_NTF,
 	ETHTOOL_MSG_MSE_GET_REPLY,
+	ETHTOOL_MSG_PORT_GET_REPLY,
 
 	__ETHTOOL_MSG_KERNEL_CNT,
 	ETHTOOL_MSG_KERNEL_MAX = (__ETHTOOL_MSG_KERNEL_CNT - 1)
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next v12 07/10] net: phy: phy_link_topology: Add a helper to retrieve ports
From: Maxime Chevallier @ 2026-06-15 15:39 UTC (permalink / raw)
  To: davem, Andrew Lunn, Jakub Kicinski, Eric Dumazet, Paolo Abeni,
	Russell King, Heiner Kallweit
  Cc: Maxime Chevallier, netdev, linux-kernel, thomas.petazzoni,
	Christophe Leroy, Herve Codina, Florian Fainelli, Vladimir Oltean,
	Köry Maincent, Marek Behún, Oleksij Rempel,
	Nicolò Veronese, Simon Horman, mwojtas, Romain Gantois,
	Daniel Golle, Dimitri Fedrau, Frank Wunderlich
In-Reply-To: <20260615153907.862987-1-maxime.chevallier@bootlin.com>

In order to allow netlink access to phy_ports, let's add a helper to
retrieve them. When handling a port coming from phy_link_topology, the
caller must hold rtnl until it's done with it.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
 include/linux/phy_link_topology.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/include/linux/phy_link_topology.h b/include/linux/phy_link_topology.h
index 296ee514ba46..95629112204e 100644
--- a/include/linux/phy_link_topology.h
+++ b/include/linux/phy_link_topology.h
@@ -13,6 +13,7 @@
 
 #include <linux/ethtool.h>
 #include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
 
 struct xarray;
 struct phy_device;
@@ -71,6 +72,20 @@ phy_link_topo_get_phy(struct net_device *dev, u32 phyindex)
 	return NULL;
 }
 
+static inline struct phy_port *
+phy_link_topo_get_port(struct net_device *dev, u32 port_id)
+{
+	struct phy_link_topology *topo = dev->link_topo;
+
+	ASSERT_RTNL();
+
+	if (!topo)
+		return NULL;
+
+	/* Caller must hold RTNL while handling the phy_port */
+	return xa_load(&topo->ports, port_id);
+}
+
 #else
 static inline int phy_link_topo_add_phy(struct net_device *dev,
 					struct phy_device *phy,
@@ -100,6 +115,12 @@ phy_link_topo_get_phy(struct net_device *dev, u32 phyindex)
 {
 	return NULL;
 }
+
+static inline struct phy_port *
+phy_link_topo_get_port(struct net_device *dev, u32 port_id)
+{
+	return NULL;
+}
 #endif
 
 #endif /* __PHY_LINK_TOPOLOGY_H */
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next v12 06/10] net: phy: phy_port: Store information about a port's upstream
From: Maxime Chevallier @ 2026-06-15 15:39 UTC (permalink / raw)
  To: davem, Andrew Lunn, Jakub Kicinski, Eric Dumazet, Paolo Abeni,
	Russell King, Heiner Kallweit
  Cc: Maxime Chevallier, netdev, linux-kernel, thomas.petazzoni,
	Christophe Leroy, Herve Codina, Florian Fainelli, Vladimir Oltean,
	Köry Maincent, Marek Behún, Oleksij Rempel,
	Nicolò Veronese, Simon Horman, mwojtas, Romain Gantois,
	Daniel Golle, Dimitri Fedrau, Frank Wunderlich
In-Reply-To: <20260615153907.862987-1-maxime.chevallier@bootlin.com>

MII phy_ports are not meant to be connected directly to a link partner.
They are meant to feed into some media converter devices that will
expose an MDI phy_port, so far we only support SFP modules for that.

In the case an MDI phy_port is backed by an MII port (e.g. a SFP
module's port, backed by the SFP cage port), let's keep track of the
port id of the MII port backing it.

Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
 drivers/net/phy/phy_device.c | 27 +++++++++++++++++++++++++++
 drivers/net/phy/phylink.c    |  5 +++++
 include/linux/phy.h          |  4 ++++
 include/linux/phy_port.h     |  3 +++
 4 files changed, 39 insertions(+)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index c72582701e66..b7cd152aaaa3 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1493,6 +1493,7 @@ static int phy_sfp_connect_phy(void *upstream, struct phy_device *phy)
 	int ret;
 
 	phydev->has_sfp_mod_phy = true;
+	phy_set_upstream_port(phy, phydev->sfp_cage_port);
 
 	/* If we aren't attached to a netdev, we can't add the SFP PHY to its
 	 * topology.
@@ -1526,6 +1527,8 @@ static void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy)
 
 	if (dev)
 		phy_link_topo_del_phy(dev, phy);
+
+	phy_set_upstream_port(phy, NULL);
 }
 
 /**
@@ -1661,6 +1664,8 @@ static int phy_add_sfp_mod_port(struct phy_device *phydev)
 	 */
 	phydev->mod_port = port;
 
+	port->upstream_port = phydev->sfp_cage_port->id;
+
 	return 0;
 }
 
@@ -3696,6 +3701,28 @@ struct phy_port *phy_get_sfp_port(struct phy_device *phydev)
 }
 EXPORT_SYMBOL_GPL(phy_get_sfp_port);
 
+/**
+ * phy_set_upstream_port() - Sets the phy_port controlling the MII this PHY is
+ *			     attached to.
+ * @phydev: pointer to the PHY device we set the upstream of.
+ * @port: The phy_port upstream of this PHY, can be NULL.
+ */
+void phy_set_upstream_port(struct phy_device *phydev, struct phy_port *port)
+{
+	struct phy_port *local_port;
+
+	ASSERT_RTNL();
+
+	phydev->upstream_port = port;
+
+	phy_for_each_port(phydev, local_port)
+		if (port)
+			local_port->upstream_port = port->id;
+		else
+			local_port->upstream_port = 0;
+}
+EXPORT_SYMBOL_GPL(phy_set_upstream_port);
+
 /**
  * fwnode_mdio_find_device - Given a fwnode, find the mdio_device
  * @fwnode: pointer to the mdio_device's fwnode
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 59ea3a2e5da4..d069338e8e4d 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -3959,6 +3959,8 @@ static int phylink_add_sfp_mod_port(struct phylink *pl)
 		}
 	}
 
+	port->upstream_port = pl->sfp_cage_port->id;
+
 	pl->mod_port = port;
 
 	return 0;
@@ -4062,6 +4064,8 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
 	phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces,
 			  pl->config->supported_interfaces);
 
+	phy_set_upstream_port(phy, pl->sfp_cage_port);
+
 	/* Do the initial configuration */
 	return phylink_sfp_config_phy(pl, phy);
 }
@@ -4070,6 +4074,7 @@ static void phylink_sfp_disconnect_phy(void *upstream,
 				       struct phy_device *phydev)
 {
 	phylink_disconnect_phy(upstream);
+	phy_set_upstream_port(phydev, NULL);
 }
 
 static const struct sfp_upstream_ops sfp_phylink_ops = {
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 59903257e978..33ed10d4502a 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -597,6 +597,7 @@ struct phy_oatc14_sqi_capability {
  * @sfp_bus: SFP bus attached to this PHY's fiber port
  * @sfp_cage_port: The phy_port connected to the downstream SFP cage
  * @mod_port: phy_port representing the SFP module, if it is phy-less
+ * @upstream_port: phy_port this PHY's MII attaches to, if any
  * @attached_dev: The attached enet driver's device instance ptr
  * @adjust_link: Callback for the enet controller to respond to changes: in the
  *               link state.
@@ -791,6 +792,7 @@ struct phy_device {
 	struct sfp_bus *sfp_bus;
 	struct phy_port *sfp_cage_port;
 	struct phy_port *mod_port;
+	struct phy_port *upstream_port;
 	struct phylink *phylink;
 	struct net_device *attached_dev;
 	struct mii_timestamper *mii_ts;
@@ -2466,6 +2468,8 @@ int __phy_hwtstamp_set(struct phy_device *phydev,
 
 struct phy_port *phy_get_sfp_port(struct phy_device *phydev);
 
+void phy_set_upstream_port(struct phy_device *phydev, struct phy_port *port);
+
 /**
  * phy_module_driver() - Helper macro for registering PHY drivers
  * @__phy_drivers: array of PHY drivers to register
diff --git a/include/linux/phy_port.h b/include/linux/phy_port.h
index 4e2a3fdd2f2e..e3a41cedebdc 100644
--- a/include/linux/phy_port.h
+++ b/include/linux/phy_port.h
@@ -40,6 +40,8 @@ struct phy_port_ops {
  * @head: Used by the port's parent to list ports
  * @parent_type: The type of device this port is directly connected to
  * @phy: If the parent is PHY_PORT_PHYDEV, the PHY controlling that port
+ * @upstream_port: For non-MII ports, indicates the MII port that feeds this
+ *		   port, e.g. the SFP cage port for a SFP module port.
  * @ops: Callback ops implemented by the port controller
  * @pairs: The number of  pairs this port has, 0 if not applicable
  * @mediums: Bitmask of the physical mediums this port provides access to
@@ -59,6 +61,7 @@ struct phy_port {
 	union {
 		struct phy_device *phy;
 	};
+	u32 upstream_port;
 
 	const struct phy_port_ops *ops;
 
-- 
2.54.0


^ permalink raw reply related


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