diff options
author | Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> | 2012-02-29 15:14:42 +0100 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:06:41 +0200 |
commit | 02bbad9ebac15c873138ca0401a80eb0afad660c (patch) | |
tree | 7beb5e6535be8787a81eef187598cb390fe38f64 | |
parent | 12f4378b06d2532e46445c501e9fb99e4f9e5b82 (diff) |
cw1200: fix for wrong order of lock operations in cw1200_config
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@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/38121
Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com>
Tested-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com>
-rw-r--r-- | 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 6c79880900b..f3c42f35d7a 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; } @@ -1438,6 +1429,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; } |