]> Git Repo - J-linux.git/blob - drivers/net/ethernet/intel/igc/igc_tsn.c
igc: Remove delay during TX ring configuration
[J-linux.git] / drivers / net / ethernet / intel / igc / igc_tsn.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c)  2019 Intel Corporation */
3
4 #include "igc.h"
5 #include "igc_hw.h"
6 #include "igc_tsn.h"
7
8 static bool is_any_launchtime(struct igc_adapter *adapter)
9 {
10         int i;
11
12         for (i = 0; i < adapter->num_tx_queues; i++) {
13                 struct igc_ring *ring = adapter->tx_ring[i];
14
15                 if (ring->launchtime_enable)
16                         return true;
17         }
18
19         return false;
20 }
21
22 static bool is_cbs_enabled(struct igc_adapter *adapter)
23 {
24         int i;
25
26         for (i = 0; i < adapter->num_tx_queues; i++) {
27                 struct igc_ring *ring = adapter->tx_ring[i];
28
29                 if (ring->cbs_enable)
30                         return true;
31         }
32
33         return false;
34 }
35
36 static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
37 {
38         unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED;
39
40         if (adapter->qbv_enable)
41                 new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
42
43         if (is_any_launchtime(adapter))
44                 new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
45
46         if (is_cbs_enabled(adapter))
47                 new_flags |= IGC_FLAG_TSN_QAV_ENABLED;
48
49         return new_flags;
50 }
51
52 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter)
53 {
54         struct igc_hw *hw = &adapter->hw;
55         u16 txoffset;
56
57         if (!is_any_launchtime(adapter))
58                 return;
59
60         switch (adapter->link_speed) {
61         case SPEED_10:
62                 txoffset = IGC_TXOFFSET_SPEED_10;
63                 break;
64         case SPEED_100:
65                 txoffset = IGC_TXOFFSET_SPEED_100;
66                 break;
67         case SPEED_1000:
68                 txoffset = IGC_TXOFFSET_SPEED_1000;
69                 break;
70         case SPEED_2500:
71                 txoffset = IGC_TXOFFSET_SPEED_2500;
72                 break;
73         default:
74                 txoffset = 0;
75                 break;
76         }
77
78         wr32(IGC_GTXOFFSET, txoffset);
79 }
80
81 /* Returns the TSN specific registers to their default values after
82  * the adapter is reset.
83  */
84 static int igc_tsn_disable_offload(struct igc_adapter *adapter)
85 {
86         struct igc_hw *hw = &adapter->hw;
87         u32 tqavctrl;
88         int i;
89
90         wr32(IGC_GTXOFFSET, 0);
91         wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
92         wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
93
94         tqavctrl = rd32(IGC_TQAVCTRL);
95         tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
96                       IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS);
97
98         wr32(IGC_TQAVCTRL, tqavctrl);
99
100         for (i = 0; i < adapter->num_tx_queues; i++) {
101                 wr32(IGC_TXQCTL(i), 0);
102                 wr32(IGC_STQT(i), 0);
103                 wr32(IGC_ENDQT(i), NSEC_PER_SEC);
104         }
105
106         wr32(IGC_QBVCYCLET_S, 0);
107         wr32(IGC_QBVCYCLET, NSEC_PER_SEC);
108
109         adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED;
110
111         return 0;
112 }
113
114 static int igc_tsn_enable_offload(struct igc_adapter *adapter)
115 {
116         struct igc_hw *hw = &adapter->hw;
117         bool tsn_mode_reconfig = false;
118         u32 tqavctrl, baset_l, baset_h;
119         u32 sec, nsec, cycle;
120         ktime_t base_time, systim;
121         int i;
122
123         wr32(IGC_TSAUXC, 0);
124         wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
125         wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
126
127         for (i = 0; i < adapter->num_tx_queues; i++) {
128                 struct igc_ring *ring = adapter->tx_ring[i];
129                 u32 txqctl = 0;
130                 u16 cbs_value;
131                 u32 tqavcc;
132
133                 wr32(IGC_STQT(i), ring->start_time);
134                 wr32(IGC_ENDQT(i), ring->end_time);
135
136                 txqctl |= IGC_TXQCTL_STRICT_CYCLE |
137                         IGC_TXQCTL_STRICT_END;
138
139                 if (ring->launchtime_enable)
140                         txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
141
142                 /* Skip configuring CBS for Q2 and Q3 */
143                 if (i > 1)
144                         goto skip_cbs;
145
146                 if (ring->cbs_enable) {
147                         if (i == 0)
148                                 txqctl |= IGC_TXQCTL_QAV_SEL_CBS0;
149                         else
150                                 txqctl |= IGC_TXQCTL_QAV_SEL_CBS1;
151
152                         /* According to i225 datasheet section 7.5.2.7, we
153                          * should set the 'idleSlope' field from TQAVCC
154                          * register following the equation:
155                          *
156                          * value = link-speed   0x7736 * BW * 0.2
157                          *         ---------- *  -----------------         (E1)
158                          *          100Mbps            2.5
159                          *
160                          * Note that 'link-speed' is in Mbps.
161                          *
162                          * 'BW' is the percentage bandwidth out of full
163                          * link speed which can be found with the
164                          * following equation. Note that idleSlope here
165                          * is the parameter from this function
166                          * which is in kbps.
167                          *
168                          *     BW =     idleSlope
169                          *          -----------------                      (E2)
170                          *          link-speed * 1000
171                          *
172                          * That said, we can come up with a generic
173                          * equation to calculate the value we should set
174                          * it TQAVCC register by replacing 'BW' in E1 by E2.
175                          * The resulting equation is:
176                          *
177                          * value = link-speed * 0x7736 * idleSlope * 0.2
178                          *         -------------------------------------   (E3)
179                          *             100 * 2.5 * link-speed * 1000
180                          *
181                          * 'link-speed' is present in both sides of the
182                          * fraction so it is canceled out. The final
183                          * equation is the following:
184                          *
185                          *     value = idleSlope * 61036
186                          *             -----------------                   (E4)
187                          *                  2500000
188                          *
189                          * NOTE: For i225, given the above, we can see
190                          *       that idleslope is represented in
191                          *       40.959433 kbps units by the value at
192                          *       the TQAVCC register (2.5Gbps / 61036),
193                          *       which reduces the granularity for
194                          *       idleslope increments.
195                          *
196                          * In i225 controller, the sendSlope and loCredit
197                          * parameters from CBS are not configurable
198                          * by software so we don't do any
199                          * 'controller configuration' in respect to
200                          * these parameters.
201                          */
202                         cbs_value = DIV_ROUND_UP_ULL(ring->idleslope
203                                                      * 61036ULL, 2500000);
204
205                         tqavcc = rd32(IGC_TQAVCC(i));
206                         tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK;
207                         tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS;
208                         wr32(IGC_TQAVCC(i), tqavcc);
209
210                         wr32(IGC_TQAVHC(i),
211                              0x80000000 + ring->hicredit * 0x7735);
212                 } else {
213                         /* Disable any CBS for the queue */
214                         txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK);
215
216                         /* Set idleSlope to zero. */
217                         tqavcc = rd32(IGC_TQAVCC(i));
218                         tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK |
219                                     IGC_TQAVCC_KEEP_CREDITS);
220                         wr32(IGC_TQAVCC(i), tqavcc);
221
222                         /* Set hiCredit to zero. */
223                         wr32(IGC_TQAVHC(i), 0);
224                 }
225 skip_cbs:
226                 wr32(IGC_TXQCTL(i), txqctl);
227         }
228
229         tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
230
231         if (tqavctrl & IGC_TQAVCTRL_TRANSMIT_MODE_TSN)
232                 tsn_mode_reconfig = true;
233
234         tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
235
236         cycle = adapter->cycle_time;
237         base_time = adapter->base_time;
238
239         nsec = rd32(IGC_SYSTIML);
240         sec = rd32(IGC_SYSTIMH);
241
242         systim = ktime_set(sec, nsec);
243         if (ktime_compare(systim, base_time) > 0) {
244                 s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
245
246                 base_time = ktime_add_ns(base_time, (n + 1) * cycle);
247
248                 /* Increase the counter if scheduling into the past while
249                  * Gate Control List (GCL) is running.
250                  */
251                 if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) &&
252                     (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) &&
253                     tsn_mode_reconfig)
254                         adapter->qbv_config_change_errors++;
255         } else {
256                 /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
257                  * has to be configured before the cycle time and base time.
258                  * Tx won't hang if there is a GCL is already running,
259                  * so in this case we don't need to set FutScdDis.
260                  */
261                 if (igc_is_device_id_i226(hw) &&
262                     !(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
263                         tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
264         }
265
266         wr32(IGC_TQAVCTRL, tqavctrl);
267
268         wr32(IGC_QBVCYCLET_S, cycle);
269         wr32(IGC_QBVCYCLET, cycle);
270
271         baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
272         wr32(IGC_BASET_H, baset_h);
273
274         /* In i226, Future base time is only supported when FutScdDis bit
275          * is enabled and only active for re-configuration.
276          * In this case, initialize the base time with zero to create
277          * "re-configuration" scenario then only set the desired base time.
278          */
279         if (tqavctrl & IGC_TQAVCTRL_FUTSCDDIS)
280                 wr32(IGC_BASET_L, 0);
281         wr32(IGC_BASET_L, baset_l);
282
283         return 0;
284 }
285
286 int igc_tsn_reset(struct igc_adapter *adapter)
287 {
288         unsigned int new_flags;
289         int err = 0;
290
291         new_flags = igc_tsn_new_flags(adapter);
292
293         if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
294                 return igc_tsn_disable_offload(adapter);
295
296         err = igc_tsn_enable_offload(adapter);
297         if (err < 0)
298                 return err;
299
300         adapter->flags = new_flags;
301
302         return err;
303 }
304
305 int igc_tsn_offload_apply(struct igc_adapter *adapter)
306 {
307         struct igc_hw *hw = &adapter->hw;
308
309         if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) {
310                 schedule_work(&adapter->reset_task);
311                 return 0;
312         }
313
314         igc_tsn_reset(adapter);
315
316         return 0;
317 }
This page took 0.051185 seconds and 4 git commands to generate.