]> Git Repo - J-linux.git/blob - drivers/net/ethernet/intel/igc/igc_tsn.c
ASoC: Merge v6.5-rc2
[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->taprio_offload_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         u32 tqavctrl, baset_l, baset_h;
118         u32 sec, nsec, cycle;
119         ktime_t base_time, systim;
120         int i;
121
122         wr32(IGC_TSAUXC, 0);
123         wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
124         wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
125
126         for (i = 0; i < adapter->num_tx_queues; i++) {
127                 struct igc_ring *ring = adapter->tx_ring[i];
128                 u32 txqctl = 0;
129                 u16 cbs_value;
130                 u32 tqavcc;
131
132                 wr32(IGC_STQT(i), ring->start_time);
133                 wr32(IGC_ENDQT(i), ring->end_time);
134
135                 if (adapter->taprio_offload_enable) {
136                         /* If taprio_offload_enable is set we are in "taprio"
137                          * mode and we need to be strict about the
138                          * cycles: only transmit a packet if it can be
139                          * completed during that cycle.
140                          *
141                          * If taprio_offload_enable is NOT true when
142                          * enabling TSN offload, the cycle should have
143                          * no external effects, but is only used internally
144                          * to adapt the base time register after a second
145                          * has passed.
146                          *
147                          * Enabling strict mode in this case would
148                          * unnecessarily prevent the transmission of
149                          * certain packets (i.e. at the boundary of a
150                          * second) and thus interfere with the launchtime
151                          * feature that promises transmission at a
152                          * certain point in time.
153                          */
154                         txqctl |= IGC_TXQCTL_STRICT_CYCLE |
155                                 IGC_TXQCTL_STRICT_END;
156                 }
157
158                 if (ring->launchtime_enable)
159                         txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
160
161                 /* Skip configuring CBS for Q2 and Q3 */
162                 if (i > 1)
163                         goto skip_cbs;
164
165                 if (ring->cbs_enable) {
166                         if (i == 0)
167                                 txqctl |= IGC_TXQCTL_QAV_SEL_CBS0;
168                         else
169                                 txqctl |= IGC_TXQCTL_QAV_SEL_CBS1;
170
171                         /* According to i225 datasheet section 7.5.2.7, we
172                          * should set the 'idleSlope' field from TQAVCC
173                          * register following the equation:
174                          *
175                          * value = link-speed   0x7736 * BW * 0.2
176                          *         ---------- *  -----------------         (E1)
177                          *          100Mbps            2.5
178                          *
179                          * Note that 'link-speed' is in Mbps.
180                          *
181                          * 'BW' is the percentage bandwidth out of full
182                          * link speed which can be found with the
183                          * following equation. Note that idleSlope here
184                          * is the parameter from this function
185                          * which is in kbps.
186                          *
187                          *     BW =     idleSlope
188                          *          -----------------                      (E2)
189                          *          link-speed * 1000
190                          *
191                          * That said, we can come up with a generic
192                          * equation to calculate the value we should set
193                          * it TQAVCC register by replacing 'BW' in E1 by E2.
194                          * The resulting equation is:
195                          *
196                          * value = link-speed * 0x7736 * idleSlope * 0.2
197                          *         -------------------------------------   (E3)
198                          *             100 * 2.5 * link-speed * 1000
199                          *
200                          * 'link-speed' is present in both sides of the
201                          * fraction so it is canceled out. The final
202                          * equation is the following:
203                          *
204                          *     value = idleSlope * 61036
205                          *             -----------------                   (E4)
206                          *                  2500000
207                          *
208                          * NOTE: For i225, given the above, we can see
209                          *       that idleslope is represented in
210                          *       40.959433 kbps units by the value at
211                          *       the TQAVCC register (2.5Gbps / 61036),
212                          *       which reduces the granularity for
213                          *       idleslope increments.
214                          *
215                          * In i225 controller, the sendSlope and loCredit
216                          * parameters from CBS are not configurable
217                          * by software so we don't do any
218                          * 'controller configuration' in respect to
219                          * these parameters.
220                          */
221                         cbs_value = DIV_ROUND_UP_ULL(ring->idleslope
222                                                      * 61036ULL, 2500000);
223
224                         tqavcc = rd32(IGC_TQAVCC(i));
225                         tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK;
226                         tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS;
227                         wr32(IGC_TQAVCC(i), tqavcc);
228
229                         wr32(IGC_TQAVHC(i),
230                              0x80000000 + ring->hicredit * 0x7735);
231                 } else {
232                         /* Disable any CBS for the queue */
233                         txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK);
234
235                         /* Set idleSlope to zero. */
236                         tqavcc = rd32(IGC_TQAVCC(i));
237                         tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK |
238                                     IGC_TQAVCC_KEEP_CREDITS);
239                         wr32(IGC_TQAVCC(i), tqavcc);
240
241                         /* Set hiCredit to zero. */
242                         wr32(IGC_TQAVHC(i), 0);
243                 }
244 skip_cbs:
245                 wr32(IGC_TXQCTL(i), txqctl);
246         }
247
248         tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
249
250         tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
251
252         adapter->qbv_count++;
253
254         cycle = adapter->cycle_time;
255         base_time = adapter->base_time;
256
257         nsec = rd32(IGC_SYSTIML);
258         sec = rd32(IGC_SYSTIMH);
259
260         systim = ktime_set(sec, nsec);
261         if (ktime_compare(systim, base_time) > 0) {
262                 s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
263
264                 base_time = ktime_add_ns(base_time, (n + 1) * cycle);
265
266                 /* Increase the counter if scheduling into the past while
267                  * Gate Control List (GCL) is running.
268                  */
269                 if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) &&
270                     (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) &&
271                     (adapter->qbv_count > 1))
272                         adapter->qbv_config_change_errors++;
273         } else {
274                 if (igc_is_device_id_i226(hw)) {
275                         ktime_t adjust_time, expires_time;
276
277                        /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
278                         * has to be configured before the cycle time and base time.
279                         * Tx won't hang if a GCL is already running,
280                         * so in this case we don't need to set FutScdDis.
281                         */
282                         if (!(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
283                                 tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
284
285                         nsec = rd32(IGC_SYSTIML);
286                         sec = rd32(IGC_SYSTIMH);
287                         systim = ktime_set(sec, nsec);
288
289                         adjust_time = adapter->base_time;
290                         expires_time = ktime_sub_ns(adjust_time, systim);
291                         hrtimer_start(&adapter->hrtimer, expires_time, HRTIMER_MODE_REL);
292                 }
293         }
294
295         wr32(IGC_TQAVCTRL, tqavctrl);
296
297         wr32(IGC_QBVCYCLET_S, cycle);
298         wr32(IGC_QBVCYCLET, cycle);
299
300         baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
301         wr32(IGC_BASET_H, baset_h);
302
303         /* In i226, Future base time is only supported when FutScdDis bit
304          * is enabled and only active for re-configuration.
305          * In this case, initialize the base time with zero to create
306          * "re-configuration" scenario then only set the desired base time.
307          */
308         if (tqavctrl & IGC_TQAVCTRL_FUTSCDDIS)
309                 wr32(IGC_BASET_L, 0);
310         wr32(IGC_BASET_L, baset_l);
311
312         return 0;
313 }
314
315 int igc_tsn_reset(struct igc_adapter *adapter)
316 {
317         unsigned int new_flags;
318         int err = 0;
319
320         new_flags = igc_tsn_new_flags(adapter);
321
322         if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
323                 return igc_tsn_disable_offload(adapter);
324
325         err = igc_tsn_enable_offload(adapter);
326         if (err < 0)
327                 return err;
328
329         adapter->flags = new_flags;
330
331         return err;
332 }
333
334 int igc_tsn_offload_apply(struct igc_adapter *adapter)
335 {
336         struct igc_hw *hw = &adapter->hw;
337
338         /* Per I225/6 HW Design Section 7.5.2.1, transmit mode
339          * cannot be changed dynamically. Require reset the adapter.
340          */
341         if (netif_running(adapter->netdev) &&
342             (igc_is_device_id_i225(hw) || !adapter->qbv_count)) {
343                 schedule_work(&adapter->reset_task);
344                 return 0;
345         }
346
347         igc_tsn_reset(adapter);
348
349         return 0;
350 }
This page took 0.04802 seconds and 4 git commands to generate.