diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c')
| -rw-r--r-- | drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 425 |
1 files changed, 389 insertions, 36 deletions
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c index 422ce13a7c94..1f80a527264a 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -/* Copyright 2019 NXP */ +/* Copyright 2019, 2024-2026 NXP */ #include <linux/acpi.h> #include <linux/pcs-lynx.h> @@ -15,7 +15,195 @@ #define DPMAC_PROTOCOL_CHANGE_VER_MAJOR 4 #define DPMAC_PROTOCOL_CHANGE_VER_MINOR 8 +#define DPMAC_STATS_BUNDLE_VER_MAJOR 4 +#define DPMAC_STATS_BUNDLE_VER_MINOR 10 + +#define DPMAC_STANDARD_STATS_VER_MAJOR 4 +#define DPMAC_STANDARD_STATS_VER_MINOR 11 + #define DPAA2_MAC_FEATURE_PROTOCOL_CHANGE BIT(0) +#define DPAA2_MAC_FEATURE_STATS_BUNDLE BIT(1) +#define DPAA2_MAC_FEATURE_STANDARD_STATS BIT(2) + +struct dpmac_counter { + enum dpmac_counter_id id; + size_t offset; + const char *name; +}; + +#define DPMAC_COUNTER(counter_id, struct_name, struct_offset) \ + { \ + .id = counter_id, \ + .offset = offsetof(struct_name, struct_offset), \ + } + +#define DPMAC_UNSTRUCTURED_COUNTER(counter_id, counter_name) \ + { \ + .id = counter_id, \ + .name = counter_name, \ + } + +#define DPMAC_RMON_COUNTER(counter_id, struct_offset) \ + DPMAC_COUNTER(counter_id, struct ethtool_rmon_stats, struct_offset) + +#define DPMAC_PAUSE_COUNTER(counter_id, struct_offset) \ + DPMAC_COUNTER(counter_id, struct ethtool_pause_stats, struct_offset) + +#define DPMAC_CTRL_COUNTER(counter_id, struct_offset) \ + DPMAC_COUNTER(counter_id, struct ethtool_eth_ctrl_stats, struct_offset) + +#define DPMAC_MAC_COUNTER(counter_id, struct_offset) \ + DPMAC_COUNTER(counter_id, struct ethtool_eth_mac_stats, struct_offset) + +static const struct dpmac_counter dpaa2_mac_ethtool_stats[] = { + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_ALL_FRAME, "[mac] rx all frames"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_GOOD_FRAME, "[mac] rx frames ok"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_ERR_FRAME, "[mac] rx frame errors"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_FRAME_DISCARD, "[mac] rx frame discards"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_UCAST_FRAME, "[mac] rx u-cast"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_BCAST_FRAME, "[mac] rx b-cast"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_MCAST_FRAME, "[mac] rx m-cast"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_FRAME_64, "[mac] rx 64 bytes"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_FRAME_127, "[mac] rx 65-127 bytes"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_FRAME_255, "[mac] rx 128-255 bytes"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_FRAME_511, "[mac] rx 256-511 bytes"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_FRAME_1023, "[mac] rx 512-1023 bytes"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_FRAME_1518, "[mac] rx 1024-1518 bytes"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_FRAME_1519_MAX, "[mac] rx 1519-max bytes"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_FRAG, "[mac] rx frags"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_JABBER, "[mac] rx jabber"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_ALIGN_ERR, "[mac] rx align errors"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_OVERSIZED, "[mac] rx oversized"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_VALID_PAUSE_FRAME, "[mac] rx pause"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_BYTE, "[mac] rx bytes"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_EGR_GOOD_FRAME, "[mac] tx frames ok"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_EGR_UCAST_FRAME, "[mac] tx u-cast"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_EGR_MCAST_FRAME, "[mac] tx m-cast"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_EGR_BCAST_FRAME, "[mac] tx b-cast"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_EGR_ERR_FRAME, "[mac] tx frame errors"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_EGR_UNDERSIZED, "[mac] tx undersized"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_EGR_VALID_PAUSE_FRAME, "[mac] tx b-pause"), + DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_EGR_BYTE, "[mac] tx bytes"), +}; + +#define DPAA2_MAC_NUM_ETHTOOL_STATS ARRAY_SIZE(dpaa2_mac_ethtool_stats) + +static const struct dpmac_counter dpaa2_mac_rmon_stats[] = { + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_64, hist[0]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_127, hist[1]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_255, hist[2]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_511, hist[3]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_1023, hist[4]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_1518, hist[5]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_1519_MAX, hist[6]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_64, hist_tx[0]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_127, hist_tx[1]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_255, hist_tx[2]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_511, hist_tx[3]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_1023, hist_tx[4]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_1518, hist_tx[5]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_1519_MAX, hist_tx[6]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_UNDERSIZED, undersize_pkts), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_OVERSIZED, oversize_pkts), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAG, fragments), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_JABBER, jabbers), +}; + +#define DPAA2_MAC_NUM_RMON_STATS ARRAY_SIZE(dpaa2_mac_rmon_stats) + +static const struct dpmac_counter dpaa2_mac_pause_stats[] = { + DPMAC_PAUSE_COUNTER(DPMAC_CNT_ING_VALID_PAUSE_FRAME, rx_pause_frames), + DPMAC_PAUSE_COUNTER(DPMAC_CNT_EGR_VALID_PAUSE_FRAME, tx_pause_frames), +}; + +#define DPAA2_MAC_NUM_PAUSE_STATS ARRAY_SIZE(dpaa2_mac_pause_stats) + +static const struct dpmac_counter dpaa2_mac_eth_ctrl_stats[] = { + DPMAC_CTRL_COUNTER(DPMAC_CNT_ING_CONTROL_FRAME, MACControlFramesReceived), + DPMAC_CTRL_COUNTER(DPMAC_CNT_EGR_CONTROL_FRAME, MACControlFramesTransmitted), +}; + +#define DPAA2_MAC_NUM_ETH_CTRL_STATS ARRAY_SIZE(dpaa2_mac_eth_ctrl_stats) + +static const struct dpmac_counter dpaa2_mac_eth_mac_stats[] = { + DPMAC_MAC_COUNTER(DPMAC_CNT_EGR_GOOD_FRAME, FramesTransmittedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_GOOD_FRAME, FramesReceivedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_FCS_ERR, FrameCheckSequenceErrors), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_ALIGN_ERR, AlignmentErrors), + DPMAC_MAC_COUNTER(DPMAC_CNT_EGR_ALL_BYTE, OctetsTransmittedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_EGR_ERR_FRAME, FramesLostDueToIntMACXmitError), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_ALL_BYTE, OctetsReceivedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_FRAME_DISCARD_NOT_TRUNC, FramesLostDueToIntMACRcvError), + DPMAC_MAC_COUNTER(DPMAC_CNT_EGR_MCAST_FRAME, MulticastFramesXmittedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_EGR_BCAST_FRAME, BroadcastFramesXmittedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_MCAST_FRAME, MulticastFramesReceivedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_BCAST_FRAME, BroadcastFramesReceivedOK), +}; + +#define DPAA2_MAC_NUM_ETH_MAC_STATS ARRAY_SIZE(dpaa2_mac_eth_mac_stats) + +static void dpaa2_mac_setup_stats(struct dpaa2_mac *mac, + struct dpaa2_mac_stats *stats, + size_t num_stats, + const struct dpmac_counter *counters) +{ + struct device *dev = mac->net_dev->dev.parent; + size_t size_idx, size_values; + __le32 *cnt_idx; + + size_idx = num_stats * sizeof(u32); + stats->idx_dma_mem = dma_alloc_noncoherent(dev, size_idx, + &stats->idx_iova, + DMA_TO_DEVICE, + GFP_KERNEL); + if (!stats->idx_dma_mem) + goto out; + + size_values = num_stats * sizeof(u64); + stats->values_dma_mem = dma_alloc_noncoherent(dev, size_values, + &stats->values_iova, + DMA_FROM_DEVICE, + GFP_KERNEL); + if (!stats->values_dma_mem) + goto err_alloc_values; + + cnt_idx = stats->idx_dma_mem; + for (size_t i = 0; i < num_stats; i++) + *cnt_idx++ = cpu_to_le32((u32)(counters[i].id)); + + dma_sync_single_for_device(dev, stats->idx_iova, size_idx, + DMA_TO_DEVICE); + + return; + +err_alloc_values: + dma_free_noncoherent(dev, num_stats * sizeof(u32), stats->idx_dma_mem, + stats->idx_iova, DMA_TO_DEVICE); +out: + stats->idx_dma_mem = NULL; + stats->values_dma_mem = NULL; +} + +static void dpaa2_mac_clear_stats(struct dpaa2_mac *mac, + struct dpaa2_mac_stats *stats, + size_t num_stats) +{ + struct device *dev = mac->net_dev->dev.parent; + + if (stats->idx_dma_mem) { + dma_free_noncoherent(dev, num_stats * sizeof(u32), + stats->idx_dma_mem, + stats->idx_iova, DMA_TO_DEVICE); + stats->idx_dma_mem = NULL; + } + + if (stats->values_dma_mem) { + dma_free_noncoherent(dev, num_stats * sizeof(u64), + stats->values_dma_mem, + stats->values_iova, DMA_FROM_DEVICE); + stats->values_dma_mem = NULL; + } +} static int dpaa2_mac_cmp_ver(struct dpaa2_mac *mac, u16 ver_major, u16 ver_minor) @@ -32,6 +220,14 @@ static void dpaa2_mac_detect_features(struct dpaa2_mac *mac) if (dpaa2_mac_cmp_ver(mac, DPMAC_PROTOCOL_CHANGE_VER_MAJOR, DPMAC_PROTOCOL_CHANGE_VER_MINOR) >= 0) mac->features |= DPAA2_MAC_FEATURE_PROTOCOL_CHANGE; + + if (dpaa2_mac_cmp_ver(mac, DPMAC_STATS_BUNDLE_VER_MAJOR, + DPMAC_STATS_BUNDLE_VER_MINOR) >= 0) + mac->features |= DPAA2_MAC_FEATURE_STATS_BUNDLE; + + if (dpaa2_mac_cmp_ver(mac, DPMAC_STANDARD_STATS_VER_MAJOR, + DPMAC_STANDARD_STATS_VER_MINOR) >= 0) + mac->features |= DPAA2_MAC_FEATURE_STANDARD_STATS; } static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode) @@ -348,6 +544,7 @@ void dpaa2_mac_start(struct dpaa2_mac *mac) phylink_start(mac->phylink); } +EXPORT_SYMBOL_GPL(dpaa2_mac_start); void dpaa2_mac_stop(struct dpaa2_mac *mac) { @@ -358,6 +555,7 @@ void dpaa2_mac_stop(struct dpaa2_mac *mac) if (mac->serdes_phy) phy_power_off(mac->serdes_phy); } +EXPORT_SYMBOL_GPL(dpaa2_mac_stop); int dpaa2_mac_connect(struct dpaa2_mac *mac) { @@ -450,6 +648,7 @@ err_pcs_destroy: return err; } +EXPORT_SYMBOL_GPL(dpaa2_mac_connect); void dpaa2_mac_disconnect(struct dpaa2_mac *mac) { @@ -462,6 +661,7 @@ void dpaa2_mac_disconnect(struct dpaa2_mac *mac) of_phy_put(mac->serdes_phy); mac->serdes_phy = NULL; } +EXPORT_SYMBOL_GPL(dpaa2_mac_disconnect); int dpaa2_mac_open(struct dpaa2_mac *mac) { @@ -504,77 +704,226 @@ int dpaa2_mac_open(struct dpaa2_mac *mac) mac->fw_node = fw_node; net_dev->dev.of_node = to_of_node(mac->fw_node); + if (mac->features & DPAA2_MAC_FEATURE_STATS_BUNDLE) + dpaa2_mac_setup_stats(mac, &mac->ethtool_stats, + DPAA2_MAC_NUM_ETHTOOL_STATS, + dpaa2_mac_ethtool_stats); + + if (mac->features & DPAA2_MAC_FEATURE_STANDARD_STATS) { + dpaa2_mac_setup_stats(mac, &mac->rmon_stats, + DPAA2_MAC_NUM_RMON_STATS, + dpaa2_mac_rmon_stats); + + dpaa2_mac_setup_stats(mac, &mac->pause_stats, + DPAA2_MAC_NUM_PAUSE_STATS, + dpaa2_mac_pause_stats); + + dpaa2_mac_setup_stats(mac, &mac->eth_ctrl_stats, + DPAA2_MAC_NUM_ETH_CTRL_STATS, + dpaa2_mac_eth_ctrl_stats); + + dpaa2_mac_setup_stats(mac, &mac->eth_mac_stats, + DPAA2_MAC_NUM_ETH_MAC_STATS, + dpaa2_mac_eth_mac_stats); + } + return 0; err_close_dpmac: dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle); return err; } +EXPORT_SYMBOL_GPL(dpaa2_mac_open); void dpaa2_mac_close(struct dpaa2_mac *mac) { struct fsl_mc_device *dpmac_dev = mac->mc_dev; + if (mac->features & DPAA2_MAC_FEATURE_STATS_BUNDLE) + dpaa2_mac_clear_stats(mac, &mac->ethtool_stats, + DPAA2_MAC_NUM_ETHTOOL_STATS); + + if (mac->features & DPAA2_MAC_FEATURE_STANDARD_STATS) { + dpaa2_mac_clear_stats(mac, &mac->rmon_stats, + DPAA2_MAC_NUM_RMON_STATS); + dpaa2_mac_clear_stats(mac, &mac->pause_stats, + DPAA2_MAC_NUM_PAUSE_STATS); + dpaa2_mac_clear_stats(mac, &mac->eth_ctrl_stats, + DPAA2_MAC_NUM_ETH_CTRL_STATS); + dpaa2_mac_clear_stats(mac, &mac->eth_mac_stats, + DPAA2_MAC_NUM_ETH_MAC_STATS); + } + dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle); if (mac->fw_node) fwnode_handle_put(mac->fw_node); } +EXPORT_SYMBOL_GPL(dpaa2_mac_close); -static char dpaa2_mac_ethtool_stats[][ETH_GSTRING_LEN] = { - [DPMAC_CNT_ING_ALL_FRAME] = "[mac] rx all frames", - [DPMAC_CNT_ING_GOOD_FRAME] = "[mac] rx frames ok", - [DPMAC_CNT_ING_ERR_FRAME] = "[mac] rx frame errors", - [DPMAC_CNT_ING_FRAME_DISCARD] = "[mac] rx frame discards", - [DPMAC_CNT_ING_UCAST_FRAME] = "[mac] rx u-cast", - [DPMAC_CNT_ING_BCAST_FRAME] = "[mac] rx b-cast", - [DPMAC_CNT_ING_MCAST_FRAME] = "[mac] rx m-cast", - [DPMAC_CNT_ING_FRAME_64] = "[mac] rx 64 bytes", - [DPMAC_CNT_ING_FRAME_127] = "[mac] rx 65-127 bytes", - [DPMAC_CNT_ING_FRAME_255] = "[mac] rx 128-255 bytes", - [DPMAC_CNT_ING_FRAME_511] = "[mac] rx 256-511 bytes", - [DPMAC_CNT_ING_FRAME_1023] = "[mac] rx 512-1023 bytes", - [DPMAC_CNT_ING_FRAME_1518] = "[mac] rx 1024-1518 bytes", - [DPMAC_CNT_ING_FRAME_1519_MAX] = "[mac] rx 1519-max bytes", - [DPMAC_CNT_ING_FRAG] = "[mac] rx frags", - [DPMAC_CNT_ING_JABBER] = "[mac] rx jabber", - [DPMAC_CNT_ING_ALIGN_ERR] = "[mac] rx align errors", - [DPMAC_CNT_ING_OVERSIZED] = "[mac] rx oversized", - [DPMAC_CNT_ING_VALID_PAUSE_FRAME] = "[mac] rx pause", - [DPMAC_CNT_ING_BYTE] = "[mac] rx bytes", - [DPMAC_CNT_EGR_GOOD_FRAME] = "[mac] tx frames ok", - [DPMAC_CNT_EGR_UCAST_FRAME] = "[mac] tx u-cast", - [DPMAC_CNT_EGR_MCAST_FRAME] = "[mac] tx m-cast", - [DPMAC_CNT_EGR_BCAST_FRAME] = "[mac] tx b-cast", - [DPMAC_CNT_EGR_ERR_FRAME] = "[mac] tx frame errors", - [DPMAC_CNT_EGR_UNDERSIZED] = "[mac] tx undersized", - [DPMAC_CNT_EGR_VALID_PAUSE_FRAME] = "[mac] tx b-pause", - [DPMAC_CNT_EGR_BYTE] = "[mac] tx bytes", +static void dpaa2_mac_transfer_stats(const struct dpmac_counter *counters, + size_t num_counters, void *s, + __le64 *cnt_values) +{ + for (size_t i = 0; i < num_counters; i++) { + u64 *p = s + counters[i].offset; + + *p = le64_to_cpu(cnt_values[i]); + } +} + +static const struct ethtool_rmon_hist_range dpaa2_mac_rmon_ranges[] = { + { 64, 64 }, + { 65, 127 }, + { 128, 255 }, + { 256, 511 }, + { 512, 1023 }, + { 1024, 1518 }, + { 1519, DPAA2_ETH_MFL }, + {}, }; -#define DPAA2_MAC_NUM_STATS ARRAY_SIZE(dpaa2_mac_ethtool_stats) +static void dpaa2_mac_get_standard_stats(struct dpaa2_mac *mac, + struct dpaa2_mac_stats *stats, + size_t num_cnt, + const struct dpmac_counter *counters, + void *s) +{ + struct device *dev = mac->net_dev->dev.parent; + struct fsl_mc_device *dpmac_dev = mac->mc_dev; + size_t values_size = num_cnt * sizeof(u64); + int err; + + if (!(mac->features & DPAA2_MAC_FEATURE_STANDARD_STATS)) + return; + + if (!stats->idx_dma_mem || !stats->values_dma_mem) + return; + + dma_sync_single_for_device(dev, stats->values_iova, values_size, + DMA_FROM_DEVICE); + + err = dpmac_get_statistics(mac->mc_io, 0, dpmac_dev->mc_handle, + stats->idx_iova, stats->values_iova, + num_cnt); + if (err) { + netdev_err(mac->net_dev, "%s: dpmac_get_statistics() = %d\n", + __func__, err); + return; + } + + dma_sync_single_for_cpu(dev, stats->values_iova, values_size, + DMA_FROM_DEVICE); + + dpaa2_mac_transfer_stats(counters, num_cnt, s, stats->values_dma_mem); +} + +void dpaa2_mac_get_rmon_stats(struct dpaa2_mac *mac, + struct ethtool_rmon_stats *s, + const struct ethtool_rmon_hist_range **ranges) +{ + if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) + return; + + dpaa2_mac_get_standard_stats(mac, &mac->rmon_stats, + DPAA2_MAC_NUM_RMON_STATS, + dpaa2_mac_rmon_stats, s); + + *ranges = dpaa2_mac_rmon_ranges; +} +EXPORT_SYMBOL_GPL(dpaa2_mac_get_rmon_stats); + +void dpaa2_mac_get_pause_stats(struct dpaa2_mac *mac, + struct ethtool_pause_stats *s) +{ + if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) + return; + + dpaa2_mac_get_standard_stats(mac, &mac->pause_stats, + DPAA2_MAC_NUM_PAUSE_STATS, + dpaa2_mac_pause_stats, s); +} +EXPORT_SYMBOL_GPL(dpaa2_mac_get_pause_stats); + +void dpaa2_mac_get_ctrl_stats(struct dpaa2_mac *mac, + struct ethtool_eth_ctrl_stats *s) +{ + if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) + return; + + dpaa2_mac_get_standard_stats(mac, &mac->eth_ctrl_stats, + DPAA2_MAC_NUM_ETH_CTRL_STATS, + dpaa2_mac_eth_ctrl_stats, s); +} +EXPORT_SYMBOL_GPL(dpaa2_mac_get_ctrl_stats); + +void dpaa2_mac_get_eth_mac_stats(struct dpaa2_mac *mac, + struct ethtool_eth_mac_stats *s) +{ + if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) + return; + + dpaa2_mac_get_standard_stats(mac, &mac->eth_mac_stats, + DPAA2_MAC_NUM_ETH_MAC_STATS, + dpaa2_mac_eth_mac_stats, s); +} +EXPORT_SYMBOL_GPL(dpaa2_mac_get_eth_mac_stats); int dpaa2_mac_get_sset_count(void) { - return DPAA2_MAC_NUM_STATS; + return DPAA2_MAC_NUM_ETHTOOL_STATS; } +EXPORT_SYMBOL_GPL(dpaa2_mac_get_sset_count); void dpaa2_mac_get_strings(u8 **data) { int i; - for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) - ethtool_puts(data, dpaa2_mac_ethtool_stats[i]); + for (i = 0; i < DPAA2_MAC_NUM_ETHTOOL_STATS; i++) + ethtool_puts(data, dpaa2_mac_ethtool_stats[i].name); } +EXPORT_SYMBOL_GPL(dpaa2_mac_get_strings); void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data) { + size_t values_size = DPAA2_MAC_NUM_ETHTOOL_STATS * sizeof(u64); + struct device *dev = mac->net_dev->dev.parent; struct fsl_mc_device *dpmac_dev = mac->mc_dev; + __le64 *cnt_values; int i, err; u64 value; - for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) { + if (!(mac->features & DPAA2_MAC_FEATURE_STATS_BUNDLE)) + goto fallback; + + if (!mac->ethtool_stats.idx_dma_mem || + !mac->ethtool_stats.values_dma_mem) + goto fallback; + + dma_sync_single_for_device(dev, mac->ethtool_stats.values_iova, + values_size, DMA_FROM_DEVICE); + + err = dpmac_get_statistics(mac->mc_io, 0, dpmac_dev->mc_handle, + mac->ethtool_stats.idx_iova, + mac->ethtool_stats.values_iova, + DPAA2_MAC_NUM_ETHTOOL_STATS); + if (err) + goto fallback; + + dma_sync_single_for_cpu(dev, mac->ethtool_stats.values_iova, + values_size, DMA_FROM_DEVICE); + + cnt_values = mac->ethtool_stats.values_dma_mem; + for (i = 0; i < DPAA2_MAC_NUM_ETHTOOL_STATS; i++) + *(data + i) = le64_to_cpu(*cnt_values++); + + return; + +fallback: + + /* Fallback and retrieve each counter one by one */ + for (i = 0; i < DPAA2_MAC_NUM_ETHTOOL_STATS; i++) { err = dpmac_get_counter(mac->mc_io, 0, dpmac_dev->mc_handle, - i, &value); + dpaa2_mac_ethtool_stats[i].id, &value); if (err) { netdev_err_once(mac->net_dev, "dpmac_get_counter error %d\n", err); @@ -584,3 +933,7 @@ void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data) *(data + i) = value; } } +EXPORT_SYMBOL_GPL(dpaa2_mac_get_ethtool_stats); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DPAA2 Ethernet MAC library"); |
