7
7
*/
8
8
9
9
#include <linux/pm_runtime.h>
10
+ #include <linux/math.h>
10
11
#include <linux/time.h>
12
+ #include <linux/units.h>
11
13
#include <net/pkt_cls.h>
12
14
13
15
#include "am65-cpsw-nuss.h"
14
16
#include "am65-cpsw-qos.h"
15
17
#include "am65-cpts.h"
16
18
#include "cpsw_ale.h"
17
19
20
+ #define TO_MBPS (x ) DIV_ROUND_UP((x), BYTES_PER_MBIT)
21
+
18
22
enum timer_act {
19
23
TACT_PROG , /* need program timer */
20
24
TACT_NEED_STOP , /* need stop first */
@@ -31,6 +35,232 @@ am65_cpsw_qos_tx_rate_calc(u32 rate_mbps, unsigned long bus_freq)
31
35
return ir ;
32
36
}
33
37
38
+ static void am65_cpsw_tx_pn_shaper_reset (struct am65_cpsw_port * port )
39
+ {
40
+ int prio ;
41
+
42
+ for (prio = 0 ; prio < AM65_CPSW_PN_FIFO_PRIO_NUM ; prio ++ ) {
43
+ writel (0 , port -> port_base + AM65_CPSW_PN_REG_PRI_CIR (prio ));
44
+ writel (0 , port -> port_base + AM65_CPSW_PN_REG_PRI_EIR (prio ));
45
+ }
46
+ }
47
+
48
+ static void am65_cpsw_tx_pn_shaper_apply (struct am65_cpsw_port * port )
49
+ {
50
+ struct am65_cpsw_mqprio * p_mqprio = & port -> qos .mqprio ;
51
+ struct am65_cpsw_common * common = port -> common ;
52
+ struct tc_mqprio_qopt_offload * mqprio ;
53
+ bool enable , shaper_susp = false;
54
+ u32 rate_mbps ;
55
+ int tc , prio ;
56
+
57
+ mqprio = & p_mqprio -> mqprio_hw ;
58
+ /* takes care of no link case as well */
59
+ if (p_mqprio -> max_rate_total > port -> qos .link_speed )
60
+ shaper_susp = true;
61
+
62
+ am65_cpsw_tx_pn_shaper_reset (port );
63
+
64
+ enable = p_mqprio -> shaper_en && !shaper_susp ;
65
+ if (!enable )
66
+ return ;
67
+
68
+ /* Rate limit is specified per Traffic Class but
69
+ * for CPSW, rate limit can be applied per priority
70
+ * at port FIFO.
71
+ *
72
+ * We have assigned the same priority (TCn) to all queues
73
+ * of a Traffic Class so they share the same shaper
74
+ * bandwidth.
75
+ */
76
+ for (tc = 0 ; tc < mqprio -> qopt .num_tc ; tc ++ ) {
77
+ prio = tc ;
78
+
79
+ rate_mbps = TO_MBPS (mqprio -> min_rate [tc ]);
80
+ rate_mbps = am65_cpsw_qos_tx_rate_calc (rate_mbps ,
81
+ common -> bus_freq );
82
+ writel (rate_mbps ,
83
+ port -> port_base + AM65_CPSW_PN_REG_PRI_CIR (prio ));
84
+
85
+ rate_mbps = 0 ;
86
+
87
+ if (mqprio -> max_rate [tc ]) {
88
+ rate_mbps = mqprio -> max_rate [tc ] - mqprio -> min_rate [tc ];
89
+ rate_mbps = TO_MBPS (rate_mbps );
90
+ rate_mbps = am65_cpsw_qos_tx_rate_calc (rate_mbps ,
91
+ common -> bus_freq );
92
+ }
93
+
94
+ writel (rate_mbps ,
95
+ port -> port_base + AM65_CPSW_PN_REG_PRI_EIR (prio ));
96
+ }
97
+ }
98
+
99
+ static int am65_cpsw_mqprio_verify_shaper (struct am65_cpsw_port * port ,
100
+ struct tc_mqprio_qopt_offload * mqprio )
101
+ {
102
+ struct am65_cpsw_mqprio * p_mqprio = & port -> qos .mqprio ;
103
+ struct netlink_ext_ack * extack = mqprio -> extack ;
104
+ u64 min_rate_total = 0 , max_rate_total = 0 ;
105
+ u32 min_rate_msk = 0 , max_rate_msk = 0 ;
106
+ bool has_min_rate , has_max_rate ;
107
+ int num_tc , i ;
108
+
109
+ if (!(mqprio -> flags & TC_MQPRIO_F_SHAPER ))
110
+ return 0 ;
111
+
112
+ if (mqprio -> shaper != TC_MQPRIO_SHAPER_BW_RATE )
113
+ return 0 ;
114
+
115
+ has_min_rate = !!(mqprio -> flags & TC_MQPRIO_F_MIN_RATE );
116
+ has_max_rate = !!(mqprio -> flags & TC_MQPRIO_F_MAX_RATE );
117
+
118
+ if (!has_min_rate && has_max_rate ) {
119
+ NL_SET_ERR_MSG_MOD (extack , "min_rate is required with max_rate" );
120
+ return - EOPNOTSUPP ;
121
+ }
122
+
123
+ if (!has_min_rate )
124
+ return 0 ;
125
+
126
+ num_tc = mqprio -> qopt .num_tc ;
127
+
128
+ for (i = num_tc - 1 ; i >= 0 ; i -- ) {
129
+ u32 ch_msk ;
130
+
131
+ if (mqprio -> min_rate [i ])
132
+ min_rate_msk |= BIT (i );
133
+ min_rate_total += mqprio -> min_rate [i ];
134
+
135
+ if (has_max_rate ) {
136
+ if (mqprio -> max_rate [i ])
137
+ max_rate_msk |= BIT (i );
138
+ max_rate_total += mqprio -> max_rate [i ];
139
+
140
+ if (!mqprio -> min_rate [i ] && mqprio -> max_rate [i ]) {
141
+ NL_SET_ERR_MSG_FMT_MOD (extack ,
142
+ "TX tc%d rate max>0 but min=0" ,
143
+ i );
144
+ return - EINVAL ;
145
+ }
146
+
147
+ if (mqprio -> max_rate [i ] &&
148
+ mqprio -> max_rate [i ] < mqprio -> min_rate [i ]) {
149
+ NL_SET_ERR_MSG_FMT_MOD (extack ,
150
+ "TX tc%d rate min(%llu)>max(%llu)" ,
151
+ i , mqprio -> min_rate [i ],
152
+ mqprio -> max_rate [i ]);
153
+ return - EINVAL ;
154
+ }
155
+ }
156
+
157
+ ch_msk = GENMASK (num_tc - 1 , i );
158
+ if ((min_rate_msk & BIT (i )) && (min_rate_msk ^ ch_msk )) {
159
+ NL_SET_ERR_MSG_FMT_MOD (extack ,
160
+ "Min rate must be set sequentially hi->lo tx_rate_msk%x" ,
161
+ min_rate_msk );
162
+ return - EINVAL ;
163
+ }
164
+
165
+ if ((max_rate_msk & BIT (i )) && (max_rate_msk ^ ch_msk )) {
166
+ NL_SET_ERR_MSG_FMT_MOD (extack ,
167
+ "Max rate must be set sequentially hi->lo tx_rate_msk%x" ,
168
+ max_rate_msk );
169
+ return - EINVAL ;
170
+ }
171
+ }
172
+
173
+ min_rate_total = TO_MBPS (min_rate_total );
174
+ max_rate_total = TO_MBPS (max_rate_total );
175
+
176
+ p_mqprio -> shaper_en = true;
177
+ p_mqprio -> max_rate_total = max_t (u64 , min_rate_total , max_rate_total );
178
+
179
+ return 0 ;
180
+ }
181
+
182
+ static void am65_cpsw_reset_tc_mqprio (struct net_device * ndev )
183
+ {
184
+ struct am65_cpsw_port * port = am65_ndev_to_port (ndev );
185
+ struct am65_cpsw_mqprio * p_mqprio = & port -> qos .mqprio ;
186
+
187
+ p_mqprio -> shaper_en = false;
188
+ p_mqprio -> max_rate_total = 0 ;
189
+
190
+ am65_cpsw_tx_pn_shaper_reset (port );
191
+ netdev_reset_tc (ndev );
192
+
193
+ /* Reset all Queue priorities to 0 */
194
+ writel (0 , port -> port_base + AM65_CPSW_PN_REG_TX_PRI_MAP );
195
+ }
196
+
197
+ static int am65_cpsw_setup_mqprio (struct net_device * ndev , void * type_data )
198
+ {
199
+ struct am65_cpsw_port * port = am65_ndev_to_port (ndev );
200
+ struct am65_cpsw_mqprio * p_mqprio = & port -> qos .mqprio ;
201
+ struct tc_mqprio_qopt_offload * mqprio = type_data ;
202
+ struct am65_cpsw_common * common = port -> common ;
203
+ struct tc_mqprio_qopt * qopt = & mqprio -> qopt ;
204
+ int i , tc , offset , count , prio , ret ;
205
+ u8 num_tc = qopt -> num_tc ;
206
+ u32 tx_prio_map = 0 ;
207
+
208
+ memcpy (& p_mqprio -> mqprio_hw , mqprio , sizeof (* mqprio ));
209
+
210
+ ret = pm_runtime_get_sync (common -> dev );
211
+ if (ret < 0 ) {
212
+ pm_runtime_put_noidle (common -> dev );
213
+ return ret ;
214
+ }
215
+
216
+ if (!num_tc ) {
217
+ am65_cpsw_reset_tc_mqprio (ndev );
218
+ ret = 0 ;
219
+ goto exit_put ;
220
+ }
221
+
222
+ ret = am65_cpsw_mqprio_verify_shaper (port , mqprio );
223
+ if (ret )
224
+ goto exit_put ;
225
+
226
+ netdev_set_num_tc (ndev , num_tc );
227
+
228
+ /* Multiple Linux priorities can map to a Traffic Class
229
+ * A Traffic Class can have multiple contiguous Queues,
230
+ * Queues get mapped to Channels (thread_id),
231
+ * if not VLAN tagged, thread_id is used as packet_priority
232
+ * if VLAN tagged. VLAN priority is used as packet_priority
233
+ * packet_priority gets mapped to header_priority in p0_rx_pri_map,
234
+ * header_priority gets mapped to switch_priority in pn_tx_pri_map.
235
+ * As p0_rx_pri_map is left at defaults (0x76543210), we can
236
+ * assume that Queue_n gets mapped to header_priority_n. We can then
237
+ * set the switch priority in pn_tx_pri_map.
238
+ */
239
+
240
+ for (tc = 0 ; tc < num_tc ; tc ++ ) {
241
+ prio = tc ;
242
+
243
+ /* For simplicity we assign the same priority (TCn) to
244
+ * all queues of a Traffic Class.
245
+ */
246
+ for (i = qopt -> offset [tc ]; i < qopt -> offset [tc ] + qopt -> count [tc ]; i ++ )
247
+ tx_prio_map |= prio << (4 * i );
248
+
249
+ count = qopt -> count [tc ];
250
+ offset = qopt -> offset [tc ];
251
+ netdev_set_tc_queue (ndev , tc , count , offset );
252
+ }
253
+
254
+ writel (tx_prio_map , port -> port_base + AM65_CPSW_PN_REG_TX_PRI_MAP );
255
+
256
+ am65_cpsw_tx_pn_shaper_apply (port );
257
+
258
+ exit_put :
259
+ pm_runtime_put (common -> dev );
260
+
261
+ return ret ;
262
+ }
263
+
34
264
static int am65_cpsw_port_est_enabled (struct am65_cpsw_port * port )
35
265
{
36
266
return port -> qos .est_oper || port -> qos .est_admin ;
@@ -414,6 +644,8 @@ static void am65_cpsw_taprio_destroy(struct net_device *ndev)
414
644
415
645
port -> qos .est_oper = NULL ;
416
646
port -> qos .est_admin = NULL ;
647
+
648
+ am65_cpsw_reset_tc_mqprio (ndev );
417
649
}
418
650
419
651
static void am65_cpsw_cp_taprio (struct tc_taprio_qopt_offload * from ,
@@ -462,6 +694,10 @@ static int am65_cpsw_taprio_replace(struct net_device *ndev,
462
694
if (!est_new )
463
695
return - ENOMEM ;
464
696
697
+ ret = am65_cpsw_setup_mqprio (ndev , & taprio -> mqprio );
698
+ if (ret )
699
+ return ret ;
700
+
465
701
am65_cpsw_cp_taprio (taprio , & est_new -> taprio );
466
702
467
703
am65_cpsw_est_update_state (ndev );
@@ -505,6 +741,7 @@ static int am65_cpsw_taprio_replace(struct net_device *ndev,
505
741
return 0 ;
506
742
507
743
fail :
744
+ am65_cpsw_reset_tc_mqprio (ndev );
508
745
devm_kfree (& ndev -> dev , est_new );
509
746
return ret ;
510
747
}
@@ -515,7 +752,6 @@ static void am65_cpsw_est_link_up(struct net_device *ndev, int link_speed)
515
752
ktime_t cur_time ;
516
753
s64 delta ;
517
754
518
- port -> qos .link_speed = link_speed ;
519
755
if (!am65_cpsw_port_est_enabled (port ))
520
756
return ;
521
757
@@ -559,6 +795,14 @@ static int am65_cpsw_tc_query_caps(struct net_device *ndev, void *type_data)
559
795
struct tc_query_caps_base * base = type_data ;
560
796
561
797
switch (base -> type ) {
798
+ case TC_SETUP_QDISC_MQPRIO : {
799
+ struct tc_mqprio_caps * caps = base -> caps ;
800
+
801
+ caps -> validate_queue_counts = true;
802
+
803
+ return 0 ;
804
+ }
805
+
562
806
case TC_SETUP_QDISC_TAPRIO : {
563
807
struct tc_taprio_caps * caps = base -> caps ;
564
808
@@ -857,6 +1101,8 @@ int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type,
857
1101
return am65_cpsw_tc_query_caps (ndev , type_data );
858
1102
case TC_SETUP_QDISC_TAPRIO :
859
1103
return am65_cpsw_setup_taprio (ndev , type_data );
1104
+ case TC_SETUP_QDISC_MQPRIO :
1105
+ return am65_cpsw_setup_mqprio (ndev , type_data );
860
1106
case TC_SETUP_BLOCK :
861
1107
return am65_cpsw_qos_setup_tc_block (ndev , type_data );
862
1108
default :
@@ -868,6 +1114,9 @@ void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed)
868
1114
{
869
1115
struct am65_cpsw_port * port = am65_ndev_to_port (ndev );
870
1116
1117
+ port -> qos .link_speed = link_speed ;
1118
+ am65_cpsw_tx_pn_shaper_apply (port );
1119
+
871
1120
am65_cpsw_est_link_up (ndev , link_speed );
872
1121
port -> qos .link_down_time = 0 ;
873
1122
}
@@ -876,8 +1125,9 @@ void am65_cpsw_qos_link_down(struct net_device *ndev)
876
1125
{
877
1126
struct am65_cpsw_port * port = am65_ndev_to_port (ndev );
878
1127
1128
+ port -> qos .link_speed = SPEED_UNKNOWN ;
1129
+ am65_cpsw_tx_pn_shaper_apply (port );
1130
+
879
1131
if (!port -> qos .link_down_time )
880
1132
port -> qos .link_down_time = ktime_get ();
881
-
882
- port -> qos .link_speed = SPEED_UNKNOWN ;
883
1133
}
0 commit comments