altera_tse_ethtool.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Ethtool support for Altera Triple-Speed Ethernet MAC driver
  3. * Copyright (C) 2008-2014 Altera Corporation. All rights reserved
  4. *
  5. * Contributors:
  6. * Dalon Westergreen
  7. * Thomas Chou
  8. * Ian Abbott
  9. * Yuriy Kozlov
  10. * Tobias Klauser
  11. * Andriy Smolskyy
  12. * Roman Bulgakov
  13. * Dmytro Mytarchuk
  14. *
  15. * Original driver contributed by SLS.
  16. * Major updates contributed by GlobalLogic
  17. */
  18. #include <linux/ethtool.h>
  19. #include <linux/kernel.h>
  20. #include <linux/netdevice.h>
  21. #include <linux/phy.h>
  22. #include "altera_tse.h"
  23. #define TSE_STATS_LEN 31
  24. #define TSE_NUM_REGS 128
  25. static char const stat_gstrings[][ETH_GSTRING_LEN] = {
  26. "tx_packets",
  27. "rx_packets",
  28. "rx_crc_errors",
  29. "rx_align_errors",
  30. "tx_bytes",
  31. "rx_bytes",
  32. "tx_pause",
  33. "rx_pause",
  34. "rx_errors",
  35. "tx_errors",
  36. "rx_unicast",
  37. "rx_multicast",
  38. "rx_broadcast",
  39. "tx_discards",
  40. "tx_unicast",
  41. "tx_multicast",
  42. "tx_broadcast",
  43. "ether_drops",
  44. "rx_total_bytes",
  45. "rx_total_packets",
  46. "rx_undersize",
  47. "rx_oversize",
  48. "rx_64_bytes",
  49. "rx_65_127_bytes",
  50. "rx_128_255_bytes",
  51. "rx_256_511_bytes",
  52. "rx_512_1023_bytes",
  53. "rx_1024_1518_bytes",
  54. "rx_gte_1519_bytes",
  55. "rx_jabbers",
  56. "rx_runts",
  57. };
  58. static void tse_get_drvinfo(struct net_device *dev,
  59. struct ethtool_drvinfo *info)
  60. {
  61. struct altera_tse_private *priv = netdev_priv(dev);
  62. u32 rev = ioread32(&priv->mac_dev->megacore_revision);
  63. strcpy(info->driver, "altera_tse");
  64. snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "v%d.%d",
  65. rev & 0xFFFF, (rev & 0xFFFF0000) >> 16);
  66. sprintf(info->bus_info, "platform");
  67. }
  68. /* Fill in a buffer with the strings which correspond to the
  69. * stats
  70. */
  71. static void tse_gstrings(struct net_device *dev, u32 stringset, u8 *buf)
  72. {
  73. memcpy(buf, stat_gstrings, TSE_STATS_LEN * ETH_GSTRING_LEN);
  74. }
  75. static void tse_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
  76. u64 *buf)
  77. {
  78. struct altera_tse_private *priv = netdev_priv(dev);
  79. u64 ext;
  80. buf[0] = csrrd32(priv->mac_dev,
  81. tse_csroffs(frames_transmitted_ok));
  82. buf[1] = csrrd32(priv->mac_dev,
  83. tse_csroffs(frames_received_ok));
  84. buf[2] = csrrd32(priv->mac_dev,
  85. tse_csroffs(frames_check_sequence_errors));
  86. buf[3] = csrrd32(priv->mac_dev,
  87. tse_csroffs(alignment_errors));
  88. /* Extended aOctetsTransmittedOK counter */
  89. ext = (u64) csrrd32(priv->mac_dev,
  90. tse_csroffs(msb_octets_transmitted_ok)) << 32;
  91. ext |= csrrd32(priv->mac_dev,
  92. tse_csroffs(octets_transmitted_ok));
  93. buf[4] = ext;
  94. /* Extended aOctetsReceivedOK counter */
  95. ext = (u64) csrrd32(priv->mac_dev,
  96. tse_csroffs(msb_octets_received_ok)) << 32;
  97. ext |= csrrd32(priv->mac_dev,
  98. tse_csroffs(octets_received_ok));
  99. buf[5] = ext;
  100. buf[6] = csrrd32(priv->mac_dev,
  101. tse_csroffs(tx_pause_mac_ctrl_frames));
  102. buf[7] = csrrd32(priv->mac_dev,
  103. tse_csroffs(rx_pause_mac_ctrl_frames));
  104. buf[8] = csrrd32(priv->mac_dev,
  105. tse_csroffs(if_in_errors));
  106. buf[9] = csrrd32(priv->mac_dev,
  107. tse_csroffs(if_out_errors));
  108. buf[10] = csrrd32(priv->mac_dev,
  109. tse_csroffs(if_in_ucast_pkts));
  110. buf[11] = csrrd32(priv->mac_dev,
  111. tse_csroffs(if_in_multicast_pkts));
  112. buf[12] = csrrd32(priv->mac_dev,
  113. tse_csroffs(if_in_broadcast_pkts));
  114. buf[13] = csrrd32(priv->mac_dev,
  115. tse_csroffs(if_out_discards));
  116. buf[14] = csrrd32(priv->mac_dev,
  117. tse_csroffs(if_out_ucast_pkts));
  118. buf[15] = csrrd32(priv->mac_dev,
  119. tse_csroffs(if_out_multicast_pkts));
  120. buf[16] = csrrd32(priv->mac_dev,
  121. tse_csroffs(if_out_broadcast_pkts));
  122. buf[17] = csrrd32(priv->mac_dev,
  123. tse_csroffs(ether_stats_drop_events));
  124. /* Extended etherStatsOctets counter */
  125. ext = (u64) csrrd32(priv->mac_dev,
  126. tse_csroffs(msb_ether_stats_octets)) << 32;
  127. ext |= csrrd32(priv->mac_dev,
  128. tse_csroffs(ether_stats_octets));
  129. buf[18] = ext;
  130. buf[19] = csrrd32(priv->mac_dev,
  131. tse_csroffs(ether_stats_pkts));
  132. buf[20] = csrrd32(priv->mac_dev,
  133. tse_csroffs(ether_stats_undersize_pkts));
  134. buf[21] = csrrd32(priv->mac_dev,
  135. tse_csroffs(ether_stats_oversize_pkts));
  136. buf[22] = csrrd32(priv->mac_dev,
  137. tse_csroffs(ether_stats_pkts_64_octets));
  138. buf[23] = csrrd32(priv->mac_dev,
  139. tse_csroffs(ether_stats_pkts_65to127_octets));
  140. buf[24] = csrrd32(priv->mac_dev,
  141. tse_csroffs(ether_stats_pkts_128to255_octets));
  142. buf[25] = csrrd32(priv->mac_dev,
  143. tse_csroffs(ether_stats_pkts_256to511_octets));
  144. buf[26] = csrrd32(priv->mac_dev,
  145. tse_csroffs(ether_stats_pkts_512to1023_octets));
  146. buf[27] = csrrd32(priv->mac_dev,
  147. tse_csroffs(ether_stats_pkts_1024to1518_octets));
  148. buf[28] = csrrd32(priv->mac_dev,
  149. tse_csroffs(ether_stats_pkts_1519tox_octets));
  150. buf[29] = csrrd32(priv->mac_dev,
  151. tse_csroffs(ether_stats_jabbers));
  152. buf[30] = csrrd32(priv->mac_dev,
  153. tse_csroffs(ether_stats_fragments));
  154. }
  155. static int tse_sset_count(struct net_device *dev, int sset)
  156. {
  157. switch (sset) {
  158. case ETH_SS_STATS:
  159. return TSE_STATS_LEN;
  160. default:
  161. return -EOPNOTSUPP;
  162. }
  163. }
  164. static u32 tse_get_msglevel(struct net_device *dev)
  165. {
  166. struct altera_tse_private *priv = netdev_priv(dev);
  167. return priv->msg_enable;
  168. }
  169. static void tse_set_msglevel(struct net_device *dev, uint32_t data)
  170. {
  171. struct altera_tse_private *priv = netdev_priv(dev);
  172. priv->msg_enable = data;
  173. }
  174. static int tse_reglen(struct net_device *dev)
  175. {
  176. return TSE_NUM_REGS * sizeof(u32);
  177. }
  178. static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs,
  179. void *regbuf)
  180. {
  181. struct altera_tse_private *priv = netdev_priv(dev);
  182. u32 *buf = regbuf;
  183. int i;
  184. /* Set version to a known value, so ethtool knows
  185. * how to do any special formatting of this data.
  186. * This version number will need to change if and
  187. * when this register table is changed.
  188. *
  189. * version[31:0] = 1: Dump the first 128 TSE Registers
  190. * Upper bits are all 0 by default
  191. *
  192. * Upper 16-bits will indicate feature presence for
  193. * Ethtool register decoding in future version.
  194. */
  195. regs->version = 1;
  196. for (i = 0; i < TSE_NUM_REGS; i++)
  197. buf[i] = csrrd32(priv->mac_dev, i * 4);
  198. }
  199. static int tse_ethtool_set_link_ksettings(struct net_device *dev,
  200. const struct ethtool_link_ksettings *cmd)
  201. {
  202. struct altera_tse_private *priv = netdev_priv(dev);
  203. return phylink_ethtool_ksettings_set(priv->phylink, cmd);
  204. }
  205. static int tse_ethtool_get_link_ksettings(struct net_device *dev,
  206. struct ethtool_link_ksettings *cmd)
  207. {
  208. struct altera_tse_private *priv = netdev_priv(dev);
  209. return phylink_ethtool_ksettings_get(priv->phylink, cmd);
  210. }
  211. static const struct ethtool_ops tse_ethtool_ops = {
  212. .get_drvinfo = tse_get_drvinfo,
  213. .get_regs_len = tse_reglen,
  214. .get_regs = tse_get_regs,
  215. .get_link = ethtool_op_get_link,
  216. .get_strings = tse_gstrings,
  217. .get_sset_count = tse_sset_count,
  218. .get_ethtool_stats = tse_fill_stats,
  219. .get_msglevel = tse_get_msglevel,
  220. .set_msglevel = tse_set_msglevel,
  221. .get_link_ksettings = tse_ethtool_get_link_ksettings,
  222. .set_link_ksettings = tse_ethtool_set_link_ksettings,
  223. .get_ts_info = ethtool_op_get_ts_info,
  224. };
  225. void altera_tse_set_ethtool_ops(struct net_device *netdev)
  226. {
  227. netdev->ethtool_ops = &tse_ethtool_ops;
  228. }