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>
This commit is contained in:
committed by
Wey-Yi Guy
parent
a8674a1efc
commit
e74fe2330a
@@ -2266,6 +2266,7 @@ void iwlagn_init_notification_wait(struct iwl_priv *priv,
|
|||||||
wait_entry->fn_data = fn_data;
|
wait_entry->fn_data = fn_data;
|
||||||
wait_entry->cmd = cmd;
|
wait_entry->cmd = cmd;
|
||||||
wait_entry->triggered = false;
|
wait_entry->triggered = false;
|
||||||
|
wait_entry->aborted = false;
|
||||||
|
|
||||||
spin_lock_bh(&priv->_agn.notif_wait_lock);
|
spin_lock_bh(&priv->_agn.notif_wait_lock);
|
||||||
list_add(&wait_entry->list, &priv->_agn.notif_waits);
|
list_add(&wait_entry->list, &priv->_agn.notif_waits);
|
||||||
@@ -2279,13 +2280,16 @@ int iwlagn_wait_notification(struct iwl_priv *priv,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = wait_event_timeout(priv->_agn.notif_waitq,
|
ret = wait_event_timeout(priv->_agn.notif_waitq,
|
||||||
wait_entry->triggered,
|
wait_entry->triggered || wait_entry->aborted,
|
||||||
timeout);
|
timeout);
|
||||||
|
|
||||||
spin_lock_bh(&priv->_agn.notif_wait_lock);
|
spin_lock_bh(&priv->_agn.notif_wait_lock);
|
||||||
list_del(&wait_entry->list);
|
list_del(&wait_entry->list);
|
||||||
spin_unlock_bh(&priv->_agn.notif_wait_lock);
|
spin_unlock_bh(&priv->_agn.notif_wait_lock);
|
||||||
|
|
||||||
|
if (wait_entry->aborted)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
/* return value is always >= 0 */
|
/* return value is always >= 0 */
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
|
@@ -867,6 +867,19 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
||||||
{
|
{
|
||||||
unsigned int reload_msec;
|
unsigned int reload_msec;
|
||||||
@@ -878,6 +891,8 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
|||||||
/* Cancel currently queued command. */
|
/* Cancel currently queued command. */
|
||||||
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
|
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
|
||||||
|
|
||||||
|
iwlagn_abort_notification_waits(priv);
|
||||||
|
|
||||||
/* Keep the restart process from trying to send host
|
/* Keep the restart process from trying to send host
|
||||||
* commands by clearing the ready bit */
|
* commands by clearing the ready bit */
|
||||||
clear_bit(STATUS_READY, &priv->status);
|
clear_bit(STATUS_READY, &priv->status);
|
||||||
|
@@ -1110,7 +1110,7 @@ struct iwl_notification_wait {
|
|||||||
void *fn_data;
|
void *fn_data;
|
||||||
|
|
||||||
u8 cmd;
|
u8 cmd;
|
||||||
bool triggered;
|
bool triggered, aborted;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum iwl_rxon_context_id {
|
enum iwl_rxon_context_id {
|
||||||
|
Reference in New Issue
Block a user