lan966x_tbf.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // SPDX-License-Identifier: GPL-2.0+
  2. #include "lan966x_main.h"
  3. int lan966x_tbf_add(struct lan966x_port *port,
  4. struct tc_tbf_qopt_offload *qopt)
  5. {
  6. struct lan966x *lan966x = port->lan966x;
  7. bool root = qopt->parent == TC_H_ROOT;
  8. u32 queue = 0;
  9. u32 cir, cbs;
  10. u32 se_idx;
  11. if (!root) {
  12. queue = TC_H_MIN(qopt->parent) - 1;
  13. if (queue >= NUM_PRIO_QUEUES)
  14. return -EOPNOTSUPP;
  15. }
  16. if (root)
  17. se_idx = SE_IDX_PORT + port->chip_port;
  18. else
  19. se_idx = SE_IDX_QUEUE + port->chip_port * NUM_PRIO_QUEUES + queue;
  20. cir = div_u64(qopt->replace_params.rate.rate_bytes_ps, 1000) * 8;
  21. cbs = qopt->replace_params.max_size;
  22. /* Rate unit is 100 kbps */
  23. cir = DIV_ROUND_UP(cir, 100);
  24. /* Avoid using zero rate */
  25. cir = cir ?: 1;
  26. /* Burst unit is 4kB */
  27. cbs = DIV_ROUND_UP(cbs, 4096);
  28. /* Avoid using zero burst */
  29. cbs = cbs ?: 1;
  30. /* Check that actually the result can be written */
  31. if (cir > GENMASK(15, 0) ||
  32. cbs > GENMASK(6, 0))
  33. return -EINVAL;
  34. lan_rmw(QSYS_SE_CFG_SE_AVB_ENA_SET(0) |
  35. QSYS_SE_CFG_SE_FRM_MODE_SET(1),
  36. QSYS_SE_CFG_SE_AVB_ENA |
  37. QSYS_SE_CFG_SE_FRM_MODE,
  38. lan966x, QSYS_SE_CFG(se_idx));
  39. lan_wr(QSYS_CIR_CFG_CIR_RATE_SET(cir) |
  40. QSYS_CIR_CFG_CIR_BURST_SET(cbs),
  41. lan966x, QSYS_CIR_CFG(se_idx));
  42. return 0;
  43. }
  44. int lan966x_tbf_del(struct lan966x_port *port,
  45. struct tc_tbf_qopt_offload *qopt)
  46. {
  47. struct lan966x *lan966x = port->lan966x;
  48. bool root = qopt->parent == TC_H_ROOT;
  49. u32 queue = 0;
  50. u32 se_idx;
  51. if (!root) {
  52. queue = TC_H_MIN(qopt->parent) - 1;
  53. if (queue >= NUM_PRIO_QUEUES)
  54. return -EOPNOTSUPP;
  55. }
  56. if (root)
  57. se_idx = SE_IDX_PORT + port->chip_port;
  58. else
  59. se_idx = SE_IDX_QUEUE + port->chip_port * NUM_PRIO_QUEUES + queue;
  60. lan_rmw(QSYS_SE_CFG_SE_AVB_ENA_SET(0) |
  61. QSYS_SE_CFG_SE_FRM_MODE_SET(0),
  62. QSYS_SE_CFG_SE_AVB_ENA |
  63. QSYS_SE_CFG_SE_FRM_MODE,
  64. lan966x, QSYS_SE_CFG(se_idx));
  65. lan_wr(QSYS_CIR_CFG_CIR_RATE_SET(0) |
  66. QSYS_CIR_CFG_CIR_BURST_SET(0),
  67. lan966x, QSYS_CIR_CFG(se_idx));
  68. return 0;
  69. }