diff options
author | Brice Goglin <brice@myri.com> | 2006-12-18 11:50:40 +0100 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-26 16:28:20 -0500 |
commit | df30a740e4647b035e44a94e6977ad42a94cb850 (patch) | |
tree | e3805821b02b350f0d25710119647ef94a5d7d4b /drivers/net | |
parent | 7adda30c82f403c948b016a40fc68a1ef427dbca (diff) | |
download | linux-df30a740e4647b035e44a94e6977ad42a94cb850.tar.bz2 |
myri10ge: move request_irq to myri10ge_open
Request IRQ in myri10ge_open() and free in close() instead of probe()
and remove() to eliminate potential race between the watchdog and the
interrupt handler. Additionaly, the interrupt handler won't get called
on shared irq anymore when the interface is down.
Signed-off-by: Brice Goglin <brice@myri.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/myri10ge/myri10ge.c | 98 |
1 files changed, 54 insertions, 44 deletions
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 28540265240c..53325ba0a6ae 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -721,12 +721,10 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0); mgp->irq_claim = (__iomem __be32 *) (mgp->sram + cmd.data0); - if (!mgp->msi_enabled) { - status |= myri10ge_send_cmd - (mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd, 0); - mgp->irq_deassert = (__iomem __be32 *) (mgp->sram + cmd.data0); + status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, + &cmd, 0); + mgp->irq_deassert = (__iomem __be32 *) (mgp->sram + cmd.data0); - } status |= myri10ge_send_cmd (mgp, MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd, 0); mgp->intr_coal_delay_ptr = (__iomem __be32 *) (mgp->sram + cmd.data0); @@ -1619,6 +1617,41 @@ static void myri10ge_free_rings(struct net_device *dev) mgp->tx.req_list = NULL; } +static int myri10ge_request_irq(struct myri10ge_priv *mgp) +{ + struct pci_dev *pdev = mgp->pdev; + int status; + + if (myri10ge_msi) { + status = pci_enable_msi(pdev); + if (status != 0) + dev_err(&pdev->dev, + "Error %d setting up MSI; falling back to xPIC\n", + status); + else + mgp->msi_enabled = 1; + } else { + mgp->msi_enabled = 0; + } + status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED, + mgp->dev->name, mgp); + if (status != 0) { + dev_err(&pdev->dev, "failed to allocate IRQ\n"); + if (mgp->msi_enabled) + pci_disable_msi(pdev); + } + return status; +} + +static void myri10ge_free_irq(struct myri10ge_priv *mgp) +{ + struct pci_dev *pdev = mgp->pdev; + + free_irq(pdev->irq, mgp); + if (mgp->msi_enabled) + pci_disable_msi(pdev); +} + static int myri10ge_open(struct net_device *dev) { struct myri10ge_priv *mgp; @@ -1634,10 +1667,13 @@ static int myri10ge_open(struct net_device *dev) status = myri10ge_reset(mgp); if (status != 0) { printk(KERN_ERR "myri10ge: %s: failed reset\n", dev->name); - mgp->running = MYRI10GE_ETH_STOPPED; - return -ENXIO; + goto abort_with_nothing; } + status = myri10ge_request_irq(mgp); + if (status != 0) + goto abort_with_nothing; + /* decide what small buffer size to use. For good TCP rx * performance, it is important to not receive 1514 byte * frames into jumbo buffers, as it confuses the socket buffer @@ -1677,7 +1713,7 @@ static int myri10ge_open(struct net_device *dev) "myri10ge: %s: failed to get ring sizes or locations\n", dev->name); mgp->running = MYRI10GE_ETH_STOPPED; - return -ENXIO; + goto abort_with_irq; } if (mgp->mtrr >= 0) { @@ -1708,7 +1744,7 @@ static int myri10ge_open(struct net_device *dev) status = myri10ge_allocate_rings(dev); if (status != 0) - goto abort_with_nothing; + goto abort_with_irq; /* now give firmware buffers sizes, and MTU */ cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN; @@ -1771,6 +1807,9 @@ static int myri10ge_open(struct net_device *dev) abort_with_rings: myri10ge_free_rings(dev); +abort_with_irq: + myri10ge_free_irq(mgp); + abort_with_nothing: mgp->running = MYRI10GE_ETH_STOPPED; return -ENOMEM; @@ -1807,7 +1846,7 @@ static int myri10ge_close(struct net_device *dev) printk(KERN_ERR "myri10ge: %s never got down irq\n", dev->name); netif_tx_disable(dev); - + myri10ge_free_irq(mgp); myri10ge_free_rings(dev); mgp->running = MYRI10GE_ETH_STOPPED; @@ -2529,7 +2568,6 @@ static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) rtnl_unlock(); } myri10ge_dummy_rdma(mgp, 0); - free_irq(pdev->irq, mgp); myri10ge_save_state(mgp); pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -2565,13 +2603,6 @@ static int myri10ge_resume(struct pci_dev *pdev) pci_set_master(pdev); - status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED, - netdev->name, mgp); - if (status != 0) { - dev_err(&pdev->dev, "failed to allocate IRQ\n"); - goto abort_with_enabled; - } - myri10ge_reset(mgp); myri10ge_dummy_rdma(mgp, 1); @@ -2581,8 +2612,11 @@ static int myri10ge_resume(struct pci_dev *pdev) if (netif_running(netdev)) { rtnl_lock(); - myri10ge_open(netdev); + status = myri10ge_open(netdev); rtnl_unlock(); + if (status != 0) + goto abort_with_enabled; + } netif_device_attach(netdev); @@ -2860,23 +2894,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto abort_with_firmware; } - if (myri10ge_msi) { - status = pci_enable_msi(pdev); - if (status != 0) - dev_err(&pdev->dev, - "Error %d setting up MSI; falling back to xPIC\n", - status); - else - mgp->msi_enabled = 1; - } - - status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED, - netdev->name, mgp); - if (status != 0) { - dev_err(&pdev->dev, "failed to allocate IRQ\n"); - goto abort_with_firmware; - } - pci_set_drvdata(pdev, mgp); if ((myri10ge_initial_mtu + ETH_HLEN) > MYRI10GE_MAX_ETHER_MTU) myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; @@ -2913,8 +2930,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_err(&pdev->dev, "register_netdev failed: %d\n", status); goto abort_with_state; } - dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n", - (mgp->msi_enabled ? "MSI" : "xPIC"), + dev_info(dev, "%d, tx bndry %d, fw %s, WC %s\n", pdev->irq, mgp->tx.boundary, mgp->fw_name, (mgp->mtrr >= 0 ? "Enabled" : "Disabled")); @@ -2922,9 +2938,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) abort_with_state: myri10ge_restore_state(mgp); - free_irq(pdev->irq, mgp); - if (mgp->msi_enabled) - pci_disable_msi(pdev); abort_with_firmware: myri10ge_dummy_rdma(mgp, 0); @@ -2975,9 +2988,6 @@ static void myri10ge_remove(struct pci_dev *pdev) flush_scheduled_work(); netdev = mgp->dev; unregister_netdev(netdev); - free_irq(pdev->irq, mgp); - if (mgp->msi_enabled) - pci_disable_msi(pdev); myri10ge_dummy_rdma(mgp, 0); |