ath9k_htc: fix race conditions when stop device

We do not kill any scheduled tasklets when stopping device, that may
cause usage of resources after free. Disable interrupts, kill tasklets
and then works in correct order.

Cc: stable@kernel.org
Tested-by: Sujith <m.sujith@gmail.com>
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Stanislaw Gruszka 2011-01-25 14:15:12 +01:00 committed by John W. Linville
parent 203043f579
commit ea888357ec
2 changed files with 15 additions and 9 deletions

View File

@ -142,9 +142,6 @@ static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
{ {
ath9k_htc_exit_debug(priv->ah); ath9k_htc_exit_debug(priv->ah);
ath9k_hw_deinit(priv->ah); ath9k_hw_deinit(priv->ah);
tasklet_kill(&priv->swba_tasklet);
tasklet_kill(&priv->rx_tasklet);
tasklet_kill(&priv->tx_tasklet);
kfree(priv->ah); kfree(priv->ah);
priv->ah = NULL; priv->ah = NULL;
} }

View File

@ -1025,12 +1025,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
int ret = 0; int ret = 0;
u8 cmd_rsp; u8 cmd_rsp;
/* Cancel all the running timers/work .. */
cancel_work_sync(&priv->fatal_work);
cancel_work_sync(&priv->ps_work);
cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
ath9k_led_stop_brightness(priv);
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
if (priv->op_flags & OP_INVALID) { if (priv->op_flags & OP_INVALID) {
@ -1044,8 +1038,23 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DISABLE_INTR_CMDID);
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
WMI_CMD(WMI_STOP_RECV_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID);
tasklet_kill(&priv->swba_tasklet);
tasklet_kill(&priv->rx_tasklet);
tasklet_kill(&priv->tx_tasklet);
skb_queue_purge(&priv->tx_queue); skb_queue_purge(&priv->tx_queue);
mutex_unlock(&priv->mutex);
/* Cancel all the running timers/work .. */
cancel_work_sync(&priv->fatal_work);
cancel_work_sync(&priv->ps_work);
cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
ath9k_led_stop_brightness(priv);
mutex_lock(&priv->mutex);
/* Remove monitor interface here */ /* Remove monitor interface here */
if (ah->opmode == NL80211_IFTYPE_MONITOR) { if (ah->opmode == NL80211_IFTYPE_MONITOR) {
if (ath9k_htc_remove_monitor_interface(priv)) if (ath9k_htc_remove_monitor_interface(priv))