lan966x_ethtool.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. // SPDX-License-Identifier: GPL-2.0+
  2. #include <linux/netdevice.h>
  3. #include "lan966x_main.h"
  4. /* Number of traffic classes */
  5. #define LAN966X_NUM_TC 8
  6. #define LAN966X_STATS_CHECK_DELAY (2 * HZ)
  7. static const struct lan966x_stat_layout lan966x_stats_layout[] = {
  8. { .name = "rx_octets", .offset = 0x00, },
  9. { .name = "rx_unicast", .offset = 0x01, },
  10. { .name = "rx_multicast", .offset = 0x02 },
  11. { .name = "rx_broadcast", .offset = 0x03 },
  12. { .name = "rx_short", .offset = 0x04 },
  13. { .name = "rx_frag", .offset = 0x05 },
  14. { .name = "rx_jabber", .offset = 0x06 },
  15. { .name = "rx_crc", .offset = 0x07 },
  16. { .name = "rx_symbol_err", .offset = 0x08 },
  17. { .name = "rx_sz_64", .offset = 0x09 },
  18. { .name = "rx_sz_65_127", .offset = 0x0a},
  19. { .name = "rx_sz_128_255", .offset = 0x0b},
  20. { .name = "rx_sz_256_511", .offset = 0x0c },
  21. { .name = "rx_sz_512_1023", .offset = 0x0d },
  22. { .name = "rx_sz_1024_1526", .offset = 0x0e },
  23. { .name = "rx_sz_jumbo", .offset = 0x0f },
  24. { .name = "rx_pause", .offset = 0x10 },
  25. { .name = "rx_control", .offset = 0x11 },
  26. { .name = "rx_long", .offset = 0x12 },
  27. { .name = "rx_cat_drop", .offset = 0x13 },
  28. { .name = "rx_red_prio_0", .offset = 0x14 },
  29. { .name = "rx_red_prio_1", .offset = 0x15 },
  30. { .name = "rx_red_prio_2", .offset = 0x16 },
  31. { .name = "rx_red_prio_3", .offset = 0x17 },
  32. { .name = "rx_red_prio_4", .offset = 0x18 },
  33. { .name = "rx_red_prio_5", .offset = 0x19 },
  34. { .name = "rx_red_prio_6", .offset = 0x1a },
  35. { .name = "rx_red_prio_7", .offset = 0x1b },
  36. { .name = "rx_yellow_prio_0", .offset = 0x1c },
  37. { .name = "rx_yellow_prio_1", .offset = 0x1d },
  38. { .name = "rx_yellow_prio_2", .offset = 0x1e },
  39. { .name = "rx_yellow_prio_3", .offset = 0x1f },
  40. { .name = "rx_yellow_prio_4", .offset = 0x20 },
  41. { .name = "rx_yellow_prio_5", .offset = 0x21 },
  42. { .name = "rx_yellow_prio_6", .offset = 0x22 },
  43. { .name = "rx_yellow_prio_7", .offset = 0x23 },
  44. { .name = "rx_green_prio_0", .offset = 0x24 },
  45. { .name = "rx_green_prio_1", .offset = 0x25 },
  46. { .name = "rx_green_prio_2", .offset = 0x26 },
  47. { .name = "rx_green_prio_3", .offset = 0x27 },
  48. { .name = "rx_green_prio_4", .offset = 0x28 },
  49. { .name = "rx_green_prio_5", .offset = 0x29 },
  50. { .name = "rx_green_prio_6", .offset = 0x2a },
  51. { .name = "rx_green_prio_7", .offset = 0x2b },
  52. { .name = "rx_assembly_err", .offset = 0x2c },
  53. { .name = "rx_smd_err", .offset = 0x2d },
  54. { .name = "rx_assembly_ok", .offset = 0x2e },
  55. { .name = "rx_merge_frag", .offset = 0x2f },
  56. { .name = "rx_pmac_octets", .offset = 0x30, },
  57. { .name = "rx_pmac_unicast", .offset = 0x31, },
  58. { .name = "rx_pmac_multicast", .offset = 0x32 },
  59. { .name = "rx_pmac_broadcast", .offset = 0x33 },
  60. { .name = "rx_pmac_short", .offset = 0x34 },
  61. { .name = "rx_pmac_frag", .offset = 0x35 },
  62. { .name = "rx_pmac_jabber", .offset = 0x36 },
  63. { .name = "rx_pmac_crc", .offset = 0x37 },
  64. { .name = "rx_pmac_symbol_err", .offset = 0x38 },
  65. { .name = "rx_pmac_sz_64", .offset = 0x39 },
  66. { .name = "rx_pmac_sz_65_127", .offset = 0x3a },
  67. { .name = "rx_pmac_sz_128_255", .offset = 0x3b },
  68. { .name = "rx_pmac_sz_256_511", .offset = 0x3c },
  69. { .name = "rx_pmac_sz_512_1023", .offset = 0x3d },
  70. { .name = "rx_pmac_sz_1024_1526", .offset = 0x3e },
  71. { .name = "rx_pmac_sz_jumbo", .offset = 0x3f },
  72. { .name = "rx_pmac_pause", .offset = 0x40 },
  73. { .name = "rx_pmac_control", .offset = 0x41 },
  74. { .name = "rx_pmac_long", .offset = 0x42 },
  75. { .name = "tx_octets", .offset = 0x80, },
  76. { .name = "tx_unicast", .offset = 0x81, },
  77. { .name = "tx_multicast", .offset = 0x82 },
  78. { .name = "tx_broadcast", .offset = 0x83 },
  79. { .name = "tx_col", .offset = 0x84 },
  80. { .name = "tx_drop", .offset = 0x85 },
  81. { .name = "tx_pause", .offset = 0x86 },
  82. { .name = "tx_sz_64", .offset = 0x87 },
  83. { .name = "tx_sz_65_127", .offset = 0x88 },
  84. { .name = "tx_sz_128_255", .offset = 0x89 },
  85. { .name = "tx_sz_256_511", .offset = 0x8a },
  86. { .name = "tx_sz_512_1023", .offset = 0x8b },
  87. { .name = "tx_sz_1024_1526", .offset = 0x8c },
  88. { .name = "tx_sz_jumbo", .offset = 0x8d },
  89. { .name = "tx_yellow_prio_0", .offset = 0x8e },
  90. { .name = "tx_yellow_prio_1", .offset = 0x8f },
  91. { .name = "tx_yellow_prio_2", .offset = 0x90 },
  92. { .name = "tx_yellow_prio_3", .offset = 0x91 },
  93. { .name = "tx_yellow_prio_4", .offset = 0x92 },
  94. { .name = "tx_yellow_prio_5", .offset = 0x93 },
  95. { .name = "tx_yellow_prio_6", .offset = 0x94 },
  96. { .name = "tx_yellow_prio_7", .offset = 0x95 },
  97. { .name = "tx_green_prio_0", .offset = 0x96 },
  98. { .name = "tx_green_prio_1", .offset = 0x97 },
  99. { .name = "tx_green_prio_2", .offset = 0x98 },
  100. { .name = "tx_green_prio_3", .offset = 0x99 },
  101. { .name = "tx_green_prio_4", .offset = 0x9a },
  102. { .name = "tx_green_prio_5", .offset = 0x9b },
  103. { .name = "tx_green_prio_6", .offset = 0x9c },
  104. { .name = "tx_green_prio_7", .offset = 0x9d },
  105. { .name = "tx_aged", .offset = 0x9e },
  106. { .name = "tx_llct", .offset = 0x9f },
  107. { .name = "tx_ct", .offset = 0xa0 },
  108. { .name = "tx_mm_hold", .offset = 0xa1 },
  109. { .name = "tx_merge_frag", .offset = 0xa2 },
  110. { .name = "tx_pmac_octets", .offset = 0xa3, },
  111. { .name = "tx_pmac_unicast", .offset = 0xa4, },
  112. { .name = "tx_pmac_multicast", .offset = 0xa5 },
  113. { .name = "tx_pmac_broadcast", .offset = 0xa6 },
  114. { .name = "tx_pmac_pause", .offset = 0xa7 },
  115. { .name = "tx_pmac_sz_64", .offset = 0xa8 },
  116. { .name = "tx_pmac_sz_65_127", .offset = 0xa9 },
  117. { .name = "tx_pmac_sz_128_255", .offset = 0xaa },
  118. { .name = "tx_pmac_sz_256_511", .offset = 0xab },
  119. { .name = "tx_pmac_sz_512_1023", .offset = 0xac },
  120. { .name = "tx_pmac_sz_1024_1526", .offset = 0xad },
  121. { .name = "tx_pmac_sz_jumbo", .offset = 0xae },
  122. { .name = "dr_local", .offset = 0x100 },
  123. { .name = "dr_tail", .offset = 0x101 },
  124. { .name = "dr_yellow_prio_0", .offset = 0x102 },
  125. { .name = "dr_yellow_prio_1", .offset = 0x103 },
  126. { .name = "dr_yellow_prio_2", .offset = 0x104 },
  127. { .name = "dr_yellow_prio_3", .offset = 0x105 },
  128. { .name = "dr_yellow_prio_4", .offset = 0x106 },
  129. { .name = "dr_yellow_prio_5", .offset = 0x107 },
  130. { .name = "dr_yellow_prio_6", .offset = 0x108 },
  131. { .name = "dr_yellow_prio_7", .offset = 0x109 },
  132. { .name = "dr_green_prio_0", .offset = 0x10a },
  133. { .name = "dr_green_prio_1", .offset = 0x10b },
  134. { .name = "dr_green_prio_2", .offset = 0x10c },
  135. { .name = "dr_green_prio_3", .offset = 0x10d },
  136. { .name = "dr_green_prio_4", .offset = 0x10e },
  137. { .name = "dr_green_prio_5", .offset = 0x10f },
  138. { .name = "dr_green_prio_6", .offset = 0x110 },
  139. { .name = "dr_green_prio_7", .offset = 0x111 },
  140. };
  141. /* The following numbers are indexes into lan966x_stats_layout[] */
  142. #define SYS_COUNT_RX_OCT 0
  143. #define SYS_COUNT_RX_UC 1
  144. #define SYS_COUNT_RX_MC 2
  145. #define SYS_COUNT_RX_BC 3
  146. #define SYS_COUNT_RX_SHORT 4
  147. #define SYS_COUNT_RX_FRAG 5
  148. #define SYS_COUNT_RX_JABBER 6
  149. #define SYS_COUNT_RX_CRC 7
  150. #define SYS_COUNT_RX_SYMBOL_ERR 8
  151. #define SYS_COUNT_RX_SZ_64 9
  152. #define SYS_COUNT_RX_SZ_65_127 10
  153. #define SYS_COUNT_RX_SZ_128_255 11
  154. #define SYS_COUNT_RX_SZ_256_511 12
  155. #define SYS_COUNT_RX_SZ_512_1023 13
  156. #define SYS_COUNT_RX_SZ_1024_1526 14
  157. #define SYS_COUNT_RX_SZ_JUMBO 15
  158. #define SYS_COUNT_RX_PAUSE 16
  159. #define SYS_COUNT_RX_CONTROL 17
  160. #define SYS_COUNT_RX_LONG 18
  161. #define SYS_COUNT_RX_CAT_DROP 19
  162. #define SYS_COUNT_RX_RED_PRIO_0 20
  163. #define SYS_COUNT_RX_RED_PRIO_1 21
  164. #define SYS_COUNT_RX_RED_PRIO_2 22
  165. #define SYS_COUNT_RX_RED_PRIO_3 23
  166. #define SYS_COUNT_RX_RED_PRIO_4 24
  167. #define SYS_COUNT_RX_RED_PRIO_5 25
  168. #define SYS_COUNT_RX_RED_PRIO_6 26
  169. #define SYS_COUNT_RX_RED_PRIO_7 27
  170. #define SYS_COUNT_RX_YELLOW_PRIO_0 28
  171. #define SYS_COUNT_RX_YELLOW_PRIO_1 29
  172. #define SYS_COUNT_RX_YELLOW_PRIO_2 30
  173. #define SYS_COUNT_RX_YELLOW_PRIO_3 31
  174. #define SYS_COUNT_RX_YELLOW_PRIO_4 32
  175. #define SYS_COUNT_RX_YELLOW_PRIO_5 33
  176. #define SYS_COUNT_RX_YELLOW_PRIO_6 34
  177. #define SYS_COUNT_RX_YELLOW_PRIO_7 35
  178. #define SYS_COUNT_RX_GREEN_PRIO_0 36
  179. #define SYS_COUNT_RX_GREEN_PRIO_1 37
  180. #define SYS_COUNT_RX_GREEN_PRIO_2 38
  181. #define SYS_COUNT_RX_GREEN_PRIO_3 39
  182. #define SYS_COUNT_RX_GREEN_PRIO_4 40
  183. #define SYS_COUNT_RX_GREEN_PRIO_5 41
  184. #define SYS_COUNT_RX_GREEN_PRIO_6 42
  185. #define SYS_COUNT_RX_GREEN_PRIO_7 43
  186. #define SYS_COUNT_RX_ASSEMBLY_ERR 44
  187. #define SYS_COUNT_RX_SMD_ERR 45
  188. #define SYS_COUNT_RX_ASSEMBLY_OK 46
  189. #define SYS_COUNT_RX_MERGE_FRAG 47
  190. #define SYS_COUNT_RX_PMAC_OCT 48
  191. #define SYS_COUNT_RX_PMAC_UC 49
  192. #define SYS_COUNT_RX_PMAC_MC 50
  193. #define SYS_COUNT_RX_PMAC_BC 51
  194. #define SYS_COUNT_RX_PMAC_SHORT 52
  195. #define SYS_COUNT_RX_PMAC_FRAG 53
  196. #define SYS_COUNT_RX_PMAC_JABBER 54
  197. #define SYS_COUNT_RX_PMAC_CRC 55
  198. #define SYS_COUNT_RX_PMAC_SYMBOL_ERR 56
  199. #define SYS_COUNT_RX_PMAC_SZ_64 57
  200. #define SYS_COUNT_RX_PMAC_SZ_65_127 58
  201. #define SYS_COUNT_RX_PMAC_SZ_128_255 59
  202. #define SYS_COUNT_RX_PMAC_SZ_256_511 60
  203. #define SYS_COUNT_RX_PMAC_SZ_512_1023 61
  204. #define SYS_COUNT_RX_PMAC_SZ_1024_1526 62
  205. #define SYS_COUNT_RX_PMAC_SZ_JUMBO 63
  206. #define SYS_COUNT_RX_PMAC_PAUSE 64
  207. #define SYS_COUNT_RX_PMAC_CONTROL 65
  208. #define SYS_COUNT_RX_PMAC_LONG 66
  209. #define SYS_COUNT_TX_OCT 67
  210. #define SYS_COUNT_TX_UC 68
  211. #define SYS_COUNT_TX_MC 69
  212. #define SYS_COUNT_TX_BC 70
  213. #define SYS_COUNT_TX_COL 71
  214. #define SYS_COUNT_TX_DROP 72
  215. #define SYS_COUNT_TX_PAUSE 73
  216. #define SYS_COUNT_TX_SZ_64 74
  217. #define SYS_COUNT_TX_SZ_65_127 75
  218. #define SYS_COUNT_TX_SZ_128_255 76
  219. #define SYS_COUNT_TX_SZ_256_511 77
  220. #define SYS_COUNT_TX_SZ_512_1023 78
  221. #define SYS_COUNT_TX_SZ_1024_1526 79
  222. #define SYS_COUNT_TX_SZ_JUMBO 80
  223. #define SYS_COUNT_TX_YELLOW_PRIO_0 81
  224. #define SYS_COUNT_TX_YELLOW_PRIO_1 82
  225. #define SYS_COUNT_TX_YELLOW_PRIO_2 83
  226. #define SYS_COUNT_TX_YELLOW_PRIO_3 84
  227. #define SYS_COUNT_TX_YELLOW_PRIO_4 85
  228. #define SYS_COUNT_TX_YELLOW_PRIO_5 86
  229. #define SYS_COUNT_TX_YELLOW_PRIO_6 87
  230. #define SYS_COUNT_TX_YELLOW_PRIO_7 88
  231. #define SYS_COUNT_TX_GREEN_PRIO_0 89
  232. #define SYS_COUNT_TX_GREEN_PRIO_1 90
  233. #define SYS_COUNT_TX_GREEN_PRIO_2 91
  234. #define SYS_COUNT_TX_GREEN_PRIO_3 92
  235. #define SYS_COUNT_TX_GREEN_PRIO_4 93
  236. #define SYS_COUNT_TX_GREEN_PRIO_5 94
  237. #define SYS_COUNT_TX_GREEN_PRIO_6 95
  238. #define SYS_COUNT_TX_GREEN_PRIO_7 96
  239. #define SYS_COUNT_TX_AGED 97
  240. #define SYS_COUNT_TX_LLCT 98
  241. #define SYS_COUNT_TX_CT 99
  242. #define SYS_COUNT_TX_MM_HOLD 100
  243. #define SYS_COUNT_TX_MERGE_FRAG 101
  244. #define SYS_COUNT_TX_PMAC_OCT 102
  245. #define SYS_COUNT_TX_PMAC_UC 103
  246. #define SYS_COUNT_TX_PMAC_MC 104
  247. #define SYS_COUNT_TX_PMAC_BC 105
  248. #define SYS_COUNT_TX_PMAC_PAUSE 106
  249. #define SYS_COUNT_TX_PMAC_SZ_64 107
  250. #define SYS_COUNT_TX_PMAC_SZ_65_127 108
  251. #define SYS_COUNT_TX_PMAC_SZ_128_255 109
  252. #define SYS_COUNT_TX_PMAC_SZ_256_511 110
  253. #define SYS_COUNT_TX_PMAC_SZ_512_1023 111
  254. #define SYS_COUNT_TX_PMAC_SZ_1024_1526 112
  255. #define SYS_COUNT_TX_PMAC_SZ_JUMBO 113
  256. #define SYS_COUNT_DR_LOCAL 114
  257. #define SYS_COUNT_DR_TAIL 115
  258. #define SYS_COUNT_DR_YELLOW_PRIO_0 116
  259. #define SYS_COUNT_DR_YELLOW_PRIO_1 117
  260. #define SYS_COUNT_DR_YELLOW_PRIO_2 118
  261. #define SYS_COUNT_DR_YELLOW_PRIO_3 119
  262. #define SYS_COUNT_DR_YELLOW_PRIO_4 120
  263. #define SYS_COUNT_DR_YELLOW_PRIO_5 121
  264. #define SYS_COUNT_DR_YELLOW_PRIO_6 122
  265. #define SYS_COUNT_DR_YELLOW_PRIO_7 123
  266. #define SYS_COUNT_DR_GREEN_PRIO_0 124
  267. #define SYS_COUNT_DR_GREEN_PRIO_1 125
  268. #define SYS_COUNT_DR_GREEN_PRIO_2 126
  269. #define SYS_COUNT_DR_GREEN_PRIO_3 127
  270. #define SYS_COUNT_DR_GREEN_PRIO_4 128
  271. #define SYS_COUNT_DR_GREEN_PRIO_5 129
  272. #define SYS_COUNT_DR_GREEN_PRIO_6 130
  273. #define SYS_COUNT_DR_GREEN_PRIO_7 131
  274. /* Add a possibly wrapping 32 bit value to a 64 bit counter */
  275. static void lan966x_add_cnt(u64 *cnt, u32 val)
  276. {
  277. if (val < (*cnt & U32_MAX))
  278. *cnt += (u64)1 << 32; /* value has wrapped */
  279. *cnt = (*cnt & ~(u64)U32_MAX) + val;
  280. }
  281. static void lan966x_stats_update(struct lan966x *lan966x)
  282. {
  283. int i, j;
  284. mutex_lock(&lan966x->stats_lock);
  285. for (i = 0; i < lan966x->num_phys_ports; i++) {
  286. uint idx = i * lan966x->num_stats;
  287. lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(i),
  288. lan966x, SYS_STAT_CFG);
  289. for (j = 0; j < lan966x->num_stats; j++) {
  290. u32 offset = lan966x->stats_layout[j].offset;
  291. lan966x_add_cnt(&lan966x->stats[idx++],
  292. lan_rd(lan966x, SYS_CNT(offset)));
  293. }
  294. }
  295. mutex_unlock(&lan966x->stats_lock);
  296. }
  297. static int lan966x_get_sset_count(struct net_device *dev, int sset)
  298. {
  299. struct lan966x_port *port = netdev_priv(dev);
  300. struct lan966x *lan966x = port->lan966x;
  301. if (sset != ETH_SS_STATS)
  302. return -EOPNOTSUPP;
  303. return lan966x->num_stats;
  304. }
  305. static void lan966x_get_strings(struct net_device *netdev, u32 sset, u8 *data)
  306. {
  307. struct lan966x_port *port = netdev_priv(netdev);
  308. struct lan966x *lan966x = port->lan966x;
  309. int i;
  310. if (sset != ETH_SS_STATS)
  311. return;
  312. for (i = 0; i < lan966x->num_stats; i++)
  313. memcpy(data + i * ETH_GSTRING_LEN,
  314. lan966x->stats_layout[i].name, ETH_GSTRING_LEN);
  315. }
  316. static void lan966x_get_ethtool_stats(struct net_device *dev,
  317. struct ethtool_stats *stats, u64 *data)
  318. {
  319. struct lan966x_port *port = netdev_priv(dev);
  320. struct lan966x *lan966x = port->lan966x;
  321. int i;
  322. /* check and update now */
  323. lan966x_stats_update(lan966x);
  324. /* Copy all counters */
  325. for (i = 0; i < lan966x->num_stats; i++)
  326. *data++ = lan966x->stats[port->chip_port *
  327. lan966x->num_stats + i];
  328. }
  329. static void lan966x_get_eth_mac_stats(struct net_device *dev,
  330. struct ethtool_eth_mac_stats *mac_stats)
  331. {
  332. struct lan966x_port *port = netdev_priv(dev);
  333. struct lan966x *lan966x = port->lan966x;
  334. u32 idx;
  335. lan966x_stats_update(lan966x);
  336. idx = port->chip_port * lan966x->num_stats;
  337. mutex_lock(&lan966x->stats_lock);
  338. mac_stats->FramesTransmittedOK =
  339. lan966x->stats[idx + SYS_COUNT_TX_UC] +
  340. lan966x->stats[idx + SYS_COUNT_TX_MC] +
  341. lan966x->stats[idx + SYS_COUNT_TX_BC] +
  342. lan966x->stats[idx + SYS_COUNT_TX_PMAC_UC] +
  343. lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC] +
  344. lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];
  345. mac_stats->SingleCollisionFrames =
  346. lan966x->stats[idx + SYS_COUNT_TX_COL];
  347. mac_stats->FramesReceivedOK =
  348. lan966x->stats[idx + SYS_COUNT_RX_UC] +
  349. lan966x->stats[idx + SYS_COUNT_RX_MC] +
  350. lan966x->stats[idx + SYS_COUNT_RX_BC];
  351. mac_stats->FrameCheckSequenceErrors =
  352. lan966x->stats[idx + SYS_COUNT_RX_CRC] +
  353. lan966x->stats[idx + SYS_COUNT_RX_CRC];
  354. mac_stats->OctetsTransmittedOK =
  355. lan966x->stats[idx + SYS_COUNT_TX_OCT] +
  356. lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
  357. mac_stats->FramesWithDeferredXmissions =
  358. lan966x->stats[idx + SYS_COUNT_TX_MM_HOLD];
  359. mac_stats->OctetsReceivedOK =
  360. lan966x->stats[idx + SYS_COUNT_RX_OCT];
  361. mac_stats->MulticastFramesXmittedOK =
  362. lan966x->stats[idx + SYS_COUNT_TX_MC] +
  363. lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC];
  364. mac_stats->BroadcastFramesXmittedOK =
  365. lan966x->stats[idx + SYS_COUNT_TX_BC] +
  366. lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];
  367. mac_stats->MulticastFramesReceivedOK =
  368. lan966x->stats[idx + SYS_COUNT_RX_MC];
  369. mac_stats->BroadcastFramesReceivedOK =
  370. lan966x->stats[idx + SYS_COUNT_RX_BC];
  371. mac_stats->InRangeLengthErrors =
  372. lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
  373. lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
  374. lan966x->stats[idx + SYS_COUNT_RX_CRC] +
  375. lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
  376. lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
  377. lan966x->stats[idx + SYS_COUNT_RX_PMAC_CRC];
  378. mac_stats->OutOfRangeLengthField =
  379. lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
  380. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
  381. lan966x->stats[idx + SYS_COUNT_RX_LONG] +
  382. lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
  383. mac_stats->FrameTooLongErrors =
  384. lan966x->stats[idx + SYS_COUNT_RX_LONG] +
  385. lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
  386. mutex_unlock(&lan966x->stats_lock);
  387. }
  388. static const struct ethtool_rmon_hist_range lan966x_rmon_ranges[] = {
  389. { 0, 64 },
  390. { 65, 127 },
  391. { 128, 255 },
  392. { 256, 511 },
  393. { 512, 1023 },
  394. { 1024, 1518 },
  395. { 1519, 10239 },
  396. {}
  397. };
  398. static void lan966x_get_eth_rmon_stats(struct net_device *dev,
  399. struct ethtool_rmon_stats *rmon_stats,
  400. const struct ethtool_rmon_hist_range **ranges)
  401. {
  402. struct lan966x_port *port = netdev_priv(dev);
  403. struct lan966x *lan966x = port->lan966x;
  404. u32 idx;
  405. lan966x_stats_update(lan966x);
  406. idx = port->chip_port * lan966x->num_stats;
  407. mutex_lock(&lan966x->stats_lock);
  408. rmon_stats->undersize_pkts =
  409. lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
  410. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT];
  411. rmon_stats->oversize_pkts =
  412. lan966x->stats[idx + SYS_COUNT_RX_LONG] +
  413. lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
  414. rmon_stats->fragments =
  415. lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
  416. lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG];
  417. rmon_stats->jabbers =
  418. lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
  419. lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER];
  420. rmon_stats->hist[0] =
  421. lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
  422. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64];
  423. rmon_stats->hist[1] =
  424. lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
  425. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127];
  426. rmon_stats->hist[2] =
  427. lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
  428. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255];
  429. rmon_stats->hist[3] =
  430. lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
  431. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511];
  432. rmon_stats->hist[4] =
  433. lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
  434. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023];
  435. rmon_stats->hist[5] =
  436. lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
  437. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
  438. rmon_stats->hist[6] =
  439. lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
  440. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
  441. rmon_stats->hist_tx[0] =
  442. lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
  443. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64];
  444. rmon_stats->hist_tx[1] =
  445. lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
  446. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127];
  447. rmon_stats->hist_tx[2] =
  448. lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
  449. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255];
  450. rmon_stats->hist_tx[3] =
  451. lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
  452. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511];
  453. rmon_stats->hist_tx[4] =
  454. lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
  455. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023];
  456. rmon_stats->hist_tx[5] =
  457. lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
  458. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
  459. rmon_stats->hist_tx[6] =
  460. lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
  461. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
  462. mutex_unlock(&lan966x->stats_lock);
  463. *ranges = lan966x_rmon_ranges;
  464. }
  465. static int lan966x_get_link_ksettings(struct net_device *ndev,
  466. struct ethtool_link_ksettings *cmd)
  467. {
  468. struct lan966x_port *port = netdev_priv(ndev);
  469. return phylink_ethtool_ksettings_get(port->phylink, cmd);
  470. }
  471. static int lan966x_set_link_ksettings(struct net_device *ndev,
  472. const struct ethtool_link_ksettings *cmd)
  473. {
  474. struct lan966x_port *port = netdev_priv(ndev);
  475. return phylink_ethtool_ksettings_set(port->phylink, cmd);
  476. }
  477. static void lan966x_get_pauseparam(struct net_device *dev,
  478. struct ethtool_pauseparam *pause)
  479. {
  480. struct lan966x_port *port = netdev_priv(dev);
  481. phylink_ethtool_get_pauseparam(port->phylink, pause);
  482. }
  483. static int lan966x_set_pauseparam(struct net_device *dev,
  484. struct ethtool_pauseparam *pause)
  485. {
  486. struct lan966x_port *port = netdev_priv(dev);
  487. return phylink_ethtool_set_pauseparam(port->phylink, pause);
  488. }
  489. static int lan966x_get_ts_info(struct net_device *dev,
  490. struct kernel_ethtool_ts_info *info)
  491. {
  492. struct lan966x_port *port = netdev_priv(dev);
  493. struct lan966x *lan966x = port->lan966x;
  494. struct lan966x_phc *phc;
  495. if (!lan966x->ptp)
  496. return ethtool_op_get_ts_info(dev, info);
  497. phc = &lan966x->phc[LAN966X_PHC_PORT];
  498. if (phc->clock) {
  499. info->phc_index = ptp_clock_index(phc->clock);
  500. } else {
  501. info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE;
  502. return 0;
  503. }
  504. info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
  505. SOF_TIMESTAMPING_TX_HARDWARE |
  506. SOF_TIMESTAMPING_RX_HARDWARE |
  507. SOF_TIMESTAMPING_RAW_HARDWARE;
  508. info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
  509. BIT(HWTSTAMP_TX_ONESTEP_SYNC);
  510. info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
  511. BIT(HWTSTAMP_FILTER_ALL);
  512. return 0;
  513. }
  514. const struct ethtool_ops lan966x_ethtool_ops = {
  515. .get_link_ksettings = lan966x_get_link_ksettings,
  516. .set_link_ksettings = lan966x_set_link_ksettings,
  517. .get_pauseparam = lan966x_get_pauseparam,
  518. .set_pauseparam = lan966x_set_pauseparam,
  519. .get_sset_count = lan966x_get_sset_count,
  520. .get_strings = lan966x_get_strings,
  521. .get_ethtool_stats = lan966x_get_ethtool_stats,
  522. .get_eth_mac_stats = lan966x_get_eth_mac_stats,
  523. .get_rmon_stats = lan966x_get_eth_rmon_stats,
  524. .get_link = ethtool_op_get_link,
  525. .get_ts_info = lan966x_get_ts_info,
  526. };
  527. static void lan966x_check_stats_work(struct work_struct *work)
  528. {
  529. struct delayed_work *del_work = to_delayed_work(work);
  530. struct lan966x *lan966x = container_of(del_work, struct lan966x,
  531. stats_work);
  532. lan966x_stats_update(lan966x);
  533. queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,
  534. LAN966X_STATS_CHECK_DELAY);
  535. }
  536. void lan966x_stats_get(struct net_device *dev,
  537. struct rtnl_link_stats64 *stats)
  538. {
  539. struct lan966x_port *port = netdev_priv(dev);
  540. struct lan966x *lan966x = port->lan966x;
  541. u32 idx;
  542. int i;
  543. idx = port->chip_port * lan966x->num_stats;
  544. mutex_lock(&lan966x->stats_lock);
  545. stats->rx_bytes = lan966x->stats[idx + SYS_COUNT_RX_OCT] +
  546. lan966x->stats[idx + SYS_COUNT_RX_PMAC_OCT];
  547. stats->rx_packets = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
  548. lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
  549. lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
  550. lan966x->stats[idx + SYS_COUNT_RX_CRC] +
  551. lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
  552. lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
  553. lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
  554. lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
  555. lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
  556. lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
  557. lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
  558. lan966x->stats[idx + SYS_COUNT_RX_SZ_JUMBO] +
  559. lan966x->stats[idx + SYS_COUNT_RX_LONG] +
  560. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
  561. lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
  562. lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
  563. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64] +
  564. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127] +
  565. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255] +
  566. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511] +
  567. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023] +
  568. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526] +
  569. lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_JUMBO];
  570. stats->multicast = lan966x->stats[idx + SYS_COUNT_RX_MC] +
  571. lan966x->stats[idx + SYS_COUNT_RX_PMAC_MC];
  572. stats->rx_errors = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
  573. lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
  574. lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
  575. lan966x->stats[idx + SYS_COUNT_RX_CRC] +
  576. lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
  577. lan966x->stats[idx + SYS_COUNT_RX_LONG];
  578. stats->rx_dropped = dev->stats.rx_dropped +
  579. lan966x->stats[idx + SYS_COUNT_RX_LONG] +
  580. lan966x->stats[idx + SYS_COUNT_DR_LOCAL] +
  581. lan966x->stats[idx + SYS_COUNT_DR_TAIL] +
  582. lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_0] +
  583. lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_1] +
  584. lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_2] +
  585. lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_3] +
  586. lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_4] +
  587. lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_5] +
  588. lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_6] +
  589. lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_7];
  590. for (i = 0; i < LAN966X_NUM_TC; i++) {
  591. stats->rx_dropped +=
  592. (lan966x->stats[idx + SYS_COUNT_DR_YELLOW_PRIO_0 + i] +
  593. lan966x->stats[idx + SYS_COUNT_DR_GREEN_PRIO_0 + i]);
  594. }
  595. /* Get Tx stats */
  596. stats->tx_bytes = lan966x->stats[idx + SYS_COUNT_TX_OCT] +
  597. lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
  598. stats->tx_packets = lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
  599. lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
  600. lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
  601. lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
  602. lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
  603. lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
  604. lan966x->stats[idx + SYS_COUNT_TX_SZ_JUMBO] +
  605. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64] +
  606. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127] +
  607. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255] +
  608. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511] +
  609. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023] +
  610. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526] +
  611. lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_JUMBO];
  612. stats->tx_dropped = lan966x->stats[idx + SYS_COUNT_TX_DROP] +
  613. lan966x->stats[idx + SYS_COUNT_TX_AGED];
  614. stats->collisions = lan966x->stats[idx + SYS_COUNT_TX_COL];
  615. mutex_unlock(&lan966x->stats_lock);
  616. }
  617. int lan966x_stats_init(struct lan966x *lan966x)
  618. {
  619. char queue_name[32];
  620. lan966x->stats_layout = lan966x_stats_layout;
  621. lan966x->num_stats = ARRAY_SIZE(lan966x_stats_layout);
  622. lan966x->stats = devm_kcalloc(lan966x->dev, lan966x->num_phys_ports *
  623. lan966x->num_stats,
  624. sizeof(u64), GFP_KERNEL);
  625. if (!lan966x->stats)
  626. return -ENOMEM;
  627. /* Init stats worker */
  628. mutex_init(&lan966x->stats_lock);
  629. snprintf(queue_name, sizeof(queue_name), "%s-stats",
  630. dev_name(lan966x->dev));
  631. lan966x->stats_queue = create_singlethread_workqueue(queue_name);
  632. if (!lan966x->stats_queue)
  633. return -ENOMEM;
  634. INIT_DELAYED_WORK(&lan966x->stats_work, lan966x_check_stats_work);
  635. queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,
  636. LAN966X_STATS_CHECK_DELAY);
  637. return 0;
  638. }