net: ethtool: strset: Allow querying phy stats by index
authorMaxime Chevallier <maxime.chevallier@bootlin.com>
Wed, 21 Aug 2024 15:10:06 +0000 (17:10 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 23 Aug 2024 12:04:35 +0000 (13:04 +0100)
The ETH_SS_PHY_STATS command gets PHY statistics. Use the phydev pointer
from the ethnl request to allow query phy stats from each PHY on the
link.

Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Tested-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ethtool/strset.c

index 56b99606f00b99665b1cf269a2072047f78f08d2..b3382b3cf325c518b3a61fdff86885f595e7f7d5 100644 (file)
@@ -126,7 +126,7 @@ struct strset_reply_data {
 
 const struct nla_policy ethnl_strset_get_policy[] = {
        [ETHTOOL_A_STRSET_HEADER]       =
-               NLA_POLICY_NESTED(ethnl_header_policy),
+               NLA_POLICY_NESTED(ethnl_header_policy_phy),
        [ETHTOOL_A_STRSET_STRINGSETS]   = { .type = NLA_NESTED },
        [ETHTOOL_A_STRSET_COUNTS_ONLY]  = { .type = NLA_FLAG },
 };
@@ -233,17 +233,18 @@ static void strset_cleanup_data(struct ethnl_reply_data *reply_base)
 }
 
 static int strset_prepare_set(struct strset_info *info, struct net_device *dev,
-                             unsigned int id, bool counts_only)
+                             struct phy_device *phydev, unsigned int id,
+                             bool counts_only)
 {
        const struct ethtool_phy_ops *phy_ops = ethtool_phy_ops;
        const struct ethtool_ops *ops = dev->ethtool_ops;
        void *strings;
        int count, ret;
 
-       if (id == ETH_SS_PHY_STATS && dev->phydev &&
+       if (id == ETH_SS_PHY_STATS && phydev &&
            !ops->get_ethtool_phy_stats && phy_ops &&
            phy_ops->get_sset_count)
-               ret = phy_ops->get_sset_count(dev->phydev);
+               ret = phy_ops->get_sset_count(phydev);
        else if (ops->get_sset_count && ops->get_strings)
                ret = ops->get_sset_count(dev, id);
        else
@@ -258,10 +259,10 @@ static int strset_prepare_set(struct strset_info *info, struct net_device *dev,
                strings = kcalloc(count, ETH_GSTRING_LEN, GFP_KERNEL);
                if (!strings)
                        return -ENOMEM;
-               if (id == ETH_SS_PHY_STATS && dev->phydev &&
+               if (id == ETH_SS_PHY_STATS && phydev &&
                    !ops->get_ethtool_phy_stats && phy_ops &&
                    phy_ops->get_strings)
-                       phy_ops->get_strings(dev->phydev, strings);
+                       phy_ops->get_strings(phydev, strings);
                else
                        ops->get_strings(dev, id, strings);
                info->strings = strings;
@@ -279,6 +280,8 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base,
        const struct strset_req_info *req_info = STRSET_REQINFO(req_base);
        struct strset_reply_data *data = STRSET_REPDATA(reply_base);
        struct net_device *dev = reply_base->dev;
+       struct nlattr **tb = info->attrs;
+       struct phy_device *phydev;
        unsigned int i;
        int ret;
 
@@ -296,6 +299,13 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base,
                return 0;
        }
 
+       phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_HEADER_FLAGS],
+                                     info->extack);
+
+       /* phydev can be NULL, check for errors only */
+       if (IS_ERR(phydev))
+               return PTR_ERR(phydev);
+
        ret = ethnl_ops_begin(dev);
        if (ret < 0)
                goto err_strset;
@@ -304,7 +314,7 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base,
                    !data->sets[i].per_dev)
                        continue;
 
-               ret = strset_prepare_set(&data->sets[i], dev, i,
+               ret = strset_prepare_set(&data->sets[i], dev, phydev, i,
                                         req_info->counts_only);
                if (ret < 0)
                        goto err_ops;