xref: /linux/drivers/net/ethernet/microchip/sparx5/sparx5_tas.c (revision a52629f85a3a97f76a12b9cb97717a36318a708e)
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver
3  *
4  * Copyright (c) 2026 Microchip Technology Inc. and its subsidiaries.
5  */
6 
7 #include <net/pkt_sched.h>
8 
9 #include "sparx5_main.h"
10 #include "sparx5_qos.h"
11 
12 enum sparx5_tas_link_speed {
13 	TAS_SPEED_NO_GB,
14 	TAS_SPEED_10,
15 	TAS_SPEED_100,
16 	TAS_SPEED_1000,
17 	TAS_SPEED_2500,
18 	TAS_SPEED_5000,
19 	TAS_SPEED_10000,
20 	TAS_SPEED_25000,
21 };
22 
23 /* Maximum time in milliseconds to wait for TAS state transitions. */
24 #define TAS_TIMEOUT_MS 2000
25 
26 /* Minimum supported cycle time in nanoseconds */
27 #define TAS_MIN_CYCLE_TIME_NS (1 * NSEC_PER_USEC) /* 1 usec */
28 
29 /* Maximum supported cycle time in nanoseconds */
30 #define TAS_MAX_CYCLE_TIME_NS ((1 * NSEC_PER_SEC) - 1) /* 999.999.999 nsec */
31 
32 /* STARTUP_TIME in units of 256 ns, must be non-zero for a list to start */
33 #define TAS_STARTUP_TIME_DEFAULT 8
34 
35 /* We use 2 TAS lists per present port, as far as the chip has lists:
36  * num_tas_lists = min(port_count * SPX5_TAS_ENTRIES_PER_PORT, n_tas_lists);
37  *
38  * The index for the 2 entries of the n'th present port is calculated as:
39  * index_1 = n * SPX5_TAS_ENTRIES_PER_PORT;
40  * index_2 = index_1 + 1;
41  *
42  * GCL entries are allocated from a bitmap shared by all ports and sized to the
43  * chip's GCL pool. Each list records the range it owns. The range is freed
44  * once hardware reports the list back in ADMIN, which for a list obsoleted by
45  * a replace happens some time after the replace itself. Entry 0 is reserved:
46  * unwritten NEXT_GCL fields read as 0, so a list must never own it.
47  *
48  * We use 1 TAS profile per port, shared by both of its lists:
49  * index = portno;
50  *
51  * We do not yet support frame preemption and the default guard band
52  * of 1536 bytes is always used on all queues.
53  *
54  * The gate mask of each entry is written as is to the port's 8 queues,
55  * where bit n gates queue (QoS class) n. The mqprio parameters of the
56  * taprio qdisc (prio_tc_map, queue ranges) are not used, so a schedule
57  * must use 8 traffic classes mapped 1:1 to the queues, as with the
58  * mqprio offload. Other values of num_tc are rejected.
59  *
60  * These are the possible combinations of states for the two TAS lists in a
61  * running system.
62  *
63  * ADMIN/ADMIN: No schedules are currently operating or pending.
64  *
65  * ADMIN/PENDING: No schedule is currently operating but one is pending and
66  * when current time exceeds the configured base time it will automatically
67  * enter the OPERATING state. The state is now ADMIN/OPERATING.
68  *
69  * ADMIN/OPERATING: A schedule is currently operating and will run until it is
70  * terminated manually.
71  *
72  * OPERATING/PENDING: A schedule is currently operating and another is
73  * pending. When current time exceeds the configured base time for the
74  * pending schedule it will automatically stop the operating schedule and
75  * enter the OPERATING state. The state is now ADMIN/OPERATING.
76  *
77  * When we want to disable TAS on a port, we must stop schedules that are in
78  * state PENDING or OPERATING.
79  * Pending schedules are stopped first and then operating schedules.
80  * The gate state for the port must be restored to "all-queues-open" manually
81  * in case the schedule was stopped with one or more of the queues closed.
82  *
83  * When we add a schedule we always use a base time in the future, where base
84  * time is at least current time + (2 * cycle time). This is a requirement
85  * from the hardware. This means that a schedule will always start in state
86  * PENDING. It also means that we always use the new schedule to stop an
87  * eventually operating schedule.
88  *
89  * When we want to add a new schedule we must consider the current state of
90  * the two TAS list entries:
91  *
92  * ADMIN/ADMIN: Just add the new schedule in one of the TAS lists.
93  *
94  * ADMIN/PENDING: Stop the current pending schedule and add the new one.
95  *
96  * ADMIN/OPERATING: Add the new schedule in the TAS list that is currently in
97  * admin state and configure it to stop the currently operating schedule when
98  * current time exceeds the configured base time in the new schedule.
99  *
100  * OPERATING/PENDING: Stop the current pending schedule, add the new one and
101  * configure it to stop the currently operating schedule when
102  * current time exceeds the configured base time in the new schedule.
103  */
104 
105 /* Scheduler element index (HSCH_POS) for this port's per-port TAS gate,
106  * i.e. its position at the layer-2 boundary of the scheduling hierarchy.
107  */
108 static int sparx5_tas_scheduler_get(struct sparx5 *sparx5, int portno)
109 {
110 	if (is_sparx5(sparx5))
111 		return SPX5_HSCH_L0_SE_CNT + SPX5_HSCH_L1_SE_CNT + portno;
112 	else
113 		return 1120 + portno;
114 }
115 
116 static int sparx5_tas_list_index(struct sparx5_port *port, u8 tas_entry)
117 {
118 	const struct sparx5_consts *consts = port->sparx5->data->consts;
119 	int portno, pidx = 0;
120 
121 	/* Limit the index to available ports: the n'th present port uses
122 	 * lists 2n and 2n + 1, so the lists of all ports fit in
123 	 * port_count * SPX5_TAS_ENTRIES_PER_PORT.
124 	 */
125 	for (portno = 0; portno < consts->n_ports; ++portno) {
126 		if (portno == port->portno)
127 			return (pidx * SPX5_TAS_ENTRIES_PER_PORT) + tas_entry;
128 		if (port->sparx5->ports[portno])
129 			pidx++;
130 	}
131 
132 	return 0;
133 }
134 
135 /* Number of TAS lists in use: two per present port, as far as the chip has
136  * lists for. A port whose lists fall outside this range has no TAS.
137  */
138 static int sparx5_tas_num_lists(struct sparx5 *sparx5)
139 {
140 	return min_t(int, sparx5->port_count * SPX5_TAS_ENTRIES_PER_PORT,
141 		     sparx5->data->consts->n_tas_lists);
142 }
143 
144 static bool sparx5_tas_port_has_lists(struct sparx5_port *port)
145 {
146 	return sparx5_tas_list_index(port, SPX5_TAS_ENTRIES_PER_PORT - 1) <
147 	       sparx5_tas_num_lists(port->sparx5);
148 }
149 
150 static const char *sparx5_tas_state_to_str(int state)
151 {
152 	switch (state) {
153 	case SPX5_TAS_STATE_ADMIN:
154 		return "ADMIN";
155 	case SPX5_TAS_STATE_ADVANCING:
156 		return "ADVANCING";
157 	case SPX5_TAS_STATE_PENDING:
158 		return "PENDING";
159 	case SPX5_TAS_STATE_OPERATING:
160 		return "OPERATING";
161 	case SPX5_TAS_STATE_TERMINATING:
162 		return "TERMINATING";
163 	default:
164 		return "??";
165 	}
166 }
167 
168 static void sparx5_tas_select_list(struct sparx5 *sparx5, int list)
169 {
170 	spx5_rmw(HSCH_TAS_CFG_CTRL_LIST_NUM_SET(list),
171 		 HSCH_TAS_CFG_CTRL_LIST_NUM,
172 		 sparx5,
173 		 HSCH_TAS_CFG_CTRL);
174 }
175 
176 static int sparx5_tas_list_state_get(struct sparx5 *sparx5)
177 {
178 	return HSCH_TAS_LIST_STATE_LIST_STATE_GET(spx5_rd(sparx5,
179 							  HSCH_TAS_LIST_STATE));
180 }
181 
182 static int sparx5_tas_gcl_alloc(struct sparx5 *sparx5, int count)
183 {
184 	u32 n_gcl = sparx5->data->consts->n_tas_gcl;
185 	unsigned long base;
186 
187 	base = bitmap_find_next_zero_area(sparx5->tas_gcl_bitmap,
188 					  n_gcl,
189 					  0,
190 					  count,
191 					  0);
192 	if (base >= n_gcl)
193 		return -ENOSPC;
194 
195 	bitmap_set(sparx5->tas_gcl_bitmap, base, count);
196 
197 	return base;
198 }
199 
200 static void sparx5_tas_gcl_free(struct sparx5_port *port, int slot)
201 {
202 	if (port->tas_lists[slot].gcl_count)
203 		bitmap_clear(port->sparx5->tas_gcl_bitmap,
204 			     port->tas_lists[slot].gcl_base,
205 			     port->tas_lists[slot].gcl_count);
206 
207 	port->tas_lists[slot].gcl_base = 0;
208 	port->tas_lists[slot].gcl_count = 0;
209 }
210 
211 /* Free the GCL entries of every list that hardware has returned to ADMIN */
212 static void sparx5_tas_gcl_flush(struct sparx5 *sparx5)
213 {
214 	struct sparx5_port *port;
215 	int i, j;
216 
217 	lockdep_assert_held(&sparx5->tas_lock);
218 
219 	for (i = 0; i < sparx5->data->consts->n_ports; i++) {
220 		port = sparx5->ports[i];
221 		if (!port)
222 			continue;
223 
224 		for (j = 0; j < SPX5_TAS_ENTRIES_PER_PORT; j++) {
225 			if (!port->tas_lists[j].gcl_count)
226 				continue;
227 
228 			sparx5_tas_select_list(sparx5,
229 					       sparx5_tas_list_index(port, j));
230 			if (sparx5_tas_list_state_get(sparx5) ==
231 			    SPX5_TAS_STATE_ADMIN)
232 				sparx5_tas_gcl_free(port, j);
233 		}
234 	}
235 }
236 
237 /* Request state 'req' (or only wait if 'req' < 0) on the selected list until
238  * it reaches a state in the 'done' mask.
239  */
240 static int sparx5_tas_list_state_wait(struct sparx5_port *port, int list,
241 				      int req, u32 done)
242 {
243 	struct sparx5 *sparx5 = port->sparx5;
244 	unsigned long end;
245 	int state;
246 
247 	/* Do not wait forever for the state change */
248 	end = jiffies + msecs_to_jiffies(TAS_TIMEOUT_MS);
249 	do {
250 		if (req >= 0)
251 			spx5_rmw(HSCH_TAS_LIST_STATE_LIST_STATE_SET(req),
252 				 HSCH_TAS_LIST_STATE_LIST_STATE,
253 				 sparx5,
254 				 HSCH_TAS_LIST_STATE);
255 
256 		state = sparx5_tas_list_state_get(sparx5);
257 		if (BIT(state) & done)
258 			return 0;
259 
260 		cond_resched();
261 	} while (!time_after(jiffies, end));
262 
263 	netdev_err(port->ndev, "Timeout switching TAS state %s in list %d\n",
264 		   sparx5_tas_state_to_str(state), list);
265 
266 	return -ETIME;
267 }
268 
269 /* Wait for hardware to bring the selected list back to ADMIN */
270 static int sparx5_tas_wait_admin(struct sparx5_port *port, int list)
271 {
272 	return sparx5_tas_list_state_wait(port, list, -1,
273 					  BIT(SPX5_TAS_STATE_ADMIN));
274 }
275 
276 static int sparx5_tas_shutdown_pending(struct sparx5_port *port)
277 {
278 	struct sparx5 *sparx5 = port->sparx5;
279 	int i, list, state, err;
280 
281 	for (i = 0; i < SPX5_TAS_ENTRIES_PER_PORT; i++) {
282 		list = sparx5_tas_list_index(port, i);
283 		spx5_rmw(HSCH_TAS_CFG_CTRL_LIST_NUM_SET(list),
284 			 HSCH_TAS_CFG_CTRL_LIST_NUM,
285 			 sparx5,
286 			 HSCH_TAS_CFG_CTRL);
287 
288 		state = sparx5_tas_list_state_get(sparx5);
289 		if (state != SPX5_TAS_STATE_ADVANCING &&
290 		    state != SPX5_TAS_STATE_PENDING)
291 			continue;
292 
293 		err = sparx5_tas_list_state_wait(port, list,
294 						 SPX5_TAS_STATE_ADMIN,
295 						 BIT(SPX5_TAS_STATE_ADMIN));
296 		if (err)
297 			return err;
298 
299 		sparx5_tas_gcl_free(port, i);
300 	}
301 
302 	return 0;
303 }
304 
305 static int sparx5_tas_shutdown_operating(struct sparx5_port *port)
306 {
307 	struct sparx5 *sparx5 = port->sparx5;
308 	int i, list, state, err = 0;
309 	u32 sched;
310 
311 	sched = sparx5_tas_scheduler_get(sparx5, port->portno);
312 
313 	for (i = 0; i < SPX5_TAS_ENTRIES_PER_PORT; i++) {
314 		list = sparx5_tas_list_index(port, i);
315 		spx5_rmw(HSCH_TAS_CFG_CTRL_LIST_NUM_SET(list),
316 			 HSCH_TAS_CFG_CTRL_LIST_NUM,
317 			 sparx5,
318 			 HSCH_TAS_CFG_CTRL);
319 
320 		/* A list being stopped still runs its gate operations until
321 		 * the end of its cycle, so wait for it before opening the
322 		 * gates.
323 		 */
324 		state = sparx5_tas_list_state_get(sparx5);
325 		if (state != SPX5_TAS_STATE_OPERATING &&
326 		    state != SPX5_TAS_STATE_TERMINATING)
327 			continue;
328 
329 		if (state == SPX5_TAS_STATE_OPERATING &&
330 		    sparx5_tas_list_state_wait(port, list,
331 					       SPX5_TAS_STATE_TERMINATING,
332 					       BIT(SPX5_TAS_STATE_TERMINATING) |
333 					       BIT(SPX5_TAS_STATE_ADMIN))) {
334 			err = -ETIME;
335 			continue;
336 		}
337 
338 		if (sparx5_tas_wait_admin(port, list)) {
339 			err = -ETIME;
340 			continue;
341 		}
342 
343 		sparx5_tas_gcl_free(port, i);
344 	}
345 
346 	/* Restore gate state to "all-queues-open". */
347 
348 	/* Select port n on layer 2 of Hierarchical Scheduler */
349 	spx5_wr(HSCH_TAS_GATE_STATE_CTRL_HSCH_POS_SET(sched),
350 		sparx5,
351 		HSCH_TAS_GATE_STATE_CTRL);
352 
353 	/* Set gate state to "all-queues-open" */
354 	spx5_wr(HSCH_TAS_GATE_STATE_TAS_GATE_STATE_SET(0xff),
355 		sparx5,
356 		HSCH_TAS_GATE_STATE);
357 
358 	return err;
359 }
360 
361 /* Find an ADMIN list for a new schedule, after stopping a pending one. An
362  * operating list is returned in obsolete, to be stopped by the new list.
363  */
364 static int sparx5_tas_list_find(struct sparx5_port *port, int *new,
365 				int *obsolete)
366 {
367 	int i, err, oper = -1, state_cnt[SPX5_NUM_TAS_STATE] = {0};
368 	struct sparx5 *sparx5 = port->sparx5;
369 	int state[SPX5_TAS_ENTRIES_PER_PORT];
370 	int list[SPX5_TAS_ENTRIES_PER_PORT];
371 	bool valid = false;
372 
373 	err = sparx5_tas_shutdown_pending(port);
374 	if (err)
375 		return err;
376 
377 	for (i = 0; i < SPX5_TAS_ENTRIES_PER_PORT; i++) {
378 		list[i] = sparx5_tas_list_index(port, i);
379 		spx5_rmw(HSCH_TAS_CFG_CTRL_LIST_NUM_SET(list[i]),
380 			 HSCH_TAS_CFG_CTRL_LIST_NUM,
381 			 sparx5,
382 			 HSCH_TAS_CFG_CTRL);
383 
384 		state[i] = sparx5_tas_list_state_get(sparx5);
385 
386 		if (state[i] == SPX5_TAS_STATE_TERMINATING) {
387 			err = sparx5_tas_wait_admin(port, list[i]);
388 			if (err)
389 				return err;
390 			state[i] = SPX5_TAS_STATE_ADMIN;
391 		}
392 
393 		if (state[i] >= SPX5_NUM_TAS_STATE) {
394 			netdev_err(port->ndev,
395 				   "Invalid tas list state %u %u %d\n",
396 				   state[i], port->portno, i);
397 			return -EINVAL;
398 		}
399 
400 		if (state[i] == SPX5_TAS_STATE_OPERATING)
401 			oper = list[i];
402 
403 		state_cnt[state[i]]++;
404 	}
405 
406 	if (state_cnt[SPX5_TAS_STATE_ADMIN] == 2)
407 		valid = true;
408 
409 	if (state_cnt[SPX5_TAS_STATE_ADMIN] == 1 &&
410 	    state_cnt[SPX5_TAS_STATE_OPERATING] == 1)
411 		valid = true;
412 
413 	if (!valid) {
414 		netdev_err(port->ndev,
415 			   "Invalid tas state combination: %d %d %d %d %d\n",
416 			   state_cnt[SPX5_TAS_STATE_ADMIN],
417 			   state_cnt[SPX5_TAS_STATE_ADVANCING],
418 			   state_cnt[SPX5_TAS_STATE_PENDING],
419 			   state_cnt[SPX5_TAS_STATE_OPERATING],
420 			   state_cnt[SPX5_TAS_STATE_TERMINATING]);
421 
422 		return -EINVAL;
423 	}
424 
425 	for (i = 0; i < SPX5_TAS_ENTRIES_PER_PORT; i++) {
426 		if (state[i] == SPX5_TAS_STATE_ADMIN) {
427 			*new = list[i];
428 			*obsolete = (oper == -1) ? *new : oper;
429 			return 0;
430 		}
431 	}
432 
433 	return -EBUSY; /* No suitable list found */
434 }
435 
436 /* Program the list and its GCL entries [base, base + num_entries) */
437 static void sparx5_tas_gcl_setup(struct sparx5_port *port, int list, int base,
438 				 struct tc_taprio_qopt_offload *qopt)
439 {
440 	struct sparx5 *sparx5 = port->sparx5;
441 	u32 sched, entry, prof;
442 	int i;
443 
444 	sched = sparx5_tas_scheduler_get(sparx5, port->portno);
445 	/* Each port uses the TAS profile of its own number */
446 	prof = port->portno;
447 
448 	/* Program only the chosen list; the sibling slot stays in ADMIN. */
449 	sparx5_tas_select_list(sparx5, list);
450 
451 	spx5_rmw(HSCH_TAS_LIST_CFG_LIST_BASE_ADDR_SET(base),
452 		 HSCH_TAS_LIST_CFG_LIST_BASE_ADDR,
453 		 sparx5,
454 		 HSCH_TAS_LIST_CFG);
455 
456 	if (is_sparx5(sparx5)) {
457 		spx5_rmw(HSCH_TAS_LIST_CFG_LIST_LENGTH_SET(qopt->num_entries),
458 			 HSCH_TAS_LIST_CFG_LIST_LENGTH,
459 			 sparx5,
460 			 HSCH_TAS_LIST_CFG);
461 	} else {
462 		/* Associate TAS list with physical port number and
463 		 * scheduler element.
464 		 */
465 		spx5_rmw(HSCH_TAS_LIST_CFG_LIST_PORT_NUM_SET(port->portno),
466 			 HSCH_TAS_LIST_CFG_LIST_PORT_NUM, sparx5,
467 			 HSCH_TAS_LIST_CFG);
468 		spx5_rmw(HSCH_TAS_LIST_CFG_LIST_HSCH_POS_SET(sched),
469 			 HSCH_TAS_LIST_CFG_LIST_HSCH_POS, sparx5,
470 			 HSCH_TAS_LIST_CFG);
471 	}
472 
473 	for (i = 0; i < qopt->num_entries; i++) {
474 		u32 gcl_next = (i >= qopt->num_entries - 1) ? base :
475 							       base + i + 1;
476 		u32 gate_mask = qopt->entries[i].gate_mask;
477 
478 		/* On sparx5 GCL_ENTRY_NUM is relative to the list's BASE_ADDR.
479 		 * On lan969x the GCL is a linked list and GCL_ENTRY_NUM is an
480 		 * absolute index into the pool, as is NEXT_GCL.
481 		 */
482 		entry = is_sparx5(sparx5) ? i : base + i;
483 
484 		spx5_rmw(HSCH_TAS_CFG_CTRL_GCL_ENTRY_NUM_SET(entry),
485 			 HSCH_TAS_CFG_CTRL_GCL_ENTRY_NUM,
486 			 sparx5,
487 			 HSCH_TAS_CFG_CTRL);
488 
489 		/* Set gate states for this GCL */
490 		spx5_rmw(HSCH_TAS_GCL_CTRL_CFG_GATE_STATE_SET(gate_mask),
491 			 HSCH_TAS_GCL_CTRL_CFG_GATE_STATE, sparx5,
492 			 HSCH_TAS_GCL_CTRL_CFG);
493 
494 		if (is_sparx5(sparx5)) {
495 			spx5_rmw(HSCH_TAS_GCL_CTRL_CFG_HSCH_POS_SET(sched) |
496 				 HSCH_TAS_GCL_CTRL_CFG_PORT_PROFILE_SET(prof),
497 				 HSCH_TAS_GCL_CTRL_CFG_HSCH_POS |
498 				 HSCH_TAS_GCL_CTRL_CFG_PORT_PROFILE, sparx5,
499 				 HSCH_TAS_GCL_CTRL_CFG);
500 		} else {
501 			/* The GCL list is a linked list on lan969x */
502 			spx5_wr(HSCH_TAS_GCL_CTRL_CFG2_NEXT_GCL_SET(gcl_next),
503 				sparx5, HSCH_TAS_GCL_CTRL_CFG2);
504 		}
505 
506 		spx5_wr(qopt->entries[i].interval,
507 			sparx5,
508 			HSCH_TAS_GCL_TIME_CFG);
509 	}
510 }
511 
512 int sparx5_tas_enable(struct sparx5_port *port,
513 		      struct tc_taprio_qopt_offload *qopt)
514 {
515 	u64 cycle_time = qopt->cycle_time, calculated_cycle_time = 0;
516 	int i, err, base, slot, state, new_list = -1, obsolete = -1;
517 	struct sparx5 *sparx5 = port->sparx5;
518 	struct timespec64 ts;
519 	ktime_t base_time;
520 	unsigned long end;
521 	u32 startup, val;
522 
523 	if (qopt->cycle_time_extension) {
524 		netdev_err(port->ndev,
525 			   "cycle_time_extension is not supported\n");
526 		return -EOPNOTSUPP;
527 	}
528 
529 	/* The base time is taken from the PTP clock */
530 	if (!sparx5->ptp)
531 		return -EOPNOTSUPP;
532 
533 	if (qopt->base_time < 0) {
534 		netdev_err(port->ndev, "Invalid base_time %lld\n",
535 			   qopt->base_time);
536 		return -EINVAL;
537 	}
538 
539 	if (!sparx5_tas_port_has_lists(port)) {
540 		netdev_err(port->ndev, "No TAS lists left for this port\n");
541 		return -EOPNOTSUPP;
542 	}
543 
544 	if (qopt->mqprio.qopt.num_tc != SPX5_PRIOS) {
545 		netdev_err(port->ndev, "Only %d traffic classes supported\n",
546 			   SPX5_PRIOS);
547 		return -EOPNOTSUPP;
548 	}
549 
550 	for (i = 0; i < qopt->num_entries; i++) {
551 		if (qopt->entries[i].command != TC_TAPRIO_CMD_SET_GATES) {
552 			netdev_err(port->ndev, "Unsupported GCL command: %d\n",
553 				   qopt->entries[i].command);
554 			return -EOPNOTSUPP;
555 		}
556 	}
557 
558 	mutex_lock(&sparx5->tas_lock);
559 
560 	sparx5_tas_gcl_flush(sparx5);
561 
562 	if (cycle_time > TAS_MAX_CYCLE_TIME_NS) {
563 		netdev_err(port->ndev, "Invalid cycle_time %llu\n", cycle_time);
564 		err = -EINVAL;
565 		goto out;
566 	}
567 
568 	for (i = 0; i < qopt->num_entries; i++) {
569 		u32 interval = qopt->entries[i].interval;
570 
571 		if (interval < TAS_MIN_CYCLE_TIME_NS) {
572 			netdev_err(port->ndev,
573 				   "Invalid minimum cycle time %u\n", interval);
574 			err = -EINVAL;
575 			goto out;
576 		}
577 
578 		if (interval > TAS_MAX_CYCLE_TIME_NS) {
579 			netdev_err(port->ndev,
580 				   "Invalid maximum cycle time %u\n", interval);
581 			err = -EINVAL;
582 			goto out;
583 		}
584 
585 		calculated_cycle_time += interval;
586 	}
587 
588 	if (calculated_cycle_time > TAS_MAX_CYCLE_TIME_NS ||
589 	    cycle_time < calculated_cycle_time) {
590 		netdev_err(port->ndev, "Invalid cycle_time %llu\n", cycle_time);
591 		err = -EINVAL;
592 		goto out;
593 	}
594 
595 	sparx5_new_base_time(sparx5, cycle_time, qopt->base_time, &base_time);
596 
597 	/* Allocate before sparx5_tas_list_find() stops a pending schedule, so
598 	 * running out of GCL entries fails the replace without touching
599 	 * hardware.
600 	 */
601 	base = sparx5_tas_gcl_alloc(sparx5, qopt->num_entries);
602 	if (base < 0) {
603 		netdev_err(port->ndev, "No room for %zu GCL entries\n",
604 			   qopt->num_entries);
605 		err = base;
606 		goto out;
607 	}
608 
609 	/* Select an appropriate entry to use */
610 	err = sparx5_tas_list_find(port, &new_list, &obsolete);
611 	if (err) {
612 		bitmap_clear(sparx5->tas_gcl_bitmap, base, qopt->num_entries);
613 		goto out;
614 	}
615 
616 	/* The new list is in ADMIN, so a range it still owns can go */
617 	slot = new_list - sparx5_tas_list_index(port, 0);
618 	sparx5_tas_gcl_free(port, slot);
619 
620 	sparx5_tas_gcl_setup(port, new_list, base, qopt);
621 
622 	/* The obsolete list keeps its entries until it reaches ADMIN */
623 	port->tas_lists[slot].gcl_base = base;
624 	port->tas_lists[slot].gcl_count = qopt->num_entries;
625 
626 	/* Setup TAS list */
627 	ts = ktime_to_timespec64(base_time);
628 	spx5_wr(HSCH_TAS_BASE_TIME_NSEC_BASE_TIME_NSEC_SET(ts.tv_nsec),
629 		sparx5,
630 		HSCH_TAS_BASE_TIME_NSEC);
631 
632 	spx5_wr((ts.tv_sec & GENMASK(31, 0)),
633 		sparx5,
634 		HSCH_TAS_BASE_TIME_SEC_LSB);
635 
636 	val = ts.tv_sec >> 32;
637 	spx5_wr(HSCH_TAS_BASE_TIME_SEC_MSB_BASE_TIME_SEC_MSB_SET(val),
638 		sparx5,
639 		HSCH_TAS_BASE_TIME_SEC_MSB);
640 
641 	spx5_wr(cycle_time,
642 		sparx5,
643 		HSCH_TAS_CYCLE_TIME_CFG);
644 
645 	/* Full write, to also clear a sticky STARTUP_ERROR from a previous use
646 	 * of this list.
647 	 */
648 	spx5_wr(HSCH_TAS_STARTUP_CFG_OBSOLETE_IDX_SET(obsolete) |
649 		HSCH_TAS_STARTUP_CFG_STARTUP_TIME_SET(TAS_STARTUP_TIME_DEFAULT),
650 		sparx5,
651 		HSCH_TAS_STARTUP_CFG);
652 
653 	/* Start list processing */
654 	spx5_rmw(HSCH_TAS_LIST_STATE_LIST_STATE_SET(SPX5_TAS_STATE_ADVANCING),
655 		 HSCH_TAS_LIST_STATE_LIST_STATE,
656 		 sparx5,
657 		 HSCH_TAS_LIST_STATE);
658 
659 	/* Do not wait forever for the startup error flag to be reported */
660 	end = jiffies + msecs_to_jiffies(TAS_TIMEOUT_MS);
661 	do {
662 		/* Read the state first, so an error that ended ADVANCING is
663 		 * already latched when STARTUP_CFG is read.
664 		 */
665 		val = spx5_rd(sparx5, HSCH_TAS_LIST_STATE);
666 		state = HSCH_TAS_LIST_STATE_LIST_STATE_GET(val);
667 		startup = spx5_rd(sparx5, HSCH_TAS_STARTUP_CFG);
668 		if (HSCH_TAS_STARTUP_CFG_STARTUP_ERROR_GET(startup) ||
669 		    state != SPX5_TAS_STATE_ADVANCING)
670 			break;
671 
672 		cond_resched();
673 	} while (!time_after(jiffies, end));
674 
675 	if (HSCH_TAS_STARTUP_CFG_STARTUP_ERROR_GET(startup)) {
676 		netdev_err(port->ndev, "TAS startup error in list %d\n",
677 			   new_list);
678 		err = -EIO;
679 	} else if (state == SPX5_TAS_STATE_ADVANCING) {
680 		netdev_err(port->ndev, "Timeout starting TAS list %d\n",
681 			   new_list);
682 		err = -ETIME;
683 	}
684 
685 	/* taprio sends no DESTROY for a failed offload, so do not leave a
686 	 * list behind that may still start.
687 	 */
688 	if (err)
689 		sparx5_tas_shutdown_pending(port);
690 
691 out:
692 	mutex_unlock(&sparx5->tas_lock);
693 	return err;
694 }
695 
696 int sparx5_tas_disable(struct sparx5_port *port)
697 {
698 	int err, ret;
699 
700 	/* Nothing was offloaded on a port without lists */
701 	if (!sparx5_tas_port_has_lists(port))
702 		return 0;
703 
704 	mutex_lock(&port->sparx5->tas_lock);
705 
706 	sparx5_tas_gcl_flush(port->sparx5);
707 
708 	/* Stop the operating list and restore the gates even if a pending list
709 	 * could not be stopped, as taprio does not retry a failed destroy.
710 	 */
711 	err = sparx5_tas_shutdown_pending(port);
712 	ret = sparx5_tas_shutdown_operating(port);
713 	if (!err)
714 		err = ret;
715 
716 	mutex_unlock(&port->sparx5->tas_lock);
717 
718 	return err;
719 }
720 
721 int sparx5_tas_init(struct sparx5 *sparx5)
722 {
723 	const struct sparx5_consts *consts = sparx5->data->consts;
724 	int i, num_ports, list_num_max;
725 
726 	/* There are only 128 (sparx5) / 60 (lan969x) TAS lists, not enough
727 	 * for the whole port range. LIST_NUM_MAX is the highest list index
728 	 * processed, and the datasheet gives 24 as its minimum value.
729 	 */
730 	num_ports = consts->n_ports;
731 	list_num_max = max(sparx5_tas_num_lists(sparx5) - 1, 24);
732 
733 	sparx5->tas_gcl_bitmap = devm_bitmap_zalloc(sparx5->dev,
734 						    consts->n_tas_gcl,
735 						    GFP_KERNEL);
736 	if (!sparx5->tas_gcl_bitmap)
737 		return -ENOMEM;
738 
739 	/* Unwritten NEXT_GCL fields read as 0, so no list may own entry 0 */
740 	bitmap_set(sparx5->tas_gcl_bitmap, 0, 1);
741 
742 	mutex_init(&sparx5->tas_lock);
743 
744 	/* Apply the guard band to gate closes of all traffic classes, not only
745 	 * the classes not marked as scheduled in SCH_TRAFFIC_QUEUES.
746 	 */
747 	spx5_rmw(HSCH_TAS_CFG_CTRL_LIST_NUM_MAX_SET(list_num_max) |
748 		 HSCH_TAS_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q_SET(1),
749 		 HSCH_TAS_CFG_CTRL_LIST_NUM_MAX |
750 		 HSCH_TAS_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q,
751 		 sparx5,
752 		 HSCH_TAS_CFG_CTRL);
753 
754 	/* Associate profile with port (profile idx = port on lan969x) */
755 	if (is_sparx5(sparx5)) {
756 		for (i = 0; i < num_ports; i++) {
757 			if (!sparx5->ports[i])
758 				continue;
759 
760 			spx5_rmw(HSCH_TAS_PROFILE_CONFIG_PORT_NUM_SET(i),
761 				 HSCH_TAS_PROFILE_CONFIG_PORT_NUM,
762 				 sparx5,
763 				 HSCH_TAS_PROFILE_CONFIG(i));
764 		}
765 	}
766 
767 	return 0;
768 }
769 
770 void sparx5_tas_speed(struct sparx5_port *port, int speed)
771 {
772 	struct sparx5 *sparx5 = port->sparx5;
773 	u8 spd;
774 
775 	switch (speed) {
776 	case SPEED_10:
777 		spd = TAS_SPEED_10;
778 		break;
779 	case SPEED_100:
780 		spd = TAS_SPEED_100;
781 		break;
782 	case SPEED_1000:
783 		spd = TAS_SPEED_1000;
784 		break;
785 	case SPEED_2500:
786 		spd = TAS_SPEED_2500;
787 		break;
788 	case SPEED_5000:
789 		spd = TAS_SPEED_5000;
790 		break;
791 	case SPEED_10000:
792 		spd = TAS_SPEED_10000;
793 		break;
794 	case SPEED_25000:
795 		spd = TAS_SPEED_25000;
796 		break;
797 	default:
798 		netdev_err(port->ndev, "TAS: Unsupported speed: %d\n", speed);
799 		return;
800 	}
801 
802 	spx5_rmw(HSCH_TAS_PROFILE_CONFIG_LINK_SPEED_SET(spd),
803 		 HSCH_TAS_PROFILE_CONFIG_LINK_SPEED,
804 		 sparx5,
805 		 HSCH_TAS_PROFILE_CONFIG(port->portno));
806 }
807