dwc-xlgmac-ethtool.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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. strlcpy(drvinfo->driver, pdata->drv_name, sizeof(drvinfo->driver));
  96. strlcpy(drvinfo->version, pdata->drv_ver, sizeof(drvinfo->version));
  97. strlcpy(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 xlgmac_ethtool_get_coalesce(struct net_device *netdev,
  133. struct ethtool_coalesce *ec)
  134. {
  135. struct xlgmac_pdata *pdata = netdev_priv(netdev);
  136. memset(ec, 0, sizeof(struct ethtool_coalesce));
  137. ec->rx_coalesce_usecs = pdata->rx_usecs;
  138. ec->rx_max_coalesced_frames = pdata->rx_frames;
  139. ec->tx_max_coalesced_frames = pdata->tx_frames;
  140. return 0;
  141. }
  142. static int xlgmac_ethtool_set_coalesce(struct net_device *netdev,
  143. struct ethtool_coalesce *ec)
  144. {
  145. struct xlgmac_pdata *pdata = netdev_priv(netdev);
  146. struct xlgmac_hw_ops *hw_ops = &pdata->hw_ops;
  147. unsigned int rx_frames, rx_riwt, rx_usecs;
  148. unsigned int tx_frames;
  149. /* Check for not supported parameters */
  150. if ((ec->rx_coalesce_usecs_irq) || (ec->rx_max_coalesced_frames_irq) ||
  151. (ec->tx_coalesce_usecs) || (ec->tx_coalesce_usecs_high) ||
  152. (ec->tx_max_coalesced_frames_irq) || (ec->tx_coalesce_usecs_irq) ||
  153. (ec->stats_block_coalesce_usecs) || (ec->pkt_rate_low) ||
  154. (ec->use_adaptive_rx_coalesce) || (ec->use_adaptive_tx_coalesce) ||
  155. (ec->rx_max_coalesced_frames_low) || (ec->rx_coalesce_usecs_low) ||
  156. (ec->tx_coalesce_usecs_low) || (ec->tx_max_coalesced_frames_low) ||
  157. (ec->pkt_rate_high) || (ec->rx_coalesce_usecs_high) ||
  158. (ec->rx_max_coalesced_frames_high) ||
  159. (ec->tx_max_coalesced_frames_high) ||
  160. (ec->rate_sample_interval))
  161. return -EOPNOTSUPP;
  162. rx_usecs = ec->rx_coalesce_usecs;
  163. rx_riwt = hw_ops->usec_to_riwt(pdata, rx_usecs);
  164. rx_frames = ec->rx_max_coalesced_frames;
  165. tx_frames = ec->tx_max_coalesced_frames;
  166. if ((rx_riwt > XLGMAC_MAX_DMA_RIWT) ||
  167. (rx_riwt < XLGMAC_MIN_DMA_RIWT) ||
  168. (rx_frames > pdata->rx_desc_count))
  169. return -EINVAL;
  170. if (tx_frames > pdata->tx_desc_count)
  171. return -EINVAL;
  172. pdata->rx_riwt = rx_riwt;
  173. pdata->rx_usecs = rx_usecs;
  174. pdata->rx_frames = rx_frames;
  175. hw_ops->config_rx_coalesce(pdata);
  176. pdata->tx_frames = tx_frames;
  177. hw_ops->config_tx_coalesce(pdata);
  178. return 0;
  179. }
  180. static void xlgmac_ethtool_get_strings(struct net_device *netdev,
  181. u32 stringset, u8 *data)
  182. {
  183. int i;
  184. switch (stringset) {
  185. case ETH_SS_STATS:
  186. for (i = 0; i < XLGMAC_STATS_COUNT; i++) {
  187. memcpy(data, xlgmac_gstring_stats[i].stat_string,
  188. ETH_GSTRING_LEN);
  189. data += ETH_GSTRING_LEN;
  190. }
  191. break;
  192. default:
  193. WARN_ON(1);
  194. break;
  195. }
  196. }
  197. static int xlgmac_ethtool_get_sset_count(struct net_device *netdev,
  198. int stringset)
  199. {
  200. int ret;
  201. switch (stringset) {
  202. case ETH_SS_STATS:
  203. ret = XLGMAC_STATS_COUNT;
  204. break;
  205. default:
  206. ret = -EOPNOTSUPP;
  207. }
  208. return ret;
  209. }
  210. static void xlgmac_ethtool_get_ethtool_stats(struct net_device *netdev,
  211. struct ethtool_stats *stats,
  212. u64 *data)
  213. {
  214. struct xlgmac_pdata *pdata = netdev_priv(netdev);
  215. u8 *stat;
  216. int i;
  217. pdata->hw_ops.read_mmc_stats(pdata);
  218. for (i = 0; i < XLGMAC_STATS_COUNT; i++) {
  219. stat = (u8 *)pdata + xlgmac_gstring_stats[i].stat_offset;
  220. *data++ = *(u64 *)stat;
  221. }
  222. }
  223. static const struct ethtool_ops xlgmac_ethtool_ops = {
  224. .get_drvinfo = xlgmac_ethtool_get_drvinfo,
  225. .get_link = ethtool_op_get_link,
  226. .get_msglevel = xlgmac_ethtool_get_msglevel,
  227. .set_msglevel = xlgmac_ethtool_set_msglevel,
  228. .get_channels = xlgmac_ethtool_get_channels,
  229. .get_coalesce = xlgmac_ethtool_get_coalesce,
  230. .set_coalesce = xlgmac_ethtool_set_coalesce,
  231. .get_strings = xlgmac_ethtool_get_strings,
  232. .get_sset_count = xlgmac_ethtool_get_sset_count,
  233. .get_ethtool_stats = xlgmac_ethtool_get_ethtool_stats,
  234. };
  235. const struct ethtool_ops *xlgmac_get_ethtool_ops(void)
  236. {
  237. return &xlgmac_ethtool_ops;
  238. }