ocelot_devlink.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  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. /* Pool size and type are fixed up at runtime. Keeping this structure to
  436. * look up the cell size multipliers.
  437. */
  438. static const struct devlink_sb_pool_info ocelot_sb_pool[] = {
  439. [OCELOT_SB_BUF] = {
  440. .cell_size = OCELOT_BUFFER_CELL_SZ,
  441. .threshold_type = DEVLINK_SB_THRESHOLD_TYPE_STATIC,
  442. },
  443. [OCELOT_SB_REF] = {
  444. .cell_size = 1,
  445. .threshold_type = DEVLINK_SB_THRESHOLD_TYPE_STATIC,
  446. },
  447. };
  448. /* Returns the pool size configured through ocelot_sb_pool_set */
  449. int ocelot_sb_pool_get(struct ocelot *ocelot, unsigned int sb_index,
  450. u16 pool_index,
  451. struct devlink_sb_pool_info *pool_info)
  452. {
  453. if (sb_index >= OCELOT_SB_NUM)
  454. return -ENODEV;
  455. if (pool_index >= OCELOT_SB_POOL_NUM)
  456. return -ENODEV;
  457. *pool_info = ocelot_sb_pool[sb_index];
  458. pool_info->size = ocelot->pool_size[sb_index][pool_index];
  459. if (pool_index)
  460. pool_info->pool_type = DEVLINK_SB_POOL_TYPE_INGRESS;
  461. else
  462. pool_info->pool_type = DEVLINK_SB_POOL_TYPE_EGRESS;
  463. return 0;
  464. }
  465. EXPORT_SYMBOL(ocelot_sb_pool_get);
  466. /* The pool size received here configures the total amount of resources used on
  467. * ingress (or on egress, depending upon the pool index). The pool size, minus
  468. * the values for the port and port-tc reservations, is written into the
  469. * COL_SHR(dp=0) sharing watermark.
  470. */
  471. int ocelot_sb_pool_set(struct ocelot *ocelot, unsigned int sb_index,
  472. u16 pool_index, u32 size,
  473. enum devlink_sb_threshold_type threshold_type,
  474. struct netlink_ext_ack *extack)
  475. {
  476. u32 old_pool_size;
  477. int err;
  478. if (sb_index >= OCELOT_SB_NUM) {
  479. NL_SET_ERR_MSG_MOD(extack,
  480. "Invalid sb, use 0 for buffers and 1 for frame references");
  481. return -ENODEV;
  482. }
  483. if (pool_index >= OCELOT_SB_POOL_NUM) {
  484. NL_SET_ERR_MSG_MOD(extack,
  485. "Invalid pool, use 0 for ingress and 1 for egress");
  486. return -ENODEV;
  487. }
  488. if (threshold_type != DEVLINK_SB_THRESHOLD_TYPE_STATIC) {
  489. NL_SET_ERR_MSG_MOD(extack,
  490. "Only static threshold supported");
  491. return -EOPNOTSUPP;
  492. }
  493. old_pool_size = ocelot->pool_size[sb_index][pool_index];
  494. ocelot->pool_size[sb_index][pool_index] = size;
  495. err = ocelot_watermark_validate(ocelot, extack);
  496. if (err) {
  497. ocelot->pool_size[sb_index][pool_index] = old_pool_size;
  498. return err;
  499. }
  500. ocelot_setup_sharing_watermarks(ocelot);
  501. return 0;
  502. }
  503. EXPORT_SYMBOL(ocelot_sb_pool_set);
  504. /* This retrieves the configuration made with ocelot_sb_port_pool_set */
  505. int ocelot_sb_port_pool_get(struct ocelot *ocelot, int port,
  506. unsigned int sb_index, u16 pool_index,
  507. u32 *p_threshold)
  508. {
  509. int wm_index;
  510. switch (sb_index) {
  511. case OCELOT_SB_BUF:
  512. if (pool_index == OCELOT_SB_POOL_ING)
  513. wm_index = BUF_P_RSRV_I(port);
  514. else
  515. wm_index = BUF_P_RSRV_E(port);
  516. break;
  517. case OCELOT_SB_REF:
  518. if (pool_index == OCELOT_SB_POOL_ING)
  519. wm_index = REF_P_RSRV_I(port);
  520. else
  521. wm_index = REF_P_RSRV_E(port);
  522. break;
  523. default:
  524. return -ENODEV;
  525. }
  526. *p_threshold = ocelot_wm_read(ocelot, wm_index);
  527. *p_threshold *= ocelot_sb_pool[sb_index].cell_size;
  528. return 0;
  529. }
  530. EXPORT_SYMBOL(ocelot_sb_port_pool_get);
  531. /* This configures the P_RSRV per-port reserved resource watermark */
  532. int ocelot_sb_port_pool_set(struct ocelot *ocelot, int port,
  533. unsigned int sb_index, u16 pool_index,
  534. u32 threshold, struct netlink_ext_ack *extack)
  535. {
  536. int wm_index, err;
  537. u32 old_thr;
  538. switch (sb_index) {
  539. case OCELOT_SB_BUF:
  540. if (pool_index == OCELOT_SB_POOL_ING)
  541. wm_index = BUF_P_RSRV_I(port);
  542. else
  543. wm_index = BUF_P_RSRV_E(port);
  544. break;
  545. case OCELOT_SB_REF:
  546. if (pool_index == OCELOT_SB_POOL_ING)
  547. wm_index = REF_P_RSRV_I(port);
  548. else
  549. wm_index = REF_P_RSRV_E(port);
  550. break;
  551. default:
  552. NL_SET_ERR_MSG_MOD(extack, "Invalid shared buffer");
  553. return -ENODEV;
  554. }
  555. threshold /= ocelot_sb_pool[sb_index].cell_size;
  556. old_thr = ocelot_wm_read(ocelot, wm_index);
  557. ocelot_wm_write(ocelot, wm_index, threshold);
  558. err = ocelot_watermark_validate(ocelot, extack);
  559. if (err) {
  560. ocelot_wm_write(ocelot, wm_index, old_thr);
  561. return err;
  562. }
  563. ocelot_setup_sharing_watermarks(ocelot);
  564. return 0;
  565. }
  566. EXPORT_SYMBOL(ocelot_sb_port_pool_set);
  567. /* This retrieves the configuration done by ocelot_sb_tc_pool_bind_set */
  568. int ocelot_sb_tc_pool_bind_get(struct ocelot *ocelot, int port,
  569. unsigned int sb_index, u16 tc_index,
  570. enum devlink_sb_pool_type pool_type,
  571. u16 *p_pool_index, u32 *p_threshold)
  572. {
  573. int wm_index;
  574. switch (sb_index) {
  575. case OCELOT_SB_BUF:
  576. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  577. wm_index = BUF_Q_RSRV_I(port, tc_index);
  578. else
  579. wm_index = BUF_Q_RSRV_E(port, tc_index);
  580. break;
  581. case OCELOT_SB_REF:
  582. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  583. wm_index = REF_Q_RSRV_I(port, tc_index);
  584. else
  585. wm_index = REF_Q_RSRV_E(port, tc_index);
  586. break;
  587. default:
  588. return -ENODEV;
  589. }
  590. *p_threshold = ocelot_wm_read(ocelot, wm_index);
  591. *p_threshold *= ocelot_sb_pool[sb_index].cell_size;
  592. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  593. *p_pool_index = 0;
  594. else
  595. *p_pool_index = 1;
  596. return 0;
  597. }
  598. EXPORT_SYMBOL(ocelot_sb_tc_pool_bind_get);
  599. /* This configures the Q_RSRV per-port-tc reserved resource watermark */
  600. int ocelot_sb_tc_pool_bind_set(struct ocelot *ocelot, int port,
  601. unsigned int sb_index, u16 tc_index,
  602. enum devlink_sb_pool_type pool_type,
  603. u16 pool_index, u32 threshold,
  604. struct netlink_ext_ack *extack)
  605. {
  606. int wm_index, err;
  607. u32 old_thr;
  608. /* Paranoid check? */
  609. if (pool_index == OCELOT_SB_POOL_ING &&
  610. pool_type != DEVLINK_SB_POOL_TYPE_INGRESS)
  611. return -EINVAL;
  612. if (pool_index == OCELOT_SB_POOL_EGR &&
  613. pool_type != DEVLINK_SB_POOL_TYPE_EGRESS)
  614. return -EINVAL;
  615. switch (sb_index) {
  616. case OCELOT_SB_BUF:
  617. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  618. wm_index = BUF_Q_RSRV_I(port, tc_index);
  619. else
  620. wm_index = BUF_Q_RSRV_E(port, tc_index);
  621. break;
  622. case OCELOT_SB_REF:
  623. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  624. wm_index = REF_Q_RSRV_I(port, tc_index);
  625. else
  626. wm_index = REF_Q_RSRV_E(port, tc_index);
  627. break;
  628. default:
  629. NL_SET_ERR_MSG_MOD(extack, "Invalid shared buffer");
  630. return -ENODEV;
  631. }
  632. threshold /= ocelot_sb_pool[sb_index].cell_size;
  633. old_thr = ocelot_wm_read(ocelot, wm_index);
  634. ocelot_wm_write(ocelot, wm_index, threshold);
  635. err = ocelot_watermark_validate(ocelot, extack);
  636. if (err) {
  637. ocelot_wm_write(ocelot, wm_index, old_thr);
  638. return err;
  639. }
  640. ocelot_setup_sharing_watermarks(ocelot);
  641. return 0;
  642. }
  643. EXPORT_SYMBOL(ocelot_sb_tc_pool_bind_set);
  644. /* The hardware does not support atomic snapshots, we'll read out the
  645. * occupancy registers individually and have this as just a stub.
  646. */
  647. int ocelot_sb_occ_snapshot(struct ocelot *ocelot, unsigned int sb_index)
  648. {
  649. return 0;
  650. }
  651. EXPORT_SYMBOL(ocelot_sb_occ_snapshot);
  652. /* The watermark occupancy registers are cleared upon read,
  653. * so let's read them.
  654. */
  655. int ocelot_sb_occ_max_clear(struct ocelot *ocelot, unsigned int sb_index)
  656. {
  657. u32 inuse, maxuse;
  658. int port, prio;
  659. switch (sb_index) {
  660. case OCELOT_SB_BUF:
  661. for (port = 0; port <= ocelot->num_phys_ports; port++) {
  662. for (prio = 0; prio < OCELOT_NUM_TC; prio++) {
  663. ocelot_wm_status(ocelot, BUF_Q_RSRV_I(port, prio),
  664. &inuse, &maxuse);
  665. ocelot_wm_status(ocelot, BUF_Q_RSRV_E(port, prio),
  666. &inuse, &maxuse);
  667. }
  668. ocelot_wm_status(ocelot, BUF_P_RSRV_I(port),
  669. &inuse, &maxuse);
  670. ocelot_wm_status(ocelot, BUF_P_RSRV_E(port),
  671. &inuse, &maxuse);
  672. }
  673. break;
  674. case OCELOT_SB_REF:
  675. for (port = 0; port <= ocelot->num_phys_ports; port++) {
  676. for (prio = 0; prio < OCELOT_NUM_TC; prio++) {
  677. ocelot_wm_status(ocelot, REF_Q_RSRV_I(port, prio),
  678. &inuse, &maxuse);
  679. ocelot_wm_status(ocelot, REF_Q_RSRV_E(port, prio),
  680. &inuse, &maxuse);
  681. }
  682. ocelot_wm_status(ocelot, REF_P_RSRV_I(port),
  683. &inuse, &maxuse);
  684. ocelot_wm_status(ocelot, REF_P_RSRV_E(port),
  685. &inuse, &maxuse);
  686. }
  687. break;
  688. default:
  689. return -ENODEV;
  690. }
  691. return 0;
  692. }
  693. EXPORT_SYMBOL(ocelot_sb_occ_max_clear);
  694. /* This retrieves the watermark occupancy for per-port P_RSRV watermarks */
  695. int ocelot_sb_occ_port_pool_get(struct ocelot *ocelot, int port,
  696. unsigned int sb_index, u16 pool_index,
  697. u32 *p_cur, u32 *p_max)
  698. {
  699. int wm_index;
  700. switch (sb_index) {
  701. case OCELOT_SB_BUF:
  702. if (pool_index == OCELOT_SB_POOL_ING)
  703. wm_index = BUF_P_RSRV_I(port);
  704. else
  705. wm_index = BUF_P_RSRV_E(port);
  706. break;
  707. case OCELOT_SB_REF:
  708. if (pool_index == OCELOT_SB_POOL_ING)
  709. wm_index = REF_P_RSRV_I(port);
  710. else
  711. wm_index = REF_P_RSRV_E(port);
  712. break;
  713. default:
  714. return -ENODEV;
  715. }
  716. ocelot_wm_status(ocelot, wm_index, p_cur, p_max);
  717. *p_cur *= ocelot_sb_pool[sb_index].cell_size;
  718. *p_max *= ocelot_sb_pool[sb_index].cell_size;
  719. return 0;
  720. }
  721. EXPORT_SYMBOL(ocelot_sb_occ_port_pool_get);
  722. /* This retrieves the watermark occupancy for per-port-tc Q_RSRV watermarks */
  723. int ocelot_sb_occ_tc_port_bind_get(struct ocelot *ocelot, int port,
  724. unsigned int sb_index, u16 tc_index,
  725. enum devlink_sb_pool_type pool_type,
  726. u32 *p_cur, u32 *p_max)
  727. {
  728. int wm_index;
  729. switch (sb_index) {
  730. case OCELOT_SB_BUF:
  731. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  732. wm_index = BUF_Q_RSRV_I(port, tc_index);
  733. else
  734. wm_index = BUF_Q_RSRV_E(port, tc_index);
  735. break;
  736. case OCELOT_SB_REF:
  737. if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS)
  738. wm_index = REF_Q_RSRV_I(port, tc_index);
  739. else
  740. wm_index = REF_Q_RSRV_E(port, tc_index);
  741. break;
  742. default:
  743. return -ENODEV;
  744. }
  745. ocelot_wm_status(ocelot, wm_index, p_cur, p_max);
  746. *p_cur *= ocelot_sb_pool[sb_index].cell_size;
  747. *p_max *= ocelot_sb_pool[sb_index].cell_size;
  748. return 0;
  749. }
  750. EXPORT_SYMBOL(ocelot_sb_occ_tc_port_bind_get);
  751. int ocelot_devlink_sb_register(struct ocelot *ocelot)
  752. {
  753. int err;
  754. err = devlink_sb_register(ocelot->devlink, OCELOT_SB_BUF,
  755. ocelot->packet_buffer_size, 1, 1,
  756. OCELOT_NUM_TC, OCELOT_NUM_TC);
  757. if (err)
  758. return err;
  759. err = devlink_sb_register(ocelot->devlink, OCELOT_SB_REF,
  760. ocelot->num_frame_refs, 1, 1,
  761. OCELOT_NUM_TC, OCELOT_NUM_TC);
  762. if (err) {
  763. devlink_sb_unregister(ocelot->devlink, OCELOT_SB_BUF);
  764. return err;
  765. }
  766. ocelot->pool_size[OCELOT_SB_BUF][OCELOT_SB_POOL_ING] = ocelot->packet_buffer_size;
  767. ocelot->pool_size[OCELOT_SB_BUF][OCELOT_SB_POOL_EGR] = ocelot->packet_buffer_size;
  768. ocelot->pool_size[OCELOT_SB_REF][OCELOT_SB_POOL_ING] = ocelot->num_frame_refs;
  769. ocelot->pool_size[OCELOT_SB_REF][OCELOT_SB_POOL_EGR] = ocelot->num_frame_refs;
  770. ocelot_watermark_init(ocelot);
  771. return 0;
  772. }
  773. EXPORT_SYMBOL(ocelot_devlink_sb_register);
  774. void ocelot_devlink_sb_unregister(struct ocelot *ocelot)
  775. {
  776. devlink_sb_unregister(ocelot->devlink, OCELOT_SB_BUF);
  777. devlink_sb_unregister(ocelot->devlink, OCELOT_SB_REF);
  778. }
  779. EXPORT_SYMBOL(ocelot_devlink_sb_unregister);