drivers/net/ethernet/microchip/lan966x/lan966x_lag.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
Extension
.c
Size
8867 bytes
Lines
369
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

for_each_set_bit(p, &bond_mask, lan966x->num_phys_ports) {
			struct lan966x_port *port = lan966x->ports[p];

			if (!port)
				continue;

			lan_wr(ANA_PGID_PGID_SET(bond_mask),
			       lan966x, ANA_PGID(p));
			if (port->lag_tx_active)
				aggr_idx[num_active_ports++] = p;
		}

		for (i = PGID_AGGR; i < PGID_SRC; ++i) {
			u32 ac;

			ac = lan_rd(lan966x, ANA_PGID(i));
			ac &= ~bond_mask;
			/* Don't do division by zero if there was no active
			 * port. Just make all aggregation codes zero.
			 */
			if (num_active_ports)
				ac |= BIT(aggr_idx[i % num_active_ports]);
			lan_wr(ANA_PGID_PGID_SET(ac),
			       lan966x, ANA_PGID(i));
		}

		/* Mark all ports in the same LAG as visited to avoid applying
		 * the same config again.
		 */
		for (p = lag; p < lan966x->num_phys_ports; p++) {
			struct lan966x_port *port = lan966x->ports[p];

			if (!port)
				continue;

			if (port->bond == bond)
				visited |= BIT(p);
		}
	}
}

static void lan966x_lag_set_port_ids(struct lan966x *lan966x)
{
	struct lan966x_port *port;
	u32 bond_mask;
	u32 lag_id;
	int p;

	for (p = 0; p < lan966x->num_phys_ports; ++p) {
		port = lan966x->ports[p];
		if (!port)
			continue;

		lag_id = port->chip_port;

		bond_mask = lan966x_lag_get_mask(lan966x, port->bond);
		if (bond_mask)
			lag_id = __ffs(bond_mask);

		lan_rmw(ANA_PORT_CFG_PORTID_VAL_SET(lag_id),
			ANA_PORT_CFG_PORTID_VAL,
			lan966x, ANA_PORT_CFG(port->chip_port));
	}
}

static void lan966x_lag_update_ids(struct lan966x *lan966x)
{
	lan966x_lag_set_port_ids(lan966x);
	lan966x_update_fwd_mask(lan966x);
	lan966x_lag_set_aggr_pgids(lan966x);
}

int lan966x_lag_port_join(struct lan966x_port *port,
			  struct net_device *brport_dev,
			  struct net_device *bond,
			  struct netlink_ext_ack *extack)
{
	struct lan966x *lan966x = port->lan966x;
	struct net_device *dev = port->dev;
	u32 lag_id = -1;
	u32 bond_mask;
	int err;

	bond_mask = lan966x_lag_get_mask(lan966x, bond);
	if (bond_mask)
		lag_id = __ffs(bond_mask);

	port->bond = bond;
	lan966x_lag_update_ids(lan966x);

Annotation

Implementation Notes