drivers/net/ethernet/atheros/alx/ethtool.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/atheros/alx/ethtool.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/atheros/alx/ethtool.c
Extension
.c
Size
8860 bytes
Lines
335
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 (hw->flowctrl & ALX_FC_RX) {
			advertising |= ADVERTISED_Pause;

			if (!(hw->flowctrl & ALX_FC_TX))
				advertising |= ADVERTISED_Asym_Pause;
		} else if (hw->flowctrl & ALX_FC_TX) {
			advertising |= ADVERTISED_Asym_Pause;
		}
	}

	mutex_lock(&alx->mtx);
	cmd->base.speed = hw->link_speed;
	cmd->base.duplex = hw->duplex;
	mutex_unlock(&alx->mtx);

	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
						supported);
	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
						advertising);

	return 0;
}

static int alx_set_link_ksettings(struct net_device *netdev,
				  const struct ethtool_link_ksettings *cmd)
{
	struct alx_priv *alx = netdev_priv(netdev);
	struct alx_hw *hw = &alx->hw;
	u32 adv_cfg;
	u32 advertising;
	int ret;

	ethtool_convert_link_mode_to_legacy_u32(&advertising,
						cmd->link_modes.advertising);

	if (cmd->base.autoneg == AUTONEG_ENABLE) {
		if (advertising & ~alx_get_supported_speeds(hw))
			return -EINVAL;
		adv_cfg = advertising | ADVERTISED_Autoneg;
	} else {
		adv_cfg = alx_speed_to_ethadv(cmd->base.speed,
					      cmd->base.duplex);

		if (!adv_cfg || adv_cfg == ADVERTISED_1000baseT_Full)
			return -EINVAL;
	}

	hw->adv_cfg = adv_cfg;

	mutex_lock(&alx->mtx);
	ret = alx_setup_speed_duplex(hw, adv_cfg, hw->flowctrl);
	mutex_unlock(&alx->mtx);

	return ret;
}

static void alx_get_pauseparam(struct net_device *netdev,
			       struct ethtool_pauseparam *pause)
{
	struct alx_priv *alx = netdev_priv(netdev);
	struct alx_hw *hw = &alx->hw;

	mutex_lock(&alx->mtx);
	pause->autoneg = !!(hw->flowctrl & ALX_FC_ANEG &&
			    hw->adv_cfg & ADVERTISED_Autoneg);
	pause->tx_pause = !!(hw->flowctrl & ALX_FC_TX);
	pause->rx_pause = !!(hw->flowctrl & ALX_FC_RX);
	mutex_unlock(&alx->mtx);
}


static int alx_set_pauseparam(struct net_device *netdev,
			      struct ethtool_pauseparam *pause)
{
	struct alx_priv *alx = netdev_priv(netdev);
	struct alx_hw *hw = &alx->hw;
	int err = 0;
	bool reconfig_phy = false;
	u8 fc = 0;

	if (pause->tx_pause)
		fc |= ALX_FC_TX;
	if (pause->rx_pause)
		fc |= ALX_FC_RX;
	if (pause->autoneg)
		fc |= ALX_FC_ANEG;

	mutex_lock(&alx->mtx);

	/* restart auto-neg for auto-mode */

Annotation

Implementation Notes