libertas: wake all pending commands on shutdown

Marcelo Tosatti mtosatti at redhat.unroutablecom
Mon Dec 11 15:18:31 EST 2006


Commit:     d2bd5c5a43b8b828521b322d8adf0528fa58391d
Parent:     55cf1c4375aab7c5540078a096e9d82abea158af
commit d2bd5c5a43b8b828521b322d8adf0528fa58391d
Author:     Marcelo Tosatti <mtosatti at redhat.com>
AuthorDate: Mon Dec 11 17:49:13 2006 -0200
Commit:     Marcelo Tosatti <mtosatti at redhat.com>
CommitDate: Mon Dec 11 17:49:13 2006 -0200

    libertas: wake all pending commands on shutdown
    
    Wake all pending commands on driver shutdown, one of them which is not
    adapter->CurCmd might hold rtnl_lock (ethtool/ioctl for example), which
    will cause unregister_netdev() to deadlock.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
---
 drivers/net/wireless/libertas/wlan_main.c |   23 ++++++++++++++++-------
 1 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/libertas/wlan_main.c b/drivers/net/wireless/libertas/wlan_main.c
index 253ebe3..9b3f469 100644
--- a/drivers/net/wireless/libertas/wlan_main.c
+++ b/drivers/net/wireless/libertas/wlan_main.c
@@ -1074,6 +1074,20 @@ err_kmalloc:
 	return NULL;
 }
 
+void wake_pending_cmdnodes(wlan_private *priv)
+{
+	struct CmdCtrlNode *cmdnode;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->adapter->driver_lock, flags);
+	list_for_each_entry(cmdnode, &priv->adapter->CmdPendingQ, list) {
+		cmdnode->CmdWaitQWoken = 1;
+		wake_up_interruptible(&cmdnode->cmdwait_q);
+	}
+	spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);
+}
+
+
 /** 
  *  @brief This function removes the card.
  *  
@@ -1108,19 +1122,14 @@ static int wlan_remove_card(void *card)
 	netif_stop_queue(priv->wlan_dev.netdev);
 	netif_carrier_off(priv->wlan_dev.netdev);
 
+	wake_pending_cmdnodes(priv);
+
 	unregister_netdev(mesh_dev);
 	unregister_netdev(dev);
 
 	cancel_delayed_work(&priv->assoc_work);
 	destroy_workqueue(priv->assoc_thread);
 
-	if (Adapter->CurCmd) {
-		dprintk(1, "Wake up current cmdwait_q\n");
-		wake_up_interruptible(&Adapter->CurCmd->cmdwait_q);
-	}
-
-	Adapter->CurCmd = NULL;
-
 	if (Adapter->PSMode == Wlan802_11PowerModeMAX_PSP) {
 		Adapter->PSMode = Wlan802_11PowerModeCAM;
 		libertas_ps_wakeup(priv, HostCmd_OPTION_WAITFORRSP);


More information about the Commits-kernel mailing list