From e3f5d16120f5118e2f86f1f88deaa69e6843b31f Mon Sep 17 00:00:00 2001
From: Javier Cardona <javier@cozybit.com>
Date: Fri, 8 Jun 2012 13:30:24 -0700
Subject: mac80211: Remove unused variable

Signed-off-by: Javier Cardona <javier@cozybit.com>
Reviewed-by: Jason Abele <jason@cozybit.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mesh_hwmp.c | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index fa7c58035246..acbd1ad8eb33 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -323,7 +323,6 @@ void ieee80211s_update_metric(struct ieee80211_local *local,
 static u32 airtime_link_metric_get(struct ieee80211_local *local,
 				   struct sta_info *sta)
 {
-	struct ieee80211_supported_band *sband;
 	struct rate_info rinfo;
 	/* This should be adjusted for each device */
 	int device_constant = 1 << ARITH_SHIFT;
@@ -333,8 +332,6 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
 	u32 tx_time, estimated_retx;
 	u64 result;
 
-	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
 	if (sta->fail_avg >= 100)
 		return MAX_METRIC;
 
-- 
cgit v1.2.2


From 35b3fe1caa26e1ffc5144d3faadecdfa0a8a0f44 Mon Sep 17 00:00:00 2001
From: Javier Cardona <javier@cozybit.com>
Date: Fri, 8 Jun 2012 13:30:25 -0700
Subject: mac80211: Rename stainfo variable for the more common sta

Signed-off-by: Javier Cardona <javier@cozybit.com>
Reviewed-by: Jason Abele <jason@cozybit.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mesh.h      | 2 +-
 net/mac80211/mesh_hwmp.c | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index e3642756f8f4..c7400a23b64b 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -245,7 +245,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
 int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
 void ieee80211s_init(void);
 void ieee80211s_update_metric(struct ieee80211_local *local,
-		struct sta_info *stainfo, struct sk_buff *skb);
+		struct sta_info *sta, struct sk_buff *skb);
 void ieee80211s_stop(void);
 void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
 void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index acbd1ad8eb33..9b6da2de660d 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -303,7 +303,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
 }
 
 void ieee80211s_update_metric(struct ieee80211_local *local,
-		struct sta_info *stainfo, struct sk_buff *skb)
+		struct sta_info *sta, struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -315,9 +315,9 @@ void ieee80211s_update_metric(struct ieee80211_local *local,
 	failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
 
 	/* moving average, scaled to 100 */
-	stainfo->fail_avg = ((80 * stainfo->fail_avg + 5) / 100 + 20 * failed);
-	if (stainfo->fail_avg > 95)
-		mesh_plink_broken(stainfo);
+	sta->fail_avg = ((80 * sta->fail_avg + 5) / 100 + 20 * failed);
+	if (sta->fail_avg > 95)
+		mesh_plink_broken(sta);
 }
 
 static u32 airtime_link_metric_get(struct ieee80211_local *local,
-- 
cgit v1.2.2


From a4f606ea73d56d15f28653d2242e54d58bb612e5 Mon Sep 17 00:00:00 2001
From: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Date: Mon, 11 Jun 2012 11:59:36 +0800
Subject: {nl,cfg,mac}80211: fix the coding style related to mesh parameters

fix the coding style related to mesh parameters, especially the indentation,
as pointed out by Johannes Berg.

Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c            |  3 +--
 net/mac80211/debugfs_netdev.c | 34 +++++++++++++++++-----------------
 2 files changed, 18 insertions(+), 19 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 498c94e34427..f41f9bea242a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1571,10 +1571,9 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
 		conf->dot11MeshGateAnnouncementProtocol =
 			nconf->dot11MeshGateAnnouncementProtocol;
 	}
-	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) {
+	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask))
 		conf->dot11MeshHWMPRannInterval =
 			nconf->dot11MeshHWMPRannInterval;
-	}
 	if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask))
 		conf->dot11MeshForwarding = nconf->dot11MeshForwarding;
 	if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) {
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index d4272ff43f71..c429417e1322 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -468,45 +468,45 @@ IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
 IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
 IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
 IEEE80211_IF_FILE(dropped_frames_congestion,
-		u.mesh.mshstats.dropped_frames_congestion, DEC);
+		  u.mesh.mshstats.dropped_frames_congestion, DEC);
 IEEE80211_IF_FILE(dropped_frames_no_route,
-		u.mesh.mshstats.dropped_frames_no_route, DEC);
+		  u.mesh.mshstats.dropped_frames_no_route, DEC);
 IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC);
 
 /* Mesh parameters */
 IEEE80211_IF_FILE(dot11MeshMaxRetries,
-		u.mesh.mshcfg.dot11MeshMaxRetries, DEC);
+		  u.mesh.mshcfg.dot11MeshMaxRetries, DEC);
 IEEE80211_IF_FILE(dot11MeshRetryTimeout,
-		u.mesh.mshcfg.dot11MeshRetryTimeout, DEC);
+		  u.mesh.mshcfg.dot11MeshRetryTimeout, DEC);
 IEEE80211_IF_FILE(dot11MeshConfirmTimeout,
-		u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC);
+		  u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC);
 IEEE80211_IF_FILE(dot11MeshHoldingTimeout,
-		u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC);
+		  u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC);
 IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC);
 IEEE80211_IF_FILE(element_ttl, u.mesh.mshcfg.element_ttl, DEC);
 IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC);
 IEEE80211_IF_FILE(dot11MeshMaxPeerLinks,
-		u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC);
+		  u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC);
 IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout,
-		u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC);
+		  u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC);
 IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval,
-		u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC);
+		  u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC);
 IEEE80211_IF_FILE(dot11MeshHWMPperrMinInterval,
-		u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC);
+		  u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC);
 IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime,
-		u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC);
+		  u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC);
 IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries,
-		u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC);
+		  u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC);
 IEEE80211_IF_FILE(path_refresh_time,
-		u.mesh.mshcfg.path_refresh_time, DEC);
+		  u.mesh.mshcfg.path_refresh_time, DEC);
 IEEE80211_IF_FILE(min_discovery_timeout,
-		u.mesh.mshcfg.min_discovery_timeout, DEC);
+		  u.mesh.mshcfg.min_discovery_timeout, DEC);
 IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
-		u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
+		  u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
 IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol,
-		u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC);
+		  u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC);
 IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
-		u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
+		  u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
 IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
 IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
 IEEE80211_IF_FILE(ht_opmode, u.mesh.mshcfg.ht_opmode, DEC);
-- 
cgit v1.2.2


From cef28271be62e672637f1ba2a019a5a9a981eb2d Mon Sep 17 00:00:00 2001
From: Johannes Berg <johannes.berg@intel.com>
Date: Mon, 11 Jun 2012 11:34:18 +0200
Subject: mac80211: remove unneeded ieee80211_run_deferred_scan()

Ilan pointed out to me that ieee80211_start_next_roc()
already calls ieee80211_run_deferred_scan() if the list
of ROC items is empty, so there's no need to call it
again after calling ieee80211_start_next_roc().

Reported-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c        | 1 -
 net/mac80211/offchannel.c | 5 -----
 2 files changed, 6 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index f41f9bea242a..93d203cf8c12 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2330,7 +2330,6 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
 
 		list_del(&found->list);
 
-		ieee80211_run_deferred_scan(local);
 		ieee80211_start_next_roc(local);
 		mutex_unlock(&local->mtx);
 
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index abb226dc4753..fcb01ee8ee7b 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -379,7 +379,6 @@ void ieee80211_sw_roc_work(struct work_struct *work)
 		ieee80211_recalc_idle(local);
 
 		ieee80211_start_next_roc(local);
-		ieee80211_run_deferred_scan(local);
 	}
 
  out_unlock:
@@ -410,9 +409,6 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
 	/* if there's another roc, start it now */
 	ieee80211_start_next_roc(local);
 
-	/* or scan maybe */
-	ieee80211_run_deferred_scan(local);
-
  out_unlock:
 	mutex_unlock(&local->mtx);
 }
@@ -455,7 +451,6 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
 	}
 
 	ieee80211_start_next_roc(local);
-	ieee80211_run_deferred_scan(local);
 	mutex_unlock(&local->mtx);
 
 	list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
-- 
cgit v1.2.2


From e979e33c3972044e1be5e46552a02c3b9c0bc7a7 Mon Sep 17 00:00:00 2001
From: Johannes Berg <johannes.berg@intel.com>
Date: Mon, 11 Jun 2012 17:09:41 +0200
Subject: mac80211: allow cancelling dependent ROCs

In my redesign of remain-on-channel I forgot
that an item could be cancelled when it's a
dependent item that is part of another item.
Allow cancelling such items by removing them
from the dependents list.

Note that when we cancel the main item, all
its dependents are also cancelled. It would
be possible to not do that, but would need
tricks to promote an item from dependent to
top-level and is tricky in the HW ROC case.

Reported-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

(limited to 'net/mac80211')

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 93d203cf8c12..9a974579ba89 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2305,6 +2305,21 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
 
 	mutex_lock(&local->mtx);
 	list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
+		struct ieee80211_roc_work *dep, *tmp2;
+
+		list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) {
+			if (!mgmt_tx && (unsigned long)dep != cookie)
+				continue;
+			else if (mgmt_tx && dep->mgmt_tx_cookie != cookie)
+				continue;
+			/* found dependent item -- just remove it */
+			list_del(&dep->list);
+			mutex_unlock(&local->mtx);
+
+			ieee80211_roc_notify_destroy(dep);
+			return 0;
+		}
+
 		if (!mgmt_tx && (unsigned long)roc != cookie)
 			continue;
 		else if (mgmt_tx && roc->mgmt_tx_cookie != cookie)
@@ -2319,6 +2334,13 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
 		return -ENOENT;
 	}
 
+	/*
+	 * We found the item to cancel, so do that. Note that it
+	 * may have dependents, which we also cancel (and send
+	 * the expired signal for.) Not doing so would be quite
+	 * tricky here, but we may need to fix it later.
+	 */
+
 	if (local->ops->remain_on_channel) {
 		if (found->started) {
 			ret = drv_cancel_remain_on_channel(local);
-- 
cgit v1.2.2


From ac4d82fa01c194dba10b9a7c35449ba36eb642fc Mon Sep 17 00:00:00 2001
From: Pontus Fuchs <pontus.fuchs@gmail.com>
Date: Tue, 12 Jun 2012 14:13:19 +0200
Subject: mac80211: Disallow changing chan type on monitor when CHAN_MODE_FIXED

If you add a monitor interface in parallel to a normal interface
mac80211 will let you to change the channel type on the monitor
interface even if you are connected. Add an explicit check to
disallow this.

Signed-off-by: Pontus Fuchs <pontus.fuchs@gmail.com>
[fix typo in commit log, use sdata instead of netdev]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 9a974579ba89..cd8b1fb05d42 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -689,7 +689,8 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
 	case CHAN_MODE_HOPPING:
 		return -EBUSY;
 	case CHAN_MODE_FIXED:
-		if (local->oper_channel != chan)
+		if (local->oper_channel != chan ||
+		    (!sdata && local->_oper_channel_type != channel_type))
 			return -EBUSY;
 		if (!sdata && local->_oper_channel_type == channel_type)
 			return 0;
-- 
cgit v1.2.2


From ac1073a61d73b6277794d2efc872eb7e1b706b5c Mon Sep 17 00:00:00 2001
From: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Date: Thu, 14 Jun 2012 02:06:06 +0800
Subject: {nl,cfg,mac}80211: implement dot11MeshHWMProotInterval and
 dot11MeshHWMPactivePathToRootTimeout

Add the mesh configuration parameters dot11MeshHWMProotInterval
and dot11MeshHWMPactivePathToRootTimeout to be used by
proactive PREQ mechanism.

Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
[line-break commit log]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c            | 6 ++++++
 net/mac80211/debugfs_netdev.c | 6 ++++++
 2 files changed, 12 insertions(+)

(limited to 'net/mac80211')

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index cd8b1fb05d42..d93cda1c4215 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1590,6 +1590,12 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
 		sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode;
 		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
 	}
+	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, mask))
+		conf->dot11MeshHWMPactivePathToRootTimeout =
+			nconf->dot11MeshHWMPactivePathToRootTimeout;
+	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ROOT_INTERVAL, mask))
+		conf->dot11MeshHWMProotInterval =
+			nconf->dot11MeshHWMProotInterval;
 	return 0;
 }
 
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index c429417e1322..a8cea70902e4 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -510,6 +510,10 @@ IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
 IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
 IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
 IEEE80211_IF_FILE(ht_opmode, u.mesh.mshcfg.ht_opmode, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMPactivePathToRootTimeout,
+		  u.mesh.mshcfg.dot11MeshHWMPactivePathToRootTimeout, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMProotInterval,
+		  u.mesh.mshcfg.dot11MeshHWMProotInterval, DEC);
 #endif
 
 #define DEBUGFS_ADD_MODE(name, mode) \
@@ -611,6 +615,8 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
 	MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
 	MESHPARAMS_ADD(rssi_threshold);
 	MESHPARAMS_ADD(ht_opmode);
+	MESHPARAMS_ADD(dot11MeshHWMPactivePathToRootTimeout);
+	MESHPARAMS_ADD(dot11MeshHWMProotInterval);
 #undef MESHPARAMS_ADD
 }
 #endif
-- 
cgit v1.2.2


From a69cc44fe9ebb806c5f3f8bd83fb4a50ca63647b Mon Sep 17 00:00:00 2001
From: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Date: Thu, 14 Jun 2012 02:06:07 +0800
Subject: mac80211: implement the proactive PREQ generation

Generate the proactive PREQ element as defined in
Sec. 13.10.9.3 (Case C) of IEEE Std. 802.11-2012
based on the selection of dot11MeshHWMPRootMode as follow:
dot11MeshHWMPRootMode (2) is proactivePREQnoPREP
dot11MeshHWMPRootMode (3) is proactivePREQwithPREP

The proactive PREQ is generated based on the interval
defined by dot11MeshHWMProotInterval.

With this change, proactive RANN element is now generated
if the dot11MeshHWMPRootMode is set to (4) instead of (1).

Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
[line-break commit log]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mesh.c      | 10 ++++++++--
 net/mac80211/mesh_hwmp.c | 27 ++++++++++++++++++++++++---
 2 files changed, 32 insertions(+), 5 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 7cf19509fb68..6bff3c4d17dd 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -541,11 +541,17 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
 static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+	u32 interval;
 
 	mesh_path_tx_root_frame(sdata);
+
+	if (ifmsh->mshcfg.dot11MeshHWMPRootMode == IEEE80211_PROACTIVE_RANN)
+		interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
+	else
+		interval = ifmsh->mshcfg.dot11MeshHWMProotInterval;
+
 	mod_timer(&ifmsh->mesh_path_root_timer,
-		  round_jiffies(TU_TO_EXP_TIME(
-				  ifmsh->mshcfg.dot11MeshHWMPRannInterval)));
+		  round_jiffies(TU_TO_EXP_TIME(interval)));
 }
 
 #ifdef CONFIG_PM
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 9b6da2de660d..a6b08f5c4612 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -1154,13 +1154,34 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 	u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
-	u8 flags;
+	u8 flags, target_flags = 0;
 
 	flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol)
 			? RANN_FLAG_IS_GATE : 0;
-	mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
+
+	switch (ifmsh->mshcfg.dot11MeshHWMPRootMode) {
+	case IEEE80211_PROACTIVE_RANN:
+		mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
 			       cpu_to_le32(++ifmsh->sn),
 			       0, NULL, 0, broadcast_addr,
-			       0, sdata->u.mesh.mshcfg.element_ttl,
+			       0, ifmsh->mshcfg.element_ttl,
 			       cpu_to_le32(interval), 0, 0, sdata);
+		break;
+	case IEEE80211_PROACTIVE_PREQ_WITH_PREP:
+		flags |= IEEE80211_PREQ_PROACTIVE_PREP_FLAG;
+	case IEEE80211_PROACTIVE_PREQ_NO_PREP:
+		interval = ifmsh->mshcfg.dot11MeshHWMPactivePathToRootTimeout;
+		target_flags |= IEEE80211_PREQ_TO_FLAG |
+				IEEE80211_PREQ_USN_FLAG;
+		mesh_path_sel_frame_tx(MPATH_PREQ, flags, sdata->vif.addr,
+				cpu_to_le32(++ifmsh->sn), target_flags,
+				(u8 *) broadcast_addr, 0, broadcast_addr,
+				0, ifmsh->mshcfg.element_ttl,
+				cpu_to_le32(interval),
+				0, cpu_to_le32(ifmsh->preq_id++), sdata);
+		break;
+	default:
+		mhwmp_dbg("Proactive mechanism not supported");
+		return;
+	}
 }
-- 
cgit v1.2.2


From 3fbf4b71be81e6dd3d6bfbcdef9618628ee1bafe Mon Sep 17 00:00:00 2001
From: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Date: Sun, 17 Jun 2012 02:27:40 +0800
Subject: mac80211: implement the proactive PREP generation

Generate the proactive PREP element in Proactive PREQ mode as
defined in Sec. 13.10.10.3 (Case D) of IEEE Std. 802.11-2012.

Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mesh_hwmp.c | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index a6b08f5c4612..35e3acbe2262 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -516,10 +516,11 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 	struct mesh_path *mpath = NULL;
 	u8 *target_addr, *orig_addr;
 	const u8 *da;
-	u8 target_flags, ttl;
-	u32 orig_sn, target_sn, lifetime;
+	u8 target_flags, ttl, flags;
+	u32 orig_sn, target_sn, lifetime, orig_metric;
 	bool reply = false;
 	bool forward = true;
+	bool root_is_gate;
 
 	/* Update target SN, if present */
 	target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
@@ -527,6 +528,10 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 	target_sn = PREQ_IE_TARGET_SN(preq_elem);
 	orig_sn = PREQ_IE_ORIG_SN(preq_elem);
 	target_flags = PREQ_IE_TARGET_F(preq_elem);
+	orig_metric = metric;
+	/* Proactive PREQ gate announcements */
+	flags = PREQ_IE_FLAGS(preq_elem);
+	root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
 
 	mhwmp_dbg("received PREQ from %pM", orig_addr);
 
@@ -541,6 +546,22 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 			target_sn = ++ifmsh->sn;
 			ifmsh->last_sn_update = jiffies;
 		}
+	} else if (is_broadcast_ether_addr(target_addr) &&
+		   (target_flags & IEEE80211_PREQ_TO_FLAG)) {
+		rcu_read_lock();
+		mpath = mesh_path_lookup(orig_addr, sdata);
+		if (mpath) {
+			if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
+				reply = true;
+				target_addr = sdata->vif.addr;
+				target_sn = ++ifmsh->sn;
+				metric = 0;
+				ifmsh->last_sn_update = jiffies;
+			}
+			if (root_is_gate)
+				mesh_path_add_gate(mpath);
+		}
+		rcu_read_unlock();
 	} else {
 		rcu_read_lock();
 		mpath = mesh_path_lookup(target_addr, sdata);
@@ -573,13 +594,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 				cpu_to_le32(target_sn), mgmt->sa, 0, ttl,
 				cpu_to_le32(lifetime), cpu_to_le32(metric),
 				0, sdata);
-		} else
+		} else {
 			ifmsh->mshstats.dropped_frames_ttl++;
+		}
 	}
 
 	if (forward && ifmsh->mshcfg.dot11MeshForwarding) {
 		u32 preq_id;
-		u8 hopcount, flags;
+		u8 hopcount;
 
 		ttl = PREQ_IE_TTL(preq_elem);
 		lifetime = PREQ_IE_LIFETIME(preq_elem);
@@ -589,11 +611,17 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 		}
 		mhwmp_dbg("forwarding the PREQ from %pM", orig_addr);
 		--ttl;
-		flags = PREQ_IE_FLAGS(preq_elem);
 		preq_id = PREQ_IE_PREQ_ID(preq_elem);
 		hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
 		da = (mpath && mpath->is_root) ?
 			mpath->rann_snd_addr : broadcast_addr;
+
+		if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
+			target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
+			target_sn = PREQ_IE_TARGET_SN(preq_elem);
+			metric = orig_metric;
+		}
+
 		mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
 				cpu_to_le32(orig_sn), target_flags, target_addr,
 				cpu_to_le32(target_sn), da,
-- 
cgit v1.2.2


From dbb912cd4ce64e763c5610b49a85529d2634e9d8 Mon Sep 17 00:00:00 2001
From: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Date: Thu, 14 Jun 2012 02:06:09 +0800
Subject: mac80211: invoke the timer only with correct dot11MeshHWMPRootMode
 value

mesh_path_root_timer is invoked once the dot11MeshHWMPRootMode
is larger than 1. This patch also adds the backward compatible
to the previous setting on dot11MeshHWMPRootMode. If the user
configures as follow, it will still trigger the proactive RANN
with Gate Announcement.

iw mesh0 set mesh_param mesh_hwmp_rootmode 1
iw mesh0 set mesh_param mesh_gate_announcements 1

similar to the following setting:

iw mesh0 set mesh_param mesh_hwmp_rootmode 4
iw mesh0 set mesh_param mesh_gate_announcements 1

Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
[line-break commit log]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c  | 4 ++--
 net/mac80211/mesh.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d93cda1c4215..5bd316c0a63d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1565,8 +1565,8 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
 		 * announcements, so require this ifmsh to also be a root node
 		 * */
 		if (nconf->dot11MeshGateAnnouncementProtocol &&
-		    !conf->dot11MeshHWMPRootMode) {
-			conf->dot11MeshHWMPRootMode = 1;
+		    !(conf->dot11MeshHWMPRootMode > IEEE80211_ROOTMODE_ROOT)) {
+			conf->dot11MeshHWMPRootMode = IEEE80211_PROACTIVE_RANN;
 			ieee80211_mesh_root_setup(ifmsh);
 		}
 		conf->dot11MeshGateAnnouncementProtocol =
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 6bff3c4d17dd..ae40a83675e9 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -443,7 +443,7 @@ static void ieee80211_mesh_path_root_timer(unsigned long data)
 
 void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
 {
-	if (ifmsh->mshcfg.dot11MeshHWMPRootMode)
+	if (ifmsh->mshcfg.dot11MeshHWMPRootMode > IEEE80211_ROOTMODE_ROOT)
 		set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
 	else {
 		clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
-- 
cgit v1.2.2


From 728b19e5fb9bbebbd580784a092b786fe379ed8e Mon Sep 17 00:00:00 2001
From: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Date: Thu, 14 Jun 2012 02:06:10 +0800
Subject: {nl,cfg,mac}80211: implement dot11MeshHWMPconfirmationInterval

As defined in section 13.10.9.3 Case D (802.11-2012), this
control variable is used to limit the mesh STA to send only
one PREQ to a root mesh STA within this interval of time
(in TUs). The default value for this variable is set to
2000 TUs. However, for current implementation, the maximum
configurable of dot11MeshHWMPconfirmationInterval is
restricted by dot11MeshHWMPactivePathTimeout.

Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
[line-break commit log]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c            | 3 +++
 net/mac80211/debugfs_netdev.c | 3 +++
 net/mac80211/mesh.h           | 2 ++
 net/mac80211/mesh_hwmp.c      | 7 ++++++-
 4 files changed, 14 insertions(+), 1 deletion(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5bd316c0a63d..6e25ac4873c7 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1596,6 +1596,9 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
 	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ROOT_INTERVAL, mask))
 		conf->dot11MeshHWMProotInterval =
 			nconf->dot11MeshHWMProotInterval;
+	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, mask))
+		conf->dot11MeshHWMPconfirmationInterval =
+			nconf->dot11MeshHWMPconfirmationInterval;
 	return 0;
 }
 
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index a8cea70902e4..512c894893d6 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -514,6 +514,8 @@ IEEE80211_IF_FILE(dot11MeshHWMPactivePathToRootTimeout,
 		  u.mesh.mshcfg.dot11MeshHWMPactivePathToRootTimeout, DEC);
 IEEE80211_IF_FILE(dot11MeshHWMProotInterval,
 		  u.mesh.mshcfg.dot11MeshHWMProotInterval, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMPconfirmationInterval,
+		  u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval, DEC);
 #endif
 
 #define DEBUGFS_ADD_MODE(name, mode) \
@@ -617,6 +619,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
 	MESHPARAMS_ADD(ht_opmode);
 	MESHPARAMS_ADD(dot11MeshHWMPactivePathToRootTimeout);
 	MESHPARAMS_ADD(dot11MeshHWMProotInterval);
+	MESHPARAMS_ADD(dot11MeshHWMPconfirmationInterval);
 #undef MESHPARAMS_ADD
 }
 #endif
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index c7400a23b64b..faaa39bcfd10 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -104,6 +104,7 @@ enum mesh_deferred_task_flags {
  * an mpath to a hash bucket on a path table.
  * @rann_snd_addr: the RANN sender address
  * @rann_metric: the aggregated path metric towards the root node
+ * @last_preq_to_root: Timestamp of last PREQ sent to root
  * @is_root: the destination station of this path is a root node
  * @is_gate: the destination station of this path is a mesh gate
  *
@@ -131,6 +132,7 @@ struct mesh_path {
 	spinlock_t state_lock;
 	u8 rann_snd_addr[ETH_ALEN];
 	u32 rann_metric;
+	unsigned long last_preq_to_root;
 	bool is_root;
 	bool is_gate;
 };
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 35e3acbe2262..bea52479e3aa 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -98,6 +98,8 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
 #define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries)
 #define disc_timeout_jiff(s) \
 	msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout)
+#define root_path_confirmation_jiffies(s) \
+	msecs_to_jiffies(sdata->u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval)
 
 enum mpath_frame_type {
 	MPATH_PREQ = 0,
@@ -811,11 +813,14 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
 	}
 
 	if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) ||
-	     time_after(jiffies, mpath->exp_time - 1*HZ)) &&
+	     (time_after(jiffies, mpath->last_preq_to_root +
+				  root_path_confirmation_jiffies(sdata)) ||
+	     time_before(jiffies, mpath->last_preq_to_root))) &&
 	     !(mpath->flags & MESH_PATH_FIXED)) {
 		mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name,
 							       orig_addr);
 		mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
+		mpath->last_preq_to_root = jiffies;
 	}
 
 	if ((SN_LT(mpath->sn, orig_sn) || (mpath->sn == orig_sn &&
-- 
cgit v1.2.2


From 58886a9011f8eae705b9f585ec6c80b34f3c4e6c Mon Sep 17 00:00:00 2001
From: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Date: Fri, 15 Jun 2012 00:23:53 +0800
Subject: mac80211: fix the assignment of mesh element TTL

This patch fixes the wrong assignment of mesh element TTL.

Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6e25ac4873c7..17162fcc24bc 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1530,7 +1530,7 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
 	if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask))
 		conf->dot11MeshTTL = nconf->dot11MeshTTL;
 	if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask))
-		conf->dot11MeshTTL = nconf->element_ttl;
+		conf->element_ttl = nconf->element_ttl;
 	if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask))
 		conf->auto_open_plinks = nconf->auto_open_plinks;
 	if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask))
-- 
cgit v1.2.2


From 04800ada2acc3a9ffc754c1d73576cef326f3311 Mon Sep 17 00:00:00 2001
From: Arik Nemtsov <arik@wizery.com>
Date: Wed, 6 Jun 2012 11:25:02 +0300
Subject: mac80211: stop Rx during HW reconfig

While HW reconfig is in progress, drop all incoming Rx. This prevents
incoming packets from changing the internal state of the driver or
calling callbacks of the low level driver while it is in inconsistent
state.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ieee80211_i.h | 3 +++
 net/mac80211/main.c        | 7 +++++++
 net/mac80211/rx.c          | 4 ++++
 net/mac80211/util.c        | 3 +++
 4 files changed, 17 insertions(+)

(limited to 'net/mac80211')

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e6cbf5b68c89..ddf768f6350e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -881,6 +881,9 @@ struct ieee80211_local {
 	/* device is started */
 	bool started;
 
+	/* device is during a HW reconfig */
+	bool in_reconfig;
+
 	/* wowlan is enabled -- don't reconfig on resume */
 	bool wowlan;
 
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index d81c178c7712..976e41365c25 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -345,6 +345,13 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
 	ieee80211_stop_queues_by_reason(hw,
 		IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
+	/*
+	 * Stop all Rx during the reconfig. We don't want state changes
+	 * or driver callbacks while this is in progress.
+	 */
+	local->in_reconfig = true;
+	barrier();
+
 	schedule_work(&local->restart_work);
 }
 EXPORT_SYMBOL(ieee80211_restart_hw);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6fd2cb0838c4..072e8f3afa2b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3027,6 +3027,10 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	if (unlikely(local->quiescing || local->suspended))
 		goto drop;
 
+	/* We might be during a HW reconfig, prevent Rx for the same reason */
+	if (unlikely(local->in_reconfig))
+		goto drop;
+
 	/*
 	 * The same happens when we're not even started,
 	 * but that's worth a warning.
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 1df4019f294b..242ecde381f6 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1411,6 +1411,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 		if (ieee80211_sdata_running(sdata))
 			ieee80211_enable_keys(sdata);
 
+	local->in_reconfig = false;
+	barrier();
+
  wake_up:
 	/*
 	 * Clear the WLAN_STA_BLOCK_BA flag so new aggregation
-- 
cgit v1.2.2


From d6a4ed6fe0a0d4790941e7f13e56630b8b9b053d Mon Sep 17 00:00:00 2001
From: Arik Nemtsov <arik@wizery.com>
Date: Mon, 18 Jun 2012 10:43:50 +0300
Subject: mac80211: set only VO as a U-APSD enabled AC

Some APs experience problems when working with U-APSD. Decrease the
probability of that happening by using legacy mode for all ACs but VO.

The AP that caused us troubles was a Cisco 4410N. It ignores our
setting, and always treats non-VO ACs as legacy.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ieee80211_i.h | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ddf768f6350e..34af2e5263c2 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -55,11 +55,14 @@ struct ieee80211_local;
 #define TU_TO_JIFFIES(x)	(usecs_to_jiffies((x) * 1024))
 #define TU_TO_EXP_TIME(x)	(jiffies + TU_TO_JIFFIES(x))
 
+/*
+ * Some APs experience problems when working with U-APSD. Decrease the
+ * probability of that happening by using legacy mode for all ACs but VO.
+ * The AP that caused us trouble was a Cisco 4410N. It ignores our
+ * setting, and always treats non-VO ACs as legacy.
+ */
 #define IEEE80211_DEFAULT_UAPSD_QUEUES \
-	(IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |	\
-	 IEEE80211_WMM_IE_STA_QOSINFO_AC_BE |	\
-	 IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |	\
-	 IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
+	IEEE80211_WMM_IE_STA_QOSINFO_AC_VO
 
 #define IEEE80211_DEFAULT_MAX_SP_LEN		\
 	IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
-- 
cgit v1.2.2


From 7ebfa46973aa239f79fbd4651ddeed5c92df45b2 Mon Sep 17 00:00:00 2001
From: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Date: Fri, 15 Jun 2012 10:20:02 +0800
Subject: mac80211: fix and improve mesh RANN processing

This patch fixes the problem of dropping RANN element if the TTL
is 1. If the received RANN element TTL is 1 or greater than 1, the
RANN is processed. However, forwarding of received RANN element
with TTL 1 or less is prohibited according to the standard. This
is previously reported by Monthadar Al Jaberi.

Besides, this patch also avoid the processing of unicast PREQ
generation if the RANN element does not meet the acceptance
criteria mentioned in Sec. 13.10.12.4.2 of IEEE Std. 802.11-2012.

Reported-by: Monthadar Al Jaberi <monthadar@gmail.com>
Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mesh_hwmp.c | 43 +++++++++++++++++++++++++------------------
 1 file changed, 25 insertions(+), 18 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index bea52479e3aa..aed1821bd6f1 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -771,11 +771,6 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
 	bool root_is_gate;
 
 	ttl = rann->rann_ttl;
-	if (ttl <= 1) {
-		ifmsh->mshstats.dropped_frames_ttl++;
-		return;
-	}
-	ttl--;
 	flags = rann->rann_flags;
 	root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
 	orig_addr = rann->rann_addr;
@@ -812,37 +807,49 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
 		}
 	}
 
+	if (!(SN_LT(mpath->sn, orig_sn)) &&
+	    !(mpath->sn == orig_sn && metric < mpath->rann_metric)) {
+		rcu_read_unlock();
+		return;
+	}
+
 	if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) ||
 	     (time_after(jiffies, mpath->last_preq_to_root +
 				  root_path_confirmation_jiffies(sdata)) ||
 	     time_before(jiffies, mpath->last_preq_to_root))) &&
-	     !(mpath->flags & MESH_PATH_FIXED)) {
+	     !(mpath->flags & MESH_PATH_FIXED) && (ttl != 0)) {
 		mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name,
 							       orig_addr);
 		mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
 		mpath->last_preq_to_root = jiffies;
 	}
 
-	if ((SN_LT(mpath->sn, orig_sn) || (mpath->sn == orig_sn &&
-	   metric < mpath->rann_metric)) && ifmsh->mshcfg.dot11MeshForwarding) {
+	mpath->sn = orig_sn;
+	mpath->rann_metric = metric + metric_txsta;
+	mpath->is_root = true;
+	/* Recording RANNs sender address to send individually
+	 * addressed PREQs destined for root mesh STA */
+	memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN);
+
+	if (root_is_gate)
+		mesh_path_add_gate(mpath);
+
+	if (ttl <= 1) {
+		ifmsh->mshstats.dropped_frames_ttl++;
+		rcu_read_unlock();
+		return;
+	}
+	ttl--;
+
+	if (ifmsh->mshcfg.dot11MeshForwarding) {
 		mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
 				       cpu_to_le32(orig_sn),
 				       0, NULL, 0, broadcast_addr,
 				       hopcount, ttl, cpu_to_le32(interval),
 				       cpu_to_le32(metric + metric_txsta),
 				       0, sdata);
-		mpath->sn = orig_sn;
-		mpath->rann_metric = metric + metric_txsta;
-		/* Recording RANNs sender address to send individually
-		 * addressed PREQs destined for root mesh STA */
-		memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN);
 	}
 
-	mpath->is_root = true;
-
-	if (root_is_gate)
-		mesh_path_add_gate(mpath);
-
 	rcu_read_unlock();
 }
 
-- 
cgit v1.2.2


From 559cef996d2e4c9b652a53bb3a53e5787e247f57 Mon Sep 17 00:00:00 2001
From: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
Date: Mon, 18 Jun 2012 19:03:52 +0530
Subject: mac80211: cleanup offchannel_ps_enable argument

The 'tell_ap' argument is always true. So that remove it
and simplify the function.

Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/offchannel.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index fcb01ee8ee7b..febce7fb7bb1 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -25,8 +25,7 @@
  * because we *may* be doing work on-operating channel, and want our
  * hardware unconditionally awake, but still let the AP send us normal frames.
  */
-static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata,
-					   bool tell_ap)
+static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -47,8 +46,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata,
 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 	}
 
-	if (tell_ap && (!local->offchannel_ps_enabled ||
-			!(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)))
+	if (!local->offchannel_ps_enabled ||
+	    !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
 		/*
 		 * If power save was enabled, no need to send a nullfunc
 		 * frame because AP knows that we are sleeping. But if the
@@ -133,7 +132,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
 			if (offchannel_ps_enable &&
 			    (sdata->vif.type == NL80211_IFTYPE_STATION) &&
 			    sdata->u.mgd.associated)
-				ieee80211_offchannel_ps_enable(sdata, true);
+				ieee80211_offchannel_ps_enable(sdata);
 		}
 	}
 	mutex_unlock(&local->iflist_mtx);
-- 
cgit v1.2.2


From 6df653c71e8168e1df01118cc85cd84d0deeb583 Mon Sep 17 00:00:00 2001
From: Luciano Coelho <coelho@ti.com>
Date: Mon, 18 Jun 2012 15:52:51 +0300
Subject: mac80211: initialize sta pointer to avoid false-positive warning

Some compilers (eg. gcc 4.4.1 for ARM) report a false positive warning
in mlme.c:

net/mac80211/mlme.c: In function 'ieee80211_prep_connection':
net/mac80211/mlme.c:3035: warning: 'sta' may be used uninitialized in this function

This is a false positive because the place where 'sta' is used is
inside an if with the same condition of where it is set:

[...]
        if (!have_sta) {
                sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL);
                if (!sta)
                        return -ENOMEM;
        }
[...]
        if (!have_sta) {
[...]
                sta->sta.supp_rates[cbss->channel->band] = rates;
[...]

For some reason the compiler doesn't understand this and warns.

While this is not a problem in the code itself, we can avoid polluting
the build logs with false positives by setting sta to NULL on
declaration and checking for sta instead of !have_sta in the second if.

Reported-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mlme.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0f45d02e0ba7..fa927c6aa14b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3012,7 +3012,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	struct ieee80211_bss *bss = (void *)cbss->priv;
-	struct sta_info *sta;
+	struct sta_info *sta = NULL;
 	bool have_sta = false;
 	int err;
 	int ht_cfreq;
@@ -3102,7 +3102,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
 	local->oper_channel = cbss->channel;
 	ieee80211_hw_config(local, 0);
 
-	if (!have_sta) {
+	if (sta) {
 		u32 rates = 0, basic_rates = 0;
 		bool have_higher_than_11mbit;
 		int min_rate = INT_MAX, min_rate_index = -1;
-- 
cgit v1.2.2


From 50ae34a254ca5192e46503884ed0edd60795fe87 Mon Sep 17 00:00:00 2001
From: Luciano Coelho <coelho@ti.com>
Date: Wed, 20 Jun 2012 17:23:24 +0300
Subject: mac80211: use the correct capability info in
 ieee80211_set_associated()

If an AP is beaconing with different capabilities than the one we get
in the associate response, we were still using the capabilities
received in the beacons.  One example is when the AP is beaconing with
the short slot bit set to zero and then we try to connect to it with
long slot.  In this case, we would keep using long slot until the next
beacon was received.

Fix this by using the correct capability value when calling
ieee80211_handle_bss_capability().  We were using cbss->capability,
but we should use the bss_conf->assoc_capability instead.

Signed-off-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mlme.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index fa927c6aa14b..94d0183ce224 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1275,7 +1275,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 
 	bss_info_changed |= BSS_CHANGED_BEACON_INT;
 	bss_info_changed |= ieee80211_handle_bss_capability(sdata,
-		cbss->capability, bss->has_erp_value, bss->erp_value);
+		bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value);
 
 	sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec(
 		IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int));
-- 
cgit v1.2.2


From 00e96decfd0b927f975c98340a5982c5039eeaae Mon Sep 17 00:00:00 2001
From: Yoni Divinsky <yoni.divinsky@ti.com>
Date: Wed, 20 Jun 2012 15:39:13 +0300
Subject: mac80211: save wmm_acm per sdata

Save and configure the wmm_acm per sdata, rather than
per hardware.

If wmm_acm is saved per hardware when running two
interfaces simultaneously on the same hardware one
interface's wmm policy will be affected by the other
interface.

Signed-off-by: Yoni Divinsky <yoni.divinsky@ti.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ieee80211_i.h |  4 +++-
 net/mac80211/iface.c       |  2 +-
 net/mac80211/mlme.c        | 10 +++++-----
 net/mac80211/rx.c          |  2 +-
 net/mac80211/wme.c         | 11 ++++++-----
 net/mac80211/wme.h         |  2 +-
 6 files changed, 17 insertions(+), 14 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 34af2e5263c2..0024c32d7bc4 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -680,6 +680,9 @@ struct ieee80211_sub_if_data {
 	/* TID bitmap for NoAck policy */
 	u16 noack_map;
 
+	/* bit field of ACM bits (BIT(802.1D tag)) */
+	u8 wmm_acm;
+
 	struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
 	struct ieee80211_key __rcu *default_unicast_key;
 	struct ieee80211_key __rcu *default_multicast_key;
@@ -1025,7 +1028,6 @@ struct ieee80211_local {
 	int total_ps_buffered; /* total number of all buffered unicast and
 				* multicast packets for power saving stations
 				*/
-	unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
 
 	bool pspolling;
 	bool offchannel_ps_enabled;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 87aeb4f21ffd..728d3eac1f59 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -808,7 +808,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
 
 	hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
 
-	return ieee80211_select_queue_80211(local, skb, hdr);
+	return ieee80211_select_queue_80211(sdata, skb, hdr);
 }
 
 static const struct net_device_ops ieee80211_monitorif_ops = {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 94d0183ce224..2b450f541993 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1141,7 +1141,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
 
 	memset(&params, 0, sizeof(params));
 
-	local->wmm_acm = 0;
+	sdata->wmm_acm = 0;
 	for (; left >= 4; left -= 4, pos += 4) {
 		int aci = (pos[0] >> 5) & 0x03;
 		int acm = (pos[0] >> 4) & 0x01;
@@ -1152,21 +1152,21 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
 		case 1: /* AC_BK */
 			queue = 3;
 			if (acm)
-				local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
+				sdata->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
 			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
 				uapsd = true;
 			break;
 		case 2: /* AC_VI */
 			queue = 1;
 			if (acm)
-				local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
+				sdata->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
 			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
 				uapsd = true;
 			break;
 		case 3: /* AC_VO */
 			queue = 0;
 			if (acm)
-				local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
+				sdata->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
 			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
 				uapsd = true;
 			break;
@@ -1174,7 +1174,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
 		default:
 			queue = 2;
 			if (acm)
-				local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
+				sdata->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
 			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
 				uapsd = true;
 			break;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 072e8f3afa2b..446a327b3de0 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1935,7 +1935,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 	    ether_addr_equal(sdata->vif.addr, hdr->addr3))
 		return RX_CONTINUE;
 
-	q = ieee80211_select_queue_80211(local, skb, hdr);
+	q = ieee80211_select_queue_80211(sdata, skb, hdr);
 	if (ieee80211_queue_stopped(&local->hw, q)) {
 		IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
 		return RX_DROP_MONITOR;
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index c3d643a6536c..cea06e9f26f4 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -52,11 +52,11 @@ static int wme_downgrade_ac(struct sk_buff *skb)
 	}
 }
 
-static u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
+static u16 ieee80211_downgrade_queue(struct ieee80211_sub_if_data *sdata,
 				     struct sk_buff *skb)
 {
 	/* in case we are a client verify acm is not set for this ac */
-	while (unlikely(local->wmm_acm & BIT(skb->priority))) {
+	while (unlikely(sdata->wmm_acm & BIT(skb->priority))) {
 		if (wme_downgrade_ac(skb)) {
 			/*
 			 * This should not really happen. The AP has marked all
@@ -73,10 +73,11 @@ static u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
 }
 
 /* Indicate which queue to use for this fully formed 802.11 frame */
-u16 ieee80211_select_queue_80211(struct ieee80211_local *local,
+u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
 				 struct sk_buff *skb,
 				 struct ieee80211_hdr *hdr)
 {
+	struct ieee80211_local *local = sdata->local;
 	u8 *p;
 
 	if (local->hw.queues < IEEE80211_NUM_ACS)
@@ -94,7 +95,7 @@ u16 ieee80211_select_queue_80211(struct ieee80211_local *local,
 	p = ieee80211_get_qos_ctl(hdr);
 	skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
 
-	return ieee80211_downgrade_queue(local, skb);
+	return ieee80211_downgrade_queue(sdata, skb);
 }
 
 /* Indicate which queue to use. */
@@ -156,7 +157,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
 	 * data frame has */
 	skb->priority = cfg80211_classify8021d(skb);
 
-	return ieee80211_downgrade_queue(local, skb);
+	return ieee80211_downgrade_queue(sdata, skb);
 }
 
 void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
index ca80818b7b66..7fea4bb8acbc 100644
--- a/net/mac80211/wme.h
+++ b/net/mac80211/wme.h
@@ -15,7 +15,7 @@
 
 extern const int ieee802_1d_to_ac[8];
 
-u16 ieee80211_select_queue_80211(struct ieee80211_local *local,
+u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
 				 struct sk_buff *skb,
 				 struct ieee80211_hdr *hdr);
 u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
-- 
cgit v1.2.2


From 9ea4fa158f3a038d5be82ccc7e142f198233f059 Mon Sep 17 00:00:00 2001
From: Eyal Shapira <eyal@wizery.com>
Date: Wed, 20 Jun 2012 13:10:14 +0300
Subject: mac80211: fix cleanup if driver suspend callback fails

In case the driver suspend callback fails, mac80211 is left
with stopped queues which prevents any further traffic as well
as all STAs are left marked with WLAN_STA_BLOCK_BA which will
cause any further ADDBA requests to be declined. Fix it by
undoing both before returning from __iee80211_suspend.

Reported-by: Vitaly Wool <vitalywool@gmail.com>
Signed-off-by: Eyal Shapira <eyal@wizery.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/pm.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

(limited to 'net/mac80211')

diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 98c128be3827..5c572e7a1a71 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -78,6 +78,16 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 		if (err < 0) {
 			local->quiescing = false;
 			local->wowlan = false;
+			if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
+				mutex_lock(&local->sta_mtx);
+				list_for_each_entry(sta,
+						    &local->sta_list, list) {
+					clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
+				}
+				mutex_unlock(&local->sta_mtx);
+			}
+			ieee80211_wake_queues_by_reason(hw,
+					IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 			return err;
 		} else if (err > 0) {
 			WARN_ON(err != 1);
-- 
cgit v1.2.2


From 6abe0563224f8540c88e1d84d2bb394bd408c951 Mon Sep 17 00:00:00 2001
From: Will Hawkins <hawkinsw@opentechinstitute.org>
Date: Wed, 20 Jun 2012 11:51:14 -0400
Subject: mac80211: Track auth frame registrations on IBSS ifaces

Track userspace registrations for authentication
frames received on an IBSS interface. This field
will be used to decide whether or not to send
"open system" authentication frames when a new
station joins an adhoc network.

Signed-off-by: Will Hawkins <hawkinsw@opentechinstitute.org>
[redesign the code flow a bit]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c         | 28 +++++++++++++++++++++-------
 net/mac80211/ieee80211_i.h |  1 +
 2 files changed, 22 insertions(+), 7 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 17162fcc24bc..a6abcd473434 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2516,16 +2516,30 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
 					  u16 frame_type, bool reg)
 {
 	struct ieee80211_local *local = wiphy_priv(wiphy);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-	if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
-		return;
+	switch (frame_type) {
+	case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH:
+		if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+			struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
 
-	if (reg)
-		local->probe_req_reg++;
-	else
-		local->probe_req_reg--;
+			if (reg)
+				ifibss->auth_frame_registrations++;
+			else
+				ifibss->auth_frame_registrations--;
+		}
+		break;
+	case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ:
+		if (reg)
+			local->probe_req_reg++;
+		else
+			local->probe_req_reg--;
 
-	ieee80211_queue_work(&local->hw, &local->reconfig_filter);
+		ieee80211_queue_work(&local->hw, &local->reconfig_filter);
+		break;
+	default:
+		break;
+	}
 }
 
 static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0024c32d7bc4..36ce2bb066bf 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -511,6 +511,7 @@ struct ieee80211_if_ibss {
 	bool privacy;
 
 	bool control_port;
+	unsigned int auth_frame_registrations;
 
 	u8 bssid[ETH_ALEN] __aligned(2);
 	u8 ssid[IEEE80211_MAX_SSID_LEN];
-- 
cgit v1.2.2


From 452a6d22615bb8262a932b362f41fc5d89f03293 Mon Sep 17 00:00:00 2001
From: Will Hawkins <hawkinsw@opentechinstitute.org>
Date: Tue, 19 Jun 2012 17:59:13 -0400
Subject: mac80211: send auth in IBSS only if userspace isn't handling it

Check the auth frame registration count before sending
"open system" authentication messages when a new station
registers on a particular IBSS network. This stops us
from sending out multiple authentication messages with
different authentication algorithms.

Signed-off-by: Will Hawkins <hawkinsw@opentechinstitute.org>
[reword commit message a bit]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ibss.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 725cb4be229d..ff46ff424941 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -279,7 +279,7 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
 	/* If it fails, maybe we raced another insertion? */
 	if (sta_info_insert_rcu(sta))
 		return sta_info_get(sdata, addr);
-	if (auth) {
+	if (auth && !sdata->u.ibss.auth_frame_registrations) {
 		ibss_vdbg("TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n",
 			  sdata->vif.addr, sdata->u.ibss.bssid, addr);
 		ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0,
-- 
cgit v1.2.2


From 3bfda62c50b0a4b118dcfce36686508ca2892292 Mon Sep 17 00:00:00 2001
From: Will Hawkins <hawkinsw@opentechinstitute.org>
Date: Tue, 19 Jun 2012 17:59:14 -0400
Subject: mac80211: Allow userspace to register for auth frames in IBSS

Set the necessary flags to allow user space applications
to register for authentication frames on IBSS interfaces.
This is useful for situations where userspace applications
want to control key negotiation between stations.

Signed-off-by: Will Hawkins <hawkinsw@opentechinstitute.org>
[reword commit message a bit]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/main.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 976e41365c25..0b040fb73673 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -462,7 +462,9 @@ static const struct ieee80211_txrx_stypes
 ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
 	[NL80211_IFTYPE_ADHOC] = {
 		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ACTION >> 4),
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+			BIT(IEEE80211_STYPE_AUTH >> 4) |
+			BIT(IEEE80211_STYPE_DEAUTH >> 4),
 	},
 	[NL80211_IFTYPE_STATION] = {
 		.tx = 0xffff,
-- 
cgit v1.2.2


From 0f6b3f597daab2254614e2773e322e73fb1b6f4b Mon Sep 17 00:00:00 2001
From: Johannes Berg <johannes.berg@intel.com>
Date: Wed, 20 Jun 2012 20:11:33 +0200
Subject: mac80211: fix double-start of remain-on-channel

When a remain-on-channel item is deleted, we remove it
from the list and then start the next item. However,
if it wasn't actually the first item then calling
ieee80211_start_next_roc() is wrong as it will start
the first item -- even if that was already started.

Fix the two places that do this and add a warning to
prevent the problem from reoccurring.

Reported-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c        | 3 ++-
 net/mac80211/offchannel.c | 6 +++++-
 2 files changed, 7 insertions(+), 2 deletions(-)

(limited to 'net/mac80211')

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a6abcd473434..03aff23c70fd 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2362,7 +2362,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
 
 		list_del(&found->list);
 
-		ieee80211_start_next_roc(local);
+		if (found->started)
+			ieee80211_start_next_roc(local);
 		mutex_unlock(&local->mtx);
 
 		ieee80211_roc_notify_destroy(found);
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index febce7fb7bb1..7f93626ddc61 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -262,6 +262,9 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
 	roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work,
 			       list);
 
+	if (WARN_ON_ONCE(roc->started))
+		return;
+
 	if (local->ops->remain_on_channel) {
 		int ret, duration = roc->duration;
 
@@ -377,7 +380,8 @@ void ieee80211_sw_roc_work(struct work_struct *work)
 
 		ieee80211_recalc_idle(local);
 
-		ieee80211_start_next_roc(local);
+		if (roc->started)
+			ieee80211_start_next_roc(local);
 	}
 
  out_unlock:
-- 
cgit v1.2.2