drivers/net/ethernet/ti/cpsw_ale.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/ti/cpsw_ale.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/ti/cpsw_ale.c
Extension
.c
Size
48765 bytes
Lines
1773
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 ale_entry_fld {
	u8 start_bit;
	u8 num_bits;
	u8 flags;
};

enum {
	CPSW_ALE_F_STATUS_REG = BIT(0), /* Status register present */
	CPSW_ALE_F_HW_AUTOAGING = BIT(1), /* HW auto aging */

	CPSW_ALE_F_COUNT
};

/**
 * struct cpsw_ale_dev_id - The ALE version/SoC specific configuration
 * @dev_id: ALE version/SoC id
 * @features: features supported by ALE
 * @tbl_entries: number of ALE entries
 * @reg_fields: pointer to array of register field configuration
 * @num_fields: number of fields in the reg_fields array
 * @nu_switch_ale: NU Switch ALE
 * @vlan_entry_tbl: ALE vlan entry fields description tbl
 */
struct cpsw_ale_dev_id {
	const char *dev_id;
	u32 features;
	u32 tbl_entries;
	const struct reg_field *reg_fields;
	int num_fields;
	bool nu_switch_ale;
	const struct ale_entry_fld *vlan_entry_tbl;
};

#define ALE_TABLE_WRITE		BIT(31)

#define ALE_TYPE_FREE			0
#define ALE_TYPE_ADDR			1
#define ALE_TYPE_VLAN			2
#define ALE_TYPE_VLAN_ADDR		3

#define ALE_UCAST_PERSISTANT		0
#define ALE_UCAST_UNTOUCHED		1
#define ALE_UCAST_OUI			2
#define ALE_UCAST_TOUCHED		3

#define ALE_TABLE_SIZE_MULTIPLIER	1024
#define ALE_POLICER_SIZE_MULTIPLIER	8

static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
{
	int idx, idx2, index;
	u32 hi_val = 0;

	idx    = start / 32;
	idx2 = (start + bits - 1) / 32;
	/* Check if bits to be fetched exceed a word */
	if (idx != idx2) {
		index = 2 - idx2; /* flip */
		hi_val = ale_entry[index] << ((idx2 * 32) - start);
	}
	start -= idx * 32;
	idx    = 2 - idx; /* flip */
	return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits);
}

static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
				      u32 value)
{
	int idx, idx2, index;

	value &= BITMASK(bits);
	idx = start / 32;
	idx2 = (start + bits - 1) / 32;
	/* Check if bits to be set exceed a word */
	if (idx != idx2) {
		index = 2 - idx2; /* flip */
		ale_entry[index] &= ~(BITMASK(bits + start - (idx2 * 32)));
		ale_entry[index] |= (value >> ((idx2 * 32) - start));
	}
	start -= idx * 32;
	idx = 2 - idx; /* flip */
	ale_entry[idx] &= ~(BITMASK(bits) << start);
	ale_entry[idx] |=  (value << start);
}

#define DEFINE_ALE_FIELD_GET(name, start, bits)				\
static inline int cpsw_ale_get_##name(u32 *ale_entry)			\
{									\
	return cpsw_ale_get_field(ale_entry, start, bits);		\
}

Annotation

Implementation Notes