Commit e96c93aa authored by Maxime Chevallier's avatar Maxime Chevallier Committed by David S. Miller
Browse files

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: default avatarMaxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Tested-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3688ff30
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -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;