[PATCH 35/99] cw1200: fix for wrong order of lock operations in cw1200_config
Dmitry Tarnyagin
dmitry.tarnyagin at stericsson.com
Wed Feb 29 14:14:42 UTC 2012
Invalid lock order was used in cw1200_config, leading to a deadlock
with scan. Proper order of lock operations if you need both scan
and config locks:
- down(&priv->scan.lock);
- mutex_lock(&priv->conf_mutex);
- do_something();
- mutex_unlock(&priv->conf_mutex);
- up(&priv->scan.lock);
ST-Ericsson ID: 375035
Change-Id: I1988fc061b014bd5d1ffe3ab739cb0fcb3590224
Signed-off-by: Dmitry Tarnyagin <dmitry.tarnyagin at stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/38121
Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski at tieto.com>
Tested-by: Bartosz MARKOWSKI <bartosz.markowski at tieto.com>
---
drivers/staging/cw1200/sta.c | 23 +++++++++--------------
1 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/drivers/staging/cw1200/sta.c b/drivers/staging/cw1200/sta.c
index 4b6aff5..0446a1a 100644
--- a/drivers/staging/cw1200/sta.c
+++ b/drivers/staging/cw1200/sta.c
@@ -251,6 +251,7 @@ int cw1200_config(struct ieee80211_hw *dev, u32 changed)
struct cw1200_common *priv = dev->priv;
struct ieee80211_conf *conf = &dev->conf;
+ down(&priv->scan.lock);
mutex_lock(&priv->conf_mutex);
/* TODO: IEEE80211_CONF_CHANGE_QOS */
if (changed & IEEE80211_CONF_CHANGE_POWER) {
@@ -272,12 +273,6 @@ int cw1200_config(struct ieee80211_hw *dev, u32 changed)
ret = WARN_ON(__cw1200_flush(priv, false));
if (!ret) {
- while(down_trylock(&priv->scan.lock)) {
- sta_printk(KERN_DEBUG "[STA] waiting, "
- "scan in progress.\n");
- msleep(100);
- }
-
ret = WARN_ON(wsm_switch_channel(priv, &channel));
if (!ret) {
ret = wait_event_timeout(
@@ -294,8 +289,6 @@ int cw1200_config(struct ieee80211_hw *dev, u32 changed)
ret = -ETIMEDOUT;
} else
wsm_unlock_tx(priv);
-
- up(&priv->scan.lock);
}
}
@@ -316,12 +309,9 @@ int cw1200_config(struct ieee80211_hw *dev, u32 changed)
priv->powersave_mode.fastPsmIdlePeriod =
conf->dynamic_ps_timeout << 1;
- if (priv->join_status == CW1200_JOIN_STATUS_STA && priv->bss_params.aid) {
- while (down_trylock(&priv->scan.lock))
- msleep(100);
+ if (priv->join_status == CW1200_JOIN_STATUS_STA &&
+ priv->bss_params.aid)
cw1200_set_pm(priv, &priv->powersave_mode);
- up(&priv->scan.lock);
- }
}
#if defined(CONFIG_CW1200_USE_STE_EXTENSIONS)
@@ -417,6 +407,7 @@ int cw1200_config(struct ieee80211_hw *dev, u32 changed)
/* WARN_ON(tx_policy_force_upload(priv)); */
}
mutex_unlock(&priv->conf_mutex);
+ up(&priv->scan.lock);
return ret;
}
@@ -1439,6 +1430,10 @@ int cw1200_set_uapsd_param(struct cw1200_common *priv,
static int cw1200_cancel_scan(struct cw1200_common *priv)
{
- /* STUB(); */
+ while (down_trylock(&priv->scan.lock)) {
+ priv->scan.req = NULL;
+ schedule();
+ }
+ up(&priv->scan.lock);
return 0;
}
--
1.7.8.3
More information about the kernel
mailing list