drivers/net/dsa/ocelot/felix.c

Source file repositories/reference/linux-study-clean/drivers/net/dsa/ocelot/felix.c

File Facts

System
Linux kernel
Corpus path
drivers/net/dsa/ocelot/felix.c
Extension
.c
Size
68111 bytes
Lines
2465
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 (using_tag_8021q) {
			/* Redirect to the tag_8021q CPU port. If timestamps
			 * are necessary, also copy trapped packets to the CPU
			 * port module.
			 */
			mask_mode = OCELOT_MASK_MODE_REDIRECT;
			port_mask = BIT(felix_trap_get_cpu_port(ds, trap));
			cpu_copy_ena = !!trap->take_ts;
		} else {
			/* Trap packets only to the CPU port module, which is
			 * redirected to the NPI port (the DSA CPU port)
			 */
			mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
			port_mask = 0;
			cpu_copy_ena = true;
		}

		if (trap->action.mask_mode == mask_mode &&
		    trap->action.port_mask == port_mask &&
		    trap->action.cpu_copy_ena == cpu_copy_ena)
			continue;

		trap->action.mask_mode = mask_mode;
		trap->action.port_mask = port_mask;
		trap->action.cpu_copy_ena = cpu_copy_ena;

		err = ocelot_vcap_filter_replace(ocelot, trap);
		if (err)
			return err;
	}

	return 0;
}

/* The CPU port module is connected to the Node Processor Interface (NPI). This
 * is the mode through which frames can be injected from and extracted to an
 * external CPU, over Ethernet. In NXP SoCs, the "external CPU" is the ARM CPU
 * running Linux, and this forms a DSA setup together with the enetc or fman
 * DSA conduit.
 */
static void felix_npi_port_init(struct ocelot *ocelot, int port)
{
	ocelot->npi = port;

	ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
		     QSYS_EXT_CPU_CFG_EXT_CPU_PORT(port),
		     QSYS_EXT_CPU_CFG);

	/* NPI port Injection/Extraction configuration */
	ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_XTR_HDR,
			    ocelot->npi_xtr_prefix);
	ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_INJ_HDR,
			    ocelot->npi_inj_prefix);

	/* Disable transmission of pause frames */
	ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 0);
}

static void felix_npi_port_deinit(struct ocelot *ocelot, int port)
{
	/* Restore hardware defaults */
	int unused_port = ocelot->num_phys_ports + 2;

	ocelot->npi = -1;

	ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPU_PORT(unused_port),
		     QSYS_EXT_CPU_CFG);

	ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_XTR_HDR,
			    OCELOT_TAG_PREFIX_DISABLED);
	ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_INJ_HDR,
			    OCELOT_TAG_PREFIX_DISABLED);

	/* Enable transmission of pause frames */
	ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 1);
}

static int felix_tag_npi_setup(struct dsa_switch *ds)
{
	struct dsa_port *dp, *first_cpu_dp = NULL;
	struct ocelot *ocelot = ds->priv;

	dsa_switch_for_each_user_port(dp, ds) {
		if (first_cpu_dp && dp->cpu_dp != first_cpu_dp) {
			dev_err(ds->dev, "Multiple NPI ports not supported\n");
			return -EINVAL;
		}

		first_cpu_dp = dp->cpu_dp;
	}

Annotation

Implementation Notes