summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorWei Ni <wni@nvidia.com>2012-10-11 17:35:02 +0800
committerMrutyunjay Sawant <msawant@nvidia.com>2012-10-16 04:29:59 -0700
commit4ffe2cabbc00d9d12a3884178e3f85aa9f66804c (patch)
treee2aed48489b53e5b5a10ae771c3e33fcba605b20 /net
parentd8878060996204b616ae6810ead88c2ab8d1aa9a (diff)
mac80211&nl80211: support to abort a scan request on tx
mac80211 & nl80211: add support to abort a scan request on tx The original issue is the chromium issue: http://code.google.com/p/chromium-os/issues/detail?id=11485 This fix comes from: https://gerrit.chromium.org/gerrit/#change,5744 https://gerrit.chromium.org/gerrit/#change,5745 This change will not affect android/l4t. Add this changes, so that we can support ChromeOs and Android both. Change-Id: I8a98efcaa706952dd3f3d9872f26138d432d7b0c Signed-off-by: Wei Ni <wni@nvidia.com> Reviewed-on: http://git-master/r/143538 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Rhyland Klein <rklein@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/scan.c36
-rw-r--r--net/wireless/nl80211.c7
3 files changed, 43 insertions, 6 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index db8fae51714c..3c143b4ed1e1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -808,6 +808,10 @@ enum {
* @SCAN_SUSPEND: Suspend the scan and go back to operating channel to
* send out data
* @SCAN_RESUME: Resume the scan and scan the next channel
+ * @SCAN_ABORT: Abnormally terminate the scan operation, set only when
+ * on the operating channel
+ * @SCAN_SUSPEND_ABORT: Return to the operating channel then
+ * terminate the scan operation
*/
enum mac80211_scan_state {
SCAN_DECISION,
@@ -815,6 +819,8 @@ enum mac80211_scan_state {
SCAN_SEND_PROBE,
SCAN_SUSPEND,
SCAN_RESUME,
+ SCAN_ABORT,
+ SCAN_SUSPEND_ABORT,
};
struct ieee80211_local {
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index c70e17677135..7d61c8acfaa3 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -487,6 +487,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
unsigned long min_beacon_int = 0;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_channel *next_chan;
+ enum mac80211_scan_state next_scan_state;
/*
* check if at least one STA interface is associated,
@@ -545,10 +546,24 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
usecs_to_jiffies(min_beacon_int * 1024) *
local->hw.conf.listen_interval);
- if (associated && (!tx_empty || bad_latency || listen_int_exceeded))
- local->next_scan_state = SCAN_SUSPEND;
+ if (associated && !tx_empty) {
+ if (unlikely(local->scan_req->flags &
+ CFG80211_SCAN_FLAG_TX_ABORT)) {
+ /*
+ * Scan request is marked to abort when there
+ * is outbound traffic. Mark state to return
+ * the operating channel and then abort. This
+ * happens as soon as possible.
+ */
+ next_scan_state = SCAN_SUSPEND_ABORT;
+ } else
+ next_scan_state = SCAN_SUSPEND;
+ } else if (associated && (bad_latency || listen_int_exceeded))
+ next_scan_state = SCAN_SUSPEND;
else
- local->next_scan_state = SCAN_SET_CHANNEL;
+ next_scan_state = SCAN_SET_CHANNEL;
+
+ local->next_scan_state = next_scan_state;
*next_delay = 0;
}
@@ -636,9 +651,14 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
*/
ieee80211_offchannel_return(local, false);
- *next_delay = HZ / 5;
- /* afterwards, resume scan & go to next channel */
- local->next_scan_state = SCAN_RESUME;
+ if (local->next_scan_state == SCAN_SUSPEND) {
+ *next_delay = HZ / 5;
+ /* afterwards, resume scan & go to next channel */
+ local->next_scan_state = SCAN_RESUME;
+ } else {
+ *next_delay = 0;
+ local->next_scan_state = SCAN_ABORT;
+ }
}
static void ieee80211_scan_state_resume(struct ieee80211_local *local,
@@ -731,11 +751,15 @@ void ieee80211_scan_work(struct work_struct *work)
ieee80211_scan_state_send_probe(local, &next_delay);
break;
case SCAN_SUSPEND:
+ case SCAN_SUSPEND_ABORT:
ieee80211_scan_state_suspend(local, &next_delay);
break;
case SCAN_RESUME:
ieee80211_scan_state_resume(local, &next_delay);
break;
+ case SCAN_ABORT:
+ aborted = true;
+ goto out_complete;
}
} while (next_delay == 0);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e0e655b4b80a..22b74e7f217d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -136,6 +136,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
[NL80211_ATTR_IE] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_DATA_LEN },
+ [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
[NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
[NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
@@ -3867,6 +3868,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->no_cck =
nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
+ if (info->attrs[NL80211_ATTR_SCAN_FLAGS])
+ request->flags = nla_get_u32(
+ info->attrs[NL80211_ATTR_SCAN_FLAGS]);
+
request->dev = dev;
request->wiphy = &rdev->wiphy;
@@ -6923,6 +6928,8 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
if (req->ie)
NLA_PUT(msg, NL80211_ATTR_IE, req->ie_len, req->ie);
+ NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags);
+
return 0;
nla_put_failure:
return -ENOBUFS;