ocelot_stats.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. // SPDX-License-Identifier: (GPL-2.0 OR MIT)
  2. /* Statistics for Ocelot switch family
  3. *
  4. * Copyright (c) 2017 Microsemi Corporation
  5. * Copyright 2022 NXP
  6. */
  7. #include <linux/ethtool_netlink.h>
  8. #include <linux/spinlock.h>
  9. #include <linux/mutex.h>
  10. #include <linux/workqueue.h>
  11. #include "ocelot.h"
  12. enum ocelot_stat {
  13. OCELOT_STAT_RX_OCTETS,
  14. OCELOT_STAT_RX_UNICAST,
  15. OCELOT_STAT_RX_MULTICAST,
  16. OCELOT_STAT_RX_BROADCAST,
  17. OCELOT_STAT_RX_SHORTS,
  18. OCELOT_STAT_RX_FRAGMENTS,
  19. OCELOT_STAT_RX_JABBERS,
  20. OCELOT_STAT_RX_CRC_ALIGN_ERRS,
  21. OCELOT_STAT_RX_SYM_ERRS,
  22. OCELOT_STAT_RX_64,
  23. OCELOT_STAT_RX_65_127,
  24. OCELOT_STAT_RX_128_255,
  25. OCELOT_STAT_RX_256_511,
  26. OCELOT_STAT_RX_512_1023,
  27. OCELOT_STAT_RX_1024_1526,
  28. OCELOT_STAT_RX_1527_MAX,
  29. OCELOT_STAT_RX_PAUSE,
  30. OCELOT_STAT_RX_CONTROL,
  31. OCELOT_STAT_RX_LONGS,
  32. OCELOT_STAT_RX_CLASSIFIED_DROPS,
  33. OCELOT_STAT_RX_RED_PRIO_0,
  34. OCELOT_STAT_RX_RED_PRIO_1,
  35. OCELOT_STAT_RX_RED_PRIO_2,
  36. OCELOT_STAT_RX_RED_PRIO_3,
  37. OCELOT_STAT_RX_RED_PRIO_4,
  38. OCELOT_STAT_RX_RED_PRIO_5,
  39. OCELOT_STAT_RX_RED_PRIO_6,
  40. OCELOT_STAT_RX_RED_PRIO_7,
  41. OCELOT_STAT_RX_YELLOW_PRIO_0,
  42. OCELOT_STAT_RX_YELLOW_PRIO_1,
  43. OCELOT_STAT_RX_YELLOW_PRIO_2,
  44. OCELOT_STAT_RX_YELLOW_PRIO_3,
  45. OCELOT_STAT_RX_YELLOW_PRIO_4,
  46. OCELOT_STAT_RX_YELLOW_PRIO_5,
  47. OCELOT_STAT_RX_YELLOW_PRIO_6,
  48. OCELOT_STAT_RX_YELLOW_PRIO_7,
  49. OCELOT_STAT_RX_GREEN_PRIO_0,
  50. OCELOT_STAT_RX_GREEN_PRIO_1,
  51. OCELOT_STAT_RX_GREEN_PRIO_2,
  52. OCELOT_STAT_RX_GREEN_PRIO_3,
  53. OCELOT_STAT_RX_GREEN_PRIO_4,
  54. OCELOT_STAT_RX_GREEN_PRIO_5,
  55. OCELOT_STAT_RX_GREEN_PRIO_6,
  56. OCELOT_STAT_RX_GREEN_PRIO_7,
  57. OCELOT_STAT_RX_ASSEMBLY_ERRS,
  58. OCELOT_STAT_RX_SMD_ERRS,
  59. OCELOT_STAT_RX_ASSEMBLY_OK,
  60. OCELOT_STAT_RX_MERGE_FRAGMENTS,
  61. OCELOT_STAT_RX_PMAC_OCTETS,
  62. OCELOT_STAT_RX_PMAC_UNICAST,
  63. OCELOT_STAT_RX_PMAC_MULTICAST,
  64. OCELOT_STAT_RX_PMAC_BROADCAST,
  65. OCELOT_STAT_RX_PMAC_SHORTS,
  66. OCELOT_STAT_RX_PMAC_FRAGMENTS,
  67. OCELOT_STAT_RX_PMAC_JABBERS,
  68. OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS,
  69. OCELOT_STAT_RX_PMAC_SYM_ERRS,
  70. OCELOT_STAT_RX_PMAC_64,
  71. OCELOT_STAT_RX_PMAC_65_127,
  72. OCELOT_STAT_RX_PMAC_128_255,
  73. OCELOT_STAT_RX_PMAC_256_511,
  74. OCELOT_STAT_RX_PMAC_512_1023,
  75. OCELOT_STAT_RX_PMAC_1024_1526,
  76. OCELOT_STAT_RX_PMAC_1527_MAX,
  77. OCELOT_STAT_RX_PMAC_PAUSE,
  78. OCELOT_STAT_RX_PMAC_CONTROL,
  79. OCELOT_STAT_RX_PMAC_LONGS,
  80. OCELOT_STAT_TX_OCTETS,
  81. OCELOT_STAT_TX_UNICAST,
  82. OCELOT_STAT_TX_MULTICAST,
  83. OCELOT_STAT_TX_BROADCAST,
  84. OCELOT_STAT_TX_COLLISION,
  85. OCELOT_STAT_TX_DROPS,
  86. OCELOT_STAT_TX_PAUSE,
  87. OCELOT_STAT_TX_64,
  88. OCELOT_STAT_TX_65_127,
  89. OCELOT_STAT_TX_128_255,
  90. OCELOT_STAT_TX_256_511,
  91. OCELOT_STAT_TX_512_1023,
  92. OCELOT_STAT_TX_1024_1526,
  93. OCELOT_STAT_TX_1527_MAX,
  94. OCELOT_STAT_TX_YELLOW_PRIO_0,
  95. OCELOT_STAT_TX_YELLOW_PRIO_1,
  96. OCELOT_STAT_TX_YELLOW_PRIO_2,
  97. OCELOT_STAT_TX_YELLOW_PRIO_3,
  98. OCELOT_STAT_TX_YELLOW_PRIO_4,
  99. OCELOT_STAT_TX_YELLOW_PRIO_5,
  100. OCELOT_STAT_TX_YELLOW_PRIO_6,
  101. OCELOT_STAT_TX_YELLOW_PRIO_7,
  102. OCELOT_STAT_TX_GREEN_PRIO_0,
  103. OCELOT_STAT_TX_GREEN_PRIO_1,
  104. OCELOT_STAT_TX_GREEN_PRIO_2,
  105. OCELOT_STAT_TX_GREEN_PRIO_3,
  106. OCELOT_STAT_TX_GREEN_PRIO_4,
  107. OCELOT_STAT_TX_GREEN_PRIO_5,
  108. OCELOT_STAT_TX_GREEN_PRIO_6,
  109. OCELOT_STAT_TX_GREEN_PRIO_7,
  110. OCELOT_STAT_TX_AGED,
  111. OCELOT_STAT_TX_MM_HOLD,
  112. OCELOT_STAT_TX_MERGE_FRAGMENTS,
  113. OCELOT_STAT_TX_PMAC_OCTETS,
  114. OCELOT_STAT_TX_PMAC_UNICAST,
  115. OCELOT_STAT_TX_PMAC_MULTICAST,
  116. OCELOT_STAT_TX_PMAC_BROADCAST,
  117. OCELOT_STAT_TX_PMAC_PAUSE,
  118. OCELOT_STAT_TX_PMAC_64,
  119. OCELOT_STAT_TX_PMAC_65_127,
  120. OCELOT_STAT_TX_PMAC_128_255,
  121. OCELOT_STAT_TX_PMAC_256_511,
  122. OCELOT_STAT_TX_PMAC_512_1023,
  123. OCELOT_STAT_TX_PMAC_1024_1526,
  124. OCELOT_STAT_TX_PMAC_1527_MAX,
  125. OCELOT_STAT_DROP_LOCAL,
  126. OCELOT_STAT_DROP_TAIL,
  127. OCELOT_STAT_DROP_YELLOW_PRIO_0,
  128. OCELOT_STAT_DROP_YELLOW_PRIO_1,
  129. OCELOT_STAT_DROP_YELLOW_PRIO_2,
  130. OCELOT_STAT_DROP_YELLOW_PRIO_3,
  131. OCELOT_STAT_DROP_YELLOW_PRIO_4,
  132. OCELOT_STAT_DROP_YELLOW_PRIO_5,
  133. OCELOT_STAT_DROP_YELLOW_PRIO_6,
  134. OCELOT_STAT_DROP_YELLOW_PRIO_7,
  135. OCELOT_STAT_DROP_GREEN_PRIO_0,
  136. OCELOT_STAT_DROP_GREEN_PRIO_1,
  137. OCELOT_STAT_DROP_GREEN_PRIO_2,
  138. OCELOT_STAT_DROP_GREEN_PRIO_3,
  139. OCELOT_STAT_DROP_GREEN_PRIO_4,
  140. OCELOT_STAT_DROP_GREEN_PRIO_5,
  141. OCELOT_STAT_DROP_GREEN_PRIO_6,
  142. OCELOT_STAT_DROP_GREEN_PRIO_7,
  143. OCELOT_NUM_STATS,
  144. };
  145. struct ocelot_stat_layout {
  146. enum ocelot_reg reg;
  147. char name[ETH_GSTRING_LEN];
  148. };
  149. /* 32-bit counter checked for wraparound by ocelot_port_update_stats()
  150. * and copied to ocelot->stats.
  151. */
  152. #define OCELOT_STAT(kind) \
  153. [OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind }
  154. /* Same as above, except also exported to ethtool -S. Standard counters should
  155. * only be exposed to more specific interfaces rather than by their string name.
  156. */
  157. #define OCELOT_STAT_ETHTOOL(kind, ethtool_name) \
  158. [OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind, .name = ethtool_name }
  159. #define OCELOT_COMMON_STATS \
  160. OCELOT_STAT_ETHTOOL(RX_OCTETS, "rx_octets"), \
  161. OCELOT_STAT_ETHTOOL(RX_UNICAST, "rx_unicast"), \
  162. OCELOT_STAT_ETHTOOL(RX_MULTICAST, "rx_multicast"), \
  163. OCELOT_STAT_ETHTOOL(RX_BROADCAST, "rx_broadcast"), \
  164. OCELOT_STAT_ETHTOOL(RX_SHORTS, "rx_shorts"), \
  165. OCELOT_STAT_ETHTOOL(RX_FRAGMENTS, "rx_fragments"), \
  166. OCELOT_STAT_ETHTOOL(RX_JABBERS, "rx_jabbers"), \
  167. OCELOT_STAT_ETHTOOL(RX_CRC_ALIGN_ERRS, "rx_crc_align_errs"), \
  168. OCELOT_STAT_ETHTOOL(RX_SYM_ERRS, "rx_sym_errs"), \
  169. OCELOT_STAT_ETHTOOL(RX_64, "rx_frames_below_65_octets"), \
  170. OCELOT_STAT_ETHTOOL(RX_65_127, "rx_frames_65_to_127_octets"), \
  171. OCELOT_STAT_ETHTOOL(RX_128_255, "rx_frames_128_to_255_octets"), \
  172. OCELOT_STAT_ETHTOOL(RX_256_511, "rx_frames_256_to_511_octets"), \
  173. OCELOT_STAT_ETHTOOL(RX_512_1023, "rx_frames_512_to_1023_octets"), \
  174. OCELOT_STAT_ETHTOOL(RX_1024_1526, "rx_frames_1024_to_1526_octets"), \
  175. OCELOT_STAT_ETHTOOL(RX_1527_MAX, "rx_frames_over_1526_octets"), \
  176. OCELOT_STAT_ETHTOOL(RX_PAUSE, "rx_pause"), \
  177. OCELOT_STAT_ETHTOOL(RX_CONTROL, "rx_control"), \
  178. OCELOT_STAT_ETHTOOL(RX_LONGS, "rx_longs"), \
  179. OCELOT_STAT_ETHTOOL(RX_CLASSIFIED_DROPS, "rx_classified_drops"), \
  180. OCELOT_STAT_ETHTOOL(RX_RED_PRIO_0, "rx_red_prio_0"), \
  181. OCELOT_STAT_ETHTOOL(RX_RED_PRIO_1, "rx_red_prio_1"), \
  182. OCELOT_STAT_ETHTOOL(RX_RED_PRIO_2, "rx_red_prio_2"), \
  183. OCELOT_STAT_ETHTOOL(RX_RED_PRIO_3, "rx_red_prio_3"), \
  184. OCELOT_STAT_ETHTOOL(RX_RED_PRIO_4, "rx_red_prio_4"), \
  185. OCELOT_STAT_ETHTOOL(RX_RED_PRIO_5, "rx_red_prio_5"), \
  186. OCELOT_STAT_ETHTOOL(RX_RED_PRIO_6, "rx_red_prio_6"), \
  187. OCELOT_STAT_ETHTOOL(RX_RED_PRIO_7, "rx_red_prio_7"), \
  188. OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_0, "rx_yellow_prio_0"), \
  189. OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_1, "rx_yellow_prio_1"), \
  190. OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_2, "rx_yellow_prio_2"), \
  191. OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_3, "rx_yellow_prio_3"), \
  192. OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_4, "rx_yellow_prio_4"), \
  193. OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_5, "rx_yellow_prio_5"), \
  194. OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_6, "rx_yellow_prio_6"), \
  195. OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_7, "rx_yellow_prio_7"), \
  196. OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_0, "rx_green_prio_0"), \
  197. OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_1, "rx_green_prio_1"), \
  198. OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_2, "rx_green_prio_2"), \
  199. OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_3, "rx_green_prio_3"), \
  200. OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_4, "rx_green_prio_4"), \
  201. OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_5, "rx_green_prio_5"), \
  202. OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_6, "rx_green_prio_6"), \
  203. OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_7, "rx_green_prio_7"), \
  204. OCELOT_STAT_ETHTOOL(TX_OCTETS, "tx_octets"), \
  205. OCELOT_STAT_ETHTOOL(TX_UNICAST, "tx_unicast"), \
  206. OCELOT_STAT_ETHTOOL(TX_MULTICAST, "tx_multicast"), \
  207. OCELOT_STAT_ETHTOOL(TX_BROADCAST, "tx_broadcast"), \
  208. OCELOT_STAT_ETHTOOL(TX_COLLISION, "tx_collision"), \
  209. OCELOT_STAT_ETHTOOL(TX_DROPS, "tx_drops"), \
  210. OCELOT_STAT_ETHTOOL(TX_PAUSE, "tx_pause"), \
  211. OCELOT_STAT_ETHTOOL(TX_64, "tx_frames_below_65_octets"), \
  212. OCELOT_STAT_ETHTOOL(TX_65_127, "tx_frames_65_to_127_octets"), \
  213. OCELOT_STAT_ETHTOOL(TX_128_255, "tx_frames_128_255_octets"), \
  214. OCELOT_STAT_ETHTOOL(TX_256_511, "tx_frames_256_511_octets"), \
  215. OCELOT_STAT_ETHTOOL(TX_512_1023, "tx_frames_512_1023_octets"), \
  216. OCELOT_STAT_ETHTOOL(TX_1024_1526, "tx_frames_1024_1526_octets"), \
  217. OCELOT_STAT_ETHTOOL(TX_1527_MAX, "tx_frames_over_1526_octets"), \
  218. OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_0, "tx_yellow_prio_0"), \
  219. OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_1, "tx_yellow_prio_1"), \
  220. OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_2, "tx_yellow_prio_2"), \
  221. OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_3, "tx_yellow_prio_3"), \
  222. OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_4, "tx_yellow_prio_4"), \
  223. OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_5, "tx_yellow_prio_5"), \
  224. OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_6, "tx_yellow_prio_6"), \
  225. OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_7, "tx_yellow_prio_7"), \
  226. OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_0, "tx_green_prio_0"), \
  227. OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_1, "tx_green_prio_1"), \
  228. OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_2, "tx_green_prio_2"), \
  229. OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_3, "tx_green_prio_3"), \
  230. OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_4, "tx_green_prio_4"), \
  231. OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_5, "tx_green_prio_5"), \
  232. OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_6, "tx_green_prio_6"), \
  233. OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_7, "tx_green_prio_7"), \
  234. OCELOT_STAT_ETHTOOL(TX_AGED, "tx_aged"), \
  235. OCELOT_STAT_ETHTOOL(DROP_LOCAL, "drop_local"), \
  236. OCELOT_STAT_ETHTOOL(DROP_TAIL, "drop_tail"), \
  237. OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_0, "drop_yellow_prio_0"), \
  238. OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_1, "drop_yellow_prio_1"), \
  239. OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_2, "drop_yellow_prio_2"), \
  240. OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_3, "drop_yellow_prio_3"), \
  241. OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_4, "drop_yellow_prio_4"), \
  242. OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_5, "drop_yellow_prio_5"), \
  243. OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_6, "drop_yellow_prio_6"), \
  244. OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_7, "drop_yellow_prio_7"), \
  245. OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_0, "drop_green_prio_0"), \
  246. OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_1, "drop_green_prio_1"), \
  247. OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_2, "drop_green_prio_2"), \
  248. OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_3, "drop_green_prio_3"), \
  249. OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_4, "drop_green_prio_4"), \
  250. OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_5, "drop_green_prio_5"), \
  251. OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_6, "drop_green_prio_6"), \
  252. OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_7, "drop_green_prio_7")
  253. struct ocelot_stats_region {
  254. struct list_head node;
  255. enum ocelot_reg base;
  256. enum ocelot_stat first_stat;
  257. int count;
  258. u32 *buf;
  259. };
  260. static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = {
  261. OCELOT_COMMON_STATS,
  262. };
  263. static const struct ocelot_stat_layout ocelot_mm_stats_layout[OCELOT_NUM_STATS] = {
  264. OCELOT_COMMON_STATS,
  265. OCELOT_STAT(RX_ASSEMBLY_ERRS),
  266. OCELOT_STAT(RX_SMD_ERRS),
  267. OCELOT_STAT(RX_ASSEMBLY_OK),
  268. OCELOT_STAT(RX_MERGE_FRAGMENTS),
  269. OCELOT_STAT(TX_MERGE_FRAGMENTS),
  270. OCELOT_STAT(TX_MM_HOLD),
  271. OCELOT_STAT(RX_PMAC_OCTETS),
  272. OCELOT_STAT(RX_PMAC_UNICAST),
  273. OCELOT_STAT(RX_PMAC_MULTICAST),
  274. OCELOT_STAT(RX_PMAC_BROADCAST),
  275. OCELOT_STAT(RX_PMAC_SHORTS),
  276. OCELOT_STAT(RX_PMAC_FRAGMENTS),
  277. OCELOT_STAT(RX_PMAC_JABBERS),
  278. OCELOT_STAT(RX_PMAC_CRC_ALIGN_ERRS),
  279. OCELOT_STAT(RX_PMAC_SYM_ERRS),
  280. OCELOT_STAT(RX_PMAC_64),
  281. OCELOT_STAT(RX_PMAC_65_127),
  282. OCELOT_STAT(RX_PMAC_128_255),
  283. OCELOT_STAT(RX_PMAC_256_511),
  284. OCELOT_STAT(RX_PMAC_512_1023),
  285. OCELOT_STAT(RX_PMAC_1024_1526),
  286. OCELOT_STAT(RX_PMAC_1527_MAX),
  287. OCELOT_STAT(RX_PMAC_PAUSE),
  288. OCELOT_STAT(RX_PMAC_CONTROL),
  289. OCELOT_STAT(RX_PMAC_LONGS),
  290. OCELOT_STAT(TX_PMAC_OCTETS),
  291. OCELOT_STAT(TX_PMAC_UNICAST),
  292. OCELOT_STAT(TX_PMAC_MULTICAST),
  293. OCELOT_STAT(TX_PMAC_BROADCAST),
  294. OCELOT_STAT(TX_PMAC_PAUSE),
  295. OCELOT_STAT(TX_PMAC_64),
  296. OCELOT_STAT(TX_PMAC_65_127),
  297. OCELOT_STAT(TX_PMAC_128_255),
  298. OCELOT_STAT(TX_PMAC_256_511),
  299. OCELOT_STAT(TX_PMAC_512_1023),
  300. OCELOT_STAT(TX_PMAC_1024_1526),
  301. OCELOT_STAT(TX_PMAC_1527_MAX),
  302. };
  303. static const struct ocelot_stat_layout *
  304. ocelot_get_stats_layout(struct ocelot *ocelot)
  305. {
  306. if (ocelot->mm_supported)
  307. return ocelot_mm_stats_layout;
  308. return ocelot_stats_layout;
  309. }
  310. /* Read the counters from hardware and keep them in region->buf.
  311. * Caller must hold &ocelot->stat_view_lock.
  312. */
  313. static int ocelot_port_update_stats(struct ocelot *ocelot, int port)
  314. {
  315. struct ocelot_stats_region *region;
  316. int err;
  317. /* Configure the port to read the stats from */
  318. ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), SYS_STAT_CFG);
  319. list_for_each_entry(region, &ocelot->stats_regions, node) {
  320. err = ocelot_bulk_read(ocelot, region->base, region->buf,
  321. region->count);
  322. if (err)
  323. return err;
  324. }
  325. return 0;
  326. }
  327. /* Transfer the counters from region->buf to ocelot->stats.
  328. * Caller must hold &ocelot->stat_view_lock and &ocelot->stats_lock.
  329. */
  330. static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port)
  331. {
  332. struct ocelot_stats_region *region;
  333. int j;
  334. list_for_each_entry(region, &ocelot->stats_regions, node) {
  335. unsigned int idx = port * OCELOT_NUM_STATS + region->first_stat;
  336. for (j = 0; j < region->count; j++) {
  337. u64 *stat = &ocelot->stats[idx + j];
  338. u64 val = region->buf[j];
  339. if (val < (*stat & U32_MAX))
  340. *stat += (u64)1 << 32;
  341. *stat = (*stat & ~(u64)U32_MAX) + val;
  342. }
  343. }
  344. }
  345. static void ocelot_check_stats_work(struct work_struct *work)
  346. {
  347. struct delayed_work *del_work = to_delayed_work(work);
  348. struct ocelot *ocelot = container_of(del_work, struct ocelot,
  349. stats_work);
  350. int port, err;
  351. mutex_lock(&ocelot->stat_view_lock);
  352. for (port = 0; port < ocelot->num_phys_ports; port++) {
  353. err = ocelot_port_update_stats(ocelot, port);
  354. if (err)
  355. break;
  356. spin_lock(&ocelot->stats_lock);
  357. ocelot_port_transfer_stats(ocelot, port);
  358. spin_unlock(&ocelot->stats_lock);
  359. }
  360. if (!err && ocelot->ops->update_stats)
  361. ocelot->ops->update_stats(ocelot);
  362. mutex_unlock(&ocelot->stat_view_lock);
  363. if (err)
  364. dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err);
  365. queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
  366. OCELOT_STATS_CHECK_DELAY);
  367. }
  368. void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data)
  369. {
  370. const struct ocelot_stat_layout *layout;
  371. enum ocelot_stat i;
  372. if (sset != ETH_SS_STATS)
  373. return;
  374. layout = ocelot_get_stats_layout(ocelot);
  375. for (i = 0; i < OCELOT_NUM_STATS; i++) {
  376. if (layout[i].name[0] == '\0')
  377. continue;
  378. memcpy(data, layout[i].name, ETH_GSTRING_LEN);
  379. data += ETH_GSTRING_LEN;
  380. }
  381. }
  382. EXPORT_SYMBOL(ocelot_get_strings);
  383. /* Update ocelot->stats for the given port and run the given callback */
  384. static void ocelot_port_stats_run(struct ocelot *ocelot, int port, void *priv,
  385. void (*cb)(struct ocelot *ocelot, int port,
  386. void *priv))
  387. {
  388. int err;
  389. mutex_lock(&ocelot->stat_view_lock);
  390. err = ocelot_port_update_stats(ocelot, port);
  391. if (err) {
  392. dev_err(ocelot->dev, "Failed to update port %d stats: %pe\n",
  393. port, ERR_PTR(err));
  394. goto out_unlock;
  395. }
  396. spin_lock(&ocelot->stats_lock);
  397. ocelot_port_transfer_stats(ocelot, port);
  398. cb(ocelot, port, priv);
  399. spin_unlock(&ocelot->stats_lock);
  400. out_unlock:
  401. mutex_unlock(&ocelot->stat_view_lock);
  402. }
  403. int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset)
  404. {
  405. const struct ocelot_stat_layout *layout;
  406. enum ocelot_stat i;
  407. int num_stats = 0;
  408. if (sset != ETH_SS_STATS)
  409. return -EOPNOTSUPP;
  410. layout = ocelot_get_stats_layout(ocelot);
  411. for (i = 0; i < OCELOT_NUM_STATS; i++)
  412. if (layout[i].name[0] != '\0')
  413. num_stats++;
  414. return num_stats;
  415. }
  416. EXPORT_SYMBOL(ocelot_get_sset_count);
  417. static void ocelot_port_ethtool_stats_cb(struct ocelot *ocelot, int port,
  418. void *priv)
  419. {
  420. const struct ocelot_stat_layout *layout;
  421. enum ocelot_stat i;
  422. u64 *data = priv;
  423. layout = ocelot_get_stats_layout(ocelot);
  424. /* Copy all supported counters */
  425. for (i = 0; i < OCELOT_NUM_STATS; i++) {
  426. int index = port * OCELOT_NUM_STATS + i;
  427. if (layout[i].name[0] == '\0')
  428. continue;
  429. *data++ = ocelot->stats[index];
  430. }
  431. }
  432. void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data)
  433. {
  434. ocelot_port_stats_run(ocelot, port, data, ocelot_port_ethtool_stats_cb);
  435. }
  436. EXPORT_SYMBOL(ocelot_get_ethtool_stats);
  437. static void ocelot_port_pause_stats_cb(struct ocelot *ocelot, int port, void *priv)
  438. {
  439. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  440. struct ethtool_pause_stats *pause_stats = priv;
  441. pause_stats->tx_pause_frames = s[OCELOT_STAT_TX_PAUSE];
  442. pause_stats->rx_pause_frames = s[OCELOT_STAT_RX_PAUSE];
  443. }
  444. static void ocelot_port_pmac_pause_stats_cb(struct ocelot *ocelot, int port,
  445. void *priv)
  446. {
  447. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  448. struct ethtool_pause_stats *pause_stats = priv;
  449. pause_stats->tx_pause_frames = s[OCELOT_STAT_TX_PMAC_PAUSE];
  450. pause_stats->rx_pause_frames = s[OCELOT_STAT_RX_PMAC_PAUSE];
  451. }
  452. static void ocelot_port_mm_stats_cb(struct ocelot *ocelot, int port,
  453. void *priv)
  454. {
  455. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  456. struct ethtool_mm_stats *stats = priv;
  457. stats->MACMergeFrameAssErrorCount = s[OCELOT_STAT_RX_ASSEMBLY_ERRS];
  458. stats->MACMergeFrameSmdErrorCount = s[OCELOT_STAT_RX_SMD_ERRS];
  459. stats->MACMergeFrameAssOkCount = s[OCELOT_STAT_RX_ASSEMBLY_OK];
  460. stats->MACMergeFragCountRx = s[OCELOT_STAT_RX_MERGE_FRAGMENTS];
  461. stats->MACMergeFragCountTx = s[OCELOT_STAT_TX_MERGE_FRAGMENTS];
  462. stats->MACMergeHoldCount = s[OCELOT_STAT_TX_MM_HOLD];
  463. }
  464. void ocelot_port_get_pause_stats(struct ocelot *ocelot, int port,
  465. struct ethtool_pause_stats *pause_stats)
  466. {
  467. struct net_device *dev;
  468. switch (pause_stats->src) {
  469. case ETHTOOL_MAC_STATS_SRC_EMAC:
  470. ocelot_port_stats_run(ocelot, port, pause_stats,
  471. ocelot_port_pause_stats_cb);
  472. break;
  473. case ETHTOOL_MAC_STATS_SRC_PMAC:
  474. if (ocelot->mm_supported)
  475. ocelot_port_stats_run(ocelot, port, pause_stats,
  476. ocelot_port_pmac_pause_stats_cb);
  477. break;
  478. case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
  479. dev = ocelot->ops->port_to_netdev(ocelot, port);
  480. ethtool_aggregate_pause_stats(dev, pause_stats);
  481. break;
  482. }
  483. }
  484. EXPORT_SYMBOL_GPL(ocelot_port_get_pause_stats);
  485. void ocelot_port_get_mm_stats(struct ocelot *ocelot, int port,
  486. struct ethtool_mm_stats *stats)
  487. {
  488. if (!ocelot->mm_supported)
  489. return;
  490. ocelot_port_stats_run(ocelot, port, stats, ocelot_port_mm_stats_cb);
  491. }
  492. EXPORT_SYMBOL_GPL(ocelot_port_get_mm_stats);
  493. static const struct ethtool_rmon_hist_range ocelot_rmon_ranges[] = {
  494. { 64, 64 },
  495. { 65, 127 },
  496. { 128, 255 },
  497. { 256, 511 },
  498. { 512, 1023 },
  499. { 1024, 1526 },
  500. { 1527, 65535 },
  501. {},
  502. };
  503. static void ocelot_port_rmon_stats_cb(struct ocelot *ocelot, int port, void *priv)
  504. {
  505. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  506. struct ethtool_rmon_stats *rmon_stats = priv;
  507. rmon_stats->undersize_pkts = s[OCELOT_STAT_RX_SHORTS];
  508. rmon_stats->oversize_pkts = s[OCELOT_STAT_RX_LONGS];
  509. rmon_stats->fragments = s[OCELOT_STAT_RX_FRAGMENTS];
  510. rmon_stats->jabbers = s[OCELOT_STAT_RX_JABBERS];
  511. rmon_stats->hist[0] = s[OCELOT_STAT_RX_64];
  512. rmon_stats->hist[1] = s[OCELOT_STAT_RX_65_127];
  513. rmon_stats->hist[2] = s[OCELOT_STAT_RX_128_255];
  514. rmon_stats->hist[3] = s[OCELOT_STAT_RX_256_511];
  515. rmon_stats->hist[4] = s[OCELOT_STAT_RX_512_1023];
  516. rmon_stats->hist[5] = s[OCELOT_STAT_RX_1024_1526];
  517. rmon_stats->hist[6] = s[OCELOT_STAT_RX_1527_MAX];
  518. rmon_stats->hist_tx[0] = s[OCELOT_STAT_TX_64];
  519. rmon_stats->hist_tx[1] = s[OCELOT_STAT_TX_65_127];
  520. rmon_stats->hist_tx[2] = s[OCELOT_STAT_TX_128_255];
  521. rmon_stats->hist_tx[3] = s[OCELOT_STAT_TX_256_511];
  522. rmon_stats->hist_tx[4] = s[OCELOT_STAT_TX_512_1023];
  523. rmon_stats->hist_tx[5] = s[OCELOT_STAT_TX_1024_1526];
  524. rmon_stats->hist_tx[6] = s[OCELOT_STAT_TX_1527_MAX];
  525. }
  526. static void ocelot_port_pmac_rmon_stats_cb(struct ocelot *ocelot, int port,
  527. void *priv)
  528. {
  529. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  530. struct ethtool_rmon_stats *rmon_stats = priv;
  531. rmon_stats->undersize_pkts = s[OCELOT_STAT_RX_PMAC_SHORTS];
  532. rmon_stats->oversize_pkts = s[OCELOT_STAT_RX_PMAC_LONGS];
  533. rmon_stats->fragments = s[OCELOT_STAT_RX_PMAC_FRAGMENTS];
  534. rmon_stats->jabbers = s[OCELOT_STAT_RX_PMAC_JABBERS];
  535. rmon_stats->hist[0] = s[OCELOT_STAT_RX_PMAC_64];
  536. rmon_stats->hist[1] = s[OCELOT_STAT_RX_PMAC_65_127];
  537. rmon_stats->hist[2] = s[OCELOT_STAT_RX_PMAC_128_255];
  538. rmon_stats->hist[3] = s[OCELOT_STAT_RX_PMAC_256_511];
  539. rmon_stats->hist[4] = s[OCELOT_STAT_RX_PMAC_512_1023];
  540. rmon_stats->hist[5] = s[OCELOT_STAT_RX_PMAC_1024_1526];
  541. rmon_stats->hist[6] = s[OCELOT_STAT_RX_PMAC_1527_MAX];
  542. rmon_stats->hist_tx[0] = s[OCELOT_STAT_TX_PMAC_64];
  543. rmon_stats->hist_tx[1] = s[OCELOT_STAT_TX_PMAC_65_127];
  544. rmon_stats->hist_tx[2] = s[OCELOT_STAT_TX_PMAC_128_255];
  545. rmon_stats->hist_tx[3] = s[OCELOT_STAT_TX_PMAC_256_511];
  546. rmon_stats->hist_tx[4] = s[OCELOT_STAT_TX_PMAC_512_1023];
  547. rmon_stats->hist_tx[5] = s[OCELOT_STAT_TX_PMAC_1024_1526];
  548. rmon_stats->hist_tx[6] = s[OCELOT_STAT_TX_PMAC_1527_MAX];
  549. }
  550. void ocelot_port_get_rmon_stats(struct ocelot *ocelot, int port,
  551. struct ethtool_rmon_stats *rmon_stats,
  552. const struct ethtool_rmon_hist_range **ranges)
  553. {
  554. struct net_device *dev;
  555. *ranges = ocelot_rmon_ranges;
  556. switch (rmon_stats->src) {
  557. case ETHTOOL_MAC_STATS_SRC_EMAC:
  558. ocelot_port_stats_run(ocelot, port, rmon_stats,
  559. ocelot_port_rmon_stats_cb);
  560. break;
  561. case ETHTOOL_MAC_STATS_SRC_PMAC:
  562. if (ocelot->mm_supported)
  563. ocelot_port_stats_run(ocelot, port, rmon_stats,
  564. ocelot_port_pmac_rmon_stats_cb);
  565. break;
  566. case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
  567. dev = ocelot->ops->port_to_netdev(ocelot, port);
  568. ethtool_aggregate_rmon_stats(dev, rmon_stats);
  569. break;
  570. }
  571. }
  572. EXPORT_SYMBOL_GPL(ocelot_port_get_rmon_stats);
  573. static void ocelot_port_ctrl_stats_cb(struct ocelot *ocelot, int port, void *priv)
  574. {
  575. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  576. struct ethtool_eth_ctrl_stats *ctrl_stats = priv;
  577. ctrl_stats->MACControlFramesReceived = s[OCELOT_STAT_RX_CONTROL];
  578. }
  579. static void ocelot_port_pmac_ctrl_stats_cb(struct ocelot *ocelot, int port,
  580. void *priv)
  581. {
  582. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  583. struct ethtool_eth_ctrl_stats *ctrl_stats = priv;
  584. ctrl_stats->MACControlFramesReceived = s[OCELOT_STAT_RX_PMAC_CONTROL];
  585. }
  586. void ocelot_port_get_eth_ctrl_stats(struct ocelot *ocelot, int port,
  587. struct ethtool_eth_ctrl_stats *ctrl_stats)
  588. {
  589. struct net_device *dev;
  590. switch (ctrl_stats->src) {
  591. case ETHTOOL_MAC_STATS_SRC_EMAC:
  592. ocelot_port_stats_run(ocelot, port, ctrl_stats,
  593. ocelot_port_ctrl_stats_cb);
  594. break;
  595. case ETHTOOL_MAC_STATS_SRC_PMAC:
  596. if (ocelot->mm_supported)
  597. ocelot_port_stats_run(ocelot, port, ctrl_stats,
  598. ocelot_port_pmac_ctrl_stats_cb);
  599. break;
  600. case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
  601. dev = ocelot->ops->port_to_netdev(ocelot, port);
  602. ethtool_aggregate_ctrl_stats(dev, ctrl_stats);
  603. break;
  604. }
  605. }
  606. EXPORT_SYMBOL_GPL(ocelot_port_get_eth_ctrl_stats);
  607. static void ocelot_port_mac_stats_cb(struct ocelot *ocelot, int port, void *priv)
  608. {
  609. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  610. struct ethtool_eth_mac_stats *mac_stats = priv;
  611. mac_stats->OctetsTransmittedOK = s[OCELOT_STAT_TX_OCTETS];
  612. mac_stats->FramesTransmittedOK = s[OCELOT_STAT_TX_64] +
  613. s[OCELOT_STAT_TX_65_127] +
  614. s[OCELOT_STAT_TX_128_255] +
  615. s[OCELOT_STAT_TX_256_511] +
  616. s[OCELOT_STAT_TX_512_1023] +
  617. s[OCELOT_STAT_TX_1024_1526] +
  618. s[OCELOT_STAT_TX_1527_MAX];
  619. mac_stats->OctetsReceivedOK = s[OCELOT_STAT_RX_OCTETS];
  620. mac_stats->FramesReceivedOK = s[OCELOT_STAT_RX_GREEN_PRIO_0] +
  621. s[OCELOT_STAT_RX_GREEN_PRIO_1] +
  622. s[OCELOT_STAT_RX_GREEN_PRIO_2] +
  623. s[OCELOT_STAT_RX_GREEN_PRIO_3] +
  624. s[OCELOT_STAT_RX_GREEN_PRIO_4] +
  625. s[OCELOT_STAT_RX_GREEN_PRIO_5] +
  626. s[OCELOT_STAT_RX_GREEN_PRIO_6] +
  627. s[OCELOT_STAT_RX_GREEN_PRIO_7] +
  628. s[OCELOT_STAT_RX_YELLOW_PRIO_0] +
  629. s[OCELOT_STAT_RX_YELLOW_PRIO_1] +
  630. s[OCELOT_STAT_RX_YELLOW_PRIO_2] +
  631. s[OCELOT_STAT_RX_YELLOW_PRIO_3] +
  632. s[OCELOT_STAT_RX_YELLOW_PRIO_4] +
  633. s[OCELOT_STAT_RX_YELLOW_PRIO_5] +
  634. s[OCELOT_STAT_RX_YELLOW_PRIO_6] +
  635. s[OCELOT_STAT_RX_YELLOW_PRIO_7];
  636. mac_stats->MulticastFramesXmittedOK = s[OCELOT_STAT_TX_MULTICAST];
  637. mac_stats->BroadcastFramesXmittedOK = s[OCELOT_STAT_TX_BROADCAST];
  638. mac_stats->MulticastFramesReceivedOK = s[OCELOT_STAT_RX_MULTICAST];
  639. mac_stats->BroadcastFramesReceivedOK = s[OCELOT_STAT_RX_BROADCAST];
  640. mac_stats->FrameTooLongErrors = s[OCELOT_STAT_RX_LONGS];
  641. /* Sadly, C_RX_CRC is the sum of FCS and alignment errors, they are not
  642. * counted individually.
  643. */
  644. mac_stats->FrameCheckSequenceErrors = s[OCELOT_STAT_RX_CRC_ALIGN_ERRS];
  645. mac_stats->AlignmentErrors = s[OCELOT_STAT_RX_CRC_ALIGN_ERRS];
  646. }
  647. static void ocelot_port_pmac_mac_stats_cb(struct ocelot *ocelot, int port,
  648. void *priv)
  649. {
  650. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  651. struct ethtool_eth_mac_stats *mac_stats = priv;
  652. mac_stats->OctetsTransmittedOK = s[OCELOT_STAT_TX_PMAC_OCTETS];
  653. mac_stats->FramesTransmittedOK = s[OCELOT_STAT_TX_PMAC_64] +
  654. s[OCELOT_STAT_TX_PMAC_65_127] +
  655. s[OCELOT_STAT_TX_PMAC_128_255] +
  656. s[OCELOT_STAT_TX_PMAC_256_511] +
  657. s[OCELOT_STAT_TX_PMAC_512_1023] +
  658. s[OCELOT_STAT_TX_PMAC_1024_1526] +
  659. s[OCELOT_STAT_TX_PMAC_1527_MAX];
  660. mac_stats->OctetsReceivedOK = s[OCELOT_STAT_RX_PMAC_OCTETS];
  661. mac_stats->FramesReceivedOK = s[OCELOT_STAT_RX_PMAC_64] +
  662. s[OCELOT_STAT_RX_PMAC_65_127] +
  663. s[OCELOT_STAT_RX_PMAC_128_255] +
  664. s[OCELOT_STAT_RX_PMAC_256_511] +
  665. s[OCELOT_STAT_RX_PMAC_512_1023] +
  666. s[OCELOT_STAT_RX_PMAC_1024_1526] +
  667. s[OCELOT_STAT_RX_PMAC_1527_MAX];
  668. mac_stats->MulticastFramesXmittedOK = s[OCELOT_STAT_TX_PMAC_MULTICAST];
  669. mac_stats->BroadcastFramesXmittedOK = s[OCELOT_STAT_TX_PMAC_BROADCAST];
  670. mac_stats->MulticastFramesReceivedOK = s[OCELOT_STAT_RX_PMAC_MULTICAST];
  671. mac_stats->BroadcastFramesReceivedOK = s[OCELOT_STAT_RX_PMAC_BROADCAST];
  672. mac_stats->FrameTooLongErrors = s[OCELOT_STAT_RX_PMAC_LONGS];
  673. /* Sadly, C_RX_CRC is the sum of FCS and alignment errors, they are not
  674. * counted individually.
  675. */
  676. mac_stats->FrameCheckSequenceErrors = s[OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS];
  677. mac_stats->AlignmentErrors = s[OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS];
  678. }
  679. void ocelot_port_get_eth_mac_stats(struct ocelot *ocelot, int port,
  680. struct ethtool_eth_mac_stats *mac_stats)
  681. {
  682. struct net_device *dev;
  683. switch (mac_stats->src) {
  684. case ETHTOOL_MAC_STATS_SRC_EMAC:
  685. ocelot_port_stats_run(ocelot, port, mac_stats,
  686. ocelot_port_mac_stats_cb);
  687. break;
  688. case ETHTOOL_MAC_STATS_SRC_PMAC:
  689. if (ocelot->mm_supported)
  690. ocelot_port_stats_run(ocelot, port, mac_stats,
  691. ocelot_port_pmac_mac_stats_cb);
  692. break;
  693. case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
  694. dev = ocelot->ops->port_to_netdev(ocelot, port);
  695. ethtool_aggregate_mac_stats(dev, mac_stats);
  696. break;
  697. }
  698. }
  699. EXPORT_SYMBOL_GPL(ocelot_port_get_eth_mac_stats);
  700. static void ocelot_port_phy_stats_cb(struct ocelot *ocelot, int port, void *priv)
  701. {
  702. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  703. struct ethtool_eth_phy_stats *phy_stats = priv;
  704. phy_stats->SymbolErrorDuringCarrier = s[OCELOT_STAT_RX_SYM_ERRS];
  705. }
  706. static void ocelot_port_pmac_phy_stats_cb(struct ocelot *ocelot, int port,
  707. void *priv)
  708. {
  709. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  710. struct ethtool_eth_phy_stats *phy_stats = priv;
  711. phy_stats->SymbolErrorDuringCarrier = s[OCELOT_STAT_RX_PMAC_SYM_ERRS];
  712. }
  713. void ocelot_port_get_eth_phy_stats(struct ocelot *ocelot, int port,
  714. struct ethtool_eth_phy_stats *phy_stats)
  715. {
  716. struct net_device *dev;
  717. switch (phy_stats->src) {
  718. case ETHTOOL_MAC_STATS_SRC_EMAC:
  719. ocelot_port_stats_run(ocelot, port, phy_stats,
  720. ocelot_port_phy_stats_cb);
  721. break;
  722. case ETHTOOL_MAC_STATS_SRC_PMAC:
  723. if (ocelot->mm_supported)
  724. ocelot_port_stats_run(ocelot, port, phy_stats,
  725. ocelot_port_pmac_phy_stats_cb);
  726. break;
  727. case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
  728. dev = ocelot->ops->port_to_netdev(ocelot, port);
  729. ethtool_aggregate_phy_stats(dev, phy_stats);
  730. break;
  731. }
  732. }
  733. EXPORT_SYMBOL_GPL(ocelot_port_get_eth_phy_stats);
  734. void ocelot_port_get_stats64(struct ocelot *ocelot, int port,
  735. struct rtnl_link_stats64 *stats)
  736. {
  737. u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
  738. spin_lock(&ocelot->stats_lock);
  739. /* Get Rx stats */
  740. stats->rx_bytes = s[OCELOT_STAT_RX_OCTETS];
  741. stats->rx_packets = s[OCELOT_STAT_RX_SHORTS] +
  742. s[OCELOT_STAT_RX_FRAGMENTS] +
  743. s[OCELOT_STAT_RX_JABBERS] +
  744. s[OCELOT_STAT_RX_LONGS] +
  745. s[OCELOT_STAT_RX_64] +
  746. s[OCELOT_STAT_RX_65_127] +
  747. s[OCELOT_STAT_RX_128_255] +
  748. s[OCELOT_STAT_RX_256_511] +
  749. s[OCELOT_STAT_RX_512_1023] +
  750. s[OCELOT_STAT_RX_1024_1526] +
  751. s[OCELOT_STAT_RX_1527_MAX];
  752. stats->multicast = s[OCELOT_STAT_RX_MULTICAST];
  753. stats->rx_missed_errors = s[OCELOT_STAT_DROP_TAIL];
  754. stats->rx_dropped = s[OCELOT_STAT_RX_RED_PRIO_0] +
  755. s[OCELOT_STAT_RX_RED_PRIO_1] +
  756. s[OCELOT_STAT_RX_RED_PRIO_2] +
  757. s[OCELOT_STAT_RX_RED_PRIO_3] +
  758. s[OCELOT_STAT_RX_RED_PRIO_4] +
  759. s[OCELOT_STAT_RX_RED_PRIO_5] +
  760. s[OCELOT_STAT_RX_RED_PRIO_6] +
  761. s[OCELOT_STAT_RX_RED_PRIO_7] +
  762. s[OCELOT_STAT_DROP_LOCAL] +
  763. s[OCELOT_STAT_DROP_YELLOW_PRIO_0] +
  764. s[OCELOT_STAT_DROP_YELLOW_PRIO_1] +
  765. s[OCELOT_STAT_DROP_YELLOW_PRIO_2] +
  766. s[OCELOT_STAT_DROP_YELLOW_PRIO_3] +
  767. s[OCELOT_STAT_DROP_YELLOW_PRIO_4] +
  768. s[OCELOT_STAT_DROP_YELLOW_PRIO_5] +
  769. s[OCELOT_STAT_DROP_YELLOW_PRIO_6] +
  770. s[OCELOT_STAT_DROP_YELLOW_PRIO_7] +
  771. s[OCELOT_STAT_DROP_GREEN_PRIO_0] +
  772. s[OCELOT_STAT_DROP_GREEN_PRIO_1] +
  773. s[OCELOT_STAT_DROP_GREEN_PRIO_2] +
  774. s[OCELOT_STAT_DROP_GREEN_PRIO_3] +
  775. s[OCELOT_STAT_DROP_GREEN_PRIO_4] +
  776. s[OCELOT_STAT_DROP_GREEN_PRIO_5] +
  777. s[OCELOT_STAT_DROP_GREEN_PRIO_6] +
  778. s[OCELOT_STAT_DROP_GREEN_PRIO_7];
  779. /* Get Tx stats */
  780. stats->tx_bytes = s[OCELOT_STAT_TX_OCTETS];
  781. stats->tx_packets = s[OCELOT_STAT_TX_64] +
  782. s[OCELOT_STAT_TX_65_127] +
  783. s[OCELOT_STAT_TX_128_255] +
  784. s[OCELOT_STAT_TX_256_511] +
  785. s[OCELOT_STAT_TX_512_1023] +
  786. s[OCELOT_STAT_TX_1024_1526] +
  787. s[OCELOT_STAT_TX_1527_MAX];
  788. stats->tx_dropped = s[OCELOT_STAT_TX_DROPS] +
  789. s[OCELOT_STAT_TX_AGED];
  790. stats->collisions = s[OCELOT_STAT_TX_COLLISION];
  791. spin_unlock(&ocelot->stats_lock);
  792. }
  793. EXPORT_SYMBOL(ocelot_port_get_stats64);
  794. static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
  795. {
  796. struct ocelot_stats_region *region = NULL;
  797. const struct ocelot_stat_layout *layout;
  798. enum ocelot_reg last = 0;
  799. enum ocelot_stat i;
  800. INIT_LIST_HEAD(&ocelot->stats_regions);
  801. layout = ocelot_get_stats_layout(ocelot);
  802. for (i = 0; i < OCELOT_NUM_STATS; i++) {
  803. if (!layout[i].reg)
  804. continue;
  805. /* enum ocelot_stat must be kept sorted in the same order
  806. * as the addresses behind layout[i].reg in order to have
  807. * efficient bulking
  808. */
  809. if (last) {
  810. WARN(ocelot->map[SYS][last & REG_MASK] >= ocelot->map[SYS][layout[i].reg & REG_MASK],
  811. "reg 0x%x had address 0x%x but reg 0x%x has address 0x%x, bulking broken!",
  812. last, ocelot->map[SYS][last & REG_MASK],
  813. layout[i].reg, ocelot->map[SYS][layout[i].reg & REG_MASK]);
  814. }
  815. if (region && ocelot->map[SYS][layout[i].reg & REG_MASK] ==
  816. ocelot->map[SYS][last & REG_MASK] + 4) {
  817. region->count++;
  818. } else {
  819. region = devm_kzalloc(ocelot->dev, sizeof(*region),
  820. GFP_KERNEL);
  821. if (!region)
  822. return -ENOMEM;
  823. region->base = layout[i].reg;
  824. region->first_stat = i;
  825. region->count = 1;
  826. list_add_tail(&region->node, &ocelot->stats_regions);
  827. }
  828. last = layout[i].reg;
  829. }
  830. list_for_each_entry(region, &ocelot->stats_regions, node) {
  831. enum ocelot_target target;
  832. u32 addr;
  833. ocelot_reg_to_target_addr(ocelot, region->base, &target,
  834. &addr);
  835. dev_dbg(ocelot->dev,
  836. "region of %d contiguous counters starting with SYS:STAT:CNT[0x%03x]\n",
  837. region->count, addr / 4);
  838. region->buf = devm_kcalloc(ocelot->dev, region->count,
  839. sizeof(*region->buf), GFP_KERNEL);
  840. if (!region->buf)
  841. return -ENOMEM;
  842. }
  843. return 0;
  844. }
  845. int ocelot_stats_init(struct ocelot *ocelot)
  846. {
  847. char queue_name[32];
  848. int ret;
  849. ocelot->stats = devm_kcalloc(ocelot->dev,
  850. ocelot->num_phys_ports * OCELOT_NUM_STATS,
  851. sizeof(u64), GFP_KERNEL);
  852. if (!ocelot->stats)
  853. return -ENOMEM;
  854. snprintf(queue_name, sizeof(queue_name), "%s-stats",
  855. dev_name(ocelot->dev));
  856. ocelot->stats_queue = create_singlethread_workqueue(queue_name);
  857. if (!ocelot->stats_queue)
  858. return -ENOMEM;
  859. spin_lock_init(&ocelot->stats_lock);
  860. mutex_init(&ocelot->stat_view_lock);
  861. ret = ocelot_prepare_stats_regions(ocelot);
  862. if (ret) {
  863. destroy_workqueue(ocelot->stats_queue);
  864. return ret;
  865. }
  866. INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats_work);
  867. queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
  868. OCELOT_STATS_CHECK_DELAY);
  869. return 0;
  870. }
  871. void ocelot_stats_deinit(struct ocelot *ocelot)
  872. {
  873. disable_delayed_work_sync(&ocelot->stats_work);
  874. destroy_workqueue(ocelot->stats_queue);
  875. }