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 | |
| 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>
| -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 | } |
