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