drivers/net/dsa/hirschmann/hellcreek.c

Source file repositories/reference/linux-study-clean/drivers/net/dsa/hirschmann/hellcreek.c

File Facts

System
Linux kernel
Corpus path
drivers/net/dsa/hirschmann/hellcreek.c
Extension
.c
Size
54565 bytes
Lines
2114
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

if (vlan->vid == restricted_vid) {
			NL_SET_ERR_MSG_MOD(extack, "VID restricted by driver");
			return -EBUSY;
		}
	}

	return 0;
}

static void hellcreek_select_vlan_params(struct hellcreek *hellcreek, int port,
					 int *shift, int *mask)
{
	switch (port) {
	case 0:
		*shift = HR_VIDMBRCFG_P0MBR_SHIFT;
		*mask  = HR_VIDMBRCFG_P0MBR_MASK;
		break;
	case 1:
		*shift = HR_VIDMBRCFG_P1MBR_SHIFT;
		*mask  = HR_VIDMBRCFG_P1MBR_MASK;
		break;
	case 2:
		*shift = HR_VIDMBRCFG_P2MBR_SHIFT;
		*mask  = HR_VIDMBRCFG_P2MBR_MASK;
		break;
	case 3:
		*shift = HR_VIDMBRCFG_P3MBR_SHIFT;
		*mask  = HR_VIDMBRCFG_P3MBR_MASK;
		break;
	default:
		*shift = *mask = 0;
		dev_err(hellcreek->dev, "Unknown port %d selected!\n", port);
	}
}

static void hellcreek_apply_vlan(struct hellcreek *hellcreek, int port, u16 vid,
				 bool pvid, bool untagged)
{
	int shift, mask;
	u16 val;

	dev_dbg(hellcreek->dev, "Apply VLAN: port=%d vid=%u pvid=%d untagged=%d",
		port, vid, pvid, untagged);

	mutex_lock(&hellcreek->reg_lock);

	hellcreek_select_port(hellcreek, port);
	hellcreek_select_vlan(hellcreek, vid, pvid);

	/* Setup port vlan membership */
	hellcreek_select_vlan_params(hellcreek, port, &shift, &mask);
	val = hellcreek->vidmbrcfg[vid];
	val &= ~mask;
	if (untagged)
		val |= HELLCREEK_VLAN_UNTAGGED_MEMBER << shift;
	else
		val |= HELLCREEK_VLAN_TAGGED_MEMBER << shift;

	hellcreek_write(hellcreek, val, HR_VIDMBRCFG);
	hellcreek->vidmbrcfg[vid] = val;

	mutex_unlock(&hellcreek->reg_lock);
}

static void hellcreek_unapply_vlan(struct hellcreek *hellcreek, int port,
				   u16 vid)
{
	int shift, mask;
	u16 val;

	dev_dbg(hellcreek->dev, "Unapply VLAN: port=%d vid=%u\n", port, vid);

	mutex_lock(&hellcreek->reg_lock);

	hellcreek_select_vlan(hellcreek, vid, false);

	/* Setup port vlan membership */
	hellcreek_select_vlan_params(hellcreek, port, &shift, &mask);
	val = hellcreek->vidmbrcfg[vid];
	val &= ~mask;
	val |= HELLCREEK_VLAN_NO_MEMBER << shift;

	hellcreek_write(hellcreek, val, HR_VIDMBRCFG);
	hellcreek->vidmbrcfg[vid] = val;

	mutex_unlock(&hellcreek->reg_lock);
}

static int hellcreek_vlan_add(struct dsa_switch *ds, int port,
			      const struct switchdev_obj_port_vlan *vlan,

Annotation

Implementation Notes