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