rockchip_canfd-ethtool.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Copyright (c) 2023, 2024 Pengutronix,
  4. // Marc Kleine-Budde <kernel@pengutronix.de>
  5. //
  6. #include <linux/ethtool.h>
  7. #include "rockchip_canfd.h"
  8. enum rkcanfd_stats_type {
  9. RKCANFD_STATS_TYPE_RX_FIFO_EMPTY_ERRORS,
  10. RKCANFD_STATS_TYPE_TX_EXTENDED_AS_STANDARD_ERRORS,
  11. };
  12. static const char rkcanfd_stats_strings[][ETH_GSTRING_LEN] = {
  13. [RKCANFD_STATS_TYPE_RX_FIFO_EMPTY_ERRORS] = "rx_fifo_empty_errors",
  14. [RKCANFD_STATS_TYPE_TX_EXTENDED_AS_STANDARD_ERRORS] = "tx_extended_as_standard_errors",
  15. };
  16. static void
  17. rkcanfd_ethtool_get_strings(struct net_device *ndev, u32 stringset, u8 *buf)
  18. {
  19. switch (stringset) {
  20. case ETH_SS_STATS:
  21. memcpy(buf, rkcanfd_stats_strings,
  22. sizeof(rkcanfd_stats_strings));
  23. }
  24. }
  25. static int rkcanfd_ethtool_get_sset_count(struct net_device *netdev, int sset)
  26. {
  27. switch (sset) {
  28. case ETH_SS_STATS:
  29. return ARRAY_SIZE(rkcanfd_stats_strings);
  30. default:
  31. return -EOPNOTSUPP;
  32. }
  33. }
  34. static void
  35. rkcanfd_ethtool_get_ethtool_stats(struct net_device *ndev,
  36. struct ethtool_stats *stats, u64 *data)
  37. {
  38. struct rkcanfd_priv *priv = netdev_priv(ndev);
  39. struct rkcanfd_stats *rkcanfd_stats;
  40. unsigned int start;
  41. rkcanfd_stats = &priv->stats;
  42. do {
  43. start = u64_stats_fetch_begin(&rkcanfd_stats->syncp);
  44. data[RKCANFD_STATS_TYPE_RX_FIFO_EMPTY_ERRORS] =
  45. u64_stats_read(&rkcanfd_stats->rx_fifo_empty_errors);
  46. data[RKCANFD_STATS_TYPE_TX_EXTENDED_AS_STANDARD_ERRORS] =
  47. u64_stats_read(&rkcanfd_stats->tx_extended_as_standard_errors);
  48. } while (u64_stats_fetch_retry(&rkcanfd_stats->syncp, start));
  49. }
  50. static const struct ethtool_ops rkcanfd_ethtool_ops = {
  51. .get_ts_info = can_ethtool_op_get_ts_info_hwts,
  52. .get_strings = rkcanfd_ethtool_get_strings,
  53. .get_sset_count = rkcanfd_ethtool_get_sset_count,
  54. .get_ethtool_stats = rkcanfd_ethtool_get_ethtool_stats,
  55. };
  56. void rkcanfd_ethtool_init(struct rkcanfd_priv *priv)
  57. {
  58. priv->ndev->ethtool_ops = &rkcanfd_ethtool_ops;
  59. u64_stats_init(&priv->stats.syncp);
  60. }