drivers/net/ethernet/broadcom/bcm63xx_enet.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/broadcom/bcm63xx_enet.c
Extension
.c
Size
71723 bytes
Lines
2815
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 bcm_enet_ops = {
	.ndo_open		= bcm_enet_open,
	.ndo_stop		= bcm_enet_stop,
	.ndo_start_xmit		= bcm_enet_start_xmit,
	.ndo_set_mac_address	= bcm_enet_set_mac_address,
	.ndo_set_rx_mode	= bcm_enet_set_multicast_list,
	.ndo_eth_ioctl		= bcm_enet_ioctl,
	.ndo_change_mtu		= bcm_enet_change_mtu,
};

/*
 * allocate netdevice, request register memory and register device.
 */
static int bcm_enet_probe(struct platform_device *pdev)
{
	struct bcm_enet_priv *priv;
	struct net_device *dev;
	struct bcm63xx_enet_platform_data *pd;
	int irq, irq_rx, irq_tx;
	struct mii_bus *bus;
	int i, ret;

	if (!bcm_enet_shared_base[0])
		return -EPROBE_DEFER;

	irq = platform_get_irq(pdev, 0);
	irq_rx = platform_get_irq(pdev, 1);
	irq_tx = platform_get_irq(pdev, 2);
	if (irq < 0 || irq_rx < 0 || irq_tx < 0)
		return -ENODEV;

	dev = alloc_etherdev(sizeof(*priv));
	if (!dev)
		return -ENOMEM;
	priv = netdev_priv(dev);

	priv->enet_is_sw = false;
	priv->dma_maxburst = BCMENET_DMA_MAXBURST;
	priv->rx_buf_offset = NET_SKB_PAD;

	ret = bcm_enet_change_mtu(dev, dev->mtu);
	if (ret)
		goto out;

	priv->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(priv->base)) {
		ret = PTR_ERR(priv->base);
		goto out;
	}

	dev->irq = priv->irq = irq;
	priv->irq_rx = irq_rx;
	priv->irq_tx = irq_tx;

	priv->mac_clk = devm_clk_get(&pdev->dev, "enet");
	if (IS_ERR(priv->mac_clk)) {
		ret = PTR_ERR(priv->mac_clk);
		goto out;
	}
	ret = clk_prepare_enable(priv->mac_clk);
	if (ret)
		goto out;

	/* initialize default and fetch platform data */
	priv->rx_ring_size = BCMENET_DEF_RX_DESC;
	priv->tx_ring_size = BCMENET_DEF_TX_DESC;

	pd = dev_get_platdata(&pdev->dev);
	if (pd) {
		eth_hw_addr_set(dev, pd->mac_addr);
		priv->has_phy = pd->has_phy;
		priv->phy_id = pd->phy_id;
		priv->has_phy_interrupt = pd->has_phy_interrupt;
		priv->phy_interrupt = pd->phy_interrupt;
		priv->use_external_mii = !pd->use_internal_phy;
		priv->pause_auto = pd->pause_auto;
		priv->pause_rx = pd->pause_rx;
		priv->pause_tx = pd->pause_tx;
		priv->force_duplex_full = pd->force_duplex_full;
		priv->force_speed_100 = pd->force_speed_100;
		priv->dma_chan_en_mask = pd->dma_chan_en_mask;
		priv->dma_chan_int_mask = pd->dma_chan_int_mask;
		priv->dma_chan_width = pd->dma_chan_width;
		priv->dma_has_sram = pd->dma_has_sram;
		priv->dma_desc_shift = pd->dma_desc_shift;
		priv->rx_chan = pd->rx_chan;
		priv->tx_chan = pd->tx_chan;
	}

	if (priv->has_phy && !priv->use_external_mii) {

Annotation

Implementation Notes