netxen: Fix BUG "sleeping function called from invalid context"
authorManish Chopra <manish.chopra@qlogic.com>
Tue, 30 Sep 2014 07:56:35 +0000 (03:56 -0400)
committerDavid S. Miller <davem@davemloft.net>
Tue, 30 Sep 2014 20:22:43 +0000 (16:22 -0400)
o __netxen_nic_down() function might sleep while holding spinlock_t(tx_clean_lock).
  Acquire this lock for only releasing TX buffers instead of taking it
  for whole down path.

Reported-by: Mike Galbraith <umgwanakikbuti@gmail.com>
Signed-off-by: Manish Chopra <manish.chopra@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c

index 32058614151ae8c498887da42278521e4f8bed3b..ae4ec7b3bfd3fcf0161f97fdac9501d51b9d252f 100644 (file)
@@ -135,6 +135,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
        int i, j;
        struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
 
+       spin_lock(&adapter->tx_clean_lock);
        cmd_buf = tx_ring->cmd_buf_arr;
        for (i = 0; i < tx_ring->num_desc; i++) {
                buffrag = cmd_buf->frag_array;
@@ -158,6 +159,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
                }
                cmd_buf++;
        }
+       spin_unlock(&adapter->tx_clean_lock);
 }
 
 void netxen_free_sw_resources(struct netxen_adapter *adapter)
index 1159031f885b10bde26d5119e0aeaedd5641ee0c..5ec5a2b0e9895e02a0dd778d55c79a9d210685ef 100644 (file)
@@ -1186,7 +1186,6 @@ __netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
                return;
 
        smp_mb();
-       spin_lock(&adapter->tx_clean_lock);
        netif_carrier_off(netdev);
        netif_tx_disable(netdev);
 
@@ -1204,7 +1203,6 @@ __netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
        netxen_napi_disable(adapter);
 
        netxen_release_tx_buffers(adapter);
-       spin_unlock(&adapter->tx_clean_lock);
 }
 
 /* Usage: During suspend and firmware recovery module */