ocelot_police.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // SPDX-License-Identifier: (GPL-2.0 OR MIT)
  2. /* Microsemi Ocelot Switch driver
  3. *
  4. * Copyright (c) 2019 Microsemi Corporation
  5. */
  6. #include "ocelot_police.h"
  7. enum mscc_qos_rate_mode {
  8. MSCC_QOS_RATE_MODE_DISABLED, /* Policer/shaper disabled */
  9. MSCC_QOS_RATE_MODE_LINE, /* Measure line rate in kbps incl. IPG */
  10. MSCC_QOS_RATE_MODE_DATA, /* Measures data rate in kbps excl. IPG */
  11. MSCC_QOS_RATE_MODE_FRAME, /* Measures frame rate in fps */
  12. __MSCC_QOS_RATE_MODE_END,
  13. NUM_MSCC_QOS_RATE_MODE = __MSCC_QOS_RATE_MODE_END,
  14. MSCC_QOS_RATE_MODE_MAX = __MSCC_QOS_RATE_MODE_END - 1,
  15. };
  16. /* Types for ANA:POL[0-192]:POL_MODE_CFG.FRM_MODE */
  17. #define POL_MODE_LINERATE 0 /* Incl IPG. Unit: 33 1/3 kbps, 4096 bytes */
  18. #define POL_MODE_DATARATE 1 /* Excl IPG. Unit: 33 1/3 kbps, 4096 bytes */
  19. #define POL_MODE_FRMRATE_HI 2 /* Unit: 33 1/3 fps, 32.8 frames */
  20. #define POL_MODE_FRMRATE_LO 3 /* Unit: 1/3 fps, 0.3 frames */
  21. /* Policer indexes */
  22. #define POL_IX_PORT 0 /* 0-11 : Port policers */
  23. #define POL_IX_QUEUE 32 /* 32-127 : Queue policers */
  24. /* Default policer order */
  25. #define POL_ORDER 0x1d3 /* Ocelot policer order: Serial (QoS -> Port -> VCAP) */
  26. struct qos_policer_conf {
  27. enum mscc_qos_rate_mode mode;
  28. bool dlb; /* Enable DLB (dual leaky bucket mode */
  29. bool cf; /* Coupling flag (ignored in SLB mode) */
  30. u32 cir; /* CIR in kbps/fps (ignored in SLB mode) */
  31. u32 cbs; /* CBS in bytes/frames (ignored in SLB mode) */
  32. u32 pir; /* PIR in kbps/fps */
  33. u32 pbs; /* PBS in bytes/frames */
  34. u8 ipg; /* Size of IPG when MSCC_QOS_RATE_MODE_LINE is chosen */
  35. };
  36. static int qos_policer_conf_set(struct ocelot_port *port, u32 pol_ix,
  37. struct qos_policer_conf *conf)
  38. {
  39. u32 cf = 0, cir_ena = 0, frm_mode = POL_MODE_LINERATE;
  40. u32 cir = 0, cbs = 0, pir = 0, pbs = 0;
  41. bool cir_discard = 0, pir_discard = 0;
  42. struct ocelot *ocelot = port->ocelot;
  43. u32 pbs_max = 0, cbs_max = 0;
  44. u8 ipg = 20;
  45. u32 value;
  46. pir = conf->pir;
  47. pbs = conf->pbs;
  48. switch (conf->mode) {
  49. case MSCC_QOS_RATE_MODE_LINE:
  50. case MSCC_QOS_RATE_MODE_DATA:
  51. if (conf->mode == MSCC_QOS_RATE_MODE_LINE) {
  52. frm_mode = POL_MODE_LINERATE;
  53. ipg = min_t(u8, GENMASK(4, 0), conf->ipg);
  54. } else {
  55. frm_mode = POL_MODE_DATARATE;
  56. }
  57. if (conf->dlb) {
  58. cir_ena = 1;
  59. cir = conf->cir;
  60. cbs = conf->cbs;
  61. if (cir == 0 && cbs == 0) {
  62. /* Discard cir frames */
  63. cir_discard = 1;
  64. } else {
  65. cir = DIV_ROUND_UP(cir, 100);
  66. cir *= 3; /* 33 1/3 kbps */
  67. cbs = DIV_ROUND_UP(cbs, 4096);
  68. cbs = (cbs ? cbs : 1); /* No zero burst size */
  69. cbs_max = 60; /* Limit burst size */
  70. cf = conf->cf;
  71. if (cf)
  72. pir += conf->cir;
  73. }
  74. }
  75. if (pir == 0 && pbs == 0) {
  76. /* Discard PIR frames */
  77. pir_discard = 1;
  78. } else {
  79. pir = DIV_ROUND_UP(pir, 100);
  80. pir *= 3; /* 33 1/3 kbps */
  81. pbs = DIV_ROUND_UP(pbs, 4096);
  82. pbs = (pbs ? pbs : 1); /* No zero burst size */
  83. pbs_max = 60; /* Limit burst size */
  84. }
  85. break;
  86. case MSCC_QOS_RATE_MODE_FRAME:
  87. if (pir >= 100) {
  88. frm_mode = POL_MODE_FRMRATE_HI;
  89. pir = DIV_ROUND_UP(pir, 100);
  90. pir *= 3; /* 33 1/3 fps */
  91. pbs = (pbs * 10) / 328; /* 32.8 frames */
  92. pbs = (pbs ? pbs : 1); /* No zero burst size */
  93. pbs_max = GENMASK(6, 0); /* Limit burst size */
  94. } else {
  95. frm_mode = POL_MODE_FRMRATE_LO;
  96. if (pir == 0 && pbs == 0) {
  97. /* Discard all frames */
  98. pir_discard = 1;
  99. cir_discard = 1;
  100. } else {
  101. pir *= 3; /* 1/3 fps */
  102. pbs = (pbs * 10) / 3; /* 0.3 frames */
  103. pbs = (pbs ? pbs : 1); /* No zero burst size */
  104. pbs_max = 61; /* Limit burst size */
  105. }
  106. }
  107. break;
  108. default: /* MSCC_QOS_RATE_MODE_DISABLED */
  109. /* Disable policer using maximum rate and zero burst */
  110. pir = GENMASK(15, 0);
  111. pbs = 0;
  112. break;
  113. }
  114. /* Check limits */
  115. if (pir > GENMASK(15, 0)) {
  116. netdev_err(port->dev, "Invalid pir\n");
  117. return -EINVAL;
  118. }
  119. if (cir > GENMASK(15, 0)) {
  120. netdev_err(port->dev, "Invalid cir\n");
  121. return -EINVAL;
  122. }
  123. if (pbs > pbs_max) {
  124. netdev_err(port->dev, "Invalid pbs\n");
  125. return -EINVAL;
  126. }
  127. if (cbs > cbs_max) {
  128. netdev_err(port->dev, "Invalid cbs\n");
  129. return -EINVAL;
  130. }
  131. value = (ANA_POL_MODE_CFG_IPG_SIZE(ipg) |
  132. ANA_POL_MODE_CFG_FRM_MODE(frm_mode) |
  133. (cf ? ANA_POL_MODE_CFG_DLB_COUPLED : 0) |
  134. (cir_ena ? ANA_POL_MODE_CFG_CIR_ENA : 0) |
  135. ANA_POL_MODE_CFG_OVERSHOOT_ENA);
  136. ocelot_write_gix(ocelot, value, ANA_POL_MODE_CFG, pol_ix);
  137. ocelot_write_gix(ocelot,
  138. ANA_POL_PIR_CFG_PIR_RATE(pir) |
  139. ANA_POL_PIR_CFG_PIR_BURST(pbs),
  140. ANA_POL_PIR_CFG, pol_ix);
  141. ocelot_write_gix(ocelot,
  142. (pir_discard ? GENMASK(22, 0) : 0),
  143. ANA_POL_PIR_STATE, pol_ix);
  144. ocelot_write_gix(ocelot,
  145. ANA_POL_CIR_CFG_CIR_RATE(cir) |
  146. ANA_POL_CIR_CFG_CIR_BURST(cbs),
  147. ANA_POL_CIR_CFG, pol_ix);
  148. ocelot_write_gix(ocelot,
  149. (cir_discard ? GENMASK(22, 0) : 0),
  150. ANA_POL_CIR_STATE, pol_ix);
  151. return 0;
  152. }
  153. int ocelot_port_policer_add(struct ocelot_port *port,
  154. struct ocelot_policer *pol)
  155. {
  156. struct ocelot *ocelot = port->ocelot;
  157. struct qos_policer_conf pp = { 0 };
  158. int err;
  159. if (!pol)
  160. return -EINVAL;
  161. pp.mode = MSCC_QOS_RATE_MODE_DATA;
  162. pp.pir = pol->rate;
  163. pp.pbs = pol->burst;
  164. netdev_dbg(port->dev,
  165. "%s: port %u pir %u kbps, pbs %u bytes\n",
  166. __func__, port->chip_port, pp.pir, pp.pbs);
  167. err = qos_policer_conf_set(port, POL_IX_PORT + port->chip_port, &pp);
  168. if (err)
  169. return err;
  170. ocelot_rmw_gix(ocelot,
  171. ANA_PORT_POL_CFG_PORT_POL_ENA |
  172. ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER),
  173. ANA_PORT_POL_CFG_PORT_POL_ENA |
  174. ANA_PORT_POL_CFG_POL_ORDER_M,
  175. ANA_PORT_POL_CFG, port->chip_port);
  176. return 0;
  177. }
  178. int ocelot_port_policer_del(struct ocelot_port *port)
  179. {
  180. struct ocelot *ocelot = port->ocelot;
  181. struct qos_policer_conf pp = { 0 };
  182. int err;
  183. netdev_dbg(port->dev, "%s: port %u\n", __func__, port->chip_port);
  184. pp.mode = MSCC_QOS_RATE_MODE_DISABLED;
  185. err = qos_policer_conf_set(port, POL_IX_PORT + port->chip_port, &pp);
  186. if (err)
  187. return err;
  188. ocelot_rmw_gix(ocelot,
  189. ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER),
  190. ANA_PORT_POL_CFG_PORT_POL_ENA |
  191. ANA_PORT_POL_CFG_POL_ORDER_M,
  192. ANA_PORT_POL_CFG, port->chip_port);
  193. return 0;
  194. }