diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2007-07-02 09:37:57 +0530 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-07-02 08:24:52 -0400 |
commit | 96acb6eb8effe7c2549909e2ee49f4130f2c167d (patch) | |
tree | 5f6049fe53d9305f7edb45e4ed94aed59f66aef7 /drivers/net/netxen/netxen_nic_main.c | |
parent | d14e37e12087e98b63907518dff83a90297605d6 (diff) |
RESEND [PATCH 3/3] NetXen: Graceful teardown of interface and hardware upon module unload
Resending patch 3/3 only.
These changes allow driver close routine to be called during module unload,
to clean-up buffers and other software resources, flush queues etc. Also,
hardware is reset to pristine state.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: Milan Bag <mbag@netxen.com>
Signed-off-by: Wen Xiong <wenxiong@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 128 |
1 files changed, 86 insertions, 42 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index dba8e6b29ff3..a66ff58366cf 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -507,11 +507,14 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (val == 0x55555555) { /* This is the first boot after power up */ netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val); - if (!(val & 0x4)) { - val |= 0x4; - netxen_nic_write_w0(adapter, NETXEN_PCIE_REG(0x4), val); - netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val); - } + if (!(val & 0x4)) { + val |= 0x4; + netxen_nic_write_w0(adapter, NETXEN_PCIE_REG(0x4), val); + netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val); + if (!(val & 0x4)) + printk(KERN_ERR "%s: failed to set MSI bit in PCI-e reg\n", + netxen_nic_driver_name); + } val = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_SW_RESET)); printk(KERN_INFO"NetXen: read 0x%08x for reset reg.\n",val); @@ -523,11 +526,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = -ENODEV; goto err_out_free_dev; } - - /* clear the register for future unloads/loads */ - writel(0, NETXEN_CRB_NORMALIZE(adapter, - NETXEN_CAM_RAM(0x1fc))); } + + /* clear the register for future unloads/loads */ + writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc))); printk(KERN_INFO "State: 0x%0x\n", readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE))); @@ -545,13 +547,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) NETXEN_ROMUSB_GLB_PEGTUNE_DONE)); /* Handshake with the card before we register the devices. */ netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); - - /* leave the hw in the same state as reboot */ - writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); - netxen_pinit_from_rom(adapter, 0); - udelay(500); - netxen_load_firmware(adapter); - netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); } /* @@ -642,8 +637,8 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) struct netxen_rx_buffer *buffer; struct netxen_recv_context *recv_ctx; struct netxen_rcv_desc_ctx *rcv_desc; - int i; - int ctxid, ring; + int i, ctxid, ring; + static int init_firmware_done = 0; adapter = pci_get_drvdata(pdev); if (adapter == NULL) @@ -651,30 +646,20 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netdev = adapter->netdev; - netxen_nic_disable_int(adapter); - if (adapter->irq) - free_irq(adapter->irq, adapter); - + unregister_netdev(netdev); + if (adapter->stop_port) adapter->stop_port(adapter); - if ((adapter->flags & NETXEN_NIC_MSI_ENABLED)) - pci_disable_msi(pdev); - - if (adapter->portnum == 0) - netxen_free_adapter_offload(adapter); + netxen_nic_disable_int(adapter); - if(adapter->portnum == 0) { - /* leave the hw in the same state as reboot */ - writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); - netxen_pinit_from_rom(adapter, 0); - udelay(500); - netxen_load_firmware(adapter); - netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); - } + if (adapter->irq) + free_irq(adapter->irq, adapter); - if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { + init_firmware_done++; netxen_free_hw_resources(adapter); + } for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) { recv_ctx = &adapter->recv_ctx[ctxid]; @@ -694,17 +679,73 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) } } - unregister_netdev(netdev); + if (adapter->flags & NETXEN_NIC_MSI_ENABLED) + pci_disable_msi(pdev); vfree(adapter->cmd_buf_arr); + pci_disable_device(pdev); + + if (adapter->portnum == 0) { + if (init_firmware_done) { + dma_watchdog_shutdown_request(adapter); + msleep(100); + i = 100; + while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) { + printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n"); + msleep(100); + i--; + } + + if (i == 0) { + printk(KERN_ERR "dma_watchdog_shutdown_request failed\n"); + return; + } + + /* clear the register for future unloads/loads */ + writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc))); + printk(KERN_INFO "State: 0x%0x\n", + readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE))); + + /* leave the hw in the same state as reboot */ + writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); + if (netxen_pinit_from_rom(adapter, 0)) + return; + msleep(1); + if (netxen_load_firmware(adapter)) + return; + netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); + } + + /* clear the register for future unloads/loads */ + writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc))); + printk(KERN_INFO "State: 0x%0x\n", + readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE))); + + dma_watchdog_shutdown_request(adapter); + msleep(100); + i = 100; + while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) { + printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n"); + msleep(100); + i--; + } + + if (i) { + netxen_free_adapter_offload(adapter); + } else { + printk(KERN_ERR "failed to dma shutdown\n"); + return; + } + + } + iounmap(adapter->ahw.db_base); iounmap(adapter->ahw.pci_base0); iounmap(adapter->ahw.pci_base1); iounmap(adapter->ahw.pci_base2); pci_release_regions(pdev); - pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); free_netdev(netdev); @@ -801,7 +842,7 @@ static int netxen_nic_close(struct net_device *netdev) if (buffrag->dma) { pci_unmap_single(adapter->pdev, buffrag->dma, buffrag->length, PCI_DMA_TODEVICE); - buffrag->dma = (u64) NULL; + buffrag->dma = 0ULL; } for (j = 0; j < cmd_buff->frag_count; j++) { buffrag++; @@ -809,7 +850,7 @@ static int netxen_nic_close(struct net_device *netdev) pci_unmap_page(adapter->pdev, buffrag->dma, buffrag->length, PCI_DMA_TODEVICE); - buffrag->dma = (u64) NULL; + buffrag->dma = 0ULL; } } /* Free the skb we received in netxen_nic_xmit_frame */ @@ -819,8 +860,10 @@ static int netxen_nic_close(struct net_device *netdev) } cmd_buff++; } - FLUSH_SCHEDULED_WORK(); - del_timer_sync(&adapter->watchdog_timer); + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { + FLUSH_SCHEDULED_WORK(); + del_timer_sync(&adapter->watchdog_timer); + } return 0; } @@ -1259,6 +1302,7 @@ static void __exit netxen_exit_module(void) /* * Wait for some time to allow the dma to drain, if any. */ + msleep(100); pci_unregister_driver(&netxen_driver); destroy_workqueue(netxen_workq); } |