diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2009-05-08 18:02:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-09 16:13:36 -0400 |
commit | be339aee634d5cb98a8df8d6febe04002ec497f3 (patch) | |
tree | afca65306a28220adb2e24d0f0cbdfe19501b4af /drivers/net/netxen/netxen_nic_main.c | |
parent | 7a2469ce4d8984722d65628969ad6f8b09da136f (diff) |
netxen: fix irq tear down and msix leak.
o Fix the order of irq and hardware context teardown.
Also synchronize the interrupt in dev close() before
releasing tx buffers.
o Fix possible msi-x vector leak if available vectors are
less than requested.
o Request multiple msix vectors only if hardware supports
multiple rx queues.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 74 |
1 files changed, 43 insertions, 31 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index edb4bcda71ea..c61c1d187a9e 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -175,12 +175,6 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) | |||
175 | struct nx_host_sds_ring *sds_ring; | 175 | struct nx_host_sds_ring *sds_ring; |
176 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | 176 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; |
177 | 177 | ||
178 | if ((adapter->flags & NETXEN_NIC_MSIX_ENABLED) && | ||
179 | adapter->rss_supported) | ||
180 | adapter->max_sds_rings = (num_online_cpus() >= 4) ? 4 : 2; | ||
181 | else | ||
182 | adapter->max_sds_rings = 1; | ||
183 | |||
184 | if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) | 178 | if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) |
185 | return 1; | 179 | return 1; |
186 | 180 | ||
@@ -216,8 +210,9 @@ netxen_napi_disable(struct netxen_adapter *adapter) | |||
216 | 210 | ||
217 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 211 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
218 | sds_ring = &recv_ctx->sds_rings[ring]; | 212 | sds_ring = &recv_ctx->sds_rings[ring]; |
219 | netxen_nic_disable_int(sds_ring); | ||
220 | napi_disable(&sds_ring->napi); | 213 | napi_disable(&sds_ring->napi); |
214 | netxen_nic_disable_int(sds_ring); | ||
215 | synchronize_irq(sds_ring->irq); | ||
221 | } | 216 | } |
222 | } | 217 | } |
223 | 218 | ||
@@ -407,11 +402,11 @@ static void netxen_set_msix_bit(struct pci_dev *pdev, int enable) | |||
407 | } | 402 | } |
408 | } | 403 | } |
409 | 404 | ||
410 | static void netxen_init_msix_entries(struct netxen_adapter *adapter) | 405 | static void netxen_init_msix_entries(struct netxen_adapter *adapter, int count) |
411 | { | 406 | { |
412 | int i; | 407 | int i; |
413 | 408 | ||
414 | for (i = 0; i < MSIX_ENTRIES_PER_ADAPTER; i++) | 409 | for (i = 0; i < count; i++) |
415 | adapter->msix_entries[i].entry = i; | 410 | adapter->msix_entries[i].entry = i; |
416 | } | 411 | } |
417 | 412 | ||
@@ -496,6 +491,15 @@ netxen_setup_intr(struct netxen_adapter *adapter) | |||
496 | { | 491 | { |
497 | struct netxen_legacy_intr_set *legacy_intrp; | 492 | struct netxen_legacy_intr_set *legacy_intrp; |
498 | struct pci_dev *pdev = adapter->pdev; | 493 | struct pci_dev *pdev = adapter->pdev; |
494 | int err, num_msix; | ||
495 | |||
496 | if (adapter->rss_supported) { | ||
497 | num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ? | ||
498 | MSIX_ENTRIES_PER_ADAPTER : 2; | ||
499 | } else | ||
500 | num_msix = 1; | ||
501 | |||
502 | adapter->max_sds_rings = 1; | ||
499 | 503 | ||
500 | adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); | 504 | adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); |
501 | 505 | ||
@@ -512,26 +516,35 @@ netxen_setup_intr(struct netxen_adapter *adapter) | |||
512 | 516 | ||
513 | if (adapter->msix_supported) { | 517 | if (adapter->msix_supported) { |
514 | 518 | ||
515 | netxen_init_msix_entries(adapter); | 519 | netxen_init_msix_entries(adapter, num_msix); |
516 | if (pci_enable_msix(pdev, adapter->msix_entries, | 520 | err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); |
517 | MSIX_ENTRIES_PER_ADAPTER)) | 521 | if (err == 0) { |
518 | goto request_msi; | 522 | adapter->flags |= NETXEN_NIC_MSIX_ENABLED; |
523 | netxen_set_msix_bit(pdev, 1); | ||
519 | 524 | ||
520 | adapter->flags |= NETXEN_NIC_MSIX_ENABLED; | 525 | if (adapter->rss_supported) |
521 | netxen_set_msix_bit(pdev, 1); | 526 | adapter->max_sds_rings = num_msix; |
522 | dev_info(&pdev->dev, "using msi-x interrupts\n"); | ||
523 | 527 | ||
524 | } else { | 528 | dev_info(&pdev->dev, "using msi-x interrupts\n"); |
525 | request_msi: | 529 | return; |
526 | if (use_msi && !pci_enable_msi(pdev)) { | 530 | } |
527 | adapter->flags |= NETXEN_NIC_MSI_ENABLED; | 531 | |
528 | adapter->msi_tgt_status = | 532 | if (err > 0) |
529 | msi_tgt_status[adapter->ahw.pci_func]; | 533 | pci_disable_msix(pdev); |
530 | dev_info(&pdev->dev, "using msi interrupts\n"); | 534 | |
531 | } else | 535 | /* fall through for msi */ |
532 | dev_info(&pdev->dev, "using legacy interrupts\n"); | ||
533 | adapter->msix_entries[0].vector = pdev->irq; | ||
534 | } | 536 | } |
537 | |||
538 | if (use_msi && !pci_enable_msi(pdev)) { | ||
539 | adapter->flags |= NETXEN_NIC_MSI_ENABLED; | ||
540 | adapter->msi_tgt_status = | ||
541 | msi_tgt_status[adapter->ahw.pci_func]; | ||
542 | dev_info(&pdev->dev, "using msi interrupts\n"); | ||
543 | return; | ||
544 | } | ||
545 | |||
546 | dev_info(&pdev->dev, "using legacy interrupts\n"); | ||
547 | adapter->msix_entries[0].vector = pdev->irq; | ||
535 | } | 548 | } |
536 | 549 | ||
537 | static void | 550 | static void |
@@ -767,7 +780,7 @@ netxen_nic_request_irq(struct netxen_adapter *adapter) | |||
767 | 780 | ||
768 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 781 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
769 | sds_ring = &recv_ctx->sds_rings[ring]; | 782 | sds_ring = &recv_ctx->sds_rings[ring]; |
770 | sprintf(sds_ring->name, "%16s[%d]", netdev->name, ring); | 783 | sprintf(sds_ring->name, "%s[%d]", netdev->name, ring); |
771 | err = request_irq(sds_ring->irq, handler, | 784 | err = request_irq(sds_ring->irq, handler, |
772 | flags, sds_ring->name, sds_ring); | 785 | flags, sds_ring->name, sds_ring); |
773 | if (err) | 786 | if (err) |
@@ -830,8 +843,6 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) | |||
830 | { | 843 | { |
831 | netif_carrier_off(netdev); | 844 | netif_carrier_off(netdev); |
832 | netif_stop_queue(netdev); | 845 | netif_stop_queue(netdev); |
833 | smp_mb(); | ||
834 | netxen_napi_disable(adapter); | ||
835 | 846 | ||
836 | if (adapter->stop_port) | 847 | if (adapter->stop_port) |
837 | adapter->stop_port(adapter); | 848 | adapter->stop_port(adapter); |
@@ -839,6 +850,8 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) | |||
839 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | 850 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) |
840 | netxen_p3_free_mac_list(adapter); | 851 | netxen_p3_free_mac_list(adapter); |
841 | 852 | ||
853 | netxen_napi_disable(adapter); | ||
854 | |||
842 | netxen_release_tx_buffers(adapter); | 855 | netxen_release_tx_buffers(adapter); |
843 | 856 | ||
844 | FLUSH_SCHEDULED_WORK(); | 857 | FLUSH_SCHEDULED_WORK(); |
@@ -917,10 +930,9 @@ err_out_free_sw: | |||
917 | static void | 930 | static void |
918 | netxen_nic_detach(struct netxen_adapter *adapter) | 931 | netxen_nic_detach(struct netxen_adapter *adapter) |
919 | { | 932 | { |
920 | netxen_nic_free_irq(adapter); | ||
921 | |||
922 | netxen_release_rx_buffers(adapter); | 933 | netxen_release_rx_buffers(adapter); |
923 | netxen_free_hw_resources(adapter); | 934 | netxen_free_hw_resources(adapter); |
935 | netxen_nic_free_irq(adapter); | ||
924 | netxen_free_sw_resources(adapter); | 936 | netxen_free_sw_resources(adapter); |
925 | 937 | ||
926 | adapter->is_up = 0; | 938 | adapter->is_up = 0; |