diff options
Diffstat (limited to 'drivers/net/netxen')
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 180 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hdr.h | 2 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 33 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 51 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 177 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_phan_reg.h | 14 |
6 files changed, 341 insertions, 116 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 91f25e0a638e..619503742b7d 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -937,6 +937,7 @@ struct netxen_adapter { struct netxen_ring_ctx *ctx_desc; struct pci_dev *ctx_desc_pdev; dma_addr_t ctx_desc_phys_addr; + int intr_scheme; int (*enable_phy_interrupts) (struct netxen_adapter *); int (*disable_phy_interrupts) (struct netxen_adapter *); void (*handle_phy_intr) (struct netxen_adapter *); @@ -951,6 +952,24 @@ struct netxen_adapter { int (*stop_port) (struct netxen_adapter *); }; /* netxen_adapter structure */ +/* + * NetXen dma watchdog control structure + * + * Bit 0 : enabled => R/O: 1 watchdog active, 0 inactive + * Bit 1 : disable_request => 1 req disable dma watchdog + * Bit 2 : enable_request => 1 req enable dma watchdog + * Bit 3-31 : unused + */ + +#define netxen_set_dma_watchdog_disable_req(config_word) \ + _netxen_set_bits(config_word, 1, 1, 1) +#define netxen_set_dma_watchdog_enable_req(config_word) \ + _netxen_set_bits(config_word, 2, 1, 1) +#define netxen_get_dma_watchdog_enabled(config_word) \ + ((config_word) & 0x1) +#define netxen_get_dma_watchdog_disabled(config_word) \ + (((config_word) >> 1) & 0x1) + /* Max number of xmit producer threads that can run simultaneously */ #define MAX_XMIT_PRODUCERS 16 @@ -1030,8 +1049,8 @@ int netxen_nic_erase_pxe(struct netxen_adapter *adapter); /* Functions from netxen_nic_init.c */ void netxen_free_adapter_offload(struct netxen_adapter *adapter); int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); -void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); -void netxen_load_firmware(struct netxen_adapter *adapter); +int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); +int netxen_load_firmware(struct netxen_adapter *adapter); int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr, @@ -1080,37 +1099,106 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); static inline void netxen_nic_disable_int(struct netxen_adapter *adapter) { - /* - * ISR_INT_MASK: Can be read from window 0 or 1. - */ - writel(0x7ff, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); + uint32_t mask = 0x7ff; + int retries = 32; + + DPRINTK(1, INFO, "Entered ISR Disable \n"); + + switch (adapter->portnum) { + case 0: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); + break; + case 1: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); + break; + case 2: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); + break; + case 3: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); + break; + } + if (adapter->intr_scheme != -1 && + adapter->intr_scheme != INTR_SCHEME_PERPORT) { + writel(mask, + (void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK))); + } + + /* Window = 0 or 1 */ + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + do { + writel(0xffffffff, (void *) + (PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS))); + mask = readl((void *) + (pci_base_offset(adapter, ISR_INT_VECTOR))); + if (!(mask & 0x80)) + break; + udelay(10); + } while (--retries); + + if (!retries) { + printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n", + netxen_nic_driver_name); + } + } + + DPRINTK(1, INFO, "Done with Disable Int\n"); + + return; } static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) { u32 mask; - switch (adapter->ahw.board_type) { - case NETXEN_NIC_GBE: - mask = 0x77b; + DPRINTK(1, INFO, "Entered ISR Enable \n"); + + if (adapter->intr_scheme != -1 && + adapter->intr_scheme != INTR_SCHEME_PERPORT) { + switch (adapter->ahw.board_type) { + case NETXEN_NIC_GBE: + mask = 0x77b; + break; + case NETXEN_NIC_XGBE: + mask = 0x77f; + break; + default: + mask = 0x7ff; + break; + } + + writel(mask, + (void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK))); + } + switch (adapter->portnum) { + case 0: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); + break; + case 1: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); break; - case NETXEN_NIC_XGBE: - mask = 0x77f; + case 2: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); break; - default: - mask = 0x7ff; + case 3: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); break; } - writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); - if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { mask = 0xbff; - writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); - writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, - ISR_INT_TARGET_MASK)); + if (adapter->intr_scheme != -1 && + adapter->intr_scheme != INTR_SCHEME_PERPORT) { + writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); + } + writel(mask, + (void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK))); } + + DPRINTK(1, INFO, "Done with enable Int\n"); + + return; } /* @@ -1164,6 +1252,62 @@ static inline void get_brd_name_by_type(u32 type, char *name) name = "Unknown"; } +static inline int +dma_watchdog_shutdown_request(struct netxen_adapter *adapter) +{ + u32 ctrl; + + /* check if already inactive */ + if (netxen_nic_hw_read_wx(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) + printk(KERN_ERR "failed to read dma watchdog status\n"); + + if (netxen_get_dma_watchdog_enabled(ctrl) == 0) + return 1; + + /* Send the disable request */ + netxen_set_dma_watchdog_disable_req(ctrl); + netxen_crb_writelit_adapter(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); + + return 0; +} + +static inline int +dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter) +{ + u32 ctrl; + + if (netxen_nic_hw_read_wx(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) + printk(KERN_ERR "failed to read dma watchdog status\n"); + + return ((netxen_get_dma_watchdog_enabled(ctrl) == 0) && + (netxen_get_dma_watchdog_disabled(ctrl) == 0)); +} + +static inline int +dma_watchdog_wakeup(struct netxen_adapter *adapter) +{ + u32 ctrl; + + if (netxen_nic_hw_read_wx(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) + printk(KERN_ERR "failed to read dma watchdog status\n"); + + if (netxen_get_dma_watchdog_enabled(ctrl)) + return 1; + + /* send the wakeup request */ + netxen_set_dma_watchdog_enable_req(ctrl); + + netxen_crb_writelit_adapter(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); + + return 0; +} + + int netxen_is_flash_supported(struct netxen_adapter *adapter); int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]); 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 { #define PCIE_MAX_MASTER_SPLIT (0x14048) +#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) + #endif /* __NETXEN_NIC_HDR_H_ */ diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index c012764d1145..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) recv_crb_registers[ctx]. crb_rcvpeg_state)); while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) { - udelay(100); + msleep(1); /* Window 1 call */ state = readl(NETXEN_CRB_NORMALIZE(adapter, recv_crb_registers @@ -392,7 +392,11 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) return err; } } - DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n"); + adapter->intr_scheme = readl( + NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW)); + printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netxen_nic_driver_name, + adapter->intr_scheme); + DPRINTK(INFO, "Receive Peg ready too. starting stuff\n"); addr = netxen_alloc(adapter->ahw.pdev, sizeof(struct netxen_ring_ctx) + @@ -697,7 +701,7 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw) adapter->curr_window = 0; } -void netxen_load_firmware(struct netxen_adapter *adapter) +int netxen_load_firmware(struct netxen_adapter *adapter) { int i; u32 data, size = 0; @@ -709,15 +713,24 @@ void netxen_load_firmware(struct netxen_adapter *adapter) writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST)); for (i = 0; i < size; i++) { - if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) { - DPRINTK(ERR, - "Error in netxen_rom_fast_read(). Will skip" - "loading flash image\n"); - return; - } + int retries = 10; + if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) + return -EIO; + off = netxen_nic_pci_set_window(adapter, memaddr); addr = pci_base_offset(adapter, off); writel(data, addr); + do { + if (readl(addr) == data) + break; + msleep(100); + writel(data, addr); + } while (--retries); + if (!retries) { + printk(KERN_ERR "%s: firmware load aborted, write failed at 0x%x\n", + netxen_nic_driver_name, memaddr); + return -EIO; + } flashaddr += 4; memaddr += 4; } @@ -727,7 +740,7 @@ void netxen_load_firmware(struct netxen_adapter *adapter) NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL)); writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST)); - udelay(100); + return 0; } int diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index bb23f4c360db..1811bcb8c380 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -139,6 +139,8 @@ int netxen_init_firmware(struct netxen_adapter *adapter) return err; } /* Window 1 call */ + writel(INTR_SCHEME_PERPORT, + NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST)); writel(MPORT_MULTI_FUNCTION_MODE, NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE)); writel(PHAN_INITIALIZE_ACK, @@ -405,10 +407,7 @@ static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr, static inline int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { - if (jiffies > (last_schedule_time + (8 * HZ))) { - last_schedule_time = jiffies; - schedule(); - } + cond_resched(); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); @@ -854,10 +853,10 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) netxen_nic_pci_change_crbwindow(adapter, 1); } if (init_delay == 1) { - ssleep(1); + msleep(2000); init_delay = 0; } - msleep(1); + msleep(20); } kfree(buf); @@ -933,10 +932,6 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) void netxen_free_adapter_offload(struct netxen_adapter *adapter) { if (adapter->dummy_dma.addr) { - writel(0, NETXEN_CRB_NORMALIZE(adapter, - CRB_HOST_DUMMY_BUF_ADDR_HI)); - writel(0, NETXEN_CRB_NORMALIZE(adapter, - CRB_HOST_DUMMY_BUF_ADDR_LO)); pci_free_consistent(adapter->ahw.pdev, NETXEN_HOST_DUMMY_DMA_SIZE, adapter->dummy_dma.addr, @@ -945,25 +940,32 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter) } } -void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) +int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) { u32 val = 0; - int loops = 0; + int retries = 30; if (!pegtune_val) { - val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); - while (val != PHAN_INITIALIZE_COMPLETE && - val != PHAN_INITIALIZE_ACK && loops < 200000) { - udelay(100); - schedule(); - val = - readl(NETXEN_CRB_NORMALIZE + do { + val = readl(NETXEN_CRB_NORMALIZE (adapter, CRB_CMDPEG_STATE)); - loops++; + pegtune_val = readl(NETXEN_CRB_NORMALIZE + (adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE)); + + if (val == PHAN_INITIALIZE_COMPLETE || + val == PHAN_INITIALIZE_ACK) + return 0; + + msleep(1000); + } while (--retries); + if (!retries) { + printk(KERN_WARNING "netxen_phantom_init: init failed, " + "pegtune_val=%x\n", pegtune_val); + return -1; } - if (val != PHAN_INITIALIZE_COMPLETE) - printk("WARNING: Initial boot wait loop failed...\n"); } + + return 0; } int netxen_nic_rx_has_work(struct netxen_adapter *adapter) @@ -1120,6 +1122,7 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, adapter->stats.csummed++; skb->ip_summed = CHECKSUM_UNNECESSARY; } + skb->dev = netdev; if (desc_ctx == RCV_DESC_LRO_CTXID) { /* True length was only available on the last pkt */ skb_put(skb, buffer->lro_length); @@ -1224,6 +1227,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) NETXEN_CRB_NORMALIZE(adapter, recv_crb_registers[adapter->portnum]. crb_rcv_status_consumer)); + wmb(); } return count; @@ -1276,11 +1280,13 @@ int netxen_process_cmd_ring(unsigned long data) if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) { pci_unmap_single(pdev, frag->dma, frag->length, PCI_DMA_TODEVICE); + frag->dma = 0ULL; for (i = 1; i < buffer->frag_count; i++) { DPRINTK(INFO, "getting fragment no %d\n", i); frag++; /* Get the next frag */ pci_unmap_page(pdev, frag->dma, frag->length, PCI_DMA_TODEVICE); + frag->dma = 0ULL; } adapter->stats.skbfreed++; @@ -1446,6 +1452,7 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) writel(msg, DB_NORMALIZE(adapter, NETXEN_RCV_PRODUCER_OFFSET)); + wmb(); } } } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 6167b58d2731..a66ff58366cf 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -308,7 +308,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->netdev = netdev; adapter->pdev = pdev; + + /* this will be read from FW later */ + adapter->intr_scheme = -1; + + /* This will be reset for mezz cards */ adapter->portnum = pci_func_id; + adapter->status &= ~NETXEN_NETDEV_STATUS; netdev->open = netxen_nic_open; netdev->stop = netxen_nic_close; @@ -336,11 +342,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; - if (pci_enable_msi(pdev)) { + if (pci_enable_msi(pdev)) adapter->flags &= ~NETXEN_NIC_MSI_ENABLED; - printk(KERN_WARNING "%s: unable to allocate MSI interrupt" - " error\n", netxen_nic_driver_name); - } else + else adapter->flags |= NETXEN_NIC_MSI_ENABLED; netdev->irq = pdev->irq; @@ -355,13 +359,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* initialize the adapter */ netxen_initialize_adapter_hw(adapter); -#ifdef CONFIG_PPC - if ((adapter->ahw.boardcfg.board_type == - NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) && - (pci_func_id == 2)) - goto err_out_free_adapter; -#endif /* CONFIG_PPC */ - /* * Adapter in our case is quad port so initialize it before * initializing the ports @@ -509,22 +506,30 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) NETXEN_CAM_RAM(0x1fc))); 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)) + 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); if (val != 0x80000f) { /* clear the register for future unloads/loads */ - writel(0, NETXEN_CRB_NORMALIZE(adapter, - NETXEN_CAM_RAM(0x1fc))); - printk(KERN_ERR "ERROR in NetXen HW init sequence.\n"); - err = -ENODEV; - goto err_out_free_dev; + writel(0, NETXEN_CRB_NORMALIZE(adapter, + NETXEN_CAM_RAM(0x1fc))); + printk(KERN_ERR "ERROR in NetXen HW init sequence.\n"); + 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))); @@ -542,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); } /* @@ -639,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) @@ -648,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]; @@ -691,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); @@ -798,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++; @@ -806,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 */ @@ -816,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; } @@ -1103,28 +1149,26 @@ static int netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) { u32 ret = 0; + u32 our_int = 0; DPRINTK(INFO, "Entered handle ISR\n"); adapter->stats.ints++; if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { - int count = 0; - u32 mask; - u32 our_int = 0; our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); /* not our interrupt */ if ((our_int & (0x80 << adapter->portnum)) == 0) return ret; - netxen_nic_disable_int(adapter); - /* Window = 0 or 1 */ - do { - writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter, - ISR_INT_TARGET_STATUS)); - mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR)); - } while (((mask & 0x80) != 0) && (++count < 32)); - if ((mask & 0x80) != 0) - printk("Could not disable interrupt completely\n"); + } + netxen_nic_disable_int(adapter); + + if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { + /* claim interrupt */ + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + writel(our_int & ~((u32)(0x80 << adapter->portnum)), + NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); + } } if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) { @@ -1136,7 +1180,7 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) } else { static unsigned int intcount = 0; if ((++intcount & 0xfff) == 0xfff) - printk(KERN_ERR + DPRINTK(KERN_ERR "%s: %s interrupt %d while in poll\n", netxen_nic_driver_name, netdev->name, intcount); @@ -1258,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); } diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index 9457fc7249c8..10fe6fafa6f6 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -114,6 +114,20 @@ #define CRB_V2P_3 NETXEN_NIC_REG(0x29c) #define CRB_V2P(port) (CRB_V2P_0+((port)*4)) #define CRB_DRIVER_VERSION NETXEN_NIC_REG(0x2a0) +/* sw int status/mask registers */ +#define CRB_SW_INT_MASK_0 NETXEN_NIC_REG(0x1d8) +#define CRB_SW_INT_MASK_1 NETXEN_NIC_REG(0x1e0) +#define CRB_SW_INT_MASK_2 NETXEN_NIC_REG(0x1e4) +#define CRB_SW_INT_MASK_3 NETXEN_NIC_REG(0x1e8) + +/* + * capabilities register, can be used to selectively enable/disable features + * for backward compability + */ +#define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8) +#define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) + +#define INTR_SCHEME_PERPORT 0x1 /* used for ethtool tests */ #define CRB_SCRATCHPAD_TEST NETXEN_NIC_REG(0x280) |