summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c')
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c425
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");