drivers/net/ethernet/marvell/prestera/prestera_ethtool.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
Extension
.c
Size
22692 bytes
Lines
798
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 (err) {
			state->speed = SPEED_UNKNOWN;
			state->duplex = DUPLEX_UNKNOWN;
		} else {
			state->speed = speed;
			state->duplex = duplex == PRESTERA_PORT_DUPLEX_FULL ?
					  DUPLEX_FULL : DUPLEX_HALF;
		}
	}

	ecmd->base.speed = port->state_mac.speed;
	ecmd->base.duplex = port->state_mac.duplex;
}

static void prestera_port_mdix_get(struct ethtool_link_ksettings *ecmd,
				   struct prestera_port *port)
{
	struct prestera_port_phy_state *state = &port->state_phy;

	if (prestera_hw_port_phy_mode_get(port,
					  &state->mdix, NULL, NULL, NULL)) {
		netdev_warn(port->dev, "MDIX params get failed");
		state->mdix = ETH_TP_MDI_INVALID;
	}

	ecmd->base.eth_tp_mdix = port->state_phy.mdix;
	ecmd->base.eth_tp_mdix_ctrl = port->cfg_phy.mdix;
}

static int
prestera_ethtool_get_link_ksettings(struct net_device *dev,
				    struct ethtool_link_ksettings *ecmd)
{
	struct prestera_port *port = netdev_priv(dev);

	ethtool_link_ksettings_zero_link_mode(ecmd, supported);
	ethtool_link_ksettings_zero_link_mode(ecmd, advertising);
	ethtool_link_ksettings_zero_link_mode(ecmd, lp_advertising);
	ecmd->base.speed = SPEED_UNKNOWN;
	ecmd->base.duplex = DUPLEX_UNKNOWN;

	if (port->phy_link)
		return phylink_ethtool_ksettings_get(port->phy_link, ecmd);

	ecmd->base.autoneg = port->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;

	if (port->caps.type == PRESTERA_PORT_TYPE_TP) {
		ethtool_link_ksettings_add_link_mode(ecmd, supported, Autoneg);

		if (netif_running(dev) &&
		    (port->autoneg ||
		     port->caps.transceiver == PRESTERA_PORT_TCVR_COPPER))
			ethtool_link_ksettings_add_link_mode(ecmd, advertising,
							     Autoneg);
	}

	prestera_modes_to_eth(ecmd->link_modes.supported,
			      port->caps.supp_link_modes,
			      port->caps.supp_fec,
			      port->caps.type);

	prestera_port_supp_types_get(ecmd, port);

	if (netif_carrier_ok(dev))
		prestera_port_link_mode_get(ecmd, port);

	ecmd->base.port = prestera_port_type_get(port);

	if (port->autoneg) {
		if (netif_running(dev))
			prestera_modes_to_eth(ecmd->link_modes.advertising,
					      port->adver_link_modes,
					      port->adver_fec,
					      port->caps.type);

		if (netif_carrier_ok(dev) &&
		    port->caps.transceiver == PRESTERA_PORT_TCVR_COPPER)
			prestera_port_remote_cap_get(ecmd, port);
	}

	if (port->caps.type == PRESTERA_PORT_TYPE_TP &&
	    port->caps.transceiver == PRESTERA_PORT_TCVR_COPPER)
		prestera_port_mdix_get(ecmd, port);

	return 0;
}

static int prestera_port_mdix_set(const struct ethtool_link_ksettings *ecmd,
				  struct prestera_port *port)
{

Annotation

Implementation Notes