drivers/net/ethernet/atheros/ag71xx.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/atheros/ag71xx.c
Extension
.c
Size
51761 bytes
Lines
2039
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 ag71xx_netdev_ops = {
	.ndo_open		= ag71xx_open,
	.ndo_stop		= ag71xx_stop,
	.ndo_start_xmit		= ag71xx_hard_start_xmit,
	.ndo_eth_ioctl		= ag71xx_do_ioctl,
	.ndo_tx_timeout		= ag71xx_tx_timeout,
	.ndo_change_mtu		= ag71xx_change_mtu,
	.ndo_set_mac_address	= eth_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
};

static const u32 ar71xx_addr_ar7100[] = {
	0x19000000, 0x1a000000,
};

static int ag71xx_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	const struct ag71xx_dcfg *dcfg;
	struct net_device *ndev;
	struct resource *res;
	struct clk *clk_eth;
	int tx_size, err, i;
	struct ag71xx *ag;

	if (!np)
		return -ENODEV;

	ndev = devm_alloc_etherdev(&pdev->dev, sizeof(*ag));
	if (!ndev)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -EINVAL;

	dcfg = of_device_get_match_data(&pdev->dev);
	if (!dcfg)
		return -EINVAL;

	ag = netdev_priv(ndev);
	ag->mac_idx = -1;
	for (i = 0; i < ARRAY_SIZE(ar71xx_addr_ar7100); i++) {
		if (ar71xx_addr_ar7100[i] == res->start)
			ag->mac_idx = i;
	}

	if (ag->mac_idx < 0) {
		netif_err(ag, probe, ndev, "unknown mac idx\n");
		return -EINVAL;
	}

	clk_eth = devm_clk_get_enabled(&pdev->dev, "eth");
	if (IS_ERR(clk_eth))
		return dev_err_probe(&pdev->dev, PTR_ERR(clk_eth),
				     "Failed to get eth clk.");

	SET_NETDEV_DEV(ndev, &pdev->dev);

	ag->pdev = pdev;
	ag->ndev = ndev;
	ag->dcfg = dcfg;
	ag->msg_enable = netif_msg_init(-1, AG71XX_DEFAULT_MSG_ENABLE);
	memcpy(ag->fifodata, dcfg->fifodata, sizeof(ag->fifodata));

	ag->mac_reset = devm_reset_control_get(&pdev->dev, "mac");
	if (IS_ERR(ag->mac_reset))
		return dev_err_probe(&pdev->dev, PTR_ERR(ag->mac_reset),
				     "missing mac reset");

	ag->mac_base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(ag->mac_base))
		return PTR_ERR(ag->mac_base);

	/* ensure that HW is in manual polling mode before interrupts are
	 * activated. Otherwise ag71xx_interrupt might call napi_schedule
	 * before it is initialized by netif_napi_add.
	 */
	ag71xx_int_disable(ag, AG71XX_INT_POLL);

	ndev->irq = platform_get_irq(pdev, 0);
	if (ndev->irq < 0)
		return ndev->irq;

	err = devm_request_irq(&pdev->dev, ndev->irq, ag71xx_interrupt,
			       0x0, dev_name(&pdev->dev), ndev);
	if (err) {
		netif_err(ag, probe, ndev, "unable to request IRQ %d\n",
			  ndev->irq);
		return err;

Annotation

Implementation Notes