netxen: free napi resources during detach
o Defer napi resouce allocation to device attach.
o Free napi resources and delete napi during detach.
This ensures right behavior across firmware reset.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index d24e1cb..28f270f 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -167,6 +167,8 @@
{
if (recv_ctx->sds_rings != NULL)
kfree(recv_ctx->sds_rings);
+
+ recv_ctx->sds_rings = NULL;
}
static int
@@ -189,6 +191,21 @@
}
static void
+netxen_napi_del(struct netxen_adapter *adapter)
+{
+ int ring;
+ struct nx_host_sds_ring *sds_ring;
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ netif_napi_del(&sds_ring->napi);
+ }
+
+ netxen_free_sds_rings(&adapter->recv_ctx);
+}
+
+static void
netxen_napi_enable(struct netxen_adapter *adapter)
{
int ring;
@@ -889,10 +906,12 @@
struct nx_host_tx_ring *tx_ring;
err = netxen_init_firmware(adapter);
- if (err != 0) {
- printk(KERN_ERR "Failed to init firmware\n");
- return -EIO;
- }
+ if (err)
+ return err;
+
+ err = netxen_napi_add(adapter, netdev);
+ if (err)
+ return err;
if (adapter->fw_major < 4)
adapter->max_rds_rings = 3;
@@ -956,6 +975,7 @@
netxen_free_hw_resources(adapter);
netxen_release_rx_buffers(adapter);
netxen_nic_free_irq(adapter);
+ netxen_napi_del(adapter);
netxen_free_sw_resources(adapter);
adapter->is_up = 0;
@@ -1100,9 +1120,6 @@
netdev->irq = adapter->msix_entries[0].vector;
- if (netxen_napi_add(adapter, netdev))
- goto err_out_disable_msi;
-
init_timer(&adapter->watchdog_timer);
adapter->watchdog_timer.function = &netxen_watchdog;
adapter->watchdog_timer.data = (unsigned long)adapter;
@@ -1183,7 +1200,6 @@
netxen_free_adapter_offload(adapter);
netxen_teardown_intr(adapter);
- netxen_free_sds_rings(&adapter->recv_ctx);
netxen_cleanup_pci_map(adapter);