Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [RFC v2 2/2] ath9k: integrate initial DFS module
From: Felix Fietkau @ 2011-11-03 15:11 UTC (permalink / raw)
  To: Zefir Kurtisi; +Cc: linux-wireless, ath9k-devel, rodrigue
In-Reply-To: <1320328553-28066-3-git-send-email-zefir.kurtisi@neratec.com>

On 2011-11-03 2:55 PM, Zefir Kurtisi wrote:
> This patch integrates the DFS module into ath9k, including
>   * building the module into ath9k_hw
>   * setting up DFS debugfs
>   * defining HW capability flag for DFS support
>   * setting this flag by DFS supporting devices
>     (so far: AR_SREV_9280_20_OR_LATER, TBC)
>   * setting PHYRADAR rx filter flag to enable radar
>     pulse reporting
>   * forward radar PHY errors to dfs module
>
> This is WIP and at its current stage is limited to test ath9k
> pulse detection capabilities. The DFS pattern matching is
> TBD in the higher layers and is not part of this patch.
>
> CONFIG_ATH9K_DFS must be set to enable pulse detection.
>
> Signed-off-by: Zefir Kurtisi<zefir.kurtisi@neratec.com>
> ---
>   drivers/net/wireless/ath/ath9k/Makefile |    2 ++
>   drivers/net/wireless/ath/ath9k/debug.c  |    3 +++
>   drivers/net/wireless/ath/ath9k/debug.h  |    2 ++
>   drivers/net/wireless/ath/ath9k/hw.c     |   12 ++++++++++++
>   drivers/net/wireless/ath/ath9k/hw.h     |    1 +
>   drivers/net/wireless/ath/ath9k/main.c   |   17 +++++++++++++++++
>   drivers/net/wireless/ath/ath9k/recv.c   |   18 +++++++++++++-----
>   7 files changed, 50 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
> index d3b92ce..4d70aab 100644
> --- a/drivers/net/wireless/ath/ath9k/main.c
> +++ b/drivers/net/wireless/ath/ath9k/main.c
> @@ -305,6 +305,23 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
>   		ath9k_hw_antdiv_comb_conf_set(ah,&div_ant_conf);
>   	}
>
> +	if (ah->caps.hw_caps&&  ATH9K_HW_CAP_DFS) {
> +		/**
> +		 * enable radar pulse detection
> +		 *
> +		 * TODO: do this only for DFS channels
> +		 */
> +		ah->private_ops.set_radar_params(ah,&ah->radar_conf);
> +		ath9k_hw_setrxfilter(ah,
> +			ath9k_hw_getrxfilter(ah) | ATH9K_RX_FILTER_PHYRADAR);
> +		ath_dbg(common, ATH_DBG_DFS,
> +			"DFS radar detection enabled for channel %d\n",
> +			ah->curchan->channel);
> +	} else {
> +		ath9k_hw_setrxfilter(ah,
> +			ath9k_hw_getrxfilter(ah)&  ~ATH9K_RX_FILTER_PHYRADAR);
> +	}
> +
Please drop this chunk of code and move the check to ath_calcrxfilter, 
which gets called after every reset anyway. Also, use a separate flag in 
sc->flags for actually enabling DFS. Even if the chip has DFS support, 
we don't always want to enable it - especially not on 2.4 GHz or indoor 
5 GHz channels.

- Felix


^ permalink raw reply

* [RFC v2 2/2] ath9k: integrate initial DFS module
From: Zefir Kurtisi @ 2011-11-03 13:55 UTC (permalink / raw)
  To: linux-wireless, ath9k-devel; +Cc: rodrigue, nbd, Zefir Kurtisi
In-Reply-To: <1320328553-28066-1-git-send-email-zefir.kurtisi@neratec.com>

This patch integrates the DFS module into ath9k, including
 * building the module into ath9k_hw
 * setting up DFS debugfs
 * defining HW capability flag for DFS support
 * setting this flag by DFS supporting devices
   (so far: AR_SREV_9280_20_OR_LATER, TBC)
 * setting PHYRADAR rx filter flag to enable radar
   pulse reporting
 * forward radar PHY errors to dfs module

This is WIP and at its current stage is limited to test ath9k
pulse detection capabilities. The DFS pattern matching is
TBD in the higher layers and is not part of this patch.

CONFIG_ATH9K_DFS must be set to enable pulse detection.

Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
---
 drivers/net/wireless/ath/ath9k/Makefile |    2 ++
 drivers/net/wireless/ath/ath9k/debug.c  |    3 +++
 drivers/net/wireless/ath/ath9k/debug.h  |    2 ++
 drivers/net/wireless/ath/ath9k/hw.c     |   12 ++++++++++++
 drivers/net/wireless/ath/ath9k/hw.h     |    1 +
 drivers/net/wireless/ath/ath9k/main.c   |   17 +++++++++++++++++
 drivers/net/wireless/ath/ath9k/recv.c   |   18 +++++++++++++-----
 7 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 36ed3c4..1f260a5 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -29,6 +29,8 @@ ath9k_hw-y:=	\
 		eeprom_9287.o \
 		ani.o \
 		btcoex.o \
+		dfs.o \
+		dfs_debug.o \
 		mac.o \
 		ar9002_mac.o \
 		ar9003_mac.o \
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 138ae09..6642108 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1633,6 +1633,9 @@ int ath9k_init_debug(struct ath_hw *ah)
 	debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
 			    sc, &fops_debug);
 #endif
+
+	ath9k_dfs_init_debug(sc);
+
 	debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
 			    &fops_dma);
 	debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 4f6c939..f70735a 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -19,6 +19,7 @@
 
 #include "hw.h"
 #include "rc.h"
+#include "dfs_debug.h"
 
 struct ath_txq;
 struct ath_buf;
@@ -180,6 +181,7 @@ struct ath_stats {
 	struct ath_interrupt_stats istats;
 	struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
 	struct ath_rx_stats rxstats;
+	struct ath_dfs_stats dfs_stats;
 	u32 reset[__RESET_TYPE_MAX];
 };
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 76dbc85..0f2fb42 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2333,6 +2333,18 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 		pCap->pcie_lcr_offset = 0x80;
 	}
 
+#ifdef CONFIG_ATH9K_DFS
+	/*
+	 * enable radar detection on DFS supporting devices
+	 */
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
+		/*
+		 * TODO: check for which chip-sets we want to support DFS
+		 */
+		pCap->hw_caps |= ATH9K_HW_CAP_DFS;
+	}
+#endif
+
 	tx_chainmask = pCap->tx_chainmask;
 	rx_chainmask = pCap->rx_chainmask;
 	while (tx_chainmask || rx_chainmask) {
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 9dbc3cd..4f02f83 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -204,6 +204,7 @@ enum ath9k_hw_caps {
 	ATH9K_HW_CAP_5GHZ			= BIT(14),
 	ATH9K_HW_CAP_APM			= BIT(15),
 	ATH9K_HW_CAP_RTT			= BIT(16),
+	ATH9K_HW_CAP_DFS			= BIT(17),
 };
 
 struct ath9k_hw_capabilities {
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index d3b92ce..4d70aab 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -305,6 +305,23 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
 		ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf);
 	}
 
+	if (ah->caps.hw_caps && ATH9K_HW_CAP_DFS) {
+		/**
+		 * enable radar pulse detection
+		 *
+		 * TODO: do this only for DFS channels
+		 */
+		ah->private_ops.set_radar_params(ah, &ah->radar_conf);
+		ath9k_hw_setrxfilter(ah,
+			ath9k_hw_getrxfilter(ah) | ATH9K_RX_FILTER_PHYRADAR);
+		ath_dbg(common, ATH_DBG_DFS,
+			"DFS radar detection enabled for channel %d\n",
+			ah->curchan->channel);
+	} else {
+		ath9k_hw_setrxfilter(ah,
+			ath9k_hw_getrxfilter(ah) & ~ATH9K_RX_FILTER_PHYRADAR);
+	}
+
 	ieee80211_wake_queues(sc->hw);
 
 	return true;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index a46e6ab..5dfd081 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -17,6 +17,7 @@
 #include <linux/dma-mapping.h>
 #include "ath9k.h"
 #include "ar9003_mac.h"
+#include "dfs.h"
 
 #define SKB_CB_ATHBUF(__skb)	(*((struct ath_buf **)__skb->cb))
 
@@ -1865,11 +1866,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		if (sc->sc_flags & SC_OP_RXFLUSH)
 			goto requeue_drop_frag;
 
-		retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
-						 rxs, &decrypt_error);
-		if (retval)
-			goto requeue_drop_frag;
-
 		rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
 		if (rs.rs_tstamp > tsf_lower &&
 		    unlikely(rs.rs_tstamp - tsf_lower > 0x10000000))
@@ -1879,6 +1875,18 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		    unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
 			rxs->mactime += 0x100000000ULL;
 
+		if ((ah->caps.hw_caps & ATH9K_HW_CAP_DFS) &&
+		    (rs.rs_status & ATH9K_RXERR_PHY) &&
+		    (rs.rs_phyerr == ATH9K_PHYERR_RADAR)) {
+			/* DFS: check for radar pulse */
+			ath9k_dfs_process_phyerr(sc, hdr, &rs, rxs->mactime);
+		}
+
+		retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
+						 rxs, &decrypt_error);
+		if (retval)
+			goto requeue_drop_frag;
+
 		/* Ensure we always have an skb to requeue once we are done
 		 * processing the current buffer's skb */
 		requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC);
-- 
1.7.4.1


^ permalink raw reply related

* [RFC v2 1/2] ath9k: add DFS radar pulse processing
From: Zefir Kurtisi @ 2011-11-03 13:55 UTC (permalink / raw)
  To: linux-wireless, ath9k-devel; +Cc: rodrigue, nbd, Zefir Kurtisi
In-Reply-To: <1320328553-28066-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 pattern 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       |  192 ++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/dfs.h       |   24 ++++
 drivers/net/wireless/ath/ath9k/dfs_debug.c |   89 +++++++++++++
 drivers/net/wireless/ath/ath9k/dfs_debug.h |   59 +++++++++
 5 files changed, 366 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..9d3c8b9
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/dfs.c
@@ -0,0 +1,192 @@
+/*
+ * 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"
+
+/* pulse duration reported is scaled with 1000/800 us */
+#define AR93X_NSECS_PER_DUR 800
+static u32 dur_to_usecs(u32 dur)
+{
+	return (dur * AR93X_NSECS_PER_DUR + 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 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 0:
+		/* Bogus bandwidth info received in descriptor,
+		 so ignore this PHY error */
+		DFS_STAT_INC(sc, bwinfo_discards);
+		return false;
+	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;
+	}
+
+	if (rssi == 0) {
+		DFS_STAT_INC(sc, rssi_discards);
+		return false;
+	}
+
+	/*
+	 * TODO: check chirping pulses
+	 */
+
+	/* convert duration to usecs */
+	drp->width = dur_to_usecs(dur);
+	drp->rssi = rssi;
+
+	DFS_STAT_INC(sc, pulses_detected);
+	return true;
+}
+
+
+/*
+ * 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 (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..4d95cad
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/dfs.h
@@ -0,0 +1,24 @@
+/*
+ * 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
+
+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

* [RFC v2 0/2] ath9k: DFS radar detection
From: Zefir Kurtisi @ 2011-11-03 13:55 UTC (permalink / raw)
  To: linux-wireless, ath9k-devel; +Cc: rodrigue, nbd, Zefir Kurtisi

This patch series proposes DFS radar pulse detection for ath9k.

Updates
 * use DFS HW capability flag instead of #ifdefs
 * disable feature by default
 * moved DFS debugfs into own file
 * reverted BIT() debug flags to hex
 * limited DFS support to AR_SREV_9280_20_OR_LATER (TBC)
 * minor changes considering feedback


Zefir Kurtisi (2):
  ath9k: add DFS radar pulse processing
  ath9k: integrate initial DFS module

 drivers/net/wireless/ath/ath.h             |    2 +
 drivers/net/wireless/ath/ath9k/Makefile    |    2 +
 drivers/net/wireless/ath/ath9k/debug.c     |    3 +
 drivers/net/wireless/ath/ath9k/debug.h     |    2 +
 drivers/net/wireless/ath/ath9k/dfs.c       |  192 ++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/dfs.h       |   24 ++++
 drivers/net/wireless/ath/ath9k/dfs_debug.c |   89 +++++++++++++
 drivers/net/wireless/ath/ath9k/dfs_debug.h |   59 +++++++++
 drivers/net/wireless/ath/ath9k/hw.c        |   12 ++
 drivers/net/wireless/ath/ath9k/hw.h        |    1 +
 drivers/net/wireless/ath/ath9k/main.c      |   17 +++
 drivers/net/wireless/ath/ath9k/recv.c      |   18 ++-
 12 files changed, 416 insertions(+), 5 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

-- 
1.7.4.1


^ permalink raw reply

* [PATCH 3.2] cfg80211: allow setting TXQ parameters only in AP mode
From: Johannes Berg @ 2011-11-03 13:50 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, Eliad Peller

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

In other modes the parameters should not be set.
Right now, mac80211 will set them, even if the
user asked for setting them on VLANs which the
driver doesn't know about, causing all kinds of
trouble.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/wireless/nl80211.c |    6 ++++++
 1 file changed, 6 insertions(+)

--- a/net/wireless/nl80211.c	2011-11-03 14:41:42.000000000 +0100
+++ b/net/wireless/nl80211.c	2011-11-03 14:47:23.000000000 +0100
@@ -1252,6 +1252,12 @@ static int nl80211_set_wiphy(struct sk_b
 			goto bad_res;
 		}
 
+		if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+		    netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
+			result = -EINVAL;
+			goto bad_res;
+		}
+
 		nla_for_each_nested(nl_txq_params,
 				    info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
 				    rem_txq_params) {



^ permalink raw reply

* [PATCH] mac80211: verify virtual interfaces in driver API
From: Johannes Berg @ 2011-11-03 13:41 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

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

The driver is never informed about monitor or
AP_VLAN interfaces, so whenever we pass those
to it later this is a bug. Verify we don't as
there are some cases where this could happen.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/driver-ops.h  |   68 +++++++++++++++++++++++++++++++++++++++++----
 net/mac80211/ieee80211_i.h |    2 +
 net/mac80211/iface.c       |    6 +--
 net/mac80211/pm.c          |    2 -
 net/mac80211/util.c        |    2 -
 5 files changed, 69 insertions(+), 11 deletions(-)

--- a/net/mac80211/driver-ops.h	2011-11-03 10:54:18.000000000 +0100
+++ b/net/mac80211/driver-ops.h	2011-11-03 11:52:47.000000000 +0100
@@ -5,6 +5,11 @@
 #include "ieee80211_i.h"
 #include "driver-trace.h"
 
+static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata)
+{
+	WARN_ON(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER));
+}
+
 static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
 {
 	local->ops->tx(&local->hw, skb);
@@ -69,15 +74,23 @@ static inline int drv_resume(struct ieee
 #endif
 
 static inline int drv_add_interface(struct ieee80211_local *local,
-				    struct ieee80211_vif *vif)
+				    struct ieee80211_sub_if_data *sdata)
 {
 	int ret;
 
 	might_sleep();
 
-	trace_drv_add_interface(local, vif_to_sdata(vif));
-	ret = local->ops->add_interface(&local->hw, vif);
+	if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+		    sdata->vif.type == NL80211_IFTYPE_MONITOR))
+		return -EINVAL;
+
+	trace_drv_add_interface(local, sdata);
+	ret = local->ops->add_interface(&local->hw, &sdata->vif);
 	trace_drv_return_int(local, ret);
+
+	if (ret == 0)
+		sdata->flags |= IEEE80211_SDATA_IN_DRIVER;
+
 	return ret;
 }
 
@@ -89,6 +102,8 @@ static inline int drv_change_interface(s
 
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_change_interface(local, sdata, type, p2p);
 	ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p);
 	trace_drv_return_int(local, ret);
@@ -96,12 +111,15 @@ static inline int drv_change_interface(s
 }
 
 static inline void drv_remove_interface(struct ieee80211_local *local,
-					struct ieee80211_vif *vif)
+					struct ieee80211_sub_if_data *sdata)
 {
 	might_sleep();
 
-	trace_drv_remove_interface(local, vif_to_sdata(vif));
-	local->ops->remove_interface(&local->hw, vif);
+	check_sdata_in_driver(sdata);
+
+	trace_drv_remove_interface(local, sdata);
+	local->ops->remove_interface(&local->hw, &sdata->vif);
+	sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;
 	trace_drv_return_void(local);
 }
 
@@ -124,6 +142,8 @@ static inline void drv_bss_info_changed(
 {
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_bss_info_changed(local, sdata, info, changed);
 	if (local->ops->bss_info_changed)
 		local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed);
@@ -139,6 +159,8 @@ static inline int drv_tx_sync(struct iee
 
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_tx_sync(local, sdata, bssid, type);
 	if (local->ops->tx_sync)
 		ret = local->ops->tx_sync(&local->hw, &sdata->vif,
@@ -154,6 +176,8 @@ static inline void drv_finish_tx_sync(st
 {
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_finish_tx_sync(local, sdata, bssid, type);
 	if (local->ops->finish_tx_sync)
 		local->ops->finish_tx_sync(&local->hw, &sdata->vif,
@@ -211,6 +235,8 @@ static inline int drv_set_key(struct iee
 
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_set_key(local, cmd, sdata, sta, key);
 	ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key);
 	trace_drv_return_int(local, ret);
@@ -228,6 +254,8 @@ static inline void drv_update_tkip_key(s
 	if (sta)
 		ista = &sta->sta;
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_update_tkip_key(local, sdata, conf, ista, iv32);
 	if (local->ops->update_tkip_key)
 		local->ops->update_tkip_key(&local->hw, &sdata->vif, conf,
@@ -243,6 +271,8 @@ static inline int drv_hw_scan(struct iee
 
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_hw_scan(local, sdata);
 	ret = local->ops->hw_scan(&local->hw, &sdata->vif, req);
 	trace_drv_return_int(local, ret);
@@ -254,6 +284,8 @@ static inline void drv_cancel_hw_scan(st
 {
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_cancel_hw_scan(local, sdata);
 	local->ops->cancel_hw_scan(&local->hw, &sdata->vif);
 	trace_drv_return_void(local);
@@ -269,6 +301,8 @@ drv_sched_scan_start(struct ieee80211_lo
 
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_sched_scan_start(local, sdata);
 	ret = local->ops->sched_scan_start(&local->hw, &sdata->vif,
 					      req, ies);
@@ -281,6 +315,8 @@ static inline void drv_sched_scan_stop(s
 {
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_sched_scan_stop(local, sdata);
 	local->ops->sched_scan_stop(&local->hw, &sdata->vif);
 	trace_drv_return_void(local);
@@ -377,6 +413,8 @@ static inline void drv_sta_notify(struct
 				  enum sta_notify_cmd cmd,
 				  struct ieee80211_sta *sta)
 {
+	check_sdata_in_driver(sdata);
+
 	trace_drv_sta_notify(local, sdata, cmd, sta);
 	if (local->ops->sta_notify)
 		local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta);
@@ -391,6 +429,8 @@ static inline int drv_sta_add(struct iee
 
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_sta_add(local, sdata, sta);
 	if (local->ops->sta_add)
 		ret = local->ops->sta_add(&local->hw, &sdata->vif, sta);
@@ -406,6 +446,8 @@ static inline void drv_sta_remove(struct
 {
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_sta_remove(local, sdata, sta);
 	if (local->ops->sta_remove)
 		local->ops->sta_remove(&local->hw, &sdata->vif, sta);
@@ -421,6 +463,8 @@ static inline int drv_conf_tx(struct iee
 
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_conf_tx(local, sdata, queue, params);
 	if (local->ops->conf_tx)
 		ret = local->ops->conf_tx(&local->hw, &sdata->vif,
@@ -436,6 +480,8 @@ static inline u64 drv_get_tsf(struct iee
 
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_get_tsf(local, sdata);
 	if (local->ops->get_tsf)
 		ret = local->ops->get_tsf(&local->hw, &sdata->vif);
@@ -449,6 +495,8 @@ static inline void drv_set_tsf(struct ie
 {
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_set_tsf(local, sdata, tsf);
 	if (local->ops->set_tsf)
 		local->ops->set_tsf(&local->hw, &sdata->vif, tsf);
@@ -460,6 +508,8 @@ static inline void drv_reset_tsf(struct
 {
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_reset_tsf(local, sdata);
 	if (local->ops->reset_tsf)
 		local->ops->reset_tsf(&local->hw, &sdata->vif);
@@ -489,6 +539,8 @@ static inline int drv_ampdu_action(struc
 
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size);
 
 	if (local->ops->ampdu_action)
@@ -644,6 +696,8 @@ static inline int drv_set_bitrate_mask(s
 
 	might_sleep();
 
+	check_sdata_in_driver(sdata);
+
 	trace_drv_set_bitrate_mask(local, sdata, mask);
 	if (local->ops->set_bitrate_mask)
 		ret = local->ops->set_bitrate_mask(&local->hw,
@@ -657,6 +711,8 @@ static inline void drv_set_rekey_data(st
 				      struct ieee80211_sub_if_data *sdata,
 				      struct cfg80211_gtk_rekey_data *data)
 {
+	check_sdata_in_driver(sdata);
+
 	trace_drv_set_rekey_data(local, sdata, data);
 	if (local->ops->set_rekey_data)
 		local->ops->set_rekey_data(&local->hw, &sdata->vif, data);
--- a/net/mac80211/ieee80211_i.h	2011-11-03 11:52:43.000000000 +0100
+++ b/net/mac80211/ieee80211_i.h	2011-11-03 11:52:47.000000000 +0100
@@ -543,6 +543,7 @@ struct ieee80211_if_mesh {
  *	associated stations and deliver multicast frames both
  *	back to wireless media and to the local net stack.
  * @IEEE80211_SDATA_DISCONNECT_RESUME: Disconnect after resume.
+ * @IEEE80211_SDATA_IN_DRIVER: indicates interface was added to driver
  */
 enum ieee80211_sub_if_data_flags {
 	IEEE80211_SDATA_ALLMULTI		= BIT(0),
@@ -550,6 +551,7 @@ enum ieee80211_sub_if_data_flags {
 	IEEE80211_SDATA_OPERATING_GMODE		= BIT(2),
 	IEEE80211_SDATA_DONT_BRIDGE_PACKETS	= BIT(3),
 	IEEE80211_SDATA_DISCONNECT_RESUME	= BIT(4),
+	IEEE80211_SDATA_IN_DRIVER		= BIT(5),
 };
 
 /**
--- a/net/mac80211/iface.c	2011-11-03 10:54:17.000000000 +0100
+++ b/net/mac80211/iface.c	2011-11-03 11:52:47.000000000 +0100
@@ -265,7 +265,7 @@ static int ieee80211_do_open(struct net_
 		break;
 	default:
 		if (coming_up) {
-			res = drv_add_interface(local, &sdata->vif);
+			res = drv_add_interface(local, sdata);
 			if (res)
 				goto err_stop;
 		}
@@ -345,7 +345,7 @@ static int ieee80211_do_open(struct net_
 
 	return 0;
  err_del_interface:
-	drv_remove_interface(local, &sdata->vif);
+	drv_remove_interface(local, sdata);
  err_stop:
 	if (!local->open_count)
 		drv_stop(local);
@@ -520,7 +520,7 @@ static void ieee80211_do_stop(struct iee
 		ieee80211_free_keys(sdata);
 
 		if (going_down)
-			drv_remove_interface(local, &sdata->vif);
+			drv_remove_interface(local, sdata);
 	}
 
 	sdata->bss = NULL;
--- a/net/mac80211/util.c	2011-11-03 10:54:18.000000000 +0100
+++ b/net/mac80211/util.c	2011-11-03 11:52:47.000000000 +0100
@@ -1021,7 +1021,7 @@ int ieee80211_reconfig(struct ieee80211_
 		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 		    sdata->vif.type != NL80211_IFTYPE_MONITOR &&
 		    ieee80211_sdata_running(sdata))
-			res = drv_add_interface(local, &sdata->vif);
+			res = drv_add_interface(local, sdata);
 	}
 
 	/* add STAs back */
--- a/net/mac80211/pm.c	2011-11-03 10:54:18.000000000 +0100
+++ b/net/mac80211/pm.c	2011-11-03 11:52:47.000000000 +0100
@@ -125,7 +125,7 @@ int __ieee80211_suspend(struct ieee80211
 		ieee80211_bss_info_change_notify(sdata,
 			BSS_CHANGED_BEACON_ENABLED);
 
-		drv_remove_interface(local, &sdata->vif);
+		drv_remove_interface(local, sdata);
 	}
 
 	/* stop hardware - this must stop RX */



^ permalink raw reply

* b43 scans wifi networks with old firmware only.
From: Roman V.Leon. @ 2011-11-03 11:21 UTC (permalink / raw)
  To: linux-wireless

Hello Gents.
I have problem with b43 driver 5.100.138, it's not scanning networks for
unknown reason. I have broadcom wifi card PCIID is 14e4:4315, linux kern
ver. is 3.0. When i'm trying to launch iwlist scan, i'm getting "no scan
results".

for example:
sudo ifconfig wlan0 up
sudo iwlist wlan0 scan
    No scan results.

With the older driver 5.10.56.2808, i see normal scan results. If you need
any more information, i will send.

-- 
Thanks,
Roman V.Leon.


^ permalink raw reply

* [PATCH] net: add wireless TX status socket option
From: Johannes Berg @ 2011-11-03 10:56 UTC (permalink / raw)
  To: netdev; +Cc: linux-wireless

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

The 802.1X EAPOL handshake hostapd does requires
knowing whether the frame was ack'ed by the peer.
Currently, we fudge this pretty badly by not even
transmitting the frame as a normal data frame but
injecting it with radiotap and getting the status
out of radiotap monitor as well. This is rather
complex, confuses users (mon.wlan0 presence) and
doesn't work with all hardware.

To get rid of that hack, introduce a real wifi TX
status option for data frame transmissions.

This works similar to the existing TX timestamping
in that it reflects the SKB back to the socket's
error queue with a SCM_WIFI_STATUS cmsg that has
an int indicating ACK status (0/1).

Since it is possible that at some point we will
want to have TX timestamping and wifi status in a
single errqueue SKB (there's little point in not
doing that), redefine SO_EE_ORIGIN_TIMESTAMPING
to SO_EE_ORIGIN_TXSTATUS which can collect more
than just the timestamp; keep the old constant
as an alias of course. Currently the internal APIs
don't make that possible, but it wouldn't be hard
to split them up in a way that makes it possible.

Thanks to Neil Horman for helping me figure out
the functions that add the control messages.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
I'd like to merge this through the wireless tree since
some new features sort of depend on it. Thoughts?

 arch/alpha/include/asm/socket.h   |    3 +++
 arch/arm/include/asm/socket.h     |    3 +++
 arch/avr32/include/asm/socket.h   |    3 +++
 arch/cris/include/asm/socket.h    |    3 +++
 arch/frv/include/asm/socket.h     |    3 +++
 arch/h8300/include/asm/socket.h   |    3 +++
 arch/ia64/include/asm/socket.h    |    3 +++
 arch/m32r/include/asm/socket.h    |    3 +++
 arch/m68k/include/asm/socket.h    |    3 +++
 arch/mips/include/asm/socket.h    |    3 +++
 arch/mn10300/include/asm/socket.h |    3 +++
 arch/parisc/include/asm/socket.h  |    3 +++
 arch/powerpc/include/asm/socket.h |    3 +++
 arch/s390/include/asm/socket.h    |    3 +++
 arch/sparc/include/asm/socket.h   |    3 +++
 arch/xtensa/include/asm/socket.h  |    3 +++
 include/asm-generic/socket.h      |    3 +++
 include/linux/errqueue.h          |    3 ++-
 include/linux/skbuff.h            |   19 +++++++++++++++++--
 include/net/sock.h                |    6 ++++++
 net/core/skbuff.c                 |   20 ++++++++++++++++++++
 net/core/sock.c                   |    9 +++++++++
 net/socket.c                      |   18 ++++++++++++++++++
 23 files changed, 123 insertions(+), 3 deletions(-)

--- a/include/asm-generic/socket.h	2011-11-03 10:54:12.000000000 +0100
+++ b/include/asm-generic/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -64,4 +64,7 @@
 #define SO_DOMAIN		39
 
 #define SO_RXQ_OVFL             40
+
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS	SO_WIFI_STATUS
 #endif /* __ASM_GENERIC_SOCKET_H */
--- a/net/core/sock.c	2011-11-03 10:54:12.000000000 +0100
+++ b/net/core/sock.c	2011-11-03 11:52:53.000000000 +0100
@@ -743,6 +743,11 @@ set_rcvbuf:
 		else
 			sock_reset_flag(sk, SOCK_RXQ_OVFL);
 		break;
+
+	case SO_WIFI_STATUS:
+		sock_valbool_flag(sk, SOCK_WIFI_STATUS, valbool);
+		break;
+
 	default:
 		ret = -ENOPROTOOPT;
 		break;
@@ -964,6 +969,10 @@ int sock_getsockopt(struct socket *sock,
 		v.val = !!sock_flag(sk, SOCK_RXQ_OVFL);
 		break;
 
+	case SO_WIFI_STATUS:
+		v.val = !!sock_flag(sk, SOCK_WIFI_STATUS);
+		break;
+
 	default:
 		return -ENOPROTOOPT;
 	}
--- a/include/net/sock.h	2011-11-03 10:54:12.000000000 +0100
+++ b/include/net/sock.h	2011-11-03 11:54:03.000000000 +0100
@@ -564,6 +564,7 @@ enum sock_flags {
 	SOCK_FASYNC, /* fasync() active */
 	SOCK_RXQ_OVFL,
 	SOCK_ZEROCOPY, /* buffers from userspace */
+	SOCK_WIFI_STATUS, /* push wifi status to userspace */
 };
 
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
@@ -1705,6 +1706,8 @@ static inline int sock_intr_errno(long t
 
 extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
 	struct sk_buff *skb);
+extern void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
+	struct sk_buff *skb);
 
 static __inline__ void
 sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
@@ -1732,6 +1735,9 @@ sock_recv_timestamp(struct msghdr *msg,
 		__sock_recv_timestamp(msg, sk, skb);
 	else
 		sk->sk_stamp = kt;
+
+	if (sock_flag(sk, SOCK_WIFI_STATUS) && skb->wifi_acked_valid)
+		__sock_recv_wifi_status(msg, sk, skb);
 }
 
 extern void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
--- a/arch/alpha/include/asm/socket.h	2011-11-03 10:54:12.000000000 +0100
+++ b/arch/alpha/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -69,6 +69,9 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
--- a/arch/arm/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/arm/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/avr32/include/asm/socket.h	2011-11-03 10:54:10.000000000 +0100
+++ b/arch/avr32/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* __ASM_AVR32_SOCKET_H */
--- a/arch/cris/include/asm/socket.h	2011-11-03 10:54:12.000000000 +0100
+++ b/arch/cris/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -64,6 +64,9 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
 
 
--- a/arch/frv/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/frv/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -62,5 +62,8 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
 
--- a/arch/h8300/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/h8300/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/ia64/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/ia64/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -71,4 +71,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_IA64_SOCKET_H */
--- a/arch/m32r/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/m32r/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_M32R_SOCKET_H */
--- a/arch/m68k/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/m68k/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/mips/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/mips/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -82,6 +82,9 @@ To add: #define SO_REUSEPORT 0x0200	/* A
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #ifdef __KERNEL__
 
 /** sock_type - Socket types
--- a/arch/mn10300/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/mn10300/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/parisc/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/parisc/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -61,6 +61,9 @@
 
 #define SO_RXQ_OVFL             0x4021
 
+#define SO_WIFI_STATUS		0x4022
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
--- a/arch/powerpc/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/powerpc/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -69,4 +69,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif	/* _ASM_POWERPC_SOCKET_H */
--- a/arch/s390/include/asm/socket.h	2011-11-03 10:54:10.000000000 +0100
+++ b/arch/s390/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -70,4 +70,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/sparc/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/sparc/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -58,6 +58,9 @@
 
 #define SO_RXQ_OVFL             0x0024
 
+#define SO_WIFI_STATUS		0x0025
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
--- a/arch/xtensa/include/asm/socket.h	2011-11-03 10:54:11.000000000 +0100
+++ b/arch/xtensa/include/asm/socket.h	2011-11-03 11:52:53.000000000 +0100
@@ -73,4 +73,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif	/* _XTENSA_SOCKET_H */
--- a/include/linux/errqueue.h	2011-11-03 10:54:12.000000000 +0100
+++ b/include/linux/errqueue.h	2011-11-03 11:52:53.000000000 +0100
@@ -17,7 +17,8 @@ struct sock_extended_err {
 #define SO_EE_ORIGIN_LOCAL	1
 #define SO_EE_ORIGIN_ICMP	2
 #define SO_EE_ORIGIN_ICMP6	3
-#define SO_EE_ORIGIN_TIMESTAMPING 4
+#define SO_EE_ORIGIN_TXSTATUS	4
+#define SO_EE_ORIGIN_TIMESTAMPING SO_EE_ORIGIN_TXSTATUS
 
 #define SO_EE_OFFENDER(ee)	((struct sockaddr*)((ee)+1))
 
--- a/include/linux/skbuff.h	2011-11-03 10:54:12.000000000 +0100
+++ b/include/linux/skbuff.h	2011-11-03 11:52:53.000000000 +0100
@@ -190,6 +190,9 @@ enum {
 
 	/* device driver supports TX zero-copy buffers */
 	SKBTX_DEV_ZEROCOPY = 1 << 4,
+
+	/* generate wifi status information (where possible) */
+	SKBTX_WIFI_STATUS = 1 << 5,
 };
 
 /*
@@ -322,6 +325,8 @@ typedef unsigned char *sk_buff_data_t;
  *	@queue_mapping: Queue mapping for multiqueue devices
  *	@ndisc_nodetype: router type (from link layer)
  *	@ooo_okay: allow the mapping of a socket to a queue to be changed
+ *	@wifi_acked_valid: wifi_acked was set
+ *	@wifi_acked: whether frame was acked on wifi or not
  *	@dma_cookie: a cookie to one of several possible DMA operations
  *		done by skb DMA functions
  *	@secmark: security marking
@@ -414,10 +419,11 @@ struct sk_buff {
 	__u8			ndisc_nodetype:2;
 #endif
 	__u8			ooo_okay:1;
+	__u8			wifi_acked_valid:1;
+	__u8			wifi_acked:1;
+	/* 11/13 bit hole (depending on nodetype presence) */
 	kmemcheck_bitfield_end(flags2);
 
-	/* 0/13 bit hole */
-
 #ifdef CONFIG_NET_DMA
 	dma_cookie_t		dma_cookie;
 #endif
@@ -2062,6 +2068,15 @@ static inline void skb_tx_timestamp(stru
 	sw_tx_timestamp(skb);
 }
 
+/**
+ * skb_complete_wifi_ack - deliver skb with wifi status
+ *
+ * @skb: the original outgoing packet
+ * @acked: ack status
+ *
+ */
+void skb_complete_wifi_ack(struct sk_buff *skb, bool acked);
+
 extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
 extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
 
--- a/net/core/skbuff.c	2011-11-03 10:54:12.000000000 +0100
+++ b/net/core/skbuff.c	2011-11-03 11:52:53.000000000 +0100
@@ -3150,6 +3150,26 @@ void skb_tstamp_tx(struct sk_buff *orig_
 }
 EXPORT_SYMBOL_GPL(skb_tstamp_tx);
 
+void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)
+{
+	struct sock *sk = skb->sk;
+	struct sock_exterr_skb *serr;
+	int err;
+
+	skb->wifi_acked_valid = 1;
+	skb->wifi_acked = acked;
+
+	serr = SKB_EXT_ERR(skb);
+	memset(serr, 0, sizeof(*serr));
+	serr->ee.ee_errno = ENOMSG;
+	serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS;
+
+	err = sock_queue_err_skb(sk, skb);
+	if (err)
+		kfree_skb(skb);
+}
+EXPORT_SYMBOL_GPL(skb_complete_wifi_ack);
+
 
 /**
  * skb_partial_csum_set - set up and verify partial csum values for packet
--- a/net/socket.c	2011-11-03 10:54:12.000000000 +0100
+++ b/net/socket.c	2011-11-03 11:55:06.000000000 +0100
@@ -538,6 +538,8 @@ int sock_tx_timestamp(struct sock *sk, _
 		*tx_flags |= SKBTX_HW_TSTAMP;
 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
 		*tx_flags |= SKBTX_SW_TSTAMP;
+	if (sock_flag(sk, SOCK_WIFI_STATUS))
+		*tx_flags |= SKBTX_WIFI_STATUS;
 	return 0;
 }
 EXPORT_SYMBOL(sock_tx_timestamp);
@@ -674,6 +676,22 @@ void __sock_recv_timestamp(struct msghdr
 }
 EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
 
+void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
+	struct sk_buff *skb)
+{
+	int ack;
+
+	if (!sock_flag(sk, SOCK_WIFI_STATUS))
+		return;
+	if (!skb->wifi_acked_valid)
+		return;
+
+	ack = skb->wifi_acked;
+
+	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
+}
+EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
+
 static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
 				   struct sk_buff *skb)
 {



^ permalink raw reply

* [PATCH] ath6kl: add suspend_cutpower module parameter
From: Kalle Valo @ 2011-11-03 10:18 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

This is to force ath6kl to power off hardware during suspend even if
sdio support keep power. This is needed, for example, when sdio
controller is buggy or maximum powersaving is desired.

Usage:

insmod ath6kl.ko suspend_cutpower=1

Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/core.h |    1 +
 drivers/net/wireless/ath/ath6kl/init.c |    5 +++++
 drivers/net/wireless/ath/ath6kl/sdio.c |    3 ++-
 3 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index f301c32..c30642e 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -166,6 +166,7 @@ struct ath6kl_fw_ie {
 #define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN  BIT(1)
 #define ATH6KL_CONF_ENABLE_11N			BIT(2)
 #define ATH6KL_CONF_ENABLE_TX_BURST		BIT(3)
+#define ATH6KL_CONF_SUSPEND_CUTPOWER		BIT(4)
 
 enum wlan_low_pwr_state {
 	WLAN_POWER_STATE_ON,
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 363fb3d..4881a18 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -27,9 +27,11 @@
 
 unsigned int debug_mask;
 static unsigned int testmode;
+static bool suspend_cutpower;
 
 module_param(debug_mask, uint, 0644);
 module_param(testmode, uint, 0644);
+module_param(suspend_cutpower, bool, 0444);
 
 /*
  * Include definitions here that can be used to tune the WLAN module
@@ -1596,6 +1598,9 @@ int ath6kl_core_init(struct ath6kl *ar)
 	ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
 			 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
 
+	if (suspend_cutpower)
+		ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER;
+
 	ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
 
 	set_bit(FIRST_BOOT, &ar->flag);
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index ccb888b..a026dae 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -784,7 +784,8 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar)
 
 	ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio suspend pm_caps 0x%x\n", flags);
 
-	if (!(flags & MMC_PM_KEEP_POWER)) {
+	if (!(flags & MMC_PM_KEEP_POWER) ||
+	    (ar->conf_flags & ATH6KL_CONF_SUSPEND_CUTPOWER)) {
 		/* as host doesn't support keep power we need to cut power */
 		return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER);
 	}


^ permalink raw reply related

* Re: [PATCH] cfg80211: merge in beacon ies of hidden bss.
From: Johannes Berg @ 2011-11-03 10:13 UTC (permalink / raw)
  To: Dmitry Tarnyagin; +Cc: linux-wireless
In-Reply-To: <CAMG6FYjQWc2fXDM8eWpEi7OqS+tVfjh5onf_332R3pzq8ks0aQ@mail.gmail.com>

Hi,

> -1 means "lesser", which is not true if both of ies are absent.
> 0 means "equal", which is correct (but logically impossible with the
> current usage of the comparator). Now I think even WARN_ON is a bad
> idea, the comparator can be reused for other purposes when both
> SSID ies are missing.

Fair enough. Maybe a comment along the lines of
/* can't really happen, but they're the same then */

would be useful.

> > Eliad pointed out another thing: It is possible to have multiple SSIDs
> > hidden behind a single hidden SSID. Therefore, this should update all of
> > those BSS structs. Also, I'm a tad confused about the matching code
> > here, this code path executes for both received beacons and probe
> > responses, but probe responses would typically have found the BSS
> > already? But what if we only have a beacon and then receive a probe
> > response? Or vice versa? Some comments would be good outlining how that
> > works.
> >
> I will add some comments in the code. Is a word, the code searches for a beacon
> of the hidden BSS and copies beacon IEs (with nullified SSID) into the probe
> response bss entry (with real SSID). It works fine in case of multi-SSID hidden
> BSS too.

Right, that should work.

> > Or vice versa?
> It will not work. Update of beacon IEs of probe response is not implemented.
> The code is not trying to update existing probe response bss entries when beacon
> IEs are getting changed. Technically it's possible to update them, but
> I think it's a bit
> overkill, I'm addressing only PSM in this commit.

I think that would actually be useful too since userspace may obtain
this data from scan results at any point in time, and might expect
up-to-date information? Could be a separate patch though.

Anyway, comments indicating what happens and which case this handles
would be great.

Thanks!

johannes


^ permalink raw reply

* Re: [PATCH] cfg80211: merge in beacon ies of hidden bss.
From: Dmitry Tarnyagin @ 2011-11-03 10:03 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320313141.3950.35.camel@jlt3.sipsolutions.net>

Hi Johannes,

On Thu, Nov 3, 2011 at 10:39 AM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> Hi Dmitry,
>
>> >> +     if (!ie1 && !ie2)
>> >> +             return 0;
>> > I don't think it's valid to leave out the SSID IE, so I'd rather not
>> > have that test here. It might interact badly with other uses (mesh?)
>> ie1 and ie2 could not NULL at the same time, otherwise the bss
>> would be found in the first search attempt. However, I would prefer
>> to have some water-proof check here. WARN_ON? BUG_ON?
> Maybe a warning? But I don't see why it'll just fall through to the next
> line and return -1 if one of them is missing.
>
-1 means "lesser", which is not true if both of ies are absent.
0 means "equal", which is correct (but logically impossible with the
current usage of the comparator). Now I think even WARN_ON is a bad
idea, the comparator can be reused for other purposes when both
SSID ies are missing.

>> Key comparator must use same algorithm in any rb-tree search function
>> (order is important), otherwise ordering of items in the tree is broken
>> and search gives incorrect results.
>> This code uses same order as cmp_ies() does.
> Oh. Good point. Add a comment?
>
Yes, I will.

> Eliad pointed out another thing: It is possible to have multiple SSIDs
> hidden behind a single hidden SSID. Therefore, this should update all of
> those BSS structs. Also, I'm a tad confused about the matching code
> here, this code path executes for both received beacons and probe
> responses, but probe responses would typically have found the BSS
> already? But what if we only have a beacon and then receive a probe
> response? Or vice versa? Some comments would be good outlining how that
> works.
>
I will add some comments in the code. Is a word, the code searches for a beacon
of the hidden BSS and copies beacon IEs (with nullified SSID) into the probe
response bss entry (with real SSID). It works fine in case of multi-SSID hidden
BSS too.

> what if we only have a beacon and then receive a probe response?
It's the typical usecase for association with hidden BSS.  The probe
response will
be updated with beacon IEs.

> Or vice versa?
It will not work. Update of beacon IEs of probe response is not implemented.
The code is not trying to update existing probe response bss entries when beacon
IEs are getting changed. Technically it's possible to update them, but
I think it's a bit
overkill, I'm addressing only PSM in this commit.

Thank you and with best regards,
Dmitry

^ permalink raw reply

* [PATCH] ath6kl: don't power down hardware when interface is down
From: Kalle Valo @ 2011-11-03  9:53 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

Jouni reported that my patch "ath6kl: power down hardware when interface
is down" caused a regression on his x86 boxes and scan didn't work anymore.
I was able to reproduce the problem by disabling all debug messages.

So there has to be a race condition somewhere in the code and disable the
functionality until the race is fixed. Now hardware is powered from the
point where module is loaded until it's removed.

Reported-by: Jouni Malinen <jouni@qca.qualcomm.com>
Tested-by: Jouni Malinen <jouni@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/init.c |    6 ------
 drivers/net/wireless/ath/ath6kl/main.c |   12 ------------
 2 files changed, 0 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 909e2e9..363fb3d 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1612,12 +1612,6 @@ int ath6kl_core_init(struct ath6kl *ar)
 	 */
 	memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
 
-	ret = ath6kl_init_hw_stop(ar);
-	if (ret) {
-		ath6kl_err("Failed to stop hardware: %d\n", ret);
-		goto err_htc_cleanup;
-	}
-
 	return ret;
 
 err_rxbuf_cleanup:
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index f9410e4..021b2f6 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1062,12 +1062,6 @@ struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar)
 static int ath6kl_open(struct net_device *dev)
 {
 	struct ath6kl_vif *vif = netdev_priv(dev);
-	int ret;
-
-	/* FIXME: how to handle multi vif support? */
-	ret = ath6kl_init_hw_start(vif->ar);
-	if (ret)
-		return ret;
 
 	set_bit(WLAN_ENABLED, &vif->flags);
 
@@ -1084,7 +1078,6 @@ static int ath6kl_close(struct net_device *dev)
 {
 	struct ath6kl *ar = ath6kl_priv(dev);
 	struct ath6kl_vif *vif = netdev_priv(dev);
-	int ret;
 
 	netif_stop_queue(dev);
 
@@ -1099,11 +1092,6 @@ static int ath6kl_close(struct net_device *dev)
 
 	ath6kl_cfg80211_scan_complete_event(vif, true);
 
-	/* FIXME: how to handle multi vif support? */
-	ret = ath6kl_init_hw_stop(ar);
-	if (ret)
-		return ret;
-
 	clear_bit(WLAN_ENABLED, &vif->flags);
 
 	return 0;


^ permalink raw reply related

* Re: [PATCH] ieee80211: Define cipher suite selector for WPI-SMS4
From: Jouni Malinen @ 2011-11-03  9:49 UTC (permalink / raw)
  To: Dan Williams; +Cc: John W. Linville, Johannes Berg, linux-wireless
In-Reply-To: <1320282954.20617.1.camel@dcbw.foobar.com>

On Wed, Nov 02, 2011 at 08:15:52PM -0500, Dan Williams wrote:
> On Wed, 2011-11-02 at 23:34 +0200, Jouni Malinen wrote:
> > This value is used for WPI-SMS4 in ISO/IEC JTC 1 N 9880.
> 
> Does that mean WAPI at some point? :)

Well, I think we are getting to the point where more or less all the
needed interfaces are in place to implement this cleanly. I would assume
that some drivers have already supported this in the past, but there
must have been some hacks in place, e.g., to avoid the WPI PN
configuration that I fixed in the other patch from yesterday. There is
still a small piece needed for AP mode to indicate some events that I
hope to get submitted once I actually understand what it does ;-). In
addition, better configuration of the AKM could be useful to get added
eventually.

Johannes covered other parts of the question and I don't have
anything to add at this point.

-- 
Jouni Malinen                                            PGP id EFC895FA

^ permalink raw reply

* [PATCH 3/3] mac80211: simplify ieee80211_work_work
From: Stanislaw Gruszka @ 2011-11-03  9:40 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Stanislaw Gruszka
In-Reply-To: <1320313247-23167-1-git-send-email-sgruszka@redhat.com>

Since local->tmp_channel is always NULL in one branch, some code paths
will newer be taken in that branch, so remove them.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 net/mac80211/work.c |   17 +++--------------
 1 files changed, 3 insertions(+), 14 deletions(-)

diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 6c53b6d..788b96e 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -969,10 +969,9 @@ static void ieee80211_work_work(struct work_struct *work)
 		}
 
 		if (!started && !local->tmp_channel) {
-			bool on_oper_chan;
-			bool tmp_chan_changed = false;
-			bool on_oper_chan2;
+			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. */
@@ -981,11 +980,6 @@ static void ieee80211_work_work(struct work_struct *work)
 				wk_ct = ieee80211_calc_ct(wk->chan_type,
 						local->hw.conf.channel_type);
 
-			if (local->tmp_channel)
-				if ((local->tmp_channel != wk->chan) ||
-				    (local->tmp_channel_type != wk_ct))
-					tmp_chan_changed = true;
-
 			local->tmp_channel = wk->chan;
 			local->tmp_channel_type = wk_ct;
 			/*
@@ -1008,12 +1002,7 @@ static void ieee80211_work_work(struct work_struct *work)
 								    true,
 								    false);
 				}
-			} else if (tmp_chan_changed)
-				/* Still off-channel, but on some other
-				 * channel, so update hardware.
-				 * PS should already be off-channel.
-				 */
-				ieee80211_hw_config(local, 0);
+			}
 
 			started = true;
 			wk->timeout = jiffies;
-- 
1.7.1


^ permalink raw reply related

* [PATCH 2/3] mac80211: remove useless brackets in ieee80211_cfg_on_oper_channel
From: Stanislaw Gruszka @ 2011-11-03  9:40 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Stanislaw Gruszka
In-Reply-To: <1320313247-23167-1-git-send-email-sgruszka@redhat.com>

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 net/mac80211/main.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 7710b10..cd87fd9 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -126,8 +126,8 @@ bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
 		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))
+	if (local->oper_channel != local->hw.conf.channel ||
+	    local->_oper_channel_type != local->hw.conf.channel_type)
 		return false;
 
 	return true;
-- 
1.7.1


^ permalink raw reply related

* [PATCH 1/3] mac80211: remove uneeded scan_chan variable
From: Stanislaw Gruszka @ 2011-11-03  9:40 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Stanislaw Gruszka

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 net/mac80211/main.c |   14 ++++++--------
 1 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index d4ee6d2..7710b10 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -100,7 +100,7 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
  */
 bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
 {
-	struct ieee80211_channel *chan, *scan_chan;
+	struct ieee80211_channel *chan;
 	enum nl80211_channel_type channel_type;
 
 	/* This logic needs to match logic in ieee80211_hw_config */
@@ -114,7 +114,7 @@ bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
 		else
 			channel_type = NL80211_CHAN_NO_HT;
 	} else if (local->tmp_channel) {
-		chan = scan_chan = local->tmp_channel;
+		chan = local->tmp_channel;
 		channel_type = local->tmp_channel_type;
 	} else {
 		chan = local->oper_channel;
@@ -135,7 +135,7 @@ bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
 
 int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 {
-	struct ieee80211_channel *chan, *scan_chan;
+	struct ieee80211_channel *chan;
 	int ret = 0;
 	int power;
 	enum nl80211_channel_type channel_type;
@@ -143,14 +143,12 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 
 	might_sleep();
 
-	scan_chan = local->scan_channel;
-
 	/* If this off-channel logic ever changes,  ieee80211_on_oper_channel
 	 * may need to change as well.
 	 */
 	offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
-	if (scan_chan) {
-		chan = scan_chan;
+	if (local->scan_channel) {
+		chan = local->scan_channel;
 		/* If scanning on oper channel, use whatever channel-type
 		 * is currently in use.
 		 */
@@ -159,7 +157,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 		else
 			channel_type = NL80211_CHAN_NO_HT;
 	} else if (local->tmp_channel) {
-		chan = scan_chan = local->tmp_channel;
+		chan = local->tmp_channel;
 		channel_type = local->tmp_channel_type;
 	} else {
 		chan = local->oper_channel;
-- 
1.7.1


^ permalink raw reply related

* [PATCH 0/3] ath6kl: Add support for WAPI configuration
From: Jouni Malinen @ 2011-11-03  9:39 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, Jouni Malinen

This set of patches extends ath6kl to allow station and AP mode WAPI
support to be enabled. Please note that these depend on earlier patches
that are not yet in wireless-testing.git:

ieee80211: Define cipher suite selector for WPI-SMS4
nl80211: Increase maximum NL80211_ATTR_KEY_SEQ length to 16

In addition, the three patches I sent yesterday for ath6kl should be
applied first:

ath6kl: Remove unused WMI crypto defines
ath6kl: Fix key configuration to copy at most seq_len from seq
ath6kl: Do not hide ath6kl_wmi_addkey_cmd() error values


Dai Shuibing (3):
  ath6kl: Add support for configuring SMS4 keys
  ath6kl: Allow SMS4 to be configured in AP mode
  ath6kl: Indicate WAPI IE from (Re)Association Request frame

 drivers/net/wireless/ath/ath6kl/cfg80211.c |   24 ++++++++++++++++++++++--
 drivers/net/wireless/ath/ath6kl/common.h   |    1 +
 drivers/net/wireless/ath/ath6kl/main.c     |   12 ++++++++++++
 3 files changed, 35 insertions(+), 2 deletions(-)

-- 
1.7.4.1


^ permalink raw reply

* [PATCH 3/3] ath6kl: Indicate WAPI IE from (Re)Association Request frame
From: Jouni Malinen @ 2011-11-03  9:39 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, Dai Shuibing, Jouni Malinen
In-Reply-To: <1320313179-9259-1-git-send-email-jouni@qca.qualcomm.com>

From: Dai Shuibing <shuibing@qca.qualcomm.com>

This is needed to know whether the STA requests WAPI to be used and if
so, with what AKM and cipher.

Signed-off-by: Dai Shuibing <shuibing@qca.qualcomm.com>
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/main.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index a800837..559539b 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -534,6 +534,18 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
 				wpa_ie = pos; /* WPS IE */
 				break; /* overrides WPA/RSN IE */
 			}
+		} else if (pos[0] == 0x44 && wpa_ie == NULL) {
+			/*
+			 * Note: WAPI Parameter Set IE re-uses Element ID that
+			 * was officially allocated for BSS AC Access Delay. As
+			 * such, we need to be a bit more careful on when
+			 * parsing the frame. However, BSS AC Access Delay
+			 * element is not supposed to be included in
+			 * (Re)Association Request frames, so this should not
+			 * cause problems.
+			 */
+			wpa_ie = pos; /* WAPI IE */
+			break;
 		}
 		pos += 2 + pos[1];
 	}
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 2/3] ath6kl: Allow SMS4 to be configured in AP mode
From: Jouni Malinen @ 2011-11-03  9:39 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, Dai Shuibing, Jouni Malinen
In-Reply-To: <1320313179-9259-1-git-send-email-jouni@qca.qualcomm.com>

From: Dai Shuibing <shuibing@qca.qualcomm.com>

Signed-off-by: Dai Shuibing <shuibing@qca.qualcomm.com>
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/cfg80211.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 42eeed1..095a378 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1923,6 +1923,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
 		case WLAN_CIPHER_SUITE_CCMP:
 			p.prwise_crypto_type |= AES_CRYPT;
 			break;
+		case WLAN_CIPHER_SUITE_SMS4:
+			p.prwise_crypto_type |= WAPI_CRYPT;
+			break;
 		}
 	}
 	if (p.prwise_crypto_type == 0) {
@@ -1942,6 +1945,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
 	case WLAN_CIPHER_SUITE_CCMP:
 		p.grp_crypto_type = AES_CRYPT;
 		break;
+	case WLAN_CIPHER_SUITE_SMS4:
+		p.grp_crypto_type = WAPI_CRYPT;
+		break;
 	default:
 		p.grp_crypto_type = NONE_CRYPT;
 		break;
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 1/3] ath6kl: Add support for configuring SMS4 keys
From: Jouni Malinen @ 2011-11-03  9:39 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, Dai Shuibing, Jouni Malinen
In-Reply-To: <1320313179-9259-1-git-send-email-jouni@qca.qualcomm.com>

From: Dai Shuibing <shuibing@qca.qualcomm.com>

Indicate support for WPI-SMS4 cipher and allow SMS4 keys to be
configured.

Signed-off-by: Dai Shuibing <shuibing@qca.qualcomm.com>
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/cfg80211.c |   18 ++++++++++++++++--
 drivers/net/wireless/ath/ath6kl/common.h   |    1 +
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 04d24d4..42eeed1 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -203,6 +203,10 @@ static int ath6kl_set_cipher(struct ath6kl_vif *vif, u32 cipher, bool ucast)
 		*ar_cipher = AES_CRYPT;
 		*ar_cipher_len = 0;
 		break;
+	case WLAN_CIPHER_SUITE_SMS4:
+		*ar_cipher = WAPI_CRYPT;
+		*ar_cipher_len = 0;
+		break;
 	default:
 		ath6kl_err("cipher 0x%x not supported\n", cipher);
 		return -ENOTSUPP;
@@ -935,13 +939,19 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
 		key_usage = GROUP_USAGE;
 
 	if (params) {
+		int seq_len = params->seq_len;
+		if (params->cipher == WLAN_CIPHER_SUITE_SMS4 &&
+		    seq_len > ATH6KL_KEY_SEQ_LEN) {
+			/* Only first half of the WPI PN is configured */
+			seq_len = ATH6KL_KEY_SEQ_LEN;
+		}
 		if (params->key_len > WLAN_MAX_KEY_LEN ||
-		    params->seq_len > sizeof(key->seq))
+		    seq_len > sizeof(key->seq))
 			return -EINVAL;
 
 		key->key_len = params->key_len;
 		memcpy(key->key, params->key, key->key_len);
-		key->seq_len = params->seq_len;
+		key->seq_len = seq_len;
 		memcpy(key->seq, params->seq, key->seq_len);
 		key->cipher = params->cipher;
 	}
@@ -959,6 +969,9 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
 	case WLAN_CIPHER_SUITE_CCMP:
 		key_type = AES_CRYPT;
 		break;
+	case WLAN_CIPHER_SUITE_SMS4:
+		key_type = WAPI_CRYPT;
+		break;
 
 	default:
 		return -ENOTSUPP;
@@ -1451,6 +1464,7 @@ static const u32 cipher_suites[] = {
 	WLAN_CIPHER_SUITE_TKIP,
 	WLAN_CIPHER_SUITE_CCMP,
 	CCKM_KRK_CIPHER_SUITE,
+	WLAN_CIPHER_SUITE_SMS4,
 };
 
 static bool is_rate_legacy(s32 rate)
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h
index 41e465f..bfd6597 100644
--- a/drivers/net/wireless/ath/ath6kl/common.h
+++ b/drivers/net/wireless/ath/ath6kl/common.h
@@ -71,6 +71,7 @@ enum crypto_type {
 	WEP_CRYPT           = 0x02,
 	TKIP_CRYPT          = 0x04,
 	AES_CRYPT           = 0x08,
+	WAPI_CRYPT          = 0x10,
 };
 
 struct htc_endpoint_credit_dist;
-- 
1.7.4.1


^ permalink raw reply related

* Re: [PATCH] cfg80211: merge in beacon ies of hidden bss.
From: Johannes Berg @ 2011-11-03  9:39 UTC (permalink / raw)
  To: Dmitry Tarnyagin; +Cc: linux-wireless
In-Reply-To: <CAMG6FYhgeNg3CbDZg7GkJkq1ArJ=5n+bD=zPx=6ZFe7-Kj4Jmw@mail.gmail.com>

Hi Dmitry,

> >> +     if (!ie1 && !ie2)
> >> +             return 0;
> > I don't think it's valid to leave out the SSID IE, so I'd rather not
> > have that test here. It might interact badly with other uses (mesh?)
> >
> ie1 and ie2 could not NULL at the same time, otherwise the bss
> would be found in the first search attempt. However, I would prefer
> to have some water-proof check here. WARN_ON? BUG_ON?

Maybe a warning? But I don't see why it'll just fall through to the next
line and return -1 if one of them is missing.

> >> +             if (ie2[i + 2])
> >> +                     return -1;
> > I don't understand this loop. Why check that ie2 is zeroed, but check
> > only to the minlen of ie1, ie2?
> >
> Check that ie2 is zeroed is a check for hidden SSID.
> Check only to minlent to be in-line with cmp_ies().
> 
> >> +     return ie2[1] - ie1[1];
> > I'd error out much earlier if the length is different instead of
> > comparing to the minlen first.
> >
> Key comparator must use same algorithm in any rb-tree search function
> (order is important), otherwise ordering of items in the tree is broken
> and search gives incorrect results.
> This code uses same order as cmp_ies() does.

Oh. Good point. Add a comment?

> >> @@ -494,6 +578,13 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
> >>       spin_lock_bh(&dev->bss_lock);
> >>
> >>       found = rb_find_bss(dev, res);
> >> +     if (!found) {
> >> +             struct cfg80211_internal_bss *hidden;
> >> +
> >> +             hidden = rb_find_hidden_bss(dev, res);
> >> +             if (hidden)
> >> +                     merge_hidden_ies(res, hidden);
> >> +     }
> > I was going to complain that I don't understand why this works -- but
> > then I think now I do. If you move the code down into the else branch
> > it'll be much easier to follow.
> >
> Ok.
> 
> Thank you for review!

Eliad pointed out another thing: It is possible to have multiple SSIDs
hidden behind a single hidden SSID. Therefore, this should update all of
those BSS structs. Also, I'm a tad confused about the matching code
here, this code path executes for both received beacons and probe
responses, but probe responses would typically have found the BSS
already? But what if we only have a beacon and then receive a probe
response? Or vice versa? Some comments would be good outlining how that
works.

johannes


^ permalink raw reply

* Re: [PATCH] cfg80211: merge in beacon ies of hidden bss.
From: Dmitry Tarnyagin @ 2011-11-03  9:17 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320310524.3950.29.camel@jlt3.sipsolutions.net>

Hi Johannes,

On Thu, Nov 3, 2011 at 9:55 AM, Johannes Berg <johannes@sipsolutions.net> wrote:

>> +     if (!ie1 && !ie2)
>> +             return 0;
> I don't think it's valid to leave out the SSID IE, so I'd rather not
> have that test here. It might interact badly with other uses (mesh?)
>
ie1 and ie2 could not NULL at the same time, otherwise the bss
would be found in the first search attempt. However, I would prefer
to have some water-proof check here. WARN_ON? BUG_ON?

>> +     for (i = 0; i < ielen; ++i)
> ++i here is a bit atypical code style.
>
Ok.

>> +             if (ie2[i + 2])
>> +                     return -1;
> I don't understand this loop. Why check that ie2 is zeroed, but check
> only to the minlen of ie1, ie2?
>
Check that ie2 is zeroed is a check for hidden SSID.
Check only to minlent to be in-line with cmp_ies().

>> +     return ie2[1] - ie1[1];
> I'd error out much earlier if the length is different instead of
> comparing to the minlen first.
>
Key comparator must use same algorithm in any rb-tree search function
(order is important), otherwise ordering of items in the tree is broken
and search gives incorrect results.
This code uses same order as cmp_ies() does.

>
>> +static int
>> +merge_hidden_ies(struct cfg80211_internal_bss *res,
>> +              struct cfg80211_internal_bss *hidden)
> There seems little use for the return value.
>
Agree. int -> void

>> @@ -494,6 +578,13 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
>>       spin_lock_bh(&dev->bss_lock);
>>
>>       found = rb_find_bss(dev, res);
>> +     if (!found) {
>> +             struct cfg80211_internal_bss *hidden;
>> +
>> +             hidden = rb_find_hidden_bss(dev, res);
>> +             if (hidden)
>> +                     merge_hidden_ies(res, hidden);
>> +     }
> I was going to complain that I don't understand why this works -- but
> then I think now I do. If you move the code down into the else branch
> it'll be much easier to follow.
>
Ok.

Thank you for review!

With best regards,
Dmitry

^ permalink raw reply

* [PATCH] mac80211: preserve EOSP in QoS header
From: Johannes Berg @ 2011-11-03  8:59 UTC (permalink / raw)
  To: John Linville; +Cc: Janusz Dziedzic, linux-wireless

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

Janusz reported that the EOSP bit in mac80211 was
getting cleared all the time. I had not found this
since I tested uAPSD with a device that always set
the bit itself. Preserve the bit when building the
QoS header.

Reported-by: Janusz Dziedzic <janusz.dziedzic@gmail.com>
Tested-by: Janusz Dziedzic <janusz.dziedzic@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
This might conflict slightly with Thomas's patch that adds
the NOACK bit for multicast frames.

 net/mac80211/wme.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

--- a/net/mac80211/wme.c	2011-11-02 11:05:29.000000000 +0100
+++ b/net/mac80211/wme.c	2011-11-03 09:14:30.000000000 +0100
@@ -143,10 +143,13 @@ void ieee80211_set_qos_hdr(struct ieee80
 	/* Fill in the QoS header if there is one. */
 	if (ieee80211_is_data_qos(hdr->frame_control)) {
 		u8 *p = ieee80211_get_qos_ctl(hdr);
-		u8 ack_policy = 0, tid;
+		u8 ack_policy, tid;
 
 		tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
 
+		/* preserve EOSP bit */
+		ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
+
 		if (unlikely(sdata->local->wifi_wme_noack_test))
 			ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
 		/* qos header is 2 bytes */



^ permalink raw reply

* Re: [PATCH] cfg80211: merge in beacon ies of hidden bss.
From: Johannes Berg @ 2011-11-03  8:55 UTC (permalink / raw)
  To: Dmitry Tarnyagin; +Cc: linux-wireless
In-Reply-To: <CAMG6FYiV8F=MFBeUQCGSj__h=REVLMvTZCvLEvDPT7GP2KWsWw@mail.gmail.com>

On Wed, 2011-11-02 at 19:19 +0100, Dmitry Tarnyagin wrote:

> +static int cmp_hidden_bss(struct cfg80211_bss *a,
> +		   struct cfg80211_bss *b)
> +{
> +	const u8 *ie1;
> +	const u8 *ie2;
> +	size_t ielen;
> +	int i;
> +	int r;
> +
> +	r = cmp_bss_core(a, b);
> +	if (r)
> +		return r;
> +
> +	ie1 = cfg80211_find_ie(WLAN_EID_SSID,
> +			a->information_elements,
> +			a->len_information_elements);
> +	ie2 = cfg80211_find_ie(WLAN_EID_SSID,
> +			b->information_elements,
> +			b->len_information_elements);
> +	if (!ie1 && !ie2)
> +		return 0;

I don't think it's valid to leave out the SSID IE, so I'd rather not
have that test here. It might interact badly with other uses (mesh?)

> +	if (!ie1 || !ie2)
> +		return -1;
> +
> +	ielen = min(ie1[1], ie2[1]);
> +	for (i = 0; i < ielen; ++i)

++i here is a bit atypical code style.

> +		if (ie2[i + 2])
> +			return -1;

I don't understand this loop. Why check that ie2 is zeroed, but check
only to the minlen of ie1, ie2?

> +	return ie2[1] - ie1[1];

I'd error out much earlier if the length is different instead of
comparing to the minlen first.

> +static int
> +merge_hidden_ies(struct cfg80211_internal_bss *res,
> +		 struct cfg80211_internal_bss *hidden)

There seems little use for the return value.

> +{
> +	if (unlikely(res->pub.beacon_ies))
> +		return -EALREADY;
> +	if (WARN_ON(!hidden->pub.beacon_ies))
> +		return -EINVAL;
> +
> +	res->pub.beacon_ies = kmalloc(hidden->pub.len_beacon_ies, GFP_ATOMIC);
> +	if (unlikely(!res->pub.beacon_ies))
> +		return -ENOMEM;
> +
> +	res->beacon_ies_allocated = true;
> +	res->pub.len_beacon_ies = hidden->pub.len_beacon_ies;
> +	memcpy(res->pub.beacon_ies, hidden->pub.beacon_ies,
> +			res->pub.len_beacon_ies);
> +
> +	return 0;
> +}
> +
> +static struct cfg80211_internal_bss *
>  cfg80211_bss_update(struct cfg80211_registered_device *dev,
>  		    struct cfg80211_internal_bss *res)
>  {
> @@ -494,6 +578,13 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
>  	spin_lock_bh(&dev->bss_lock);
> 
>  	found = rb_find_bss(dev, res);
> +	if (!found) {
> +		struct cfg80211_internal_bss *hidden;
> +
> +		hidden = rb_find_hidden_bss(dev, res);
> +		if (hidden)
> +			merge_hidden_ies(res, hidden);
> +	}

I was going to complain that I don't understand why this works -- but
then I think now I do. If you move the code down into the else branch
it'll be much easier to follow.

johannes


^ permalink raw reply

* Re: mac80211: UAPSD - EOSP bit seems to be not set when send qos null frame
From: Janusz Dziedzic @ 2011-11-03  8:49 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320308142.3950.3.camel@jlt3.sipsolutions.net>

2011/11/3 Johannes Berg <johannes@sipsolutions.net>:
> On Thu, 2011-11-03 at 09:08 +0100, Johannes Berg wrote:
>
>> > Yes, I see this is set correctly before we call ieee80211_set_qos_hdr().
>> > Next ieee80211_set_qos_hdr() fuction seems not care about EOSP bit and
>> > we have this bit cleared before ieee80211_tx() call.
>>
>> Oh, WTH. Somebody had posted a patch that fixed that, I thought that
>> went in but in my testing this didn't show up since my device always
>> sets/clears it according to what I told it.
>
> Try this please.
>
> johannes
>
> --- wireless-testing.orig/net/mac80211/wme.c    2011-11-02 11:05:29.000000000 +0100
> +++ wireless-testing/net/mac80211/wme.c 2011-11-03 09:14:30.000000000 +0100
> @@ -143,10 +143,13 @@ void ieee80211_set_qos_hdr(struct ieee80
>        /* Fill in the QoS header if there is one. */
>        if (ieee80211_is_data_qos(hdr->frame_control)) {
>                u8 *p = ieee80211_get_qos_ctl(hdr);
> -               u8 ack_policy = 0, tid;
> +               u8 ack_policy, tid;
>
>                tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
>
> +               /* preserve EOSP bit */
> +               ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
> +
>                if (unlikely(sdata->local->wifi_wme_noack_test))
>                        ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
>                /* qos header is 2 bytes */
>
>
>

Verified. Now works correctly.
Thanks.

BR
Janusz

^ permalink raw reply


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