drivers/net/ethernet/sgi/ioc3-eth.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sgi/ioc3-eth.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sgi/ioc3-eth.c
Extension
.c
Size
33876 bytes
Lines
1287
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 ioc3_netdev_ops = {
	.ndo_open		= ioc3_open,
	.ndo_stop		= ioc3_close,
	.ndo_start_xmit		= ioc3_start_xmit,
	.ndo_tx_timeout		= ioc3_timeout,
	.ndo_get_stats		= ioc3_get_stats,
	.ndo_set_rx_mode	= ioc3_set_multicast_list,
	.ndo_eth_ioctl		= ioc3_ioctl,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= ioc3_set_mac_address,
};

static int ioc3eth_probe(struct platform_device *pdev)
{
	u32 sw_physid1, sw_physid2, vendor, model, rev;
	struct ioc3_private *ip;
	struct net_device *dev;
	struct resource *regs;
	u8 mac_addr[6];
	int err;

	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!regs) {
		dev_err(&pdev->dev, "Invalid resource\n");
		return -EINVAL;
	}
	/* get mac addr from one wire prom */
	if (ioc3eth_get_mac_addr(regs, mac_addr))
		return -EPROBE_DEFER; /* not available yet */

	dev = alloc_etherdev(sizeof(struct ioc3_private));
	if (!dev)
		return -ENOMEM;

	SET_NETDEV_DEV(dev, &pdev->dev);

	ip = netdev_priv(dev);
	ip->dma_dev = pdev->dev.parent;
	ip->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(ip->regs)) {
		err = PTR_ERR(ip->regs);
		goto out_free;
	}

	ip->ssram = devm_platform_ioremap_resource(pdev, 1);
	if (IS_ERR(ip->ssram)) {
		err = PTR_ERR(ip->ssram);
		goto out_free;
	}

	dev->irq = platform_get_irq(pdev, 0);
	if (dev->irq < 0) {
		err = dev->irq;
		goto out_free;
	}

	if (devm_request_irq(&pdev->dev, dev->irq, ioc3_interrupt,
			     IRQF_SHARED, "ioc3-eth", dev)) {
		dev_err(&pdev->dev, "Can't get irq %d\n", dev->irq);
		err = -ENODEV;
		goto out_free;
	}

	spin_lock_init(&ip->ioc3_lock);
	timer_setup(&ip->ioc3_timer, ioc3_timer, 0);

	ioc3_stop(ip);

	/* Allocate rx ring.  4kb = 512 entries, must be 4kb aligned */
	ip->rxr = dma_alloc_coherent(ip->dma_dev, RX_RING_SIZE, &ip->rxr_dma,
				     GFP_KERNEL);
	if (!ip->rxr) {
		pr_err("ioc3-eth: rx ring allocation failed\n");
		err = -ENOMEM;
		goto out_stop;
	}

	/* Allocate tx rings.  16kb = 128 bufs, must be 16kb aligned  */
	ip->tx_ring = dma_alloc_coherent(ip->dma_dev, TX_RING_SIZE + SZ_16K - 1,
					 &ip->txr_dma, GFP_KERNEL);
	if (!ip->tx_ring) {
		pr_err("ioc3-eth: tx ring allocation failed\n");
		err = -ENOMEM;
		goto out_stop;
	}
	/* Align TX ring */
	ip->txr = PTR_ALIGN(ip->tx_ring, SZ_16K);
	ip->txr_dma = ALIGN(ip->txr_dma, SZ_16K);

	ioc3_init(dev);

Annotation

Implementation Notes