iwlagn: leave notification waits on firmware errors
When the firmware encounters an error while the
driver is waiting for a notification, it will
never get that notification. Therefore, instead
of timing out, bail out on errors when waiting
for notifications.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 8284168..a29e2e2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -2266,6 +2266,7 @@
wait_entry->fn_data = fn_data;
wait_entry->cmd = cmd;
wait_entry->triggered = false;
+ wait_entry->aborted = false;
spin_lock_bh(&priv->_agn.notif_wait_lock);
list_add(&wait_entry->list, &priv->_agn.notif_waits);
@@ -2279,13 +2280,16 @@
int ret;
ret = wait_event_timeout(priv->_agn.notif_waitq,
- wait_entry->triggered,
+ wait_entry->triggered || wait_entry->aborted,
timeout);
spin_lock_bh(&priv->_agn.notif_wait_lock);
list_del(&wait_entry->list);
spin_unlock_bh(&priv->_agn.notif_wait_lock);
+ if (wait_entry->aborted)
+ return -EIO;
+
/* return value is always >= 0 */
if (ret <= 0)
return -ETIMEDOUT;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 885167f..46d6965 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -867,6 +867,19 @@
}
#endif
+static void iwlagn_abort_notification_waits(struct iwl_priv *priv)
+{
+ unsigned long flags;
+ struct iwl_notification_wait *wait_entry;
+
+ spin_lock_irqsave(&priv->_agn.notif_wait_lock, flags);
+ list_for_each_entry(wait_entry, &priv->_agn.notif_waits, list)
+ wait_entry->aborted = true;
+ spin_unlock_irqrestore(&priv->_agn.notif_wait_lock, flags);
+
+ wake_up_all(&priv->_agn.notif_waitq);
+}
+
void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
{
unsigned int reload_msec;
@@ -878,6 +891,8 @@
/* Cancel currently queued command. */
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+ iwlagn_abort_notification_waits(priv);
+
/* Keep the restart process from trying to send host
* commands by clearing the ready bit */
clear_bit(STATUS_READY, &priv->status);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index d8bf117..0345292 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1110,7 +1110,7 @@
void *fn_data;
u8 cmd;
- bool triggered;
+ bool triggered, aborted;
};
enum iwl_rxon_context_id {