drivers/net/ethernet/renesas/rswitch_l2.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/renesas/rswitch_l2.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/renesas/rswitch_l2.c
Extension
.c
Size
8200 bytes
Lines
316
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 (new_forwarding_offload || rdev->forwarding_offloaded) {
			/* Update allowed offload destinations even for ports
			 * with L2 offload enabled earlier.
			 *
			 * Do not allow L2 forwarding to self for hw port.
			 */
			iowrite32(FIELD_PREP(FWCP2_LTWFW_MASK, fwd_mask | BIT(rdev->port)),
				  priv->addr + FWPC2(rdev->port));
		}

		if (new_forwarding_offload && !rdev->forwarding_offloaded)
			rswitch_change_l2_hw_offloading(rdev, true, false);
		else if (!new_forwarding_offload && rdev->forwarding_offloaded)
			rswitch_change_l2_hw_offloading(rdev, false, false);
	}
}

void rswitch_update_l2_offload(struct rswitch_private *priv)
{
	rswitch_update_l2_hw_learning(priv);
	rswitch_update_l2_hw_forwarding(priv);
}

static void rswitch_update_offload_brdev(struct rswitch_private *priv)
{
	struct net_device *offload_brdev = NULL;
	struct rswitch_device *rdev, *rdev2;

	rswitch_for_all_ports(priv, rdev) {
		if (!rdev->brdev)
			continue;
		rswitch_for_all_ports(priv, rdev2) {
			if (rdev2 == rdev)
				break;
			if (rdev2->brdev == rdev->brdev) {
				offload_brdev = rdev->brdev;
				break;
			}
		}
		if (offload_brdev)
			break;
	}

	if (offload_brdev == priv->offload_brdev)
		dev_dbg(&priv->pdev->dev,
			"changing l2 offload from %s to %s\n",
			netdev_name(priv->offload_brdev),
			netdev_name(offload_brdev));
	else if (offload_brdev)
		dev_dbg(&priv->pdev->dev, "starting l2 offload for %s\n",
			netdev_name(offload_brdev));
	else if (!offload_brdev)
		dev_dbg(&priv->pdev->dev, "stopping l2 offload for %s\n",
			netdev_name(priv->offload_brdev));

	priv->offload_brdev = offload_brdev;

	rswitch_update_l2_offload(priv);
}

static bool rswitch_port_check(const struct net_device *ndev)
{
	return is_rdev(ndev);
}

static void rswitch_port_update_brdev(struct net_device *ndev,
				      struct net_device *brdev)
{
	struct rswitch_device *rdev;

	if (!is_rdev(ndev))
		return;

	rdev = netdev_priv(ndev);
	rdev->brdev = brdev;
	rswitch_update_offload_brdev(rdev->priv);
}

static int rswitch_port_update_stp_state(struct net_device *ndev, u8 stp_state)
{
	struct rswitch_device *rdev;

	if (!is_rdev(ndev))
		return -ENODEV;

	rdev = netdev_priv(ndev);
	rdev->learning_requested = (stp_state == BR_STATE_LEARNING ||
				    stp_state == BR_STATE_FORWARDING);
	rdev->forwarding_requested = (stp_state == BR_STATE_FORWARDING);
	rswitch_update_l2_offload(rdev->priv);

Annotation

Implementation Notes