drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
Extension
.c
Size
15316 bytes
Lines
549
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct net_device_ops mlxbf_gige_netdev_ops = {
	.ndo_open		= mlxbf_gige_open,
	.ndo_stop		= mlxbf_gige_stop,
	.ndo_start_xmit		= mlxbf_gige_start_xmit,
	.ndo_set_mac_address	= eth_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_eth_ioctl		= mlxbf_gige_eth_ioctl,
	.ndo_set_rx_mode        = mlxbf_gige_set_rx_mode,
	.ndo_get_stats64        = mlxbf_gige_get_stats64,
};

static void mlxbf_gige_bf2_adjust_link(struct net_device *netdev)
{
	struct phy_device *phydev = netdev->phydev;

	phy_print_status(phydev);
}

static void mlxbf_gige_bf3_adjust_link(struct net_device *netdev)
{
	struct mlxbf_gige *priv = netdev_priv(netdev);
	struct phy_device *phydev = netdev->phydev;
	u8 sgmii_mode;
	u16 ipg_size;
	u32 val;

	if (phydev->link && phydev->speed != priv->prev_speed) {
		switch (phydev->speed) {
		case 1000:
			ipg_size = MLXBF_GIGE_1G_IPG_SIZE;
			sgmii_mode = MLXBF_GIGE_1G_SGMII_MODE;
			break;
		case 100:
			ipg_size = MLXBF_GIGE_100M_IPG_SIZE;
			sgmii_mode = MLXBF_GIGE_100M_SGMII_MODE;
			break;
		case 10:
			ipg_size = MLXBF_GIGE_10M_IPG_SIZE;
			sgmii_mode = MLXBF_GIGE_10M_SGMII_MODE;
			break;
		default:
			return;
		}

		val = readl(priv->plu_base + MLXBF_GIGE_PLU_TX_REG0);
		val &= ~(MLXBF_GIGE_PLU_TX_IPG_SIZE_MASK | MLXBF_GIGE_PLU_TX_SGMII_MODE_MASK);
		val |= FIELD_PREP(MLXBF_GIGE_PLU_TX_IPG_SIZE_MASK, ipg_size);
		val |= FIELD_PREP(MLXBF_GIGE_PLU_TX_SGMII_MODE_MASK, sgmii_mode);
		writel(val, priv->plu_base + MLXBF_GIGE_PLU_TX_REG0);

		val = readl(priv->plu_base + MLXBF_GIGE_PLU_RX_REG0);
		val &= ~MLXBF_GIGE_PLU_RX_SGMII_MODE_MASK;
		val |= FIELD_PREP(MLXBF_GIGE_PLU_RX_SGMII_MODE_MASK, sgmii_mode);
		writel(val, priv->plu_base + MLXBF_GIGE_PLU_RX_REG0);

		priv->prev_speed = phydev->speed;
	}

	phy_print_status(phydev);
}

static void mlxbf_gige_bf2_set_phy_link_mode(struct phy_device *phydev)
{
	/* MAC only supports 1000T full duplex mode */
	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Full_BIT);
	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);

	/* Only symmetric pause with flow control enabled is supported so no
	 * need to negotiate pause.
	 */
	linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising);
	linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising);
}

static void mlxbf_gige_bf3_set_phy_link_mode(struct phy_device *phydev)
{
	/* MAC only supports full duplex mode */
	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);

	/* Only symmetric pause with flow control enabled is supported so no
	 * need to negotiate pause.
	 */
	linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising);
	linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising);
}

Annotation

Implementation Notes