diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 260 |
1 files changed, 160 insertions, 100 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 6dbdc8be3949..06c4778f5200 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -32,6 +32,7 @@ | |||
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <linux/vmalloc.h> | 34 | #include <linux/vmalloc.h> |
35 | #include <linux/highmem.h> | ||
35 | #include "netxen_nic_hw.h" | 36 | #include "netxen_nic_hw.h" |
36 | 37 | ||
37 | #include "netxen_nic.h" | 38 | #include "netxen_nic.h" |
@@ -48,14 +49,21 @@ MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); | |||
48 | MODULE_LICENSE("GPL"); | 49 | MODULE_LICENSE("GPL"); |
49 | MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); | 50 | MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); |
50 | 51 | ||
51 | char netxen_nic_driver_name[] = "netxen"; | 52 | char netxen_nic_driver_name[] = "netxen-nic"; |
52 | static char netxen_nic_driver_string[] = "NetXen Network Driver version " | 53 | static char netxen_nic_driver_string[] = "NetXen Network Driver version " |
53 | NETXEN_NIC_LINUX_VERSIONID; | 54 | NETXEN_NIC_LINUX_VERSIONID; |
54 | 55 | ||
56 | struct netxen_adapter *g_adapter = NULL; | ||
57 | |||
55 | #define NETXEN_NETDEV_WEIGHT 120 | 58 | #define NETXEN_NETDEV_WEIGHT 120 |
56 | #define NETXEN_ADAPTER_UP_MAGIC 777 | 59 | #define NETXEN_ADAPTER_UP_MAGIC 777 |
57 | #define NETXEN_NIC_PEG_TUNE 0 | 60 | #define NETXEN_NIC_PEG_TUNE 0 |
58 | 61 | ||
62 | u8 nx_p2_id = NX_P2_C0; | ||
63 | |||
64 | #define DMA_32BIT_MASK 0x00000000ffffffffULL | ||
65 | #define DMA_35BIT_MASK 0x00000007ffffffffULL | ||
66 | |||
59 | /* Local functions to NetXen NIC driver */ | 67 | /* Local functions to NetXen NIC driver */ |
60 | static int __devinit netxen_nic_probe(struct pci_dev *pdev, | 68 | static int __devinit netxen_nic_probe(struct pci_dev *pdev, |
61 | const struct pci_device_id *ent); | 69 | const struct pci_device_id *ent); |
@@ -87,6 +95,9 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = { | |||
87 | 95 | ||
88 | MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); | 96 | MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); |
89 | 97 | ||
98 | struct workqueue_struct *netxen_workq; | ||
99 | static void netxen_watchdog(unsigned long); | ||
100 | |||
90 | /* | 101 | /* |
91 | * netxen_nic_probe() | 102 | * netxen_nic_probe() |
92 | * | 103 | * |
@@ -105,20 +116,28 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
105 | struct net_device *netdev = NULL; | 116 | struct net_device *netdev = NULL; |
106 | struct netxen_adapter *adapter = NULL; | 117 | struct netxen_adapter *adapter = NULL; |
107 | struct netxen_port *port = NULL; | 118 | struct netxen_port *port = NULL; |
108 | u8 *mem_ptr0 = NULL; | 119 | void __iomem *mem_ptr0 = NULL; |
109 | u8 *mem_ptr1 = NULL; | 120 | void __iomem *mem_ptr1 = NULL; |
110 | u8 *mem_ptr2 = NULL; | 121 | void __iomem *mem_ptr2 = NULL; |
111 | 122 | ||
112 | unsigned long mem_base, mem_len; | 123 | u8 *db_ptr = NULL; |
124 | unsigned long mem_base, mem_len, db_base, db_len; | ||
113 | int pci_using_dac, i, err; | 125 | int pci_using_dac, i, err; |
114 | int ring; | 126 | int ring; |
115 | struct netxen_recv_context *recv_ctx = NULL; | 127 | struct netxen_recv_context *recv_ctx = NULL; |
116 | struct netxen_rcv_desc_ctx *rcv_desc = NULL; | 128 | struct netxen_rcv_desc_ctx *rcv_desc = NULL; |
117 | struct netxen_cmd_buffer *cmd_buf_arr = NULL; | 129 | struct netxen_cmd_buffer *cmd_buf_arr = NULL; |
118 | u64 mac_addr[FLASH_NUM_PORTS + 1]; | 130 | u64 mac_addr[FLASH_NUM_PORTS + 1]; |
119 | int valid_mac; | 131 | int valid_mac = 0; |
132 | static int netxen_cards_found = 0; | ||
120 | 133 | ||
121 | printk(KERN_INFO "%s \n", netxen_nic_driver_string); | 134 | printk(KERN_INFO "%s \n", netxen_nic_driver_string); |
135 | /* In current scheme, we use only PCI function 0 */ | ||
136 | if (PCI_FUNC(pdev->devfn) != 0) { | ||
137 | DPRINTK(ERR, "NetXen function %d will not be enabled.\n", | ||
138 | PCI_FUNC(pdev->devfn)); | ||
139 | return -ENODEV; | ||
140 | } | ||
122 | if ((err = pci_enable_device(pdev))) | 141 | if ((err = pci_enable_device(pdev))) |
123 | return err; | 142 | return err; |
124 | if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { | 143 | if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { |
@@ -130,10 +149,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
130 | goto err_out_disable_pdev; | 149 | goto err_out_disable_pdev; |
131 | 150 | ||
132 | pci_set_master(pdev); | 151 | pci_set_master(pdev); |
133 | if ((pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) && | 152 | pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id); |
134 | (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) == 0)) | 153 | if (nx_p2_id == NX_P2_C1 && |
154 | (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) && | ||
155 | (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) { | ||
135 | pci_using_dac = 1; | 156 | pci_using_dac = 1; |
136 | else { | 157 | } else { |
137 | if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) || | 158 | if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) || |
138 | (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) | 159 | (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) |
139 | goto err_out_free_res; | 160 | goto err_out_free_res; |
@@ -153,21 +174,34 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
153 | ioremap(mem_base + THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE); | 174 | ioremap(mem_base + THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE); |
154 | 175 | ||
155 | if ((mem_ptr0 == 0UL) || (mem_ptr1 == 0UL) || (mem_ptr2 == 0UL)) { | 176 | if ((mem_ptr0 == 0UL) || (mem_ptr1 == 0UL) || (mem_ptr2 == 0UL)) { |
156 | DPRINTK(1, ERR, | 177 | DPRINTK(ERR, |
157 | "Cannot remap adapter memory aborting.:" | 178 | "Cannot remap adapter memory aborting.:" |
158 | "0 -> %p, 1 -> %p, 2 -> %p\n", | 179 | "0 -> %p, 1 -> %p, 2 -> %p\n", |
159 | mem_ptr0, mem_ptr1, mem_ptr2); | 180 | mem_ptr0, mem_ptr1, mem_ptr2); |
160 | 181 | ||
161 | err = -EIO; | 182 | err = -EIO; |
162 | if (mem_ptr0) | 183 | goto err_out_iounmap; |
163 | iounmap(mem_ptr0); | 184 | } |
164 | if (mem_ptr1) | 185 | db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */ |
165 | iounmap(mem_ptr1); | 186 | db_len = pci_resource_len(pdev, 4); |
166 | if (mem_ptr2) | 187 | |
167 | iounmap(mem_ptr2); | 188 | if (db_len == 0) { |
168 | 189 | printk(KERN_ERR "%s: doorbell is disabled\n", | |
169 | goto err_out_free_res; | 190 | netxen_nic_driver_name); |
191 | err = -EIO; | ||
192 | goto err_out_iounmap; | ||
193 | } | ||
194 | DPRINTK(INFO, "doorbell ioremap from %lx a size of %lx\n", db_base, | ||
195 | db_len); | ||
196 | |||
197 | db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES); | ||
198 | if (db_ptr == 0UL) { | ||
199 | printk(KERN_ERR "%s: Failed to allocate doorbell map.", | ||
200 | netxen_nic_driver_name); | ||
201 | err = -EIO; | ||
202 | goto err_out_iounmap; | ||
170 | } | 203 | } |
204 | DPRINTK(INFO, "doorbell ioremaped at %p\n", db_ptr); | ||
171 | 205 | ||
172 | /* | 206 | /* |
173 | * Allocate a adapter structure which will manage all the initialization | 207 | * Allocate a adapter structure which will manage all the initialization |
@@ -183,17 +217,24 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
183 | netxen_nic_driver_name, | 217 | netxen_nic_driver_name, |
184 | (int)sizeof(struct netxen_adapter)); | 218 | (int)sizeof(struct netxen_adapter)); |
185 | err = -ENOMEM; | 219 | err = -ENOMEM; |
186 | goto err_out_iounmap; | 220 | goto err_out_dbunmap; |
187 | } | 221 | } |
188 | 222 | ||
223 | if (netxen_cards_found == 0) { | ||
224 | g_adapter = adapter; | ||
225 | } | ||
189 | adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS; | 226 | adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS; |
190 | adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS; | 227 | adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS; |
191 | adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS; | 228 | adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS; |
229 | adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS; | ||
192 | 230 | ||
193 | pci_set_drvdata(pdev, adapter); | 231 | pci_set_drvdata(pdev, adapter); |
194 | 232 | ||
195 | cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE); | 233 | cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE); |
196 | if (cmd_buf_arr == NULL) { | 234 | if (cmd_buf_arr == NULL) { |
235 | printk(KERN_ERR | ||
236 | "%s: Could not allocate cmd_buf_arr memory:%d\n", | ||
237 | netxen_nic_driver_name, (int)TX_RINGSIZE); | ||
197 | err = -ENOMEM; | 238 | err = -ENOMEM; |
198 | goto err_out_free_adapter; | 239 | goto err_out_free_adapter; |
199 | } | 240 | } |
@@ -220,11 +261,23 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
220 | rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH; | 261 | rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH; |
221 | break; | 262 | break; |
222 | 263 | ||
264 | case RCV_RING_LRO: | ||
265 | rcv_desc->max_rx_desc_count = | ||
266 | adapter->max_lro_rx_desc_count; | ||
267 | rcv_desc->flags = RCV_DESC_LRO; | ||
268 | rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN; | ||
269 | rcv_desc->skb_size = MAX_RX_LRO_BUFFER_LENGTH; | ||
270 | break; | ||
271 | |||
223 | } | 272 | } |
224 | rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *) | 273 | rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *) |
225 | vmalloc(RCV_BUFFSIZE); | 274 | vmalloc(RCV_BUFFSIZE); |
226 | 275 | ||
227 | if (rcv_desc->rx_buf_arr == NULL) { | 276 | if (rcv_desc->rx_buf_arr == NULL) { |
277 | printk(KERN_ERR "%s: Could not allocate" | ||
278 | "rcv_desc->rx_buf_arr memory:%d\n", | ||
279 | netxen_nic_driver_name, | ||
280 | (int)RCV_BUFFSIZE); | ||
228 | err = -ENOMEM; | 281 | err = -ENOMEM; |
229 | goto err_out_free_rx_buffer; | 282 | goto err_out_free_rx_buffer; |
230 | } | 283 | } |
@@ -237,16 +290,17 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
237 | adapter->ahw.pci_base0 = mem_ptr0; | 290 | adapter->ahw.pci_base0 = mem_ptr0; |
238 | adapter->ahw.pci_base1 = mem_ptr1; | 291 | adapter->ahw.pci_base1 = mem_ptr1; |
239 | adapter->ahw.pci_base2 = mem_ptr2; | 292 | adapter->ahw.pci_base2 = mem_ptr2; |
293 | adapter->ahw.db_base = db_ptr; | ||
294 | adapter->ahw.db_len = db_len; | ||
240 | spin_lock_init(&adapter->tx_lock); | 295 | spin_lock_init(&adapter->tx_lock); |
241 | spin_lock_init(&adapter->lock); | 296 | spin_lock_init(&adapter->lock); |
297 | netxen_initialize_adapter_sw(adapter); /* initialize the buffers in adapter */ | ||
242 | #ifdef CONFIG_IA64 | 298 | #ifdef CONFIG_IA64 |
243 | netxen_pinit_from_rom(adapter, 0); | 299 | netxen_pinit_from_rom(adapter, 0); |
244 | udelay(500); | 300 | udelay(500); |
245 | netxen_load_firmware(adapter); | 301 | netxen_load_firmware(adapter); |
246 | #endif | 302 | #endif |
247 | 303 | ||
248 | /* initialize the buffers in adapter */ | ||
249 | netxen_initialize_adapter_sw(adapter); | ||
250 | /* | 304 | /* |
251 | * Set the CRB window to invalid. If any register in window 0 is | 305 | * Set the CRB window to invalid. If any register in window 0 is |
252 | * accessed it should set the window to 0 and then reset it to 1. | 306 | * accessed it should set the window to 0 and then reset it to 1. |
@@ -268,7 +322,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
268 | (void (*)(void *))netxen_watchdog_task, adapter); | 322 | (void (*)(void *))netxen_watchdog_task, adapter); |
269 | adapter->ahw.pdev = pdev; | 323 | adapter->ahw.pdev = pdev; |
270 | adapter->proc_cmd_buf_counter = 0; | 324 | adapter->proc_cmd_buf_counter = 0; |
271 | pci_read_config_byte(pdev, PCI_REVISION_ID, &adapter->ahw.revision_id); | 325 | adapter->ahw.revision_id = nx_p2_id; |
272 | 326 | ||
273 | if (pci_enable_msi(pdev)) { | 327 | if (pci_enable_msi(pdev)) { |
274 | adapter->flags &= ~NETXEN_NIC_MSI_ENABLED; | 328 | adapter->flags &= ~NETXEN_NIC_MSI_ENABLED; |
@@ -290,6 +344,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
290 | writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET)); | 344 | writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET)); |
291 | writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO)); | 345 | writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO)); |
292 | 346 | ||
347 | /* do this before waking up pegs so that we have valid dummy dma addr */ | ||
348 | err = netxen_initialize_adapter_offload(adapter); | ||
349 | if (err) { | ||
350 | goto err_out_free_dev; | ||
351 | } | ||
352 | |||
293 | /* Unlock the HW, prompting the boot sequence */ | 353 | /* Unlock the HW, prompting the boot sequence */ |
294 | writel(1, | 354 | writel(1, |
295 | NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE)); | 355 | NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE)); |
@@ -298,6 +358,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
298 | netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); | 358 | netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); |
299 | 359 | ||
300 | /* initialize the all the ports */ | 360 | /* initialize the all the ports */ |
361 | adapter->active_ports = 0; | ||
301 | 362 | ||
302 | for (i = 0; i < adapter->ahw.max_ports; i++) { | 363 | for (i = 0; i < adapter->ahw.max_ports; i++) { |
303 | netdev = alloc_etherdev(sizeof(struct netxen_port)); | 364 | netdev = alloc_etherdev(sizeof(struct netxen_port)); |
@@ -368,7 +429,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
368 | netdev->dev_addr); | 429 | netdev->dev_addr); |
369 | } | 430 | } |
370 | } | 431 | } |
371 | INIT_WORK(&adapter->tx_timeout_task, | 432 | INIT_WORK(adapter->tx_timeout_task + i, |
372 | (void (*)(void *))netxen_tx_timeout_task, netdev); | 433 | (void (*)(void *))netxen_tx_timeout_task, netdev); |
373 | netif_carrier_off(netdev); | 434 | netif_carrier_off(netdev); |
374 | netif_stop_queue(netdev); | 435 | netif_stop_queue(netdev); |
@@ -381,7 +442,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
381 | goto err_out_free_dev; | 442 | goto err_out_free_dev; |
382 | } | 443 | } |
383 | adapter->port_count++; | 444 | adapter->port_count++; |
384 | adapter->active_ports = 0; | ||
385 | adapter->port[i] = port; | 445 | adapter->port[i] = port; |
386 | } | 446 | } |
387 | 447 | ||
@@ -402,6 +462,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
402 | break; | 462 | break; |
403 | } | 463 | } |
404 | 464 | ||
465 | adapter->number = netxen_cards_found; | ||
405 | adapter->driver_mismatch = 0; | 466 | adapter->driver_mismatch = 0; |
406 | 467 | ||
407 | return 0; | 468 | return 0; |
@@ -417,6 +478,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
417 | } | 478 | } |
418 | } | 479 | } |
419 | 480 | ||
481 | netxen_free_adapter_offload(adapter); | ||
482 | |||
420 | err_out_free_rx_buffer: | 483 | err_out_free_rx_buffer: |
421 | for (i = 0; i < MAX_RCV_CTX; ++i) { | 484 | for (i = 0; i < MAX_RCV_CTX; ++i) { |
422 | recv_ctx = &adapter->recv_ctx[i]; | 485 | recv_ctx = &adapter->recv_ctx[i]; |
@@ -428,19 +491,23 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
428 | } | 491 | } |
429 | } | 492 | } |
430 | } | 493 | } |
431 | |||
432 | vfree(cmd_buf_arr); | 494 | vfree(cmd_buf_arr); |
433 | 495 | ||
434 | kfree(adapter->port); | ||
435 | |||
436 | err_out_free_adapter: | 496 | err_out_free_adapter: |
437 | pci_set_drvdata(pdev, NULL); | 497 | pci_set_drvdata(pdev, NULL); |
438 | kfree(adapter); | 498 | kfree(adapter); |
439 | 499 | ||
500 | err_out_dbunmap: | ||
501 | if (db_ptr) | ||
502 | iounmap(db_ptr); | ||
503 | |||
440 | err_out_iounmap: | 504 | err_out_iounmap: |
441 | iounmap(mem_ptr0); | 505 | if (mem_ptr0) |
442 | iounmap(mem_ptr1); | 506 | iounmap(mem_ptr0); |
443 | iounmap(mem_ptr2); | 507 | if (mem_ptr1) |
508 | iounmap(mem_ptr1); | ||
509 | if (mem_ptr2) | ||
510 | iounmap(mem_ptr2); | ||
444 | 511 | ||
445 | err_out_free_res: | 512 | err_out_free_res: |
446 | pci_release_regions(pdev); | 513 | pci_release_regions(pdev); |
@@ -465,12 +532,8 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) | |||
465 | 532 | ||
466 | netxen_nic_stop_all_ports(adapter); | 533 | netxen_nic_stop_all_ports(adapter); |
467 | /* leave the hw in the same state as reboot */ | 534 | /* leave the hw in the same state as reboot */ |
468 | netxen_pinit_from_rom(adapter, 0); | ||
469 | udelay(500); | ||
470 | netxen_load_firmware(adapter); | 535 | netxen_load_firmware(adapter); |
471 | 536 | netxen_free_adapter_offload(adapter); | |
472 | if ((adapter->flags & NETXEN_NIC_MSI_ENABLED)) | ||
473 | netxen_nic_disable_int(adapter); | ||
474 | 537 | ||
475 | udelay(500); /* Delay for a while to drain the DMA engines */ | 538 | udelay(500); /* Delay for a while to drain the DMA engines */ |
476 | for (i = 0; i < adapter->port_count; i++) { | 539 | for (i = 0; i < adapter->port_count; i++) { |
@@ -487,6 +550,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) | |||
487 | if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) | 550 | if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) |
488 | netxen_free_hw_resources(adapter); | 551 | netxen_free_hw_resources(adapter); |
489 | 552 | ||
553 | iounmap(adapter->ahw.db_base); | ||
490 | iounmap(adapter->ahw.pci_base0); | 554 | iounmap(adapter->ahw.pci_base0); |
491 | iounmap(adapter->ahw.pci_base1); | 555 | iounmap(adapter->ahw.pci_base1); |
492 | iounmap(adapter->ahw.pci_base2); | 556 | iounmap(adapter->ahw.pci_base2); |
@@ -534,6 +598,8 @@ static int netxen_nic_open(struct net_device *netdev) | |||
534 | return -EIO; | 598 | return -EIO; |
535 | } | 599 | } |
536 | netxen_nic_flash_print(adapter); | 600 | netxen_nic_flash_print(adapter); |
601 | if (adapter->init_niu) | ||
602 | adapter->init_niu(adapter); | ||
537 | 603 | ||
538 | /* setup all the resources for the Phantom... */ | 604 | /* setup all the resources for the Phantom... */ |
539 | /* this include the descriptors for rcv, tx, and status */ | 605 | /* this include the descriptors for rcv, tx, and status */ |
@@ -551,25 +617,24 @@ static int netxen_nic_open(struct net_device *netdev) | |||
551 | netxen_free_hw_resources(adapter); | 617 | netxen_free_hw_resources(adapter); |
552 | return -EIO; | 618 | return -EIO; |
553 | } | 619 | } |
554 | if (adapter->init_niu) | ||
555 | adapter->init_niu(adapter); | ||
556 | for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { | 620 | for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { |
557 | for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) | 621 | for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) |
558 | netxen_post_rx_buffers(adapter, ctx, ring); | 622 | netxen_post_rx_buffers(adapter, ctx, ring); |
559 | } | 623 | } |
560 | adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; | 624 | adapter->irq = adapter->ahw.pdev->irq; |
561 | } | ||
562 | adapter->active_ports++; | ||
563 | if (adapter->active_ports == 1) { | ||
564 | err = request_irq(adapter->ahw.pdev->irq, &netxen_intr, | 625 | err = request_irq(adapter->ahw.pdev->irq, &netxen_intr, |
565 | SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name, | 626 | SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name, |
566 | adapter); | 627 | adapter); |
567 | if (err) { | 628 | if (err) { |
568 | printk(KERN_ERR "request_irq failed with: %d\n", err); | 629 | printk(KERN_ERR "request_irq failed with: %d\n", err); |
569 | adapter->active_ports--; | 630 | netxen_free_hw_resources(adapter); |
570 | return err; | 631 | return err; |
571 | } | 632 | } |
572 | adapter->irq = adapter->ahw.pdev->irq; | 633 | |
634 | adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; | ||
635 | } | ||
636 | adapter->active_ports++; | ||
637 | if (adapter->active_ports == 1) { | ||
573 | if (!adapter->driver_mismatch) | 638 | if (!adapter->driver_mismatch) |
574 | mod_timer(&adapter->watchdog_timer, jiffies); | 639 | mod_timer(&adapter->watchdog_timer, jiffies); |
575 | 640 | ||
@@ -583,6 +648,9 @@ static int netxen_nic_open(struct net_device *netdev) | |||
583 | netxen_nic_set_link_parameters(port); | 648 | netxen_nic_set_link_parameters(port); |
584 | 649 | ||
585 | netxen_nic_set_multi(netdev); | 650 | netxen_nic_set_multi(netdev); |
651 | if (adapter->set_mtu) | ||
652 | adapter->set_mtu(port, netdev->mtu); | ||
653 | |||
586 | if (!adapter->driver_mismatch) | 654 | if (!adapter->driver_mismatch) |
587 | netif_start_queue(netdev); | 655 | netif_start_queue(netdev); |
588 | 656 | ||
@@ -635,6 +703,7 @@ static int netxen_nic_close(struct net_device *netdev) | |||
635 | } | 703 | } |
636 | cmd_buff++; | 704 | cmd_buff++; |
637 | } | 705 | } |
706 | FLUSH_SCHEDULED_WORK(); | ||
638 | del_timer_sync(&adapter->watchdog_timer); | 707 | del_timer_sync(&adapter->watchdog_timer); |
639 | } | 708 | } |
640 | 709 | ||
@@ -655,7 +724,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
655 | struct cmd_desc_type0 *hwdesc; | 724 | struct cmd_desc_type0 *hwdesc; |
656 | int k; | 725 | int k; |
657 | struct netxen_cmd_buffer *pbuf = NULL; | 726 | struct netxen_cmd_buffer *pbuf = NULL; |
658 | unsigned int tries = 0; | ||
659 | static int dropped_packet = 0; | 727 | static int dropped_packet = 0; |
660 | int frag_count; | 728 | int frag_count; |
661 | u32 local_producer = 0; | 729 | u32 local_producer = 0; |
@@ -717,7 +785,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
717 | if (((skb->nh.iph)->ihl * sizeof(u32)) + | 785 | if (((skb->nh.iph)->ihl * sizeof(u32)) + |
718 | ((skb->h.th)->doff * sizeof(u32)) + | 786 | ((skb->h.th)->doff * sizeof(u32)) + |
719 | sizeof(struct ethhdr) > | 787 | sizeof(struct ethhdr) > |
720 | (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) { | 788 | (sizeof(struct cmd_desc_type0) - 2)) { |
721 | no_of_desc++; | 789 | no_of_desc++; |
722 | } | 790 | } |
723 | } | 791 | } |
@@ -728,27 +796,17 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
728 | if ((k + no_of_desc) >= | 796 | if ((k + no_of_desc) >= |
729 | ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count : | 797 | ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count : |
730 | last_cmd_consumer)) { | 798 | last_cmd_consumer)) { |
799 | port->stats.nocmddescriptor++; | ||
800 | DPRINTK(ERR, "No command descriptors available," | ||
801 | " producer = %d, consumer = %d count=%llu," | ||
802 | " dropping packet\n", producer, | ||
803 | adapter->last_cmd_consumer, | ||
804 | port->stats.nocmddescriptor); | ||
805 | |||
806 | netif_stop_queue(netdev); | ||
807 | port->flags |= NETXEN_NETDEV_STATUS; | ||
731 | spin_unlock_bh(&adapter->tx_lock); | 808 | spin_unlock_bh(&adapter->tx_lock); |
732 | if (tries == 0) { | 809 | return NETDEV_TX_BUSY; |
733 | local_bh_disable(); | ||
734 | netxen_process_cmd_ring((unsigned long)adapter); | ||
735 | local_bh_enable(); | ||
736 | ++tries; | ||
737 | goto retry_getting_window; | ||
738 | } else { | ||
739 | port->stats.nocmddescriptor++; | ||
740 | DPRINTK(ERR, "No command descriptors available," | ||
741 | " producer = %d, consumer = %d count=%llu," | ||
742 | " dropping packet\n", producer, | ||
743 | adapter->last_cmd_consumer, | ||
744 | port->stats.nocmddescriptor); | ||
745 | |||
746 | spin_lock_bh(&adapter->tx_lock); | ||
747 | netif_stop_queue(netdev); | ||
748 | port->flags |= NETXEN_NETDEV_STATUS; | ||
749 | spin_unlock_bh(&adapter->tx_lock); | ||
750 | return NETDEV_TX_BUSY; | ||
751 | } | ||
752 | } | 810 | } |
753 | k = get_index_range(k, max_tx_desc_count, no_of_desc); | 811 | k = get_index_range(k, max_tx_desc_count, no_of_desc); |
754 | adapter->cmd_producer = k; | 812 | adapter->cmd_producer = k; |
@@ -770,7 +828,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
770 | pbuf->mss = 0; | 828 | pbuf->mss = 0; |
771 | hwdesc->mss = 0; | 829 | hwdesc->mss = 0; |
772 | } | 830 | } |
773 | pbuf->no_of_descriptors = no_of_desc; | ||
774 | pbuf->total_length = skb->len; | 831 | pbuf->total_length = skb->len; |
775 | pbuf->skb = skb; | 832 | pbuf->skb = skb; |
776 | pbuf->cmd = TX_ETHER_PKT; | 833 | pbuf->cmd = TX_ETHER_PKT; |
@@ -780,11 +837,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
780 | buffrag->dma = pci_map_single(port->pdev, skb->data, first_seg_len, | 837 | buffrag->dma = pci_map_single(port->pdev, skb->data, first_seg_len, |
781 | PCI_DMA_TODEVICE); | 838 | PCI_DMA_TODEVICE); |
782 | buffrag->length = first_seg_len; | 839 | buffrag->length = first_seg_len; |
783 | CMD_DESC_TOTAL_LENGTH_WRT(hwdesc, skb->len); | 840 | netxen_set_cmd_desc_totallength(hwdesc, skb->len); |
784 | hwdesc->num_of_buffers = frag_count; | 841 | netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count); |
785 | hwdesc->opcode = TX_ETHER_PKT; | 842 | netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT); |
786 | 843 | ||
787 | CMD_DESC_PORT_WRT(hwdesc, port->portnum); | 844 | netxen_set_cmd_desc_port(hwdesc, port->portnum); |
788 | hwdesc->buffer1_length = cpu_to_le16(first_seg_len); | 845 | hwdesc->buffer1_length = cpu_to_le16(first_seg_len); |
789 | hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); | 846 | hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); |
790 | 847 | ||
@@ -843,12 +900,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
843 | /* For LSO, we need to copy the MAC/IP/TCP headers into | 900 | /* For LSO, we need to copy the MAC/IP/TCP headers into |
844 | * the descriptor ring | 901 | * the descriptor ring |
845 | */ | 902 | */ |
846 | if (hw->cmd_desc_head[saved_producer].opcode == TX_TCP_LSO) { | 903 | if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer]) |
904 | == TX_TCP_LSO) { | ||
847 | int hdr_len, first_hdr_len, more_hdr; | 905 | int hdr_len, first_hdr_len, more_hdr; |
848 | hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length; | 906 | hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length; |
849 | if (hdr_len > (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) { | 907 | if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) { |
850 | first_hdr_len = | 908 | first_hdr_len = sizeof(struct cmd_desc_type0) - 2; |
851 | sizeof(struct cmd_desc_type0) - NET_IP_ALIGN; | ||
852 | more_hdr = 1; | 909 | more_hdr = 1; |
853 | } else { | 910 | } else { |
854 | first_hdr_len = hdr_len; | 911 | first_hdr_len = hdr_len; |
@@ -858,7 +915,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
858 | hwdesc = &hw->cmd_desc_head[producer]; | 915 | hwdesc = &hw->cmd_desc_head[producer]; |
859 | 916 | ||
860 | /* copy the first 64 bytes */ | 917 | /* copy the first 64 bytes */ |
861 | memcpy(((void *)hwdesc) + NET_IP_ALIGN, | 918 | memcpy(((void *)hwdesc) + 2, |
862 | (void *)(skb->data), first_hdr_len); | 919 | (void *)(skb->data), first_hdr_len); |
863 | producer = get_next_index(producer, max_tx_desc_count); | 920 | producer = get_next_index(producer, max_tx_desc_count); |
864 | 921 | ||
@@ -874,7 +931,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
874 | } | 931 | } |
875 | spin_lock_bh(&adapter->tx_lock); | 932 | spin_lock_bh(&adapter->tx_lock); |
876 | port->stats.txbytes += | 933 | port->stats.txbytes += |
877 | CMD_DESC_TOTAL_LENGTH(&hw->cmd_desc_head[saved_producer]); | 934 | netxen_get_cmd_desc_totallength(&hw->cmd_desc_head[saved_producer]); |
878 | /* Code to update the adapter considering how many producer threads | 935 | /* Code to update the adapter considering how many producer threads |
879 | are currently working */ | 936 | are currently working */ |
880 | if ((--adapter->num_threads) == 0) { | 937 | if ((--adapter->num_threads) == 0) { |
@@ -884,20 +941,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
884 | NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET)); | 941 | NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET)); |
885 | wmb(); | 942 | wmb(); |
886 | adapter->total_threads = 0; | 943 | adapter->total_threads = 0; |
887 | } else { | ||
888 | u32 crb_producer = 0; | ||
889 | crb_producer = | ||
890 | readl(NETXEN_CRB_NORMALIZE | ||
891 | (adapter, CRB_CMD_PRODUCER_OFFSET)); | ||
892 | if (crb_producer == local_producer) { | ||
893 | crb_producer = get_index_range(crb_producer, | ||
894 | max_tx_desc_count, | ||
895 | no_of_desc); | ||
896 | writel(crb_producer, | ||
897 | NETXEN_CRB_NORMALIZE(adapter, | ||
898 | CRB_CMD_PRODUCER_OFFSET)); | ||
899 | wmb(); | ||
900 | } | ||
901 | } | 944 | } |
902 | 945 | ||
903 | port->stats.xmitfinished++; | 946 | port->stats.xmitfinished++; |
@@ -914,15 +957,20 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
914 | static void netxen_watchdog(unsigned long v) | 957 | static void netxen_watchdog(unsigned long v) |
915 | { | 958 | { |
916 | struct netxen_adapter *adapter = (struct netxen_adapter *)v; | 959 | struct netxen_adapter *adapter = (struct netxen_adapter *)v; |
917 | schedule_work(&adapter->watchdog_task); | 960 | if (adapter != g_adapter) { |
961 | printk("%s: ***BUG*** adapter[%p] != g_adapter[%p]\n", | ||
962 | __FUNCTION__, adapter, g_adapter); | ||
963 | return; | ||
964 | } | ||
965 | |||
966 | SCHEDULE_WORK(&adapter->watchdog_task); | ||
918 | } | 967 | } |
919 | 968 | ||
920 | static void netxen_tx_timeout(struct net_device *netdev) | 969 | static void netxen_tx_timeout(struct net_device *netdev) |
921 | { | 970 | { |
922 | struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev); | 971 | struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev); |
923 | struct netxen_adapter *adapter = port->adapter; | ||
924 | 972 | ||
925 | schedule_work(&adapter->tx_timeout_task); | 973 | SCHEDULE_WORK(port->adapter->tx_timeout_task + port->portnum); |
926 | } | 974 | } |
927 | 975 | ||
928 | static void netxen_tx_timeout_task(struct net_device *netdev) | 976 | static void netxen_tx_timeout_task(struct net_device *netdev) |
@@ -953,6 +1001,11 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) | |||
953 | if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { | 1001 | if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { |
954 | int count = 0; | 1002 | int count = 0; |
955 | u32 mask; | 1003 | u32 mask; |
1004 | mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR)); | ||
1005 | if ((mask & 0x80) == 0) { | ||
1006 | /* not our interrupt */ | ||
1007 | return ret; | ||
1008 | } | ||
956 | netxen_nic_disable_int(adapter); | 1009 | netxen_nic_disable_int(adapter); |
957 | /* Window = 0 or 1 */ | 1010 | /* Window = 0 or 1 */ |
958 | do { | 1011 | do { |
@@ -1012,7 +1065,10 @@ irqreturn_t netxen_intr(int irq, void *data) | |||
1012 | netdev = port->netdev; | 1065 | netdev = port->netdev; |
1013 | 1066 | ||
1014 | /* process our status queue (for all 4 ports) */ | 1067 | /* process our status queue (for all 4 ports) */ |
1015 | netxen_handle_int(adapter, netdev); | 1068 | if (netif_running(netdev)) { |
1069 | netxen_handle_int(adapter, netdev); | ||
1070 | break; | ||
1071 | } | ||
1016 | } | 1072 | } |
1017 | 1073 | ||
1018 | return IRQ_HANDLED; | 1074 | return IRQ_HANDLED; |
@@ -1054,11 +1110,11 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget) | |||
1054 | netdev->quota -= work_done; | 1110 | netdev->quota -= work_done; |
1055 | *budget -= work_done; | 1111 | *budget -= work_done; |
1056 | 1112 | ||
1057 | if (work_done >= work_to_do | 1113 | if (work_done >= work_to_do && netxen_nic_rx_has_work(adapter) != 0) |
1058 | && netxen_nic_rx_has_work(adapter) != 0) | ||
1059 | done = 0; | 1114 | done = 0; |
1060 | 1115 | ||
1061 | netxen_process_cmd_ring((unsigned long)adapter); | 1116 | if (netxen_process_cmd_ring((unsigned long)adapter) == 0) |
1117 | done = 0; | ||
1062 | 1118 | ||
1063 | DPRINTK(INFO, "new work_done: %d work_to_do: %d\n", | 1119 | DPRINTK(INFO, "new work_done: %d work_to_do: %d\n", |
1064 | work_done, work_to_do); | 1120 | work_done, work_to_do); |
@@ -1104,8 +1160,9 @@ netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
1104 | if (ifr->ifr_data) { | 1160 | if (ifr->ifr_data) { |
1105 | sprintf(dev_name, "%s-%d", NETXEN_NIC_NAME_RSP, | 1161 | sprintf(dev_name, "%s-%d", NETXEN_NIC_NAME_RSP, |
1106 | port->portnum); | 1162 | port->portnum); |
1107 | nr_bytes = copy_to_user((char *)ifr->ifr_data, dev_name, | 1163 | nr_bytes = |
1108 | NETXEN_NIC_NAME_LEN); | 1164 | copy_to_user((char __user *)ifr->ifr_data, dev_name, |
1165 | NETXEN_NIC_NAME_LEN); | ||
1109 | if (nr_bytes) | 1166 | if (nr_bytes) |
1110 | err = -EIO; | 1167 | err = -EIO; |
1111 | 1168 | ||
@@ -1132,6 +1189,9 @@ static struct pci_driver netxen_driver = { | |||
1132 | 1189 | ||
1133 | static int __init netxen_init_module(void) | 1190 | static int __init netxen_init_module(void) |
1134 | { | 1191 | { |
1192 | if ((netxen_workq = create_singlethread_workqueue("netxen")) == 0) | ||
1193 | return -ENOMEM; | ||
1194 | |||
1135 | return pci_module_init(&netxen_driver); | 1195 | return pci_module_init(&netxen_driver); |
1136 | } | 1196 | } |
1137 | 1197 | ||
@@ -1142,7 +1202,7 @@ static void __exit netxen_exit_module(void) | |||
1142 | /* | 1202 | /* |
1143 | * Wait for some time to allow the dma to drain, if any. | 1203 | * Wait for some time to allow the dma to drain, if any. |
1144 | */ | 1204 | */ |
1145 | mdelay(5); | 1205 | destroy_workqueue(netxen_workq); |
1146 | pci_unregister_driver(&netxen_driver); | 1206 | pci_unregister_driver(&netxen_driver); |
1147 | } | 1207 | } |
1148 | 1208 | ||