drivers/net/dsa/sja1105/sja1105_tas.c

Source file repositories/reference/linux-study-clean/drivers/net/dsa/sja1105/sja1105_tas.c

File Facts

System
Linux kernel
Corpus path
drivers/net/dsa/sja1105/sja1105_tas.c
Extension
.c
Size
29418 bytes
Lines
899
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (earliest_base_time > offload->base_time) {
			earliest_base_time = offload->base_time;
			its_cycle_time = offload->cycle_time;
		}
	}

	if (!list_empty(&gating_cfg->entries)) {
		tas_data->enabled = true;

		if (max_cycle_time < gating_cfg->cycle_time)
			max_cycle_time = gating_cfg->cycle_time;
		if (latest_base_time < gating_cfg->base_time)
			latest_base_time = gating_cfg->base_time;
		if (earliest_base_time > gating_cfg->base_time) {
			earliest_base_time = gating_cfg->base_time;
			its_cycle_time = gating_cfg->cycle_time;
		}
	}

	if (!tas_data->enabled)
		return 0;

	/* Roll the earliest base time over until it is in a comparable
	 * time base with the latest, then compare their deltas.
	 * We want to enforce that all ports' base times are within
	 * SJA1105_TAS_MAX_DELTA 200ns cycles of one another.
	 */
	earliest_base_time = future_base_time(earliest_base_time,
					      its_cycle_time,
					      latest_base_time);
	while (earliest_base_time > latest_base_time)
		earliest_base_time -= its_cycle_time;
	if (latest_base_time - earliest_base_time >
	    sja1105_delta_to_ns(SJA1105_TAS_MAX_DELTA)) {
		dev_err(ds->dev,
			"Base times too far apart: min %llu max %llu\n",
			earliest_base_time, latest_base_time);
		return -ERANGE;
	}

	tas_data->earliest_base_time = earliest_base_time;
	tas_data->max_cycle_time = max_cycle_time;

	dev_dbg(ds->dev, "earliest base time %lld ns\n", earliest_base_time);
	dev_dbg(ds->dev, "latest base time %lld ns\n", latest_base_time);
	dev_dbg(ds->dev, "longest cycle time %lld ns\n", max_cycle_time);

	return 0;
}

/* Lo and behold: the egress scheduler from hell.
 *
 * At the hardware level, the Time-Aware Shaper holds a global linear arrray of
 * all schedule entries for all ports. These are the Gate Control List (GCL)
 * entries, let's call them "timeslots" for short. This linear array of
 * timeslots is held in BLK_IDX_SCHEDULE.
 *
 * Then there are a maximum of 8 "execution threads" inside the switch, which
 * iterate cyclically through the "schedule". Each "cycle" has an entry point
 * and an exit point, both being timeslot indices in the schedule table. The
 * hardware calls each cycle a "subschedule".
 *
 * Subschedule (cycle) i starts when
 *   ptpclkval >= ptpschtm + BLK_IDX_SCHEDULE_ENTRY_POINTS[i].delta.
 *
 * The hardware scheduler iterates BLK_IDX_SCHEDULE with a k ranging from
 *   k = BLK_IDX_SCHEDULE_ENTRY_POINTS[i].address to
 *   k = BLK_IDX_SCHEDULE_PARAMS.subscheind[i]
 *
 * For each schedule entry (timeslot) k, the engine executes the gate control
 * list entry for the duration of BLK_IDX_SCHEDULE[k].delta.
 *
 *         +---------+
 *         |         | BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS
 *         +---------+
 *              |
 *              +-----------------+
 *                                | .actsubsch
 *  BLK_IDX_SCHEDULE_ENTRY_POINTS v
 *                 +-------+-------+
 *                 |cycle 0|cycle 1|
 *                 +-------+-------+
 *                   |  |      |  |
 *  +----------------+  |      |  +-------------------------------------+
 *  |   .subschindx     |      |             .subschindx                |
 *  |                   |      +---------------+                        |
 *  |          .address |        .address      |                        |
 *  |                   |                      |                        |
 *  |                   |                      |                        |
 *  |  BLK_IDX_SCHEDULE v                      v                        |

Annotation

Implementation Notes