diff options
author | Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> | 2011-08-23 11:02:47 +0200 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:06:27 +0200 |
commit | 23f9adb012bcb4258d3c96fd3b364b92730b8a36 (patch) | |
tree | 6c0a26d1a60c047f55ff2a4969300859e8168f82 /drivers/staging | |
parent | 05cb169377de26ef5209b061f7f7760a62d428b5 (diff) |
cw1200: Force unjoin on scan if association is not completed.
Firmware behaves strange if scan request is sent when device
is joined but association is not completed.
Patch detects this condition and forces unjoin request to the
device.
ST-Ericsson ID: 356953
Change-Id: I9df66365d46e2d9b65990dfc54ad22604e3a3daa
Signed-off-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/29403
Tested-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com>
Reviewed-by: QATEST
Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33517
Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/cw1200/scan.c | 51 | ||||
-rw-r--r-- | drivers/staging/cw1200/scan.h | 1 |
2 files changed, 34 insertions, 18 deletions
diff --git a/drivers/staging/cw1200/scan.c b/drivers/staging/cw1200/scan.c index 4daf4e2daa2..c9210e57397 100644 --- a/drivers/staging/cw1200/scan.c +++ b/drivers/staging/cw1200/scan.c @@ -93,21 +93,12 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, wsm_lock_tx(priv); - if (priv->join_status == CW1200_JOIN_STATUS_STA && - !(priv->powersave_mode.pmMode & WSM_PSM_PS)) { - struct wsm_set_pm pm = priv->powersave_mode; - pm.pmMode = WSM_PSM_PS; - wsm_set_pm(priv, &pm); - } else if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) { - /* FW bug: driver has to restart p2p-dev mode after scan */ - cw1200_disable_listening(priv); - } - BUG_ON(priv->scan.req); priv->scan.req = req; priv->scan.n_ssids = 0; priv->scan.status = 0; priv->scan.begin = &req->channels[0]; + priv->scan.curr = priv->scan.begin; priv->scan.end = &req->channels[req->n_channels]; priv->scan.output_power = priv->output_power; @@ -124,6 +115,7 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, } mutex_unlock(&priv->conf_mutex); + if (frame.skb) dev_kfree_skb(frame.skb); queue_work(priv->workqueue, &priv->scan.work); @@ -139,11 +131,34 @@ void cw1200_scan_work(struct work_struct *work) .scanType = WSM_SCAN_TYPE_FOREGROUND, .scanFlags = WSM_SCAN_FLAG_SPLIT_METHOD, }; + bool first_run = priv->scan.begin == priv->scan.curr && + priv->scan.begin != priv->scan.end; int i; + if (first_run) { + /* Firmware gets crazy if scan request is sent + * when STA is joined but not yet associated. + * Force unjoin in this case. */ + if (cancel_delayed_work_sync(&priv->join_timeout) > 0) + cw1200_join_timeout(&priv->join_timeout.work); + } + mutex_lock(&priv->conf_mutex); - if (!priv->scan.req || (priv->scan.begin == priv->scan.end)) { + if (first_run) { + if (priv->join_status == CW1200_JOIN_STATUS_STA && + !(priv->powersave_mode.pmMode & WSM_PSM_PS)) { + struct wsm_set_pm pm = priv->powersave_mode; + pm.pmMode = WSM_PSM_PS; + wsm_set_pm(priv, &pm); + } else if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) { + /* FW bug: driver has to restart p2p-dev mode + * after scan */ + cw1200_disable_listening(priv); + } + } + + if (!priv->scan.req || (priv->scan.curr == priv->scan.end)) { if (priv->scan.output_power != priv->output_power) WARN_ON(wsm_set_output_power(priv, priv->output_power * 10)); @@ -166,8 +181,8 @@ void cw1200_scan_work(struct work_struct *work) up(&priv->scan.lock); return; } else { - struct ieee80211_channel *first = *priv->scan.begin; - for (it = priv->scan.begin + 1, i = 1; + struct ieee80211_channel *first = *priv->scan.curr; + for (it = priv->scan.curr + 1, i = 1; it != priv->scan.end && i < WSM_SCAN_MAX_NUM_OF_CHANNELS; ++it, ++i) { if ((*it)->band != first->band) @@ -187,7 +202,7 @@ void cw1200_scan_work(struct work_struct *work) (first->flags & IEEE80211_CHAN_PASSIVE_SCAN) ? 0 : 2; scan.numOfSSIDs = priv->scan.n_ssids; scan.ssids = &priv->scan.ssids[0]; - scan.numOfChannels = it - priv->scan.begin; + scan.numOfChannels = it - priv->scan.curr; /* TODO: Is it optimal? */ scan.probeDelay = 100; /* It is not stated in WSM specification, however @@ -196,14 +211,14 @@ void cw1200_scan_work(struct work_struct *work) if (priv->join_status == CW1200_JOIN_STATUS_STA) scan.scanType = WSM_SCAN_TYPE_BACKGROUND; scan.ch = kzalloc( - sizeof(struct wsm_scan_ch[it - priv->scan.begin]), + sizeof(struct wsm_scan_ch[it - priv->scan.curr]), GFP_KERNEL); if (!scan.ch) { priv->scan.status = -ENOMEM; goto fail; } for (i = 0; i < scan.numOfChannels; ++i) { - scan.ch[i].number = priv->scan.begin[i]->hw_value; + scan.ch[i].number = priv->scan.curr[i]->hw_value; scan.ch[i].minChannelTime = 50; scan.ch[i].maxChannelTime = 110; } @@ -217,13 +232,13 @@ void cw1200_scan_work(struct work_struct *work) kfree(scan.ch); if (WARN_ON(priv->scan.status)) goto fail; - priv->scan.begin = it; + priv->scan.curr = it; } mutex_unlock(&priv->conf_mutex); return; fail: - priv->scan.begin = priv->scan.end; + priv->scan.curr = priv->scan.end; mutex_unlock(&priv->conf_mutex); queue_work(priv->workqueue, &priv->scan.work); return; diff --git a/drivers/staging/cw1200/scan.h b/drivers/staging/cw1200/scan.h index 3e7f6a42d6c..f2ea372aad7 100644 --- a/drivers/staging/cw1200/scan.h +++ b/drivers/staging/cw1200/scan.h @@ -27,6 +27,7 @@ struct cw1200_scan { struct delayed_work timeout; struct cfg80211_scan_request *req; struct ieee80211_channel **begin; + struct ieee80211_channel **curr; struct ieee80211_channel **end; struct wsm_ssid ssids[WSM_SCAN_MAX_NUM_OF_SSIDS]; u8 *ie; |