xref: /linux/drivers/net/ethernet/intel/igc/igc_tsn.c (revision f10d52087cbe85dcff2af3dc94c5b9d06e6d4b9a)
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 static bool igc_tsn_is_tx_mode_in_tsn(struct igc_adapter *adapter)
53 {
54 	struct igc_hw *hw = &adapter->hw;
55 
56 	return !!(rd32(IGC_TQAVCTRL) & IGC_TQAVCTRL_TRANSMIT_MODE_TSN);
57 }
58 
59 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter)
60 {
61 	struct igc_hw *hw = &adapter->hw;
62 	u16 txoffset;
63 
64 	if (!igc_tsn_is_tx_mode_in_tsn(adapter))
65 		return;
66 
67 	switch (adapter->link_speed) {
68 	case SPEED_10:
69 		txoffset = IGC_TXOFFSET_SPEED_10;
70 		break;
71 	case SPEED_100:
72 		txoffset = IGC_TXOFFSET_SPEED_100;
73 		break;
74 	case SPEED_1000:
75 		txoffset = IGC_TXOFFSET_SPEED_1000;
76 		break;
77 	case SPEED_2500:
78 		txoffset = IGC_TXOFFSET_SPEED_2500;
79 		break;
80 	default:
81 		txoffset = 0;
82 		break;
83 	}
84 
85 	wr32(IGC_GTXOFFSET, txoffset);
86 }
87 
88 static void igc_tsn_restore_retx_default(struct igc_adapter *adapter)
89 {
90 	struct igc_hw *hw = &adapter->hw;
91 	u32 retxctl;
92 
93 	retxctl = rd32(IGC_RETX_CTL) & IGC_RETX_CTL_WATERMARK_MASK;
94 	wr32(IGC_RETX_CTL, retxctl);
95 }
96 
97 bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter)
98 {
99 	struct igc_hw *hw = &adapter->hw;
100 
101 	return (rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) &&
102 		adapter->taprio_offload_enable;
103 }
104 
105 /* Returns the TSN specific registers to their default values after
106  * the adapter is reset.
107  */
108 static int igc_tsn_disable_offload(struct igc_adapter *adapter)
109 {
110 	struct igc_hw *hw = &adapter->hw;
111 	u32 tqavctrl;
112 	int i;
113 
114 	wr32(IGC_GTXOFFSET, 0);
115 	wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
116 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
117 
118 	if (igc_is_device_id_i226(hw))
119 		igc_tsn_restore_retx_default(adapter);
120 
121 	tqavctrl = rd32(IGC_TQAVCTRL);
122 	tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
123 		      IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS);
124 
125 	wr32(IGC_TQAVCTRL, tqavctrl);
126 
127 	for (i = 0; i < adapter->num_tx_queues; i++) {
128 		wr32(IGC_TXQCTL(i), 0);
129 		wr32(IGC_STQT(i), 0);
130 		wr32(IGC_ENDQT(i), NSEC_PER_SEC);
131 	}
132 
133 	wr32(IGC_QBVCYCLET_S, 0);
134 	wr32(IGC_QBVCYCLET, NSEC_PER_SEC);
135 
136 	adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED;
137 
138 	return 0;
139 }
140 
141 /* To partially fix i226 HW errata, reduce MAC internal buffering from 192 Bytes
142  * to 88 Bytes by setting RETX_CTL register using the recommendation from:
143  * a) Ethernet Controller I225/I226 Specification Update Rev 2.1
144  *    Item 9: TSN: Packet Transmission Might Cross the Qbv Window
145  * b) I225/6 SW User Manual Rev 1.2.4: Section 8.11.5 Retry Buffer Control
146  */
147 static void igc_tsn_set_retx_qbvfullthreshold(struct igc_adapter *adapter)
148 {
149 	struct igc_hw *hw = &adapter->hw;
150 	u32 retxctl, watermark;
151 
152 	retxctl = rd32(IGC_RETX_CTL);
153 	watermark = retxctl & IGC_RETX_CTL_WATERMARK_MASK;
154 	/* Set QBVFULLTH value using watermark and set QBVFULLEN */
155 	retxctl |= (watermark << IGC_RETX_CTL_QBVFULLTH_SHIFT) |
156 		   IGC_RETX_CTL_QBVFULLEN;
157 	wr32(IGC_RETX_CTL, retxctl);
158 }
159 
160 static int igc_tsn_enable_offload(struct igc_adapter *adapter)
161 {
162 	struct igc_hw *hw = &adapter->hw;
163 	u32 tqavctrl, baset_l, baset_h;
164 	u32 sec, nsec, cycle;
165 	ktime_t base_time, systim;
166 	int i;
167 
168 	wr32(IGC_TSAUXC, 0);
169 	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
170 	wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
171 
172 	if (igc_is_device_id_i226(hw))
173 		igc_tsn_set_retx_qbvfullthreshold(adapter);
174 
175 	for (i = 0; i < adapter->num_tx_queues; i++) {
176 		struct igc_ring *ring = adapter->tx_ring[i];
177 		u32 txqctl = 0;
178 		u16 cbs_value;
179 		u32 tqavcc;
180 
181 		wr32(IGC_STQT(i), ring->start_time);
182 		wr32(IGC_ENDQT(i), ring->end_time);
183 
184 		if (adapter->taprio_offload_enable) {
185 			/* If taprio_offload_enable is set we are in "taprio"
186 			 * mode and we need to be strict about the
187 			 * cycles: only transmit a packet if it can be
188 			 * completed during that cycle.
189 			 *
190 			 * If taprio_offload_enable is NOT true when
191 			 * enabling TSN offload, the cycle should have
192 			 * no external effects, but is only used internally
193 			 * to adapt the base time register after a second
194 			 * has passed.
195 			 *
196 			 * Enabling strict mode in this case would
197 			 * unnecessarily prevent the transmission of
198 			 * certain packets (i.e. at the boundary of a
199 			 * second) and thus interfere with the launchtime
200 			 * feature that promises transmission at a
201 			 * certain point in time.
202 			 */
203 			txqctl |= IGC_TXQCTL_STRICT_CYCLE |
204 				IGC_TXQCTL_STRICT_END;
205 		}
206 
207 		if (ring->launchtime_enable)
208 			txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
209 
210 		/* Skip configuring CBS for Q2 and Q3 */
211 		if (i > 1)
212 			goto skip_cbs;
213 
214 		if (ring->cbs_enable) {
215 			if (i == 0)
216 				txqctl |= IGC_TXQCTL_QAV_SEL_CBS0;
217 			else
218 				txqctl |= IGC_TXQCTL_QAV_SEL_CBS1;
219 
220 			/* According to i225 datasheet section 7.5.2.7, we
221 			 * should set the 'idleSlope' field from TQAVCC
222 			 * register following the equation:
223 			 *
224 			 * value = link-speed   0x7736 * BW * 0.2
225 			 *         ---------- *  -----------------         (E1)
226 			 *          100Mbps            2.5
227 			 *
228 			 * Note that 'link-speed' is in Mbps.
229 			 *
230 			 * 'BW' is the percentage bandwidth out of full
231 			 * link speed which can be found with the
232 			 * following equation. Note that idleSlope here
233 			 * is the parameter from this function
234 			 * which is in kbps.
235 			 *
236 			 *     BW =     idleSlope
237 			 *          -----------------                      (E2)
238 			 *          link-speed * 1000
239 			 *
240 			 * That said, we can come up with a generic
241 			 * equation to calculate the value we should set
242 			 * it TQAVCC register by replacing 'BW' in E1 by E2.
243 			 * The resulting equation is:
244 			 *
245 			 * value = link-speed * 0x7736 * idleSlope * 0.2
246 			 *         -------------------------------------   (E3)
247 			 *             100 * 2.5 * link-speed * 1000
248 			 *
249 			 * 'link-speed' is present in both sides of the
250 			 * fraction so it is canceled out. The final
251 			 * equation is the following:
252 			 *
253 			 *     value = idleSlope * 61036
254 			 *             -----------------                   (E4)
255 			 *                  2500000
256 			 *
257 			 * NOTE: For i225, given the above, we can see
258 			 *       that idleslope is represented in
259 			 *       40.959433 kbps units by the value at
260 			 *       the TQAVCC register (2.5Gbps / 61036),
261 			 *       which reduces the granularity for
262 			 *       idleslope increments.
263 			 *
264 			 * In i225 controller, the sendSlope and loCredit
265 			 * parameters from CBS are not configurable
266 			 * by software so we don't do any
267 			 * 'controller configuration' in respect to
268 			 * these parameters.
269 			 */
270 			cbs_value = DIV_ROUND_UP_ULL(ring->idleslope
271 						     * 61036ULL, 2500000);
272 
273 			tqavcc = rd32(IGC_TQAVCC(i));
274 			tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK;
275 			tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS;
276 			wr32(IGC_TQAVCC(i), tqavcc);
277 
278 			wr32(IGC_TQAVHC(i),
279 			     0x80000000 + ring->hicredit * 0x7736);
280 		} else {
281 			/* Disable any CBS for the queue */
282 			txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK);
283 
284 			/* Set idleSlope to zero. */
285 			tqavcc = rd32(IGC_TQAVCC(i));
286 			tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK |
287 				    IGC_TQAVCC_KEEP_CREDITS);
288 			wr32(IGC_TQAVCC(i), tqavcc);
289 
290 			/* Set hiCredit to zero. */
291 			wr32(IGC_TQAVHC(i), 0);
292 		}
293 skip_cbs:
294 		wr32(IGC_TXQCTL(i), txqctl);
295 	}
296 
297 	tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
298 
299 	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
300 
301 	adapter->qbv_count++;
302 
303 	cycle = adapter->cycle_time;
304 	base_time = adapter->base_time;
305 
306 	nsec = rd32(IGC_SYSTIML);
307 	sec = rd32(IGC_SYSTIMH);
308 
309 	systim = ktime_set(sec, nsec);
310 	if (ktime_compare(systim, base_time) > 0) {
311 		s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
312 
313 		base_time = ktime_add_ns(base_time, (n + 1) * cycle);
314 	} else {
315 		if (igc_is_device_id_i226(hw)) {
316 			ktime_t adjust_time, expires_time;
317 
318 		       /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
319 			* has to be configured before the cycle time and base time.
320 			* Tx won't hang if a GCL is already running,
321 			* so in this case we don't need to set FutScdDis.
322 			*/
323 			if (!(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
324 				tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
325 
326 			nsec = rd32(IGC_SYSTIML);
327 			sec = rd32(IGC_SYSTIMH);
328 			systim = ktime_set(sec, nsec);
329 
330 			adjust_time = adapter->base_time;
331 			expires_time = ktime_sub_ns(adjust_time, systim);
332 			hrtimer_start(&adapter->hrtimer, expires_time, HRTIMER_MODE_REL);
333 		}
334 	}
335 
336 	wr32(IGC_TQAVCTRL, tqavctrl);
337 
338 	wr32(IGC_QBVCYCLET_S, cycle);
339 	wr32(IGC_QBVCYCLET, cycle);
340 
341 	baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
342 	wr32(IGC_BASET_H, baset_h);
343 
344 	/* In i226, Future base time is only supported when FutScdDis bit
345 	 * is enabled and only active for re-configuration.
346 	 * In this case, initialize the base time with zero to create
347 	 * "re-configuration" scenario then only set the desired base time.
348 	 */
349 	if (tqavctrl & IGC_TQAVCTRL_FUTSCDDIS)
350 		wr32(IGC_BASET_L, 0);
351 	wr32(IGC_BASET_L, baset_l);
352 
353 	return 0;
354 }
355 
356 int igc_tsn_reset(struct igc_adapter *adapter)
357 {
358 	unsigned int new_flags;
359 	int err = 0;
360 
361 	new_flags = igc_tsn_new_flags(adapter);
362 
363 	if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
364 		return igc_tsn_disable_offload(adapter);
365 
366 	err = igc_tsn_enable_offload(adapter);
367 	if (err < 0)
368 		return err;
369 
370 	adapter->flags = new_flags;
371 
372 	return err;
373 }
374 
375 static bool igc_tsn_will_tx_mode_change(struct igc_adapter *adapter)
376 {
377 	bool any_tsn_enabled = !!(igc_tsn_new_flags(adapter) &
378 				  IGC_FLAG_TSN_ANY_ENABLED);
379 
380 	return (any_tsn_enabled && !igc_tsn_is_tx_mode_in_tsn(adapter)) ||
381 	       (!any_tsn_enabled && igc_tsn_is_tx_mode_in_tsn(adapter));
382 }
383 
384 int igc_tsn_offload_apply(struct igc_adapter *adapter)
385 {
386 	/* Per I225/6 HW Design Section 7.5.2.1 guideline, if tx mode change
387 	 * from legacy->tsn or tsn->legacy, then reset adapter is needed.
388 	 */
389 	if (netif_running(adapter->netdev) &&
390 	    igc_tsn_will_tx_mode_change(adapter)) {
391 		schedule_work(&adapter->reset_task);
392 		return 0;
393 	}
394 
395 	igc_tsn_reset(adapter);
396 
397 	return 0;
398 }
399