drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_calendar.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_calendar.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_calendar.c
Extension
.c
Size
4659 bytes
Lines
192
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

struct lan969x_dsm_cal_dev_speed {
	/* Number of devices that requires this speed. */
	u32 n_devs;

	/* Array of devices that requires this speed. */
	u32 devs[LAN969X_DSM_CAL_DEVS_PER_TAXI];

	/* Number of slots required for one device running this speed. */
	u32 n_slots;

	/* Gap between two slots for one device running this speed. */
	u32 gap;
};

static u32
lan969x_taxi_ports[LAN969X_DSM_CAL_TAXIS][LAN969X_DSM_CAL_DEVS_PER_TAXI] = {
	{  0,  4,  1,  2,  3,  5,  6,  7, 28, 29 },
	{  8, 12,  9, 13, 10, 11, 14, 15, 99, 99 },
	{ 16, 20, 17, 21, 18, 19, 22, 23, 99, 99 },
	{ 24, 25, 99, 99, 99, 99, 99, 99, 99, 99 },
	{ 26, 27, 99, 99, 99, 99, 99, 99, 99, 99 }
};

static int lan969x_dsm_cal_idx_get(u32 *calendar, u32 cal_len, u32 *cal_idx)
{
	if (*cal_idx >= cal_len)
		return -EINVAL;

	do {
		if (calendar[*cal_idx] == SPX5_DSM_CAL_EMPTY)
			return 0;

		(*cal_idx)++;
	} while (*cal_idx < cal_len);

	return -ENOENT;
}

static enum lan969x_dsm_cal_dev lan969x_dsm_cal_get_dev(int speed)
{
	return (speed == 10000 ? DSM_CAL_DEV_10G :
		speed == 5000  ? DSM_CAL_DEV_5G :
		speed == 2500  ? DSM_CAL_DEV_2G5 :
				 DSM_CAL_DEV_OTHER);
}

static int lan969x_dsm_cal_get_speed(enum lan969x_dsm_cal_dev dev)
{
	return (dev == DSM_CAL_DEV_10G ? 10000 :
		dev == DSM_CAL_DEV_5G  ? 5000 :
		dev == DSM_CAL_DEV_2G5 ? 2500 :
					 1000);
}

int lan969x_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi,
			      struct sparx5_calendar_data *data)
{
	struct lan969x_dsm_cal_dev_speed dev_speeds[DSM_CAL_DEV_MAX] = {};
	u32 cal_len, n_slots, taxi_bw, n_devs = 0, required_bw  = 0;
	struct lan969x_dsm_cal_dev_speed *speed;
	int err;

	/* Maximum bandwidth for this taxi */
	taxi_bw = (128 * 1000000) / sparx5_clk_period(sparx5->coreclock);

	memcpy(data->taxi_ports, &lan969x_taxi_ports[taxi],
	       LAN969X_DSM_CAL_DEVS_PER_TAXI * sizeof(u32));

	for (int i = 0; i < LAN969X_DSM_CAL_DEVS_PER_TAXI; i++) {
		u32 portno = data->taxi_ports[i];
		enum sparx5_cal_bw bw;

		bw = sparx5_get_port_cal_speed(sparx5, portno);

		if (portno < sparx5->data->consts->n_ports_all)
			data->taxi_speeds[i] = sparx5_cal_speed_to_value(bw);
		else
			data->taxi_speeds[i] = 0;
	}

	/* Determine the different port types (10G, 5G, 2.5G, <= 1G) in the
	 * this taxi map.
	 */
	for (int i = 0; i < LAN969X_DSM_CAL_DEVS_PER_TAXI; i++) {
		u32 taxi_speed = data->taxi_speeds[i];
		enum lan969x_dsm_cal_dev dev;

		if (taxi_speed == 0)
			continue;

Annotation

Implementation Notes