mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: wei.fang@oss.nxp.com
To: claudiu.manoil@nxp.com, vladimir.oltean@nxp.com,
	xiaoning.wang@nxp.com, andrew@lunn.ch, olteanv@gmail.com,
	andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com, linux@armlinux.org.uk
Cc: wei.fang@nxp.com, imx@lists.linux.dev, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH v4 net-next 04/15] net: enetc: add link speed message support to PF driver
Date: Wed,  9 Sep 2026 18:07:22 +0800	[thread overview]
Message-ID: <20260909100733.1139689-5-wei.fang@oss.nxp.com> (raw)
In-Reply-To: <20260909100733.1139689-1-wei.fang@oss.nxp.com>

From: Wei Fang <wei.fang@nxp.com>

When a VF is driven by DPDK, its user space application needs accurate
link speed information to make correct forwarding and configuration
decisions. Add link speed message support so the PF replies with the
current link speed when it receives a get-link-speed message from a VF.

Use a new message class 0x81 (ENETC_MSG_CLASS_ID_LINK_SPEED). The
PSI-to-VSI message is 16 bits: the high 8 bits are the class ID and the
low 8 bits are the speed code, so up to 255 speed values are supported
(ENETC_MSG_SPEED_MAX = 0xff). Instead of enumerating every speed above
5Gbps, use a formula so future high speeds need no enum or switch
changes:

  speed_code = (link_speed - 5000) / 1000 + ENETC_MSG_SPEED_5G

The speed is read via phylink_ethtool_ksettings_get() rather than the
speed passed to the mac_link_up() callback. When the MAC has a PCS
layer, mac_link_up() reports the PCS link speed, which may differ from
the external PHY link speed; phylink_ethtool_ksettings_get() returns the
actual external link speed.

Unlike the link status message (class 0x80), the get-link-speed message
is only permitted for trusted VFs. Reading the speed requires the PF to
take rtnl_lock(), so an untrusted VF spamming this query could cause
rtnl_lock contention and starve routine network configuration on the
host. An untrusted VF therefore receives a permission-deny response; a
VF can be marked trusted via 'ip link set <pf> vf N trust on'.

Note that link speed change notification is not supported yet.

Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 .../ethernet/freescale/enetc/enetc_mailbox.h  | 41 +++++++++
 .../net/ethernet/freescale/enetc/enetc_msg.c  | 90 +++++++++++++++++++
 2 files changed, 131 insertions(+)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mailbox.h b/drivers/net/ethernet/freescale/enetc/enetc_mailbox.h
index 846998f07989..832d2f6ddcd8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_mailbox.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_mailbox.h
@@ -91,6 +91,7 @@
  * The class code for the following messages is 8-bit.
  * 1. Get IP revision messages
  * 2. Link status messages
+ * 3. Link speed messages
  */
 #define ENETC_PF_MSG_CLASS_CODE_U8		GENMASK(7, 0)
 #define ENETC_PF_MSG_CLASS_ID			GENMASK(15, 8)
@@ -112,6 +113,7 @@ enum enetc_msg_class_id {
 	/* Common Class ID for PSI-to-VSI and VSI-to-PSI messages */
 	ENETC_MSG_CLASS_ID_MAC_FILTER		= 0x20,
 	ENETC_MSG_CLASS_ID_LINK_STATUS		= 0x80,
+	ENETC_MSG_CLASS_ID_LINK_SPEED		= 0x81,
 	ENETC_MSG_CLASS_ID_IP_REVISION		= 0xf0,
 };
 
@@ -129,6 +131,13 @@ enum enetc_msg_link_status_cmd_id {
 	ENETC_MSG_UNREGISTER_LINK_CHANGE_NOTIFIER,
 };
 
+enum enetc_msg_link_speed_cmd_id {
+	ENETC_MSG_GET_CURRENT_LINK_SPEED,
+	/* The following command IDs are not currently supported */
+	ENETC_MSG_REGISTER_SPEED_CHANGE_NOTIFIER,
+	ENETC_MSG_UNREGISTER_SPEED_CHANGE_NOTIFIER,
+};
+
 /* Class-specific error return codes of MAC filter */
 enum enetc_mac_filter_class_code {
 	ENETC_MF_CLASS_CODE_INVALID_MAC,
@@ -138,6 +147,28 @@ enum enetc_mac_filter_class_code {
 #define ENETC_CLASS_CODE_LINK_DOWN		BIT(0)
 #define ENETC_CLASS_CODE_TX_PAUSE_EN		BIT(1)
 
+/* Class-specific notifications/codes of link speed */
+enum enetc_link_speed_class_code {
+	ENETC_MSG_SPEED_UNKNOWN,
+	ENETC_MSG_SPEED_10M_HD,
+	ENETC_MSG_SPEED_10M_FD,
+	ENETC_MSG_SPEED_100M_HD,
+	ENETC_MSG_SPEED_100M_FD,
+	ENETC_MSG_SPEED_1000M,
+	ENETC_MSG_SPEED_2500M,
+	ENETC_MSG_SPEED_5G,
+	/* Do not add enumeration values for any speed greater than
+	 * 5Gbps. For any speed greater than 5Gbps, its speed class
+	 * code should follow the formula below.
+	 *
+	 * SPEED = (link_speed - 5000) / 1000 + ENETC_MSG_SPEED_5G
+	 *
+	 * The unit of link_speed should be Mbps, the max SPEED
+	 * should <= ENETC_MSG_SPEED_MAX.
+	 */
+	ENETC_MSG_SPEED_MAX = 0xff,
+};
+
 struct enetc_msg_swbd {
 	void *vaddr;
 	dma_addr_t dma;
@@ -181,6 +212,16 @@ struct enetc_msg_mac_exact_filter {
  * cmd_id 0x0: get the current link status
  * cmd_id 0x1: register link status change notification
  * cmd_id 0x2: unregister link status change notification
+ *
+ * Link speed message, class_id 0x81.
+ * cmd_id 0x0: get the current link speed. Unlike the link status
+ *   query (class 0x80), this query is only permitted for trusted VFs;
+ *   an untrusted VF receives a permission-deny response. This is
+ *   because the PF must take rtnl_lock() to read the link speed, so
+ *   restricting it to trusted VFs avoids rtnl_lock contention on the
+ *   host from a misbehaving VF.
+ * cmd_id 0x1: register link speed change notification, not supported yet
+ * cmd_id 0x2: unregister link speed change notification, not supported yet
  */
 struct enetc_msg_generic {
 	struct enetc_msg_header hdr;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_msg.c b/drivers/net/ethernet/freescale/enetc/enetc_msg.c
index 79dbaf72fcff..08a9ffdd3eb0 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_msg.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_msg.c
@@ -230,6 +230,93 @@ static u16 enetc_msg_handle_link_status(struct enetc_pf *pf, int vf_id,
 	return 0;
 }
 
+static u16 enetc_build_link_speed_msg(int speed, int duplex)
+{
+	u32 speed_code = ENETC_MSG_SPEED_UNKNOWN;
+
+	switch (speed) {
+	case SPEED_10:
+		if (duplex == DUPLEX_HALF)
+			speed_code = ENETC_MSG_SPEED_10M_HD;
+		else if (duplex == DUPLEX_FULL)
+			speed_code = ENETC_MSG_SPEED_10M_FD;
+		break;
+	case SPEED_100:
+		if (duplex == DUPLEX_HALF)
+			speed_code = ENETC_MSG_SPEED_100M_HD;
+		else if (duplex == DUPLEX_FULL)
+			speed_code = ENETC_MSG_SPEED_100M_FD;
+		break;
+	case SPEED_1000:
+		speed_code = ENETC_MSG_SPEED_1000M;
+		break;
+	case SPEED_2500:
+		speed_code = ENETC_MSG_SPEED_2500M;
+		break;
+	case SPEED_5000:
+		speed_code = ENETC_MSG_SPEED_5G;
+		break;
+	default:
+		if (speed < SPEED_5000)
+			break;
+
+		speed_code = (speed - SPEED_5000) / SPEED_1000 +
+			     ENETC_MSG_SPEED_5G;
+		if (speed_code > ENETC_MSG_SPEED_MAX)
+			speed_code = ENETC_MSG_SPEED_UNKNOWN;
+	}
+
+	return FIELD_PREP(ENETC_PF_MSG_CLASS_ID,
+			  ENETC_MSG_CLASS_ID_LINK_SPEED) |
+	       FIELD_PREP(ENETC_PF_MSG_CLASS_CODE_U8, speed_code);
+}
+
+static u16 enetc_msg_get_link_speed(struct enetc_pf *pf, int vf_id)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(pf->si->ndev);
+	struct enetc_vf_state *vf_state = &pf->vf_state[vf_id];
+	struct ethtool_link_ksettings link_info = {};
+
+	/* A malicious or malfunctioning VM could potentially spam these
+	 * messages in a tight loop causing global rtnl_lock contention,
+	 * which may severely starve other processes on the host that
+	 * require rtnl_lock for routine network configuration, resulting
+	 * in a system-wide control-plane denial of service. Therefore,
+	 * we expect the VF query for link speed to be trusted. There's no
+	 * need to consider the transition from trusted to untrusted here,
+	 * as this won't cause rtnl_lock() to be called frequently.
+	 */
+	mutex_lock(&vf_state->lock);
+	if (!(vf_state->flags & ENETC_VF_FLAG_TRUSTED)) {
+		mutex_unlock(&vf_state->lock);
+
+		return ENETC_PF_MSG_PERM_DENY;
+	}
+	mutex_unlock(&vf_state->lock);
+
+	rtnl_lock();
+	phylink_ethtool_ksettings_get(priv->phylink, &link_info);
+	rtnl_unlock();
+
+	return enetc_build_link_speed_msg(link_info.base.speed,
+					  link_info.base.duplex);
+}
+
+static u16 enetc_msg_handle_link_speed(struct enetc_pf *pf, int vf_id,
+				       void *vf_msg)
+{
+	struct enetc_msg_header *msg_hdr = vf_msg;
+
+	switch (msg_hdr->cmd_id) {
+	case ENETC_MSG_GET_CURRENT_LINK_SPEED:
+		return enetc_msg_get_link_speed(pf, vf_id);
+	case ENETC_MSG_REGISTER_SPEED_CHANGE_NOTIFIER:
+	case ENETC_MSG_UNREGISTER_SPEED_CHANGE_NOTIFIER:
+	default:
+		return ENETC_PF_MSG_NOTSUPP;
+	}
+}
+
 /* If *pf_msg is set to 0, it means that PF has responded to VF in
  * enetc_msg_handle_rxmsg() through enetc_pf_reply_msg(), which also
  * clears the corresponding VF MR bit in PSIIDR.
@@ -312,6 +399,9 @@ static void enetc_msg_handle_rxmsg(struct enetc_pf *pf, int vf_id,
 	case ENETC_MSG_CLASS_ID_LINK_STATUS:
 		*pf_msg = enetc_msg_handle_link_status(pf, vf_id, msg);
 		break;
+	case ENETC_MSG_CLASS_ID_LINK_SPEED:
+		*pf_msg = enetc_msg_handle_link_speed(pf, vf_id, msg);
+		break;
 	default:
 		dev_err_ratelimited(dev,
 				    "Unsupported message class ID: 0x%x\n",
-- 
2.34.1


  parent reply	other threads:[~2026-09-09 10:35 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-09 10:07 [PATCH v4 net-next 00/15] net: enetc: SR-IOV improvements and ENETC v4 VF support wei.fang
2026-09-09 10:07 ` [PATCH v4 net-next 01/15] net: enetc: add trusted " wei.fang
2026-09-10 11:20   ` netdev-bot+sashiko
2026-09-11  2:29     ` Wei Fang
2026-09-09 10:07 ` [PATCH v4 net-next 02/15] net: enetc: move msg_task and msg_int_name to struct enetc_si wei.fang
2026-09-11 20:14   ` Claudiu Manoil
2026-09-09 10:07 ` [PATCH v4 net-next 03/15] net: enetc: add link status message support to PF driver wei.fang
2026-09-10 11:20   ` netdev-bot+sashiko
2026-09-11  5:55     ` Wei Fang
2026-09-11 20:15   ` Claudiu Manoil
2026-09-09 10:07 ` wei.fang [this message]
2026-09-10 11:20   ` [PATCH v4 net-next 04/15] net: enetc: add link speed " netdev-bot+sashiko
2026-09-11  2:56     ` Wei Fang
2026-09-11 20:16   ` Claudiu Manoil
2026-09-09 10:07 ` [PATCH v4 net-next 05/15] net: enetc: use enetc_set_si_hw_addr() to set VF MAC address wei.fang
2026-09-09 10:07 ` [PATCH v4 net-next 06/15] net: enetc: relocate enetc_pf_set_vf_mac() for common PF support wei.fang
2026-09-09 10:07 ` [PATCH v4 net-next 07/15] net: enetc: add .ndo_set_vf_mac() to the enetc v4 driver wei.fang
2026-09-09 10:07 ` [PATCH v4 net-next 08/15] net: enetc: move mac_filter from struct enetc_pf to struct enetc_si wei.fang
2026-09-09 10:07 ` [PATCH v4 net-next 09/15] net: enetc: add MAC address filtering support for VFs of ENETC v4 wei.fang
2026-09-10 11:21   ` netdev-bot+sashiko
2026-09-11  6:13     ` Wei Fang
2026-09-09 10:07 ` [PATCH v4 net-next 10/15] net: enetc: simplify and rename PSIIER enable/disable helpers wei.fang
2026-09-09 10:07 ` [PATCH v4 net-next 11/15] net: enetc: restore VF MAC promiscuous mode after FLR for ENETC v4 wei.fang
2026-09-10 11:21   ` netdev-bot+sashiko
2026-09-11  6:23     ` Wei Fang
2026-09-11 20:17   ` Claudiu Manoil
2026-09-09 10:07 ` [PATCH v4 net-next 12/15] net: enetc: add VF support for i.MX94 and i.MX95 wei.fang
2026-09-09 10:07 ` [PATCH v4 net-next 13/15] net: enetc: implement ndo_set_rx_mode_async for ENETC v4 VF wei.fang
2026-09-10 11:21   ` netdev-bot+sashiko
2026-09-11  7:17     ` Wei Fang
2026-09-09 10:07 ` [PATCH v4 net-next 14/15] net: enetc: add PSI-to-VSI link status notification support for VF wei.fang
2026-09-09 10:07 ` [PATCH v4 net-next 15/15] net: enetc: add ndo_get_vf_config() support wei.fang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260909100733.1139689-5-wei.fang@oss.nxp.com \
    --to=wei.fang@oss.nxp.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=andrew@lunn.ch \
    --cc=claudiu.manoil@nxp.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=imx@lists.linux.dev \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=netdev@vger.kernel.org \
    --cc=olteanv@gmail.com \
    --cc=pabeni@redhat.com \
    --cc=vladimir.oltean@nxp.com \
    --cc=wei.fang@nxp.com \
    --cc=xiaoning.wang@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®