@@ -802,6 +802,15 @@ struct ethtool_ops {
void (*get_rmon_stats)(struct net_device *dev,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges);
+ void (*get_eth_pmac_phy_stats)(struct net_device *dev,
+ struct ethtool_eth_phy_stats *phy_stats);
+ void (*get_eth_pmac_mac_stats)(struct net_device *dev,
+ struct ethtool_eth_mac_stats *mac_stats);
+ void (*get_eth_pmac_ctrl_stats)(struct net_device *dev,
+ struct ethtool_eth_ctrl_stats *ctrl_stats);
+ void (*get_pmac_rmon_stats)(struct net_device *dev,
+ struct ethtool_rmon_stats *rmon_stats,
+ const struct ethtool_rmon_hist_range **ranges);
int (*get_module_power_mode)(struct net_device *dev,
struct ethtool_module_power_mode_params *params,
struct netlink_ext_ack *extack);
@@ -742,6 +742,10 @@ enum {
ETHTOOL_STATS_ETH_MAC,
ETHTOOL_STATS_ETH_CTRL,
ETHTOOL_STATS_RMON,
+ ETHTOOL_STATS_ETH_PMAC_PHY,
+ ETHTOOL_STATS_ETH_PMAC_MAC,
+ ETHTOOL_STATS_ETH_PMAC_CTRL,
+ ETHTOOL_STATS_PMAC_RMON,
/* add new constants above here */
__ETHTOOL_STATS_CNT
@@ -24,8 +24,13 @@ struct stats_reply_data {
struct ethtool_eth_mac_stats mac_stats;
struct ethtool_eth_ctrl_stats ctrl_stats;
struct ethtool_rmon_stats rmon_stats;
+ struct ethtool_eth_phy_stats pmac_phy_stats;
+ struct ethtool_eth_mac_stats pmac_mac_stats;
+ struct ethtool_eth_ctrl_stats pmac_ctrl_stats;
+ struct ethtool_rmon_stats pmac_rmon_stats;
);
const struct ethtool_rmon_hist_range *rmon_ranges;
+ const struct ethtool_rmon_hist_range *pmac_rmon_ranges;
};
#define STATS_REPDATA(__reply_base) \
@@ -36,6 +41,10 @@ const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN] = {
[ETHTOOL_STATS_ETH_MAC] = "eth-mac",
[ETHTOOL_STATS_ETH_CTRL] = "eth-ctrl",
[ETHTOOL_STATS_RMON] = "rmon",
+ [ETHTOOL_STATS_ETH_PMAC_PHY] = "eth-pmac-phy",
+ [ETHTOOL_STATS_ETH_PMAC_MAC] = "eth-pmac-mac",
+ [ETHTOOL_STATS_ETH_PMAC_CTRL] = "eth-pmac-ctrl",
+ [ETHTOOL_STATS_PMAC_RMON] = "pmac-rmon",
};
const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN] = {
@@ -143,6 +152,20 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
ops->get_rmon_stats(dev, &data->rmon_stats,
&data->rmon_ranges);
+ if (test_bit(ETHTOOL_STATS_ETH_PMAC_PHY, req_info->stat_mask) &&
+ ops->get_eth_pmac_phy_stats)
+ ops->get_eth_pmac_phy_stats(dev, &data->pmac_phy_stats);
+ if (test_bit(ETHTOOL_STATS_ETH_PMAC_MAC, req_info->stat_mask) &&
+ ops->get_eth_pmac_mac_stats)
+ ops->get_eth_pmac_mac_stats(dev, &data->pmac_mac_stats);
+ if (test_bit(ETHTOOL_STATS_ETH_PMAC_CTRL, req_info->stat_mask) &&
+ ops->get_eth_pmac_ctrl_stats)
+ ops->get_eth_pmac_ctrl_stats(dev, &data->pmac_ctrl_stats);
+ if (test_bit(ETHTOOL_STATS_PMAC_RMON, req_info->stat_mask) &&
+ ops->get_pmac_rmon_stats)
+ ops->get_pmac_rmon_stats(dev, &data->pmac_rmon_stats,
+ &data->pmac_rmon_ranges);
+
ethnl_ops_complete(dev);
return 0;
}
@@ -176,6 +199,28 @@ static int stats_reply_size(const struct ethnl_req_info *req_base,
nla_total_size(4)) * /* _A_STATS_GRP_HIST_BKT_HI */
ETHTOOL_RMON_HIST_MAX * 2;
}
+ if (test_bit(ETHTOOL_STATS_ETH_PMAC_PHY, req_info->stat_mask)) {
+ n_stats += sizeof(struct ethtool_eth_mac_stats) / sizeof(u64);
+ n_grps++;
+ }
+ if (test_bit(ETHTOOL_STATS_ETH_PMAC_MAC, req_info->stat_mask)) {
+ n_stats += sizeof(struct ethtool_eth_mac_stats) / sizeof(u64);
+ n_grps++;
+ }
+ if (test_bit(ETHTOOL_STATS_ETH_PMAC_CTRL, req_info->stat_mask)) {
+ n_stats += sizeof(struct ethtool_eth_ctrl_stats) / sizeof(u64);
+ n_grps++;
+ }
+ if (test_bit(ETHTOOL_STATS_PMAC_RMON, req_info->stat_mask)) {
+ n_stats += sizeof(struct ethtool_rmon_stats) / sizeof(u64);
+ n_grps++;
+ /* Above includes the space for _A_STATS_GRP_HIST_VALs */
+
+ len += (nla_total_size(0) + /* _A_STATS_GRP_HIST */
+ nla_total_size(4) + /* _A_STATS_GRP_HIST_BKT_LOW */
+ nla_total_size(4)) * /* _A_STATS_GRP_HIST_BKT_HI */
+ ETHTOOL_RMON_HIST_MAX * 2;
+ }
len += n_grps * (nla_total_size(0) + /* _A_STATS_GRP */
nla_total_size(4) + /* _A_STATS_GRP_ID */
@@ -419,6 +464,31 @@ static int stats_fill_reply(struct sk_buff *skb,
ETH_SS_STATS_RMON, stats_put_rmon_stats);
}
+ if (!ret && test_bit(ETHTOOL_STATS_ETH_PMAC_PHY, req_info->stat_mask))
+ ret = stats_put_stats(skb, &data->pmac_phy_stats,
+ ETHTOOL_STATS_ETH_PMAC_PHY,
+ ETH_SS_STATS_ETH_PHY,
+ stats_put_phy_stats);
+ if (!ret && test_bit(ETHTOOL_STATS_ETH_PMAC_MAC, req_info->stat_mask))
+ ret = stats_put_stats(skb, &data->pmac_mac_stats,
+ ETHTOOL_STATS_ETH_PMAC_MAC,
+ ETH_SS_STATS_ETH_MAC,
+ stats_put_mac_stats);
+ if (!ret && test_bit(ETHTOOL_STATS_ETH_PMAC_CTRL, req_info->stat_mask))
+ ret = stats_put_stats(skb, &data->pmac_ctrl_stats,
+ ETHTOOL_STATS_ETH_PMAC_CTRL,
+ ETH_SS_STATS_ETH_CTRL,
+ stats_put_ctrl_stats);
+ if (!ret && test_bit(ETHTOOL_STATS_PMAC_RMON, req_info->stat_mask)) {
+ struct rmon_stats_put_ctx ctx = {
+ .rmon_stats = &data->pmac_rmon_stats,
+ .rmon_ranges = data->pmac_rmon_ranges,
+ };
+
+ ret = stats_put_stats(skb, &ctx, ETHTOOL_STATS_PMAC_RMON,
+ ETH_SS_STATS_RMON, stats_put_rmon_stats);
+ }
+
return ret;
}
Devices supporting a MAC Merge layer will have a second Ethernet MAC per port which handles preemptable traffic. This has all the same counters as the regular (express) MAC, so export 4 new groups of statistics for it, which have all the same structure as the ones for the eMAC, except for different names. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> --- include/linux/ethtool.h | 9 ++++ include/uapi/linux/ethtool_netlink.h | 4 ++ net/ethtool/stats.c | 70 ++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+)