aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDhananjay Phadke <dhananjay@netxen.com>2007-07-02 00:07:57 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-02 08:24:52 -0400
commit96acb6eb8effe7c2549909e2ee49f4130f2c167d (patch)
tree5f6049fe53d9305f7edb45e4ed94aed59f66aef7 /drivers
parentd14e37e12087e98b63907518dff83a90297605d6 (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')
-rw-r--r--drivers/net/netxen/netxen_nic.h78
-rw-r--r--drivers/net/netxen/netxen_nic_hdr.h2
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c29
-rw-r--r--drivers/net/netxen/netxen_nic_init.c49
-rw-r--r--drivers/net/netxen/netxen_nic_main.c128
5 files changed, 210 insertions, 76 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 6ce93fcbed32..619503742b7d 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -952,6 +952,24 @@ struct netxen_adapter {
952 int (*stop_port) (struct netxen_adapter *); 952 int (*stop_port) (struct netxen_adapter *);
953}; /* netxen_adapter structure */ 953}; /* netxen_adapter structure */
954 954
955/*
956 * NetXen dma watchdog control structure
957 *
958 * Bit 0 : enabled => R/O: 1 watchdog active, 0 inactive
959 * Bit 1 : disable_request => 1 req disable dma watchdog
960 * Bit 2 : enable_request => 1 req enable dma watchdog
961 * Bit 3-31 : unused
962 */
963
964#define netxen_set_dma_watchdog_disable_req(config_word) \
965 _netxen_set_bits(config_word, 1, 1, 1)
966#define netxen_set_dma_watchdog_enable_req(config_word) \
967 _netxen_set_bits(config_word, 2, 1, 1)
968#define netxen_get_dma_watchdog_enabled(config_word) \
969 ((config_word) & 0x1)
970#define netxen_get_dma_watchdog_disabled(config_word) \
971 (((config_word) >> 1) & 0x1)
972
955/* Max number of xmit producer threads that can run simultaneously */ 973/* Max number of xmit producer threads that can run simultaneously */
956#define MAX_XMIT_PRODUCERS 16 974#define MAX_XMIT_PRODUCERS 16
957 975
@@ -1031,8 +1049,8 @@ int netxen_nic_erase_pxe(struct netxen_adapter *adapter);
1031/* Functions from netxen_nic_init.c */ 1049/* Functions from netxen_nic_init.c */
1032void netxen_free_adapter_offload(struct netxen_adapter *adapter); 1050void netxen_free_adapter_offload(struct netxen_adapter *adapter);
1033int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); 1051int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
1034void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); 1052int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
1035void netxen_load_firmware(struct netxen_adapter *adapter); 1053int netxen_load_firmware(struct netxen_adapter *adapter);
1036int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); 1054int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
1037int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); 1055int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
1038int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr, 1056int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
@@ -1234,6 +1252,62 @@ static inline void get_brd_name_by_type(u32 type, char *name)
1234 name = "Unknown"; 1252 name = "Unknown";
1235} 1253}
1236 1254
1255static inline int
1256dma_watchdog_shutdown_request(struct netxen_adapter *adapter)
1257{
1258 u32 ctrl;
1259
1260 /* check if already inactive */
1261 if (netxen_nic_hw_read_wx(adapter,
1262 NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
1263 printk(KERN_ERR "failed to read dma watchdog status\n");
1264
1265 if (netxen_get_dma_watchdog_enabled(ctrl) == 0)
1266 return 1;
1267
1268 /* Send the disable request */
1269 netxen_set_dma_watchdog_disable_req(ctrl);
1270 netxen_crb_writelit_adapter(adapter,
1271 NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
1272
1273 return 0;
1274}
1275
1276static inline int
1277dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter)
1278{
1279 u32 ctrl;
1280
1281 if (netxen_nic_hw_read_wx(adapter,
1282 NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
1283 printk(KERN_ERR "failed to read dma watchdog status\n");
1284
1285 return ((netxen_get_dma_watchdog_enabled(ctrl) == 0) &&
1286 (netxen_get_dma_watchdog_disabled(ctrl) == 0));
1287}
1288
1289static inline int
1290dma_watchdog_wakeup(struct netxen_adapter *adapter)
1291{
1292 u32 ctrl;
1293
1294 if (netxen_nic_hw_read_wx(adapter,
1295 NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
1296 printk(KERN_ERR "failed to read dma watchdog status\n");
1297
1298 if (netxen_get_dma_watchdog_enabled(ctrl))
1299 return 1;
1300
1301 /* send the wakeup request */
1302 netxen_set_dma_watchdog_enable_req(ctrl);
1303
1304 netxen_crb_writelit_adapter(adapter,
1305 NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
1306
1307 return 0;
1308}
1309
1310
1237int netxen_is_flash_supported(struct netxen_adapter *adapter); 1311int netxen_is_flash_supported(struct netxen_adapter *adapter);
1238int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]); 1312int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]);
1239extern void netxen_change_ringparam(struct netxen_adapter *adapter); 1313extern void netxen_change_ringparam(struct netxen_adapter *adapter);
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 608e37b349b4..3276866b17e2 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -687,4 +687,6 @@ enum {
687 687
688#define PCIE_MAX_MASTER_SPLIT (0x14048) 688#define PCIE_MAX_MASTER_SPLIT (0x14048)
689 689
690#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14)
691
690#endif /* __NETXEN_NIC_HDR_H_ */ 692#endif /* __NETXEN_NIC_HDR_H_ */
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 2b40a5a19c47..aac15421bd1e 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -377,7 +377,7 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
377 recv_crb_registers[ctx]. 377 recv_crb_registers[ctx].
378 crb_rcvpeg_state)); 378 crb_rcvpeg_state));
379 while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) { 379 while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {
380 udelay(100); 380 msleep(1);
381 /* Window 1 call */ 381 /* Window 1 call */
382 state = readl(NETXEN_CRB_NORMALIZE(adapter, 382 state = readl(NETXEN_CRB_NORMALIZE(adapter,
383 recv_crb_registers 383 recv_crb_registers
@@ -394,7 +394,7 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
394 } 394 }
395 adapter->intr_scheme = readl( 395 adapter->intr_scheme = readl(
396 NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW)); 396 NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW));
397 printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netdev->name, 397 printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netxen_nic_driver_name,
398 adapter->intr_scheme); 398 adapter->intr_scheme);
399 DPRINTK(INFO, "Receive Peg ready too. starting stuff\n"); 399 DPRINTK(INFO, "Receive Peg ready too. starting stuff\n");
400 400
@@ -701,7 +701,7 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
701 adapter->curr_window = 0; 701 adapter->curr_window = 0;
702} 702}
703 703
704void netxen_load_firmware(struct netxen_adapter *adapter) 704int netxen_load_firmware(struct netxen_adapter *adapter)
705{ 705{
706 int i; 706 int i;
707 u32 data, size = 0; 707 u32 data, size = 0;
@@ -713,15 +713,24 @@ void netxen_load_firmware(struct netxen_adapter *adapter)
713 writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST)); 713 writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
714 714
715 for (i = 0; i < size; i++) { 715 for (i = 0; i < size; i++) {
716 if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) { 716 int retries = 10;
717 DPRINTK(ERR, 717 if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0)
718 "Error in netxen_rom_fast_read(). Will skip" 718 return -EIO;
719 "loading flash image\n"); 719
720 return;
721 }
722 off = netxen_nic_pci_set_window(adapter, memaddr); 720 off = netxen_nic_pci_set_window(adapter, memaddr);
723 addr = pci_base_offset(adapter, off); 721 addr = pci_base_offset(adapter, off);
724 writel(data, addr); 722 writel(data, addr);
723 do {
724 if (readl(addr) == data)
725 break;
726 msleep(100);
727 writel(data, addr);
728 } while (--retries);
729 if (!retries) {
730 printk(KERN_ERR "%s: firmware load aborted, write failed at 0x%x\n",
731 netxen_nic_driver_name, memaddr);
732 return -EIO;
733 }
725 flashaddr += 4; 734 flashaddr += 4;
726 memaddr += 4; 735 memaddr += 4;
727 } 736 }
@@ -731,7 +740,7 @@ void netxen_load_firmware(struct netxen_adapter *adapter)
731 NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL)); 740 NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
732 writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST)); 741 writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
733 742
734 udelay(100); 743 return 0;
735} 744}
736 745
737int 746int
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 15f6dc5a1cf7..1811bcb8c380 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -407,10 +407,7 @@ static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
407static inline int 407static inline int
408do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) 408do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
409{ 409{
410 if (jiffies > (last_schedule_time + (8 * HZ))) { 410 cond_resched();
411 last_schedule_time = jiffies;
412 schedule();
413 }
414 411
415 netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); 412 netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
416 netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); 413 netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
@@ -856,10 +853,10 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
856 netxen_nic_pci_change_crbwindow(adapter, 1); 853 netxen_nic_pci_change_crbwindow(adapter, 1);
857 } 854 }
858 if (init_delay == 1) { 855 if (init_delay == 1) {
859 ssleep(1); 856 msleep(2000);
860 init_delay = 0; 857 init_delay = 0;
861 } 858 }
862 msleep(1); 859 msleep(20);
863 } 860 }
864 kfree(buf); 861 kfree(buf);
865 862
@@ -935,10 +932,6 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
935void netxen_free_adapter_offload(struct netxen_adapter *adapter) 932void netxen_free_adapter_offload(struct netxen_adapter *adapter)
936{ 933{
937 if (adapter->dummy_dma.addr) { 934 if (adapter->dummy_dma.addr) {
938 writel(0, NETXEN_CRB_NORMALIZE(adapter,
939 CRB_HOST_DUMMY_BUF_ADDR_HI));
940 writel(0, NETXEN_CRB_NORMALIZE(adapter,
941 CRB_HOST_DUMMY_BUF_ADDR_LO));
942 pci_free_consistent(adapter->ahw.pdev, 935 pci_free_consistent(adapter->ahw.pdev,
943 NETXEN_HOST_DUMMY_DMA_SIZE, 936 NETXEN_HOST_DUMMY_DMA_SIZE,
944 adapter->dummy_dma.addr, 937 adapter->dummy_dma.addr,
@@ -947,25 +940,32 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter)
947 } 940 }
948} 941}
949 942
950void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) 943int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
951{ 944{
952 u32 val = 0; 945 u32 val = 0;
953 int loops = 0; 946 int retries = 30;
954 947
955 if (!pegtune_val) { 948 if (!pegtune_val) {
956 val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); 949 do {
957 while (val != PHAN_INITIALIZE_COMPLETE && 950 val = readl(NETXEN_CRB_NORMALIZE
958 val != PHAN_INITIALIZE_ACK && loops < 200000) {
959 udelay(100);
960 schedule();
961 val =
962 readl(NETXEN_CRB_NORMALIZE
963 (adapter, CRB_CMDPEG_STATE)); 951 (adapter, CRB_CMDPEG_STATE));
964 loops++; 952 pegtune_val = readl(NETXEN_CRB_NORMALIZE
953 (adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
954
955 if (val == PHAN_INITIALIZE_COMPLETE ||
956 val == PHAN_INITIALIZE_ACK)
957 return 0;
958
959 msleep(1000);
960 } while (--retries);
961 if (!retries) {
962 printk(KERN_WARNING "netxen_phantom_init: init failed, "
963 "pegtune_val=%x\n", pegtune_val);
964 return -1;
965 } 965 }
966 if (val != PHAN_INITIALIZE_COMPLETE)
967 printk("WARNING: Initial boot wait loop failed...\n");
968 } 966 }
967
968 return 0;
969} 969}
970 970
971int netxen_nic_rx_has_work(struct netxen_adapter *adapter) 971int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
@@ -1122,6 +1122,7 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
1122 adapter->stats.csummed++; 1122 adapter->stats.csummed++;
1123 skb->ip_summed = CHECKSUM_UNNECESSARY; 1123 skb->ip_summed = CHECKSUM_UNNECESSARY;
1124 } 1124 }
1125 skb->dev = netdev;
1125 if (desc_ctx == RCV_DESC_LRO_CTXID) { 1126 if (desc_ctx == RCV_DESC_LRO_CTXID) {
1126 /* True length was only available on the last pkt */ 1127 /* True length was only available on the last pkt */
1127 skb_put(skb, buffer->lro_length); 1128 skb_put(skb, buffer->lro_length);
@@ -1226,6 +1227,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
1226 NETXEN_CRB_NORMALIZE(adapter, 1227 NETXEN_CRB_NORMALIZE(adapter,
1227 recv_crb_registers[adapter->portnum]. 1228 recv_crb_registers[adapter->portnum].
1228 crb_rcv_status_consumer)); 1229 crb_rcv_status_consumer));
1230 wmb();
1229 } 1231 }
1230 1232
1231 return count; 1233 return count;
@@ -1278,11 +1280,13 @@ int netxen_process_cmd_ring(unsigned long data)
1278 if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) { 1280 if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) {
1279 pci_unmap_single(pdev, frag->dma, frag->length, 1281 pci_unmap_single(pdev, frag->dma, frag->length,
1280 PCI_DMA_TODEVICE); 1282 PCI_DMA_TODEVICE);
1283 frag->dma = 0ULL;
1281 for (i = 1; i < buffer->frag_count; i++) { 1284 for (i = 1; i < buffer->frag_count; i++) {
1282 DPRINTK(INFO, "getting fragment no %d\n", i); 1285 DPRINTK(INFO, "getting fragment no %d\n", i);
1283 frag++; /* Get the next frag */ 1286 frag++; /* Get the next frag */
1284 pci_unmap_page(pdev, frag->dma, frag->length, 1287 pci_unmap_page(pdev, frag->dma, frag->length,
1285 PCI_DMA_TODEVICE); 1288 PCI_DMA_TODEVICE);
1289 frag->dma = 0ULL;
1286 } 1290 }
1287 1291
1288 adapter->stats.skbfreed++; 1292 adapter->stats.skbfreed++;
@@ -1448,6 +1452,7 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
1448 writel(msg, 1452 writel(msg,
1449 DB_NORMALIZE(adapter, 1453 DB_NORMALIZE(adapter,
1450 NETXEN_RCV_PRODUCER_OFFSET)); 1454 NETXEN_RCV_PRODUCER_OFFSET));
1455 wmb();
1451 } 1456 }
1452 } 1457 }
1453} 1458}
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)
507 if (val == 0x55555555) { 507 if (val == 0x55555555) {
508 /* This is the first boot after power up */ 508 /* This is the first boot after power up */
509 netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val); 509 netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
510 if (!(val & 0x4)) { 510 if (!(val & 0x4)) {
511 val |= 0x4; 511 val |= 0x4;
512 netxen_nic_write_w0(adapter, NETXEN_PCIE_REG(0x4), val); 512 netxen_nic_write_w0(adapter, NETXEN_PCIE_REG(0x4), val);
513 netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val); 513 netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
514 } 514 if (!(val & 0x4))
515 printk(KERN_ERR "%s: failed to set MSI bit in PCI-e reg\n",
516 netxen_nic_driver_name);
517 }
515 val = readl(NETXEN_CRB_NORMALIZE(adapter, 518 val = readl(NETXEN_CRB_NORMALIZE(adapter,
516 NETXEN_ROMUSB_GLB_SW_RESET)); 519 NETXEN_ROMUSB_GLB_SW_RESET));
517 printk(KERN_INFO"NetXen: read 0x%08x for reset reg.\n",val); 520 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)
523 err = -ENODEV; 526 err = -ENODEV;
524 goto err_out_free_dev; 527 goto err_out_free_dev;
525 } 528 }
526
527 /* clear the register for future unloads/loads */
528 writel(0, NETXEN_CRB_NORMALIZE(adapter,
529 NETXEN_CAM_RAM(0x1fc)));
530 } 529 }
530
531 /* clear the register for future unloads/loads */
532 writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
531 printk(KERN_INFO "State: 0x%0x\n", 533 printk(KERN_INFO "State: 0x%0x\n",
532 readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE))); 534 readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
533 535
@@ -545,13 +547,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
545 NETXEN_ROMUSB_GLB_PEGTUNE_DONE)); 547 NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
546 /* Handshake with the card before we register the devices. */ 548 /* Handshake with the card before we register the devices. */
547 netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); 549 netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
548
549 /* leave the hw in the same state as reboot */
550 writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
551 netxen_pinit_from_rom(adapter, 0);
552 udelay(500);
553 netxen_load_firmware(adapter);
554 netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
555 } 550 }
556 551
557 /* 552 /*
@@ -642,8 +637,8 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
642 struct netxen_rx_buffer *buffer; 637 struct netxen_rx_buffer *buffer;
643 struct netxen_recv_context *recv_ctx; 638 struct netxen_recv_context *recv_ctx;
644 struct netxen_rcv_desc_ctx *rcv_desc; 639 struct netxen_rcv_desc_ctx *rcv_desc;
645 int i; 640 int i, ctxid, ring;
646 int ctxid, ring; 641 static int init_firmware_done = 0;
647 642
648 adapter = pci_get_drvdata(pdev); 643 adapter = pci_get_drvdata(pdev);
649 if (adapter == NULL) 644 if (adapter == NULL)
@@ -651,30 +646,20 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
651 646
652 netdev = adapter->netdev; 647 netdev = adapter->netdev;
653 648
654 netxen_nic_disable_int(adapter); 649 unregister_netdev(netdev);
655 if (adapter->irq) 650
656 free_irq(adapter->irq, adapter);
657
658 if (adapter->stop_port) 651 if (adapter->stop_port)
659 adapter->stop_port(adapter); 652 adapter->stop_port(adapter);
660 653
661 if ((adapter->flags & NETXEN_NIC_MSI_ENABLED)) 654 netxen_nic_disable_int(adapter);
662 pci_disable_msi(pdev);
663
664 if (adapter->portnum == 0)
665 netxen_free_adapter_offload(adapter);
666 655
667 if(adapter->portnum == 0) { 656 if (adapter->irq)
668 /* leave the hw in the same state as reboot */ 657 free_irq(adapter->irq, adapter);
669 writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
670 netxen_pinit_from_rom(adapter, 0);
671 udelay(500);
672 netxen_load_firmware(adapter);
673 netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
674 }
675 658
676 if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) 659 if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
660 init_firmware_done++;
677 netxen_free_hw_resources(adapter); 661 netxen_free_hw_resources(adapter);
662 }
678 663
679 for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) { 664 for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
680 recv_ctx = &adapter->recv_ctx[ctxid]; 665 recv_ctx = &adapter->recv_ctx[ctxid];
@@ -694,17 +679,73 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
694 } 679 }
695 } 680 }
696 681
697 unregister_netdev(netdev); 682 if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
683 pci_disable_msi(pdev);
698 684
699 vfree(adapter->cmd_buf_arr); 685 vfree(adapter->cmd_buf_arr);
700 686
687 pci_disable_device(pdev);
688
689 if (adapter->portnum == 0) {
690 if (init_firmware_done) {
691 dma_watchdog_shutdown_request(adapter);
692 msleep(100);
693 i = 100;
694 while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) {
695 printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n");
696 msleep(100);
697 i--;
698 }
699
700 if (i == 0) {
701 printk(KERN_ERR "dma_watchdog_shutdown_request failed\n");
702 return;
703 }
704
705 /* clear the register for future unloads/loads */
706 writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
707 printk(KERN_INFO "State: 0x%0x\n",
708 readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
709
710 /* leave the hw in the same state as reboot */
711 writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
712 if (netxen_pinit_from_rom(adapter, 0))
713 return;
714 msleep(1);
715 if (netxen_load_firmware(adapter))
716 return;
717 netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
718 }
719
720 /* clear the register for future unloads/loads */
721 writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
722 printk(KERN_INFO "State: 0x%0x\n",
723 readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
724
725 dma_watchdog_shutdown_request(adapter);
726 msleep(100);
727 i = 100;
728 while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) {
729 printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n");
730 msleep(100);
731 i--;
732 }
733
734 if (i) {
735 netxen_free_adapter_offload(adapter);
736 } else {
737 printk(KERN_ERR "failed to dma shutdown\n");
738 return;
739 }
740
741 }
742
701 iounmap(adapter->ahw.db_base); 743 iounmap(adapter->ahw.db_base);
702 iounmap(adapter->ahw.pci_base0); 744 iounmap(adapter->ahw.pci_base0);
703 iounmap(adapter->ahw.pci_base1); 745 iounmap(adapter->ahw.pci_base1);
704 iounmap(adapter->ahw.pci_base2); 746 iounmap(adapter->ahw.pci_base2);
705 747
706 pci_release_regions(pdev); 748 pci_release_regions(pdev);
707 pci_disable_device(pdev);
708 pci_set_drvdata(pdev, NULL); 749 pci_set_drvdata(pdev, NULL);
709 750
710 free_netdev(netdev); 751 free_netdev(netdev);
@@ -801,7 +842,7 @@ static int netxen_nic_close(struct net_device *netdev)
801 if (buffrag->dma) { 842 if (buffrag->dma) {
802 pci_unmap_single(adapter->pdev, buffrag->dma, 843 pci_unmap_single(adapter->pdev, buffrag->dma,
803 buffrag->length, PCI_DMA_TODEVICE); 844 buffrag->length, PCI_DMA_TODEVICE);
804 buffrag->dma = (u64) NULL; 845 buffrag->dma = 0ULL;
805 } 846 }
806 for (j = 0; j < cmd_buff->frag_count; j++) { 847 for (j = 0; j < cmd_buff->frag_count; j++) {
807 buffrag++; 848 buffrag++;
@@ -809,7 +850,7 @@ static int netxen_nic_close(struct net_device *netdev)
809 pci_unmap_page(adapter->pdev, buffrag->dma, 850 pci_unmap_page(adapter->pdev, buffrag->dma,
810 buffrag->length, 851 buffrag->length,
811 PCI_DMA_TODEVICE); 852 PCI_DMA_TODEVICE);
812 buffrag->dma = (u64) NULL; 853 buffrag->dma = 0ULL;
813 } 854 }
814 } 855 }
815 /* Free the skb we received in netxen_nic_xmit_frame */ 856 /* Free the skb we received in netxen_nic_xmit_frame */
@@ -819,8 +860,10 @@ static int netxen_nic_close(struct net_device *netdev)
819 } 860 }
820 cmd_buff++; 861 cmd_buff++;
821 } 862 }
822 FLUSH_SCHEDULED_WORK(); 863 if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
823 del_timer_sync(&adapter->watchdog_timer); 864 FLUSH_SCHEDULED_WORK();
865 del_timer_sync(&adapter->watchdog_timer);
866 }
824 867
825 return 0; 868 return 0;
826} 869}
@@ -1259,6 +1302,7 @@ static void __exit netxen_exit_module(void)
1259 /* 1302 /*
1260 * Wait for some time to allow the dma to drain, if any. 1303 * Wait for some time to allow the dma to drain, if any.
1261 */ 1304 */
1305 msleep(100);
1262 pci_unregister_driver(&netxen_driver); 1306 pci_unregister_driver(&netxen_driver);
1263 destroy_workqueue(netxen_workq); 1307 destroy_workqueue(netxen_workq);
1264} 1308}