dwc-xlgmac-ethtool.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* Synopsys DesignWare Core Enterprise Ethernet (XLGMAC) Driver
  2. *
  3. * Copyright (c) 2017 Synopsys, Inc. (www.synopsys.com)
  4. *
  5. * This program is dual-licensed; you may select either version 2 of
  6. * the GNU General Public License ("GPL") or BSD license ("BSD").
  7. *
  8. * This Synopsys DWC XLGMAC software driver and associated documentation
  9. * (hereinafter the "Software") is an unsupported proprietary work of
  10. * Synopsys, Inc. unless otherwise expressly agreed to in writing between
  11. * Synopsys and you. The Software IS NOT an item of Licensed Software or a
  12. * Licensed Product under any End User Software License Agreement or
  13. * Agreement for Licensed Products with Synopsys or any supplement thereto.
  14. * Synopsys is a registered trademark of Synopsys, Inc. Other names included
  15. * in the SOFTWARE may be the trademarks of their respective owners.
  16. */
  17. #include <linux/ethtool.h>
  18. #include <linux/kernel.h>
  19. #include <linux/netdevice.h>
  20. #include "dwc-xlgmac.h"
  21. #include "dwc-xlgmac-reg.h"
  22. struct xlgmac_stats_desc {
  23. char stat_string[ETH_GSTRING_LEN];
  24. int stat_offset;
  25. };
  26. #define XLGMAC_STAT(str, var) \
  27. { \
  28. str, \
  29. offsetof(struct xlgmac_pdata, stats.var), \
  30. }
  31. static const struct xlgmac_stats_desc xlgmac_gstring_stats[] = {
  32. /* MMC TX counters */
  33. XLGMAC_STAT("tx_bytes", txoctetcount_gb),
  34. XLGMAC_STAT("tx_bytes_good", txoctetcount_g),
  35. XLGMAC_STAT("tx_packets", txframecount_gb),
  36. XLGMAC_STAT("tx_packets_good", txframecount_g),
  37. XLGMAC_STAT("tx_unicast_packets", txunicastframes_gb),
  38. XLGMAC_STAT("tx_broadcast_packets", txbroadcastframes_gb),
  39. XLGMAC_STAT("tx_broadcast_packets_good", txbroadcastframes_g),
  40. XLGMAC_STAT("tx_multicast_packets", txmulticastframes_gb),
  41. XLGMAC_STAT("tx_multicast_packets_good", txmulticastframes_g),
  42. XLGMAC_STAT("tx_vlan_packets_good", txvlanframes_g),
  43. XLGMAC_STAT("tx_64_byte_packets", tx64octets_gb),
  44. XLGMAC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb),
  45. XLGMAC_STAT("tx_128_to_255_byte_packets", tx128to255octets_gb),
  46. XLGMAC_STAT("tx_256_to_511_byte_packets", tx256to511octets_gb),
  47. XLGMAC_STAT("tx_512_to_1023_byte_packets", tx512to1023octets_gb),
  48. XLGMAC_STAT("tx_1024_to_max_byte_packets", tx1024tomaxoctets_gb),
  49. XLGMAC_STAT("tx_underflow_errors", txunderflowerror),
  50. XLGMAC_STAT("tx_pause_frames", txpauseframes),
  51. /* MMC RX counters */
  52. XLGMAC_STAT("rx_bytes", rxoctetcount_gb),
  53. XLGMAC_STAT("rx_bytes_good", rxoctetcount_g),
  54. XLGMAC_STAT("rx_packets", rxframecount_gb),
  55. XLGMAC_STAT("rx_unicast_packets_good", rxunicastframes_g),
  56. XLGMAC_STAT("rx_broadcast_packets_good", rxbroadcastframes_g),
  57. XLGMAC_STAT("rx_multicast_packets_good", rxmulticastframes_g),
  58. XLGMAC_STAT("rx_vlan_packets", rxvlanframes_gb),
  59. XLGMAC_STAT("rx_64_byte_packets", rx64octets_gb),
  60. XLGMAC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb),
  61. XLGMAC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb),
  62. XLGMAC_STAT("rx_256_to_511_byte_packets", rx256to511octets_gb),
  63. XLGMAC_STAT("rx_512_to_1023_byte_packets", rx512to1023octets_gb),
  64. XLGMAC_STAT("rx_1024_to_max_byte_packets", rx1024tomaxoctets_gb),
  65. XLGMAC_STAT("rx_undersize_packets_good", rxundersize_g),
  66. XLGMAC_STAT("rx_oversize_packets_good", rxoversize_g),
  67. XLGMAC_STAT("rx_crc_errors", rxcrcerror),
  68. XLGMAC_STAT("rx_crc_errors_small_packets", rxrunterror),
  69. XLGMAC_STAT("rx_crc_errors_giant_packets", rxjabbererror),
  70. XLGMAC_STAT("rx_length_errors", rxlengtherror),
  71. XLGMAC_STAT("rx_out_of_range_errors", rxoutofrangetype),
  72. XLGMAC_STAT("rx_fifo_overflow_errors", rxfifooverflow),
  73. XLGMAC_STAT("rx_watchdog_errors", rxwatchdogerror),
  74. XLGMAC_STAT("rx_pause_frames", rxpauseframes),
  75. /* Extra counters */
  76. XLGMAC_STAT("tx_tso_packets", tx_tso_packets),
  77. XLGMAC_STAT("rx_split_header_packets", rx_split_header_packets),
  78. XLGMAC_STAT("tx_process_stopped", tx_process_stopped),
  79. XLGMAC_STAT("rx_process_stopped", rx_process_stopped),
  80. XLGMAC_STAT("tx_buffer_unavailable", tx_buffer_unavailable),
  81. XLGMAC_STAT("rx_buffer_unavailable", rx_buffer_unavailable),
  82. XLGMAC_STAT("fatal_bus_error", fatal_bus_error),
  83. XLGMAC_STAT("tx_vlan_packets", tx_vlan_packets),
  84. XLGMAC_STAT("rx_vlan_packets", rx_vlan_packets),
  85. XLGMAC_STAT("napi_poll_isr", napi_poll_isr),
  86. XLGMAC_STAT("napi_poll_txtimer", napi_poll_txtimer),
  87. };
  88. #define XLGMAC_STATS_COUNT ARRAY_SIZE(xlgmac_gstring_stats)
  89. static void xlgmac_ethtool_get_drvinfo(struct net_device *netdev,
  90. struct ethtool_drvinfo *drvinfo)
  91. {
  92. struct xlgmac_pdata *pdata = netdev_priv(netdev);
  93. u32 ver = pdata->hw_feat.version;
  94. u32 snpsver, devid, userver;
  95. strscpy(drvinfo->driver, pdata->drv_name, sizeof(drvinfo->driver));
  96. strscpy(drvinfo->version, pdata->drv_ver, sizeof(drvinfo->version));
  97. strscpy(drvinfo->bus_info, dev_name(pdata->dev),
  98. sizeof(drvinfo->bus_info));
  99. /* S|SNPSVER: Synopsys-defined Version
  100. * D|DEVID: Indicates the Device family
  101. * U|USERVER: User-defined Version
  102. */
  103. snpsver = XLGMAC_GET_REG_BITS(ver, MAC_VR_SNPSVER_POS,
  104. MAC_VR_SNPSVER_LEN);
  105. devid = XLGMAC_GET_REG_BITS(ver, MAC_VR_DEVID_POS,
  106. MAC_VR_DEVID_LEN);
  107. userver = XLGMAC_GET_REG_BITS(ver, MAC_VR_USERVER_POS,
  108. MAC_VR_USERVER_LEN);
  109. snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
  110. "S.D.U: %x.%x.%x", snpsver, devid, userver);
  111. }
  112. static u32 xlgmac_ethtool_get_msglevel(struct net_device *netdev)
  113. {
  114. struct xlgmac_pdata *pdata = netdev_priv(netdev);
  115. return pdata->msg_enable;
  116. }
  117. static void xlgmac_ethtool_set_msglevel(struct net_device *netdev,
  118. u32 msglevel)
  119. {
  120. struct xlgmac_pdata *pdata = netdev_priv(netdev);
  121. pdata->msg_enable = msglevel;
  122. }
  123. static void xlgmac_ethtool_get_channels(struct net_device *netdev,
  124. struct ethtool_channels *channel)
  125. {
  126. struct xlgmac_pdata *pdata = netdev_priv(netdev);
  127. channel->max_rx = XLGMAC_MAX_DMA_CHANNELS;
  128. channel->max_tx = XLGMAC_MAX_DMA_CHANNELS;
  129. channel->rx_count = pdata->rx_q_count;
  130. channel->tx_count = pdata->tx_q_count;
  131. }
  132. static int
  133. xlgmac_ethtool_get_coalesce(struct net_device *netdev,
  134. struct ethtool_coalesce *ec,
  135. struct kernel_ethtool_coalesce *kernel_coal,
  136. struct netlink_ext_ack *extack)
  137. {
  138. struct xlgmac_pdata *pdata = netdev_priv(netdev);
  139. ec->rx_coalesce_usecs = pdata->rx_usecs;
  140. ec->rx_max_coalesced_frames = pdata->rx_frames;
  141. ec->tx_max_coalesced_frames = pdata->tx_frames;
  142. return 0;
  143. }
  144. static int
  145. xlgmac_ethtool_set_coalesce(struct net_device *netdev,
  146. struct ethtool_coalesce *ec,
  147. struct kernel_ethtool_coalesce *kernel_coal,
  148. struct netlink_ext_ack *extack)
  149. {
  150. struct xlgmac_pdata *pdata = netdev_priv(netdev);
  151. struct xlgmac_hw_ops *hw_ops = &pdata->hw_ops;
  152. unsigned int rx_frames, rx_riwt, rx_usecs;
  153. unsigned int tx_frames;
  154. rx_usecs = ec->rx_coalesce_usecs;
  155. rx_riwt = hw_ops->usec_to_riwt(pdata, rx_usecs);
  156. rx_frames = ec->rx_max_coalesced_frames;
  157. tx_frames = ec->tx_max_coalesced_frames;
  158. if ((rx_riwt > XLGMAC_MAX_DMA_RIWT) ||
  159. (rx_riwt < XLGMAC_MIN_DMA_RIWT) ||
  160. (rx_frames > pdata->rx_desc_count))
  161. return -EINVAL;
  162. if (tx_frames > pdata->tx_desc_count)
  163. return -EINVAL;
  164. pdata->rx_riwt = rx_riwt;
  165. pdata->rx_usecs = rx_usecs;
  166. pdata->rx_frames = rx_frames;
  167. hw_ops->config_rx_coalesce(pdata);
  168. pdata->tx_frames = tx_frames;
  169. hw_ops->config_tx_coalesce(pdata);
  170. return 0;
  171. }
  172. static void xlgmac_ethtool_get_strings(struct net_device *netdev,
  173. u32 stringset, u8 *data)
  174. {
  175. int i;
  176. switch (stringset) {
  177. case ETH_SS_STATS:
  178. for (i = 0; i < XLGMAC_STATS_COUNT; i++) {
  179. memcpy(data, xlgmac_gstring_stats[i].stat_string,
  180. ETH_GSTRING_LEN);
  181. data += ETH_GSTRING_LEN;
  182. }
  183. break;
  184. default:
  185. WARN_ON(1);
  186. break;
  187. }
  188. }
  189. static int xlgmac_ethtool_get_sset_count(struct net_device *netdev,
  190. int stringset)
  191. {
  192. int ret;
  193. switch (stringset) {
  194. case ETH_SS_STATS:
  195. ret = XLGMAC_STATS_COUNT;
  196. break;
  197. default:
  198. ret = -EOPNOTSUPP;
  199. }
  200. return ret;
  201. }
  202. static void xlgmac_ethtool_get_ethtool_stats(struct net_device *netdev,
  203. struct ethtool_stats *stats,
  204. u64 *data)
  205. {
  206. struct xlgmac_pdata *pdata = netdev_priv(netdev);
  207. u8 *stat;
  208. int i;
  209. pdata->hw_ops.read_mmc_stats(pdata);
  210. for (i = 0; i < XLGMAC_STATS_COUNT; i++) {
  211. stat = (u8 *)pdata + xlgmac_gstring_stats[i].stat_offset;
  212. *data++ = *(u64 *)stat;
  213. }
  214. }
  215. static const struct ethtool_ops xlgmac_ethtool_ops = {
  216. .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
  217. ETHTOOL_COALESCE_MAX_FRAMES,
  218. .get_drvinfo = xlgmac_ethtool_get_drvinfo,
  219. .get_link = ethtool_op_get_link,
  220. .get_msglevel = xlgmac_ethtool_get_msglevel,
  221. .set_msglevel = xlgmac_ethtool_set_msglevel,
  222. .get_channels = xlgmac_ethtool_get_channels,
  223. .get_coalesce = xlgmac_ethtool_get_coalesce,
  224. .set_coalesce = xlgmac_ethtool_set_coalesce,
  225. .get_strings = xlgmac_ethtool_get_strings,
  226. .get_sset_count = xlgmac_ethtool_get_sset_count,
  227. .get_ethtool_stats = xlgmac_ethtool_get_ethtool_stats,
  228. };
  229. const struct ethtool_ops *xlgmac_get_ethtool_ops(void)
  230. {
  231. return &xlgmac_ethtool_ops;
  232. }