static int __devinit et131x_pci_setup(struct pci_dev *pdev, const struct pci_device_id *ent) { int result = -EBUSY; int pm_cap; bool pci_using_dac; struct net_device *netdev; struct et131x_adapter *adapter; /* Enable the device via the PCI subsystem */ if (pci_enable_device(pdev) != 0) { dev_err(&pdev->dev, "pci_enable_device() failed\n"); return -EIO; } /* Perform some basic PCI checks */ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { dev_err(&pdev->dev, "Can't find PCI device's base address\n"); goto err_disable; } if (pci_request_regions(pdev, DRIVER_NAME)) { dev_err(&pdev->dev, "Can't get PCI resources\n"); goto err_disable; } /* Enable PCI bus mastering */ pci_set_master(pdev); /* Query PCI for Power Mgmt Capabilities * * NOTE: Now reading PowerMgmt in another location; is this still * needed? */ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (pm_cap == 0) { dev_err(&pdev->dev, "Cannot find Power Management capabilities\n"); result = -EIO; goto err_release_res; } /* Check the DMA addressing support of this device */ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { pci_using_dac = true; result = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); if (result != 0) { dev_err(&pdev->dev, "Unable to obtain 64 bit DMA for consistent allocations\n"); goto err_release_res; } } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { pci_using_dac = false; } else { dev_err(&pdev->dev, "No usable DMA addressing method\n"); result = -EIO; goto err_release_res; } /* Allocate netdev and private adapter structs */ netdev = et131x_device_alloc(); if (netdev == NULL) { dev_err(&pdev->dev, "Couldn't alloc netdev struct\n"); result = -ENOMEM; goto err_release_res; } adapter = et131x_adapter_init(netdev, pdev); /* Initialise the PCI setup for the device */ et131x_pci_init(adapter, pdev); /* Map the bus-relative registers to system virtual memory */ adapter->regs = pci_ioremap_bar(pdev, 0); if (adapter->regs == NULL) { dev_err(&pdev->dev, "Cannot map device registers\n"); result = -ENOMEM; goto err_free_dev; } /* If Phy COMA mode was enabled when we went down, disable it here. */ writel(ET_PMCSR_INIT, &adapter->regs->global.pm_csr); /* Issue a global reset to the et1310 */ et131x_soft_reset(adapter); /* Disable all interrupts (paranoid) */ et131x_disable_interrupts(adapter); /* Allocate DMA memory */ result = et131x_adapter_memory_alloc(adapter); if (result != 0) { dev_err(&pdev->dev, "Could not alloc adapater memory (DMA)\n"); goto err_iounmap; } /* Init send data structures */ et131x_init_send(adapter); /* * Set up the task structure for the ISR's deferred handler */ INIT_WORK(&adapter->task, et131x_isr_handler); /* Copy address into the net_device struct */ memcpy(netdev->dev_addr, adapter->addr, ETH_ALEN); /* Setup et1310 as per the documentation */ et131x_adapter_setup(adapter); /* Create a timer to count errors received by the NIC */ init_timer(&adapter->ErrorTimer); adapter->ErrorTimer.expires = jiffies + TX_ERROR_PERIOD * HZ / 1000; adapter->ErrorTimer.function = et131x_error_timer_handler; adapter->ErrorTimer.data = (unsigned long)adapter; /* Initialize link state */ et131x_link_detection_handler((unsigned long)adapter); /* Initialize variable for counting how long we do not have link status */ adapter->boot_coma = 0; /* We can enable interrupts now * * NOTE - Because registration of interrupt handler is done in the * device's open(), defer enabling device interrupts to that * point */ /* Register the net_device struct with the Linux network layer */ result = register_netdev(netdev); if (result != 0) { dev_err(&pdev->dev, "register_netdev() failed\n"); goto err_mem_free; } /* Register the net_device struct with the PCI subsystem. Save a copy * of the PCI config space for this device now that the device has * been initialized, just in case it needs to be quickly restored. */ pci_set_drvdata(pdev, netdev); pci_save_state(adapter->pdev); return result; err_mem_free: et131x_adapter_memory_free(adapter); err_iounmap: iounmap(adapter->regs); err_free_dev: pci_dev_put(pdev); free_netdev(netdev); err_release_res: pci_release_regions(pdev); err_disable: pci_disable_device(pdev); return result; }
int __devinit et131x_pci_setup(struct pci_dev *pdev, const struct pci_device_id *ent) { int result = 0; int pm_cap; bool pci_using_dac; struct net_device *netdev = NULL; struct et131x_adapter *adapter = NULL; /* Enable the device via the PCI subsystem */ result = pci_enable_device(pdev); if (result != 0) { dev_err(&adapter->pdev->dev, "pci_enable_device() failed\n"); goto out; } /* Perform some basic PCI checks */ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { dev_err(&adapter->pdev->dev, "Can't find PCI device's base address\n"); result = -ENODEV; goto out; } result = pci_request_regions(pdev, DRIVER_NAME); if (result != 0) { dev_err(&adapter->pdev->dev, "Can't get PCI resources\n"); goto err_disable; } /* Enable PCI bus mastering */ pci_set_master(pdev); /* Query PCI for Power Mgmt Capabilities * * NOTE: Now reading PowerMgmt in another location; is this still * needed? */ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (pm_cap == 0) { dev_err(&adapter->pdev->dev, "Cannot find Power Management capabilities\n"); result = -EIO; goto err_release_res; } /* Check the DMA addressing support of this device */ if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { pci_using_dac = true; result = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); if (result != 0) { dev_err(&pdev->dev, "Unable to obtain 64 bit DMA for consistent allocations\n"); goto err_release_res; } } else if (!pci_set_dma_mask(pdev, 0xffffffffULL)) { pci_using_dac = false; } else { dev_err(&adapter->pdev->dev, "No usable DMA addressing method\n"); result = -EIO; goto err_release_res; } /* Allocate netdev and private adapter structs */ netdev = et131x_device_alloc(); if (netdev == NULL) { dev_err(&adapter->pdev->dev, "Couldn't alloc netdev struct\n"); result = -ENOMEM; goto err_release_res; } /* Setup the fundamental net_device and private adapter structure elements */ SET_NETDEV_DEV(netdev, &pdev->dev); /* if (pci_using_dac) { netdev->features |= NETIF_F_HIGHDMA; } */ /* * NOTE - Turn this on when we're ready to deal with SG-DMA * * NOTE: According to "Linux Device Drivers", 3rd ed, Rubini et al, * if checksumming is not performed in HW, then the kernel will not * use SG. * From pp 510-511: * * "Note that the kernel does not perform scatter/gather I/O to your * device if it does not also provide some form of checksumming as * well. The reason is that, if the kernel has to make a pass over a * fragmented ("nonlinear") packet to calculate the checksum, it * might as well copy the data and coalesce the packet at the same * time." * * This has been verified by setting the flags below and still not * receiving a scattered buffer from the network stack, so leave it * off until checksums are calculated in HW. */ /* netdev->features |= NETIF_F_SG; */ /* netdev->features |= NETIF_F_NO_CSUM; */ /* netdev->features |= NETIF_F_LLTX; */ /* Allocate private adapter struct and copy in relevant information */ adapter = netdev_priv(netdev); adapter->pdev = pci_dev_get(pdev); adapter->netdev = netdev; /* Do the same for the netdev struct */ netdev->irq = pdev->irq; netdev->base_addr = pdev->resource[0].start; /* Initialize spinlocks here */ spin_lock_init(&adapter->Lock); spin_lock_init(&adapter->TCBSendQLock); spin_lock_init(&adapter->TCBReadyQLock); spin_lock_init(&adapter->SendHWLock); spin_lock_init(&adapter->SendWaitLock); spin_lock_init(&adapter->RcvLock); spin_lock_init(&adapter->RcvPendLock); spin_lock_init(&adapter->FbrLock); spin_lock_init(&adapter->PHYLock); /* Parse configuration parameters into the private adapter struct */ et131x_config_parse(adapter); /* Find the physical adapter * * NOTE: This is the equivalent of the MpFindAdapter() routine; can we * lump it's init with the device specific init below into a * single init function? */ /* while (et131x_find_adapter(adapter, pdev) != 0); */ et131x_find_adapter(adapter, pdev); /* Map the bus-relative registers to system virtual memory */ adapter->regs = ioremap_nocache(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (adapter->regs == NULL) { dev_err(&pdev->dev, "Cannot map device registers\n"); result = -ENOMEM; goto err_free_dev; } /* Perform device-specific initialization here (See code below) */ /* If Phy COMA mode was enabled when we went down, disable it here. */ writel(ET_PMCSR_INIT, &adapter->regs->global.pm_csr); /* Issue a global reset to the et1310 */ et131x_soft_reset(adapter); /* Disable all interrupts (paranoid) */ et131x_disable_interrupts(adapter); /* Allocate DMA memory */ result = et131x_adapter_memory_alloc(adapter); if (result != 0) { dev_err(&pdev->dev, "Could not alloc adapater memory (DMA)\n"); goto err_iounmap; } /* Init send data structures */ et131x_init_send(adapter); /* Register the interrupt * * NOTE - This is being done in the open routine, where most other * Linux drivers setup IRQ handlers. Make sure device * interrupts are not turned on before the IRQ is registered!! * * What we will do here is setup the task structure for the * ISR's deferred handler */ INIT_WORK(&adapter->task, et131x_isr_handler); /* Determine MAC Address, and copy into the net_device struct */ et131x_setup_hardware_properties(adapter); memcpy(netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN); /* Setup et1310 as per the documentation */ et131x_adapter_setup(adapter); /* Create a timer to count errors received by the NIC */ init_timer(&adapter->ErrorTimer); adapter->ErrorTimer.expires = jiffies + TX_ERROR_PERIOD * HZ / 1000; adapter->ErrorTimer.function = et131x_error_timer_handler; adapter->ErrorTimer.data = (unsigned long)adapter; /* Initialize link state */ et131x_link_detection_handler((unsigned long)adapter); /* Intialize variable for counting how long we do not have link status */ adapter->PoMgmt.TransPhyComaModeOnBoot = 0; /* We can enable interrupts now * * NOTE - Because registration of interrupt handler is done in the * device's open(), defer enabling device interrupts to that * point */ /* Register the net_device struct with the Linux network layer */ result = register_netdev(netdev); if (result != 0) { dev_err(&pdev->dev, "register_netdev() failed\n"); goto err_mem_free; } /* Register the net_device struct with the PCI subsystem. Save a copy * of the PCI config space for this device now that the device has * been initialized, just in case it needs to be quickly restored. */ pci_set_drvdata(pdev, netdev); pci_save_state(adapter->pdev); out: return result; err_mem_free: et131x_adapter_memory_free(adapter); err_iounmap: iounmap(adapter->regs); err_free_dev: pci_dev_put(pdev); free_netdev(netdev); err_release_res: pci_release_regions(pdev); err_disable: pci_disable_device(pdev); goto out; }