Linux wireless drivers development
 help / color / mirror / Atom feed
* [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

* [PATCH 2/2] ath9k: integrate initial DFS module
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 patch integrates the DFS module into ath9k, including
 * build the module into ath9k_hw
 * set up DFS debugfs
 * define HW capability flag for DFS support
   (so far: AR_SREV_9280_20_OR_LATER, TBC)
 * define and set DFS opmode flag when on DFS channel
   * configure radar params after reset
   * provide radar RX filter flag in ath_calcrxfilter()
 * 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 not part of this patch.

Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
---
 drivers/net/wireless/ath/ath9k/Makefile |    2 ++
 drivers/net/wireless/ath/ath9k/ath9k.h  |    1 +
 drivers/net/wireless/ath/ath9k/debug.c  |    3 +++
 drivers/net/wireless/ath/ath9k/debug.h  |    2 ++
 drivers/net/wireless/ath/ath9k/hw-ops.h |    9 +++++++++
 drivers/net/wireless/ath/ath9k/hw.c     |    7 +++++++
 drivers/net/wireless/ath/ath9k/hw.h     |    1 +
 drivers/net/wireless/ath/ath9k/main.c   |   16 ++++++++++++++++
 drivers/net/wireless/ath/ath9k/recv.c   |   19 ++++++++++++++-----
 9 files changed, 55 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/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 7ab7a1e..de0309e 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -563,6 +563,7 @@ struct ath_ant_comb {
 #define SC_OP_BT_SCAN		     BIT(13)
 #define SC_OP_ANI_RUN		     BIT(14)
 #define SC_OP_PRIM_STA_VIF	     BIT(15)
+#define SC_OP_DFS		     BIT(16)
 
 /* Powersave flags */
 #define PS_WAIT_FOR_BEACON        BIT(0)
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-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index e74c233..c4ad0b0 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -212,4 +212,13 @@ static inline int ath9k_hw_fast_chan_change(struct ath_hw *ah,
 	return ath9k_hw_private_ops(ah)->fast_chan_change(ah, chan,
 							  ini_reloaded);
 }
+
+static inline void ath9k_hw_set_radar_params(struct ath_hw *ah)
+{
+	if (!ath9k_hw_private_ops(ah)->set_radar_params)
+		return;
+
+	ath9k_hw_private_ops(ah)->set_radar_params(ah, &ah->radar_conf);
+}
+
 #endif /* ATH9K_HW_OPS_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 76dbc85..c9ba80d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2333,6 +2333,13 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 		pCap->pcie_lcr_offset = 0x80;
 	}
 
+	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;
+	}
+
 	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..e86d820 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -305,6 +305,10 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
 		ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf);
 	}
 
+	/* set radar parameters if in DFS mode */
+	if (sc->sc_flags & SC_OP_DFS)
+		ath9k_hw_set_radar_params(ah);
+
 	ieee80211_wake_queues(sc->hw);
 
 	return true;
@@ -1722,9 +1726,21 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 			memset(&sc->survey[pos], 0, sizeof(struct survey_info));
 		}
 
+		if (curchan->flags & IEEE80211_CHAN_RADAR) {
+			if (!(ah->caps.hw_caps & ATH9K_HW_CAP_DFS)) {
+				ath_err(common, "HW does not support DFS\n");
+				mutex_unlock(&sc->mutex);
+				return -EINVAL;
+			}
+			sc->sc_flags |= SC_OP_DFS;
+		} else
+			sc->sc_flags &= ~SC_OP_DFS;
+
 		if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
 			ath_err(common, "Unable to set channel\n");
 			mutex_unlock(&sc->mutex);
+			/* clear DFS operation flag on failure */
+			sc->sc_flags &= ~SC_OP_DFS;
 			return -EINVAL;
 		}
 
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 0d5f275..76d804c 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))
 
@@ -473,6 +474,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
 		rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
 	}
 
+	if (sc->sc_flags & SC_OP_DFS)
+		rfilt |= ATH9K_RX_FILTER_PHYRADAR;
 	return rfilt;
 
 #undef RX_FILTER_PRESERVE
@@ -1855,11 +1858,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))
@@ -1869,6 +1867,17 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		    unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
 			rxs->mactime += 0x100000000ULL;
 
+		if ((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

* [PATCH 0/2] ath9k: DFS radar detection
From: Zefir Kurtisi @ 2011-11-08 16:34 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ath9k-devel, rodrigue, shafi.wireless, nbd,
	Zefir Kurtisi

This patch series proposes DFS radar pulse detection for ath9k.

The first patch adds a new DFS module, the second turns those
knobs to enable the HW to detect radar pulses and forward them
to the new module.

Here, sanity and plausibility checks that are HW dependent are
performed and resulting radar events are passed to higher level
generic pattern detectors for further processing (spectrum
management, etc.).

DFS support is limited to newer chip-sets (for now 9280 and later).

So far, AP operation on DFS channels is not supported by 
mac80211/hostapd. Testing the proposed pulse detection is done in
monitor mode.

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/ath9k.h     |    1 +
 drivers/net/wireless/ath/ath9k/debug.c     |    3 +
 drivers/net/wireless/ath/ath9k/debug.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 ++++++++
 drivers/net/wireless/ath/ath9k/hw-ops.h    |    9 ++
 drivers/net/wireless/ath/ath9k/hw.c        |    7 +
 drivers/net/wireless/ath/ath9k/hw.h        |    1 +
 drivers/net/wireless/ath/ath9k/main.c      |   16 +++
 drivers/net/wireless/ath/ath9k/recv.c      |   19 ++-
 14 files changed, 446 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

* Re: [PATCH v3 1/3] nl80211: Add probe response offload attribute
From: Arik Nemtsov @ 2011-11-08 16:17 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Jouni Malinen, linux-wireless
In-Reply-To: <1320767928.24797.14.camel@jlt3.sipsolutions.net>

On Tue, Nov 8, 2011 at 17:58, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2011-11-08 at 17:53 +0200, Arik Nemtsov wrote:
>> On Tue, Nov 8, 2011 at 17:31, Johannes Berg <johannes@sipsolutions.net> wrote:
>> > On Tue, 2011-11-08 at 16:35 +0200, Arik Nemtsov wrote:
>> Actually wl12xx "supports" the legacy way as well. We can operate
>> without wpa_s explicitly setting the probe-resp (even though we just
>> piece it together in other ways).
>> In this sense, it's not a mandatory feature. If wpa_s fails to
>> generate it for some reason, we don't want it to fail the AP load. The
>> AP will operate just fine.
>
> It'll operate, not sure about "just fine" :-) The way I see it that's
> mostly a backward compatibility feature, no?

I guess so. I can make the wording more explicit there so as not to confuse.

>
>> >> +++ b/include/net/cfg80211.h
>> >> @@ -1693,6 +1693,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_SUPPORT_PROBE_RESP_OFFLOAD   = BIT(17),
>> >
>> > Ditto here, maybe WIPHY_FLAG_HAS_PROBE_RESP_OFFLOAD?

sure.

>> >
>> > As we discussed, ath6kl & similar full-mac drivers with AP SME in the
>> > device should set this to advertise the probe protocol feature set they
>> > support (by passing up), and even for wl12xx it's not optional.
>>
>> All this has to do with user-space semantics. Currently hostap always
>> sets the probe-resp IEs, without checking offloading support.
>
> Which is fine too, but I think ath6kl should set this value right?

I'll add this to the kernel side for now, with no checks in hostap.

Arik

^ permalink raw reply

* Re: [PATCH v3 2/3] nl80211: Pass probe response data to drivers
From: Johannes Berg @ 2011-11-08 16:10 UTC (permalink / raw)
  To: Arik Nemtsov; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <CA+XVXffzmfOPEqJ=LhAhXwAjAjBJKtQOnOsRMHW8stodm0saFw@mail.gmail.com>

On Tue, 2011-11-08 at 18:04 +0200, Arik Nemtsov wrote:
> On Tue, Nov 8, 2011 at 17:32, Johannes Berg <johannes@sipsolutions.net> wrote:
> > On Tue, 2011-11-08 at 16:35 +0200, Arik Nemtsov wrote:
> >> 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>
> >> ---
> >> v1->3:
> >> Set the probe response data as part of the addset_beacon function, instead
> >> of set_bss. This makes more sense since the probe response is always
> >> updated with the beacon.
> >>
> >> include/linux/nl80211.h |    4 ++++
> >>  include/net/cfg80211.h  |    4 ++++
> >>  net/wireless/nl80211.c  |    9 +++++++++
> >>  3 files changed, 17 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
> >> index e74afc4..3fa03b3 100644
> >> --- a/include/linux/nl80211.h
> >> +++ b/include/linux/nl80211.h
> >> @@ -1114,6 +1114,8 @@ enum nl80211_commands {
> >>   *   In addition this attribute holds a bitmap of the supported protocols
> >>   *   for offloading using &enum nl80211_probe_resp_offload_support_attr.
> >>   *
> >> + * @NL80211_ATTR_PROBE_RESP: Probe Response template data
> >> + *
> >
> > That should say what kind of data is expected -- I think a full frame in
> > this case? Should it really be a full frame though? Maybe ath6kl
> > requires something else and we can make this somehow compatible with
> > both?
> 
> I can be more verbose in the description, sure. The probe-resp IEs are
> a subset of the full probe-resp template, so I guess we could give ath6kl a
> start_pos, end_pos into the full probe_resp buffer.
> 
> But IMHO it's cleaner the way it is now.

Agree, thanks for explaining (and on IRC too).

johannes


^ permalink raw reply

* Re: [PATCH v3 3/3] mac80211: Save probe response data for bss
From: Arik Nemtsov @ 2011-11-08 16:07 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320766462.24797.7.camel@jlt3.sipsolutions.net>

On Tue, Nov 8, 2011 at 17:34, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2011-11-08 at 16:35 +0200, Arik Nemtsov wrote:
>
>> +     new = dev_alloc_skb(resp_len);
>> +     if (!new) {
>> +             printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
>> +                    "response template\n", sdata->name);
>
> I'm pretty sure that will already warn so the message is probably not
> very useful.

Sure. I'll remove it.

^ permalink raw reply

* Re: [PATCH v3 2/3] nl80211: Pass probe response data to drivers
From: Arik Nemtsov @ 2011-11-08 16:04 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1320766360.24797.5.camel@jlt3.sipsolutions.net>

On Tue, Nov 8, 2011 at 17:32, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2011-11-08 at 16:35 +0200, Arik Nemtsov wrote:
>> 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>
>> ---
>> v1->3:
>> Set the probe response data as part of the addset_beacon function, instead
>> of set_bss. This makes more sense since the probe response is always
>> updated with the beacon.
>>
>> include/linux/nl80211.h |    4 ++++
>>  include/net/cfg80211.h  |    4 ++++
>>  net/wireless/nl80211.c  |    9 +++++++++
>>  3 files changed, 17 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
>> index e74afc4..3fa03b3 100644
>> --- a/include/linux/nl80211.h
>> +++ b/include/linux/nl80211.h
>> @@ -1114,6 +1114,8 @@ enum nl80211_commands {
>>   *   In addition this attribute holds a bitmap of the supported protocols
>>   *   for offloading using &enum nl80211_probe_resp_offload_support_attr.
>>   *
>> + * @NL80211_ATTR_PROBE_RESP: Probe Response template data
>> + *
>
> That should say what kind of data is expected -- I think a full frame in
> this case? Should it really be a full frame though? Maybe ath6kl
> requires something else and we can make this somehow compatible with
> both?

I can be more verbose in the description, sure. The probe-resp IEs are
a subset of the full probe-resp template, so I guess we could give ath6kl a
start_pos, end_pos into the full probe_resp buffer.

But IMHO it's cleaner the way it is now.

^ permalink raw reply

* Re: [PATCH v3 1/3] nl80211: Add probe response offload attribute
From: Johannes Berg @ 2011-11-08 15:58 UTC (permalink / raw)
  To: Arik Nemtsov; +Cc: Jouni Malinen, linux-wireless
In-Reply-To: <CA+XVXfcrbfVvs+PQCjyrW_QZSKZiAzKUvrqbjqJr47dU73=n2A@mail.gmail.com>

On Tue, 2011-11-08 at 17:53 +0200, Arik Nemtsov wrote:
> On Tue, Nov 8, 2011 at 17:31, Johannes Berg <johannes@sipsolutions.net> wrote:
> > On Tue, 2011-11-08 at 16:35 +0200, Arik Nemtsov wrote:
> >> 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.
> >
> >> + * @NL80211_ATTR_PROBE_RESP_OFFLOAD_SUPPORT: Indicates support for probe
> >> + *   response offloading by the driver/firmware.
> >> + *   In addition this attribute holds a bitmap of the supported protocols
> >> + *   for offloading using &enum nl80211_probe_resp_offload_support_attr.
> >
> > I wonder if this should make it more clear that probe requests will be
> > replied to, and this is not optional?
> 
> Actually wl12xx "supports" the legacy way as well. We can operate
> without wpa_s explicitly setting the probe-resp (even though we just
> piece it together in other ways).
> In this sense, it's not a mandatory feature. If wpa_s fails to
> generate it for some reason, we don't want it to fail the AP load. The
> AP will operate just fine.

It'll operate, not sure about "just fine" :-) The way I see it that's
mostly a backward compatibility feature, no?

> >> +++ b/include/net/cfg80211.h
> >> @@ -1693,6 +1693,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_SUPPORT_PROBE_RESP_OFFLOAD   = BIT(17),
> >
> > Ditto here, maybe WIPHY_FLAG_HAS_PROBE_RESP_OFFLOAD?
> >
> > As we discussed, ath6kl & similar full-mac drivers with AP SME in the
> > device should set this to advertise the probe protocol feature set they
> > support (by passing up), and even for wl12xx it's not optional.
> 
> All this has to do with user-space semantics. Currently hostap always
> sets the probe-resp IEs, without checking offloading support.

Which is fine too, but I think ath6kl should set this value right?

johannes


^ permalink raw reply

* Re: [PATCH] mac80211: set carrier_on for ibss vifs only while joined
From: Johannes Berg @ 2011-11-08 15:57 UTC (permalink / raw)
  To: Eliad Peller; +Cc: linux-wireless
In-Reply-To: <CAB3XZEcGPTzvnTg7DtG8q0E3pGT8KH+tozaO4ZtMGHyQNks_8A@mail.gmail.com>

On Tue, 2011-11-08 at 17:42 +0200, Eliad Peller wrote:
> On Tue, Nov 8, 2011 at 5:27 PM, Johannes Berg <johannes@sipsolutions.net> wrote:
> > On Tue, 2011-11-08 at 15:36 +0200, Eliad Peller wrote:
> >> mac80211 should set carrier_on for ibss vifs
> >> only while they are joined (similar to sta vifs)
> >
> >> --- a/net/mac80211/ibss.c
> >> +++ b/net/mac80211/ibss.c
> >> @@ -97,6 +97,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
> >>       /* if merging, indicate to driver that we leave the old IBSS */
> >>       if (sdata->vif.bss_conf.ibss_joined) {
> >>               sdata->vif.bss_conf.ibss_joined = false;
> >> +             netif_carrier_off(sdata->dev);
> >>               ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS);
> >>       }
> >>
> >> @@ -207,6 +208,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
> >>       bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
> >>                                       mgmt, skb->len, 0, GFP_KERNEL);
> >>       cfg80211_put_bss(bss);
> >> +     netif_carrier_on(sdata->dev);
> >>       cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
> >
> > Do we really need to toggle the carrier here? While we merge, shouldn't
> > we just keep it up, just maybe stop the queues?
> >
> technically, we leave the ibss and then rejoin (unlike roaming). so i
> guess setting the carrier on/off makes sense as well.
> do you prefer stopping the queues instead?

No, I don't really know :)

johannes


^ permalink raw reply

* Re: [PATCH v3 1/3] nl80211: Add probe response offload attribute
From: Arik Nemtsov @ 2011-11-08 15:53 UTC (permalink / raw)
  To: Johannes Berg, Jouni Malinen; +Cc: linux-wireless
In-Reply-To: <1320766291.24797.4.camel@jlt3.sipsolutions.net>

On Tue, Nov 8, 2011 at 17:31, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2011-11-08 at 16:35 +0200, Arik Nemtsov wrote:
>> 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.
>
>> + * @NL80211_ATTR_PROBE_RESP_OFFLOAD_SUPPORT: Indicates support for probe
>> + *   response offloading by the driver/firmware.
>> + *   In addition this attribute holds a bitmap of the supported protocols
>> + *   for offloading using &enum nl80211_probe_resp_offload_support_attr.
>
> I wonder if this should make it more clear that probe requests will be
> replied to, and this is not optional?

Actually wl12xx "supports" the legacy way as well. We can operate
without wpa_s explicitly setting the probe-resp (even though we just
piece it together in other ways).
In this sense, it's not a mandatory feature. If wpa_s fails to
generate it for some reason, we don't want it to fail the AP load. The
AP will operate just fine.

>
>> +++ b/include/net/cfg80211.h
>> @@ -1693,6 +1693,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_SUPPORT_PROBE_RESP_OFFLOAD   = BIT(17),
>
> Ditto here, maybe WIPHY_FLAG_HAS_PROBE_RESP_OFFLOAD?
>
> As we discussed, ath6kl & similar full-mac drivers with AP SME in the
> device should set this to advertise the probe protocol feature set they
> support (by passing up), and even for wl12xx it's not optional.

All this has to do with user-space semantics. Currently hostap always
sets the probe-resp IEs, without checking offloading support.

Jouni/ath6kl people - are you ok with adding some checks before
sending the extra IEs to kernel, as ath6kl is using them?

Arik

^ permalink raw reply

* Re: [PATCH] mac80211: set carrier_on for ibss vifs only while joined
From: Eliad Peller @ 2011-11-08 15:42 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320766054.24797.2.camel@jlt3.sipsolutions.net>

On Tue, Nov 8, 2011 at 5:27 PM, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2011-11-08 at 15:36 +0200, Eliad Peller wrote:
>> mac80211 should set carrier_on for ibss vifs
>> only while they are joined (similar to sta vifs)
>
>> --- a/net/mac80211/ibss.c
>> +++ b/net/mac80211/ibss.c
>> @@ -97,6 +97,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
>>       /* if merging, indicate to driver that we leave the old IBSS */
>>       if (sdata->vif.bss_conf.ibss_joined) {
>>               sdata->vif.bss_conf.ibss_joined = false;
>> +             netif_carrier_off(sdata->dev);
>>               ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS);
>>       }
>>
>> @@ -207,6 +208,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
>>       bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
>>                                       mgmt, skb->len, 0, GFP_KERNEL);
>>       cfg80211_put_bss(bss);
>> +     netif_carrier_on(sdata->dev);
>>       cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
>
> Do we really need to toggle the carrier here? While we merge, shouldn't
> we just keep it up, just maybe stop the queues?
>
technically, we leave the ibss and then rejoin (unlike roaming). so i
guess setting the carrier on/off makes sense as well.
do you prefer stopping the queues instead?

Eliad.

^ permalink raw reply

* Re: [PATCH v3 3/3] mac80211: Save probe response data for bss
From: Johannes Berg @ 2011-11-08 15:34 UTC (permalink / raw)
  To: Arik Nemtsov; +Cc: linux-wireless
In-Reply-To: <1320762928-6782-3-git-send-email-arik@wizery.com>

On Tue, 2011-11-08 at 16:35 +0200, Arik Nemtsov wrote:

> +	new = dev_alloc_skb(resp_len);
> +	if (!new) {
> +		printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
> +		       "response template\n", sdata->name);

I'm pretty sure that will already warn so the message is probably not
very useful.

johannes


^ permalink raw reply

* Re: [PATCH v3 2/3] nl80211: Pass probe response data to drivers
From: Johannes Berg @ 2011-11-08 15:32 UTC (permalink / raw)
  To: Arik Nemtsov; +Cc: linux-wireless, Jouni Malinen
In-Reply-To: <1320762928-6782-2-git-send-email-arik@wizery.com>

On Tue, 2011-11-08 at 16:35 +0200, Arik Nemtsov wrote:
> 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>
> ---
> v1->3:
> Set the probe response data as part of the addset_beacon function, instead
> of set_bss. This makes more sense since the probe response is always
> updated with the beacon.
> 
> include/linux/nl80211.h |    4 ++++
>  include/net/cfg80211.h  |    4 ++++
>  net/wireless/nl80211.c  |    9 +++++++++
>  3 files changed, 17 insertions(+), 0 deletions(-)
> 
> diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
> index e74afc4..3fa03b3 100644
> --- a/include/linux/nl80211.h
> +++ b/include/linux/nl80211.h
> @@ -1114,6 +1114,8 @@ enum nl80211_commands {
>   *	In addition this attribute holds a bitmap of the supported protocols
>   *	for offloading using &enum nl80211_probe_resp_offload_support_attr.
>   *
> + * @NL80211_ATTR_PROBE_RESP: Probe Response template data
> + *

That should say what kind of data is expected -- I think a full frame in
this case? Should it really be a full frame though? Maybe ath6kl
requires something else and we can make this somehow compatible with
both?

johannes


^ permalink raw reply

* Re: [PATCH v3 1/3] nl80211: Add probe response offload attribute
From: Johannes Berg @ 2011-11-08 15:31 UTC (permalink / raw)
  To: Arik Nemtsov; +Cc: linux-wireless
In-Reply-To: <1320762928-6782-1-git-send-email-arik@wizery.com>

On Tue, 2011-11-08 at 16:35 +0200, Arik Nemtsov wrote:
> 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.

> + * @NL80211_ATTR_PROBE_RESP_OFFLOAD_SUPPORT: Indicates support for probe
> + *	response offloading by the driver/firmware.
> + *	In addition this attribute holds a bitmap of the supported protocols
> + *	for offloading using &enum nl80211_probe_resp_offload_support_attr.

I wonder if this should make it more clear that probe requests will be
replied to, and this is not optional?

> +++ b/include/net/cfg80211.h
> @@ -1693,6 +1693,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_SUPPORT_PROBE_RESP_OFFLOAD	= BIT(17),

Ditto here, maybe WIPHY_FLAG_HAS_PROBE_RESP_OFFLOAD?

As we discussed, ath6kl & similar full-mac drivers with AP SME in the
device should set this to advertise the probe protocol feature set they
support (by passing up), and even for wl12xx it's not optional.

johannes


^ permalink raw reply

* Re: [PATCH] mac80211: set carrier_on for ibss vifs only while joined
From: Johannes Berg @ 2011-11-08 15:27 UTC (permalink / raw)
  To: Eliad Peller; +Cc: linux-wireless
In-Reply-To: <1320759419-20743-1-git-send-email-eliad@wizery.com>

On Tue, 2011-11-08 at 15:36 +0200, Eliad Peller wrote:
> mac80211 should set carrier_on for ibss vifs
> only while they are joined (similar to sta vifs)

> --- a/net/mac80211/ibss.c
> +++ b/net/mac80211/ibss.c
> @@ -97,6 +97,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
>  	/* if merging, indicate to driver that we leave the old IBSS */
>  	if (sdata->vif.bss_conf.ibss_joined) {
>  		sdata->vif.bss_conf.ibss_joined = false;
> +		netif_carrier_off(sdata->dev);
>  		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS);
>  	}
>  
> @@ -207,6 +208,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
>  	bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
>  					mgmt, skb->len, 0, GFP_KERNEL);
>  	cfg80211_put_bss(bss);
> +	netif_carrier_on(sdata->dev);
>  	cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);

Do we really need to toggle the carrier here? While we merge, shouldn't
we just keep it up, just maybe stop the queues?

johannes


^ permalink raw reply

* Re: [PATCH v3 1/2] wl12xx: configure probe-resp template according to notification
From: Arik Nemtsov @ 2011-11-08 15:26 UTC (permalink / raw)
  To: Eliad Peller; +Cc: linux-wireless, Luciano Coelho
In-Reply-To: <CAB3XZEcm_4kppAkQbp+HrBAgPSY5W1jiJ5qst2V5E+4x5TMHoA@mail.gmail.com>

On Tue, Nov 8, 2011 at 17:13, Eliad Peller <eliad@wizery.com> wrote:
> On Tue, Nov 8, 2011 at 4:36 PM, Arik Nemtsov <arik@wizery.com> wrote:
>> 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>
>> ---
> [...]
>> +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;
>> +}
>
> add a check for max template size?

There's already a check inside. There's a WARN_ON, and the template is
just truncated to the max size.

^ permalink raw reply

* [PATCH] mac80211: simplify scan state machine
From: Johannes Berg @ 2011-11-08 15:21 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

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

Attempting to micro-optimise the scan by going
fully live again when scanning the operating
channel just made the code extremely complex
and has little gain in most use cases. Remove
all that code and simplify the state machine
again.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ieee80211_i.h |   11 +-
 net/mac80211/scan.c        |  201 +++++++++++++++++----------------------------
 2 files changed, 83 insertions(+), 129 deletions(-)

--- a/net/mac80211/scan.c	2011-11-08 15:22:36.000000000 +0100
+++ b/net/mac80211/scan.c	2011-11-08 15:47:57.000000000 +0100
@@ -212,12 +212,7 @@ ieee80211_scan_rx(struct ieee80211_sub_i
 	if (bss)
 		ieee80211_rx_bss_put(sdata->local, bss);
 
-	/* If we are on-operating-channel, and this packet is for the
-	 * current channel, pass the pkt on up the stack so that
-	 * the rest of the stack can make use of it.
-	 */
-	if (ieee80211_cfg_on_oper_channel(sdata->local)
-	    && (channel == sdata->local->oper_channel))
+	if (channel == sdata->local->oper_channel)
 		return RX_CONTINUE;
 
 	dev_kfree_skb(skb);
@@ -263,8 +258,6 @@ static void __ieee80211_scan_completed(s
 				       bool was_hw_scan)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
-	bool on_oper_chan;
-	bool enable_beacons = false;
 
 	lockdep_assert_held(&local->mtx);
 
@@ -297,25 +290,13 @@ static void __ieee80211_scan_completed(s
 	local->scanning = 0;
 	local->scan_channel = NULL;
 
-	on_oper_chan = ieee80211_cfg_on_oper_channel(local);
-
-	if (was_hw_scan || !on_oper_chan)
-		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
-	else
-		/* Set power back to normal operating levels. */
-		ieee80211_hw_config(local, 0);
+	/* Set power back to normal operating levels. */
+	ieee80211_hw_config(local, 0);
 
 	if (!was_hw_scan) {
-		bool on_oper_chan2;
 		ieee80211_configure_filter(local);
 		drv_sw_scan_complete(local);
-		on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
-		/* We should always be on-channel at this point. */
-		WARN_ON(!on_oper_chan2);
-		if (on_oper_chan2 && (on_oper_chan != on_oper_chan2))
-			enable_beacons = true;
-
-		ieee80211_offchannel_return(local, enable_beacons, true);
+		ieee80211_offchannel_return(local, true, true);
 	}
 
 	ieee80211_recalc_idle(local);
@@ -360,11 +341,7 @@ static int ieee80211_start_sw_scan(struc
 	local->next_scan_state = SCAN_DECISION;
 	local->scan_channel_idx = 0;
 
-	/* We always want to use off-channel PS, even if we
-	 * are not really leaving oper-channel.  Don't
-	 * tell the AP though, as long as we are on-channel.
-	 */
-	ieee80211_offchannel_enable_all_ps(local, false);
+	ieee80211_offchannel_stop_vifs(local, true);
 
 	ieee80211_configure_filter(local);
 
@@ -372,8 +349,7 @@ static int ieee80211_start_sw_scan(struc
 	ieee80211_hw_config(local, 0);
 
 	ieee80211_queue_delayed_work(&local->hw,
-				     &local->scan_work,
-				     IEEE80211_CHANNEL_TIME);
+				     &local->scan_work, 0);
 
 	return 0;
 }
@@ -509,96 +485,39 @@ static void ieee80211_scan_state_decisio
 
 	next_chan = local->scan_req->channels[local->scan_channel_idx];
 
-	if (ieee80211_cfg_on_oper_channel(local)) {
-		/* We're currently on operating channel. */
-		if (next_chan == local->oper_channel)
-			/* We don't need to move off of operating channel. */
-			local->next_scan_state = SCAN_SET_CHANNEL;
-		else
-			/*
-			 * We do need to leave operating channel, as next
-			 * scan is somewhere else.
-			 */
-			local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
-	} else {
-		/*
-		 * we're currently scanning a different channel, let's
-		 * see if we can scan another channel without interfering
-		 * with the current traffic situation.
-		 *
-		 * Since we don't know if the AP has pending frames for us
-		 * we can only check for our tx queues and use the current
-		 * pm_qos requirements for rx. Hence, if no tx traffic occurs
-		 * at all we will scan as many channels in a row as the pm_qos
-		 * latency allows us to. Additionally we also check for the
-		 * currently negotiated listen interval to prevent losing
-		 * frames unnecessarily.
-		 *
-		 * Otherwise switch back to the operating channel.
-		 */
-
-		bad_latency = time_after(jiffies +
-				ieee80211_scan_get_channel_time(next_chan),
-				local->leave_oper_channel_time +
-				usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
-
-		listen_int_exceeded = time_after(jiffies +
-				ieee80211_scan_get_channel_time(next_chan),
-				local->leave_oper_channel_time +
-				usecs_to_jiffies(min_beacon_int * 1024) *
-				local->hw.conf.listen_interval);
-
-		if (associated && ( !tx_empty || bad_latency ||
-		    listen_int_exceeded))
-			local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
-		else
-			local->next_scan_state = SCAN_SET_CHANNEL;
-	}
-
-	*next_delay = 0;
-}
-
-static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
-						    unsigned long *next_delay)
-{
-	/* PS will already be in off-channel mode,
-	 * we do that once at the beginning of scanning.
-	 */
-	ieee80211_offchannel_stop_vifs(local, false);
-
 	/*
-	 * What if the nullfunc frames didn't arrive?
+	 * we're currently scanning a different channel, let's
+	 * see if we can scan another channel without interfering
+	 * with the current traffic situation.
+	 *
+	 * Since we don't know if the AP has pending frames for us
+	 * we can only check for our tx queues and use the current
+	 * pm_qos requirements for rx. Hence, if no tx traffic occurs
+	 * at all we will scan as many channels in a row as the pm_qos
+	 * latency allows us to. Additionally we also check for the
+	 * currently negotiated listen interval to prevent losing
+	 * frames unnecessarily.
+	 *
+	 * Otherwise switch back to the operating channel.
 	 */
-	drv_flush(local, false);
-	if (local->ops->flush)
-		*next_delay = 0;
-	else
-		*next_delay = HZ / 10;
 
-	/* remember when we left the operating channel */
-	local->leave_oper_channel_time = jiffies;
+	bad_latency = time_after(jiffies +
+			ieee80211_scan_get_channel_time(next_chan),
+			local->leave_oper_channel_time +
+			usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
+
+	listen_int_exceeded = time_after(jiffies +
+			ieee80211_scan_get_channel_time(next_chan),
+			local->leave_oper_channel_time +
+			usecs_to_jiffies(min_beacon_int * 1024) *
+			local->hw.conf.listen_interval);
 
-	/* advance to the next channel to be scanned */
-	local->next_scan_state = SCAN_SET_CHANNEL;
-}
-
-static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local,
-						    unsigned long *next_delay)
-{
-	/* switch back to the operating channel */
-	local->scan_channel = NULL;
-	if (!ieee80211_cfg_on_oper_channel(local))
-		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
-
-	/*
-	 * Re-enable vifs and beaconing.  Leave PS
-	 * in off-channel state..will put that back
-	 * on-channel at the end of scanning.
-	 */
-	ieee80211_offchannel_return(local, true, false);
+	if (associated && (!tx_empty || bad_latency || listen_int_exceeded))
+		local->next_scan_state = SCAN_SUSPEND;
+	else
+		local->next_scan_state = SCAN_SET_CHANNEL;
 
-	*next_delay = HZ / 5;
-	local->next_scan_state = SCAN_DECISION;
+	*next_delay = 0;
 }
 
 static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
@@ -612,10 +531,8 @@ static void ieee80211_scan_state_set_cha
 
 	local->scan_channel = chan;
 
-	/* Only call hw-config if we really need to change channels. */
-	if (chan != local->hw.conf.channel)
-		if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
-			skip = 1;
+	if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
+		skip = 1;
 
 	/* advance state machine to next channel/band */
 	local->scan_channel_idx++;
@@ -672,6 +589,44 @@ static void ieee80211_scan_state_send_pr
 	local->next_scan_state = SCAN_DECISION;
 }
 
+static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
+					 unsigned long *next_delay)
+{
+	/* switch back to the operating channel */
+	local->scan_channel = NULL;
+	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+
+	/*
+	 * Re-enable vifs and beaconing.  Leave PS
+	 * in off-channel state..will put that back
+	 * on-channel at the end of scanning.
+	 */
+	ieee80211_offchannel_return(local, true, false);
+
+	*next_delay = HZ / 5;
+	/* afterwards, resume scan & go to next channel */
+	local->next_scan_state = SCAN_RESUME;
+}
+
+static void ieee80211_scan_state_resume(struct ieee80211_local *local,
+					unsigned long *next_delay)
+{
+	/* PS already is in off-channel mode */
+	ieee80211_offchannel_stop_vifs(local, false);
+
+	if (local->ops->flush) {
+		drv_flush(local, false);
+		*next_delay = 0;
+	} else
+		*next_delay = HZ / 10;
+
+	/* remember when we left the operating channel */
+	local->leave_oper_channel_time = jiffies;
+
+	/* advance to the next channel to be scanned */
+	local->next_scan_state = SCAN_DECISION;
+}
+
 void ieee80211_scan_work(struct work_struct *work)
 {
 	struct ieee80211_local *local =
@@ -742,11 +697,11 @@ void ieee80211_scan_work(struct work_str
 		case SCAN_SEND_PROBE:
 			ieee80211_scan_state_send_probe(local, &next_delay);
 			break;
-		case SCAN_LEAVE_OPER_CHANNEL:
-			ieee80211_scan_state_leave_oper_channel(local, &next_delay);
+		case SCAN_SUSPEND:
+			ieee80211_scan_state_suspend(local, &next_delay);
 			break;
-		case SCAN_ENTER_OPER_CHANNEL:
-			ieee80211_scan_state_enter_oper_channel(local, &next_delay);
+		case SCAN_RESUME:
+			ieee80211_scan_state_resume(local, &next_delay);
 			break;
 		}
 	} while (next_delay == 0);
--- a/net/mac80211/ieee80211_i.h	2011-11-08 15:23:19.000000000 +0100
+++ b/net/mac80211/ieee80211_i.h	2011-11-08 15:50:44.000000000 +0100
@@ -722,17 +722,16 @@ enum {
  *	operating channel
  * @SCAN_SET_CHANNEL: Set the next channel to be scanned
  * @SCAN_SEND_PROBE: Send probe requests and wait for probe responses
- * @SCAN_LEAVE_OPER_CHANNEL: Leave the operating channel, notify the AP
- *	about us leaving the channel and stop all associated STA interfaces
- * @SCAN_ENTER_OPER_CHANNEL: Enter the operating channel again, notify the
- *	AP about us being back and restart all associated STA interfaces
+ * @SCAN_SUSPEND: Suspend the scan and go back to operating channel to
+ *	send out data
+ * @SCAN_RESUME: Resume the scan and scan the next channel
  */
 enum mac80211_scan_state {
 	SCAN_DECISION,
 	SCAN_SET_CHANNEL,
 	SCAN_SEND_PROBE,
-	SCAN_LEAVE_OPER_CHANNEL,
-	SCAN_ENTER_OPER_CHANNEL,
+	SCAN_SUSPEND,
+	SCAN_RESUME,
 };
 
 struct ieee80211_local {



^ permalink raw reply

* Re: [PATCH v3 1/2] wl12xx: configure probe-resp template according to notification
From: Eliad Peller @ 2011-11-08 15:13 UTC (permalink / raw)
  To: Arik Nemtsov; +Cc: linux-wireless, Luciano Coelho
In-Reply-To: <1320762970-6860-1-git-send-email-arik@wizery.com>

On Tue, Nov 8, 2011 at 4:36 PM, Arik Nemtsov <arik@wizery.com> wrote:
> 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>
> ---
[...]
> +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;
> +}

add a check for max template size?

Eliad.

^ permalink raw reply

* [PATCH] wl12xx: add chip_family to platform data struct
From: Luciano Coelho @ 2011-11-08 14:43 UTC (permalink / raw)
  To: coelho; +Cc: linux-wireless

To abstract the bus modules from the actual driver that handles the
chip, we can pass the chip_family struct in the platform data.  This
string is used by the bus modules to name the platform device they
create.  The same string is used by the platform driver to get probed.

If not specified, we use "wl12xx" as default for backwards
compatibility.

Signed-off-by: Luciano Coelho <coelho@ti.com>
---
 drivers/net/wireless/wl12xx/sdio.c   |    6 +++++-
 drivers/net/wireless/wl12xx/spi.c    |    6 +++++-
 drivers/net/wireless/wl12xx/wl12xx.h |    2 ++
 include/linux/wl12xx.h               |    3 +++
 4 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 468a505..e266a20 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -226,7 +226,11 @@ static int __devinit wl1271_probe(struct sdio_func *func,
 	/* Tell PM core that we don't need the card to be powered now */
 	pm_runtime_put_noidle(&func->dev);
 
-	glue->core = platform_device_alloc("wl12xx", -1);
+	/* get the chip family from pdata, if not available use default */
+	glue->core = platform_device_alloc(wlan_data->chip_family?
+					   wlan_data->chip_family:
+					   DEFAULT_CHIP_FAMILY,
+					   -1);
 	if (!glue->core) {
 		dev_err(glue->dev, "can't allocate platform_device");
 		ret = -ENOMEM;
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index 9e6f7fa..6a83d9e 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -351,7 +351,11 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 		goto out_free_glue;
 	}
 
-	glue->core = platform_device_alloc("wl12xx", -1);
+	/* get the chip family from pdata, if not available use default */
+	glue->core = platform_device_alloc(wlan_data->chip_family?
+					   wlan_data->chip_family:
+					   DEFAULT_CHIP_FAMILY,
+					   -1);
 	if (!glue->core) {
 		dev_err(glue->dev, "can't allocate platform_device\n");
 		ret = -ENOMEM;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index e58e801..2f35960 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -45,6 +45,8 @@
 #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin"
 #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin"
 
+#define DEFAULT_CHIP_FAMILY "wl12xx"
+
 /*
  * wl127x and wl128x are using the same NVS file name. However, the
  * ini parameters between them are different.  The driver validates
diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h
index 0d63731..adea8f8 100644
--- a/include/linux/wl12xx.h
+++ b/include/linux/wl12xx.h
@@ -53,6 +53,9 @@ struct wl12xx_platform_data {
 	bool use_eeprom;
 	int board_ref_clock;
 	int board_tcxo_clock;
+	const char *chip_family;
+
+	/* internal use */
 	unsigned long platform_quirks;
 	bool pwr_in_suspend;
 
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH v3 2/2] wl12xx: indicate probe-resp offloading support
From: Arik Nemtsov @ 2011-11-08 14:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: Luciano Coelho, Arik Nemtsov
In-Reply-To: <1320762970-6860-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>
---
 drivers/net/wireless/wl12xx/main.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 3750a6e..6c5f40b 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -5017,6 +5017,12 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
 
 	wl->hw->wiphy->reg_notifier = wl1271_reg_notify;
 
+	wl->hw->wiphy->flags |= WIPHY_FLAG_SUPPORT_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 v3 1/2] wl12xx: configure probe-resp template according to notification
From: Arik Nemtsov @ 2011-11-08 14:36 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>
---
v1->3:
re-factor the code a bit and turn the PROBE_RESP_SET flag into a per-vif
flag.

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 v3 3/3] mac80211: Save probe response data for bss
From: Arik Nemtsov @ 2011-11-08 14:35 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg, Arik Nemtsov
In-Reply-To: <1320762928-6782-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>
---
v1->3:
save the probe response in mac80211 when configuring the new beacon,
not part of a BSS change.

include/net/mac80211.h     |   15 +++++++++++++++
 net/mac80211/cfg.c         |   44 +++++++++++++++++++++++++++++++++++++++++---
 net/mac80211/ieee80211_i.h |    1 +
 net/mac80211/iface.c       |    6 +++++-
 net/mac80211/tx.c          |   31 +++++++++++++++++++++++++++++++
 net/mac80211/util.c        |    3 ++-
 6 files changed, 95 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..a06e695 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -488,6 +488,37 @@ 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_len == 0)
+		return -EINVAL;
+
+	old = sdata->u.ap.probe_resp;
+
+	if (!resp || !resp_len)
+		return -EINVAL;
+
+	new = dev_alloc_skb(resp_len);
+	if (!new) {
+		printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
+		       "response template\n", sdata->name);
+		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 +529,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 +613,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 v3 2/3] nl80211: Pass probe response data to drivers
From: Arik Nemtsov @ 2011-11-08 14:35 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg, Arik Nemtsov
In-Reply-To: <1320762928-6782-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>
---
v1->3:
Set the probe response data as part of the addset_beacon function, instead
of set_bss. This makes more sense since the probe response is always
updated with the beacon.

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

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e74afc4..3fa03b3 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1114,6 +1114,8 @@ enum nl80211_commands {
  *	In addition this attribute holds a bitmap of the supported protocols
  *	for offloading using &enum nl80211_probe_resp_offload_support_attr.
  *
+ * @NL80211_ATTR_PROBE_RESP: Probe Response template data
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1344,6 +1346,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 7939495..97f3e85 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 9800f8d..10d5b1f 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 v3 1/3] nl80211: Add probe response offload attribute
From: Arik Nemtsov @ 2011-11-08 14:35 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>
---
v1->3:
changed wording and added 80211u bit for supported offload protocols

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

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 8049bf7..e74afc4 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_SUPPORT: Indicates support for probe
+ *	response offloading by the driver/firmware.
+ *	In addition this attribute holds a bitmap of the supported protocols
+ *	for offloading using &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 - definition of optional
+ *	supported protocols for probe response offloading by the driver/FW.
+ *	to be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD_SUPPORT
+ *	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..7939495 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1693,6 +1693,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_SUPPORT_PROBE_RESP_OFFLOAD	= BIT(17),
 };
 
 /**
@@ -1956,6 +1957,10 @@ 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 */
+	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..9800f8d 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_SUPPORT_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] ath6kl: Fix packet drop when ath6kl_cookie runs out
From: Vasanthakumar Thiagarajan @ 2011-11-08 14:31 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

"ath6kl: Maintain virtual interface in a list" mistakenly stops the
netq only when the mode is ibss. This causes packet drops in sta mode
when the available cookies (buffer abstraction in ath6kl and also used
for tx throttling) runs out for the highest priority traffic. This patch
just fixes this regression though the original code may still need fixes
which can be addressed in separate patches.

Reported-by: Kalle Valo <kvalo@qca.qualcomm.com>
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/txrx.c |   12 +++++-------
 1 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index 62beadb..0b45d45 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -453,11 +453,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
 		set_bit(WMI_CTRL_EP_FULL, &ar->flag);
 		spin_unlock_bh(&ar->lock);
 		ath6kl_err("wmi ctrl ep is full\n");
-		goto stop_adhoc_netq;
+		return action;
 	}
 
 	if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG)
-		goto stop_adhoc_netq;
+		return action;
 
 	/*
 	 * The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for
@@ -465,20 +465,18 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
 	 */
 	if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] <
 	    ar->hiac_stream_active_pri &&
-	    ar->cookie_count <= MAX_HI_COOKIE_NUM) {
+	    ar->cookie_count <= MAX_HI_COOKIE_NUM)
 		/*
 		 * Give preference to the highest priority stream by
 		 * dropping the packets which overflowed.
 		 */
 		action = HTC_SEND_FULL_DROP;
-		goto stop_adhoc_netq;
-	}
 
-stop_adhoc_netq:
 	/* FIXME: Locking */
 	spin_lock_bh(&ar->list_lock);
 	list_for_each_entry(vif, &ar->vif_list, list) {
-		if (vif->nw_type == ADHOC_NETWORK) {
+		if (vif->nw_type == ADHOC_NETWORK ||
+		    action != HTC_SEND_FULL_DROP) {
 			spin_unlock_bh(&ar->list_lock);
 
 			spin_lock_bh(&vif->if_lock);
-- 
1.7.0.4


^ 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