drivers/net/ethernet/broadcom/bnx2.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/broadcom/bnx2.c
Extension
.c
Size
220024 bytes
Lines
8812
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 bnx2_netdev_ops = {
	.ndo_open		= bnx2_open,
	.ndo_start_xmit		= bnx2_start_xmit,
	.ndo_stop		= bnx2_close,
	.ndo_get_stats64	= bnx2_get_stats64,
	.ndo_set_rx_mode	= bnx2_set_rx_mode,
	.ndo_eth_ioctl		= bnx2_ioctl,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= bnx2_change_mac_addr,
	.ndo_change_mtu		= bnx2_change_mtu,
	.ndo_set_features	= bnx2_set_features,
	.ndo_tx_timeout		= bnx2_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= poll_bnx2,
#endif
};

static int
bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct net_device *dev;
	struct bnx2 *bp;
	int rc;
	char str[40];

	/* dev zeroed in init_etherdev */
	dev = alloc_etherdev_mq(sizeof(*bp), TX_MAX_RINGS);
	if (!dev)
		return -ENOMEM;

	rc = bnx2_init_board(pdev, dev);
	if (rc < 0)
		goto err_free;

	dev->netdev_ops = &bnx2_netdev_ops;
	dev->watchdog_timeo = TX_TIMEOUT;
	dev->ethtool_ops = &bnx2_ethtool_ops;

	bp = netdev_priv(dev);

	pci_set_drvdata(pdev, dev);

	/*
	 * In-flight DMA from 1st kernel could continue going in kdump kernel.
	 * New io-page table has been created before bnx2 does reset at open stage.
	 * We have to wait for the in-flight DMA to complete to avoid it look up
	 * into the newly created io-page table.
	 */
	if (is_kdump_kernel())
		bnx2_wait_dma_complete(bp);

	eth_hw_addr_set(dev, bp->mac_addr);

	dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
		NETIF_F_TSO | NETIF_F_TSO_ECN |
		NETIF_F_RXHASH | NETIF_F_RXCSUM;

	if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
		dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;

	dev->vlan_features = dev->hw_features;
	dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
	dev->features |= dev->hw_features;
	dev->priv_flags |= IFF_UNICAST_FLT;
	dev->min_mtu = MIN_ETHERNET_PACKET_SIZE;
	dev->max_mtu = MAX_ETHERNET_JUMBO_PACKET_SIZE;

	if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
		dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;

	if ((rc = register_netdev(dev))) {
		dev_err(&pdev->dev, "Cannot register net device\n");
		goto error;
	}

	netdev_info(dev, "%s (%c%d) %s found at mem %lx, IRQ %d, "
		    "node addr %pM\n", board_info[ent->driver_data].name,
		    ((BNX2_CHIP_ID(bp) & 0xf000) >> 12) + 'A',
		    ((BNX2_CHIP_ID(bp) & 0x0ff0) >> 4),
		    bnx2_bus_string(bp, str), (long)pci_resource_start(pdev, 0),
		    pdev->irq, dev->dev_addr);

	return 0;

error:
	pci_iounmap(pdev, bp->regview);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
err_free:
	bnx2_free_stats_blk(dev);

Annotation

Implementation Notes