drivers/net/ethernet/sun/sunqe.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sun/sunqe.c
Extension
.c
Size
25759 bytes
Lines
995
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 qec_ops = {
	.ndo_open		= qe_open,
	.ndo_stop		= qe_close,
	.ndo_start_xmit		= qe_start_xmit,
	.ndo_set_rx_mode	= qe_set_multicast,
	.ndo_tx_timeout		= qe_tx_timeout,
	.ndo_set_mac_address	= eth_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
};

static int qec_ether_init(struct platform_device *op)
{
	static unsigned version_printed;
	struct net_device *dev;
	struct sunqec *qecp;
	struct sunqe *qe;
	int i, res;

	if (version_printed++ == 0)
		printk(KERN_INFO "%s", version);

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

	eth_hw_addr_set(dev, idprom->id_ethaddr);

	qe = netdev_priv(dev);

	res = -ENODEV;

	i = of_getintprop_default(op->dev.of_node, "channel#", -1);
	if (i == -1)
		goto fail;
	qe->channel = i;
	spin_lock_init(&qe->lock);

	qecp = get_qec(op);
	if (!qecp)
		goto fail;

	qecp->qes[qe->channel] = qe;
	qe->dev = dev;
	qe->parent = qecp;
	qe->op = op;

	res = -ENOMEM;
	qe->qcregs = of_ioremap(&op->resource[0], 0,
				CREG_REG_SIZE, "QEC Channel Registers");
	if (!qe->qcregs) {
		printk(KERN_ERR "qe: Cannot map channel registers.\n");
		goto fail;
	}

	qe->mregs = of_ioremap(&op->resource[1], 0,
			       MREGS_REG_SIZE, "QE MACE Registers");
	if (!qe->mregs) {
		printk(KERN_ERR "qe: Cannot map MACE registers.\n");
		goto fail;
	}

	qe->qe_block = dma_alloc_coherent(&op->dev, PAGE_SIZE,
					  &qe->qblock_dvma, GFP_ATOMIC);
	qe->buffers = dma_alloc_coherent(&op->dev, sizeof(struct sunqe_buffers),
					 &qe->buffers_dvma, GFP_ATOMIC);
	if (qe->qe_block == NULL || qe->qblock_dvma == 0 ||
	    qe->buffers == NULL || qe->buffers_dvma == 0)
		goto fail;

	/* Stop this QE. */
	qe_stop(qe);

	SET_NETDEV_DEV(dev, &op->dev);

	dev->watchdog_timeo = 5*HZ;
	dev->irq = op->archdata.irqs[0];
	dev->dma = 0;
	dev->ethtool_ops = &qe_ethtool_ops;
	dev->netdev_ops = &qec_ops;

	res = register_netdev(dev);
	if (res)
		goto fail;

	platform_set_drvdata(op, qe);

	printk(KERN_INFO "%s: qe channel[%d] %pM\n", dev->name, qe->channel,
	       dev->dev_addr);
	return 0;

Annotation

Implementation Notes