drivers/net/ethernet/mscc/ocelot_mm.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mscc/ocelot_mm.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mscc/ocelot_mm.c
Extension
.c
Size
8681 bytes
Lines
301
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

// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
 * Hardware library for MAC Merge Layer and Frame Preemption on TSN-capable
 * switches (VSC9959)
 *
 * Copyright 2022-2023 NXP
 */
#include <linux/ethtool.h>
#include <soc/mscc/ocelot.h>
#include <soc/mscc/ocelot_dev.h>
#include <soc/mscc/ocelot_qsys.h>

#include "ocelot.h"

static const char *
mm_verify_state_to_string(enum ethtool_mm_verify_status state)
{
	switch (state) {
	case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
		return "INITIAL";
	case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
		return "VERIFYING";
	case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
		return "SUCCEEDED";
	case ETHTOOL_MM_VERIFY_STATUS_FAILED:
		return "FAILED";
	case ETHTOOL_MM_VERIFY_STATUS_DISABLED:
		return "DISABLED";
	default:
		return "UNKNOWN";
	}
}

static enum ethtool_mm_verify_status ocelot_mm_verify_status(u32 val)
{
	switch (DEV_MM_STAT_MM_STATUS_PRMPT_VERIFY_STATE_X(val)) {
	case 0:
		return ETHTOOL_MM_VERIFY_STATUS_INITIAL;
	case 1:
		return ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
	case 2:
		return ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
	case 3:
		return ETHTOOL_MM_VERIFY_STATUS_FAILED;
	case 4:
		return ETHTOOL_MM_VERIFY_STATUS_DISABLED;
	default:
		return ETHTOOL_MM_VERIFY_STATUS_UNKNOWN;
	}
}

void ocelot_port_update_active_preemptible_tcs(struct ocelot *ocelot, int port)
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];
	struct ocelot_mm_state *mm = &ocelot->mm[port];
	u32 val = 0;

	lockdep_assert_held(&ocelot->fwd_domain_lock);

	/* Only commit preemptible TCs when MAC Merge is active.
	 * On NXP LS1028A, when using QSGMII, the port hangs if transmitting
	 * preemptible frames at any other link speed than gigabit, so avoid
	 * preemption at lower speeds in this PHY mode.
	 */
	if ((ocelot_port->phy_mode != PHY_INTERFACE_MODE_QSGMII ||
	     ocelot_port->speed == SPEED_1000) && mm->tx_active)
		val = mm->preemptible_tcs;

	/* Cut through switching doesn't work for preemptible priorities,
	 * so first make sure it is disabled. Also, changing the preemptible
	 * TCs affects the oversized frame dropping logic, so that needs to be
	 * re-triggered. And since tas_guard_bands_update() also implicitly
	 * calls cut_through_fwd(), we don't need to explicitly call it.
	 */
	mm->active_preemptible_tcs = val;
	ocelot->ops->tas_guard_bands_update(ocelot, port);

	dev_dbg(ocelot->dev,
		"port %d %s/%s, MM TX %s, preemptible TCs 0x%x, active 0x%x\n",
		port, phy_modes(ocelot_port->phy_mode),
		phy_speed_to_str(ocelot_port->speed),
		mm->tx_active ? "active" : "inactive", mm->preemptible_tcs,
		mm->active_preemptible_tcs);

	ocelot_rmw_rix(ocelot, QSYS_PREEMPTION_CFG_P_QUEUES(val),
		       QSYS_PREEMPTION_CFG_P_QUEUES_M,
		       QSYS_PREEMPTION_CFG, port);
}

void ocelot_port_change_fp(struct ocelot *ocelot, int port,

Annotation

Implementation Notes