d26fc0f47640d85e238a43a24cd50bfff8df8605
[platform/kernel/linux-starfive.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         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                 txqctl |= IGC_TXQCTL_STRICT_CYCLE |
136                         IGC_TXQCTL_STRICT_END;
137
138                 if (ring->launchtime_enable)
139                         txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
140
141                 /* Skip configuring CBS for Q2 and Q3 */
142                 if (i > 1)
143                         goto skip_cbs;
144
145                 if (ring->cbs_enable) {
146                         if (i == 0)
147                                 txqctl |= IGC_TXQCTL_QAV_SEL_CBS0;
148                         else
149                                 txqctl |= IGC_TXQCTL_QAV_SEL_CBS1;
150
151                         /* According to i225 datasheet section 7.5.2.7, we
152                          * should set the 'idleSlope' field from TQAVCC
153                          * register following the equation:
154                          *
155                          * value = link-speed   0x7736 * BW * 0.2
156                          *         ---------- *  -----------------         (E1)
157                          *          100Mbps            2.5
158                          *
159                          * Note that 'link-speed' is in Mbps.
160                          *
161                          * 'BW' is the percentage bandwidth out of full
162                          * link speed which can be found with the
163                          * following equation. Note that idleSlope here
164                          * is the parameter from this function
165                          * which is in kbps.
166                          *
167                          *     BW =     idleSlope
168                          *          -----------------                      (E2)
169                          *          link-speed * 1000
170                          *
171                          * That said, we can come up with a generic
172                          * equation to calculate the value we should set
173                          * it TQAVCC register by replacing 'BW' in E1 by E2.
174                          * The resulting equation is:
175                          *
176                          * value = link-speed * 0x7736 * idleSlope * 0.2
177                          *         -------------------------------------   (E3)
178                          *             100 * 2.5 * link-speed * 1000
179                          *
180                          * 'link-speed' is present in both sides of the
181                          * fraction so it is canceled out. The final
182                          * equation is the following:
183                          *
184                          *     value = idleSlope * 61036
185                          *             -----------------                   (E4)
186                          *                  2500000
187                          *
188                          * NOTE: For i225, given the above, we can see
189                          *       that idleslope is represented in
190                          *       40.959433 kbps units by the value at
191                          *       the TQAVCC register (2.5Gbps / 61036),
192                          *       which reduces the granularity for
193                          *       idleslope increments.
194                          *
195                          * In i225 controller, the sendSlope and loCredit
196                          * parameters from CBS are not configurable
197                          * by software so we don't do any
198                          * 'controller configuration' in respect to
199                          * these parameters.
200                          */
201                         cbs_value = DIV_ROUND_UP_ULL(ring->idleslope
202                                                      * 61036ULL, 2500000);
203
204                         tqavcc = rd32(IGC_TQAVCC(i));
205                         tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK;
206                         tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS;
207                         wr32(IGC_TQAVCC(i), tqavcc);
208
209                         wr32(IGC_TQAVHC(i),
210                              0x80000000 + ring->hicredit * 0x7735);
211                 } else {
212                         /* Disable any CBS for the queue */
213                         txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK);
214
215                         /* Set idleSlope to zero. */
216                         tqavcc = rd32(IGC_TQAVCC(i));
217                         tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK |
218                                     IGC_TQAVCC_KEEP_CREDITS);
219                         wr32(IGC_TQAVCC(i), tqavcc);
220
221                         /* Set hiCredit to zero. */
222                         wr32(IGC_TQAVHC(i), 0);
223                 }
224 skip_cbs:
225                 wr32(IGC_TXQCTL(i), txqctl);
226         }
227
228         tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
229         tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
230
231         cycle = adapter->cycle_time;
232         base_time = adapter->base_time;
233
234         nsec = rd32(IGC_SYSTIML);
235         sec = rd32(IGC_SYSTIMH);
236
237         systim = ktime_set(sec, nsec);
238         if (ktime_compare(systim, base_time) > 0) {
239                 s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
240
241                 base_time = ktime_add_ns(base_time, (n + 1) * cycle);
242         } else {
243                 /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
244                  * has to be configured before the cycle time and base time.
245                  * Tx won't hang if there is a GCL is already running,
246                  * so in this case we don't need to set FutScdDis.
247                  */
248                 if (igc_is_device_id_i226(hw) &&
249                     !(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
250                         tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
251         }
252
253         wr32(IGC_TQAVCTRL, tqavctrl);
254
255         wr32(IGC_QBVCYCLET_S, cycle);
256         wr32(IGC_QBVCYCLET, cycle);
257
258         baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
259         wr32(IGC_BASET_H, baset_h);
260
261         /* In i226, Future base time is only supported when FutScdDis bit
262          * is enabled and only active for re-configuration.
263          * In this case, initialize the base time with zero to create
264          * "re-configuration" scenario then only set the desired base time.
265          */
266         if (tqavctrl & IGC_TQAVCTRL_FUTSCDDIS)
267                 wr32(IGC_BASET_L, 0);
268         wr32(IGC_BASET_L, baset_l);
269
270         return 0;
271 }
272
273 int igc_tsn_reset(struct igc_adapter *adapter)
274 {
275         unsigned int new_flags;
276         int err = 0;
277
278         new_flags = igc_tsn_new_flags(adapter);
279
280         if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
281                 return igc_tsn_disable_offload(adapter);
282
283         err = igc_tsn_enable_offload(adapter);
284         if (err < 0)
285                 return err;
286
287         adapter->flags = new_flags;
288
289         return err;
290 }
291
292 int igc_tsn_offload_apply(struct igc_adapter *adapter, bool enable)
293 {
294         struct igc_hw *hw = &adapter->hw;
295         int err;
296
297         if (netif_running(adapter->netdev) &&
298             (igc_is_device_id_i225(hw) || !enable)) {
299                 schedule_work(&adapter->reset_task);
300                 return 0;
301         }
302
303         err = igc_tsn_enable_offload(adapter);
304         if (err < 0)
305                 return err;
306
307         adapter->flags = igc_tsn_new_flags(adapter);
308         return 0;
309 }