lan966x_police.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // SPDX-License-Identifier: GPL-2.0+
  2. #include "lan966x_main.h"
  3. /* 0-8 : 9 port policers */
  4. #define POL_IDX_PORT 0
  5. /* Policer order: Serial (QoS -> Port -> VCAP) */
  6. #define POL_ORDER 0x1d3
  7. struct lan966x_tc_policer {
  8. /* kilobit per second */
  9. u32 rate;
  10. /* bytes */
  11. u32 burst;
  12. };
  13. static int lan966x_police_add(struct lan966x_port *port,
  14. struct lan966x_tc_policer *pol,
  15. u16 pol_idx)
  16. {
  17. struct lan966x *lan966x = port->lan966x;
  18. /* Rate unit is 33 1/3 kpps */
  19. pol->rate = DIV_ROUND_UP(pol->rate * 3, 100);
  20. /* Avoid zero burst size */
  21. pol->burst = pol->burst ?: 1;
  22. /* Unit is 4kB */
  23. pol->burst = DIV_ROUND_UP(pol->burst, 4096);
  24. if (pol->rate > GENMASK(15, 0) ||
  25. pol->burst > GENMASK(6, 0))
  26. return -EINVAL;
  27. lan_wr(ANA_POL_MODE_DROP_ON_YELLOW_ENA_SET(0) |
  28. ANA_POL_MODE_MARK_ALL_FRMS_RED_ENA_SET(0) |
  29. ANA_POL_MODE_IPG_SIZE_SET(20) |
  30. ANA_POL_MODE_FRM_MODE_SET(1) |
  31. ANA_POL_MODE_OVERSHOOT_ENA_SET(1),
  32. lan966x, ANA_POL_MODE(pol_idx));
  33. lan_wr(ANA_POL_PIR_STATE_PIR_LVL_SET(0),
  34. lan966x, ANA_POL_PIR_STATE(pol_idx));
  35. lan_wr(ANA_POL_PIR_CFG_PIR_RATE_SET(pol->rate) |
  36. ANA_POL_PIR_CFG_PIR_BURST_SET(pol->burst),
  37. lan966x, ANA_POL_PIR_CFG(pol_idx));
  38. return 0;
  39. }
  40. static void lan966x_police_del(struct lan966x_port *port, u16 pol_idx)
  41. {
  42. struct lan966x *lan966x = port->lan966x;
  43. lan_wr(ANA_POL_MODE_DROP_ON_YELLOW_ENA_SET(0) |
  44. ANA_POL_MODE_MARK_ALL_FRMS_RED_ENA_SET(0) |
  45. ANA_POL_MODE_IPG_SIZE_SET(20) |
  46. ANA_POL_MODE_FRM_MODE_SET(2) |
  47. ANA_POL_MODE_OVERSHOOT_ENA_SET(1),
  48. lan966x, ANA_POL_MODE(pol_idx));
  49. lan_wr(ANA_POL_PIR_STATE_PIR_LVL_SET(0),
  50. lan966x, ANA_POL_PIR_STATE(pol_idx));
  51. lan_wr(ANA_POL_PIR_CFG_PIR_RATE_SET(GENMASK(14, 0)) |
  52. ANA_POL_PIR_CFG_PIR_BURST_SET(0),
  53. lan966x, ANA_POL_PIR_CFG(pol_idx));
  54. }
  55. static int lan966x_police_validate(struct lan966x_port *port,
  56. const struct flow_action *action,
  57. const struct flow_action_entry *act,
  58. unsigned long police_id,
  59. bool ingress,
  60. struct netlink_ext_ack *extack)
  61. {
  62. if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
  63. NL_SET_ERR_MSG_MOD(extack,
  64. "Offload not supported when exceed action is not drop");
  65. return -EOPNOTSUPP;
  66. }
  67. if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
  68. act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
  69. NL_SET_ERR_MSG_MOD(extack,
  70. "Offload not supported when conform action is not pipe or ok");
  71. return -EOPNOTSUPP;
  72. }
  73. if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
  74. !flow_action_is_last_entry(action, act)) {
  75. NL_SET_ERR_MSG_MOD(extack,
  76. "Offload not supported when conform action is ok, but action is not last");
  77. return -EOPNOTSUPP;
  78. }
  79. if (act->police.peakrate_bytes_ps ||
  80. act->police.avrate || act->police.overhead) {
  81. NL_SET_ERR_MSG_MOD(extack,
  82. "Offload not supported when peakrate/avrate/overhead is configured");
  83. return -EOPNOTSUPP;
  84. }
  85. if (act->police.rate_pkt_ps) {
  86. NL_SET_ERR_MSG_MOD(extack,
  87. "QoS offload not support packets per second");
  88. return -EOPNOTSUPP;
  89. }
  90. if (!ingress) {
  91. NL_SET_ERR_MSG_MOD(extack,
  92. "Policer is not supported on egress");
  93. return -EOPNOTSUPP;
  94. }
  95. if (port->tc.ingress_shared_block) {
  96. NL_SET_ERR_MSG_MOD(extack,
  97. "Policer is not supported on shared ingress blocks");
  98. return -EOPNOTSUPP;
  99. }
  100. if (port->tc.police_id && port->tc.police_id != police_id) {
  101. NL_SET_ERR_MSG_MOD(extack,
  102. "Only one policer per port is supported");
  103. return -EEXIST;
  104. }
  105. return 0;
  106. }
  107. int lan966x_police_port_add(struct lan966x_port *port,
  108. struct flow_action *action,
  109. struct flow_action_entry *act,
  110. unsigned long police_id,
  111. bool ingress,
  112. struct netlink_ext_ack *extack)
  113. {
  114. struct lan966x *lan966x = port->lan966x;
  115. struct rtnl_link_stats64 new_stats;
  116. struct lan966x_tc_policer pol;
  117. struct flow_stats *old_stats;
  118. int err;
  119. err = lan966x_police_validate(port, action, act, police_id, ingress,
  120. extack);
  121. if (err)
  122. return err;
  123. memset(&pol, 0, sizeof(pol));
  124. pol.rate = div_u64(act->police.rate_bytes_ps, 1000) * 8;
  125. pol.burst = act->police.burst;
  126. err = lan966x_police_add(port, &pol, POL_IDX_PORT + port->chip_port);
  127. if (err) {
  128. NL_SET_ERR_MSG_MOD(extack,
  129. "Failed to add policer to port");
  130. return err;
  131. }
  132. lan_rmw(ANA_POL_CFG_PORT_POL_ENA_SET(1) |
  133. ANA_POL_CFG_POL_ORDER_SET(POL_ORDER),
  134. ANA_POL_CFG_PORT_POL_ENA |
  135. ANA_POL_CFG_POL_ORDER,
  136. lan966x, ANA_POL_CFG(port->chip_port));
  137. port->tc.police_id = police_id;
  138. /* Setup initial stats */
  139. old_stats = &port->tc.police_stat;
  140. lan966x_stats_get(port->dev, &new_stats);
  141. old_stats->bytes = new_stats.rx_bytes;
  142. old_stats->pkts = new_stats.rx_packets;
  143. old_stats->drops = new_stats.rx_dropped;
  144. old_stats->lastused = jiffies;
  145. return 0;
  146. }
  147. int lan966x_police_port_del(struct lan966x_port *port,
  148. unsigned long police_id,
  149. struct netlink_ext_ack *extack)
  150. {
  151. struct lan966x *lan966x = port->lan966x;
  152. if (port->tc.police_id != police_id) {
  153. NL_SET_ERR_MSG_MOD(extack,
  154. "Invalid policer id");
  155. return -EINVAL;
  156. }
  157. lan966x_police_del(port, POL_IDX_PORT + port->chip_port);
  158. lan_rmw(ANA_POL_CFG_PORT_POL_ENA_SET(0) |
  159. ANA_POL_CFG_POL_ORDER_SET(POL_ORDER),
  160. ANA_POL_CFG_PORT_POL_ENA |
  161. ANA_POL_CFG_POL_ORDER,
  162. lan966x, ANA_POL_CFG(port->chip_port));
  163. port->tc.police_id = 0;
  164. return 0;
  165. }
  166. void lan966x_police_port_stats(struct lan966x_port *port,
  167. struct flow_stats *stats)
  168. {
  169. struct rtnl_link_stats64 new_stats;
  170. struct flow_stats *old_stats;
  171. old_stats = &port->tc.police_stat;
  172. lan966x_stats_get(port->dev, &new_stats);
  173. flow_stats_update(stats,
  174. new_stats.rx_bytes - old_stats->bytes,
  175. new_stats.rx_packets - old_stats->pkts,
  176. new_stats.rx_dropped - old_stats->drops,
  177. old_stats->lastused,
  178. FLOW_ACTION_HW_STATS_IMMEDIATE);
  179. old_stats->bytes = new_stats.rx_bytes;
  180. old_stats->pkts = new_stats.rx_packets;
  181. old_stats->drops = new_stats.rx_dropped;
  182. old_stats->lastused = jiffies;
  183. }