Lines Matching +full:cycle +full:- +full:0

1 // SPDX-License-Identifier: GPL-2.0
6 #define SJA1105_TAS_CLKSRC_DISABLED 0
10 #define SJA1105_GATE_MASK GENMASK_ULL(SJA1105_NUM_TC - 1, 0)
19 struct sja1105_tas_data *tas_data = &priv->tas_data; in sja1105_tas_set_runtime_params()
20 struct sja1105_gating_config *gating_cfg = &tas_data->gating_cfg; in sja1105_tas_set_runtime_params()
21 struct dsa_switch *ds = priv->ds; in sja1105_tas_set_runtime_params()
23 s64 latest_base_time = 0; in sja1105_tas_set_runtime_params()
24 s64 its_cycle_time = 0; in sja1105_tas_set_runtime_params()
25 s64 max_cycle_time = 0; in sja1105_tas_set_runtime_params()
28 tas_data->enabled = false; in sja1105_tas_set_runtime_params()
30 for (port = 0; port < ds->num_ports; port++) { in sja1105_tas_set_runtime_params()
33 offload = tas_data->offload[port]; in sja1105_tas_set_runtime_params()
37 tas_data->enabled = true; in sja1105_tas_set_runtime_params()
39 if (max_cycle_time < offload->cycle_time) in sja1105_tas_set_runtime_params()
40 max_cycle_time = offload->cycle_time; in sja1105_tas_set_runtime_params()
41 if (latest_base_time < offload->base_time) in sja1105_tas_set_runtime_params()
42 latest_base_time = offload->base_time; in sja1105_tas_set_runtime_params()
43 if (earliest_base_time > offload->base_time) { in sja1105_tas_set_runtime_params()
44 earliest_base_time = offload->base_time; in sja1105_tas_set_runtime_params()
45 its_cycle_time = offload->cycle_time; in sja1105_tas_set_runtime_params()
49 if (!list_empty(&gating_cfg->entries)) { in sja1105_tas_set_runtime_params()
50 tas_data->enabled = true; in sja1105_tas_set_runtime_params()
52 if (max_cycle_time < gating_cfg->cycle_time) in sja1105_tas_set_runtime_params()
53 max_cycle_time = gating_cfg->cycle_time; in sja1105_tas_set_runtime_params()
54 if (latest_base_time < gating_cfg->base_time) in sja1105_tas_set_runtime_params()
55 latest_base_time = gating_cfg->base_time; in sja1105_tas_set_runtime_params()
56 if (earliest_base_time > gating_cfg->base_time) { in sja1105_tas_set_runtime_params()
57 earliest_base_time = gating_cfg->base_time; in sja1105_tas_set_runtime_params()
58 its_cycle_time = gating_cfg->cycle_time; in sja1105_tas_set_runtime_params()
62 if (!tas_data->enabled) in sja1105_tas_set_runtime_params()
63 return 0; in sja1105_tas_set_runtime_params()
74 earliest_base_time -= its_cycle_time; in sja1105_tas_set_runtime_params()
75 if (latest_base_time - earliest_base_time > in sja1105_tas_set_runtime_params()
77 dev_err(ds->dev, in sja1105_tas_set_runtime_params()
80 return -ERANGE; in sja1105_tas_set_runtime_params()
83 tas_data->earliest_base_time = earliest_base_time; in sja1105_tas_set_runtime_params()
84 tas_data->max_cycle_time = max_cycle_time; in sja1105_tas_set_runtime_params()
86 dev_dbg(ds->dev, "earliest base time %lld ns\n", earliest_base_time); in sja1105_tas_set_runtime_params()
87 dev_dbg(ds->dev, "latest base time %lld ns\n", latest_base_time); in sja1105_tas_set_runtime_params()
88 dev_dbg(ds->dev, "longest cycle time %lld ns\n", max_cycle_time); in sja1105_tas_set_runtime_params()
90 return 0; in sja1105_tas_set_runtime_params()
95 * At the hardware level, the Time-Aware Shaper holds a global linear arrray of
101 * iterate cyclically through the "schedule". Each "cycle" has an entry point
103 * hardware calls each cycle a "subschedule".
105 * Subschedule (cycle) i starts when
115 * +---------+
117 * +---------+
119 * +-----------------+
122 * +-------+-------+
123 * |cycle 0|cycle 1|
124 * +-------+-------+
126 * +----------------+ | | +-------------------------------------+
128 * | | +---------------+ |
133 * | +-------+-------+-------+-------+-------+------+ |
134 * | |entry 0|entry 1|entry 2|entry 3|entry 4|entry5| |
135 * | +-------+-------+-------+-------+-------+------+ |
138 * | +-------------------------+ | | | |
139 * | | +-------------------------------+ | | |
140 * | | | +-------------------+ | |
142 * | +---------------------------------------------------------------+ |
143 * | |subscheind[0]<=subscheind[1]<=subscheind[2]<=...<=subscheind[7]| |
144 * | +---------------------------------------------------------------+ |
147 * +--------+ +-------------------------------------------+
151 * - cycle 0: iterates the schedule table from 0 to 2 (and back)
152 * - cycle 1: iterates the schedule table from 3 to 5 (and back)
164 struct sja1105_tas_data *tas_data = &priv->tas_data; in sja1105_init_scheduling()
165 struct sja1105_gating_config *gating_cfg = &tas_data->gating_cfg; in sja1105_init_scheduling()
167 struct dsa_switch *ds = priv->ds; in sja1105_init_scheduling()
172 int num_entries = 0; in sja1105_init_scheduling()
173 int num_cycles = 0; in sja1105_init_scheduling()
174 int cycle = 0; in sja1105_init_scheduling() local
175 int i, k = 0; in sja1105_init_scheduling()
179 if (rc < 0) in sja1105_init_scheduling()
183 table = &priv->static_config.tables[BLK_IDX_SCHEDULE]; in sja1105_init_scheduling()
184 if (table->entry_count) { in sja1105_init_scheduling()
185 kfree(table->entries); in sja1105_init_scheduling()
186 table->entry_count = 0; in sja1105_init_scheduling()
190 table = &priv->static_config.tables[BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS]; in sja1105_init_scheduling()
191 if (table->entry_count) { in sja1105_init_scheduling()
192 kfree(table->entries); in sja1105_init_scheduling()
193 table->entry_count = 0; in sja1105_init_scheduling()
197 table = &priv->static_config.tables[BLK_IDX_SCHEDULE_PARAMS]; in sja1105_init_scheduling()
198 if (table->entry_count) { in sja1105_init_scheduling()
199 kfree(table->entries); in sja1105_init_scheduling()
200 table->entry_count = 0; in sja1105_init_scheduling()
204 table = &priv->static_config.tables[BLK_IDX_SCHEDULE_ENTRY_POINTS]; in sja1105_init_scheduling()
205 if (table->entry_count) { in sja1105_init_scheduling()
206 kfree(table->entries); in sja1105_init_scheduling()
207 table->entry_count = 0; in sja1105_init_scheduling()
211 for (port = 0; port < ds->num_ports; port++) { in sja1105_init_scheduling()
212 if (tas_data->offload[port]) { in sja1105_init_scheduling()
213 num_entries += tas_data->offload[port]->num_entries; in sja1105_init_scheduling()
218 if (!list_empty(&gating_cfg->entries)) { in sja1105_init_scheduling()
219 num_entries += gating_cfg->num_entries; in sja1105_init_scheduling()
225 return 0; in sja1105_init_scheduling()
227 /* Pre-allocate space in the static config tables */ in sja1105_init_scheduling()
230 table = &priv->static_config.tables[BLK_IDX_SCHEDULE]; in sja1105_init_scheduling()
231 table->entries = kcalloc(num_entries, table->ops->unpacked_entry_size, in sja1105_init_scheduling()
233 if (!table->entries) in sja1105_init_scheduling()
234 return -ENOMEM; in sja1105_init_scheduling()
235 table->entry_count = num_entries; in sja1105_init_scheduling()
236 schedule = table->entries; in sja1105_init_scheduling()
239 table = &priv->static_config.tables[BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS]; in sja1105_init_scheduling()
240 table->entries = kcalloc(SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT, in sja1105_init_scheduling()
241 table->ops->unpacked_entry_size, GFP_KERNEL); in sja1105_init_scheduling()
242 if (!table->entries) in sja1105_init_scheduling()
247 return -ENOMEM; in sja1105_init_scheduling()
248 table->entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT; in sja1105_init_scheduling()
249 schedule_entry_points_params = table->entries; in sja1105_init_scheduling()
252 table = &priv->static_config.tables[BLK_IDX_SCHEDULE_PARAMS]; in sja1105_init_scheduling()
253 table->entries = kcalloc(SJA1105_MAX_SCHEDULE_PARAMS_COUNT, in sja1105_init_scheduling()
254 table->ops->unpacked_entry_size, GFP_KERNEL); in sja1105_init_scheduling()
255 if (!table->entries) in sja1105_init_scheduling()
256 return -ENOMEM; in sja1105_init_scheduling()
257 table->entry_count = SJA1105_MAX_SCHEDULE_PARAMS_COUNT; in sja1105_init_scheduling()
258 schedule_params = table->entries; in sja1105_init_scheduling()
261 table = &priv->static_config.tables[BLK_IDX_SCHEDULE_ENTRY_POINTS]; in sja1105_init_scheduling()
262 table->entries = kcalloc(num_cycles, table->ops->unpacked_entry_size, in sja1105_init_scheduling()
264 if (!table->entries) in sja1105_init_scheduling()
265 return -ENOMEM; in sja1105_init_scheduling()
266 table->entry_count = num_cycles; in sja1105_init_scheduling()
267 schedule_entry_points = table->entries; in sja1105_init_scheduling()
270 schedule_entry_points_params->clksrc = SJA1105_TAS_CLKSRC_PTP; in sja1105_init_scheduling()
271 schedule_entry_points_params->actsubsch = num_cycles - 1; in sja1105_init_scheduling()
273 for (port = 0; port < ds->num_ports; port++) { in sja1105_init_scheduling()
278 offload = tas_data->offload[port]; in sja1105_init_scheduling()
283 schedule_end_idx = k + offload->num_entries - 1; in sja1105_init_scheduling()
288 rbt = future_base_time(offload->base_time, in sja1105_init_scheduling()
289 offload->cycle_time, in sja1105_init_scheduling()
290 tas_data->earliest_base_time); in sja1105_init_scheduling()
291 rbt -= tas_data->earliest_base_time; in sja1105_init_scheduling()
300 schedule_entry_points[cycle].subschindx = cycle; in sja1105_init_scheduling()
301 schedule_entry_points[cycle].delta = entry_point_delta; in sja1105_init_scheduling()
302 schedule_entry_points[cycle].address = schedule_start_idx; in sja1105_init_scheduling()
307 for (i = cycle; i < 8; i++) in sja1105_init_scheduling()
308 schedule_params->subscheind[i] = schedule_end_idx; in sja1105_init_scheduling()
310 for (i = 0; i < offload->num_entries; i++, k++) { in sja1105_init_scheduling()
311 s64 delta_ns = offload->entries[i].interval; in sja1105_init_scheduling()
317 ~offload->entries[i].gate_mask; in sja1105_init_scheduling()
319 cycle++; in sja1105_init_scheduling()
322 if (!list_empty(&gating_cfg->entries)) { in sja1105_init_scheduling()
329 schedule_end_idx = k + gating_cfg->num_entries - 1; in sja1105_init_scheduling()
330 rbt = future_base_time(gating_cfg->base_time, in sja1105_init_scheduling()
331 gating_cfg->cycle_time, in sja1105_init_scheduling()
332 tas_data->earliest_base_time); in sja1105_init_scheduling()
333 rbt -= tas_data->earliest_base_time; in sja1105_init_scheduling()
336 schedule_entry_points[cycle].subschindx = cycle; in sja1105_init_scheduling()
337 schedule_entry_points[cycle].delta = entry_point_delta; in sja1105_init_scheduling()
338 schedule_entry_points[cycle].address = schedule_start_idx; in sja1105_init_scheduling()
340 for (i = cycle; i < 8; i++) in sja1105_init_scheduling()
341 schedule_params->subscheind[i] = schedule_end_idx; in sja1105_init_scheduling()
343 list_for_each_entry(e, &gating_cfg->entries, list) { in sja1105_init_scheduling()
344 schedule[k].delta = ns_to_sja1105_delta(e->interval); in sja1105_init_scheduling()
345 schedule[k].destports = e->rule->vl.destports; in sja1105_init_scheduling()
348 schedule[k].vlindex = e->rule->vl.sharindx; in sja1105_init_scheduling()
349 schedule[k].winstindex = e->rule->vl.sharindx; in sja1105_init_scheduling()
350 if (e->gate_state) /* Gate open */ in sja1105_init_scheduling()
358 return 0; in sja1105_init_scheduling()
368 * tas_data->offload. We already know the other ports are in harmony with one
371 * phase given by its cycle's @base_time plus its offset within the cycle
374 * - Collisions within one cycle's (actually the longest cycle's) time frame.
376 * occurrence of each event within one cycle time.
377 * - Collisions in the future. Events may not collide within one cycle time,
378 * but if two port schedules don't have the same periodicity (aka the cycle
386 struct sja1105_tas_data *tas_data = &priv->tas_data; in sja1105_tas_check_conflicts()
396 offload = tas_data->offload[port]; in sja1105_tas_check_conflicts()
400 /* Check if the two cycle times are multiples of one another. in sja1105_tas_check_conflicts()
403 max_cycle_time = max(offload->cycle_time, admin->cycle_time); in sja1105_tas_check_conflicts()
404 min_cycle_time = min(offload->cycle_time, admin->cycle_time); in sja1105_tas_check_conflicts()
410 * (transposed back as close to 0 as possible) by dividing to in sja1105_tas_check_conflicts()
411 * the cycle time. in sja1105_tas_check_conflicts()
413 div_s64_rem(offload->base_time, offload->cycle_time, &rem); in sja1105_tas_check_conflicts()
416 div_s64_rem(admin->base_time, admin->cycle_time, &rem); in sja1105_tas_check_conflicts()
424 for (i = 0, delta1 = 0; in sja1105_tas_check_conflicts()
425 i < offload->num_entries; in sja1105_tas_check_conflicts()
426 delta1 += offload->entries[i].interval, i++) { in sja1105_tas_check_conflicts()
430 for (j = 0, delta2 = 0; in sja1105_tas_check_conflicts()
431 j < admin->num_entries; in sja1105_tas_check_conflicts()
432 delta2 += admin->entries[j].interval, j++) { in sja1105_tas_check_conflicts()
435 * first cycle time. in sja1105_tas_check_conflicts()
439 t1 += offload->cycle_time) { in sja1105_tas_check_conflicts()
442 * within the first cycle time. in sja1105_tas_check_conflicts()
446 t2 += admin->cycle_time) { in sja1105_tas_check_conflicts()
448 dev_warn(priv->ds->dev, in sja1105_tas_check_conflicts()
461 /* Check the tc-taprio configuration on @port for conflicts with the tc-gate
462 * global subschedule. If @port is -1, check it against all ports.
464 * convert the gating configuration to a dummy tc-taprio offload structure.
469 struct sja1105_gating_config *gating_cfg = &priv->tas_data.gating_cfg; in sja1105_gating_check_conflicts()
470 size_t num_entries = gating_cfg->num_entries; in sja1105_gating_check_conflicts()
472 struct dsa_switch *ds = priv->ds; in sja1105_gating_check_conflicts()
475 int i = 0; in sja1105_gating_check_conflicts()
477 if (list_empty(&gating_cfg->entries)) in sja1105_gating_check_conflicts()
486 dummy->num_entries = num_entries; in sja1105_gating_check_conflicts()
487 dummy->base_time = gating_cfg->base_time; in sja1105_gating_check_conflicts()
488 dummy->cycle_time = gating_cfg->cycle_time; in sja1105_gating_check_conflicts()
490 list_for_each_entry(e, &gating_cfg->entries, list) in sja1105_gating_check_conflicts()
491 dummy->entries[i++].interval = e->interval; in sja1105_gating_check_conflicts()
493 if (port != -1) { in sja1105_gating_check_conflicts()
496 for (port = 0; port < ds->num_ports; port++) { in sja1105_gating_check_conflicts()
512 struct sja1105_private *priv = ds->priv; in sja1105_setup_tc_taprio()
513 struct sja1105_tas_data *tas_data = &priv->tas_data; in sja1105_setup_tc_taprio()
519 if ((!!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_REPLACE) || in sja1105_setup_tc_taprio()
520 (!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_DESTROY)) in sja1105_setup_tc_taprio()
521 return -EINVAL; in sja1105_setup_tc_taprio()
523 if (admin->cmd == TAPRIO_CMD_DESTROY) { in sja1105_setup_tc_taprio()
524 taprio_offload_free(tas_data->offload[port]); in sja1105_setup_tc_taprio()
525 tas_data->offload[port] = NULL; in sja1105_setup_tc_taprio()
528 if (rc < 0) in sja1105_setup_tc_taprio()
532 } else if (admin->cmd != TAPRIO_CMD_REPLACE) { in sja1105_setup_tc_taprio()
533 return -EOPNOTSUPP; in sja1105_setup_tc_taprio()
536 /* The cycle time extension is the amount of time the last cycle from in sja1105_setup_tc_taprio()
537 * the old OPER needs to be extended in order to phase-align with the in sja1105_setup_tc_taprio()
539 * But of course our switch needs to be reset to switch-over between in sja1105_setup_tc_taprio()
540 * the ADMIN and the OPER configs - so much for a seamless transition. in sja1105_setup_tc_taprio()
541 * So don't add insult over injury and just say we don't support cycle in sja1105_setup_tc_taprio()
544 if (admin->cycle_time_extension) in sja1105_setup_tc_taprio()
545 return -ENOTSUPP; in sja1105_setup_tc_taprio()
547 for (i = 0; i < admin->num_entries; i++) { in sja1105_setup_tc_taprio()
548 s64 delta_ns = admin->entries[i].interval; in sja1105_setup_tc_taprio()
553 too_short = (delta_cycles == 0); in sja1105_setup_tc_taprio()
555 dev_err(priv->ds->dev, in sja1105_setup_tc_taprio()
558 return -ERANGE; in sja1105_setup_tc_taprio()
562 for (other_port = 0; other_port < ds->num_ports; other_port++) { in sja1105_setup_tc_taprio()
567 return -ERANGE; in sja1105_setup_tc_taprio()
571 dev_err(ds->dev, "Conflict with tc-gate schedule\n"); in sja1105_setup_tc_taprio()
572 return -ERANGE; in sja1105_setup_tc_taprio()
575 tas_data->offload[port] = taprio_offload_get(admin); in sja1105_setup_tc_taprio()
578 if (rc < 0) in sja1105_setup_tc_taprio()
586 struct sja1105_tas_data *tas_data = &priv->tas_data; in sja1105_tas_check_running()
587 struct dsa_switch *ds = priv->ds; in sja1105_tas_check_running()
588 struct sja1105_ptp_cmd cmd = {0}; in sja1105_tas_check_running()
592 if (rc < 0) in sja1105_tas_check_running()
597 tas_data->state = SJA1105_TAS_STATE_RUNNING; in sja1105_tas_check_running()
600 tas_data->state = SJA1105_TAS_STATE_DISABLED; in sja1105_tas_check_running()
603 rc = -EINVAL; in sja1105_tas_check_running()
612 const struct sja1105_regs *regs = priv->info->regs; in sja1105_tas_adjust_drift()
615 return sja1105_xfer_u32(priv, SPI_WRITE, regs->ptpclkcorp, in sja1105_tas_adjust_drift()
623 const struct sja1105_regs *regs = priv->info->regs; in sja1105_tas_set_base_time()
626 return sja1105_xfer_u64(priv, SPI_WRITE, regs->ptpschtm, in sja1105_tas_set_base_time()
632 struct sja1105_tas_data *tas_data = &priv->tas_data; in sja1105_tas_start()
633 struct sja1105_ptp_cmd *cmd = &priv->ptp_data.cmd; in sja1105_tas_start()
634 struct dsa_switch *ds = priv->ds; in sja1105_tas_start()
637 dev_dbg(ds->dev, "Starting the TAS\n"); in sja1105_tas_start()
639 if (tas_data->state == SJA1105_TAS_STATE_ENABLED_NOT_RUNNING || in sja1105_tas_start()
640 tas_data->state == SJA1105_TAS_STATE_RUNNING) { in sja1105_tas_start()
641 dev_err(ds->dev, "TAS already started\n"); in sja1105_tas_start()
642 return -EINVAL; in sja1105_tas_start()
645 cmd->ptpstrtsch = 1; in sja1105_tas_start()
646 cmd->ptpstopsch = 0; in sja1105_tas_start()
649 if (rc < 0) in sja1105_tas_start()
652 tas_data->state = SJA1105_TAS_STATE_ENABLED_NOT_RUNNING; in sja1105_tas_start()
654 return 0; in sja1105_tas_start()
659 struct sja1105_tas_data *tas_data = &priv->tas_data; in sja1105_tas_stop()
660 struct sja1105_ptp_cmd *cmd = &priv->ptp_data.cmd; in sja1105_tas_stop()
661 struct dsa_switch *ds = priv->ds; in sja1105_tas_stop()
664 dev_dbg(ds->dev, "Stopping the TAS\n"); in sja1105_tas_stop()
666 if (tas_data->state == SJA1105_TAS_STATE_DISABLED) { in sja1105_tas_stop()
667 dev_err(ds->dev, "TAS already disabled\n"); in sja1105_tas_stop()
668 return -EINVAL; in sja1105_tas_stop()
671 cmd->ptpstopsch = 1; in sja1105_tas_stop()
672 cmd->ptpstrtsch = 0; in sja1105_tas_stop()
675 if (rc < 0) in sja1105_tas_stop()
678 tas_data->state = SJA1105_TAS_STATE_DISABLED; in sja1105_tas_stop()
680 return 0; in sja1105_tas_stop()
685 * time-of-day, the schedule engine is only running in 'ticks' (25 ticks make
686 * up a delta, which is 200ns), and wrapping around at the end of each cycle.
689 * Because the PTP clock can be rate-corrected (accelerated or slowed down) by
694 * a value also in the PTP clock domain, and is also rate-corrected.
707 * cycle times have to be multiples of one another anyway, this means the
708 * correction period can simply be the largest cycle time, hence the current
710 * cycle, and therefore predictable.
714 * properly phase-aligned with the PTP clock. For this reason, you should place
715 * your best-effort traffic at the beginning of a cycle, and your
716 * time-triggered traffic afterwards.
728 struct sja1105_ptp_data *ptp_data = &priv->ptp_data; in sja1105_tas_state_machine()
730 struct dsa_switch *ds = priv->ds; in sja1105_tas_state_machine()
733 int rc = 0; in sja1105_tas_state_machine()
735 mutex_lock(&ptp_data->lock); in sja1105_tas_state_machine()
737 switch (tas_data->state) { in sja1105_tas_state_machine()
740 if (tas_data->last_op != SJA1105_PTP_ADJUSTFREQ) in sja1105_tas_state_machine()
743 rc = sja1105_tas_adjust_drift(priv, tas_data->max_cycle_time); in sja1105_tas_state_machine()
744 if (rc < 0) in sja1105_tas_state_machine()
748 if (rc < 0) in sja1105_tas_state_machine()
760 base_time = future_base_time(tas_data->earliest_base_time, in sja1105_tas_state_machine()
761 tas_data->max_cycle_time, in sja1105_tas_state_machine()
763 base_time -= sja1105_delta_to_ns(1); in sja1105_tas_state_machine()
766 if (rc < 0) in sja1105_tas_state_machine()
769 tas_data->oper_base_time = base_time; in sja1105_tas_state_machine()
772 if (rc < 0) in sja1105_tas_state_machine()
778 dev_dbg(ds->dev, "OPER base time %lld.%09ld (now %lld.%09ld)\n", in sja1105_tas_state_machine()
785 if (tas_data->last_op != SJA1105_PTP_ADJUSTFREQ) { in sja1105_tas_state_machine()
795 if (rc < 0) in sja1105_tas_state_machine()
798 if (now < tas_data->oper_base_time) { in sja1105_tas_state_machine()
800 diff = ns_to_timespec64(tas_data->oper_base_time - now); in sja1105_tas_state_machine()
801 dev_dbg(ds->dev, "time to start: [%lld.%09ld]", in sja1105_tas_state_machine()
808 if (rc < 0) in sja1105_tas_state_machine()
811 if (tas_data->state != SJA1105_TAS_STATE_RUNNING) in sja1105_tas_state_machine()
813 dev_err(ds->dev, in sja1105_tas_state_machine()
820 if (tas_data->last_op != SJA1105_PTP_ADJUSTFREQ) { in sja1105_tas_state_machine()
826 if (rc < 0) in sja1105_tas_state_machine()
829 if (tas_data->state != SJA1105_TAS_STATE_RUNNING) in sja1105_tas_state_machine()
830 dev_err(ds->dev, "TAS surprisingly stopped\n"); in sja1105_tas_state_machine()
836 dev_err(ds->dev, "TAS in an invalid state (incorrect use of API)!\n"); in sja1105_tas_state_machine()
840 dev_err(ds->dev, "An operation returned %d\n", rc); in sja1105_tas_state_machine()
842 mutex_unlock(&ptp_data->lock); in sja1105_tas_state_machine()
847 struct sja1105_private *priv = ds->priv; in sja1105_tas_clockstep()
848 struct sja1105_tas_data *tas_data = &priv->tas_data; in sja1105_tas_clockstep()
850 if (!tas_data->enabled) in sja1105_tas_clockstep()
853 tas_data->last_op = SJA1105_PTP_CLOCKSTEP; in sja1105_tas_clockstep()
854 schedule_work(&tas_data->tas_work); in sja1105_tas_clockstep()
859 struct sja1105_private *priv = ds->priv; in sja1105_tas_adjfreq()
860 struct sja1105_tas_data *tas_data = &priv->tas_data; in sja1105_tas_adjfreq()
862 if (!tas_data->enabled) in sja1105_tas_adjfreq()
866 if (tas_data->state == SJA1105_TAS_STATE_RUNNING) in sja1105_tas_adjfreq()
869 tas_data->last_op = SJA1105_PTP_ADJUSTFREQ; in sja1105_tas_adjfreq()
870 schedule_work(&tas_data->tas_work); in sja1105_tas_adjfreq()
875 struct sja1105_private *priv = ds->priv; in sja1105_tas_setup()
876 struct sja1105_tas_data *tas_data = &priv->tas_data; in sja1105_tas_setup()
878 INIT_WORK(&tas_data->tas_work, sja1105_tas_state_machine); in sja1105_tas_setup()
879 tas_data->state = SJA1105_TAS_STATE_DISABLED; in sja1105_tas_setup()
880 tas_data->last_op = SJA1105_PTP_NONE; in sja1105_tas_setup()
882 INIT_LIST_HEAD(&tas_data->gating_cfg.entries); in sja1105_tas_setup()
887 struct sja1105_private *priv = ds->priv; in sja1105_tas_teardown()
891 cancel_work_sync(&priv->tas_data.tas_work); in sja1105_tas_teardown()
893 for (port = 0; port < ds->num_ports; port++) { in sja1105_tas_teardown()
894 offload = priv->tas_data.offload[port]; in sja1105_tas_teardown()