drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
Extension
.c
Size
8050 bytes
Lines
378
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 (vid == 0) {
			netdev_warn(dev, "Adding VLAN ID 0 is not supported\n");
			return -EPERM;
		}

		if (hw->vlan_filter[0] & VLAN_TAG_VID) {
			netdev_err(dev, "Only single VLAN ID supported\n");
			return -EPERM;
		}

		hw->vlan_filter[0] = vid;

		if (netif_running(dev))
			vlan_write_single(dev, vid);

		return 0;
	}

	/* Extended Rx VLAN Filter Enable */
	val |= VLAN_TAG_DATA_ETV | VLAN_TAG_DATA_VEN | vid;

	for (i = 0; i < hw->num_vlan; i++) {
		if (hw->vlan_filter[i] == val)
			return 0;
		else if (!(hw->vlan_filter[i] & VLAN_TAG_DATA_VEN))
			index = i;
	}

	if (index == -1) {
		netdev_err(dev, "MAC_VLAN_Tag_Filter full (size: %0u)\n",
			   hw->num_vlan);
		return -EPERM;
	}

	if (netif_running(dev)) {
		ret = vlan_write_filter(dev, hw, index, val);
		if (ret)
			return ret;
	}

	hw->vlan_filter[index] = val;

	return 0;
}

static int vlan_del_hw_rx_fltr(struct net_device *dev,
			       struct mac_device_info *hw,
			       __be16 proto, u16 vid)
{
	int i, ret = 0;

	/* Single Rx VLAN Filter */
	if (hw->num_vlan == 1) {
		if ((hw->vlan_filter[0] & VLAN_TAG_VID) == vid) {
			hw->vlan_filter[0] = 0;

			if (netif_running(dev))
				vlan_write_single(dev, 0);
		}
		return 0;
	}

	/* Extended Rx VLAN Filter Enable */
	for (i = 0; i < hw->num_vlan; i++) {
		if ((hw->vlan_filter[i] & VLAN_TAG_DATA_VEN) &&
		    ((hw->vlan_filter[i] & VLAN_TAG_DATA_VID) == vid)) {

			if (netif_running(dev)) {
				ret = vlan_write_filter(dev, hw, i, 0);
				if (ret)
					return ret;
			}

			hw->vlan_filter[i] = 0;
		}
	}

	return 0;
}

static void vlan_restore_hw_rx_fltr(struct net_device *dev,
				    struct mac_device_info *hw)
{
	int i;

	/* Single Rx VLAN Filter */
	if (hw->num_vlan == 1) {
		vlan_write_single(dev, hw->vlan_filter[0]);
		return;
	}

Annotation

Implementation Notes