ocelot_devlink.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. // SPDX-License-Identifier: (GPL-2.0 OR MIT)
  2. /* Copyright 2020-2021 NXP
  3. */
  4. #include <net/devlink.h>
  5. #include "ocelot.h"
  6. /* The queue system tracks four resource consumptions:
  7. * Resource 0: Memory tracked per source port
  8. * Resource 1: Frame references tracked per source port
  9. * Resource 2: Memory tracked per destination port
  10. * Resource 3: Frame references tracked per destination port
  11. */
  12. #define OCELOT_RESOURCE_SZ 256
  13. #define OCELOT_NUM_RESOURCES 4
  14. #define BUF_xxxx_I (0 * OCELOT_RESOURCE_SZ)
  15. #define REF_xxxx_I (1 * OCELOT_RESOURCE_SZ)
  16. #define BUF_xxxx_E (2 * OCELOT_RESOURCE_SZ)
  17. #define REF_xxxx_E (3 * OCELOT_RESOURCE_SZ)
  18. /* For each resource type there are 4 types of watermarks:
  19. * Q_RSRV: reservation per QoS class per port
  20. * PRIO_SHR: sharing watermark per QoS class across all ports
  21. * P_RSRV: reservation per port
  22. * COL_SHR: sharing watermark per color (drop precedence) across all ports
  23. */
  24. #define xxx_Q_RSRV_x 0
  25. #define xxx_PRIO_SHR_x 216
  26. #define xxx_P_RSRV_x 224
  27. #define xxx_COL_SHR_x 254
  28. /* Reservation Watermarks
  29. * ----------------------
  30. *
  31. * For setting up the reserved areas, egress watermarks exist per port and per
  32. * QoS class for both ingress and egress.
  33. */
  34. /* Amount of packet buffer
  35. * | per QoS class
  36. * | | reserved
  37. * | | | per egress port
  38. * | | | |
  39. * V V v v
  40. * BUF_Q_RSRV_E
  41. */
  42. #define BUF_Q_RSRV_E(port, prio) \
  43. (BUF_xxxx_E + xxx_Q_RSRV_x + OCELOT_NUM_TC * (port) + (prio))
  44. /* Amount of packet buffer
  45. * | for all port's traffic classes
  46. * | | reserved
  47. * | | | per egress port
  48. * | | | |
  49. * V V v v
  50. * BUF_P_RSRV_E
  51. */
  52. #define BUF_P_RSRV_E(port) \
  53. (BUF_xxxx_E + xxx_P_RSRV_x + (port))
  54. /* Amount of packet buffer
  55. * | per QoS class
  56. * | | reserved
  57. * | | | per ingress port
  58. * | | | |
  59. * V V v v
  60. * BUF_Q_RSRV_I
  61. */
  62. #define BUF_Q_RSRV_I(port, prio) \
  63. (BUF_xxxx_I + xxx_Q_RSRV_x + OCELOT_NUM_TC * (port) + (prio))
  64. /* Amount of packet buffer
  65. * | for all port's traffic classes
  66. * | | reserved
  67. * | | | per ingress port
  68. * | | | |
  69. * V V v v
  70. * BUF_P_RSRV_I
  71. */
  72. #define BUF_P_RSRV_I(port) \
  73. (BUF_xxxx_I + xxx_P_RSRV_x + (port))
  74. /* Amount of frame references
  75. * | per QoS class
  76. * | | reserved
  77. * | | | per egress port
  78. * | | | |
  79. * V V v v
  80. * REF_Q_RSRV_E
  81. */
  82. #define REF_Q_RSRV_E(port, prio) \
  83. (REF_xxxx_E + xxx_Q_RSRV_x + OCELOT_NUM_TC * (port) + (prio))
  84. /* Amount of frame references
  85. * | for all port's traffic classes
  86. * | | reserved
  87. * | | | per egress port
  88. * | | | |
  89. * V V v v
  90. * REF_P_RSRV_E
  91. */
  92. #define REF_P_RSRV_E(port) \
  93. (REF_xxxx_E + xxx_P_RSRV_x + (port))
  94. /* Amount of frame references
  95. * | per QoS class
  96. * | | reserved
  97. * | | | per ingress port
  98. * | | | |
  99. * V V v v
  100. * REF_Q_RSRV_I
  101. */
  102. #define REF_Q_RSRV_I(port, prio) \
  103. (REF_xxxx_I + xxx_Q_RSRV_x + OCELOT_NUM_TC * (port) + (prio))
  104. /* Amount of frame references
  105. * | for all port's traffic classes
  106. * | | reserved
  107. * | | | per ingress port
  108. * | | | |
  109. * V V v v
  110. * REF_P_RSRV_I
  111. */
  112. #define REF_P_RSRV_I(port) \
  113. (REF_xxxx_I + xxx_P_RSRV_x + (port))
  114. /* Sharing Watermarks
  115. * ------------------
  116. *
  117. * The shared memory area is shared between all ports.
  118. */
  119. /* Amount of buffer
  120. * | per QoS class
  121. * | | from the shared memory area
  122. * | | | for egress traffic
  123. * | | | |
  124. * V V v v
  125. * BUF_PRIO_SHR_E
  126. */
  127. #define BUF_PRIO_SHR_E(prio) \
  128. (BUF_xxxx_E + xxx_PRIO_SHR_x + (prio))
  129. /* Amount of buffer
  130. * | per color (drop precedence level)
  131. * | | from the shared memory area
  132. * | | | for egress traffic
  133. * | | | |
  134. * V V v v
  135. * BUF_COL_SHR_E
  136. */
  137. #define BUF_COL_SHR_E(dp) \
  138. (BUF_xxxx_E + xxx_COL_SHR_x + (1 - (dp)))
  139. /* Amount of buffer
  140. * | per QoS class
  141. * | | from the shared memory area
  142. * | | | for ingress traffic
  143. * | | | |
  144. * V V v v
  145. * BUF_PRIO_SHR_I
  146. */
  147. #define BUF_PRIO_SHR_I(prio) \
  148. (BUF_xxxx_I + xxx_PRIO_SHR_x + (prio))
  149. /* Amount of buffer
  150. * | per color (drop precedence level)
  151. * | | from the shared memory area
  152. * | | | for ingress traffic
  153. * | | | |
  154. * V V v v
  155. * BUF_COL_SHR_I
  156. */
  157. #define BUF_COL_SHR_I(dp) \
  158. (BUF_xxxx_I + xxx_COL_SHR_x + (1 - (dp)))
  159. /* Amount of frame references
  160. * | per QoS class
  161. * | | from the shared area
  162. * | | | for egress traffic
  163. * | | | |
  164. * V V v v
  165. * REF_PRIO_SHR_E
  166. */
  167. #define REF_PRIO_SHR_E(prio) \
  168. (REF_xxxx_E + xxx_PRIO_SHR_x + (prio))
  169. /* Amount of frame references
  170. * | per color (drop precedence level)
  171. * | | from the shared area
  172. * | | | for egress traffic
  173. * | | | |
  174. * V V v v
  175. * REF_COL_SHR_E
  176. */
  177. #define REF_COL_SHR_E(dp) \
  178. (REF_xxxx_E + xxx_COL_SHR_x + (1 - (dp)))
  179. /* Amount of frame references
  180. * | per QoS class
  181. * | | from the shared area
  182. * | | | for ingress traffic
  183. * | | | |
  184. * V V v v
  185. * REF_PRIO_SHR_I
  186. */
  187. #define REF_PRIO_SHR_I(prio) \
  188. (REF_xxxx_I + xxx_PRIO_SHR_x + (prio))
  189. /* Amount of frame references
  190. * | per color (drop precedence level)
  191. * | | from the shared area
  192. * | | | for ingress traffic
  193. * | | | |
  194. * V V v v
  195. * REF_COL_SHR_I
  196. */
  197. #define REF_COL_SHR_I(dp) \
  198. (REF_xxxx_I + xxx_COL_SHR_x + (1 - (dp)))
  199. static u32 ocelot_wm_read(struct ocelot *ocelot, int index)
  200. {
  201. int wm = ocelot_read_gix(ocelot, QSYS_RES_CFG, index);
  202. return ocelot->ops->wm_dec(wm);
  203. }
  204. static void ocelot_wm_write(struct ocelot *ocelot, int index, u32 val)
  205. {
  206. u32 wm = ocelot->ops->wm_enc(val);
  207. ocelot_write_gix(ocelot, wm, QSYS_RES_CFG, index);
  208. }
  209. static void ocelot_wm_status(struct ocelot *ocelot, int index, u32 *inuse,
  210. u32 *maxuse)
  211. {
  212. int res_stat = ocelot_read_gix(ocelot, QSYS_RES_STAT, index);
  213. return ocelot->ops->wm_stat(res_stat, inuse, maxuse);
  214. }
  215. /* The hardware comes out of reset with strange defaults: the sum of all
  216. * reservations for frame memory is larger than the total buffer size.
  217. * One has to wonder how can the reservation watermarks still guarantee
  218. * anything under congestion.
  219. * Bring some sense into the hardware by changing the defaults to disable all
  220. * reservations and rely only on the sharing watermark for frames with drop
  221. * precedence 0. The user can still explicitly request reservations per port
  222. * and per port-tc through devlink-sb.
  223. */
  224. static void ocelot_disable_reservation_watermarks(struct ocelot *ocelot,
  225. int port)
  226. {
  227. int prio;
  228. for (prio = 0; prio < OCELOT_NUM_TC; prio++) {
  229. ocelot_wm_write(ocelot, BUF_Q_RSRV_I(port, prio), 0);
  230. ocelot_wm_write(ocelot, BUF_Q_RSRV_E(port, prio), 0);
  231. ocelot_wm_write(ocelot, REF_Q_RSRV_I(port, prio), 0);
  232. ocelot_wm_write(ocelot, REF_Q_RSRV_E(port, prio), 0);
  233. }
  234. ocelot_wm_write(ocelot, BUF_P_RSRV_I(port), 0);
  235. ocelot_wm_write(ocelot, BUF_P_RSRV_E(port), 0);
  236. ocelot_wm_write(ocelot, REF_P_RSRV_I(port), 0);
  237. ocelot_wm_write(ocelot, REF_P_RSRV_E(port), 0);
  238. }
  239. /* We want the sharing watermarks to consume all nonreserved resources, for
  240. * efficient resource utilization (a single traffic flow should be able to use
  241. * up the entire buffer space and frame resources as long as there's no
  242. * interference).
  243. * The switch has 10 sharing watermarks per lookup: 8 per traffic class and 2
  244. * per color (drop precedence).
  245. * The trouble with configuring these sharing watermarks is that:
  246. * (1) There's a risk that we overcommit the resources if we configure
  247. * (a) all 8 per-TC sharing watermarks to the max
  248. * (b) all 2 per-color sharing watermarks to the max
  249. * (2) There's a risk that we undercommit the resources if we configure
  250. * (a) all 8 per-TC sharing watermarks to "max / 8"
  251. * (b) all 2 per-color sharing watermarks to "max / 2"
  252. * So for Linux, let's just disable the sharing watermarks per traffic class
  253. * (setting them to 0 will make them always exceeded), and rely only on the
  254. * sharing watermark for drop priority 0. So frames with drop priority set to 1
  255. * by QoS classification or policing will still be allowed, but only as long as
  256. * the port and port-TC reservations are not exceeded.
  257. */
  258. static void ocelot_disable_tc_sharing_watermarks(struct ocelot *ocelot)
  259. {
  260. int prio;
  261. for (prio = 0; prio < OCELOT_NUM_TC; prio++) {
  262. ocelot_wm_write(ocelot, BUF_PRIO_SHR_I(prio), 0);
  263. ocelot_wm_write(ocelot, BUF_PRIO_SHR_E(prio), 0);
  264. ocelot_wm_write(ocelot, REF_PRIO_SHR_I(prio), 0);
  265. ocelot_wm_write(ocelot, REF_PRIO_SHR_E(prio), 0);
  266. }
  267. }
  268. static void ocelot_get_buf_rsrv(struct ocelot *ocelot, u32 *buf_rsrv_i,
  269. u32 *buf_rsrv_e)
  270. {
  271. int port, prio;
  272. *buf_rsrv_i = 0;
  273. *buf_rsrv_e = 0;
  274. for (port = 0; port <= ocelot->num_phys_ports; port++) {
  275. for (prio = 0; prio < OCELOT_NUM_TC; prio++) {
  276. *buf_rsrv_i += ocelot_wm_read(ocelot,
  277. BUF_Q_RSRV_I(port, prio));
  278. *buf_rsrv_e += ocelot_wm_read(ocelot,
  279. BUF_Q_RSRV_E(port, prio));
  280. }
  281. *buf_rsrv_i += ocelot_wm_read(ocelot, BUF_P_RSRV_I(port));
  282. *buf_rsrv_e += ocelot_wm_read(ocelot, BUF_P_RSRV_E(port));
  283. }
  284. *buf_rsrv_i *= OCELOT_BUFFER_CELL_SZ;
  285. *buf_rsrv_e *= OCELOT_BUFFER_CELL_SZ;
  286. }
  287. static void ocelot_get_ref_rsrv(struct ocelot *ocelot, u32 *ref_rsrv_i,
  288. u32 *ref_rsrv_e)
  289. {
  290. int port, prio;
  291. *ref_rsrv_i = 0;
  292. *ref_rsrv_e = 0;
  293. for (port = 0; port <= ocelot->num_phys_ports; port++) {
  294. for (prio = 0; prio < OCELOT_NUM_TC; prio++) {
  295. *ref_rsrv_i += ocelot_wm_read(ocelot,
  296. REF_Q_RSRV_I(port, prio));
  297. *ref_rsrv_e += ocelot_wm_read(ocelot,
  298. REF_Q_RSRV_E(port, prio));
  299. }
  300. *ref_rsrv_i += ocelot_wm_read(ocelot, REF_P_RSRV_I(port));
  301. *ref_rsrv_e += ocelot_wm_read(ocelot, REF_P_RSRV_E(port));
  302. }
  303. }
  304. /* Calculate all reservations, then set up the sharing watermark for DP=0 to
  305. * consume the remaining resources up to the pool's configured size.
  306. */
  307. static void ocelot_setup_sharing_watermarks(struct ocelot *ocelot)
  308. {
  309. u32 buf_rsrv_i, buf_rsrv_e;
  310. u32 ref_rsrv_i, ref_rsrv_e;
  311. u32 buf_shr_i, buf_shr_e;
  312. u32 ref_shr_i, ref_shr_e;
  313. ocelot_get_buf_rsrv(ocelot, &buf_rsrv_i, &buf_rsrv_e);
  314. ocelot_get_ref_rsrv(ocelot, &ref_rsrv_i, &ref_rsrv_e);
  315. buf_shr_i = ocelot->pool_size[OCELOT_SB_BUF][OCELOT_SB_POOL_ING] -
  316. buf_rsrv_i;
  317. buf_shr_e = ocelot->pool_size[OCELOT_SB_BUF][OCELOT_SB_POOL_EGR] -
  318. buf_rsrv_e;
  319. ref_shr_i = ocelot->pool_size[OCELOT_SB_REF][OCELOT_SB_POOL_ING] -
  320. ref_rsrv_i;
  321. ref_shr_e = ocelot->pool_size[OCELOT_SB_REF][OCELOT_SB_POOL_EGR] -
  322. ref_rsrv_e;
  323. buf_shr_i /= OCELOT_BUFFER_CELL_SZ;
  324. buf_shr_e /= OCELOT_BUFFER_CELL_SZ;
  325. ocelot_wm_write(ocelot, BUF_COL_SHR_I(0), buf_shr_i);
  326. ocelot_wm_write(ocelot, BUF_COL_SHR_E(0), buf_shr_e);
  327. ocelot_wm_write(ocelot, REF_COL_SHR_E(0), ref_shr_e);
  328. ocelot_wm_write(ocelot, REF_COL_SHR_I(0), ref_shr_i);
  329. ocelot_wm_write(ocelot, BUF_COL_SHR_I(1), 0);
  330. ocelot_wm_write(ocelot, BUF_COL_SHR_E(1), 0);
  331. ocelot_wm_write(ocelot, REF_COL_SHR_E(1), 0);
  332. ocelot_wm_write(ocelot, REF_COL_SHR_I(1), 0);
  333. }
  334. /* Ensure that all reservations can be enforced */
  335. static int ocelot_watermark_validate(struct ocelot *ocelot,
  336. struct netlink_ext_ack *extack)
  337. {
  338. u32 buf_rsrv_i, buf_rsrv_e;
  339. u32 ref_rsrv_i, ref_rsrv_e;
  340. ocelot_get_buf_rsrv(ocelot, &buf_rsrv_i, &buf_rsrv_e);
  341. ocelot_get_ref_rsrv(ocelot, &ref_rsrv_i, &ref_rsrv_e);
  342. if (buf_rsrv_i > ocelot->pool_size[OCELOT_SB_BUF][OCELOT_SB_POOL_ING]) {
  343. NL_SET_ERR_MSG_MOD(extack,
  344. "Ingress frame reservations exceed pool size");
  345. return -ERANGE;
  346. }
  347. if (buf_rsrv_e > ocelot->pool_size[OCELOT_SB_BUF][OCELOT_SB_POOL_EGR]) {
  348. NL_SET_ERR_MSG_MOD(extack,
  349. "Egress frame reservations exceed pool size");
  350. return -ERANGE;
  351. }
  352. if (ref_rsrv_i > ocelot->pool_size[OCELOT_SB_REF][OCELOT_SB_POOL_ING]) {
  353. NL_SET_ERR_MSG_MOD(extack,
  354. "Ingress reference reservations exceed pool size");
  355. return -ERANGE;
  356. }
  357. if (ref_rsrv_e > ocelot->pool_size[OCELOT_SB_REF][OCELOT_SB_POOL_EGR]) {
  358. NL_SET_ERR_MSG_MOD(extack,
  359. "Egress reference reservations exceed pool size");
  360. return -ERANGE;
  361. }
  362. return 0;
  363. }
  364. /* The hardware works like this:
  365. *
  366. * Frame forwarding decision taken
  367. * |
  368. * v
  369. * +--------------------+--------------------+--------------------+
  370. * | | | |
  371. * v v v v
  372. * Ingress memory Egress memory Ingress frame Egress frame
  373. * check check reference check reference check
  374. * | | | |
  375. * v v v v
  376. * BUF_Q_RSRV_I ok BUF_Q_RSRV_E ok REF_Q_RSRV_I ok REF_Q_RSRV_E ok
  377. *(src port, prio) -+ (dst port, prio) -+ (src port, prio) -+ (dst port, prio) -+
  378. * | | | | | | | |
  379. * |exceeded | |exceeded | |exceeded | |exceeded |
  380. * v | v | v | v |
  381. * BUF_P_RSRV_I ok| BUF_P_RSRV_E ok| REF_P_RSRV_I ok| REF_P_RSRV_E ok|
  382. * (src port) ----+ (dst port) ----+ (src port) ----+ (dst port) -----+
  383. * | | | | | | | |
  384. * |exceeded | |exceeded | |exceeded | |exceeded |
  385. * v | v | v | v |
  386. * BUF_PRIO_SHR_I ok| BUF_PRIO_SHR_E ok| REF_PRIO_SHR_I ok| REF_PRIO_SHR_E ok|
  387. * (prio) ------+ (prio) ------+ (prio) ------+ (prio) -------+
  388. * | | | | | | | |
  389. * |exceeded | |exceeded | |exceeded | |exceeded |
  390. * v | v | v | v |
  391. * BUF_COL_SHR_I ok| BUF_COL_SHR_E ok| REF_COL_SHR_I ok| REF_COL_SHR_E ok|
  392. * (dp) -------+ (dp) -------+ (dp) -------+ (dp) --------+
  393. * | | | | | | | |
  394. * |exceeded | |exceeded | |exceeded | |exceeded |
  395. * v v v v v v v v
  396. * fail success fail success fail success fail success
  397. * | | | | | | | |
  398. * v v v v v v v v
  399. * +-----+----+ +-----+----+ +-----+----+ +-----+-----+
  400. * | | | |
  401. * +-------> OR <-------+ +-------> OR <-------+
  402. * | |
  403. * v v
  404. * +----------------> AND <-----------------+
  405. * |
  406. * v
  407. * FIFO drop / accept
  408. *
  409. * We are modeling each of the 4 parallel lookups as a devlink-sb pool.
  410. * At least one (ingress or egress) memory pool and one (ingress or egress)
  411. * frame reference pool need to have resources for frame acceptance to succeed.
  412. *
  413. * The following watermarks are controlled explicitly through devlink-sb:
  414. * BUF_Q_RSRV_I, BUF_Q_RSRV_E, REF_Q_RSRV_I, REF_Q_RSRV_E
  415. * BUF_P_RSRV_I, BUF_P_RSRV_E, REF_P_RSRV_I, REF_P_RSRV_E
  416. * The following watermarks are controlled implicitly through devlink-sb:
  417. * BUF_COL_SHR_I, BUF_COL_SHR_E, REF_COL_SHR_I, REF_COL_SHR_E
  418. * The following watermarks are unused and disabled:
  419. * BUF_PRIO_SHR_I, BUF_PRIO_SHR_E, REF_PRIO_SHR_I, REF_PRIO_SHR_E
  420. *
  421. * This function overrides the hardware defaults with more sane ones (no
  422. * reservations by default, let sharing use all resources) and disables the
  423. * unused watermarks.
  424. */
  425. static void ocelot_watermark_init(struct ocelot *ocelot)
  426. {
  427. int all_tcs = GENMASK(OCELOT_NUM_TC - 1, 0);
  428. int port;
  429. ocelot_write(ocelot, all_tcs, QSYS_RES_QOS_MODE);
  430. for (port = 0; port <= ocelot->num_phys_ports; port++)
  431. ocelot_disable_reservation_watermarks(ocelot, port);
  432. ocelot_disable_tc_sharing_watermarks(ocelot);
  433. ocelot_setup_sharing_watermarks(ocelot);
  434. }
  435. /* Watermark encode
  436. * Bit 8: Unit; 0:1, 1:16
  437. * Bit 7-0: Value to be multiplied with unit
  438. */
  439. u16 ocelot_wm_enc(u16 value)
  440. {
  441. WARN_ON(value >= 16 * BIT(8));
  442. if (value >= BIT(8))
  443. return BIT(8) | (value / 16);
  444. return value;
  445. }
  446. EXPORT_SYMBOL(ocelot_wm_enc);
  447. u16 ocelot_wm_dec(u16 wm)
  448. {
  449. if (wm & BIT(8))
  450. return (wm & GENMASK(7, 0)) * 16;
  451. return wm;
  452. }
  453. EXPORT_SYMBOL(ocelot_wm_dec);
  454. void ocelot_wm_stat(u32 val, u32 *inuse, u32 *maxuse)
  455. {
  456. *inuse = (val & GENMASK(23, 12)) >> 12;
  457. *maxuse = val & GENMASK(11, 0);
  458. }
  459. EXPORT_SYMBOL(ocelot_wm_stat);
  460. /* Pool size and type are fixed up at runtime. Keeping this structure to
  461. * look up the cell size multipliers.
  462. */
  463. static const struct devlink_sb_pool_info ocelot_sb_pool[] = {
  464. [OCELOT_SB_BUF] = {
  465. .cell_size = OCELOT_BUFFER_CELL_SZ,
  466. .threshold_type = DEVLINK_SB_THRESHOLD_TYPE_STATIC,
  467. },
  468. [OCELOT_SB_REF] = {
  469. .cell_size = 1,
  470. .threshold_type = DEVLINK_SB_THRESHOLD_TYPE_STATIC,
  471. },
  472. };
  473. /* Returns the pool size configured through ocelot_sb_pool_set */
  474. int ocelot_sb_pool_get(struct ocelot *ocelot, unsigned int sb_index,
  475. u16 pool_index,
  476. struct devlink_sb_pool_info *pool_info)
  477. {
  478. if (sb_index >= OCELOT_SB_NUM)
  479. return -ENODEV;
  480. if (pool_index >= OCELOT_SB_POOL_NUM)
  481. return -ENODEV;
  482. *pool_info = ocelot_sb_pool[sb_index];
  483. pool_info->size = ocelot->pool_size[sb_index][pool_index];
  484. if (pool_index)
  485. pool_info->pool_type = DEVLINK_SB_POOL_TYPE_INGRESS;
  486. else
  487. pool_info->pool_type = DEVLINK_SB_POOL_TYPE_EGRESS;
  488. return 0;
  489. }
  490. EXPORT_SYMBOL(ocelot_sb_pool_get);
  491. /* The pool size received here configures the total amount of resources used on
  492. * ingress (or on egress, depending upon the pool index). The pool size, minus
  493. * the values for the port and port-tc reservations, is written into the
  494. * COL_SHR(dp=0) sharing watermark.
  495. */
  496. int ocelot_sb_pool_set(struct ocelot *ocelot, unsigned int sb_index,
  497. u16 pool_index, u32 size,
  498. enum devlink_sb_threshold_type threshold_type,
  499. struct netlink_ext_ack *extack)
  500. {
  501. u32 old_pool_size;
  502. int err;
  503. if (sb_index >= OCELOT_SB_NUM) {
  504. NL_SET_ERR_MSG_MOD(extack,
  505. "Invalid sb, use 0 for buffers and 1 for frame references");
  506. return -ENODEV;
  507. }
  508. if (pool_index >= OCELOT_SB_POOL_NUM) {
  509. NL_SET_ERR_MSG_MOD(extack,
  510. "Invalid pool, use 0 for ingress and 1 for egress");
  511. return -ENODEV;
  512. }
  513. if (threshold_type != DEVLINK_SB_THRESHOLD_TYPE_STATIC) {
  514. NL_SET_ERR_MSG_MOD(extack,
  515. "Only static threshold supported");
  516. return -EOPNOTSUPP;
  517. }
  518. old_pool_size = ocelot->pool_size[sb_index][pool_index];
  519. ocelot->pool_size[sb_index][pool_index] = size;
  520. err = ocelot_watermark_validate(ocelot, extack);
  521. if (err) {
  522. ocelot->pool_size[sb_index][pool_index] = old_pool_size;
  523. return err;
  524. }
  525. ocelot_setup_sharing_watermarks(ocelot);
  526. return 0;
  527. }
  528. EXPORT_SYMBOL(ocelot_sb_pool_set);
  529. /* This retrieves the configuration made with ocelot_sb_port_pool_set */
  530. int ocelot_sb_port_pool_get(struct ocelot *ocelot, int port,
  531. unsigned int sb_index, u16 pool_index,
  532. u32 *p_threshold)
  533. {
  534. int wm_index;
  535. switch (sb_index) {
  536. case OCELOT_SB_BUF:
  537. if (pool_index == OCELOT_SB_POOL_ING)
  538. wm_index = BUF_P_RSRV_I(port);
  539. else
  540. wm_index = BUF_P_RSRV_E(port);
  541. break;
  542. case OCELOT_SB_REF:
  543. if (pool_index == OCELOT_SB_POOL_ING)
  544. wm_index = REF_P_RSRV_I(port);
  545. else
  546. wm_index = REF_P_RSRV_E(port);
  547. break;
  548. default:
  549. return -ENODEV;
  550. }
  551. *p_threshold = ocelot_wm_read(ocelot, wm_index);
  552. *p_threshold *= ocelot_sb_pool[sb_index].cell_size;
  553. return 0;
  554. }
  555. EXPORT_SYMBOL(ocelot_sb_port_pool_get);
  556. /* This configures the P_RSRV per-port reserved resource watermark */
  557. int ocelot_sb_port_pool_set(struct ocelot *ocelot, int port,
  558. unsigned int sb_index, u16 pool_index,
  559. u32 threshold, struct netlink_ext_ack *extack)
  560. {
  561. int wm_index, err;
  562. u32 old_thr;
  563. switch (sb_index) {
  564. case OCELOT_SB_BUF:
  565. if (pool_index == OCELOT_SB_POOL_ING)
  566. wm_index = BUF_P_RSRV_I(port);
  567. else
  568. wm_index = BUF_P_RSRV_E(port);
  569. break;
  570. case OCELOT_SB_REF:
  571. if (pool_index == OCELOT_SB_POOL_ING)
  572. wm_index = REF_P_RSRV_I(port);
  573. else
  574. wm_index = REF_P_RSRV_E(port);
  575. break;
  576. default:
  577. NL_SET_ERR_MSG_MOD(extack, "Invalid shared buffer");
  578. return -ENODEV;
  579. }
  580. threshold /= ocelot_sb_pool[sb_index].cell_size;
  581. old_thr = ocelot_wm_read(ocelot, wm_index);
  582. ocelot_wm_write(ocelot, wm_index, threshold);
  583. err = ocelot_watermark_validate(ocelot, extack);
  584. if (err) {
  585. ocelot_wm_write(ocelot, wm_index, old_thr);
  586. return err;
  587. }
  588. ocelot_setup_sharing_watermarks(ocelot);
  589. return 0;
  590. }
  591. EXPORT_SYMBOL(ocelot_sb_port_pool_set);
  592. /* This retrieves the configuration done by ocelot_sb_tc_pool_bind_set */
  593. int ocelot_sb_tc_pool_bind_get(struct ocelot *ocelot, int port,
  594. unsigned int sb_index, u16 tc_index,
  595. enum devlink_sb_pool_type pool_type,
  596. u16 *p_pool_index, u32 *p_threshold)
  597. {
  598. int wm_index;
  599. switch (sb_index) {
  600. case OCELOT_SB_BUF:
  601. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  602. wm_index = BUF_Q_RSRV_I(port, tc_index);
  603. else
  604. wm_index = BUF_Q_RSRV_E(port, tc_index);
  605. break;
  606. case OCELOT_SB_REF:
  607. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  608. wm_index = REF_Q_RSRV_I(port, tc_index);
  609. else
  610. wm_index = REF_Q_RSRV_E(port, tc_index);
  611. break;
  612. default:
  613. return -ENODEV;
  614. }
  615. *p_threshold = ocelot_wm_read(ocelot, wm_index);
  616. *p_threshold *= ocelot_sb_pool[sb_index].cell_size;
  617. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  618. *p_pool_index = 0;
  619. else
  620. *p_pool_index = 1;
  621. return 0;
  622. }
  623. EXPORT_SYMBOL(ocelot_sb_tc_pool_bind_get);
  624. /* This configures the Q_RSRV per-port-tc reserved resource watermark */
  625. int ocelot_sb_tc_pool_bind_set(struct ocelot *ocelot, int port,
  626. unsigned int sb_index, u16 tc_index,
  627. enum devlink_sb_pool_type pool_type,
  628. u16 pool_index, u32 threshold,
  629. struct netlink_ext_ack *extack)
  630. {
  631. int wm_index, err;
  632. u32 old_thr;
  633. /* Paranoid check? */
  634. if (pool_index == OCELOT_SB_POOL_ING &&
  635. pool_type != DEVLINK_SB_POOL_TYPE_INGRESS)
  636. return -EINVAL;
  637. if (pool_index == OCELOT_SB_POOL_EGR &&
  638. pool_type != DEVLINK_SB_POOL_TYPE_EGRESS)
  639. return -EINVAL;
  640. switch (sb_index) {
  641. case OCELOT_SB_BUF:
  642. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  643. wm_index = BUF_Q_RSRV_I(port, tc_index);
  644. else
  645. wm_index = BUF_Q_RSRV_E(port, tc_index);
  646. break;
  647. case OCELOT_SB_REF:
  648. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  649. wm_index = REF_Q_RSRV_I(port, tc_index);
  650. else
  651. wm_index = REF_Q_RSRV_E(port, tc_index);
  652. break;
  653. default:
  654. NL_SET_ERR_MSG_MOD(extack, "Invalid shared buffer");
  655. return -ENODEV;
  656. }
  657. threshold /= ocelot_sb_pool[sb_index].cell_size;
  658. old_thr = ocelot_wm_read(ocelot, wm_index);
  659. ocelot_wm_write(ocelot, wm_index, threshold);
  660. err = ocelot_watermark_validate(ocelot, extack);
  661. if (err) {
  662. ocelot_wm_write(ocelot, wm_index, old_thr);
  663. return err;
  664. }
  665. ocelot_setup_sharing_watermarks(ocelot);
  666. return 0;
  667. }
  668. EXPORT_SYMBOL(ocelot_sb_tc_pool_bind_set);
  669. /* The hardware does not support atomic snapshots, we'll read out the
  670. * occupancy registers individually and have this as just a stub.
  671. */
  672. int ocelot_sb_occ_snapshot(struct ocelot *ocelot, unsigned int sb_index)
  673. {
  674. return 0;
  675. }
  676. EXPORT_SYMBOL(ocelot_sb_occ_snapshot);
  677. /* The watermark occupancy registers are cleared upon read,
  678. * so let's read them.
  679. */
  680. int ocelot_sb_occ_max_clear(struct ocelot *ocelot, unsigned int sb_index)
  681. {
  682. u32 inuse, maxuse;
  683. int port, prio;
  684. switch (sb_index) {
  685. case OCELOT_SB_BUF:
  686. for (port = 0; port <= ocelot->num_phys_ports; port++) {
  687. for (prio = 0; prio < OCELOT_NUM_TC; prio++) {
  688. ocelot_wm_status(ocelot, BUF_Q_RSRV_I(port, prio),
  689. &inuse, &maxuse);
  690. ocelot_wm_status(ocelot, BUF_Q_RSRV_E(port, prio),
  691. &inuse, &maxuse);
  692. }
  693. ocelot_wm_status(ocelot, BUF_P_RSRV_I(port),
  694. &inuse, &maxuse);
  695. ocelot_wm_status(ocelot, BUF_P_RSRV_E(port),
  696. &inuse, &maxuse);
  697. }
  698. break;
  699. case OCELOT_SB_REF:
  700. for (port = 0; port <= ocelot->num_phys_ports; port++) {
  701. for (prio = 0; prio < OCELOT_NUM_TC; prio++) {
  702. ocelot_wm_status(ocelot, REF_Q_RSRV_I(port, prio),
  703. &inuse, &maxuse);
  704. ocelot_wm_status(ocelot, REF_Q_RSRV_E(port, prio),
  705. &inuse, &maxuse);
  706. }
  707. ocelot_wm_status(ocelot, REF_P_RSRV_I(port),
  708. &inuse, &maxuse);
  709. ocelot_wm_status(ocelot, REF_P_RSRV_E(port),
  710. &inuse, &maxuse);
  711. }
  712. break;
  713. default:
  714. return -ENODEV;
  715. }
  716. return 0;
  717. }
  718. EXPORT_SYMBOL(ocelot_sb_occ_max_clear);
  719. /* This retrieves the watermark occupancy for per-port P_RSRV watermarks */
  720. int ocelot_sb_occ_port_pool_get(struct ocelot *ocelot, int port,
  721. unsigned int sb_index, u16 pool_index,
  722. u32 *p_cur, u32 *p_max)
  723. {
  724. int wm_index;
  725. switch (sb_index) {
  726. case OCELOT_SB_BUF:
  727. if (pool_index == OCELOT_SB_POOL_ING)
  728. wm_index = BUF_P_RSRV_I(port);
  729. else
  730. wm_index = BUF_P_RSRV_E(port);
  731. break;
  732. case OCELOT_SB_REF:
  733. if (pool_index == OCELOT_SB_POOL_ING)
  734. wm_index = REF_P_RSRV_I(port);
  735. else
  736. wm_index = REF_P_RSRV_E(port);
  737. break;
  738. default:
  739. return -ENODEV;
  740. }
  741. ocelot_wm_status(ocelot, wm_index, p_cur, p_max);
  742. *p_cur *= ocelot_sb_pool[sb_index].cell_size;
  743. *p_max *= ocelot_sb_pool[sb_index].cell_size;
  744. return 0;
  745. }
  746. EXPORT_SYMBOL(ocelot_sb_occ_port_pool_get);
  747. /* This retrieves the watermark occupancy for per-port-tc Q_RSRV watermarks */
  748. int ocelot_sb_occ_tc_port_bind_get(struct ocelot *ocelot, int port,
  749. unsigned int sb_index, u16 tc_index,
  750. enum devlink_sb_pool_type pool_type,
  751. u32 *p_cur, u32 *p_max)
  752. {
  753. int wm_index;
  754. switch (sb_index) {
  755. case OCELOT_SB_BUF:
  756. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  757. wm_index = BUF_Q_RSRV_I(port, tc_index);
  758. else
  759. wm_index = BUF_Q_RSRV_E(port, tc_index);
  760. break;
  761. case OCELOT_SB_REF:
  762. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  763. wm_index = REF_Q_RSRV_I(port, tc_index);
  764. else
  765. wm_index = REF_Q_RSRV_E(port, tc_index);
  766. break;
  767. default:
  768. return -ENODEV;
  769. }
  770. ocelot_wm_status(ocelot, wm_index, p_cur, p_max);
  771. *p_cur *= ocelot_sb_pool[sb_index].cell_size;
  772. *p_max *= ocelot_sb_pool[sb_index].cell_size;
  773. return 0;
  774. }
  775. EXPORT_SYMBOL(ocelot_sb_occ_tc_port_bind_get);
  776. int ocelot_devlink_sb_register(struct ocelot *ocelot)
  777. {
  778. int err;
  779. err = devlink_sb_register(ocelot->devlink, OCELOT_SB_BUF,
  780. ocelot->packet_buffer_size, 1, 1,
  781. OCELOT_NUM_TC, OCELOT_NUM_TC);
  782. if (err)
  783. return err;
  784. err = devlink_sb_register(ocelot->devlink, OCELOT_SB_REF,
  785. ocelot->num_frame_refs, 1, 1,
  786. OCELOT_NUM_TC, OCELOT_NUM_TC);
  787. if (err) {
  788. devlink_sb_unregister(ocelot->devlink, OCELOT_SB_BUF);
  789. return err;
  790. }
  791. ocelot->pool_size[OCELOT_SB_BUF][OCELOT_SB_POOL_ING] = ocelot->packet_buffer_size;
  792. ocelot->pool_size[OCELOT_SB_BUF][OCELOT_SB_POOL_EGR] = ocelot->packet_buffer_size;
  793. ocelot->pool_size[OCELOT_SB_REF][OCELOT_SB_POOL_ING] = ocelot->num_frame_refs;
  794. ocelot->pool_size[OCELOT_SB_REF][OCELOT_SB_POOL_EGR] = ocelot->num_frame_refs;
  795. ocelot_watermark_init(ocelot);
  796. return 0;
  797. }
  798. EXPORT_SYMBOL(ocelot_devlink_sb_register);
  799. void ocelot_devlink_sb_unregister(struct ocelot *ocelot)
  800. {
  801. devlink_sb_unregister(ocelot->devlink, OCELOT_SB_BUF);
  802. devlink_sb_unregister(ocelot->devlink, OCELOT_SB_REF);
  803. }
  804. EXPORT_SYMBOL(ocelot_devlink_sb_unregister);