diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2007-07-02 00:07:57 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-07-02 08:24:52 -0400 |
commit | 96acb6eb8effe7c2549909e2ee49f4130f2c167d (patch) | |
tree | 5f6049fe53d9305f7edb45e4ed94aed59f66aef7 /drivers/net/netxen | |
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')
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 78 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hdr.h | 2 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 29 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 49 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 128 |
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 */ |
1032 | void netxen_free_adapter_offload(struct netxen_adapter *adapter); | 1050 | void netxen_free_adapter_offload(struct netxen_adapter *adapter); |
1033 | int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); | 1051 | int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); |
1034 | void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); | 1052 | int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); |
1035 | void netxen_load_firmware(struct netxen_adapter *adapter); | 1053 | int netxen_load_firmware(struct netxen_adapter *adapter); |
1036 | int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); | 1054 | int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); |
1037 | int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); | 1055 | int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); |
1038 | int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr, | 1056 | int 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 | ||
1255 | static inline int | ||
1256 | dma_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 | |||
1276 | static inline int | ||
1277 | dma_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 | |||
1289 | static inline int | ||
1290 | dma_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 | |||
1237 | int netxen_is_flash_supported(struct netxen_adapter *adapter); | 1311 | int netxen_is_flash_supported(struct netxen_adapter *adapter); |
1238 | int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]); | 1312 | int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]); |
1239 | extern void netxen_change_ringparam(struct netxen_adapter *adapter); | 1313 | extern 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 | ||
704 | void netxen_load_firmware(struct netxen_adapter *adapter) | 704 | int 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 | ||
737 | int | 746 | int |
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, | |||
407 | static inline int | 407 | static inline int |
408 | do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) | 408 | do_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) | |||
935 | void netxen_free_adapter_offload(struct netxen_adapter *adapter) | 932 | void 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 | ||
950 | void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) | 943 | int 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 | ||
971 | int netxen_nic_rx_has_work(struct netxen_adapter *adapter) | 971 | int 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 | } |