drivers/net/ethernet/hisilicon/hix5hd2_gmac.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
Extension
.c
Size
33918 bytes
Lines
1323
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 hix5hd2_netdev_ops = {
	.ndo_open		= hix5hd2_net_open,
	.ndo_stop		= hix5hd2_net_close,
	.ndo_start_xmit		= hix5hd2_net_xmit,
	.ndo_tx_timeout		= hix5hd2_net_timeout,
	.ndo_set_mac_address	= hix5hd2_net_set_mac_address,
};

static const struct ethtool_ops hix5hd2_ethtools_ops = {
	.get_link		= ethtool_op_get_link,
	.get_link_ksettings     = phy_ethtool_get_link_ksettings,
	.set_link_ksettings     = phy_ethtool_set_link_ksettings,
};

static int hix5hd2_mdio_wait_ready(struct mii_bus *bus)
{
	struct hix5hd2_priv *priv = bus->priv;
	void __iomem *base = priv->base;
	int i, timeout = 10000;

	for (i = 0; readl_relaxed(base + MDIO_SINGLE_CMD) & MDIO_START; i++) {
		if (i == timeout)
			return -ETIMEDOUT;
		usleep_range(10, 20);
	}

	return 0;
}

static int hix5hd2_mdio_read(struct mii_bus *bus, int phy, int reg)
{
	struct hix5hd2_priv *priv = bus->priv;
	void __iomem *base = priv->base;
	int val, ret;

	ret = hix5hd2_mdio_wait_ready(bus);
	if (ret < 0)
		goto out;

	writel_relaxed(MDIO_READ | phy << 8 | reg, base + MDIO_SINGLE_CMD);
	ret = hix5hd2_mdio_wait_ready(bus);
	if (ret < 0)
		goto out;

	val = readl_relaxed(base + MDIO_RDATA_STATUS);
	if (val & MDIO_R_VALID) {
		dev_err(bus->parent, "SMI bus read not valid\n");
		ret = -ENODEV;
		goto out;
	}

	val = readl_relaxed(priv->base + MDIO_SINGLE_DATA);
	ret = (val >> 16) & 0xFFFF;
out:
	return ret;
}

static int hix5hd2_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
{
	struct hix5hd2_priv *priv = bus->priv;
	void __iomem *base = priv->base;
	int ret;

	ret = hix5hd2_mdio_wait_ready(bus);
	if (ret < 0)
		goto out;

	writel_relaxed(val, base + MDIO_SINGLE_DATA);
	writel_relaxed(MDIO_WRITE | phy << 8 | reg, base + MDIO_SINGLE_CMD);
	ret = hix5hd2_mdio_wait_ready(bus);
out:
	return ret;
}

static void hix5hd2_destroy_hw_desc_queue(struct hix5hd2_priv *priv)
{
	int i;

	for (i = 0; i < QUEUE_NUMS; i++) {
		if (priv->pool[i].desc) {
			dma_free_coherent(priv->dev, priv->pool[i].size,
					  priv->pool[i].desc,
					  priv->pool[i].phys_addr);
			priv->pool[i].desc = NULL;
		}
	}
}

static int hix5hd2_init_hw_desc_queue(struct hix5hd2_priv *priv)
{

Annotation

Implementation Notes