Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH v2] mac80211/cfg80211: report monitor channel in wireless extensions
From: Johannes Berg @ 2011-11-08 19:01 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless
In-Reply-To: <1320778327.24797.36.camel@jlt3.sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Just add API to get the channel & report it. Trivial really.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
v2: fix signal -> single (thanks Ben)

I'm not sure why this is so hard that the aircrack people
couldn't figure out what to do ...

 include/net/cfg80211.h     |    5 +++++
 net/mac80211/cfg.c         |    8 ++++++++
 net/wireless/wext-compat.c |   12 ++++++++++++
 3 files changed, 25 insertions(+)

--- a/include/net/cfg80211.h	2011-11-08 19:37:45.000000000 +0100
+++ b/include/net/cfg80211.h	2011-11-08 20:00:42.000000000 +0100
@@ -1342,6 +1342,9 @@ struct cfg80211_gtk_rekey_data {
  *	doesn't verify much. Note, however, that the passed netdev may be
  *	%NULL as well if the user requested changing the channel for the
  *	device itself, or for a monitor interface.
+ * @get_channel: Get the current operating channel, should return %NULL if
+ *	there's no single defined operating channel if for example the
+ *	device implements channel hopping for multi-channel virtual interfaces.
  *
  * @scan: Request to do a scan. If returning zero, the scan request is given
  *	the driver, and will be valid until passed to cfg80211_scan_done().
@@ -1627,6 +1630,8 @@ struct cfg80211_ops {
 
 	int	(*probe_client)(struct wiphy *wiphy, struct net_device *dev,
 				const u8 *peer, u64 *cookie);
+
+	struct ieee80211_channel *(get_channel)(struct wiphy *wiphy);
 };
 
 /*
--- a/net/wireless/wext-compat.c	2011-11-08 19:37:45.000000000 +0100
+++ b/net/wireless/wext-compat.c	2011-11-08 19:49:33.000000000 +0100
@@ -818,12 +818,24 @@ static int cfg80211_wext_giwfreq(struct
 				 struct iw_freq *freq, char *extra)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+	struct ieee80211_channel *chan;
 
 	switch (wdev->iftype) {
 	case NL80211_IFTYPE_STATION:
 		return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
 	case NL80211_IFTYPE_ADHOC:
 		return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
+	case NL80211_IFTYPE_MONITOR:
+		if (!rdev->ops->get_channel)
+			return -EINVAL;
+
+		chan = rdev->ops->get_channel(wdev->wiphy);
+		if (!chan)
+			return -EINVAL;
+		freq->m = chan->center_freq;
+		freq->e = 6;
+		return 0;
 	default:
 		if (!wdev->channel)
 			return -EINVAL;
--- a/net/mac80211/cfg.c	2011-11-08 19:37:45.000000000 +0100
+++ b/net/mac80211/cfg.c	2011-11-08 19:49:33.000000000 +0100
@@ -2579,6 +2579,13 @@ static int ieee80211_probe_client(struct
 	return 0;
 }
 
+static const struct ieee80211_channel *ieee80211_get_channel(struct wiphy *wiphy)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	return local->oper_channel;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -2645,4 +2652,5 @@ struct cfg80211_ops mac80211_config_ops
 	.tdls_oper = ieee80211_tdls_oper,
 	.tdls_mgmt = ieee80211_tdls_mgmt,
 	.probe_client = ieee80211_probe_client,
+	.get_channel = ieee80211_get_channel,
 };



^ permalink raw reply

* [PATCH v7 2/2] mac80211:  Support ht-cap over-rides.
From: greearb @ 2011-11-08 19:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <1320778857-3073-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

This implements ht-cap over-rides for mac80211 drivers.
HT may be disabled, making an /a/b/g/n station act like an
a/b/g station.  HT40 may be disabled forcing the station to
be HT20 even if the AP and local hardware support HT40.

MAX-AMSDU may be disabled.
AMPDU-Density may be increased.
AMPDU-Factor may be decreased.

This has been successfully tested with ath9k using patched
wpa_supplicant and iw.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 48363c3... 25ea406... M	include/linux/ieee80211.h
:100644 100644 a9ded52... 7f4389e... M	net/mac80211/cfg.c
:100644 100644 f80a35c... 47b89bb... M	net/mac80211/ht.c
:100644 100644 ea10a51... 6afa409... M	net/mac80211/ieee80211_i.h
:100644 100644 d4ee6d2... 7be5ad8... M	net/mac80211/main.c
:100644 100644 57fb58f... 7c71db0... M	net/mac80211/mlme.c
:100644 100644 6c53b6d... 3f318df... M	net/mac80211/work.c
 include/linux/ieee80211.h  |    6 +++
 net/mac80211/cfg.c         |    2 +-
 net/mac80211/ht.c          |   90 +++++++++++++++++++++++++++++++++++++++++++-
 net/mac80211/ieee80211_i.h |   10 ++++-
 net/mac80211/main.c        |   14 +++++++
 net/mac80211/mlme.c        |   12 +++++-
 net/mac80211/work.c        |   35 ++++++++++++-----
 7 files changed, 154 insertions(+), 15 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 48363c3..25ea406 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -906,6 +906,12 @@ struct ieee80211_mcs_info {
 #define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT	2
 #define		IEEE80211_HT_MCS_TX_MAX_STREAMS	4
 #define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION	0x10
+/*
+ * Stations supporting 802.11n are required to support
+ * at least the first 8 MCS rates.  See section 7.3.2.56.4
+ * and 20.1.1 of the 802.11n spec.
+ */
+#define IEEE80211_HT_MCS_REQ_RATES_STA		8
 
 /*
  * 802.11n D5.0 20.3.5 / 20.6 says:
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a9ded52..7f4389e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -778,7 +778,7 @@ static void sta_apply_parameters(struct ieee80211_local *local,
 	}
 
 	if (params->ht_capa)
-		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
 						  params->ht_capa,
 						  &sta->sta.ht_cap);
 
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index f80a35c..47b89bb 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -18,7 +18,89 @@
 #include "ieee80211_i.h"
 #include "rate.h"
 
-void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
+bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata)
+{
+	if ((sdata->u.mgd.ht_capa_mask.cap_info &
+	     IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
+	    !(sdata->u.mgd.ht_capa.cap_info &
+	      IEEE80211_HT_CAP_SUP_WIDTH_20_40))
+		return true;
+	return false;
+}
+
+void __check_htcap_disable(struct ieee80211_sub_if_data *sdata,
+			   struct ieee80211_sta_ht_cap *ht_cap,
+			   u16 flag)
+{
+	if (sdata->u.mgd.ht_capa_mask.cap_info & flag) {
+		if (!(sdata->u.mgd.ht_capa.cap_info & flag))
+			ht_cap->cap &= ~flag;
+	}
+}
+
+void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
+				     struct ieee80211_sta_ht_cap *ht_cap,
+				     int min_rates)
+{
+	u8 *scaps = (u8 *)(&sdata->u.mgd.ht_capa.mcs.rx_mask);
+	u8 *smask = (u8 *)(&sdata->u.mgd.ht_capa_mask.mcs.rx_mask);
+	int i;
+
+	/* NOTE:  If you add more over-rides here, update register_hw
+	 * ht_capa_mod_msk logic in main.c as well.
+	 */
+
+	/* check for HT over-rides, MCS rates first. */
+	for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
+		int q;
+		for (q = 0; q < 8; q++) {
+			/*
+			 * We always need to advert at least MCS0-7, to
+			 * be a compliant HT station, for instance
+			 */
+			if (((i * 8 + q) >= min_rates) &&
+			    (smask[i] & (1<<q))) {
+				if (!(scaps[i] & (1<<q))) {
+					/*
+					 * Can only disable rates, not force
+					 * new ones
+					 */
+					ht_cap->mcs.rx_mask[i] &= ~(1<<q);
+				}
+			}
+		}
+	}
+
+	/* Force removal of HT-40 capabilities? */
+	__check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SUP_WIDTH_20_40);
+	__check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_40);
+
+	/* Allow user to disable the max-AMSDU bit. */
+	__check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_MAX_AMSDU);
+
+	/* Allow user to decrease AMPDU factor */
+	if (sdata->u.mgd.ht_capa_mask.ampdu_params_info &
+	    IEEE80211_HT_AMPDU_PARM_FACTOR) {
+		u16 n = sdata->u.mgd.ht_capa.ampdu_params_info
+			& IEEE80211_HT_AMPDU_PARM_FACTOR;
+		if (n < ht_cap->ampdu_factor)
+			ht_cap->ampdu_factor = n;
+	}
+
+	/* Allow the user to increase AMPDU density. */
+	if (sdata->u.mgd.ht_capa_mask.ampdu_params_info &
+	    IEEE80211_HT_AMPDU_PARM_DENSITY) {
+		u16 n = (sdata->u.mgd.ht_capa.ampdu_params_info &
+			 IEEE80211_HT_AMPDU_PARM_DENSITY)
+			>> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
+		if (n > ht_cap->ampdu_density)
+			ht_cap->ampdu_density = n;
+	}
+}
+
+
+void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
+				       struct ieee80211_supported_band *sband,
 				       struct ieee80211_ht_cap *ht_cap_ie,
 				       struct ieee80211_sta_ht_cap *ht_cap)
 {
@@ -102,6 +184,12 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
 	/* handle MCS rate 32 too */
 	if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
 		ht_cap->mcs.rx_mask[32/8] |= 1;
+
+	/*
+	 * If user has specified capability over-rides, take care
+	 * of that here.
+	 */
+	ieee80211_apply_htcap_overrides(sdata, ht_cap, 0);
 }
 
 void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ea10a51..6afa409 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -443,6 +443,9 @@ struct ieee80211_if_managed {
 	 */
 	int rssi_min_thold, rssi_max_thold;
 	int last_ave_beacon_signal;
+	struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */
+	struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */
+
 };
 
 struct ieee80211_if_ibss {
@@ -1179,7 +1182,12 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 				       struct net_device *dev);
 
 /* HT */
-void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
+bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata);
+void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
+				     struct ieee80211_sta_ht_cap *ht_cap,
+				     int min_rates);
+void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
+				       struct ieee80211_supported_band *sband,
 				       struct ieee80211_ht_cap *ht_cap_ie,
 				       struct ieee80211_sta_ht_cap *ht_cap);
 void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index d4ee6d2..7be5ad8 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -560,6 +560,19 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
 	},
 };
 
+static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = {
+	.ampdu_params_info = IEEE80211_HT_AMPDU_PARM_FACTOR |
+			     IEEE80211_HT_AMPDU_PARM_DENSITY,
+
+	.cap_info = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+		    IEEE80211_HT_CAP_MAX_AMSDU |
+		    IEEE80211_HT_CAP_SGI_40,
+	.mcs = {
+		.rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff,
+			     0xff, 0xff, 0xff, 0xff, 0xff, },
+	},
+};
+
 struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 					const struct ieee80211_ops *ops)
 {
@@ -628,6 +641,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 	local->user_power_level = -1;
 	local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
 	local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
+	wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
 
 	INIT_LIST_HEAD(&local->interfaces);
 
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 57fb58f..7c71db0 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -207,6 +207,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
 		channel_type = NL80211_CHAN_HT20;
 
 		if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
+		    !ieee80111_cfg_override_disables_ht40(sdata) &&
 		    (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
 		    (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
 			switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
@@ -1584,7 +1585,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
 		sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
 
 	if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
-		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
 				elems.ht_cap_elem, &sta->sta.ht_cap);
 
 	ap_ht_cap_flags = sta->sta.ht_cap.cap;
@@ -1953,7 +1954,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 
 		sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 
-		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
 				elems.ht_cap_elem, &sta->sta.ht_cap);
 
 		ap_ht_cap_flags = sta->sta.ht_cap.cap;
@@ -2611,6 +2612,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 			ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
 
 
+	if (req->flags & ASSOC_REQ_DISABLE_HT)
+		ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+
+	memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
+	memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask,
+	       sizeof(ifmgd->ht_capa_mask));
+
 	if (req->ie && req->ie_len) {
 		memcpy(wk->ie, req->ie, req->ie_len);
 		wk->ie_len = req->ie_len;
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 6c53b6d..3f318df 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -94,7 +94,8 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
 
 /* frame sending functions */
 
-static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
+static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
+				struct sk_buff *skb, const u8 *ht_info_ie,
 				struct ieee80211_supported_band *sband,
 				struct ieee80211_channel *channel,
 				enum ieee80211_smps_mode smps)
@@ -102,11 +103,11 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
 	struct ieee80211_ht_info *ht_info;
 	u8 *pos;
 	u32 flags = channel->flags;
-	u16 cap = sband->ht_cap.cap;
+	u16 cap;
 	__le16 tmp;
+	struct ieee80211_sta_ht_cap ht_cap;
 
-	if (!sband->ht_cap.ht_supported)
-		return;
+	BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap));
 
 	if (!ht_info_ie)
 		return;
@@ -114,6 +115,20 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
 	if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info))
 		return;
 
+	memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
+	/*
+	 * This is for an association attempt, and stations must
+	 * support at least the first 8 MCS rates.  See section 20.1.1
+	 * of the 802.11n spec for details.
+	 */
+	ieee80211_apply_htcap_overrides(sdata, &ht_cap,
+					IEEE80211_HT_MCS_REQ_RATES_STA);
+
+	cap = ht_cap.cap;
+
+	if (!ht_cap.ht_supported)
+		return;
+
 	ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2);
 
 	/* determine capability flags */
@@ -166,13 +181,13 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
 	pos += sizeof(u16);
 
 	/* AMPDU parameters */
-	*pos++ = sband->ht_cap.ampdu_factor |
-		 (sband->ht_cap.ampdu_density <<
-			IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
+	*pos++ = ht_cap.ampdu_factor |
+		 (ht_cap.ampdu_density <<
+		  IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
 
 	/* MCS set */
-	memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
-	pos += sizeof(sband->ht_cap.mcs);
+	memcpy(pos, &ht_cap.mcs, sizeof(ht_cap.mcs));
+	pos += sizeof(ht_cap.mcs);
 
 	/* extended capabilities */
 	pos += sizeof(__le16);
@@ -356,7 +371,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
 
 	if (wk->assoc.use_11n && wk->assoc.wmm_used &&
 	    local->hw.queues >= 4)
-		ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie,
+		ieee80211_add_ht_ie(sdata, skb, wk->assoc.ht_information_ie,
 				    sband, wk->chan, wk->assoc.smps);
 
 	/* if present, add any custom non-vendor IEs that go after HT */
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v7 1/2] wireless:  Support ht-capabilities over-rides.
From: greearb @ 2011-11-08 19:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

This allows users to disable features such as HT, HT40,
and to modify the MCS, AMPDU, and AMSDU settings for
drivers that support it.

The MCS, AMPDU, and AMSDU features that may be disabled are
are reported in the phy-info netlink message as a mask.

Attemping to disable features that are not supported will
take no affect, but will not return errors.  This is to aid
backwards compatibility in user-space apps that may not be
clever enough to deal with parsing the the capabilities mask.

This patch only enables the infrastructure.  An additional
patch will enable the feature in mac80211.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---

v7:  Add detailed comments about what is supported in the
     HT_CAPABILITY_MASK attribute.

     Add call to cfg80211_oper_and_ht_capa() in the
     __cfg80211_connect path to make sure non mac80211
     drivers get proper masking.

:100644 100644 8049bf7... 34c3973... M	include/linux/nl80211.h
:100644 100644 92cf1c2... 5598b91... M	include/net/cfg80211.h
:100644 100644 b9ec306... dd6feda... M	net/wireless/core.h
:100644 100644 21fc970... 54d9071... M	net/wireless/mlme.c
:100644 100644 48260c2... 80e5144... M	net/wireless/nl80211.c
:100644 100644 6e86d5a... 062365b... M	net/wireless/sme.c
 include/linux/nl80211.h |   15 +++++++++++++++
 include/net/cfg80211.h  |   28 ++++++++++++++++++++++++++++
 net/wireless/core.h     |    8 ++++++--
 net/wireless/mlme.c     |   37 ++++++++++++++++++++++++++++++++++---
 net/wireless/nl80211.c  |   44 +++++++++++++++++++++++++++++++++++++++++++-
 net/wireless/sme.c      |    7 ++++++-
 6 files changed, 132 insertions(+), 7 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 8049bf7..34c3973 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1109,6 +1109,18 @@ enum nl80211_commands {
  *	%NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
  *	used for asking the driver to perform a TDLS operation.
  *
+ * @NL80211_ATTR_DISABLE_HT:  Force HT capable interfaces to disable
+ *      this feature.  Currently, only supported in mac80211 drivers.
+ * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the
+ *      ATTR_HT_CAPABILITY to which attention should be paid.
+ *      Currently, only mac80211 NICs support this feature.
+ *      The values that may be configured are:
+ *       MCS rates, MAX-AMSDU, HT-20-40 and HT_CAP_SGI_40
+ *       AMPDU density and AMPDU factor.
+ *      All values are treated as suggestions and may be ignored
+ *      by the driver as required.  The actual values may be seen in
+ *      the station debugfs ht_caps file.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1337,6 +1349,9 @@ enum nl80211_attrs {
 	NL80211_ATTR_TDLS_SUPPORT,
 	NL80211_ATTR_TDLS_EXTERNAL_SETUP,
 
+	NL80211_ATTR_DISABLE_HT,
+	NL80211_ATTR_HT_CAPABILITY_MASK,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 92cf1c2..5598b91 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1036,6 +1036,15 @@ struct cfg80211_auth_request {
 };
 
 /**
+ * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association.
+ *
+ * @ASSOC_REQ_DISABLE_HT:  Disable HT (802.11n)
+ */
+enum cfg80211_assoc_req_flags {
+	ASSOC_REQ_DISABLE_HT		= BIT(0),
+};
+
+/**
  * struct cfg80211_assoc_request - (Re)Association request data
  *
  * This structure provides information needed to complete IEEE 802.11
@@ -1046,6 +1055,10 @@ struct cfg80211_auth_request {
  * @use_mfp: Use management frame protection (IEEE 802.11w) in this association
  * @crypto: crypto settings
  * @prev_bssid: previous BSSID, if not %NULL use reassociate frame
+ * @flags:  See &enum cfg80211_assoc_req_flags
+ * @ht_capa:  HT Capabilities over-rides.  Values set in ht_capa_mask
+ *   will be used in ht_capa.  Un-supported values will be ignored.
+ * @ht_capa_mask:  The bits of ht_capa which are to be used.
  */
 struct cfg80211_assoc_request {
 	struct cfg80211_bss *bss;
@@ -1053,6 +1066,9 @@ struct cfg80211_assoc_request {
 	size_t ie_len;
 	struct cfg80211_crypto_settings crypto;
 	bool use_mfp;
+	u32 flags;
+	struct ieee80211_ht_cap ht_capa;
+	struct ieee80211_ht_cap ht_capa_mask;
 };
 
 /**
@@ -1151,6 +1167,10 @@ struct cfg80211_ibss_params {
  * @key_len: length of WEP key for shared key authentication
  * @key_idx: index of WEP key for shared key authentication
  * @key: WEP key for shared key authentication
+ * @flags:  See &enum cfg80211_assoc_req_flags
+ * @ht_capa:  HT Capabilities over-rides.  Values set in ht_capa_mask
+ *   will be used in ht_capa.  Un-supported values will be ignored.
+ * @ht_capa_mask:  The bits of ht_capa which are to be used.
  */
 struct cfg80211_connect_params {
 	struct ieee80211_channel *channel;
@@ -1164,6 +1184,9 @@ struct cfg80211_connect_params {
 	struct cfg80211_crypto_settings crypto;
 	const u8 *key;
 	u8 key_len, key_idx;
+	u32 flags;
+	struct ieee80211_ht_cap ht_capa;
+	struct ieee80211_ht_cap ht_capa_mask;
 };
 
 /**
@@ -1903,6 +1926,9 @@ struct wiphy_wowlan_support {
  *	may request, if implemented.
  *
  * @wowlan: WoWLAN support information
+ *
+ * @ht_capa_mod_mask:  Specify what ht_cap values can be over-ridden.
+ *	If null, then none can be over-ridden.
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -1983,6 +2009,8 @@ struct wiphy {
 	/* dir in debugfs: ieee80211/<wiphyname> */
 	struct dentry *debugfsdir;
 
+	const struct ieee80211_ht_cap *ht_capa_mod_mask;
+
 #ifdef CONFIG_NET_NS
 	/* the network namespace this phy lives in currently */
 	struct net *_net;
diff --git a/net/wireless/core.h b/net/wireless/core.h
index b9ec306..dd6feda 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -339,13 +339,17 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 			  const u8 *bssid, const u8 *prev_bssid,
 			  const u8 *ssid, int ssid_len,
 			  const u8 *ie, int ie_len, bool use_mfp,
-			  struct cfg80211_crypto_settings *crypt);
+			  struct cfg80211_crypto_settings *crypt,
+			  u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+			  struct ieee80211_ht_cap *ht_capa_mask);
 int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 			struct net_device *dev, struct ieee80211_channel *chan,
 			const u8 *bssid, const u8 *prev_bssid,
 			const u8 *ssid, int ssid_len,
 			const u8 *ie, int ie_len, bool use_mfp,
-			struct cfg80211_crypto_settings *crypt);
+			struct cfg80211_crypto_settings *crypt,
+			u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+			struct ieee80211_ht_cap *ht_capa_mask);
 int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
 			   struct net_device *dev, const u8 *bssid,
 			   const u8 *ie, int ie_len, u16 reason,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 21fc970..54d9071 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -501,13 +501,32 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
 	return err;
 }
 
+/*  Do a logical ht_capa &= ht_capa_mask.  */
+static void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
+			const struct ieee80211_ht_cap *ht_capa_mask)
+{
+	int i;
+	u8 *p1, *p2;
+	if (!ht_capa_mask) {
+		memset(ht_capa, 0, sizeof(*ht_capa));
+		return;
+	}
+
+	p1 = (u8*)(ht_capa);
+	p2 = (u8*)(ht_capa_mask);
+	for (i = 0; i<sizeof(*ht_capa); i++)
+		p1[i] &= p2[i];
+}
+
 int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 			  struct net_device *dev,
 			  struct ieee80211_channel *chan,
 			  const u8 *bssid, const u8 *prev_bssid,
 			  const u8 *ssid, int ssid_len,
 			  const u8 *ie, int ie_len, bool use_mfp,
-			  struct cfg80211_crypto_settings *crypt)
+			  struct cfg80211_crypto_settings *crypt,
+			  u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+			  struct ieee80211_ht_cap *ht_capa_mask)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct cfg80211_assoc_request req;
@@ -537,6 +556,15 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 	memcpy(&req.crypto, crypt, sizeof(req.crypto));
 	req.use_mfp = use_mfp;
 	req.prev_bssid = prev_bssid;
+	req.flags = assoc_flags;
+	if (ht_capa)
+		memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa));
+	if (ht_capa_mask)
+		memcpy(&req.ht_capa_mask, ht_capa_mask,
+		       sizeof(req.ht_capa_mask));
+	cfg80211_oper_and_ht_capa(&req.ht_capa_mask,
+				  rdev->wiphy.ht_capa_mod_mask);
+	
 	req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
 				   WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
 	if (!req.bss) {
@@ -574,14 +602,17 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 			const u8 *bssid, const u8 *prev_bssid,
 			const u8 *ssid, int ssid_len,
 			const u8 *ie, int ie_len, bool use_mfp,
-			struct cfg80211_crypto_settings *crypt)
+			struct cfg80211_crypto_settings *crypt,
+			u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+			struct ieee80211_ht_cap *ht_capa_mask)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	int err;
 
 	wdev_lock(wdev);
 	err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
-				    ssid, ssid_len, ie, ie_len, use_mfp, crypt);
+				    ssid, ssid_len, ie, ie_len, use_mfp, crypt,
+				    assoc_flags, ht_capa, ht_capa_mask);
 	wdev_unlock(wdev);
 
 	return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 48260c2..80e5144 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -197,6 +197,10 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
 	[NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
 	[NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
+	[NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
+	[NL80211_ATTR_HT_CAPABILITY_MASK] = {
+		.len = NL80211_HT_CAPABILITY_LEN
+	},
 };
 
 /* policy for the key attributes */
@@ -1008,6 +1012,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 	if (nl80211_put_iface_combinations(&dev->wiphy, msg))
 		goto nla_put_failure;
 
+	if (dev->wiphy.ht_capa_mod_mask)
+		NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
+			sizeof(*dev->wiphy.ht_capa_mod_mask),
+			dev->wiphy.ht_capa_mod_mask);
+
 	return genlmsg_end(msg, hdr);
 
  nla_put_failure:
@@ -4354,6 +4363,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
 	const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
 	int err, ssid_len, ie_len = 0;
 	bool use_mfp = false;
+	u32 flags = 0;
+	struct ieee80211_ht_cap *ht_capa = NULL;
+	struct ieee80211_ht_cap *ht_capa_mask = NULL;
 
 	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
 		return -EINVAL;
@@ -4397,11 +4409,25 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
 	if (info->attrs[NL80211_ATTR_PREV_BSSID])
 		prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
 
+	if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
+		flags |= ASSOC_REQ_DISABLE_HT;
+
+	if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+		ht_capa_mask =
+			nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]);
+
+	if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
+		if (!ht_capa_mask)
+			return -EINVAL;
+		ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
+	}
+
 	err = nl80211_crypto_settings(rdev, info, &crypto, 1);
 	if (!err)
 		err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
 					  ssid, ssid_len, ie, ie_len, use_mfp,
-					  &crypto);
+					  &crypto, flags, ht_capa,
+					  ht_capa_mask);
 
 	return err;
 }
@@ -4891,6 +4917,22 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 			return PTR_ERR(connkeys);
 	}
 
+	if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
+		connect.flags |= ASSOC_REQ_DISABLE_HT;
+
+	if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+		memcpy(&connect.ht_capa_mask,
+		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
+		       sizeof(connect.ht_capa_mask));
+
+	if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
+		if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+			return -EINVAL;
+		memcpy(&connect.ht_capa,
+		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
+		       sizeof(connect.ht_capa));
+	}
+
 	err = cfg80211_connect(rdev, dev, &connect, connkeys);
 	if (err)
 		kfree(connkeys);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 6e86d5a..062365b 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -189,7 +189,9 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
 					    prev_bssid,
 					    params->ssid, params->ssid_len,
 					    params->ie, params->ie_len,
-					    false, &params->crypto);
+					    false, &params->crypto,
+					    params->flags, &params->ht_capa,
+					    &params->ht_capa_mask);
 		if (err)
 			__cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
 					       NULL, 0,
@@ -773,6 +775,9 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
 		wdev->connect_keys = NULL;
 	}
 
+	cfg80211_oper_and_ht_capa(&connect.ht_capa_mask,
+				  rdev->wiphy.ht_capa_mod_mask);
+	
 	if (connkeys && connkeys->def >= 0) {
 		int idx;
 		u32 cipher;
-- 
1.7.3.4


^ permalink raw reply related

* Re: [PATCH] mac80211/cfg80211: report monitor channel in wireless extensions
From: Johannes Berg @ 2011-11-08 19:00 UTC (permalink / raw)
  To: Ben Greear; +Cc: John Linville, linux-wireless
In-Reply-To: <4EB97B70.1010909@candelatech.com>

On Tue, 2011-11-08 at 10:56 -0800, Ben Greear wrote:
> On 11/08/2011 10:52 AM, Johannes Berg wrote:

> > +++ b/include/net/cfg80211.h	2011-11-08 19:49:33.000000000 +0100
> > @@ -1342,6 +1342,9 @@ struct cfg80211_gtk_rekey_data {
> >    *	doesn't verify much. Note, however, that the passed netdev may be
> >    *	%NULL as well if the user requested changing the channel for the
> >    *	device itself, or for a monitor interface.
> > + * @get_channel: Get the current operating channel, should return %NULL if
> > + *	there's no signal defined operating channel if for example the
> 
> Do you mean "no single defined" ?

Err, yes, thanks. Fingers faster than brain.

johannes


^ permalink raw reply

* Re: [PATCH] mac80211/cfg80211: report monitor channel in wireless extensions
From: Ben Greear @ 2011-11-08 18:56 UTC (permalink / raw)
  To: Johannes Berg; +Cc: John Linville, linux-wireless
In-Reply-To: <1320778327.24797.36.camel@jlt3.sipsolutions.net>

On 11/08/2011 10:52 AM, Johannes Berg wrote:
> From: Johannes Berg<johannes.berg@intel.com>
>
> Just add API to get the channel&  report it. Trivial really.
>
> Signed-off-by: Johannes Berg<johannes.berg@intel.com>
> ---
> I'm not sure why this is so hard that the aircrack people
> couldn't figure out what to do ...
>
>   include/net/cfg80211.h     |    5 +++++
>   net/mac80211/cfg.c         |    8 ++++++++
>   net/wireless/wext-compat.c |   12 ++++++++++++
>   3 files changed, 25 insertions(+)
>
> --- a/include/net/cfg80211.h	2011-11-08 19:37:45.000000000 +0100
> +++ b/include/net/cfg80211.h	2011-11-08 19:49:33.000000000 +0100
> @@ -1342,6 +1342,9 @@ struct cfg80211_gtk_rekey_data {
>    *	doesn't verify much. Note, however, that the passed netdev may be
>    *	%NULL as well if the user requested changing the channel for the
>    *	device itself, or for a monitor interface.
> + * @get_channel: Get the current operating channel, should return %NULL if
> + *	there's no signal defined operating channel if for example the

Do you mean "no single defined" ?

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* [PATCH] mac80211/cfg80211: report monitor channel in wireless extensions
From: Johannes Berg @ 2011-11-08 18:52 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

From: Johannes Berg <johannes.berg@intel.com>

Just add API to get the channel & report it. Trivial really.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
I'm not sure why this is so hard that the aircrack people
couldn't figure out what to do ...

 include/net/cfg80211.h     |    5 +++++
 net/mac80211/cfg.c         |    8 ++++++++
 net/wireless/wext-compat.c |   12 ++++++++++++
 3 files changed, 25 insertions(+)

--- a/include/net/cfg80211.h	2011-11-08 19:37:45.000000000 +0100
+++ b/include/net/cfg80211.h	2011-11-08 19:49:33.000000000 +0100
@@ -1342,6 +1342,9 @@ struct cfg80211_gtk_rekey_data {
  *	doesn't verify much. Note, however, that the passed netdev may be
  *	%NULL as well if the user requested changing the channel for the
  *	device itself, or for a monitor interface.
+ * @get_channel: Get the current operating channel, should return %NULL if
+ *	there's no signal defined operating channel if for example the
+ *	device implements channel hopping for multi-channel virtual interfaces.
  *
  * @scan: Request to do a scan. If returning zero, the scan request is given
  *	the driver, and will be valid until passed to cfg80211_scan_done().
@@ -1627,6 +1630,8 @@ struct cfg80211_ops {
 
 	int	(*probe_client)(struct wiphy *wiphy, struct net_device *dev,
 				const u8 *peer, u64 *cookie);
+
+	struct ieee80211_channel *(get_channel)(struct wiphy *wiphy);
 };
 
 /*
--- a/net/wireless/wext-compat.c	2011-11-08 19:37:45.000000000 +0100
+++ b/net/wireless/wext-compat.c	2011-11-08 19:49:33.000000000 +0100
@@ -818,12 +818,24 @@ static int cfg80211_wext_giwfreq(struct
 				 struct iw_freq *freq, char *extra)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+	struct ieee80211_channel *chan;
 
 	switch (wdev->iftype) {
 	case NL80211_IFTYPE_STATION:
 		return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
 	case NL80211_IFTYPE_ADHOC:
 		return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
+	case NL80211_IFTYPE_MONITOR:
+		if (!rdev->ops->get_channel)
+			return -EINVAL;
+
+		chan = rdev->ops->get_channel(wdev->wiphy);
+		if (!chan)
+			return -EINVAL;
+		freq->m = chan->center_freq;
+		freq->e = 6;
+		return 0;
 	default:
 		if (!wdev->channel)
 			return -EINVAL;
--- a/net/mac80211/cfg.c	2011-11-08 19:37:45.000000000 +0100
+++ b/net/mac80211/cfg.c	2011-11-08 19:49:33.000000000 +0100
@@ -2579,6 +2579,13 @@ static int ieee80211_probe_client(struct
 	return 0;
 }
 
+static const struct ieee80211_channel *ieee80211_get_channel(struct wiphy *wiphy)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	return local->oper_channel;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -2645,4 +2652,5 @@ struct cfg80211_ops mac80211_config_ops
 	.tdls_oper = ieee80211_tdls_oper,
 	.tdls_mgmt = ieee80211_tdls_mgmt,
 	.probe_client = ieee80211_probe_client,
+	.get_channel = ieee80211_get_channel,
 };



^ permalink raw reply

* pull request: bluetooth 2011-11-08
From: Gustavo Padovan @ 2011-11-08 18:41 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, linux-bluetooth, linux-kernel

Hi John,

3 more fixes to linux 3.2. One is USB device id addition and the other two
patches combined fixes a connection issue. The first one from Arek Lichwa
revert the wrong fix and a second commit from Andrzej Kaczmarek fix the issue
properly.

Please pull, or let me know any problem with this.

	Gustavo


The following changes since commit 24b9c373ab787ccacfa2c46736153708796f5cd6:

  mac80211: uAPSD - fix IEEE80211_FCTL_MOREDATA bit setting (2011-11-07 13:19:15 -0500)

are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth master

Andrzej Kaczmarek (1):
      Bluetooth: Use miliseconds for L2CAP channel timeouts

Arek Lichwa (1):
      Bluetooth: Revert: Fix L2CAP connection establishment

Wen-chien Jesse Sung (1):
      Bluetooth: Add support for Broadcom BCM20702A0

 drivers/bluetooth/btusb.c     |    3 +++
 include/net/bluetooth/l2cap.h |    7 +++++--
 net/bluetooth/hci_conn.c      |    2 +-
 net/bluetooth/l2cap_core.c    |   16 ++++++++--------
 4 files changed, 17 insertions(+), 11 deletions(-)


^ permalink raw reply

* Re: [RFT/FYI] mac80211: revert on-channel work optimisations
From: Johannes Berg @ 2011-11-08 18:38 UTC (permalink / raw)
  To: Ben Greear; +Cc: linux-wireless
In-Reply-To: <4EB9703B.6030006@candelatech.com>

On Tue, 2011-11-08 at 10:08 -0800, Ben Greear wrote:

> >> But if
> >> you want multiple vifs to work well, then you really need to be able
> >> to continue to function on-channel when some other vif is scanning
> >> on that channel.  My use of the wifi stack requires this to work,
> >> so if it takes any significant time to get the new code in I'm going
> >> to have to stick with my complex crap.
> >
> > And I'm not saying you shouldn't, but I think for upstream right now
> > it's not really a good thing. I wish I could say otherwise but given the
> > bugs we have here etc. I don't really feel very confident.
> 
> Are there any open bugs right now that seem to be because of the
> scanning and work optimizations, or are you just paranoid that
> there are more that are not found or well understood yet?
> 
> If there is something reported, I'll make a try at fixing it.

I was looking at RH bug 731365 but I think Eliad's patches should have
fixed that. But generally, that code just makes me nervous, in
particular ieee80211_cfg_on_oper_channel(). I think all of this should
be a lot simpler, and if it isn't that's probably due to *other* bugs
this is working around.

> > Now with multi-channel stuff it's all going to change anyway, each vif
> > will have its own channel and the device will have to mostly sort out
> > the scheduling by itself, ath9k will have to do some tricks in the
> > driver, maybe with some help in mac80211, and off-channel stuff will be
> > interesting too ...
> 
> Is someone already working on this, or planning to do so soon?  

I am planning to.

> At least
> to me, the multi-channel stuff appears fundamentally broken since I'm
> not aware of any NIC that can listen in two channels at once.  Flipping
> from channel to channel seems like at best it is going to give bad latency,
> and probably lots of packet loss as well.  What is the use-case for this
> feature, anyway?

Oh, well, for example P2P printing to a printer that's already on
channel 5 while connected to an AP that's already on channel 11. That'd
be temporary, but any quality of service degradation is still better
than not being able to print.

johannes


^ permalink raw reply

* Re: [PATCH v6 1/2] wireless:  Support ht-capabilities over-rides.
From: Johannes Berg @ 2011-11-08 18:21 UTC (permalink / raw)
  To: Ben Greear; +Cc: linux-wireless
In-Reply-To: <4EB9720B.8080704@candelatech.com>

On Tue, 2011-11-08 at 10:16 -0800, Ben Greear wrote:

> > Fair enough. I think what I'm really after is having a way to know wtf
> > we're using when you requested something. That would probably be more
> > useful overall.

ok.

> The current ht_cap settings for each station are in debugfs, so hopefully it
> would not be that difficult to add it to a netlink response.  Perhaps
> it's already there..I haven't looked yet.
> 
> > FWIW, I did talk to some people at the kernel summit about the -EINVAL
> > thing and maybe there's an idea to send back the invalid attribute at
> > least, but doesn't really matter here. I'm OK with just allowing it all
> > since it's not going to be used a lot anyway.
> 
> Ok, I'll add some printks.

I really don't think you should add printks here for this.

> > OTOH, if you request a connect(), you don't even know the band and
> > technically a driver could have different capabilities on different
> > bands.
> 
> Lets see if any other drivers try to support these features.  Anyone
> doing that work will likely see some ways to make use of common code
> and things can be shuffled then.  As written, the patches are not overly
> invasive, so I think we can move stuff around later without too much
> trouble.

Ok, fair enough.

johannes


^ permalink raw reply

* Re: [PATCH v6 1/2] wireless:  Support ht-capabilities over-rides.
From: Ben Greear @ 2011-11-08 18:16 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320775251.24797.31.camel@jlt3.sipsolutions.net>

On 11/08/2011 10:00 AM, Johannes Berg wrote:
> On Tue, 2011-11-08 at 09:43 -0800, Ben Greear wrote:

>>> Also how would you feel about rejecting, instead of silently ignoring,
>>> things that we do look at but don't support, e.g. a wrong A-MSDU
>>> setting? Alternatively, cfg80211 could modify the settings in a way that
>>> drivers don't have to worry about the "downgrade only" part.
>>
>> I dislike that as well, for similar reasons.  Getting an -EINVAL back
>> from a netlink call gives very little info to the user anyway...who
>> knows what exactly was invalid?  Perhaps a printk warning coming out
>> of mac80211 when it checks for the restrictions against what the
>> driver supports would be more useful?
>
> Fair enough. I think what I'm really after is having a way to know wtf
> we're using when you requested something. That would probably be more
> useful overall.

The current ht_cap settings for each station are in debugfs, so hopefully it
would not be that difficult to add it to a netlink response.  Perhaps
it's already there..I haven't looked yet.

> FWIW, I did talk to some people at the kernel summit about the -EINVAL
> thing and maybe there's an idea to send back the invalid attribute at
> least, but doesn't really matter here. I'm OK with just allowing it all
> since it's not going to be used a lot anyway.

Ok, I'll add some printks.

>>> Finally, I think we need a tad more documentation about how this is
>>> supposed to work in case somebody wants to implement it on non-mac80211.
>>> The way it's done right now it seems fairly error prone, with all
>>> restrictions that the driver needs to implement like not allowing the
>>> a-MSDU size to be increased.
>>
>> Well, who knows...in their driver maybe the restrictions are not
>> the same.  I think that adding more info about what fields are
>> currently supported for mac80211 might be useful, but trying to
>> generalize restrictions for drivers that have not even implemented
>> any of this seems like useless overhead.
>
> Well, it goes both ways though, having more validation up front will
> make it a lot easier for new drivers to implement it because they don't
> have to bother with the validation, and I really don't see any way that
> a driver might allow making the a-MPDU spacing *smaller*, if it could
> deal with smaller it'd advertise that to start with.
>
> OTOH, if you request a connect(), you don't even know the band and
> technically a driver could have different capabilities on different
> bands.

Lets see if any other drivers try to support these features.  Anyone
doing that work will likely see some ways to make use of common code
and things can be shuffled then.  As written, the patches are not overly
invasive, so I think we can move stuff around later without too much
trouble.

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Re: [RFT/FYI] mac80211: revert on-channel work optimisations
From: Ben Greear @ 2011-11-08 18:08 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320775001.24797.26.camel@jlt3.sipsolutions.net>

On 11/08/2011 09:56 AM, Johannes Berg wrote:
> On Tue, 2011-11-08 at 09:25 -0800, Ben Greear wrote:
>
>> That's fine by me, I found the code complex as well.  All the tmp
>> and scan and active channel pointers makes for a real mess.
>
> Indeed.
>
>> But if
>> you want multiple vifs to work well, then you really need to be able
>> to continue to function on-channel when some other vif is scanning
>> on that channel.  My use of the wifi stack requires this to work,
>> so if it takes any significant time to get the new code in I'm going
>> to have to stick with my complex crap.
>
> And I'm not saying you shouldn't, but I think for upstream right now
> it's not really a good thing. I wish I could say otherwise but given the
> bugs we have here etc. I don't really feel very confident.

Are there any open bugs right now that seem to be because of the
scanning and work optimizations, or are you just paranoid that
there are more that are not found or well understood yet?

If there is something reported, I'll make a try at fixing it.

> Now with multi-channel stuff it's all going to change anyway, each vif
> will have its own channel and the device will have to mostly sort out
> the scheduling by itself, ath9k will have to do some tricks in the
> driver, maybe with some help in mac80211, and off-channel stuff will be
> interesting too ...

Is someone already working on this, or planning to do so soon?  At least
to me, the multi-channel stuff appears fundamentally broken since I'm
not aware of any NIC that can listen in two channels at once.  Flipping
from channel to channel seems like at best it is going to give bad latency,
and probably lots of packet loss as well.  What is the use-case for this
feature, anyway?

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Re: [PATCH v6 1/2] wireless:  Support ht-capabilities over-rides.
From: Johannes Berg @ 2011-11-08 18:00 UTC (permalink / raw)
  To: Ben Greear; +Cc: linux-wireless
In-Reply-To: <4EB96A5C.8040606@candelatech.com>

On Tue, 2011-11-08 at 09:43 -0800, Ben Greear wrote:

> >> +/*  Do a logical ht_capa&= ht_capa_mask.  */
> >> +static void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
> >> +			const struct ieee80211_ht_cap *ht_capa_mask)

> > I think you also need to call this in the cfg80211_connect() path.
> 
> I'll double check that...for some reason I thought everything
> eventually went through this code path.

Not for full-mac drivers, e.g. iwm.

> > Also, maybe we should reject this configuration if the device didn't
> > support it at all, ie. ht_capa_mask was NULL? It also seems a bit odd to
> > allow this on a device that doesn't even support HT.
> 
> I really don't like that.  It would mean that supplicant will
> have to selectively not add certain netlink attributes based on the
> driver and/or kernel version.  That means either probing
> to determine what the phy supports (and returning errors on
> up to user if they configure it for something not supported?)
> or just forcing the user to make all the decisions when writing
> the supplicant config file.
> 
> The truth is, my app auto-generates the supplicant config files,
> and I know what wifi driver I'm using etc, so it would be easy enough
> for me to live with this.  But, it seems like it will make life
> painful for anyone with less knowledge of the system.
> 
> > Also how would you feel about rejecting, instead of silently ignoring,
> > things that we do look at but don't support, e.g. a wrong A-MSDU
> > setting? Alternatively, cfg80211 could modify the settings in a way that
> > drivers don't have to worry about the "downgrade only" part.
> 
> I dislike that as well, for similar reasons.  Getting an -EINVAL back
> from a netlink call gives very little info to the user anyway...who
> knows what exactly was invalid?  Perhaps a printk warning coming out
> of mac80211 when it checks for the restrictions against what the
> driver supports would be more useful?

Fair enough. I think what I'm really after is having a way to know wtf
we're using when you requested something. That would probably be more
useful overall.

FWIW, I did talk to some people at the kernel summit about the -EINVAL
thing and maybe there's an idea to send back the invalid attribute at
least, but doesn't really matter here. I'm OK with just allowing it all
since it's not going to be used a lot anyway.

> > Finally, I think we need a tad more documentation about how this is
> > supposed to work in case somebody wants to implement it on non-mac80211.
> > The way it's done right now it seems fairly error prone, with all
> > restrictions that the driver needs to implement like not allowing the
> > a-MSDU size to be increased.
> 
> Well, who knows...in their driver maybe the restrictions are not
> the same.  I think that adding more info about what fields are
> currently supported for mac80211 might be useful, but trying to
> generalize restrictions for drivers that have not even implemented
> any of this seems like useless overhead.

Well, it goes both ways though, having more validation up front will
make it a lot easier for new drivers to implement it because they don't
have to bother with the validation, and I really don't see any way that
a driver might allow making the a-MPDU spacing *smaller*, if it could
deal with smaller it'd advertise that to start with.

OTOH, if you request a connect(), you don't even know the band and
technically a driver could have different capabilities on different
bands.

johannes


^ permalink raw reply

* Re: [RFT/FYI] mac80211: revert on-channel work optimisations
From: Johannes Berg @ 2011-11-08 17:56 UTC (permalink / raw)
  To: Ben Greear; +Cc: linux-wireless
In-Reply-To: <4EB9661F.9040901@candelatech.com>

On Tue, 2011-11-08 at 09:25 -0800, Ben Greear wrote:

> That's fine by me, I found the code complex as well.  All the tmp
> and scan and active channel pointers makes for a real mess.  

Indeed.

> But if
> you want multiple vifs to work well, then you really need to be able
> to continue to function on-channel when some other vif is scanning
> on that channel.  My use of the wifi stack requires this to work,
> so if it takes any significant time to get the new code in I'm going
> to have to stick with my complex crap.

And I'm not saying you shouldn't, but I think for upstream right now
it's not really a good thing. I wish I could say otherwise but given the
bugs we have here etc. I don't really feel very confident.

Now with multi-channel stuff it's all going to change anyway, each vif
will have its own channel and the device will have to mostly sort out
the scheduling by itself, ath9k will have to do some tricks in the
driver, maybe with some help in mac80211, and off-channel stuff will be
interesting too ...

johannes


^ permalink raw reply

* Re: [PATCH v6 1/2] wireless:  Support ht-capabilities over-rides.
From: Ben Greear @ 2011-11-08 17:43 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320740099.4304.5.camel@jlt3.sipsolutions.net>

On 11/08/2011 12:14 AM, Johannes Berg wrote:
> On Mon, 2011-11-07 at 15:14 -0800, greearb@candelatech.com wrote:
>
>> +++ b/net/wireless/mlme.c
>> @@ -501,13 +501,32 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
>>   	return err;
>>   }
>>
>> +/*  Do a logical ht_capa&= ht_capa_mask.  */
>> +static void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
>> +			const struct ieee80211_ht_cap *ht_capa_mask)
>> +{
>> +	int i;
>> +	u8 *p1, *p2;
>> +	if (!ht_capa_mask) {
>> +		memset(ht_capa, 0, sizeof(*ht_capa));
>> +		return;
>> +	}
>> +
>> +	p1 = (u8*)(ht_capa);
>> +	p2 = (u8*)(ht_capa_mask);
>> +	for (i = 0; i<sizeof(*ht_capa); i++)
>> +		p1[i]&= p2[i];
>> +}
>
> I think you also need to call this in the cfg80211_connect() path.

I'll double check that...for some reason I thought everything
eventually went through this code path.

>
> Also, maybe we should reject this configuration if the device didn't
> support it at all, ie. ht_capa_mask was NULL? It also seems a bit odd to
> allow this on a device that doesn't even support HT.

I really don't like that.  It would mean that supplicant will
have to selectively not add certain netlink attributes based on the
driver and/or kernel version.  That means either probing
to determine what the phy supports (and returning errors on
up to user if they configure it for something not supported?)
or just forcing the user to make all the decisions when writing
the supplicant config file.

The truth is, my app auto-generates the supplicant config files,
and I know what wifi driver I'm using etc, so it would be easy enough
for me to live with this.  But, it seems like it will make life
painful for anyone with less knowledge of the system.

> Also how would you feel about rejecting, instead of silently ignoring,
> things that we do look at but don't support, e.g. a wrong A-MSDU
> setting? Alternatively, cfg80211 could modify the settings in a way that
> drivers don't have to worry about the "downgrade only" part.

I dislike that as well, for similar reasons.  Getting an -EINVAL back
from a netlink call gives very little info to the user anyway...who
knows what exactly was invalid?  Perhaps a printk warning coming out
of mac80211 when it checks for the restrictions against what the
driver supports would be more useful?

> Finally, I think we need a tad more documentation about how this is
> supposed to work in case somebody wants to implement it on non-mac80211.
> The way it's done right now it seems fairly error prone, with all
> restrictions that the driver needs to implement like not allowing the
> a-MSDU size to be increased.

Well, who knows...in their driver maybe the restrictions are not
the same.  I think that adding more info about what fields are
currently supported for mac80211 might be useful, but trying to
generalize restrictions for drivers that have not even implemented
any of this seems like useless overhead.

Thanks,
Ben

>
> johannes
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Re: [RFT/FYI] mac80211: revert on-channel work optimisations
From: Ben Greear @ 2011-11-08 17:25 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320772727.24797.23.camel@jlt3.sipsolutions.net>

On 11/08/2011 09:18 AM, Johannes Berg wrote:
> On Tue, 2011-11-08 at 09:17 -0800, Ben Greear wrote:
>> On 11/08/2011 09:10 AM, Johannes Berg wrote:
>>> FYI -- I'm going to test this a bit more but I am going to put it in.
>>> The code is a mess -- look at how much code I remove below (and that's
>>> after everybody elses cleanups!) for a dubious optimisation.
>>>
>>> I agree that we should address this and we need to really do this to not
>>> mess up our aggregation state, but the current code is too complex and
>>> causing too many issues. We also need to think about this in the context
>>> of multi-virtual-channel support.
>>
>> Well crap.  Why don't you try to fix it right instead?
>
> Can't even understand it, I have a better chance just rewriting it.

That's fine by me, I found the code complex as well.  All the tmp
and scan and active channel pointers makes for a real mess.  But if
you want multiple vifs to work well, then you really need to be able
to continue to function on-channel when some other vif is scanning
on that channel.  My use of the wifi stack requires this to work,
so if it takes any significant time to get the new code in I'm going
to have to stick with my complex crap.

> Like I said -- I know I'll have to do that, but I need to think about
> this in the context of using different channels on different virtual
> interfaces etc. and probably rework the channel config logic in mac80211
> significantly...

Well, good luck with that.  I'll test patches if you post them.

Thanks,
Ben

>
> johannes


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Re: [RFT/FYI] mac80211: revert on-channel work optimisations
From: Johannes Berg @ 2011-11-08 17:18 UTC (permalink / raw)
  To: Ben Greear; +Cc: linux-wireless
In-Reply-To: <4EB96416.5040700@candelatech.com>

On Tue, 2011-11-08 at 09:17 -0800, Ben Greear wrote:
> On 11/08/2011 09:10 AM, Johannes Berg wrote:
> > FYI -- I'm going to test this a bit more but I am going to put it in.
> > The code is a mess -- look at how much code I remove below (and that's
> > after everybody elses cleanups!) for a dubious optimisation.
> >
> > I agree that we should address this and we need to really do this to not
> > mess up our aggregation state, but the current code is too complex and
> > causing too many issues. We also need to think about this in the context
> > of multi-virtual-channel support.
> 
> Well crap.  Why don't you try to fix it right instead?

Can't even understand it, I have a better chance just rewriting it.

Like I said -- I know I'll have to do that, but I need to think about
this in the context of using different channels on different virtual
interfaces etc. and probably rework the channel config logic in mac80211
significantly...

johannes


^ permalink raw reply

* Re: [RFT/FYI] mac80211: revert on-channel work optimisations
From: Ben Greear @ 2011-11-08 17:17 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320772222.24797.22.camel@jlt3.sipsolutions.net>

On 11/08/2011 09:10 AM, Johannes Berg wrote:
> FYI -- I'm going to test this a bit more but I am going to put it in.
> The code is a mess -- look at how much code I remove below (and that's
> after everybody elses cleanups!) for a dubious optimisation.
>
> I agree that we should address this and we need to really do this to not
> mess up our aggregation state, but the current code is too complex and
> causing too many issues. We also need to think about this in the context
> of multi-virtual-channel support.

Well crap.  Why don't you try to fix it right instead?

I'll probably end up carrying this in my own tree so
that multiple vifs work well and don't constantly
reset the ath9k causing it to shit itself...

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* [PATCH] ath6kl: indicate probe-resp offload support
From: Arik Nemtsov @ 2011-11-08 17:14 UTC (permalink / raw)
  To: linux-wireless; +Cc: Kalle Valo, Arik Nemtsov

The ath6kl responds to probe-requests in HW while operating as an AP. It
supports offloading exclusions to support the WPS, WPS2, P2P and
802.11u protocols.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
---
I haven't added validation in hostap that check for these flags before
sending down the probe-resp IEs. This is still useful for tools such as
iw, that can print out device characteristics.

I'm not sure 802.11u is actually supported, just seemed so from the
hostap code sending down the IEs.

The patch of course depends on
"nl80211: Add probe response offload attribute"

drivers/net/wireless/ath/ath6kl/init.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index b277111..075d904 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1549,7 +1549,13 @@ static int ath6kl_init(struct net_device *dev)
 	ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
 			 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
 
-	ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+	ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
+				  WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+	ar->wdev->wiphy->probe_resp_offload =
+		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
+		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
+		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
+		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
 
 	status = ath6kl_target_config_wlan_params(ar);
 	if (!status)
-- 
1.7.5.4


^ permalink raw reply related

* [RFT/FYI] mac80211: revert on-channel work optimisations
From: Johannes Berg @ 2011-11-08 17:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear

FYI -- I'm going to test this a bit more but I am going to put it in.
The code is a mess -- look at how much code I remove below (and that's
after everybody elses cleanups!) for a dubious optimisation.

I agree that we should address this and we need to really do this to not
mess up our aggregation state, but the current code is too complex and
causing too many issues. We also need to think about this in the context
of multi-virtual-channel support.

johannes



From: Johannes Berg <johannes.berg@intel.com>

The on-channel work optimisations have caused a
number of issues, and the code is unfortunately
very complex and almost impossible to follow.
Instead of attempting to put in more workarounds
let's just remove those optimisations, we can
work on them again later.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
This applies on top of Stanislaw's three patches and
my patch from today to remove the same mess from the
scan code.

 net/mac80211/ieee80211_i.h |    2 
 net/mac80211/main.c        |   41 ------------------
 net/mac80211/offchannel.c  |    9 +---
 net/mac80211/scan.c        |    4 -
 net/mac80211/work.c        |   99 +++------------------------------------------
 5 files changed, 13 insertions(+), 142 deletions(-)

--- a/net/mac80211/work.c	2011-11-08 18:04:34.000000000 +0100
+++ b/net/mac80211/work.c	2011-11-08 18:05:52.000000000 +0100
@@ -881,44 +881,6 @@ static void ieee80211_work_rx_queued_mgm
 	kfree_skb(skb);
 }
 
-static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct,
-				       enum nl80211_channel_type oper_ct)
-{
-	switch (wk_ct) {
-	case NL80211_CHAN_NO_HT:
-		return true;
-	case NL80211_CHAN_HT20:
-		if (oper_ct != NL80211_CHAN_NO_HT)
-			return true;
-		return false;
-	case NL80211_CHAN_HT40MINUS:
-	case NL80211_CHAN_HT40PLUS:
-		return (wk_ct == oper_ct);
-	}
-	WARN_ON(1); /* shouldn't get here */
-	return false;
-}
-
-static enum nl80211_channel_type
-ieee80211_calc_ct(enum nl80211_channel_type wk_ct,
-		  enum nl80211_channel_type oper_ct)
-{
-	switch (wk_ct) {
-	case NL80211_CHAN_NO_HT:
-		return oper_ct;
-	case NL80211_CHAN_HT20:
-		if (oper_ct != NL80211_CHAN_NO_HT)
-			return oper_ct;
-		return wk_ct;
-	case NL80211_CHAN_HT40MINUS:
-	case NL80211_CHAN_HT40PLUS:
-		return wk_ct;
-	}
-	WARN_ON(1); /* shouldn't get here */
-	return wk_ct;
-}
-
-
 static void ieee80211_work_timer(unsigned long data)
 {
 	struct ieee80211_local *local = (void *) data;
@@ -969,40 +931,12 @@ static void ieee80211_work_work(struct w
 		}
 
 		if (!started && !local->tmp_channel) {
-			bool on_oper_chan, on_oper_chan2;
-			enum nl80211_channel_type wk_ct;
-
-			on_oper_chan = ieee80211_cfg_on_oper_channel(local);
-
-			/* Work with existing channel type if possible. */
-			wk_ct = wk->chan_type;
-			if (wk->chan == local->hw.conf.channel)
-				wk_ct = ieee80211_calc_ct(wk->chan_type,
-						local->hw.conf.channel_type);
+			ieee80211_offchannel_stop_vifs(local, true);
 
 			local->tmp_channel = wk->chan;
-			local->tmp_channel_type = wk_ct;
-			/*
-			 * Leave the station vifs in awake mode if they
-			 * happen to be on the same channel as
-			 * the requested channel.
-			 */
-			on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
-			if (on_oper_chan != on_oper_chan2) {
-				if (on_oper_chan2) {
-					/* going off oper channel, PS too */
-					ieee80211_offchannel_stop_vifs(local,
-								       true);
-					ieee80211_hw_config(local, 0);
-				} else {
-					/* going on channel, but leave PS
-					 * off-channel. */
-					ieee80211_hw_config(local, 0);
-					ieee80211_offchannel_return(local,
-								    true,
-								    false);
-				}
-			}
+			local->tmp_channel_type = wk->chan_type;
+
+			ieee80211_hw_config(local, 0);
 
 			started = true;
 			wk->timeout = jiffies;
@@ -1071,34 +1005,17 @@ static void ieee80211_work_work(struct w
 	list_for_each_entry(wk, &local->work_list, list) {
 		if (!wk->started)
 			continue;
-		if (wk->chan != local->tmp_channel)
-			continue;
-		if (!ieee80211_work_ct_coexists(wk->chan_type,
-						local->tmp_channel_type))
+		if (wk->chan != local->tmp_channel ||
+		    wk->chan_type != local->tmp_channel_type)
 			continue;
 		remain_off_channel = true;
 	}
 
 	if (!remain_off_channel && local->tmp_channel) {
 		local->tmp_channel = NULL;
-		/* If tmp_channel wasn't operating channel, then
-		 * we need to go back on-channel.
-		 * NOTE:  If we can ever be here while scannning,
-		 * or if the hw_config() channel config logic changes,
-		 * then we may need to do a more thorough check to see if
-		 * we still need to do a hardware config.  Currently,
-		 * we cannot be here while scanning, however.
-		 */
-		if (!ieee80211_cfg_on_oper_channel(local))
-			ieee80211_hw_config(local, 0);
+		ieee80211_hw_config(local, 0);
 
-		/* At the least, we need to disable offchannel_ps,
-		 * so just go ahead and run the entire offchannel
-		 * return logic here.  We *could* skip enabling
-		 * beaconing if we were already on-oper-channel
-		 * as a future optimization.
-		 */
-		ieee80211_offchannel_return(local, true, true);
+		ieee80211_offchannel_return(local, true);
 
 		/* give connection some time to breathe */
 		run_again(local, jiffies + HZ/2);
--- a/net/mac80211/ieee80211_i.h	2011-11-08 18:05:51.000000000 +0100
+++ b/net/mac80211/ieee80211_i.h	2011-11-08 18:05:52.000000000 +0100
@@ -1139,13 +1139,11 @@ int ieee80211_request_sched_scan_stop(st
 void ieee80211_sched_scan_stopped_work(struct work_struct *work);
 
 /* off-channel helpers */
-bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local);
 void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
 					bool tell_ap);
 void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
 				    bool offchannel_ps_enable);
 void ieee80211_offchannel_return(struct ieee80211_local *local,
-				 bool enable_beaconing,
 				 bool offchannel_ps_disable);
 void ieee80211_hw_roc_setup(struct ieee80211_local *local);
 
--- a/net/mac80211/offchannel.c	2011-11-08 17:51:57.000000000 +0100
+++ b/net/mac80211/offchannel.c	2011-11-08 18:05:52.000000000 +0100
@@ -155,7 +155,6 @@ void ieee80211_offchannel_enable_all_ps(
 }
 
 void ieee80211_offchannel_return(struct ieee80211_local *local,
-				 bool enable_beaconing,
 				 bool offchannel_ps_disable)
 {
 	struct ieee80211_sub_if_data *sdata;
@@ -187,11 +186,9 @@ void ieee80211_offchannel_return(struct
 			netif_tx_wake_all_queues(sdata->dev);
 		}
 
-		/* Check to see if we should re-enable beaconing */
-		if (enable_beaconing &&
-		    (sdata->vif.type == NL80211_IFTYPE_AP ||
-		     sdata->vif.type == NL80211_IFTYPE_ADHOC ||
-		     sdata->vif.type == NL80211_IFTYPE_MESH_POINT))
+		if (sdata->vif.type == NL80211_IFTYPE_AP ||
+		    sdata->vif.type == NL80211_IFTYPE_ADHOC ||
+		    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
 			ieee80211_bss_info_change_notify(
 				sdata, BSS_CHANGED_BEACON_ENABLED);
 	}
--- a/net/mac80211/main.c	2011-11-08 18:04:34.000000000 +0100
+++ b/net/mac80211/main.c	2011-11-08 18:05:52.000000000 +0100
@@ -92,47 +92,6 @@ static void ieee80211_reconfig_filter(st
 	ieee80211_configure_filter(local);
 }
 
-/*
- * Returns true if we are logically configured to be on
- * the operating channel AND the hardware-conf is currently
- * configured on the operating channel.  Compares channel-type
- * as well.
- */
-bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
-{
-	struct ieee80211_channel *chan;
-	enum nl80211_channel_type channel_type;
-
-	/* This logic needs to match logic in ieee80211_hw_config */
-	if (local->scan_channel) {
-		chan = local->scan_channel;
-		/* If scanning on oper channel, use whatever channel-type
-		 * is currently in use.
-		 */
-		if (chan == local->oper_channel)
-			channel_type = local->_oper_channel_type;
-		else
-			channel_type = NL80211_CHAN_NO_HT;
-	} else if (local->tmp_channel) {
-		chan = local->tmp_channel;
-		channel_type = local->tmp_channel_type;
-	} else {
-		chan = local->oper_channel;
-		channel_type = local->_oper_channel_type;
-	}
-
-	if (chan != local->oper_channel ||
-	    channel_type != local->_oper_channel_type)
-		return false;
-
-	/* Check current hardware-config against oper_channel. */
-	if (local->oper_channel != local->hw.conf.channel ||
-	    local->_oper_channel_type != local->hw.conf.channel_type)
-		return false;
-
-	return true;
-}
-
 int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 {
 	struct ieee80211_channel *chan;
--- a/net/mac80211/scan.c	2011-11-08 18:05:51.000000000 +0100
+++ b/net/mac80211/scan.c	2011-11-08 18:05:52.000000000 +0100
@@ -296,7 +296,7 @@ static void __ieee80211_scan_completed(s
 	if (!was_hw_scan) {
 		ieee80211_configure_filter(local);
 		drv_sw_scan_complete(local);
-		ieee80211_offchannel_return(local, true, true);
+		ieee80211_offchannel_return(local, true);
 	}
 
 	ieee80211_recalc_idle(local);
@@ -601,7 +601,7 @@ static void ieee80211_scan_state_suspend
 	 * in off-channel state..will put that back
 	 * on-channel at the end of scanning.
 	 */
-	ieee80211_offchannel_return(local, true, false);
+	ieee80211_offchannel_return(local, false);
 
 	*next_delay = HZ / 5;
 	/* afterwards, resume scan & go to next channel */



^ permalink raw reply

* [PATCH v4 2/2] wl12xx: indicate probe-resp offloading support
From: Arik Nemtsov @ 2011-11-08 16:46 UTC (permalink / raw)
  To: linux-wireless; +Cc: Luciano Coelho, Arik Nemtsov
In-Reply-To: <1320770815-23332-1-git-send-email-arik@wizery.com>

The wl12xx driver supports probe-response offloading, and the  WPS, WPS2
and P2P special cases as well.

Signed-off-by: Guy Eilam <guy@wizery.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
---
v3->4: update name of wiphy flag

drivers/net/wireless/wl12xx/main.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 3750a6e..08b06ee 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -5017,6 +5017,13 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
 
 	wl->hw->wiphy->reg_notifier = wl1271_reg_notify;
 
+	/* the FW answers probe-requests in AP-mode */
+	wl->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+	wl->hw->wiphy->probe_resp_offload =
+		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
+		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
+		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
+
 	SET_IEEE80211_DEV(wl->hw, wl->dev);
 
 	wl->hw->sta_data_size = sizeof(struct wl1271_station);
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH v4 1/2] wl12xx: configure probe-resp template according to notification
From: Arik Nemtsov @ 2011-11-08 16:46 UTC (permalink / raw)
  To: linux-wireless; +Cc: Luciano Coelho, Arik Nemtsov

When operating in AP-mode, replace our probe-response template when a
notification is recieved from mac80211. We preserve the "legacy" way of
configuring a probe-response according to beacon for IBSS mode and for
versions of hostapd that do not support this feature.

Signed-off-by: Guy Eilam <guy@wizery.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
---
v3->4: no changes

drivers/net/wireless/wl12xx/main.c   |   57 +++++++++++++++++++++++++++++----
 drivers/net/wireless/wl12xx/wl12xx.h |    1 +
 2 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index dbb088e..3750a6e 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -3299,11 +3299,30 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb,
 	skb_trim(skb, skb->len - len);
 }
 
-static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl,
-					 struct ieee80211_vif *vif,
-					 u8 *probe_rsp_data,
-					 size_t probe_rsp_len,
-					 u32 rates)
+static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates)
+{
+	struct sk_buff *skb;
+	int ret;
+
+	skb = ieee80211_proberesp_get(wl->hw, wl->vif);
+	if (!skb)
+		return -EINVAL;
+
+	ret = wl1271_cmd_template_set(wl,
+				      CMD_TEMPL_AP_PROBE_RESPONSE,
+				      skb->data,
+				      skb->len, 0,
+				      rates);
+
+	dev_kfree_skb(skb);
+	return ret;
+}
+
+static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl,
+					     struct ieee80211_vif *vif,
+					     u8 *probe_rsp_data,
+					     size_t probe_rsp_len,
+					     u32 rates)
 {
 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
 	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
@@ -3416,6 +3435,16 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
 		wlvif->beacon_int = bss_conf->beacon_int;
 	}
 
+	if ((changed & BSS_CHANGED_AP_PROBE_RESP) && is_ap) {
+		u32 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
+		ret = wl1271_ap_set_probe_resp_tmpl(wl, rate);
+		if (ret < 0)
+			goto out;
+
+		wl1271_debug(DEBUG_AP, "probe response updated");
+		set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags);
+	}
+
 	if ((changed & BSS_CHANGED_BEACON)) {
 		struct ieee80211_hdr *hdr;
 		u32 min_rate;
@@ -3424,8 +3453,10 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
 		struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif);
 		u16 tmpl_id;
 
-		if (!beacon)
+		if (!beacon) {
+			ret = -EINVAL;
 			goto out;
+		}
 
 		wl1271_debug(DEBUG_MASTER, "beacon updated");
 
@@ -3446,6 +3477,13 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
 			goto out;
 		}
 
+		/*
+		 * In case we already have a probe-resp beacon set explicitly
+		 * by usermode, don't use the beacon data.
+		 */
+		if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags))
+			goto end_bcn;
+
 		/* remove TIM ie from probe response */
 		wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset);
 
@@ -3464,7 +3502,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
 		hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 						 IEEE80211_STYPE_PROBE_RESP);
 		if (is_ap)
-			ret = wl1271_ap_set_probe_resp_tmpl(wl, vif,
+			ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif,
 						beacon->data,
 						beacon->len,
 						min_rate);
@@ -3474,12 +3512,15 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
 						beacon->data,
 						beacon->len, 0,
 						min_rate);
+end_bcn:
 		dev_kfree_skb(beacon);
 		if (ret < 0)
 			goto out;
 	}
 
 out:
+	if (ret != 0)
+		wl1271_error("beacon info change failed: %d", ret);
 	return ret;
 }
 
@@ -3536,6 +3577,8 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
 					goto out;
 
 				clear_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags);
+				clear_bit(WLVIF_FLAG_AP_PROBE_RESP_SET,
+					  &wlvif->flags);
 				wl1271_debug(DEBUG_AP, "stopped AP");
 			}
 		}
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index e58e801..f1c9117 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -268,6 +268,7 @@ enum wl12xx_vif_flags {
 	WLVIF_FLAG_RX_STREAMING_STARTED,
 	WLVIF_FLAG_PSPOLL_FAILURE,
 	WLVIF_FLAG_CS_PROGRESS,
+	WLVIF_FLAG_AP_PROBE_RESP_SET,
 };
 
 struct wl1271_link {
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH v4 3/3] mac80211: Save probe response data for bss
From: Arik Nemtsov @ 2011-11-08 16:46 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg, Arik Nemtsov
In-Reply-To: <1320770761-23268-1-git-send-email-arik@wizery.com>

Allow setting a probe response template for an interface operating in
AP mode. Low level drivers are notified about changes in the probe
response template and are able to retrieve a copy of the current probe
response. This data can, for example, be uploaded to hardware as a
template.

Signed-off-by: Guy Eilam <guy@wizery.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
---
v3->4: remove a spurious check and debug print


 include/net/mac80211.h     |   15 +++++++++++++++
 net/mac80211/cfg.c         |   38 +++++++++++++++++++++++++++++++++++---
 net/mac80211/ieee80211_i.h |    1 +
 net/mac80211/iface.c       |    6 +++++-
 net/mac80211/tx.c          |   31 +++++++++++++++++++++++++++++++
 net/mac80211/util.c        |    3 ++-
 6 files changed, 89 insertions(+), 5 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 72eddd1..0f1d784 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -166,6 +166,7 @@ struct ieee80211_low_level_stats {
  *	that it is only ever disabled for station mode.
  * @BSS_CHANGED_IDLE: Idle changed for this BSS/interface.
  * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
+ * @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
  */
 enum ieee80211_bss_change {
 	BSS_CHANGED_ASSOC		= 1<<0,
@@ -184,6 +185,7 @@ enum ieee80211_bss_change {
 	BSS_CHANGED_QOS			= 1<<13,
 	BSS_CHANGED_IDLE		= 1<<14,
 	BSS_CHANGED_SSID		= 1<<15,
+	BSS_CHANGED_AP_PROBE_RESP	= 1<<16,
 
 	/* when adding here, make sure to change ieee80211_reconfig */
 };
@@ -2661,6 +2663,19 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
 }
 
 /**
+ * ieee80211_proberesp_get - retrieve a Probe Response template
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Creates a Probe Response template which can, for example, be uploaded to
+ * hardware. The destination address should be set by the caller.
+ *
+ * Can only be called in AP mode.
+ */
+struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw,
+					struct ieee80211_vif *vif);
+
+/**
  * ieee80211_pspoll_get - retrieve a PS Poll template
  * @hw: pointer obtained from ieee80211_alloc_hw().
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a9ded52..be99b1b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -488,6 +488,31 @@ static void ieee80211_config_ap_ssid(struct ieee80211_sub_if_data *sdata,
 		(params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE);
 }
 
+static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
+				    u8 *resp, size_t resp_len)
+{
+	struct sk_buff *new, *old;
+
+	if (!resp || !resp_len)
+		return -EINVAL;
+
+	old = sdata->u.ap.probe_resp;
+
+	new = dev_alloc_skb(resp_len);
+	if (!new)
+		return -ENOMEM;
+
+	memcpy(skb_put(new, resp_len), resp, resp_len);
+
+	rcu_assign_pointer(sdata->u.ap.probe_resp, new);
+	synchronize_rcu();
+
+	if (old)
+		dev_kfree_skb(old);
+
+	return 0;
+}
+
 /*
  * This handles both adding a beacon and setting new beacon info
  */
@@ -498,6 +523,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
 	int new_head_len, new_tail_len;
 	int size;
 	int err = -EINVAL;
+	u32 changed = 0;
 
 	old = rtnl_dereference(sdata->u.ap.beacon);
 
@@ -581,11 +607,17 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
 
 	kfree(old);
 
+	err = ieee80211_set_probe_resp(sdata, params->probe_resp,
+				       params->probe_resp_len);
+	if (!err)
+		changed |= BSS_CHANGED_AP_PROBE_RESP;
+
 	ieee80211_config_ap_ssid(sdata, params);
+	changed |= BSS_CHANGED_BEACON_ENABLED |
+		   BSS_CHANGED_BEACON |
+		   BSS_CHANGED_SSID;
 
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
-						BSS_CHANGED_BEACON |
-						BSS_CHANGED_SSID);
+	ieee80211_bss_info_change_notify(sdata, changed);
 	return 0;
 }
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ea10a51..5a351cc 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -228,6 +228,7 @@ struct beacon_data {
 
 struct ieee80211_if_ap {
 	struct beacon_data __rcu *beacon;
+	struct sk_buff __rcu *probe_resp;
 
 	struct list_head vlans;
 
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index ef741e8..74d6f79 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -450,15 +450,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 		struct ieee80211_sub_if_data *vlan, *tmpsdata;
 		struct beacon_data *old_beacon =
 			rtnl_dereference(sdata->u.ap.beacon);
+		struct sk_buff *old_probe_resp =
+			rtnl_dereference(sdata->u.ap.probe_resp);
 
 		/* sdata_running will return false, so this will disable */
 		ieee80211_bss_info_change_notify(sdata,
 						 BSS_CHANGED_BEACON_ENABLED);
 
-		/* remove beacon */
+		/* remove beacon and probe response */
 		rcu_assign_pointer(sdata->u.ap.beacon, NULL);
+		rcu_assign_pointer(sdata->u.ap.probe_resp, NULL);
 		synchronize_rcu();
 		kfree(old_beacon);
+		kfree(old_probe_resp);
 
 		/* down all dependent devices, that is VLANs */
 		list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 48bbb96..6b86f77 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2354,6 +2354,37 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_beacon_get_tim);
 
+struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw,
+					struct ieee80211_vif *vif)
+{
+	struct ieee80211_if_ap *ap = NULL;
+	struct sk_buff *presp = NULL, *skb = NULL;
+	struct ieee80211_hdr *hdr;
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+	if (sdata->vif.type != NL80211_IFTYPE_AP)
+		return NULL;
+
+	rcu_read_lock();
+
+	ap = &sdata->u.ap;
+	presp = rcu_dereference(ap->probe_resp);
+	if (!presp)
+		goto out;
+
+	skb = skb_copy(presp, GFP_ATOMIC);
+	if (!skb)
+		goto out;
+
+	hdr = (struct ieee80211_hdr *) skb->data;
+	memset(hdr->addr1, 0, sizeof(hdr->addr1));
+
+out:
+	rcu_read_unlock();
+	return skb;
+}
+EXPORT_SYMBOL(ieee80211_proberesp_get);
+
 struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif)
 {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7439d26..d6d3ef4 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1085,7 +1085,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 			changed |= BSS_CHANGED_IBSS;
 			/* fall through */
 		case NL80211_IFTYPE_AP:
-			changed |= BSS_CHANGED_SSID;
+			changed |= BSS_CHANGED_SSID |
+				   BSS_CHANGED_AP_PROBE_RESP;
 			/* fall through */
 		case NL80211_IFTYPE_MESH_POINT:
 			changed |= BSS_CHANGED_BEACON |
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH v4 2/3] nl80211: Pass probe response data to drivers
From: Arik Nemtsov @ 2011-11-08 16:46 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg, Arik Nemtsov
In-Reply-To: <1320770761-23268-1-git-send-email-arik@wizery.com>

Pass probe-response data from usermode via beacon parameters.

Signed-off-by: Guy Eilam <guy@wizery.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
---
v3->4:
Document contents of the probe-resp attribute

include/linux/nl80211.h |    6 ++++++
 include/net/cfg80211.h  |    4 ++++
 net/wireless/nl80211.c  |    9 +++++++++
 3 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e468d0b..c901c6b 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1114,6 +1114,10 @@ enum nl80211_commands {
  *	This attribute holds a bitmap of the supported protocols for
  *	offloading (see &enum nl80211_probe_resp_offload_support_attr).
  *
+ * @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire
+ *	probe-response frame. The DA field in the 802.11 header is zero-ed out,
+ *	to be filled by the FW.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1344,6 +1348,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_PROBE_RESP_OFFLOAD_SUPPORT,
 
+	NL80211_ATTR_PROBE_RESP,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9e8aa88..713c17b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -391,6 +391,8 @@ struct cfg80211_crypto_settings {
  * @assocresp_ies: extra information element(s) to add into (Re)Association
  *	Response frames or %NULL
  * @assocresp_ies_len: length of assocresp_ies in octets
+ * @probe_resp_len: length of probe response template (@probe_resp)
+ * @probe_resp: probe response template (AP mode only)
  */
 struct beacon_parameters {
 	u8 *head, *tail;
@@ -408,6 +410,8 @@ struct beacon_parameters {
 	size_t proberesp_ies_len;
 	const u8 *assocresp_ies;
 	size_t assocresp_ies_len;
+	int probe_resp_len;
+	u8 *probe_resp;
 };
 
 /**
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 62acdb8..4902213 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -196,6 +196,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
 	[NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
 	[NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
+	[NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
+				      .len = IEEE80211_MAX_DATA_LEN },
 };
 
 /* policy for the key attributes */
@@ -2160,6 +2162,13 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
 			nla_len(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]);
 	}
 
+	if (info->attrs[NL80211_ATTR_PROBE_RESP]) {
+		params.probe_resp =
+			nla_data(info->attrs[NL80211_ATTR_PROBE_RESP]);
+		params.probe_resp_len =
+			nla_len(info->attrs[NL80211_ATTR_PROBE_RESP]);
+	}
+
 	err = call(&rdev->wiphy, dev, &params);
 	if (!err && params.interval)
 		wdev->beacon_interval = params.interval;
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH v4 1/3] nl80211: Add probe response offload attribute
From: Arik Nemtsov @ 2011-11-08 16:45 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg, Arik Nemtsov

Notify user-space about probe-response offloading support in the driver.

A wiphy flag is used to indicate support and a bitmap of protocols
determines which protocols are supported.

Signed-off-by: Guy Eilam <guy@wizery.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
---
v3->4:
- Add missing documentation
- Make comments more explicit about probe-resp offloading being always
  in-effect for supporting devices.

include/linux/nl80211.h |   28 ++++++++++++++++++++++++++++
 include/net/cfg80211.h  |   10 ++++++++++
 net/wireless/nl80211.c  |    5 +++++
 3 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 8049bf7..e468d0b 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1109,6 +1109,11 @@ enum nl80211_commands {
  *	%NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
  *	used for asking the driver to perform a TDLS operation.
  *
+ * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe
+ *	requests while operating in AP-mode.
+ *	This attribute holds a bitmap of the supported protocols for
+ *	offloading (see &enum nl80211_probe_resp_offload_support_attr).
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1337,6 +1342,8 @@ enum nl80211_attrs {
 	NL80211_ATTR_TDLS_SUPPORT,
 	NL80211_ATTR_TDLS_EXTERNAL_SETUP,
 
+	NL80211_ATTR_PROBE_RESP_OFFLOAD_SUPPORT,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2650,4 +2657,25 @@ enum nl80211_tdls_operation {
 	NL80211_TDLS_DISABLE_LINK,
 };
 
+/**
+ * enum nl80211_probe_resp_offload_support_attr - optional supported
+ *	protocols for probe-response offloading by the driver/FW.
+ *	To be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD attribute.
+ *	Each enum value represents a bit in the bitmap of supported
+ *	protocols. Typically a subset of probe-requests belonging to a
+ *	supported protocol will be excluded from offload and uploaded
+ *	to the host.
+ *
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: Support for WPS ver. 1
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: Support for WPS ver. 2
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: Support for P2P
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: Support for 802.11u
+ */
+enum nl80211_probe_resp_offload_support_attr {
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS =	1<<0,
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 =	1<<1,
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P =	1<<2,
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U =	1<<3,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 92cf1c2..9e8aa88 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1675,6 +1675,8 @@ struct cfg80211_ops {
  *	teardown packets should be sent through the @NL80211_CMD_TDLS_MGMT
  *	command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be
  *	used for asking the driver/firmware to perform a TDLS operation.
+ * @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD: When operating as an AP, the device
+ *	responds to probe-requests in hardware.
  */
 enum wiphy_flags {
 	WIPHY_FLAG_CUSTOM_REGULATORY		= BIT(0),
@@ -1693,6 +1695,7 @@ enum wiphy_flags {
 	WIPHY_FLAG_AP_UAPSD			= BIT(14),
 	WIPHY_FLAG_SUPPORTS_TDLS		= BIT(15),
 	WIPHY_FLAG_TDLS_EXTERNAL_SETUP		= BIT(16),
+	WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD	= BIT(17),
 };
 
 /**
@@ -1956,6 +1959,13 @@ struct wiphy {
 	u32 available_antennas_tx;
 	u32 available_antennas_rx;
 
+	/*
+	 * Bitmap of supported protocols for probe response offloading
+	 * see &enum nl80211_probe_resp_offload_support_attr. Only valid
+	 * when the wiphy flag @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD is set.
+	 */
+	u32 probe_resp_offload;
+
 	/* If multiple wiphys are registered and you're handed e.g.
 	 * a regular netdev with assigned ieee80211_ptr, you won't
 	 * know whether it points to a wiphy your driver has registered
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b3a476f..62acdb8 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -758,6 +758,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
 		    dev->wiphy.available_antennas_rx);
 
+	if (dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD)
+		NLA_PUT_U32(msg,
+			NL80211_ATTR_PROBE_RESP_OFFLOAD_SUPPORT,
+			dev->wiphy.probe_resp_offload);
+
 	if ((dev->wiphy.available_antennas_tx ||
 	     dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) {
 		u32 tx_ant = 0, rx_ant = 0;
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH 1/2] ath9k: add DFS radar pulse processing
From: Zefir Kurtisi @ 2011-11-08 16:34 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ath9k-devel, rodrigue, shafi.wireless, nbd,
	Zefir Kurtisi
In-Reply-To: <1320770044-12271-1-git-send-email-zefir.kurtisi@neratec.com>

This initial DFS module provides basic functionality to deal with
radar pulses reported by the DFS HW pulse detector.

The reported data is evaluated and basic plausibility checks are
performed to filter false pulses. Passing radar pulses are
forwarded to pattern detectors (not part of this patch).

The patch also includes
 * new debug level ATH_DBG_DFS
 * debugfs DFS radar statistics

Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
---
 drivers/net/wireless/ath/ath.h             |    2 +
 drivers/net/wireless/ath/ath9k/dfs.c       |  203 ++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/dfs.h       |   38 +++++
 drivers/net/wireless/ath/ath9k/dfs_debug.c |   89 ++++++++++++
 drivers/net/wireless/ath/ath9k/dfs_debug.h |   59 ++++++++
 5 files changed, 391 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath9k/dfs.c
 create mode 100644 drivers/net/wireless/ath/ath9k/dfs.h
 create mode 100644 drivers/net/wireless/ath/ath9k/dfs_debug.c
 create mode 100644 drivers/net/wireless/ath/ath9k/dfs_debug.h

diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 46d6926..e38fcad 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -215,6 +215,7 @@ do {								\
  * @ATH_DBG_HWTIMER: hardware timer handling
  * @ATH_DBG_BTCOEX: bluetooth coexistance
  * @ATH_DBG_BSTUCK: stuck beacons
+ * @ATH_DBG_DFS: radar datection
  * @ATH_DBG_ANY: enable all debugging
  *
  * The debug level is used to control the amount and type of debugging output
@@ -240,6 +241,7 @@ enum ATH_DEBUG {
 	ATH_DBG_BTCOEX		= 0x00002000,
 	ATH_DBG_WMI		= 0x00004000,
 	ATH_DBG_BSTUCK		= 0x00008000,
+	ATH_DBG_DFS		= 0x00010000,
 	ATH_DBG_ANY		= 0xffffffff
 };
 
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c
new file mode 100644
index 0000000..c6d2eea
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/dfs.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "ath9k.h"
+#include "dfs.h"
+#include "dfs_debug.h"
+
+/* convert pulse duration to usecs, considering clock mode */
+static u32 dur_to_usecs(struct ath_hw *ah, u32 dur)
+{
+	const u32 AR93X_NSECS_PER_DUR = 800;
+	const u32 AR93X_NSECS_PER_DUR_FAST = (8000 / 11);
+	u32 nsecs;
+	if (IS_CHAN_A_FAST_CLOCK(ah, ah->curchan))
+		nsecs = dur * AR93X_NSECS_PER_DUR_FAST;
+	else
+		nsecs = dur * AR93X_NSECS_PER_DUR;
+
+	return (nsecs + 500) / 1000;
+}
+
+/* internal struct to pass radar data */
+struct ath_radar_data {
+	u8 pulse_bw_info;
+	u8 rssi;
+	u8 ext_rssi;
+	u8 pulse_length_ext;
+	u8 pulse_length_pri;
+};
+
+/* TODO: move into or synchronize this with generic header
+ *       as soon as IF is defined */
+struct dfs_radar_pulse {
+	u16 freq;
+	u64 ts;
+	u32 width;
+	u8 rssi;
+};
+
+#define PRI_CH_RADAR_FOUND 0x01
+#define EXT_CH_RADAR_FOUND 0x02
+static bool ath9k_postprocess_radar_event(struct ath_softc *sc,
+		struct ath_radar_data *are, struct dfs_radar_pulse *drp)
+{
+	u8 rssi;
+	u16 dur;
+
+	ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_DFS,
+		"pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n",
+		are->pulse_bw_info,
+		are->pulse_length_pri, are->rssi,
+		are->pulse_length_ext, are->ext_rssi);
+
+	/* Only the last 2 bits of the BW info are relevant, they indicate
+	 which channel the radar was detected in.*/
+	are->pulse_bw_info &= 0x03;
+
+	switch (are->pulse_bw_info) {
+	case PRI_CH_RADAR_FOUND:
+		/* radar in ctrl channel */
+		dur = are->pulse_length_pri;
+		DFS_STAT_INC(sc, pri_phy_errors);
+		/* cannot use ctrl channel RSSI
+		 * if extension channel is stronger */
+		rssi = (are->ext_rssi >= (are->rssi + 3)) ? 0 : are->rssi;
+		break;
+	case EXT_CH_RADAR_FOUND:
+		/* radar in extension channel */
+		dur = are->pulse_length_ext;
+		DFS_STAT_INC(sc, ext_phy_errors);
+		/* cannot use extension channel RSSI
+		 * if control channel is stronger */
+		rssi = (are->rssi >= (are->ext_rssi + 12)) ? 0 : are->ext_rssi;
+		break;
+	case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND):
+		/*
+		 * Conducted testing, when pulse is on DC, both pri and ext
+		 * durations are reported to be same
+		 *
+		 * Radiated testing, when pulse is on DC, different pri and
+		 * ext durations are reported, so take the larger of the two
+		 * */
+		if (are->pulse_length_ext >= are->pulse_length_pri)
+			dur = are->pulse_length_ext;
+		else
+			dur = are->pulse_length_pri;
+		DFS_STAT_INC(sc, dc_phy_errors);
+
+		/* when both are present use stronger one */
+		rssi = (are->rssi < are->ext_rssi) ? are->ext_rssi : are->rssi;
+		break;
+	default:
+		/* Bogus bandwidth info received in descriptor,
+		 so ignore this PHY error */
+		DFS_STAT_INC(sc, bwinfo_discards);
+		return false;
+	}
+
+	if (rssi == 0) {
+		DFS_STAT_INC(sc, rssi_discards);
+		return false;
+	}
+
+	/*
+	 * TODO: check chirping pulses
+	 *   checks for chirping are dependent on the DFS regulatory domain
+	 *   used, which is yet TBD
+	 */
+
+	/* convert duration to usecs */
+	drp->width = dur_to_usecs(sc->sc_ah, dur);
+	drp->rssi = rssi;
+
+	DFS_STAT_INC(sc, pulses_detected);
+	return true;
+}
+#undef PRI_CH_RADAR_FOUND
+#undef EXT_CH_RADAR_FOUND
+
+
+/*
+ * DFS: check PHY-error for radar pulse and feed the detector
+ */
+void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
+		struct ath_rx_status *rs, u64 mactime)
+{
+	struct ath_radar_data ard;
+	u16 datalen;
+	char *vdata_end;
+	struct dfs_radar_pulse drp;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if ((!(rs->rs_phyerr != ATH9K_PHYERR_RADAR)) &&
+		(!(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT))) {
+		ath_dbg(common, ATH_DBG_DFS,
+			"Error: rs_phyer=0x%x not a radar error\n",
+			rs->rs_phyerr);
+		return;
+	}
+
+	datalen = rs->rs_datalen;
+	if (datalen == 0) {
+		DFS_STAT_INC(sc, datalen_discards);
+		return;
+	}
+
+	ard.rssi = rs->rs_rssi_ctl0;
+	ard.ext_rssi = rs->rs_rssi_ext0;
+
+	/* hardware stores this as 8 bit signed value.
+	 * we will cap it at 0 if it is a negative number
+	 */
+	if (ard.rssi & 0x80)
+		ard.rssi = 0;
+	if (ard.ext_rssi & 0x80)
+		ard.ext_rssi = 0;
+
+	vdata_end = (char *)data + datalen;
+	ard.pulse_bw_info = vdata_end[-1];
+	ard.pulse_length_ext = vdata_end[-2];
+	ard.pulse_length_pri = vdata_end[-3];
+
+	ath_dbg(common, ATH_DBG_DFS,
+		"bw_info=%d, length_pri=%d, length_ext=%d, "
+		"rssi_pri=%d, rssi_ext=%d\n",
+		ard.pulse_bw_info, ard.pulse_length_pri, ard.pulse_length_ext,
+		ard.rssi, ard.ext_rssi);
+
+	drp.freq = ah->curchan->channel;
+	drp.ts = mactime;
+	if (ath9k_postprocess_radar_event(sc, &ard, &drp)) {
+		static u64 last_ts;
+		ath_dbg(common, ATH_DBG_DFS,
+			"ath9k_dfs_process_phyerr: channel=%d, ts=%llu, "
+			"width=%d, rssi=%d, delta_ts=%llu\n",
+			drp.freq, drp.ts, drp.width, drp.rssi, drp.ts-last_ts);
+		last_ts = drp.ts;
+		/*
+		 * TODO: forward pulse to pattern detector
+		 *
+		 * ieee80211_add_radar_pulse(drp.freq, drp.ts,
+		 *                           drp.width, drp.rssi);
+		 */
+	}
+}
+EXPORT_SYMBOL(ath9k_dfs_process_phyerr);
diff --git a/drivers/net/wireless/ath/ath9k/dfs.h b/drivers/net/wireless/ath/ath9k/dfs.h
new file mode 100644
index 0000000..c73c175
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/dfs.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH9K_DFS_H
+#define ATH9K_DFS_H
+
+/**
+ * ath9k_dfs_process_phyerr - process radar PHY error
+ * @sc: ath_softc
+ * @data: RX payload data
+ * @rs: RX status after processing descriptor
+ * @mactime: receive time
+ *
+ * This function is called whenever the HW DFS module detects a radar
+ * pulse and reports it as a PHY error.
+ *
+ * The radar information provided as raw payload data is validated and
+ * filtered for false pulses. Events passing all tests are forwarded to
+ * the upper layer for pattern detection.
+ */
+void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
+		struct ath_rx_status *rs, u64 mactime);
+
+#endif /* ATH9K_DFS_H */
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c
new file mode 100644
index 0000000..3c03552
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#include <linux/debugfs.h>
+
+#include "ath9k.h"
+#include "dfs_debug.h"
+
+
+#if defined(CONFIG_ATH9K_DEBUGFS)
+
+#define ATH9K_DFS_STAT(s, p) \
+	len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \
+			sc->debug.stats.dfs_stats.p);
+
+static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
+			     size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	struct ath9k_hw_version *hw_ver = &sc->sc_ah->hw_version;
+	char *buf;
+	unsigned int len = 0, size = 8000;
+	ssize_t retval = 0;
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	len += snprintf(buf + len, size - len, "DFS support for "
+			"macVersion = 0x%x, macRev = 0x%x: %s\n",
+			hw_ver->macVersion, hw_ver->macRev,
+			(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ?
+					"enabled" : "disabled");
+	ATH9K_DFS_STAT("DFS pulses detected     ", pulses_detected);
+	ATH9K_DFS_STAT("Datalen discards        ", datalen_discards);
+	ATH9K_DFS_STAT("RSSI discards           ", rssi_discards);
+	ATH9K_DFS_STAT("BW info discards        ", bwinfo_discards);
+	ATH9K_DFS_STAT("Primary channel pulses  ", pri_phy_errors);
+	ATH9K_DFS_STAT("Secondary channel pulses", ext_phy_errors);
+	ATH9K_DFS_STAT("Dual channel pulses     ", dc_phy_errors);
+
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+static int ath9k_dfs_debugfs_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+
+static const struct file_operations fops_dfs_stats = {
+	.read = read_file_dfs,
+	.open = ath9k_dfs_debugfs_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+
+void ath9k_dfs_init_debug(struct ath_softc *sc)
+{
+	debugfs_create_file("dfs_stats", S_IRUSR,
+			sc->debug.debugfs_phy, sc, &fops_dfs_stats);
+}
+EXPORT_SYMBOL(ath9k_dfs_init_debug);
+
+#endif /* CONFIG_ATH9K_DEBUGFS */
+
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.h b/drivers/net/wireless/ath/ath9k/dfs_debug.h
new file mode 100644
index 0000000..079cf53
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/dfs_debug.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef DFS_DEBUG_H
+#define DFS_DEBUG_H
+
+#include "hw.h"
+
+/**
+ * struct ath_dfs_stats - DFS Statistics
+ *
+ * @pulses_detected:  No. of pulses detected so far
+ * @datalen_discards: No. of pulses discarded due to invalid datalen
+ * @rssi_discards:    No. of pulses discarded due to invalid RSSI
+ * @bwinfo_discards:  No. of pulses discarded due to invalid BW info
+ * @pri_phy_errors:   No. of pulses reported for primary channel
+ * @ext_phy_errors:   No. of pulses reported for extension channel
+ * @dc_phy_errors:    No. of pulses reported for primary + extension channel
+ */
+struct ath_dfs_stats {
+	u32 pulses_detected;
+	u32 datalen_discards;
+	u32 rssi_discards;
+	u32 bwinfo_discards;
+	u32 pri_phy_errors;
+	u32 ext_phy_errors;
+	u32 dc_phy_errors;
+};
+
+
+#if defined(CONFIG_ATH9K_DEBUGFS)
+
+#define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++)
+void ath9k_dfs_init_debug(struct ath_softc *sc);
+
+#else
+
+#define DFS_STAT_INC(sc, c) do { } while (0)
+static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { }
+
+#endif
+
+
+#endif /* DFS_DEBUG_H */
-- 
1.7.4.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox