xref: /linux/drivers/net/ethernet/intel/igc/igc_tsn.c (revision eed4edda910fe34dfae8c6bfbcf57f4593a54295)
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 * 0x7736);
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 }
351