drivers/net/ethernet/korina.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/korina.c
Extension
.c
Size
36718 bytes
Lines
1418
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 korina_netdev_ops = {
	.ndo_open		= korina_open,
	.ndo_stop		= korina_close,
	.ndo_start_xmit		= korina_send_packet,
	.ndo_set_rx_mode	= korina_multicast_list,
	.ndo_tx_timeout		= korina_tx_timeout,
	.ndo_eth_ioctl		= korina_ioctl,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= korina_poll_controller,
#endif
};

static int korina_probe(struct platform_device *pdev)
{
	u8 *mac_addr = dev_get_platdata(&pdev->dev);
	struct korina_private *lp;
	struct net_device *dev;
	struct clk *clk;
	void __iomem *p;
	int rc;

	dev = devm_alloc_etherdev(&pdev->dev, sizeof(struct korina_private));
	if (!dev)
		return -ENOMEM;

	SET_NETDEV_DEV(dev, &pdev->dev);
	lp = netdev_priv(dev);

	if (mac_addr)
		eth_hw_addr_set(dev, mac_addr);
	else if (of_get_ethdev_address(pdev->dev.of_node, dev) < 0)
		eth_hw_addr_random(dev);

	clk = devm_clk_get_optional_enabled(&pdev->dev, "mdioclk");
	if (IS_ERR(clk))
		return PTR_ERR(clk);
	if (clk) {
		lp->mii_clock_freq = clk_get_rate(clk);
	} else {
		lp->mii_clock_freq = 200000000; /* max possible input clk */
	}

	lp->rx_irq = platform_get_irq_byname(pdev, "rx");
	lp->tx_irq = platform_get_irq_byname(pdev, "tx");

	p = devm_platform_ioremap_resource_byname(pdev, "emac");
	if (IS_ERR(p)) {
		printk(KERN_ERR DRV_NAME ": cannot remap registers\n");
		return PTR_ERR(p);
	}
	lp->eth_regs = p;

	p = devm_platform_ioremap_resource_byname(pdev, "dma_rx");
	if (IS_ERR(p)) {
		printk(KERN_ERR DRV_NAME ": cannot remap Rx DMA registers\n");
		return PTR_ERR(p);
	}
	lp->rx_dma_regs = p;

	p = devm_platform_ioremap_resource_byname(pdev, "dma_tx");
	if (IS_ERR(p)) {
		printk(KERN_ERR DRV_NAME ": cannot remap Tx DMA registers\n");
		return PTR_ERR(p);
	}
	lp->tx_dma_regs = p;

	lp->td_ring = dmam_alloc_coherent(&pdev->dev, TD_RING_SIZE,
					  &lp->td_dma, GFP_KERNEL);
	if (!lp->td_ring)
		return -ENOMEM;

	lp->rd_ring = dmam_alloc_coherent(&pdev->dev, RD_RING_SIZE,
					  &lp->rd_dma, GFP_KERNEL);
	if (!lp->rd_ring)
		return -ENOMEM;

	spin_lock_init(&lp->lock);
	/* just use the rx dma irq */
	dev->irq = lp->rx_irq;
	lp->dev = dev;
	lp->dmadev = &pdev->dev;

	dev->netdev_ops = &korina_netdev_ops;
	dev->ethtool_ops = &netdev_ethtool_ops;
	dev->watchdog_timeo = TX_TIMEOUT;
	netif_napi_add(dev, &lp->napi, korina_poll);

	lp->mii_if.dev = dev;

Annotation

Implementation Notes