]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
ethtool: linkstate: migrate linkstate functions to support multi-PHY setups
authorOleksij Rempel <o.rempel@pengutronix.de>
Fri, 10 Jan 2025 06:05:11 +0000 (07:05 +0100)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 14 Jan 2025 10:44:19 +0000 (11:44 +0100)
Adapt linkstate_get_sqi() and linkstate_get_sqi_max() to take a
phy_device argument directly, enabling support for setups with
multiple PHYs. The previous assumption of a single PHY attached to
a net_device no longer holds.

Use ethnl_req_get_phydev() to identify the appropriate PHY device
for the operation. Update linkstate_prepare_data() and related
logic to accommodate this change, ensuring compatibility with
multi-PHY configurations.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
net/ethtool/linkstate.c

index 34d76e87847d08983a452ebd3eb89f1191b1a4ed..459cfea7652d44dbaccb10cdeb660a250dc08d90 100644 (file)
@@ -26,9 +26,8 @@ const struct nla_policy ethnl_linkstate_get_policy[] = {
                NLA_POLICY_NESTED(ethnl_header_policy_stats),
 };
 
-static int linkstate_get_sqi(struct net_device *dev)
+static int linkstate_get_sqi(struct phy_device *phydev)
 {
-       struct phy_device *phydev = dev->phydev;
        int ret;
 
        if (!phydev)
@@ -46,9 +45,8 @@ static int linkstate_get_sqi(struct net_device *dev)
        return ret;
 }
 
-static int linkstate_get_sqi_max(struct net_device *dev)
+static int linkstate_get_sqi_max(struct phy_device *phydev)
 {
-       struct phy_device *phydev = dev->phydev;
        int ret;
 
        if (!phydev)
@@ -100,19 +98,28 @@ static int linkstate_prepare_data(const struct ethnl_req_info *req_base,
 {
        struct linkstate_reply_data *data = LINKSTATE_REPDATA(reply_base);
        struct net_device *dev = reply_base->dev;
+       struct nlattr **tb = info->attrs;
+       struct phy_device *phydev;
        int ret;
 
+       phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_LINKSTATE_HEADER],
+                                     info->extack);
+       if (IS_ERR(phydev)) {
+               ret = PTR_ERR(phydev);
+               goto out;
+       }
+
        ret = ethnl_ops_begin(dev);
        if (ret < 0)
                return ret;
        data->link = __ethtool_get_link(dev);
 
-       ret = linkstate_get_sqi(dev);
+       ret = linkstate_get_sqi(phydev);
        if (linkstate_sqi_critical_error(ret))
                goto out;
        data->sqi = ret;
 
-       ret = linkstate_get_sqi_max(dev);
+       ret = linkstate_get_sqi_max(phydev);
        if (linkstate_sqi_critical_error(ret))
                goto out;
        data->sqi_max = ret;
@@ -127,9 +134,9 @@ static int linkstate_prepare_data(const struct ethnl_req_info *req_base,
                           sizeof(data->link_stats) / 8);
 
        if (req_base->flags & ETHTOOL_FLAG_STATS) {
-               if (dev->phydev)
+               if (phydev)
                        data->link_stats.link_down_events =
-                               READ_ONCE(dev->phydev->link_down_events);
+                               READ_ONCE(phydev->link_down_events);
 
                if (dev->ethtool_ops->get_link_ext_stats)
                        dev->ethtool_ops->get_link_ext_stats(dev,