drivers/net/ethernet/myricom/myri10ge/myri10ge.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/myricom/myri10ge/myri10ge.c
Extension
.c
Size
113515 bytes
Lines
4072
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 myri10ge_netdev_ops = {
	.ndo_open		= myri10ge_open,
	.ndo_stop		= myri10ge_close,
	.ndo_start_xmit		= myri10ge_xmit,
	.ndo_get_stats64	= myri10ge_get_stats,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_change_mtu		= myri10ge_change_mtu,
	.ndo_set_rx_mode	= myri10ge_set_multicast_list,
	.ndo_set_mac_address	= myri10ge_set_mac_address,
};

static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct net_device *netdev;
	struct myri10ge_priv *mgp;
	struct device *dev = &pdev->dev;
	int status = -ENXIO;
	unsigned hdr_offset, ss_offset;
	static int board_number;

	netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES);
	if (netdev == NULL)
		return -ENOMEM;

	SET_NETDEV_DEV(netdev, &pdev->dev);

	mgp = netdev_priv(netdev);
	mgp->dev = netdev;
	mgp->pdev = pdev;
	mgp->pause = myri10ge_flow_control;
	mgp->intr_coal_delay = myri10ge_intr_coal_delay;
	mgp->msg_enable = netif_msg_init(myri10ge_debug, MYRI10GE_MSG_DEFAULT);
	mgp->board_number = board_number;
	init_waitqueue_head(&mgp->down_wq);

	if (pci_enable_device(pdev)) {
		dev_err(&pdev->dev, "pci_enable_device call failed\n");
		status = -ENODEV;
		goto abort_with_netdev;
	}

	/* Find the vendor-specific cap so we can check
	 * the reboot register later on */
	mgp->vendor_specific_offset
	    = pci_find_capability(pdev, PCI_CAP_ID_VNDR);

	/* Set our max read request to 4KB */
	status = pcie_set_readrq(pdev, 4096);
	if (status != 0) {
		dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n",
			status);
		goto abort_with_enabled;
	}

	myri10ge_mask_surprise_down(pdev);
	pci_set_master(pdev);
	status = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
	if (status != 0) {
		dev_err(&pdev->dev, "Error %d setting DMA mask\n", status);
		goto abort_with_enabled;
	}
	mgp->cmd = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->cmd),
				      &mgp->cmd_bus, GFP_KERNEL);
	if (!mgp->cmd) {
		status = -ENOMEM;
		goto abort_with_enabled;
	}

	mgp->board_span = pci_resource_len(pdev, 0);
	mgp->iomem_base = pci_resource_start(pdev, 0);
	mgp->wc_cookie = arch_phys_wc_add(mgp->iomem_base, mgp->board_span);
	mgp->sram = ioremap_wc(mgp->iomem_base, mgp->board_span);
	if (mgp->sram == NULL) {
		dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n",
			mgp->board_span, mgp->iomem_base);
		status = -ENXIO;
		goto abort_with_mtrr;
	}
	hdr_offset =
	    swab32(readl(mgp->sram + MCP_HEADER_PTR_OFFSET)) & 0xffffc;
	ss_offset = hdr_offset + offsetof(struct mcp_gen_header, string_specs);
	mgp->sram_size = swab32(readl(mgp->sram + ss_offset));
	if (mgp->sram_size > mgp->board_span ||
	    mgp->sram_size <= MYRI10GE_FW_OFFSET) {
		dev_err(&pdev->dev,
			"invalid sram_size %dB or board span %ldB\n",
			mgp->sram_size, mgp->board_span);
		status = -EINVAL;
		goto abort_with_ioremap;
	}

Annotation

Implementation Notes