drivers/net/ethernet/ti/icssm/icssm_switchdev.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/ti/icssm/icssm_switchdev.c
Extension
.c
Size
8502 bytes
Lines
334
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 icssm_sw_event_work {
	netdevice_tracker ndev_tracker;
	struct work_struct work;
	struct switchdev_notifier_fdb_info fdb_info;
	struct prueth_emac *emac;
	unsigned long event;
};

void icssm_prueth_sw_set_stp_state(struct prueth *prueth,
				   enum prueth_port port, u8 state)
{
	struct fdb_tbl *t = prueth->fdb_tbl;

	writeb(state, port - 1 ? (void __iomem *)&t->port2_stp_cfg->state :
			(void __iomem *)&t->port1_stp_cfg->state);
}

u8 icssm_prueth_sw_get_stp_state(struct prueth *prueth, enum prueth_port port)
{
	struct fdb_tbl *t = prueth->fdb_tbl;
	u8 state;

	state = readb(port - 1 ? (void __iomem *)&t->port2_stp_cfg->state :
			(void __iomem *)&t->port1_stp_cfg->state);
	return state;
}

static int icssm_prueth_sw_attr_set(struct net_device *ndev, const void *ctx,
				    const struct switchdev_attr *attr,
				    struct netlink_ext_ack *extack)
{
	struct prueth_emac *emac = netdev_priv(ndev);
	struct prueth *prueth = emac->prueth;
	int err = 0;
	u8 o_state;

	/* Interface is not up */
	if (!prueth->fdb_tbl)
		return 0;

	switch (attr->id) {
	case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
		o_state = icssm_prueth_sw_get_stp_state(prueth, emac->port_id);
		icssm_prueth_sw_set_stp_state(prueth, emac->port_id,
					      attr->u.stp_state);

		if (o_state != attr->u.stp_state)
			icssm_prueth_sw_purge_fdb(emac);

		dev_dbg(prueth->dev, "attr set: stp state:%u port:%u\n",
			attr->u.stp_state, emac->port_id);
		break;
	default:
		err = -EOPNOTSUPP;
		break;
	}

	return err;
}

static void icssm_prueth_sw_fdb_offload(struct net_device *ndev,
					struct switchdev_notifier_fdb_info *rcv)
{
	struct switchdev_notifier_fdb_info info;

	info.addr = rcv->addr;
	info.vid = rcv->vid;
	call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, ndev, &info.info,
				 NULL);
}

/**
 * icssm_sw_event_work - insert/delete fdb entry
 *
 * @work: work structure
 *
 */
static void icssm_sw_event_work(struct work_struct *work)
{
	struct icssm_sw_event_work *switchdev_work =
		container_of(work, struct icssm_sw_event_work, work);
	struct prueth_emac *emac = switchdev_work->emac;
	struct switchdev_notifier_fdb_info *fdb;
	struct prueth *prueth = emac->prueth;
	int port = emac->port_id;

	rtnl_lock();

	/* Interface is not up */
	if (!emac->prueth->fdb_tbl)

Annotation

Implementation Notes