Skip to content

Commit

Permalink
iwlagn: avoid hangs when restarting device
Browse files Browse the repository at this point in the history
If a device error happens while the uCode is
being loaded or initialised, we will attempt
to restart the device (which will likely fail
again, but that's not the issue here). During
this new restart, we turn off the device, but
as the uCode failed to initialise it already
is turned off. As a consequence, grabbing NIC
access will fail and cause excessive messages
and hangs.

To fix this issue, introduce a new status bit
and only attempt to reprogram the device when
it isn't already disabled.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
  • Loading branch information
Johannes Berg authored and Wey-Yi Guy committed Apr 30, 2011
1 parent ff776ce commit 9d39e5b
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 6 deletions.
21 changes: 15 additions & 6 deletions drivers/net/wireless/iwlwifi/iwl-agn-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -2363,12 +2363,21 @@ void iwlagn_stop_device(struct iwl_priv *priv)
/* device going down, Stop using ICT table */
iwl_disable_ict(priv);

iwlagn_txq_ctx_stop(priv);
iwlagn_rxq_stop(priv);

/* Power-down device's busmaster DMA clocks */
iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
udelay(5);
/*
* If a HW restart happens during firmware loading,
* then the firmware loading might call this function
* and later it might be called again due to the
* restart. So don't process again if the device is
* already dead.
*/
if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) {
iwlagn_txq_ctx_stop(priv);
iwlagn_rxq_stop(priv);

/* Power-down device's busmaster DMA clocks */
iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
udelay(5);
}

/* Make sure (redundant) we've released our request to stay awake */
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/wireless/iwlwifi/iwl-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,8 @@ void iwl_apm_stop(struct iwl_priv *priv)
{
IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n");

clear_bit(STATUS_DEVICE_ENABLED, &priv->status);

/* Stop device's DMA activity */
iwl_apm_stop_master(priv);

Expand Down Expand Up @@ -1109,6 +1111,8 @@ int iwl_apm_init(struct iwl_priv *priv)
iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);

set_bit(STATUS_DEVICE_ENABLED, &priv->status);

out:
return ret;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/iwlwifi/iwl-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ void iwlcore_free_geos(struct iwl_priv *priv);
#define STATUS_SCAN_HW 15
#define STATUS_POWER_PMI 16
#define STATUS_FW_ERROR 17
#define STATUS_DEVICE_ENABLED 18


static inline int iwl_is_ready(struct iwl_priv *priv)
Expand Down

0 comments on commit 9d39e5b

Please sign in to comment.