drivers/net/phy/smsc.c

Source file repositories/reference/linux-study-clean/drivers/net/phy/smsc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/phy/smsc.c
Extension
.c
Size
22004 bytes
Lines
901
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

struct smsc_hw_stat {
	const char *string;
	u8 reg;
	u8 bits;
};

static struct smsc_hw_stat smsc_hw_stats[] = {
	{ "phy_symbol_errors", 26, 16},
};

struct smsc_phy_priv {
	unsigned int edpd_enable:1;
	unsigned int edpd_mode_set_by_user:1;
	unsigned int edpd_max_wait_ms;
	bool wol_arp;
};

static int smsc_phy_ack_interrupt(struct phy_device *phydev)
{
	int rc = phy_read(phydev, MII_LAN83C185_ISF);

	return rc < 0 ? rc : 0;
}

int smsc_phy_config_intr(struct phy_device *phydev)
{
	int rc;

	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
		rc = smsc_phy_ack_interrupt(phydev);
		if (rc)
			return rc;

		rc = phy_write(phydev, MII_LAN83C185_IM,
			       MII_LAN83C185_ISF_INT_PHYLIB_EVENTS);
	} else {
		rc = phy_write(phydev, MII_LAN83C185_IM, 0);
		if (rc)
			return rc;

		rc = smsc_phy_ack_interrupt(phydev);
	}

	return rc < 0 ? rc : 0;
}
EXPORT_SYMBOL_GPL(smsc_phy_config_intr);

static int smsc_phy_config_edpd(struct phy_device *phydev)
{
	struct smsc_phy_priv *priv = phydev->priv;

	if (priv->edpd_enable)
		return phy_set_bits(phydev, MII_LAN83C185_CTRL_STATUS,
				    MII_LAN83C185_EDPWRDOWN);
	else
		return phy_clear_bits(phydev, MII_LAN83C185_CTRL_STATUS,
				      MII_LAN83C185_EDPWRDOWN);
}

irqreturn_t smsc_phy_handle_interrupt(struct phy_device *phydev)
{
	int irq_status;

	irq_status = phy_read(phydev, MII_LAN83C185_ISF);
	if (irq_status < 0) {
		if (irq_status != -ENODEV)
			phy_error(phydev);

		return IRQ_NONE;
	}

	if (!(irq_status & MII_LAN83C185_ISF_INT_PHYLIB_EVENTS))
		return IRQ_NONE;

	phy_trigger_machine(phydev);

	return IRQ_HANDLED;
}
EXPORT_SYMBOL_GPL(smsc_phy_handle_interrupt);

int smsc_phy_config_init(struct phy_device *phydev)
{
	struct smsc_phy_priv *priv = phydev->priv;

	if (!priv)
		return 0;

	/* don't use EDPD in irq mode except overridden by user */
	if (!priv->edpd_mode_set_by_user && phydev->irq != PHY_POLL)
		priv->edpd_enable = false;

Annotation

Implementation Notes