drivers/net/ethernet/microchip/lan966x/lan966x_mirror.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/microchip/lan966x/lan966x_mirror.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/microchip/lan966x/lan966x_mirror.c
Extension
.c
Size
3426 bytes
Lines
139
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

// SPDX-License-Identifier: GPL-2.0+

#include "lan966x_main.h"

int lan966x_mirror_port_add(struct lan966x_port *port,
			    struct flow_action_entry *action,
			    unsigned long mirror_id,
			    bool ingress,
			    struct netlink_ext_ack *extack)
{
	struct lan966x *lan966x = port->lan966x;
	struct lan966x_port *monitor_port;

	if (!lan966x_netdevice_check(action->dev)) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Destination not an lan966x port");
		return -EOPNOTSUPP;
	}

	monitor_port = netdev_priv(action->dev);

	if (lan966x->mirror_mask[ingress] & BIT(port->chip_port)) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Mirror already exists");
		return -EEXIST;
	}

	if (lan966x->mirror_monitor &&
	    lan966x->mirror_monitor != monitor_port) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Cannot change mirror port while in use");
		return -EBUSY;
	}

	if (port == monitor_port) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Cannot mirror the monitor port");
		return -EINVAL;
	}

	lan966x->mirror_mask[ingress] |= BIT(port->chip_port);

	lan966x->mirror_monitor = monitor_port;
	lan_wr(BIT(monitor_port->chip_port), lan966x, ANA_MIRRORPORTS);

	if (ingress) {
		lan_rmw(ANA_PORT_CFG_SRC_MIRROR_ENA_SET(1),
			ANA_PORT_CFG_SRC_MIRROR_ENA,
			lan966x, ANA_PORT_CFG(port->chip_port));
	} else {
		lan_wr(lan966x->mirror_mask[0], lan966x,
		       ANA_EMIRRORPORTS);
	}

	lan966x->mirror_count++;

	if (ingress)
		port->tc.ingress_mirror_id = mirror_id;
	else
		port->tc.egress_mirror_id = mirror_id;

	return 0;
}

int lan966x_mirror_port_del(struct lan966x_port *port,
			    bool ingress,
			    struct netlink_ext_ack *extack)
{
	struct lan966x *lan966x = port->lan966x;

	if (!(lan966x->mirror_mask[ingress] & BIT(port->chip_port))) {
		NL_SET_ERR_MSG_MOD(extack,
				   "There is no mirroring for this port");
		return -ENOENT;
	}

	lan966x->mirror_mask[ingress] &= ~BIT(port->chip_port);

	if (ingress) {
		lan_rmw(ANA_PORT_CFG_SRC_MIRROR_ENA_SET(0),
			ANA_PORT_CFG_SRC_MIRROR_ENA,
			lan966x, ANA_PORT_CFG(port->chip_port));
	} else {
		lan_wr(lan966x->mirror_mask[0], lan966x,
		       ANA_EMIRRORPORTS);
	}

	lan966x->mirror_count--;

	if (lan966x->mirror_count == 0) {

Annotation

Implementation Notes