705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. From 2551dc9e398c37a15e52122d385c29a8b06be45f Mon Sep 17 00:00:00 2001
  2. From: Maxime Chevallier <[email protected]>
  3. Date: Fri, 26 Nov 2021 12:20:56 +0100
  4. Subject: net: mvneta: Add TC traffic shaping offload
  5. The mvneta controller is able to do some tocken-bucket per-queue traffic
  6. shaping. This commit adds support for setting these using the TC mqprio
  7. interface.
  8. The token-bucket parameters are customisable, but the current
  9. implementation configures them to have a 10kbps resolution for the
  10. rate limitation, since it allows to cover the whole range of max_rate
  11. values from 10kbps to 5Gbps with 10kbps increments.
  12. Signed-off-by: Maxime Chevallier <[email protected]>
  13. Signed-off-by: David S. Miller <[email protected]>
  14. ---
  15. drivers/net/ethernet/marvell/mvneta.c | 120 +++++++++++++++++++++++++++++++++-
  16. 1 file changed, 119 insertions(+), 1 deletion(-)
  17. (limited to 'drivers/net/ethernet/marvell/mvneta.c')
  18. --- a/drivers/net/ethernet/marvell/mvneta.c
  19. +++ b/drivers/net/ethernet/marvell/mvneta.c
  20. @@ -248,12 +248,39 @@
  21. #define MVNETA_TXQ_SENT_DESC_MASK 0x3fff0000
  22. #define MVNETA_PORT_TX_RESET 0x3cf0
  23. #define MVNETA_PORT_TX_DMA_RESET BIT(0)
  24. +#define MVNETA_TXQ_CMD1_REG 0x3e00
  25. +#define MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 BIT(3)
  26. +#define MVNETA_TXQ_CMD1_BW_LIM_EN BIT(0)
  27. +#define MVNETA_REFILL_NUM_CLK_REG 0x3e08
  28. +#define MVNETA_REFILL_MAX_NUM_CLK 0x0000ffff
  29. #define MVNETA_TX_MTU 0x3e0c
  30. #define MVNETA_TX_TOKEN_SIZE 0x3e14
  31. #define MVNETA_TX_TOKEN_SIZE_MAX 0xffffffff
  32. +#define MVNETA_TXQ_BUCKET_REFILL_REG(q) (0x3e20 + ((q) << 2))
  33. +#define MVNETA_TXQ_BUCKET_REFILL_PERIOD_MASK 0x3ff00000
  34. +#define MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT 20
  35. +#define MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX 0x0007ffff
  36. #define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2))
  37. #define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff
  38. +/* The values of the bucket refill base period and refill period are taken from
  39. + * the reference manual, and adds up to a base resolution of 10Kbps. This allows
  40. + * to cover all rate-limit values from 10Kbps up to 5Gbps
  41. + */
  42. +
  43. +/* Base period for the rate limit algorithm */
  44. +#define MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS 100
  45. +
  46. +/* Number of Base Period to wait between each bucket refill */
  47. +#define MVNETA_TXQ_BUCKET_REFILL_PERIOD 1000
  48. +
  49. +/* The base resolution for rate limiting, in bps. Any max_rate value should be
  50. + * a multiple of that value.
  51. + */
  52. +#define MVNETA_TXQ_RATE_LIMIT_RESOLUTION (NSEC_PER_SEC / \
  53. + (MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS * \
  54. + MVNETA_TXQ_BUCKET_REFILL_PERIOD))
  55. +
  56. #define MVNETA_LPI_CTRL_0 0x2cc0
  57. #define MVNETA_LPI_CTRL_1 0x2cc4
  58. #define MVNETA_LPI_REQUEST_ENABLE BIT(0)
  59. @@ -4964,11 +4991,74 @@ static void mvneta_map_vlan_prio_to_rxq(
  60. mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, val);
  61. }
  62. +static int mvneta_enable_per_queue_rate_limit(struct mvneta_port *pp)
  63. +{
  64. + unsigned long core_clk_rate;
  65. + u32 refill_cycles;
  66. + u32 val;
  67. +
  68. + core_clk_rate = clk_get_rate(pp->clk);
  69. + if (!core_clk_rate)
  70. + return -EINVAL;
  71. +
  72. + refill_cycles = MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS /
  73. + (NSEC_PER_SEC / core_clk_rate);
  74. +
  75. + if (refill_cycles > MVNETA_REFILL_MAX_NUM_CLK)
  76. + return -EINVAL;
  77. +
  78. + /* Enable bw limit algorithm version 3 */
  79. + val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG);
  80. + val &= ~(MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN);
  81. + mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val);
  82. +
  83. + /* Set the base refill rate */
  84. + mvreg_write(pp, MVNETA_REFILL_NUM_CLK_REG, refill_cycles);
  85. +
  86. + return 0;
  87. +}
  88. +
  89. +static void mvneta_disable_per_queue_rate_limit(struct mvneta_port *pp)
  90. +{
  91. + u32 val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG);
  92. +
  93. + val |= (MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN);
  94. + mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val);
  95. +}
  96. +
  97. +static int mvneta_setup_queue_rates(struct mvneta_port *pp, int queue,
  98. + u64 min_rate, u64 max_rate)
  99. +{
  100. + u32 refill_val, rem;
  101. + u32 val = 0;
  102. +
  103. + /* Convert to from Bps to bps */
  104. + max_rate *= 8;
  105. +
  106. + if (min_rate)
  107. + return -EINVAL;
  108. +
  109. + refill_val = div_u64_rem(max_rate, MVNETA_TXQ_RATE_LIMIT_RESOLUTION,
  110. + &rem);
  111. +
  112. + if (rem || !refill_val ||
  113. + refill_val > MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX)
  114. + return -EINVAL;
  115. +
  116. + val = refill_val;
  117. + val |= (MVNETA_TXQ_BUCKET_REFILL_PERIOD <<
  118. + MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT);
  119. +
  120. + mvreg_write(pp, MVNETA_TXQ_BUCKET_REFILL_REG(queue), val);
  121. +
  122. + return 0;
  123. +}
  124. +
  125. static int mvneta_setup_mqprio(struct net_device *dev,
  126. struct tc_mqprio_qopt_offload *mqprio)
  127. {
  128. struct mvneta_port *pp = netdev_priv(dev);
  129. - int rxq, tc;
  130. + int rxq, txq, tc, ret;
  131. u8 num_tc;
  132. if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS)
  133. @@ -4982,6 +5072,7 @@ static int mvneta_setup_mqprio(struct ne
  134. mvneta_clear_rx_prio_map(pp);
  135. if (!num_tc) {
  136. + mvneta_disable_per_queue_rate_limit(pp);
  137. netdev_reset_tc(dev);
  138. return 0;
  139. }
  140. @@ -5002,6 +5093,33 @@ static int mvneta_setup_mqprio(struct ne
  141. }
  142. }
  143. + if (mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE) {
  144. + mvneta_disable_per_queue_rate_limit(pp);
  145. + return 0;
  146. + }
  147. +
  148. + if (mqprio->qopt.num_tc > txq_number)
  149. + return -EINVAL;
  150. +
  151. + ret = mvneta_enable_per_queue_rate_limit(pp);
  152. + if (ret)
  153. + return ret;
  154. +
  155. + for (tc = 0; tc < mqprio->qopt.num_tc; tc++) {
  156. + for (txq = mqprio->qopt.offset[tc];
  157. + txq < mqprio->qopt.count[tc] + mqprio->qopt.offset[tc];
  158. + txq++) {
  159. + if (txq >= txq_number)
  160. + return -EINVAL;
  161. +
  162. + ret = mvneta_setup_queue_rates(pp, txq,
  163. + mqprio->min_rate[tc],
  164. + mqprio->max_rate[tc]);
  165. + if (ret)
  166. + return ret;
  167. + }
  168. + }
  169. +
  170. return 0;
  171. }