net: ethtool: strset: Allow querying phy stats by index

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>
This commit is contained in:
Maxime Chevallier 2024-08-21 17:10:06 +02:00 committed by David S. Miller
parent 3688ff3077
commit e96c93aa4b

View File

@ -126,7 +126,7 @@ struct strset_reply_data {
const struct nla_policy ethnl_strset_get_policy[] = { const struct nla_policy ethnl_strset_get_policy[] = {
[ETHTOOL_A_STRSET_HEADER] = [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_STRINGSETS] = { .type = NLA_NESTED },
[ETHTOOL_A_STRSET_COUNTS_ONLY] = { .type = NLA_FLAG }, [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, 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_phy_ops *phy_ops = ethtool_phy_ops;
const struct ethtool_ops *ops = dev->ethtool_ops; const struct ethtool_ops *ops = dev->ethtool_ops;
void *strings; void *strings;
int count, ret; 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 && !ops->get_ethtool_phy_stats && phy_ops &&
phy_ops->get_sset_count) 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) else if (ops->get_sset_count && ops->get_strings)
ret = ops->get_sset_count(dev, id); ret = ops->get_sset_count(dev, id);
else 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); strings = kcalloc(count, ETH_GSTRING_LEN, GFP_KERNEL);
if (!strings) if (!strings)
return -ENOMEM; return -ENOMEM;
if (id == ETH_SS_PHY_STATS && dev->phydev && if (id == ETH_SS_PHY_STATS && phydev &&
!ops->get_ethtool_phy_stats && phy_ops && !ops->get_ethtool_phy_stats && phy_ops &&
phy_ops->get_strings) phy_ops->get_strings)
phy_ops->get_strings(dev->phydev, strings); phy_ops->get_strings(phydev, strings);
else else
ops->get_strings(dev, id, strings); ops->get_strings(dev, id, strings);
info->strings = 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); const struct strset_req_info *req_info = STRSET_REQINFO(req_base);
struct strset_reply_data *data = STRSET_REPDATA(reply_base); struct strset_reply_data *data = STRSET_REPDATA(reply_base);
struct net_device *dev = reply_base->dev; struct net_device *dev = reply_base->dev;
struct nlattr **tb = info->attrs;
struct phy_device *phydev;
unsigned int i; unsigned int i;
int ret; int ret;
@ -296,6 +299,13 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base,
return 0; 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); ret = ethnl_ops_begin(dev);
if (ret < 0) if (ret < 0)
goto err_strset; goto err_strset;
@ -304,7 +314,7 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base,
!data->sets[i].per_dev) !data->sets[i].per_dev)
continue; continue;
ret = strset_prepare_set(&data->sets[i], dev, i, ret = strset_prepare_set(&data->sets[i], dev, phydev, i,
req_info->counts_only); req_info->counts_only);
if (ret < 0) if (ret < 0)
goto err_ops; goto err_ops;