drivers/net/dsa/realtek/rtl8366-core.c

Source file repositories/reference/linux-study-clean/drivers/net/dsa/realtek/rtl8366-core.c

File Facts

System
Linux kernel
Corpus path
drivers/net/dsa/realtek/rtl8366-core.c
Extension
.c
Size
10529 bytes
Lines
445
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

if (mc_index == index) {
			*used = 1;
			break;
		}
	}

	return 0;
}
EXPORT_SYMBOL_NS_GPL(rtl8366_mc_is_used, "REALTEK_DSA");

/**
 * rtl8366_obtain_mc() - retrieve or allocate a VLAN member configuration
 * @priv: the Realtek SMI device instance
 * @vid: the VLAN ID to look up or allocate
 * @vlanmc: the pointer will be assigned to a pointer to a valid member config
 * if successful
 * @return: index of a new member config or negative error number
 */
static int rtl8366_obtain_mc(struct realtek_priv *priv, int vid,
			     struct rtl8366_vlan_mc *vlanmc)
{
	struct rtl8366_vlan_4k vlan4k;
	int ret;
	int i;

	/* Try to find an existing member config entry for this VID */
	for (i = 0; i < priv->num_vlan_mc; i++) {
		ret = priv->ops->get_vlan_mc(priv, i, vlanmc);
		if (ret) {
			dev_err(priv->dev, "error searching for VLAN MC %d for VID %d\n",
				i, vid);
			return ret;
		}

		if (vid == vlanmc->vid)
			return i;
	}

	/* We have no MC entry for this VID, try to find an empty one */
	for (i = 0; i < priv->num_vlan_mc; i++) {
		ret = priv->ops->get_vlan_mc(priv, i, vlanmc);
		if (ret) {
			dev_err(priv->dev, "error searching for VLAN MC %d for VID %d\n",
				i, vid);
			return ret;
		}

		if (vlanmc->vid == 0 && vlanmc->member == 0) {
			/* Update the entry from the 4K table */
			ret = priv->ops->get_vlan_4k(priv, vid, &vlan4k);
			if (ret) {
				dev_err(priv->dev, "error looking for 4K VLAN MC %d for VID %d\n",
					i, vid);
				return ret;
			}

			vlanmc->vid = vid;
			vlanmc->member = vlan4k.member;
			vlanmc->untag = vlan4k.untag;
			vlanmc->fid = vlan4k.fid;
			ret = priv->ops->set_vlan_mc(priv, i, vlanmc);
			if (ret) {
				dev_err(priv->dev, "unable to set/update VLAN MC %d for VID %d\n",
					i, vid);
				return ret;
			}

			dev_dbg(priv->dev, "created new MC at index %d for VID %d\n",
				i, vid);
			return i;
		}
	}

	/* MC table is full, try to find an unused entry and replace it */
	for (i = 0; i < priv->num_vlan_mc; i++) {
		int used;

		ret = rtl8366_mc_is_used(priv, i, &used);
		if (ret)
			return ret;

		if (!used) {
			/* Update the entry from the 4K table */
			ret = priv->ops->get_vlan_4k(priv, vid, &vlan4k);
			if (ret)
				return ret;

			vlanmc->vid = vid;
			vlanmc->member = vlan4k.member;
			vlanmc->untag = vlan4k.untag;

Annotation

Implementation Notes