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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/microchip/lan966x/lan966x_mac.c
Extension
.c
Size
16142 bytes
Lines
593
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 lan966x_mac_entry {
	struct list_head list;
	unsigned char mac[ETH_ALEN] __aligned(2);
	u16 vid;
	u16 port_index;
	int row;
	bool lag;
};

struct lan966x_mac_raw_entry {
	u32 mach;
	u32 macl;
	u32 maca;
	bool processed;
};

static int lan966x_mac_get_status(struct lan966x *lan966x)
{
	return lan_rd(lan966x, ANA_MACACCESS);
}

static int lan966x_mac_wait_for_completion(struct lan966x *lan966x)
{
	u32 val;

	return readx_poll_timeout_atomic(lan966x_mac_get_status,
					 lan966x, val,
					 (ANA_MACACCESS_MAC_TABLE_CMD_GET(val)) ==
					 MACACCESS_CMD_IDLE,
					 TABLE_UPDATE_SLEEP_US,
					 TABLE_UPDATE_TIMEOUT_US);
}

static void lan966x_mac_select(struct lan966x *lan966x,
			       const unsigned char mac[ETH_ALEN],
			       unsigned int vid)
{
	u32 macl = 0, mach = 0;

	/* Set the MAC address to handle and the vlan associated in a format
	 * understood by the hardware.
	 */
	mach |= vid    << 16;
	mach |= mac[0] << 8;
	mach |= mac[1] << 0;
	macl |= mac[2] << 24;
	macl |= mac[3] << 16;
	macl |= mac[4] << 8;
	macl |= mac[5] << 0;

	lan_wr(macl, lan966x, ANA_MACLDATA);
	lan_wr(mach, lan966x, ANA_MACHDATA);
}

static int __lan966x_mac_learn_locked(struct lan966x *lan966x, int pgid,
				      bool cpu_copy,
				      const unsigned char mac[ETH_ALEN],
				      unsigned int vid,
				      enum macaccess_entry_type type)
{
	lockdep_assert_held(&lan966x->mac_lock);

	lan966x_mac_select(lan966x, mac, vid);

	/* Issue a write command */
	lan_wr(ANA_MACACCESS_VALID_SET(1) |
	       ANA_MACACCESS_CHANGE2SW_SET(0) |
	       ANA_MACACCESS_MAC_CPU_COPY_SET(cpu_copy) |
	       ANA_MACACCESS_DEST_IDX_SET(pgid) |
	       ANA_MACACCESS_ENTRYTYPE_SET(type) |
	       ANA_MACACCESS_MAC_TABLE_CMD_SET(MACACCESS_CMD_LEARN),
	       lan966x, ANA_MACACCESS);

	return lan966x_mac_wait_for_completion(lan966x);
}

static int __lan966x_mac_learn(struct lan966x *lan966x, int pgid,
			       bool cpu_copy,
			       const unsigned char mac[ETH_ALEN],
			       unsigned int vid,
			       enum macaccess_entry_type type)
{
	int ret;

	spin_lock(&lan966x->mac_lock);
	ret = __lan966x_mac_learn_locked(lan966x, pgid, cpu_copy, mac, vid, type);
	spin_unlock(&lan966x->mac_lock);

	return ret;
}

Annotation

Implementation Notes