* Re: vendor IEs?
From: Henry Ptasinski @ 2010-12-21 18:33 UTC (permalink / raw)
To: Johannes Berg; +Cc: Daniel Halperin, linux-wireless@vger.kernel.org
In-Reply-To: <1292928100.3563.3.camel@jlt3.sipsolutions.net>
On 12/21/2010 02:41 AM, Johannes Berg wrote:
> On Sun, 2010-12-19 at 16:53 -0800, Daniel Halperin wrote:
>> Is there a compiled list of vendor-specific IEs out there? Googling
>> didn't offer much help.
>
> I'm not aware of any list, nor can there really be one since everybody
> who has an OUI is free to define their own IEs.
>
> That said, some of them are of course mostly standardised, like the WFA
> ones for WPA, WSC/WPS and P2P for instance. I don't think there's a even
> a comprehensive list of WFA ones though other than in what you get by
> combining all those standards.
The most complete info I've seen is in the wireshark dissector, but even
that is not very complete.
- Henry
^ permalink raw reply
* rtlwifi/rtl8192ce: Logs spammed with cfg80211 calls
From: Larry Finger @ 2010-12-21 17:48 UTC (permalink / raw)
To: wireless
With the new drivers rtlwifi/rtl8192ce, I'm getting my logs spammed with the
following:
wlan10: authenticate with c0:3f:0e:be:2b:45 (try 1)
wlan10: authenticated
wlan10: associate with c0:3f:0e:be:2b:45 (try 1)
wlan10: RX AssocResp from c0:3f:0e:be:2b:45 (capab=0x411 status=0 aid=2)
wlan10: associated
cfg80211: Calling CRDA to update world regulatory domain
cfg80211: World regulatory domain updated:
cfg80211: (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
cfg80211: (2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
cfg80211: (2457000 KHz - 2482000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
cfg80211: (2474000 KHz - 2494000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
cfg80211: (5170000 KHz - 5250000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
cfg80211: (5735000 KHz - 5835000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
wlan10: authenticate with c0:3f:0e:be:2b:45 (try 1)
wlan10: authenticated
I see no indication of deauthentication by the AP. What might the driver be
doing to cause cfg80211 to call CRDA over and over?
Thanks,
Larry
^ permalink raw reply
* Re: [PATCH] iwlagn: fix scan tx antenna setting on 5Ghz band
From: Guy, Wey-Yi @ 2010-12-21 17:21 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: Intel Linux Wireless, Johannes Berg,
linux-wireless@vger.kernel.org
In-Reply-To: <20101221120511.GA2287@redhat.com>
Hi Stanislaw,
On Tue, 2010-12-21 at 04:05 -0800, Stanislaw Gruszka wrote:
> Hi Wey
>
> On Mon, Dec 20, 2010 at 10:13:36AM -0800, Guy, Wey-Yi wrote:
> > On Mon, 2010-12-20 at 09:05 -0800, Stanislaw Gruszka wrote:
> > > Looks that we do not set correctly antennas when scanning
> > > on 5Ghz band and when bluetooth is enabled, because
> > > priv->cfg->scan_tx_antennas[band] is only defined for
> > > IEEE80211_BAND_2GHZ. This fix choose first valid antenna.
> > >
> > > Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> > > ---
> > > drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 3 +--
> > > 1 files changed, 1 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
> > > index 4bc82fc..099039c 100644
> > > --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
> > > +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
> > > @@ -1499,8 +1499,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
> > > priv->cfg->bt_params->advanced_bt_coexist &&
> > > priv->bt_full_concurrent) {
> > > /* operated as 1x1 in full concurrency mode */
> > > - scan_tx_antennas = first_antenna(
> > > - priv->cfg->scan_tx_antennas[band]);
> > > + scan_tx_antennas = first_antenna(scan_tx_antennas);
> >
> > If its is 2.4, we need to use the correct tx antenna, I think we can
> > remove this block of code all together since check already done above.
> >
> > if (priv->cfg->scan_tx_antennas[band])
> > scan_tx_antennas = priv->cfg->scan_tx_antennas[band];
>
> Is correct to use all antennas on 5GHz when blutooth is enabled?
> For me, more logical would be limiting to one antenna no matter of band,
> since antennas are used anyway, only frequencies differ.
>
> For rx_ant, we do not check the band, only limit to first one
> when bluetooth is used.
there is no BT coex if 5GHz is used because there is not interference
between 2.4 and 5GHz, so both antenna can be used. WiFi should operated
in normal condition.
For 2.4GHz, we also can use both antenna if there is not high traffic
load on BT side.
but you have a good catch, driver need to check band before use it
(scan_tx_antenna[band])
Thanks
Wey
^ permalink raw reply
* Re: [PATCH 1/4] DFS: interface for common pattern detector
From: Luis R. Rodriguez @ 2010-12-21 16:32 UTC (permalink / raw)
To: Zefir Kurtisi; +Cc: linux-wireless
In-Reply-To: <1874584253.11108.1292944512342.JavaMail.root@idefix>
On Tue, Dec 21, 2010 at 10:15 AM, Zefir Kurtisi
<zefir.kurtisi@neratec.com> wrote:
>
>
> Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
> ---
> include/net/cfg80211.h | 41 +++++++++
> include/net/dfs.h | 100 +++++++++++++++++++++
> 2 files changed, 141 insertions(+), 0 deletions(-)
> create mode 100644 include/net/dfs.h
>
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index 03b3bae..c3ace0e 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
Why not just keep this on dfs.h?
> @@ -1820,6 +1820,47 @@ struct ieee80211_rate *
> ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
> u32 basic_rates, int bitrate);
>
> +
> +/**
> + * DFS pattern detector interface
> + */
> +
> +/**
> + * ieee80211_add_radar_pulse - add a pulse detected by HW to detector
> + *
> + * @freq: channel frequency in [MHz]
> + * @ts: time stamp in [us]
Is this the best known resolution we are aware hardware can use?
> + * @rssi: rssi value for the deteced pulse
RSSI values are vendor defined values, for Atheros it happens to be in
dBm above the noise floor, and the value is measured during the
preamble and PLCP; i.e. with the initial 4us of detection. If we can
assume other radar pulses from other vendors will match this same
definition then we can share the pulse rssi information, otherwise we
can't.
Ideally I wish we could use instead RCPI but I am not sure if AR9003 /
AR9280 can support a translation of the RSSI value to RCPI, IIRC we
could not, but there was some goals in newer hardware to make this
happen, so maybe AR9003 can.. we'll have to check.
> + * @width: pulse width in [us]
> + *
I suppose us is a reasonable value to use, but do we want a higher
resolution just in case for the future?
> + * Each pulse the HW identified as radar is fed into the detector via this
> + * function. The three values for ts, rssi and width are those relevant for
> + * pattern matching, while freq is required to map the pulse to the correct
> + * DFS channel.
> + * No value is returned, assuming the HW does not need to know about the result
> + * of pattern matching. The further processing of matches is done at mac layer.
> + */
> +extern void ieee80211_add_radar_pulse(u16 freq, u64 ts, u8 rssi, u8 width);
Maybe we should just keep pulses specific to the drivers and only let
them inform us of the actual radar signals determinations. Seems
overkill to share pulse information, or at least pointless if we
cannot sure or have to address a lot to try to share. Unless of course
we can share RCPI based DFS radar pulse recipes.
> +/**
> + * ieee80211_radar_detected - notify mac that DFS radar was detected
> + *
> + * @freq: channel frequency in [MHz]
> + *
> + * This function is used to inform the mac that a DFS radar was detected on
> + * the given channel frequency. It might be called from the DFS pattern
> + * detector or from device drivers that do DFS detection in HW.
> + *
> + * It is meant to be the central hook that initiates all subsequent actions that
> + * need to be performed after the detection, including
> + * - put channel to Unavailable list (or adjust channel state periods
> + * in case channel was already not on Available list)
> + * - everything else required to select new channel and initiate
> + * channel switch
> + */
> +extern void ieee80211_radar_detected(u16 freq);
So drivers and mac80211 would call this right?
> +
> /*
> * Radiotap parsing functions -- for controlled injection support
> *
> diff --git a/include/net/dfs.h b/include/net/dfs.h
> new file mode 100644
> index 0000000..1dccc10
> --- /dev/null
> +++ b/include/net/dfs.h
> @@ -0,0 +1,100 @@
> +#ifndef DFS_H
> +#define DFS_H
> +/*
> + * Copyright 2010, Neratec Solutions AG, <zefir.kurtisi@neratec.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +/**
> + * DOC: Introduction
> + *
> + * DFS radar detector interface
> + *
> + * This is a proposal for a common DFS pattern detector interface.
> + *
> + * It should be used by devices that are able to detect radar pulses and need
> + * pattern matching (as defined by ETSI, FCC, JP regulatories).
> + *
> + * An instance of the proposed DFS handler is supposed to exist during an
> + * endpoint's lifetime within mac80211. WLAN devices should report the radar
> + * pulses they detect during their uptime, the DFS handler aggregates them and
> + * keeps track of channel states (as defined by regulatories).
> + *
> + * On channel state changes it notifies mac80211 to initiate all required
> + * processing.
> + */
> +
> +
> +/* TODO: move those to more common place */
> +enum dfs_domain {
> + DFS_INVALID_DOMAIN = 0, /* Uninitialized dfs domain */
> + DFS_FCC_DOMAIN = 1, /* FCC dfs domain */
> + DFS_ETSI_DOMAIN = 2, /* ETSI dfs domain */
> + DFS_JP_DOMAIN = 3, /* Japan dfs domain */
> +};
You can use the values I posted on my series for this.
> +
> +/* TODO: move dfs_state to more common place */
> +enum channel_dfs_flags {
> + CHANNEL_INVALID = 0x00,
Do we really need INVALID ? Please document each of these.
> + CHANNEL_UNAVAILABLE = 0x01,
> + CHANNEL_USABLE = 0x02,
> + CHANNEL_AVAILABLE = 0x04,
> + CHANNEL_OPERATING = 0x08,
> +};
> +
> +/**
> + * struct pulse_event - events fed to the dfs handler
> + *
> + * @ts: absolute time stamp for start of pulse in us (e.g. as TSF)
> + * @freq: channel frequency in [MHz]
> + * @rssi: rssi value for the given pulse
> + * @width: pulse width for given pulse in [us]
> + *
> + */
> +struct pulse_event {
> + u64 ts;
> + u16 freq;
> + u8 rssi;
> + u8 width;
> +};
Yeah, this seems hardware specific, so likely not something we can
share I think.
> +/**
> + * struct dfs_handler - DFS handler pseudo-OO interface
> + *
> + * @exit: terminate DFS handler and release all resources
> + * @add_pulse: add given pulse event to detector lines
> + * returns 1 if added event triggered a pattern match
> + * @data: private instance data
> + *
> + * To easily attach pulse detectors implementing different types matching
> + * algorithms, a pseudo-OO design approach was taken with a tiny interface is
> + * chosen.
> + */
Not sure I get what this is for.
> +struct dfs_handler {
> + /* VFT */
> + void (*exit)(struct dfs_handler *_this);
> + int (*add_pulse)(struct dfs_handler *_this, struct pulse_event *event);
> +
> + /* private data */
> + struct dfs_data *data;
> +};
> +
> +/**
> + * dfs_handler_init - DFS handler constructor
> + *
> + * @dfs_domain: DFS domain to detect radar patterns for
> + *
> + * A DFS handler instance is allocated via this constructor.
> + * On success the pointer to the fully initialized handler is returned that
> + * can be fed with radar pulses during its lifetime. Allocated resources are
> + * released upon calling the destructor.
> + *
> + * On failure NULL is returned.
> + */
> +struct dfs_handler *dfs_handler_init(enum dfs_domain dfs_domain);
Same here.
Luis
^ permalink raw reply
* [PATCH 2/4 V2] b43: N-PHY: implement radio 2056 init steps
From: Rafał Miłecki @ 2010-12-21 16:13 UTC (permalink / raw)
To: linux-wireless, John W. Linville; +Cc: b43-dev, Rafał Miłecki
In-Reply-To: <1292948026-472-1-git-send-email-zajec5@gmail.com>
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
Changes since RFC: added initialization and inittabs call on PHY side, fixed
e increasing, added check to do not allow reading outside array.
V2: replace mdelay with msleep
Thanks Michael for reviewing.
---
drivers/net/wireless/b43/phy_n.c | 33 +++++++++++++-
drivers/net/wireless/b43/radio_2056.c | 77 +++++++++++++++++++++++++++++++++
drivers/net/wireless/b43/radio_2056.h | 3 +
3 files changed, 111 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index a1aa570..6b91cb3 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -401,16 +401,45 @@ static void b43_radio_init2055(struct b43_wldev *dev)
b43_radio_init2055_post(dev);
}
+static void b43_radio_init2056_pre(struct b43_wldev *dev)
+{
+ b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+ ~B43_NPHY_RFCTL_CMD_CHIP0PU);
+ /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
+ b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+ B43_NPHY_RFCTL_CMD_OEPORFORCE);
+ b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+ ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
+ b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+ B43_NPHY_RFCTL_CMD_CHIP0PU);
+}
+
+static void b43_radio_init2056_post(struct b43_wldev *dev)
+{
+ b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB);
+ b43_radio_set(dev, B2056_SYN_COM_PU, 0x2);
+ b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2);
+ msleep(1);
+ b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2);
+ b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
+ b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1);
+ /*
+ if (nphy->init_por)
+ Call Radio 2056 Recalibrate
+ */
+}
+
/*
* Initialize a Broadcom 2056 N-radio
* http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
*/
static void b43_radio_init2056(struct b43_wldev *dev)
{
- /* TODO */
+ b43_radio_init2056_pre(dev);
+ b2056_upload_inittabs(dev, 0, 0);
+ b43_radio_init2056_post(dev);
}
-
/*
* Upload the N-PHY tables.
* http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c
index 0cdf6a4..1752d52 100644
--- a/drivers/net/wireless/b43/radio_2056.c
+++ b/drivers/net/wireless/b43/radio_2056.c
@@ -24,6 +24,39 @@
#include "radio_2056.h"
#include "phy_common.h"
+struct b2056_inittab_entry {
+ /* Value to write if we use the 5GHz band. */
+ u16 ghz5;
+ /* Value to write if we use the 2.4GHz band. */
+ u16 ghz2;
+ /* Flags */
+ u8 flags;
+};
+#define B2056_INITTAB_ENTRY_OK 0x01
+#define B2056_INITTAB_UPLOAD 0x02
+#define UPLOAD .flags = B2056_INITTAB_ENTRY_OK | B2056_INITTAB_UPLOAD
+#define NOUPLOAD .flags = B2056_INITTAB_ENTRY_OK
+
+struct b2056_inittabs_pts {
+ const struct b2056_inittab_entry *syn;
+ unsigned int syn_length;
+ const struct b2056_inittab_entry *tx;
+ unsigned int tx_length;
+ const struct b2056_inittab_entry *rx;
+ unsigned int rx_length;
+};
+
+#define INITTABSPTS(prefix) \
+ .syn = prefix##_syn, \
+ .syn_length = ARRAY_SIZE(prefix##_syn), \
+ .tx = prefix##_tx, \
+ .tx_length = ARRAY_SIZE(prefix##_tx), \
+ .rx = prefix##_rx, \
+ .rx_length = ARRAY_SIZE(prefix##_rx)
+
+struct b2056_inittabs_pts b2056_inittabs[] = {
+};
+
#define RADIOREGS3(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, \
@@ -6045,6 +6078,50 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev8[] =
},
};
+static void b2056_upload_inittab(struct b43_wldev *dev, bool ghz5,
+ bool ignore_uploadflag, u16 routing,
+ const struct b2056_inittab_entry *e,
+ unsigned int length)
+{
+ unsigned int i;
+ u16 value;
+
+ for (i = 0; i < length; i++, e++) {
+ if (!(e->flags & B2056_INITTAB_ENTRY_OK))
+ continue;
+ if ((e->flags & B2056_INITTAB_UPLOAD) || ignore_uploadflag) {
+ if (ghz5)
+ value = e->ghz5;
+ else
+ value = e->ghz2;
+ b43_radio_write(dev, routing | i, value);
+ }
+ }
+}
+
+void b2056_upload_inittabs(struct b43_wldev *dev,
+ bool ghz5, bool ignore_uploadflag)
+{
+ struct b2056_inittabs_pts *pts;
+
+ if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
+ B43_WARN_ON(1);
+ return;
+ }
+ pts = &b2056_inittabs[dev->phy.rev];
+
+ b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+ B2056_SYN, pts->syn, pts->syn_length);
+ b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+ B2056_TX0, pts->tx, pts->tx_length);
+ b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+ B2056_TX1, pts->tx, pts->tx_length);
+ b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+ B2056_RX0, pts->rx, pts->rx_length);
+ b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+ B2056_RX1, pts->rx, pts->rx_length);
+}
+
/* TODO: add support for rev4+ devices by searching in rev4+ tables */
const struct b43_nphy_channeltab_entry_rev3 *
b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h
index 302600c..d601f6e 100644
--- a/drivers/net/wireless/b43/radio_2056.h
+++ b/drivers/net/wireless/b43/radio_2056.h
@@ -1114,4 +1114,7 @@ struct b43_nphy_channeltab_entry_rev3 {
struct b43_phy_n_sfo_cfg phy_regs;
};
+void b2056_upload_inittabs(struct b43_wldev *dev,
+ bool ghz5, bool ignore_uploadflag);
+
#endif /* B43_RADIO_2056_H_ */
--
1.6.3.3
^ permalink raw reply related
* [PATCH 0/4] DFS: radar pattern detector design proposal
From: Zefir Kurtisi @ 2010-12-21 15:15 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <372568220.11085.1292942671813.JavaMail.root@idefix>
Hi DFS developers,
now that we are starting to think about the design for DFS functionality, this is how we started implementing a common radar pattern detector within mac80211 at our company.
It is a pure proof-of-concept and not meant to be used for other than testing.
More info available at [1].
Cheers
Zefir
[1] http://wireless.kernel.org/en/developers/DFS/DetectorDesignNt
^ permalink raw reply
* [PATCH 2/4] DFS: simple pattern detector
From: Zefir Kurtisi @ 2010-12-21 15:15 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <1644423113.11100.1292944104872.JavaMail.root@idefix>
Provides a very basic pattern detector to test the proposed design.
Implements detection for ETSI 1.5.1 single PRI radar test signals. It is
usable only for off-channel-scans, i.e. does not tolerate false pulses.
Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
---
net/wireless/Makefile | 9 +
net/wireless/core.c | 47 ++
.../net/wireless/dfs/dfs_common.h | 20 +
.../net/wireless/dfs/dfs_debug.c | 16 +
.../net/wireless/dfs/dfs_debug.h | 107 ++++
.../net/wireless/dfs/dfs_debugfs.c | 301 +++++++++++
.../net/wireless/dfs/dfs_debugfs.h | 9 +
.../net/wireless/dfs/dfs_handler.c | 94 ++++
.../net/wireless/dfs/dfs_pattern_detector.c | 559 ++++++++++++++++++++
.../net/wireless/dfs/dfs_pattern_detector.h | 46 ++
.../net/wireless/dfs/dfs_radar_types.h | 47 ++
11 files changed, 1255 insertions(+), 0 deletions(-)
create mode 100644 net/wireless/dfs/dfs_common.h
create mode 100644 net/wireless/dfs/dfs_debug.c
create mode 100644 net/wireless/dfs/dfs_debug.h
create mode 100644 net/wireless/dfs/dfs_debugfs.c
create mode 100644 net/wireless/dfs/dfs_debugfs.h
create mode 100644 net/wireless/dfs/dfs_handler.c
create mode 100644 net/wireless/dfs/dfs_pattern_detector.c
create mode 100644 net/wireless/dfs/dfs_pattern_detector.h
create mode 100644 net/wireless/dfs/dfs_radar_types.h
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 37d70ce..3d6207f 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -10,6 +10,15 @@ cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
+# DFS detector, to be made configurable
+
+cfg80211-y += \
+ dfs/dfs_pattern_detector.o \
+ dfs/dfs_handler.o \
+ dfs/dfs_debug.o \
+ dfs/dfs_debugfs.o
+
+
ccflags-y += -D__CHECK_ENDIAN__
$(obj)/regdb.c: $(src)/db.txt $(src)/genregdb.awk
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 79febd2..25cb99b 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -28,6 +28,14 @@
#include "wext-compat.h"
#include "ethtool.h"
+/*
+ * DFS handler
+ *
+ * for this proof-of-concept let's have a global instance of the handler
+ */
+#include "net/dfs.h"
+static struct dfs_handler *cfg80211_dfs_handler;
+
/* name for sysfs, %d is appended */
#define PHY_NAME "phy"
@@ -886,6 +894,33 @@ static struct pernet_operations cfg80211_pernet_ops = {
};
#endif
+
+
+/**
+ * DFS
+ */
+
+void ieee80211_add_radar_pulse(u16 freq, u64 ts, u8 rssi, u8 width)
+{
+ if (cfg80211_dfs_handler != NULL) {
+ struct pulse_event event;
+ event.width = width;
+ event.ts = ts;
+ event.rssi = rssi;
+ event.freq = freq;
+ cfg80211_dfs_handler->add_pulse(cfg80211_dfs_handler, &event);
+ }
+}
+EXPORT_SYMBOL(ieee80211_add_radar_pulse);
+
+void ieee80211_radar_detected(u16 freq)
+{
+ printk(KERN_INFO "Radar detected at freq=%d\n", freq);
+ /* TODO: whatever needs to be done after radar detection */
+}
+EXPORT_SYMBOL(ieee80211_radar_detected);
+
+
static int __init cfg80211_init(void)
{
int err;
@@ -918,6 +953,14 @@ static int __init cfg80211_init(void)
if (!cfg80211_wq)
goto out_fail_wq;
+ /**
+ * DFS handler initialization
+ *
+ * TODO: set the real domain given by countrycode
+ */
+ cfg80211_dfs_handler = dfs_handler_init(DFS_ETSI_DOMAIN);
+
+
return 0;
out_fail_wq:
@@ -939,6 +982,10 @@ subsys_initcall(cfg80211_init);
static void __exit cfg80211_exit(void)
{
+ /* release DFS handler */
+ if (cfg80211_dfs_handler != NULL)
+ cfg80211_dfs_handler->exit(cfg80211_dfs_handler);
+
debugfs_remove(ieee80211_debugfs_dir);
nl80211_exit();
unregister_netdevice_notifier(&cfg80211_netdev_notifier);
diff --git a/net/wireless/dfs/dfs_common.h b/net/wireless/dfs/dfs_common.h
new file mode 100644
index 0000000..9b71efd
--- /dev/null
+++ b/net/wireless/dfs/dfs_common.h
@@ -0,0 +1,20 @@
+#ifndef DFS_COMMON_H
+#define DFS_COMMON_H
+
+#include "net/dfs.h"
+
+
+/**
+ * struct dfs_data - DFS handler private data
+ *
+ * @dfs_handler: instance back-reference
+ * @dfs_domain: DFS domain the handler is currently working
+ * @pattern_detector: instance reference to pattern detector
+ */
+struct dfs_data {
+ struct dfs_handler *dfs_handler;
+ enum dfs_domain dfs_domain;
+ struct dfs_pattern_detector *pattern_detector;
+};
+
+#endif /* DFS_COMMON_H */
diff --git a/net/wireless/dfs/dfs_debug.c b/net/wireless/dfs/dfs_debug.c
new file mode 100644
index 0000000..ba756de
--- /dev/null
+++ b/net/wireless/dfs/dfs_debug.c
@@ -0,0 +1,16 @@
+#include "dfs_debug.h"
+
+#define USE_FULL_DEBUG 0
+
+u32 dfs_debug_level = 0
+ | DFS_DEBUG_ERROR
+ | DFS_DEBUG_WARN
+ | DFS_DEBUG_INFO
+#if USE_FULL_DEBUG
+ | DFS_DEBUG_TRACE
+ | DFS_DEBUG_LOG
+#endif
+;
+
+char dbg_buff[MAX_DEBUG_SPRINTF + 1] = {0};
+
diff --git a/net/wireless/dfs/dfs_debug.h b/net/wireless/dfs/dfs_debug.h
new file mode 100644
index 0000000..eda2735
--- /dev/null
+++ b/net/wireless/dfs/dfs_debug.h
@@ -0,0 +1,107 @@
+#ifndef DFS_DEBUG_H
+#define DFS_DEBUG_H
+
+enum {
+ DFS_DEBUG_ERROR = 0x000100,
+ DFS_DEBUG_WARN = 0x000200,
+ DFS_DEBUG_INFO = 0x000400,
+ DFS_DEBUG_TRACE = 0x000800,
+ DFS_DEBUG_LOG = 0x001000,
+};
+
+extern u32 dfs_debug_level;
+#define MAX_DEBUG_SPRINTF 511
+extern char dbg_buff[MAX_DEBUG_SPRINTF + 1];
+
+#define __SHORT_FILE__ \
+ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+
+#define DFS_DPRINTK(LEVEL, FMT, ...) \
+do { \
+ if ((LEVEL) & dfs_debug_level) \
+ printk(FMT, ##__VA_ARGS__); \
+} while (0)
+
+#define ASSERT(expr) \
+if (unlikely(!(expr))) { \
+ panic(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
+ #expr, __SHORT_FILE__, __func__, __LINE__); \
+}
+
+#else
+#include <stdio.h>
+
+#define DFS_DPRINTK(LEVEL, FMT, ...) \
+do { \
+ if ((LEVEL) & dfs_debug_level) \
+ printf(FMT, ##__VA_ARGS__); \
+} while (0)
+
+#define ASSERT(expr) \
+do { \
+ if (!(expr)) { \
+ printf("Assertion failed! %s,%s,%s,line=%d\n", \
+ #expr, __SHORT_FILE__, __func__, __LINE__); \
+ } \
+} while (0)
+
+#endif
+
+#define DTRACE(...) \
+do { \
+ DFS_DPRINTK(DFS_DEBUG_TRACE, "TRACE: %s\n", __func__); \
+} while (0)
+
+#define DLOG(FMT, ...) \
+do { \
+ snprintf(dbg_buff, MAX_DEBUG_SPRINTF, "LOG: %s\n", FMT); \
+ DFS_DPRINTK(DFS_DEBUG_LOG, dbg_buff, ##__VA_ARGS__); \
+} while (0)
+
+#define DINFO(FMT, ...) \
+do { \
+ snprintf(dbg_buff, MAX_DEBUG_SPRINTF, "INFO: %s\n", FMT); \
+ DFS_DPRINTK(DFS_DEBUG_INFO, dbg_buff, ##__VA_ARGS__); \
+} while (0)
+
+#define DWARN(FMT, ...) \
+do { \
+ snprintf(dbg_buff, MAX_DEBUG_SPRINTF, \
+ "WARN: %s: %s\n", __func__, FMT); \
+ DFS_DPRINTK(DFS_DEBUG_WARN, dbg_buff, ##__VA_ARGS__); \
+} while (0)
+
+#define DERROR(FMT, ...) \
+do { \
+ snprintf(dbg_buff, MAX_DEBUG_SPRINTF, \
+ "WARN: %s: %s\n", __func__, FMT); \
+ DFS_DPRINTK(DFS_DEBUG_ERROR, dbg_buff, ##__VA_ARGS__); \
+} while (0)
+
+#define DFATAL(FMT, ...) \
+do { \
+ snprintf(dbg_buff, MAX_DEBUG_SPRINTF, \
+ "FATAL: %s: %s\n", __func__, FMT); \
+ DFS_DPRINTK(DFS_DEBUG_ERROR, dbg_buff, ##__VA_ARGS__); \
+} while (0)
+
+
+#define DINIT(FMT, ...) \
+do { \
+ snprintf(dbg_buff, MAX_DEBUG_SPRINTF, \
+ "INIT: %s: %s\n", __func__, FMT); \
+ DFS_DPRINTK(DFS_DEBUG_ERROR, dbg_buff, ##__VA_ARGS__); \
+} while (0)
+
+#define DINFO_OK(FMT, ...) \
+do { \
+ snprintf(dbg_buff, MAX_DEBUG_SPRINTF, "OK: %s: %s\n", __func__, FMT); \
+ DFS_DPRINTK(DFS_DEBUG_INFO, dbg_buff, ##__VA_ARGS__); \
+} while (0)
+
+
+#endif /* DFS_DEBUG_H */
diff --git a/net/wireless/dfs/dfs_debugfs.c b/net/wireless/dfs/dfs_debugfs.c
new file mode 100644
index 0000000..2610bdb
--- /dev/null
+++ b/net/wireless/dfs/dfs_debugfs.c
@@ -0,0 +1,301 @@
+#include "dfs_common.h"
+
+
+#if defined(__KERNEL__)
+
+#include <linux/debugfs.h>
+
+#include "net/dfs.h"
+#include "net/cfg80211.h"
+#include "dfs_debugfs.h"
+#include "dfs_debug.h"
+
+static int dfs_debugfs_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+
+/* generic */
+static ssize_t read_dfs_generic(char __user *user_buf, size_t count,
+ loff_t *ppos, const char *fmt, int val)
+{
+ char buf[32];
+ unsigned int len;
+
+ sprintf(buf, fmt, val);
+ strcat(buf, "\n");
+ len = strlen(buf);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_dfs_generic(const char __user *user_buf, size_t count,
+ unsigned int *val)
+{
+ char buf[32];
+ ssize_t len;
+
+ unsigned long my_val;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ if (strict_strtoul(buf, 0, &my_val))
+ return -EINVAL;
+ *val = my_val;
+ return count;
+}
+
+
+/********* debug_level */
+static ssize_t read_dfs_debug_level(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return read_dfs_generic(user_buf, count, ppos, "0x%.8x",
+ dfs_debug_level);
+}
+
+static ssize_t write_dfs_debug_level(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ return write_dfs_generic(user_buf, count, &dfs_debug_level);
+}
+
+static const struct file_operations fops_dfs_debug_level = {
+ .read = read_dfs_debug_level,
+ .write = write_dfs_debug_level,
+ .open = dfs_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+
+/********* radar */
+
+#include <linux/ktime.h>
+
+#define R1_WIDTH 1
+#define R1_PPS 700
+#define R1_PPB 18
+#define R1_RSSI 30
+#define R1_FREQ 5500
+
+static int radar_pps = R1_PPS;
+static int radar_ppb = R1_PPB;
+static int radar_width = R1_WIDTH;
+static int radar_rssi = R1_RSSI;
+static int radar_freq = R1_FREQ;
+
+
+/********* radar_width */
+static ssize_t read_dfs_radar_width(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return read_dfs_generic(user_buf, count, ppos, "%d", radar_width);
+}
+
+static ssize_t write_dfs_radar_width(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ return write_dfs_generic(user_buf, count, &radar_width);
+}
+
+static const struct file_operations fops_dfs_radar_width = {
+ .read = read_dfs_radar_width,
+ .write = write_dfs_radar_width,
+ .open = dfs_debugfs_open,
+ .owner = THIS_MODULE
+};
+
+
+/********* radar_prf */
+static ssize_t read_dfs_radar_pps(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return read_dfs_generic(user_buf, count, ppos, "%d", radar_pps);
+}
+
+static ssize_t write_dfs_radar_pps(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ return write_dfs_generic(user_buf, count, &radar_pps);
+}
+
+static const struct file_operations fops_dfs_radar_pps = {
+ .read = read_dfs_radar_pps,
+ .write = write_dfs_radar_pps,
+ .open = dfs_debugfs_open,
+ .owner = THIS_MODULE
+};
+
+/********* radar_ppb */
+static ssize_t read_dfs_radar_ppb(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return read_dfs_generic(user_buf, count, ppos, "%d", radar_ppb);
+}
+
+static ssize_t write_dfs_radar_ppb(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ return write_dfs_generic(user_buf, count, &radar_ppb);
+}
+
+static const struct file_operations fops_dfs_radar_ppb = {
+ .read = read_dfs_radar_ppb,
+ .write = write_dfs_radar_ppb,
+ .open = dfs_debugfs_open,
+ .owner = THIS_MODULE
+};
+
+
+/********* radar_rssi */
+static ssize_t read_dfs_radar_rssi(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return read_dfs_generic(user_buf, count, ppos, "%d", radar_rssi);
+}
+
+static ssize_t write_dfs_radar_rssi(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ return write_dfs_generic(user_buf, count, &radar_rssi);
+}
+
+static const struct file_operations fops_dfs_radar_rssi = {
+ .read = read_dfs_radar_rssi,
+ .write = write_dfs_radar_rssi,
+ .open = dfs_debugfs_open,
+ .owner = THIS_MODULE
+};
+
+
+/********* radar_freq */
+static ssize_t read_dfs_radar_freq(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return read_dfs_generic(user_buf, count, ppos, "%d", radar_freq);
+}
+
+static ssize_t write_dfs_radar_freq(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ return write_dfs_generic(user_buf, count, &radar_rssi);
+}
+
+static const struct file_operations fops_dfs_radar_freq = {
+ .read = read_dfs_radar_freq,
+ .write = write_dfs_radar_freq,
+ .open = dfs_debugfs_open,
+ .owner = THIS_MODULE
+};
+
+
+static void generate_radar(void)
+{
+ int i;
+ s64 tsf_sim = ktime_to_us(ktime_get_real());
+ u32 deltaUs = USEC_PER_SEC / radar_pps;
+
+ DTRACE();
+
+ for (i = 0; i < radar_ppb; i++) {
+ ieee80211_add_radar_pulse(radar_freq, tsf_sim,
+ radar_rssi, radar_width);
+ tsf_sim += deltaUs;
+ }
+}
+
+
+static ssize_t write_dfs_generate_radar(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ unsigned long val;
+ char buf[32];
+ ssize_t len;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ if (strict_strtoul(buf, 0, &val))
+ return -EINVAL;
+
+ if (val == 1)
+ generate_radar();
+
+ return count;
+}
+
+static const struct file_operations fops_dfs_generate_radar = {
+ .read = NULL,
+ .write = write_dfs_generate_radar,
+ .open = dfs_debugfs_open,
+ .owner = THIS_MODULE
+};
+
+
+
+static struct dentry *dfs_debugfs_root;
+
+void dfs_debugfs_exit(struct dfs_data *dfs_data)
+{
+ ASSERT(dfs_data != NULL);
+ debugfs_remove_recursive(dfs_debugfs_root);
+ debugfs_remove(dfs_debugfs_root);
+ dfs_debugfs_root = NULL;
+}
+
+int dfs_debugfs_init(struct dfs_data *dfs_data)
+{
+ if (dfs_debugfs_root) {
+ printk(KERN_INFO
+ "dfs_init_debug(): debugfs-root already set\n");
+ dfs_debugfs_exit(dfs_data);
+ }
+
+ dfs_debugfs_root = debugfs_create_dir("dfs", NULL);
+ if (!dfs_debugfs_root)
+ return -ENOENT;
+
+ if (!debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
+ dfs_debugfs_root, dfs_data, &fops_dfs_debug_level))
+ goto failed0;
+ if (!debugfs_create_file("generate_radar", S_IWUSR, dfs_debugfs_root,
+ dfs_data, &fops_dfs_generate_radar))
+ goto failed0;
+ if (!debugfs_create_file("radar_width", S_IWUSR, dfs_debugfs_root,
+ dfs_data, &fops_dfs_radar_width))
+ goto failed0;
+ if (!debugfs_create_file("radar_pps", S_IWUSR, dfs_debugfs_root,
+ dfs_data, &fops_dfs_radar_pps))
+ goto failed0;
+ if (!debugfs_create_file("radar_ppb", S_IWUSR, dfs_debugfs_root,
+ dfs_data, &fops_dfs_radar_ppb))
+ goto failed0;
+ if (!debugfs_create_file("radar_rssi", S_IWUSR, dfs_debugfs_root,
+ dfs_data, &fops_dfs_radar_rssi))
+ goto failed0;
+ if (!debugfs_create_file("radar_freq", S_IWUSR, dfs_debugfs_root,
+ dfs_data, &fops_dfs_radar_freq))
+ goto failed0;
+ return 0;
+
+failed0:
+ dfs_debugfs_exit(dfs_data);
+ return -ENOMEM;
+}
+
+#else
+void dfs_debugfs_exit(struct dfs_data *dfs_data) {}
+
+int dfs_debugfs_init(struct dfs_data *dfs_data)
+{
+ return 0;
+}
+
+#endif
+
diff --git a/net/wireless/dfs/dfs_debugfs.h b/net/wireless/dfs/dfs_debugfs.h
new file mode 100644
index 0000000..718d9ea
--- /dev/null
+++ b/net/wireless/dfs/dfs_debugfs.h
@@ -0,0 +1,9 @@
+#ifndef DFS_DEBUGFS_H
+#define DFS_DEBUGFS_H
+
+struct dfs_data;
+
+int dfs_debugfs_init(struct dfs_data *dfs_data);
+void dfs_debugfs_exit(struct dfs_data *dfs_data);
+
+#endif /* DFS_DEBUGFS_H */
diff --git a/net/wireless/dfs/dfs_handler.c b/net/wireless/dfs/dfs_handler.c
new file mode 100644
index 0000000..7e65852
--- /dev/null
+++ b/net/wireless/dfs/dfs_handler.c
@@ -0,0 +1,94 @@
+#include "net/dfs.h"
+#include "net/cfg80211.h"
+#include "dfs_common.h"
+#include "dfs_debug.h"
+#include "dfs_debugfs.h"
+#include "dfs_pattern_detector.h"
+
+
+/* Destructor */
+static void dh_exit(struct dfs_handler *_this)
+{
+ ASSERT(_this != NULL);
+
+ if (_this->data != NULL) {
+ struct dfs_data *dfs_data = _this->data;
+ dfs_debugfs_exit(dfs_data);
+ if (dfs_data->pattern_detector != NULL)
+ dfs_data->pattern_detector->
+ exit(dfs_data->pattern_detector);
+ kfree(dfs_data);
+ _this->data = NULL;
+ }
+ kfree(_this);
+}
+
+static int dh_add_pulse(struct dfs_handler *_this, struct pulse_event *event)
+{
+ int detector_result;
+ struct dfs_data *dfs_data;
+ DTRACE();
+ ASSERT((_this != NULL) && (_this->data != NULL));
+
+ dfs_data = _this->data;
+ detector_result = dfs_data->pattern_detector->
+ add_pulse(dfs_data->pattern_detector, event);
+ if (detector_result == RADAR_DETECTED) {
+ /* DINIT("found radar type %d", radar_type); */
+ ieee80211_radar_detected(event->freq);
+ return 1;
+ }
+ return 0;
+}
+
+static struct dfs_handler default_dfs_handler = {
+ .exit = dh_exit,
+ .add_pulse = dh_add_pulse,
+};
+
+/* Constructor */
+struct dfs_handler *dfs_handler_init(enum dfs_domain dfs_domain)
+{
+ struct dfs_handler *_this;
+ struct dfs_data *dfs_data;
+ int sz = sizeof(struct dfs_handler);
+ _this = kmalloc(sz, GFP_KERNEL);
+
+ if (_this == NULL) {
+ DFATAL("dfs_handler allocation failed");
+ return NULL;
+ }
+
+ *_this = default_dfs_handler;
+
+
+ sz = sizeof(struct dfs_data);
+ dfs_data = kmalloc(sz, GFP_KERNEL);
+ if (dfs_data == NULL) {
+ DFATAL("dfs_data allocation failed");
+ goto failed;
+ }
+
+ memset(dfs_data, 0, sz);
+
+ _this->data = dfs_data;
+ dfs_data->pattern_detector = dfs_pattern_detector_init(dfs_domain);
+ if (dfs_data->pattern_detector == NULL) {
+ DFATAL("detector_init() failed!");
+ goto failed;
+ }
+ _this->data->dfs_domain = dfs_domain;
+ _this->data->dfs_handler = _this;
+
+ /* XXX: debug_fs considered as non-critical on failure */
+ dfs_debugfs_init(_this->data);
+ DINIT("ok");
+ return _this;
+
+failed:
+ _this->exit(_this);
+ return NULL;
+}
+EXPORT_SYMBOL(dfs_handler_init);
+
+
diff --git a/net/wireless/dfs/dfs_pattern_detector.c b/net/wireless/dfs/dfs_pattern_detector.c
new file mode 100644
index 0000000..17ab7d6
--- /dev/null
+++ b/net/wireless/dfs/dfs_pattern_detector.c
@@ -0,0 +1,559 @@
+#include "dfs_pattern_detector.h"
+#include "dfs_debug.h"
+#include "net/dfs.h"
+
+#include "dfs_radar_types.h"
+
+/*
+ * Abbreviations used (based on regulatory specs):
+ * * prf: pulse repetition frequency [Hz]
+ * * pri: pulse repetition interval = 1/prf, here used as [us]
+ * * ppb: pulses per burst
+ */
+
+
+#define DELTA(X, Y) ((X < Y) ? (Y-X) : (X-Y))
+
+/* number of deviation of radar time in usecs tolerated on both sides
+ * TODO: this might need to be HW-dependent
+ */
+#define MAX_PRI_TOLERANCE 10
+
+
+/**
+ * struct radar_specs - specifies a radar pattern type
+ *
+ * @type_id: pattern type, as defined by ETSI / FCC
+ * @width_min: minimum radar pulse width in [us]
+ * @width_max: maximum radar pulse width in [us]
+ * @pri_min: minimum pulse repetition interval in [us] (including tolerance)
+ * @pri_max: minimum pri in [us] (including tolerance)
+ * @num_pri: maximum number of different pri for this type
+ * @ppb: pulses per bursts for this type
+ * @ppb_thresh: number of pulses required to trigger detection
+ * @max_dur: absolute max duration of pattern: num_pri * pri_max * ppb
+ *
+ * Characteristics of each radar pattern type are calculated at initialization
+ * based on radar test signal types defined by the chosen regulatory.
+ * They remain unchanged thereafter.
+ */
+struct radar_specs {
+ unsigned int type_id;
+ unsigned int width_min;
+ unsigned int width_max;
+ unsigned int pri_min;
+ unsigned int pri_max;
+ unsigned int num_pri;
+ unsigned int ppb;
+ unsigned int ppb_thresh;
+ unsigned int max_dur;
+};
+
+
+/* so far, maximum prf number is 3 for ETSI types 5 and 6 */
+#define MAX_PRF_NUM 3
+
+/**
+ * struct radar_stats - detector statistics updated on each pulse
+ *
+ * @pri_count: number of pri used for this pattern type so far
+ * @pri: array of pris in use
+ * @matching_pulse_count: number of pulses detected correctly so far
+ * @missed_pulse_count: number of pulses assumed as lost so far
+ * @false_pulse_count: number of invalid / false pulses so far
+ * @first_ts: timestamp of first valid pulse for this type
+ * @last_ts: timestamp of last valid pulse for this type
+ *
+ * The statistics reflect the current state of the related detector line.
+ *
+ * Detection is performed in place updating the affected detector lines
+ * whenever a pulse is added. The algorithm operates without keeping track
+ * of the pulse history but requires only the statistics collected so far.
+ *
+ * Statistical decisions are made based on the numbers for matching,
+ * missed, and false pulses count.
+ */
+struct radar_stats {
+ u32 pri_count;
+ u32 pri[MAX_PRF_NUM];
+ u32 matching_pulse_count;
+ u32 missed_pulse_count;
+ u32 false_pulse_count;
+ u64 first_ts;
+ u64 last_ts;
+};
+
+/**
+ * struct dfs_channels - DFS channels' frequencies, assumed constant
+ */
+static const u16 dfs_channels[] =
+{
+ 5260, 5280, 5300, 5320,
+ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700,
+};
+#define NUM_DFS_CHANNELS (sizeof(dfs_channels)/sizeof(dfs_channels[0]))
+
+
+/**
+ * struct detector_line - detector line for one specific dfs pattern type
+ *
+ * @specs: dfs pattern type specification
+ * @stats: array of statistics for for all DFS channels
+ *
+ * Each detector line consists of a constant radar type specification and
+ * an array of statistics for all DFS channels.
+ */
+struct detector_line {
+ struct radar_specs specs;
+ struct radar_stats stats[NUM_DFS_CHANNELS];
+};
+
+
+/**
+ * struct pattern_detector_data - private instance data
+ *
+ * @num_detector_elements: number of different radar types
+ * @radar_detectors: array of num_detector_elements detector lines
+ * @min_valid_width: combined min of valid pulse widths
+ * @max_valid_width: combined max of valid pulse widths
+ * @min_valid_pri: combined min of valid pris
+ * @max_valid_pri: combined max of valid pris
+ * @max_radar_dur: combined max duration of radar patterns
+ * @first_pulse_ts: timestamp of first pulse after detector reset
+ * @last_pulse_ts: timestamp of last valid pulse
+ * @last_pulse_rssi: rssi of last pulse
+ *
+ * For global range checking dfs_pattern_detector instances are initialized
+ * with a pre-calculated set of global limits that combine the limits of
+ * all detector lines.
+ */
+struct pattern_detector_data {
+ u32 num_detector_elements;
+ struct detector_line *radar_detectors;
+ u32 min_valid_width;
+ u32 max_valid_width;
+ u32 min_valid_pri;
+ u32 max_valid_pri;
+ u32 max_radar_dur;
+ u64 first_pulse_ts;
+ u64 last_pulse_ts;
+ u32 last_pulse_rssi;
+};
+
+/**
+ * get_dfs_channel_idx - (private) find DFS channel index for given frequency
+ *
+ * @freq: frequency to search for
+ *
+ * Returns -1 if not found.
+ */
+static int get_dfs_channel_idx(u16 freq)
+{
+ int i;
+ for (i = 0; i < NUM_DFS_CHANNELS; i++)
+ if (dfs_channels[i] == freq)
+ return i;
+ return -1;
+}
+
+/**
+ * reset_detector_element - (private) reset one detector element
+ *
+ * @rs: radar statistics to reset
+ * @ts: time stamp to be reset to
+ *
+ * Resets the statistics for one pattern type of one channel. Sets the
+ * timestamp for the last valid pulse to given value.
+ */
+static void reset_detector_element(struct radar_stats *rs, u64 ts)
+{
+ memset(rs, 0, sizeof(struct radar_stats));
+ rs->last_ts = ts;
+}
+
+
+/**
+ * detector_reset - (private) reset all detector lines for a given channel
+ *
+ * @pd_data: instance data ptr
+ * @dfs_channel_idx: DFS channel index to be reset
+ *
+ * Resets the statistics for all pattern types of one given channel.
+ */
+static void detector_reset(struct pattern_detector_data *pd_data,
+ int dfs_channel_idx)
+{
+ int i;
+ u64 ts = pd_data->last_pulse_ts;
+ DTRACE();
+ for (i = 0; i < pd_data->num_detector_elements; i++) {
+ struct radar_stats *rs;
+ rs = &pd_data->radar_detectors[i].stats[dfs_channel_idx];
+ reset_detector_element(rs, ts);
+ }
+}
+
+
+/**
+ * check_pulse_lost - (private) check potentially lost pulses
+ *
+ * @rs: radar stats to be checked
+ * @delta_ts: pulse interval to be checked
+ *
+ * In case we missed some pulse '.' in a row of valid pulses '|', we try to
+ * reconstruct them by checking for delta_ts being a multiple of the pri.
+ *
+ * Assume we were fed with a pattern like
+ * | | . . |
+ * Evaluating the last pulse we check if the last interval is a multiple of our
+ * pri and in that case return 2 as the number of (potentially) lost pulses.
+ *
+ * The global check if the last interval exceeds the max duration of this
+ * pattern type is performed by the caller.
+ *
+ */
+static int check_pulse_lost(struct radar_stats *rs, u32 delta_ts)
+{
+ int lost_pulses = 0;
+
+ if (rs->pri_count == 1) {
+ /* check constant pri patterns */
+ u32 pri = rs->pri[0];
+ while (delta_ts > pri) {
+ /* we already checked that we are within valid duration
+ * => won't loop too long */
+ lost_pulses++;
+ delta_ts -= pri;
+ }
+
+ if (DELTA(pri, delta_ts) <= MAX_PRI_TOLERANCE)
+ return lost_pulses;
+
+ return 0;
+ } else {
+ /* TODO: check staggered radar patterns
+ here we need to support
+ * single burst / packet based and
+ * single burst / single pulse
+ staggered PRF radar test signals
+ */
+ }
+ return 0;
+}
+
+/**
+ * detector_check_match - (private) check for pattern match
+ *
+ * @rp: radar specs to be checked
+ * @rs: radar stats to be checked
+ * @delta_ts: pulse interval to be checked
+ *
+ * Returns 1 on match
+ */
+static int detector_check_match(struct radar_specs *rp, struct radar_stats *rs)
+{
+
+ if (rs->matching_pulse_count >= rp->ppb_thresh) {
+ DINIT("XXXXXXXXXXXXXXXXXXXXXXX MATCH on type %d", rp->type_id);
+ return 1;
+ }
+ return 0;
+}
+
+static int detector_check_pri(struct radar_specs *rp, struct radar_stats *rs,
+ u32 delta_ts)
+{
+ int lost_pulses;
+
+ int pri_num;
+ DLOG("OK: delta_ts=%d <= max_dur[%d]=%d",
+ delta_ts, rp->type_id, rp->max_dur);
+ for (pri_num = 0; pri_num < rs->pri_count; pri_num++) {
+ if (DELTA(delta_ts, rs->pri[pri_num]) < MAX_PRI_TOLERANCE) {
+ rs->matching_pulse_count++;
+ DLOG("delta_ts=%d matches pri_num[%d][%d] => "
+ "matching_pulse_count = %d", delta_ts,
+ rp->type_id, pri_num, rs->matching_pulse_count);
+ if (detector_check_match(rp, rs))
+ return 1;
+ /* we only take the first match */
+ return 0;
+ }
+ lost_pulses = check_pulse_lost(rs, delta_ts);
+ if (lost_pulses > 0) {
+ rs->matching_pulse_count += lost_pulses + 1;
+ DLOG("[%d] assuming %d lost pulses => "
+ "matching_pulse_count = %d",
+ rp->type_id, lost_pulses,
+ rs->matching_pulse_count);
+ if (detector_check_match(rp, rs))
+ return 1;
+ return 0;
+ }
+ DLOG("delta_ts=%d not multiple of [%d] = %d",
+ delta_ts, rp->type_id, rs->pri[0]);
+ reset_detector_element(rs, rs->last_ts);
+ return 0;
+
+ }
+ if (rs->pri_count >= rp->num_pri) {
+ rs->false_pulse_count++;
+ } else {
+ /* pri was not found in the current array, add it as new */
+ rs->pri[rs->pri_count++] = delta_ts;
+ rs->matching_pulse_count += 2;
+ DLOG("added new pri[%d][%d]=%d",
+ rp->type_id, rs->pri_count-1, delta_ts);
+ }
+ return 0;
+}
+
+static int detector_check_pulse_ts(struct radar_specs *rp,
+ struct radar_stats *rs, u64 ts)
+{
+ u32 delta_ts;
+
+ DTRACE();
+ delta_ts = ts - rs->last_ts;
+ DLOG("[%d]: ts=%llu, last_ts=%llu, delta_ts=%d, pri_min=%d, pri_max=%d,"
+ "max_dur=%d", rp->type_id, ts, rs->last_ts, delta_ts,
+ rp->pri_min, rp->pri_max, rp->max_dur);
+ if (delta_ts >= rp->pri_min) {
+ DLOG("OK: delta_ts >= pri_min");
+ if (delta_ts <= rp->max_dur) {
+ /* this one is for us */
+ rs->last_ts = ts;
+ return detector_check_pri(rp, rs, delta_ts);
+ } else {
+ DLOG("NOK: delta_ts=%d > max_dur[%d]=%d",
+ delta_ts, rp->type_id, rp->max_dur);
+ }
+ } else
+ DLOG("delta_ts=%d < pri_min[%d]=%d",
+ delta_ts, rp->type_id, rp->pri_min);
+ /* if for some reason this radar was not for me, safely reset stats
+ * since this pulse invalidates all previous
+ */
+ reset_detector_element(rs, ts);
+ return 0;
+}
+
+
+static u32 freq_to_usec(u32 freq)
+{
+ return (1000000 / freq);
+}
+
+/* percentage of ppb threshold to trigger detection */
+#define MIN_PPB_THRESH 66
+#define PPB_THRESH(X) ((X*MIN_PPB_THRESH + 50) / 100)
+
+static void dpd_exit(struct dfs_pattern_detector *_this)
+{
+ if (_this->data != NULL) {
+ if (_this->data->radar_detectors != NULL)
+ kfree(_this->data->radar_detectors);
+ kfree(_this->data);
+ }
+ kfree(_this);
+}
+
+static enum dfs_detector_result dpd_add_pulse(
+ struct dfs_pattern_detector *_this, struct pulse_event *event)
+{
+ int detector_result = NO_DETECTION;
+ struct pattern_detector_data *pd_data = _this->data;
+ u64 delta_ts = event->ts - pd_data->last_pulse_ts;
+ u32 width = event->width;
+ int dfs_channel_idx;
+ DTRACE();
+
+ DINFO("e->width=%d, e->ts=%llu, delta_ts=%llu, e->rssi=%d, e->freq=%d",
+ event->width, event->ts, delta_ts,
+ event->rssi, event->freq);
+
+ dfs_channel_idx = get_dfs_channel_idx(event->freq);
+ if (dfs_channel_idx < 0) {
+ DERROR("pulse_event.freq=%d is no DFS frequency, dropping");
+ return PULSE_DROPPED;
+ }
+
+ /* global condition checks */
+
+ /* condition: pulse width inside valid range? */
+ if ((width > pd_data->max_valid_width) ||
+ (width < pd_data->min_valid_width)) {
+ DINFO("pulse width %d outside valid range [%d, %d], dropping",
+ width, pd_data->min_valid_pri, pd_data->max_valid_pri);
+ return PULSE_DROPPED;
+ }
+
+ pd_data->last_pulse_ts = event->ts;
+
+ /* condition: pulse interval < max allowed pattern duration */
+ if (delta_ts > pd_data->max_radar_dur) {
+ DINFO("pulse with delta_ts=%llu > max_radar_dur=%d, resetting",
+ delta_ts, pd_data->max_radar_dur);
+ detector_reset(pd_data, dfs_channel_idx);
+ return NO_DETECTION;
+ }
+
+ /* condition: pulse interval larger that min allowed pri
+ * NOTE: we are not checking against max allowed pri to
+ * allow for coverage of multiple pris
+ */
+ if (delta_ts >= pd_data->min_valid_pri) {
+ int i;
+
+ /* do type individual pattern matching */
+ for (i = 0; i < pd_data->num_detector_elements; i++) {
+ struct radar_specs *rp;
+ rp = &pd_data->radar_detectors[i].specs;
+ /* condition: width within type specific width range */
+ if (width >= rp->width_min && width <= rp->width_max) {
+ struct radar_stats *rs;
+ rs = &pd_data->radar_detectors[i].
+ stats[dfs_channel_idx];
+ if (detector_check_pulse_ts(rp,
+ rs, event->ts)) {
+ detector_result = RADAR_DETECTED;
+ /* stop here, don't care if further
+ * patterns might also match */
+ break;
+ }
+ }
+ }
+ if (detector_result == RADAR_DETECTED) {
+ /* radar pattern found -> reset detector line */
+ detector_reset(pd_data, dfs_channel_idx);
+ }
+ return detector_result;
+ } else
+ DINFO("pulse with delta_ts=%llu outside valid pri-range "
+ "[%d, %d], resetting", delta_ts,
+ pd_data->min_valid_pri, pd_data->max_valid_pri);
+ return 0;
+}
+
+
+/* our base VFT */
+static struct dfs_pattern_detector dpd_default_vft = {
+ .exit = dpd_exit,
+ .add_pulse = dpd_add_pulse,
+};
+
+
+static void print_detector_specs(struct pattern_detector_data *pd_data)
+{
+ int i;
+ for (i = 0; i < pd_data->num_detector_elements; i++) {
+ struct radar_specs *rs = &pd_data->radar_detectors[i].specs;
+ DINIT("Initialized radar pattern type %d", i);
+ DINIT(" rs->type_id = %d", rs->type_id);
+ DINIT(" rs->width_min = %d", rs->width_min);
+ DINIT(" rs->width_max = %d", rs->width_max);
+ DINIT(" rs->pri_min = %d", rs->pri_min);
+ DINIT(" rs->pri_max = %d", rs->pri_max);
+ DINIT(" rs->num_pri = %d", rs->num_pri);
+ DINIT(" rs->ppb_thresh = %d", rs->ppb_thresh);
+ DINIT(" rs->max_dur = %d", rs->max_dur);
+ }
+ DINIT("valid ranges: width=[%d, %d], pri=[%d, %d], dur=%d",
+ pd_data->min_valid_width, pd_data->max_valid_width,
+ pd_data->min_valid_pri, pd_data->max_valid_pri,
+ pd_data->max_radar_dur);
+}
+
+
+/* allocate and initialize object data */
+static struct pattern_detector_data *setup_detector_data(struct radar_type *rt)
+{
+ int i;
+ struct pattern_detector_data *pd_data;
+ int sz = sizeof(struct pattern_detector_data);
+ pd_data = kmalloc(sz, GFP_KERNEL);
+ if (pd_data == NULL) {
+ DERROR("allocation of pattern_detector_data failed");
+ return NULL;
+ }
+
+ memset(pd_data, 0, sz);
+
+ sz = sizeof(struct detector_line) * rt->num_radar_types;
+ pd_data->radar_detectors = kmalloc(sz, GFP_KERNEL);
+ if (pd_data->radar_detectors == NULL) {
+ DERROR("allocation of radar_detectors failed");
+ return NULL;
+ }
+ memset(pd_data->radar_detectors, 0, sz);
+
+ pd_data->num_detector_elements = rt->num_radar_types;
+ pd_data->min_valid_width = (u32) -1;
+ pd_data->max_valid_width = 0;
+ pd_data->min_valid_pri = (u32) -1;
+ pd_data->max_valid_pri = 0;
+ pd_data->max_radar_dur = 0;
+
+ for (i = 0; i < rt->num_radar_types; i++) {
+ struct radar_signal_type *rst = &rt->radar_types[i];
+ struct radar_specs *rs = &pd_data->radar_detectors[i].specs;
+ DINIT("Initializing type %d", i);
+ rs->type_id = rst->type_id;
+ rs->width_min = rst->width_min;
+ rs->width_max = rst->width_max;
+ rs->pri_min = freq_to_usec(rst->pps_max) - MAX_PRI_TOLERANCE;
+ rs->pri_max = freq_to_usec(rst->pps_min) + MAX_PRI_TOLERANCE;
+ rs->num_pri = rst->num_pri;
+ rs->ppb = rst->ppb;
+ rs->ppb_thresh = PPB_THRESH(rst->ppb);
+ rs->max_dur = rs->pri_max * rst->ppb * rst->num_pri;
+
+ if (rs->width_min < pd_data->min_valid_width)
+ pd_data->min_valid_width = rs->width_min;
+ if (rs->width_max > pd_data->max_valid_width)
+ pd_data->max_valid_width = rs->width_max;
+ if (rs->pri_min < pd_data->min_valid_pri)
+ pd_data->min_valid_pri = rs->pri_min;
+ if (rs->pri_max > pd_data->max_valid_pri)
+ pd_data->max_valid_pri = rs->pri_max;
+ if (rs->max_dur > pd_data->max_radar_dur)
+ pd_data->max_radar_dur = rs->max_dur;
+ }
+ print_detector_specs(pd_data);
+ return pd_data;
+}
+
+
+struct dfs_pattern_detector *dfs_pattern_detector_init(
+ enum dfs_domain dfs_domain)
+{
+ int i;
+ struct dfs_pattern_detector *_this;
+ struct radar_type *rt;
+
+ /* find supported radar type */
+ for (i = 0; /* nothing */; i++) {
+ rt = supported_radar_types[i];
+ if (rt == NULL) {
+ DERROR("non-supported dfs-domain %d", dfs_domain);
+ return NULL;
+ }
+ if (rt->dfs_id == dfs_domain)
+ break;
+ }
+ /* allocate object instance */
+ _this = kmalloc(sizeof(struct dfs_pattern_detector), GFP_KERNEL);
+ if (_this == NULL) {
+ DERROR("allocation of dfs_pattern_detector failed");
+ return NULL;
+ }
+ *_this = dpd_default_vft;
+
+ /* allocate and initialize object data */
+ _this->data = setup_detector_data(rt);
+ if (_this->data == NULL) {
+ _this->exit(_this);
+ return NULL;
+ }
+ return _this;
+}
diff --git a/net/wireless/dfs/dfs_pattern_detector.h b/net/wireless/dfs/dfs_pattern_detector.h
new file mode 100644
index 0000000..940c8c9
--- /dev/null
+++ b/net/wireless/dfs/dfs_pattern_detector.h
@@ -0,0 +1,46 @@
+#ifndef DFS_PATTERN_DETECTOR_H
+#define DFS_PATTERN_DETECTOR_H
+
+#include "net/dfs.h"
+
+
+/**
+ * enum dfs_detector_result - DFS detector result after adding pulse
+ *
+ * Feeding a potential radar pulse to the detector might result in:
+ * @NO_DETECTION: pulse added, but no detection so far
+ * @RADAR_DETECTED: pulse added, pattern matched => radar detected
+ * @PULSE_DROPPED: pulse not added, outside valid pattern ranges
+ */
+enum dfs_detector_result {
+ NO_DETECTION,
+ RADAR_DETECTED,
+ PULSE_DROPPED,
+};
+
+/**
+ * struct dfs_pattern_detector - pseudo-OO DFS pattern detector class
+ *
+ * A DFS pattern detector object is instantiated with its constructor that
+ * returns ptr to initialized object.
+ *
+ * The VFT so far needs only two public methods:
+ * @exit: destructor
+ * @add_pulse: adds radar pulse to detector
+ *
+ * All data is private.
+ */
+struct dfs_pattern_detector {
+ /* VFT */
+ void (*exit)(struct dfs_pattern_detector *_this);
+ enum dfs_detector_result (*add_pulse)
+ (struct dfs_pattern_detector *_this, struct pulse_event *pe);
+
+ /* private data */
+ struct pattern_detector_data *data;
+};
+
+/* Constructor */
+struct dfs_pattern_detector *dfs_pattern_detector_init(enum dfs_domain);
+
+#endif /* DFS_PATTERN_DETECTOR_H */
diff --git a/net/wireless/dfs/dfs_radar_types.h b/net/wireless/dfs/dfs_radar_types.h
new file mode 100644
index 0000000..329d96c
--- /dev/null
+++ b/net/wireless/dfs/dfs_radar_types.h
@@ -0,0 +1,47 @@
+#ifndef DFS_RADAR_TYPES_H
+#define DFS_RADAR_TYPES_H
+
+#include "net/dfs.h"
+
+struct radar_signal_type {
+ unsigned int type_id;
+ unsigned int width_min;
+ unsigned int width_max;
+ unsigned int pps_min;
+ unsigned int pps_max;
+ unsigned int num_pri;
+ unsigned int ppb;
+};
+
+static struct radar_signal_type etsi_radar_ref_types_v15[] = {
+ { 0, 0, 1, 700, 700, 1, 18, },
+ { 1, 0, 5, 200, 1000, 1, 10, },
+ { 2, 0, 15, 200, 1600, 1, 15, },
+ { 3, 0, 15, 2300, 4000, 1, 25, },
+ { 4, 20, 30, 2000, 4000, 1, 20, },
+ { 5, 0, 2, 300, 400, 3, 10, },
+ { 6, 0, 2, 400, 1200, 3, 15, },
+};
+
+struct radar_type {
+ u32 dfs_id;
+ u32 num_radar_types;
+ struct radar_signal_type *radar_types;
+};
+
+static struct radar_type etsi_radar_types_v15 = {
+ .dfs_id = DFS_ETSI_DOMAIN,
+ .num_radar_types = sizeof(etsi_radar_ref_types_v15) /
+ sizeof(struct radar_signal_type),
+ .radar_types = etsi_radar_ref_types_v15,
+};
+
+
+static struct radar_type *supported_radar_types[] = {
+ &etsi_radar_types_v15,
+};
+
+
+
+#endif /* DFS_RADAR_TYPES_H */
+
--
1.5.4.3
^ permalink raw reply related
* [PATCH 1/4] DFS: interface for common pattern detector
From: Zefir Kurtisi @ 2010-12-21 15:15 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <2121764975.11097.1292943781910.JavaMail.root@idefix>
Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
---
include/net/cfg80211.h | 41 +++++++++
include/net/dfs.h | 100 +++++++++++++++++++++
2 files changed, 141 insertions(+), 0 deletions(-)
create mode 100644 include/net/dfs.h
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 03b3bae..c3ace0e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1820,6 +1820,47 @@ struct ieee80211_rate *
ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
u32 basic_rates, int bitrate);
+
+/**
+ * DFS pattern detector interface
+ */
+
+/**
+ * ieee80211_add_radar_pulse - add a pulse detected by HW to detector
+ *
+ * @freq: channel frequency in [MHz]
+ * @ts: time stamp in [us]
+ * @rssi: rssi value for the deteced pulse
+ * @width: pulse width in [us]
+ *
+ * Each pulse the HW identified as radar is fed into the detector via this
+ * function. The three values for ts, rssi and width are those relevant for
+ * pattern matching, while freq is required to map the pulse to the correct
+ * DFS channel.
+ * No value is returned, assuming the HW does not need to know about the result
+ * of pattern matching. The further processing of matches is done at mac layer.
+ */
+extern void ieee80211_add_radar_pulse(u16 freq, u64 ts, u8 rssi, u8 width);
+
+/**
+ * ieee80211_radar_detected - notify mac that DFS radar was detected
+ *
+ * @freq: channel frequency in [MHz]
+ *
+ * This function is used to inform the mac that a DFS radar was detected on
+ * the given channel frequency. It might be called from the DFS pattern
+ * detector or from device drivers that do DFS detection in HW.
+ *
+ * It is meant to be the central hook that initiates all subsequent actions that
+ * need to be performed after the detection, including
+ * - put channel to Unavailable list (or adjust channel state periods
+ * in case channel was already not on Available list)
+ * - everything else required to select new channel and initiate
+ * channel switch
+ */
+extern void ieee80211_radar_detected(u16 freq);
+
+
/*
* Radiotap parsing functions -- for controlled injection support
*
diff --git a/include/net/dfs.h b/include/net/dfs.h
new file mode 100644
index 0000000..1dccc10
--- /dev/null
+++ b/include/net/dfs.h
@@ -0,0 +1,100 @@
+#ifndef DFS_H
+#define DFS_H
+/*
+ * Copyright 2010, Neratec Solutions AG, <zefir.kurtisi@neratec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/**
+ * DOC: Introduction
+ *
+ * DFS radar detector interface
+ *
+ * This is a proposal for a common DFS pattern detector interface.
+ *
+ * It should be used by devices that are able to detect radar pulses and need
+ * pattern matching (as defined by ETSI, FCC, JP regulatories).
+ *
+ * An instance of the proposed DFS handler is supposed to exist during an
+ * endpoint's lifetime within mac80211. WLAN devices should report the radar
+ * pulses they detect during their uptime, the DFS handler aggregates them and
+ * keeps track of channel states (as defined by regulatories).
+ *
+ * On channel state changes it notifies mac80211 to initiate all required
+ * processing.
+ */
+
+
+/* TODO: move those to more common place */
+enum dfs_domain {
+ DFS_INVALID_DOMAIN = 0, /* Uninitialized dfs domain */
+ DFS_FCC_DOMAIN = 1, /* FCC dfs domain */
+ DFS_ETSI_DOMAIN = 2, /* ETSI dfs domain */
+ DFS_JP_DOMAIN = 3, /* Japan dfs domain */
+};
+
+/* TODO: move dfs_state to more common place */
+enum channel_dfs_flags {
+ CHANNEL_INVALID = 0x00,
+ CHANNEL_UNAVAILABLE = 0x01,
+ CHANNEL_USABLE = 0x02,
+ CHANNEL_AVAILABLE = 0x04,
+ CHANNEL_OPERATING = 0x08,
+};
+
+/**
+ * struct pulse_event - events fed to the dfs handler
+ *
+ * @ts: absolute time stamp for start of pulse in us (e.g. as TSF)
+ * @freq: channel frequency in [MHz]
+ * @rssi: rssi value for the given pulse
+ * @width: pulse width for given pulse in [us]
+ *
+ */
+struct pulse_event {
+ u64 ts;
+ u16 freq;
+ u8 rssi;
+ u8 width;
+};
+
+/**
+ * struct dfs_handler - DFS handler pseudo-OO interface
+ *
+ * @exit: terminate DFS handler and release all resources
+ * @add_pulse: add given pulse event to detector lines
+ * returns 1 if added event triggered a pattern match
+ * @data: private instance data
+ *
+ * To easily attach pulse detectors implementing different types matching
+ * algorithms, a pseudo-OO design approach was taken with a tiny interface is
+ * chosen.
+ */
+struct dfs_handler {
+ /* VFT */
+ void (*exit)(struct dfs_handler *_this);
+ int (*add_pulse)(struct dfs_handler *_this, struct pulse_event *event);
+
+ /* private data */
+ struct dfs_data *data;
+};
+
+/**
+ * dfs_handler_init - DFS handler constructor
+ *
+ * @dfs_domain: DFS domain to detect radar patterns for
+ *
+ * A DFS handler instance is allocated via this constructor.
+ * On success the pointer to the fully initialized handler is returned that
+ * can be fed with radar pulses during its lifetime. Allocated resources are
+ * released upon calling the destructor.
+ *
+ * On failure NULL is returned.
+ */
+struct dfs_handler *dfs_handler_init(enum dfs_domain dfs_domain);
+
+
+#endif /* DFS_H */
--
1.5.4.3
^ permalink raw reply related
* [PATCH 3/4] DFS: interface ath9k to pattern detector
From: Zefir Kurtisi @ 2010-12-21 15:15 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <993654931.11102.1292944188555.JavaMail.root@idefix>
Enable DFS radar pulse detection in ath9k PHY and feed radar detector
with potential pulse events filtered from RX PHY errors.
Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
---
.../drivers/net/wireless/ath/ath9k/mac.c | 51 ++++++++++++++++++++
.../drivers/net/wireless/ath/ath9k/main.c | 9 ++++
2 files changed, 60 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index e3d2ebf..a303010 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -624,6 +624,53 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
}
EXPORT_SYMBOL(ath9k_hw_resettxqueue);
+/*
+ * DFS: check PHY-error for radar pulse and feed the detector
+ */
+void ath9k_dfs_process_phyerr(struct ath_hw *ah, struct ath_desc *ds,
+ struct ath_rx_status *rs, u_int64_t fulltsf)
+{
+ static u64 last_ts;
+ static u32 ts_hi;
+
+ struct ath9k_channel *chan = ah->curchan;
+ u8 rssi;
+ u32 dur = 0;
+ u32 ts;
+
+ if ((!(rs->rs_phyerr != ATH9K_PHYERR_RADAR))
+ && (!(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT))) {
+ printk(KERN_INFO "Error: rs_phyer=0x%x not a radar error\n",
+ rs->rs_phyerr);
+ return;
+ }
+
+ /* update internal 64-bit time stamp with that of rs */
+ ts = rs->rs_tstamp;
+ if (ts <= (last_ts & 0xffffffff))
+ ts_hi++;
+ last_ts = ((u64)ts_hi << 32) | ts;
+
+ rssi = (u8) rs->rs_rssi_ctl0;
+
+ if (rssi == 0)
+ return;
+
+ if (rs->rs_datalen != 0) {
+ char *vdata = (char *)ds->ds_vdata + rs->rs_datalen - 3;
+ dur = (u32) vdata[0];
+#if 0
+ printk(KERN_INFO "dur=%d, datalen=%d: [%.2x, %.2x, %.2x]\n",
+ dur, rs->rs_datalen, vdata[0], vdata[1], vdata[2]);
+#endif
+ }
+
+ /* ZKU: reverse measured scaling factor of 2/3 for duration */
+ dur = (dur * 66 + 50) / 100;
+ ieee80211_add_radar_pulse(chan->channel, last_ts - dur, rssi, dur);
+}
+EXPORT_SYMBOL(ath9k_dfs_process_phyerr);
+
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
struct ath_rx_status *rs, u64 tsf)
{
@@ -696,6 +743,10 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
rs->rs_status |= ATH9K_RXERR_PHY;
phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
rs->rs_phyerr = phyerr;
+
+ /* DFS: feed assumed radar pulse */
+ ath9k_dfs_process_phyerr(ah, ds, rs, tsf);
+
} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
rs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (ads.ds_rxstatus8 & AR_MichaelErr)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 29a6d35..a799c36 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -290,6 +290,15 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
ath_start_ani(common);
}
+ /**
+ * 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);
+
ps_restore:
spin_unlock_bh(&sc->sc_pcu_lock);
--
1.5.4.3
^ permalink raw reply related
* [PATCH 4/4] DFS: added license info to new files
From: Zefir Kurtisi @ 2010-12-21 15:15 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <902496335.11104.1292944273242.JavaMail.root@idefix>
Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
---
include/net/dfs.h | 4 ++--
.../net/wireless/dfs/dfs_handler.c | 8 ++++++++
.../net/wireless/dfs/dfs_pattern_detector.c | 8 ++++++++
3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/include/net/dfs.h b/include/net/dfs.h
index 1dccc10..0744502 100644
--- a/include/net/dfs.h
+++ b/include/net/dfs.h
@@ -48,10 +48,10 @@ enum channel_dfs_flags {
/**
* struct pulse_event - events fed to the dfs handler
*
- * @ts: absolute time stamp for start of pulse in us (e.g. as TSF)
+ * @ts: absolute time stamp for start of pulse in [us] (e.g. as TSF)
* @freq: channel frequency in [MHz]
* @rssi: rssi value for the given pulse
- * @width: pulse width for given pulse in [us]
+ * @width: pulse width in [us]
*
*/
struct pulse_event {
diff --git a/net/wireless/dfs/dfs_handler.c b/net/wireless/dfs/dfs_handler.c
index 7e65852..952eb97 100644
--- a/net/wireless/dfs/dfs_handler.c
+++ b/net/wireless/dfs/dfs_handler.c
@@ -1,3 +1,11 @@
+/*
+ * Copyright 2010, Neratec Solutions AG, <zefir.kurtisi@neratec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
#include "net/dfs.h"
#include "net/cfg80211.h"
#include "dfs_common.h"
diff --git a/net/wireless/dfs/dfs_pattern_detector.c b/net/wireless/dfs/dfs_pattern_detector.c
index 17ab7d6..513cc91 100644
--- a/net/wireless/dfs/dfs_pattern_detector.c
+++ b/net/wireless/dfs/dfs_pattern_detector.c
@@ -1,3 +1,11 @@
+/*
+ * Copyright 2010, Neratec Solutions AG, <zefir.kurtisi@neratec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
#include "dfs_pattern_detector.h"
#include "dfs_debug.h"
#include "net/dfs.h"
--
1.5.4.3
^ permalink raw reply related
* Re: [PATCH 1/7] wl1251: remove unnecessary import
From: Kalle Valo @ 2010-12-21 15:19 UTC (permalink / raw)
To: Hauke Mehrtens; +Cc: linville, linux-wireless
In-Reply-To: <1292893316-26694-2-git-send-email-hauke@hauke-m.de>
Hauke Mehrtens <hauke@hauke-m.de> writes:
> No function declared in gpio.h is used here.
That's right, thanks.
> CC: Kalle Valo <kvalo@adurom.com>
> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Acked-by: Kalle Valo <kvalo@adurom.com>
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH 5/5] ath5k: Use helper function to get eeprom mode from channel
From: Nick Kossifidis @ 2010-12-21 14:49 UTC (permalink / raw)
To: Bruno Randolf; +Cc: linville, ath5k-devel, linux-wireless
In-Reply-To: <20101221083042.8765.42404.stgit@localhost6.localdomain6>
2010/12/21 Bruno Randolf <br1@einfach.org>:
> Introduce a helper function to get the EEPROM mode from channel and remove
> multiple similar switch statements. Also since it's now easy to get the EEPROM
> mode from the channel, use them inside the functions which need it, instead of
> passing a redundant ee_mode parameter.
>
> Signed-off-by: Bruno Randolf <br1@einfach.org>
> ---
> drivers/net/wireless/ath/ath5k/ath5k.h | 2 -
> drivers/net/wireless/ath/ath5k/eeprom.c | 16 +++++++
> drivers/net/wireless/ath/ath5k/eeprom.h | 2 +
> drivers/net/wireless/ath/ath5k/phy.c | 68 +++++++------------------------
> drivers/net/wireless/ath/ath5k/reset.c | 19 ++++-----
> 5 files changed, 42 insertions(+), 65 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
> index 5de8520..407e39c 100644
> --- a/drivers/net/wireless/ath/ath5k/ath5k.h
> +++ b/drivers/net/wireless/ath/ath5k/ath5k.h
> @@ -1318,7 +1318,7 @@ void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode);
> int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
> /* Init function */
> int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> - u8 mode, u8 ee_mode, bool fast);
> + u8 mode, bool fast);
>
> /*
> * Functions used internaly
> diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
> index 97eaa9a..80e6256 100644
> --- a/drivers/net/wireless/ath/ath5k/eeprom.c
> +++ b/drivers/net/wireless/ath/ath5k/eeprom.c
> @@ -1802,3 +1802,19 @@ ath5k_eeprom_detach(struct ath5k_hw *ah)
> for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
> ath5k_eeprom_free_pcal_info(ah, mode);
> }
> +
> +int
> +ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel)
> +{
> + switch (channel->hw_value & CHANNEL_MODES) {
> + case CHANNEL_A:
> + case CHANNEL_XR:
> + return AR5K_EEPROM_MODE_11A;
> + case CHANNEL_G:
> + return AR5K_EEPROM_MODE_11G;
> + case CHANNEL_B:
> + return AR5K_EEPROM_MODE_11B;
> + default:
> + return -1;
> + }
> +}
> diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
> index 0017006..7c09e15 100644
> --- a/drivers/net/wireless/ath/ath5k/eeprom.h
> +++ b/drivers/net/wireless/ath/ath5k/eeprom.h
> @@ -517,3 +517,5 @@ struct ath5k_eeprom_info {
> u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
> };
>
> +int
> +ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel);
> diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
> index b6e9621..9306d5f 100644
> --- a/drivers/net/wireless/ath/ath5k/phy.c
> +++ b/drivers/net/wireless/ath/ath5k/phy.c
> @@ -1355,20 +1355,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
> return;
> }
>
> - switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) {
> - case CHANNEL_A:
> - case CHANNEL_XR:
> - ee_mode = AR5K_EEPROM_MODE_11A;
> - break;
> - case CHANNEL_G:
> - ee_mode = AR5K_EEPROM_MODE_11G;
> - break;
> - default:
> - case CHANNEL_B:
> - ee_mode = AR5K_EEPROM_MODE_11B;
> - break;
> - }
> -
> + ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel);
>
> /* completed NF calibration, test threshold */
> nf = ath5k_hw_read_measured_noise_floor(ah);
> @@ -1941,18 +1928,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
>
> def_ant = ah->ah_def_ant;
>
> - switch (channel->hw_value & CHANNEL_MODES) {
> - case CHANNEL_A:
> - case CHANNEL_XR:
> - ee_mode = AR5K_EEPROM_MODE_11A;
> - break;
> - case CHANNEL_G:
> - ee_mode = AR5K_EEPROM_MODE_11G;
> - break;
> - case CHANNEL_B:
> - ee_mode = AR5K_EEPROM_MODE_11B;
> - break;
> - default:
> + ee_mode = ath5k_eeprom_mode_from_channel(channel);
> + if (ee_mode < 0) {
> ATH5K_ERR(ah->ah_sc,
> "invalid channel: %d\n", channel->center_freq);
> return;
> @@ -3100,11 +3077,11 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
> */
> static int
> ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> - u8 ee_mode, u8 txpower)
> + u8 txpower)
> {
> struct ath5k_rate_pcal_info rate_info;
> struct ieee80211_channel *curr_channel = ah->ah_current_channel;
> - u8 type;
> + u8 type, ee_mode;
> int ret;
>
> if (txpower > AR5K_TUNE_MAX_TXPOWER) {
> @@ -3112,6 +3089,13 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> return -EINVAL;
> }
>
> + ee_mode = ath5k_eeprom_mode_from_channel(channel);
> + if (ee_mode < 0) {
> + ATH5K_ERR(ah->ah_sc,
> + "invalid channel: %d\n", channel->center_freq);
> + return -EINVAL;
> + }
> +
> /* Initialize TX power table */
> switch (ah->ah_radio) {
> case AR5K_RF5110:
> @@ -3208,31 +3192,10 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
>
> int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
> {
> - /*Just a try M.F.*/
> - struct ieee80211_channel *channel = ah->ah_current_channel;
> - u8 ee_mode;
> -
> - switch (channel->hw_value & CHANNEL_MODES) {
> - case CHANNEL_A:
> - case CHANNEL_XR:
> - ee_mode = AR5K_EEPROM_MODE_11A;
> - break;
> - case CHANNEL_G:
> - ee_mode = AR5K_EEPROM_MODE_11G;
> - break;
> - case CHANNEL_B:
> - ee_mode = AR5K_EEPROM_MODE_11B;
> - break;
> - default:
> - ATH5K_ERR(ah->ah_sc,
> - "invalid channel: %d\n", channel->center_freq);
> - return -EINVAL;
> - }
> -
> ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
> "changing txpower to %d\n", txpower);
>
> - return ath5k_hw_txpower(ah, channel, ee_mode, txpower);
> + return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower);
> }
>
> /*************\
> @@ -3240,7 +3203,7 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
> \*************/
>
> int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> - u8 mode, u8 ee_mode, bool fast)
> + u8 mode, bool fast)
> {
> struct ieee80211_channel *curr_channel;
> int ret, i;
> @@ -3281,8 +3244,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> * RF buffer settings on 5211/5212+ so that we
> * properly set curve indices.
> */
> - ret = ath5k_hw_txpower(ah, channel, ee_mode,
> - ah->ah_txpower.txp_cur_pwr ?
> + ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_cur_pwr ?
> ah->ah_txpower.txp_cur_pwr / 2 : AR5K_TUNE_MAX_TXPOWER);
> if (ret)
> return ret;
> diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
> index 4b8b987..3c962f7 100644
> --- a/drivers/net/wireless/ath/ath5k/reset.c
> +++ b/drivers/net/wireless/ath/ath5k/reset.c
> @@ -866,15 +866,18 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
> }
>
> static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
> - struct ieee80211_channel *channel, u8 ee_mode)
> + struct ieee80211_channel *channel)
> {
> struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
> s16 cck_ofdm_pwr_delta;
> + u8 ee_mode;
>
> /* TODO: Add support for AR5210 EEPROM */
> if (ah->ah_version == AR5K_AR5210)
> return;
>
> + ee_mode = ath5k_eeprom_mode_from_channel(channel);
> +
> /* Adjust power delta for channel 14 */
> if (channel->center_freq == 2484)
> cck_ofdm_pwr_delta =
> @@ -1020,10 +1023,9 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> struct ieee80211_channel *channel, bool fast, bool skip_pcu)
> {
> u32 s_seq[10], s_led[3], tsf_up, tsf_lo;
> - u8 mode, ee_mode;
> + u8 mode;
> int i, ret;
>
> - ee_mode = 0;
> tsf_up = 0;
> tsf_lo = 0;
> mode = 0;
> @@ -1070,7 +1072,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> switch (channel->hw_value & CHANNEL_MODES) {
> case CHANNEL_A:
> mode = AR5K_MODE_11A;
> - ee_mode = AR5K_EEPROM_MODE_11A;
> break;
> case CHANNEL_G:
>
> @@ -1081,7 +1082,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> }
>
> mode = AR5K_MODE_11G;
> - ee_mode = AR5K_EEPROM_MODE_11G;
> break;
> case CHANNEL_B:
>
> @@ -1092,7 +1092,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> }
>
> mode = AR5K_MODE_11B;
> - ee_mode = AR5K_EEPROM_MODE_11B;
> break;
> case CHANNEL_XR:
> if (ah->ah_version == AR5K_AR5211) {
> @@ -1101,7 +1100,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> return -EINVAL;
> }
> mode = AR5K_MODE_XR;
> - ee_mode = AR5K_EEPROM_MODE_11A;
> break;
> default:
> ATH5K_ERR(ah->ah_sc,
> @@ -1114,8 +1112,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> * go on. If it fails continue with a normal reset.
> */
> if (fast) {
> - ret = ath5k_hw_phy_init(ah, channel, mode,
> - ee_mode, true);
> + ret = ath5k_hw_phy_init(ah, channel, mode, true);
> if (ret) {
> ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
> "fast chan change failed, falling back to normal reset\n");
> @@ -1212,7 +1209,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> ath5k_hw_tweak_initval_settings(ah, channel);
>
> /* Commit values from EEPROM */
> - ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode);
> + ath5k_hw_commit_eeprom_settings(ah, channel);
>
>
> /*
> @@ -1251,7 +1248,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> /*
> * Initialize PHY
> */
> - ret = ath5k_hw_phy_init(ah, channel, mode, ee_mode, false);
> + ret = ath5k_hw_phy_init(ah, channel, mode, false);
> if (ret) {
> ATH5K_ERR(ah->ah_sc,
> "failed to initialize PHY (%i) !\n", ret);
>
>
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick
^ permalink raw reply
* Re: [PATCH 4/5] ath5k: Remove ATH5K_INI_RFGAIN defines, use band instead
From: Nick Kossifidis @ 2010-12-21 14:49 UTC (permalink / raw)
To: Bruno Randolf; +Cc: linville, ath5k-devel, linux-wireless
In-Reply-To: <20101221083037.8765.68357.stgit@localhost6.localdomain6>
2010/12/21 Bruno Randolf <br1@einfach.org>:
> Remove redundant defines.
>
> Signed-off-by: Bruno Randolf <br1@einfach.org>
> ---
> drivers/net/wireless/ath/ath5k/ath5k.h | 6 +-----
> drivers/net/wireless/ath/ath5k/phy.c | 18 ++++++------------
> drivers/net/wireless/ath/ath5k/reset.c | 11 +++--------
> 3 files changed, 10 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
> index 342da28..5de8520 100644
> --- a/drivers/net/wireless/ath/ath5k/ath5k.h
> +++ b/drivers/net/wireless/ath/ath5k/ath5k.h
> @@ -154,10 +154,6 @@
> udelay(1); \
> } while (0)
>
> -/* Register dumps are done per operation mode */
> -#define AR5K_INI_RFGAIN_5GHZ 0
> -#define AR5K_INI_RFGAIN_2GHZ 1
> -
> /*
> * Some tuneable values (these should be changeable by the user)
> * TODO: Make use of them and add more options OR use debug/configfs
> @@ -1322,7 +1318,7 @@ void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode);
> int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
> /* Init function */
> int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> - u8 mode, u8 ee_mode, u8 freq, bool fast);
> + u8 mode, u8 ee_mode, bool fast);
>
> /*
> * Functions used internaly
> diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
> index 18c58cd..b6e9621 100644
> --- a/drivers/net/wireless/ath/ath5k/phy.c
> +++ b/drivers/net/wireless/ath/ath5k/phy.c
> @@ -609,10 +609,10 @@ done:
> /* Write initial RF gain table to set the RF sensitivity
> * this one works on all RF chips and has nothing to do
> * with gain_F calibration */
> -static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
> +static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band)
> {
> const struct ath5k_ini_rfgain *ath5k_rfg;
> - unsigned int i, size;
> + unsigned int i, size, index;
>
> switch (ah->ah_radio) {
> case AR5K_RF5111:
> @@ -644,17 +644,11 @@ static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
> return -EINVAL;
> }
>
> - switch (freq) {
> - case AR5K_INI_RFGAIN_2GHZ:
> - case AR5K_INI_RFGAIN_5GHZ:
> - break;
> - default:
> - return -EINVAL;
> - }
> + index = (band == IEEE80211_BAND_2GHZ) ? 1 : 0;
>
> for (i = 0; i < size; i++) {
> AR5K_REG_WAIT(i);
> - ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
> + ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[index],
> (u32)ath5k_rfg[i].rfg_register);
> }
>
> @@ -3246,7 +3240,7 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
> \*************/
>
> int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> - u8 mode, u8 ee_mode, u8 freq, bool fast)
> + u8 mode, u8 ee_mode, bool fast)
> {
> struct ieee80211_channel *curr_channel;
> int ret, i;
> @@ -3305,7 +3299,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> * Write initial RF gain settings
> * This should work for both 5111/5112
> */
> - ret = ath5k_hw_rfgain_init(ah, freq);
> + ret = ath5k_hw_rfgain_init(ah, channel->band);
> if (ret)
> return ret;
>
> diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
> index bc84aaa..4b8b987 100644
> --- a/drivers/net/wireless/ath/ath5k/reset.c
> +++ b/drivers/net/wireless/ath/ath5k/reset.c
> @@ -1020,13 +1020,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> struct ieee80211_channel *channel, bool fast, bool skip_pcu)
> {
> u32 s_seq[10], s_led[3], tsf_up, tsf_lo;
> - u8 mode, freq, ee_mode;
> + u8 mode, ee_mode;
> int i, ret;
>
> ee_mode = 0;
> tsf_up = 0;
> tsf_lo = 0;
> - freq = 0;
> mode = 0;
>
> /*
> @@ -1071,7 +1070,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> switch (channel->hw_value & CHANNEL_MODES) {
> case CHANNEL_A:
> mode = AR5K_MODE_11A;
> - freq = AR5K_INI_RFGAIN_5GHZ;
> ee_mode = AR5K_EEPROM_MODE_11A;
> break;
> case CHANNEL_G:
> @@ -1083,7 +1081,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> }
>
> mode = AR5K_MODE_11G;
> - freq = AR5K_INI_RFGAIN_2GHZ;
> ee_mode = AR5K_EEPROM_MODE_11G;
> break;
> case CHANNEL_B:
> @@ -1095,7 +1092,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> }
>
> mode = AR5K_MODE_11B;
> - freq = AR5K_INI_RFGAIN_2GHZ;
> ee_mode = AR5K_EEPROM_MODE_11B;
> break;
> case CHANNEL_XR:
> @@ -1105,7 +1101,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> return -EINVAL;
> }
> mode = AR5K_MODE_XR;
> - freq = AR5K_INI_RFGAIN_5GHZ;
> ee_mode = AR5K_EEPROM_MODE_11A;
> break;
> default:
> @@ -1120,7 +1115,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> */
> if (fast) {
> ret = ath5k_hw_phy_init(ah, channel, mode,
> - ee_mode, freq, true);
> + ee_mode, true);
> if (ret) {
> ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
> "fast chan change failed, falling back to normal reset\n");
> @@ -1256,7 +1251,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> /*
> * Initialize PHY
> */
> - ret = ath5k_hw_phy_init(ah, channel, mode, ee_mode, freq, false);
> + ret = ath5k_hw_phy_init(ah, channel, mode, ee_mode, false);
> if (ret) {
> ATH5K_ERR(ah->ah_sc,
> "failed to initialize PHY (%i) !\n", ret);
>
>
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick
^ permalink raw reply
* Re: [PATCH 3/5] ath5k: Track current TX power separately from max TX power
From: Nick Kossifidis @ 2010-12-21 14:48 UTC (permalink / raw)
To: Bruno Randolf; +Cc: linville, ath5k-devel, linux-wireless
In-Reply-To: <20101221083032.8765.42449.stgit@localhost6.localdomain6>
2010/12/21 Bruno Randolf <br1@einfach.org>:
> Add a new variable to keep track of the currently configured tx power. Before
> max_pwr was re-used for keeping the maximum allowed power as well as the
> current configuration. Doing a min() on it allows you to lower the txpower, but
> how would you be able to make it higher again?
>
> This patch fixes that by adding a new variable ah_cur_pwr which is used instead
> of txp_max_pwr to keep the current configuration. txp_max_pwr is used to check
> if we are within the limits.
>
> Another problem fixed by this patch is that it avoids setting a zero txpower
> when things are initialized first and the current power is not yet set.
>
> Signed-off-by: Bruno Randolf <br1@einfach.org>
> ---
> drivers/net/wireless/ath/ath5k/ath5k.h | 1 +
> drivers/net/wireless/ath/ath5k/phy.c | 7 +++----
> 2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
> index e6491bf..342da28 100644
> --- a/drivers/net/wireless/ath/ath5k/ath5k.h
> +++ b/drivers/net/wireless/ath/ath5k/ath5k.h
> @@ -1107,6 +1107,7 @@ struct ath5k_hw {
> /* Values in 0.25dB units */
> s16 txp_min_pwr;
> s16 txp_max_pwr;
> + s16 txp_cur_pwr;
> /* Values in 0.5dB units */
> s16 txp_offset;
> s16 txp_ofdm;
> diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
> index 6f0cf3a..18c58cd 100644
> --- a/drivers/net/wireless/ath/ath5k/phy.c
> +++ b/drivers/net/wireless/ath/ath5k/phy.c
> @@ -3096,7 +3096,7 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
>
> /* Min/max in 0.25dB units */
> ah->ah_txpower.txp_min_pwr = 2 * rates[7];
> - ah->ah_txpower.txp_max_pwr = 2 * rates[0];
> + ah->ah_txpower.txp_cur_pwr = 2 * rates[0];
> ah->ah_txpower.txp_ofdm = rates[7];
> }
>
> @@ -3150,8 +3150,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> /* Reset TX power values */
> memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
> ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
> - ah->ah_txpower.txp_min_pwr = 0;
> - ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER;
>
> /* Calculate the powertable */
> ret = ath5k_setup_channel_powertable(ah, channel,
> @@ -3290,7 +3288,8 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> * properly set curve indices.
> */
> ret = ath5k_hw_txpower(ah, channel, ee_mode,
> - ah->ah_txpower.txp_max_pwr / 2);
> + ah->ah_txpower.txp_cur_pwr ?
> + ah->ah_txpower.txp_cur_pwr / 2 : AR5K_TUNE_MAX_TXPOWER);
> if (ret)
> return ret;
>
>
>
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick
^ permalink raw reply
* Re: [PATCH 2/5] ath5k: Separate powertable setup and writing
From: Nick Kossifidis @ 2010-12-21 14:48 UTC (permalink / raw)
To: Bruno Randolf; +Cc: linville, ath5k-devel, linux-wireless
In-Reply-To: <20101221083026.8765.79160.stgit@localhost6.localdomain6>
2010/12/21 Bruno Randolf <br1@einfach.org>:
> And rename functions which write the powertable to make it clearer.
>
> Signed-off-by: Bruno Randolf <br1@einfach.org>
> ---
> drivers/net/wireless/ath/ath5k/phy.c | 34 ++++++++++++++++------------------
> 1 files changed, 16 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
> index 7c6d7dc..6f0cf3a 100644
> --- a/drivers/net/wireless/ath/ath5k/phy.c
> +++ b/drivers/net/wireless/ath/ath5k/phy.c
> @@ -2593,7 +2593,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
>
> /* Write PCDAC values on hw */
> static void
> -ath5k_setup_pcdac_table(struct ath5k_hw *ah)
> +ath5k_write_pcdac_table(struct ath5k_hw *ah)
> {
> u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
> int i;
> @@ -2742,7 +2742,7 @@ ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah,
>
> /* Write PDADC values on hw */
> static void
> -ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)
> +ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)
> {
> struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
> u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
> @@ -2957,8 +2957,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah,
> (s16) pcinfo_R->freq,
> pcinfo_L->max_pwr, pcinfo_R->max_pwr);
>
> - /* We are ready to go, fill PCDAC/PDADC
> - * table and write settings on hardware */
> + /* Fill PCDAC/PDADC table */
> switch (type) {
> case AR5K_PWRTABLE_LINEAR_PCDAC:
> /* For RF5112 we can have one or two curves
> @@ -2971,9 +2970,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah,
> * match max power value with max
> * table index */
> ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2);
> -
> - /* Write settings on hw */
> - ath5k_setup_pcdac_table(ah);
> break;
> case AR5K_PWRTABLE_PWR_TO_PCDAC:
> /* We are done for RF5111 since it has only
> @@ -2983,9 +2979,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah,
> /* No rate powertable adjustment for RF5111 */
> ah->ah_txpower.txp_min_idx = 0;
> ah->ah_txpower.txp_offset = 0;
> -
> - /* Write settings on hw */
> - ath5k_setup_pcdac_table(ah);
> break;
> case AR5K_PWRTABLE_PWR_TO_PDADC:
> /* Set PDADC boundaries and fill
> @@ -2993,9 +2986,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah,
> ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max,
> ee->ee_pd_gains[ee_mode]);
>
> - /* Write settings on hw */
> - ath5k_setup_pwr_to_pdadc_table(ah, ee_mode);
> -
> /* Set txp.offset, note that table_min
> * can be negative */
> ah->ah_txpower.txp_offset = table_min[0];
> @@ -3009,6 +2999,15 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah,
> return 0;
> }
>
> +/* Write power table for current channel to hw */
> +static void
> +ath5k_write_channel_powertable(struct ath5k_hw *ah, u8 ee_mode, u8 type)
> +{
> + if (type == AR5K_PWRTABLE_PWR_TO_PDADC)
> + ath5k_write_pwr_to_pdadc_table(ah, ee_mode);
> + else
> + ath5k_write_pcdac_table(ah);
> +}
>
> /*
> * Per-rate tx power setting
> @@ -3159,11 +3158,10 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> ee_mode, type);
> if (ret)
> return ret;
> - /* Write cached table on hw */
> - } else if (type == AR5K_PWRTABLE_PWR_TO_PDADC)
> - ath5k_setup_pwr_to_pdadc_table(ah, ee_mode);
> - else
> - ath5k_setup_pcdac_table(ah);
> + }
> +
> + /* Write table on hw */
> + ath5k_write_channel_powertable(ah, ee_mode, type);
>
> /* Limit max power if we have a CTL available */
> ath5k_get_max_ctl_power(ah, channel);
>
>
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick
^ permalink raw reply
* Re: [PATCH 1/5] ath5k: Simplify powertable recalculation
From: Nick Kossifidis @ 2010-12-21 14:47 UTC (permalink / raw)
To: Bruno Randolf; +Cc: linville, ath5k-devel, linux-wireless
In-Reply-To: <20101221083020.8765.16350.stgit@localhost6.localdomain6>
2010/12/21 Bruno Randolf <br1@einfach.org>:
> Let ath5k_hw_txpower() decide if it can re-use the powertable or if it has to
> be recalculated instead of passing a 'fast' flag from the outside.
>
> Signed-off-by: Bruno Randolf <br1@einfach.org>
> ---
> drivers/net/wireless/ath/ath5k/ath5k.h | 1 +
> drivers/net/wireless/ath/ath5k/phy.c | 35 ++++++++++++--------------------
> 2 files changed, 14 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
> index d6e7440..e6491bf 100644
> --- a/drivers/net/wireless/ath/ath5k/ath5k.h
> +++ b/drivers/net/wireless/ath/ath5k/ath5k.h
> @@ -1113,6 +1113,7 @@ struct ath5k_hw {
> s16 txp_cck_ofdm_gainf_delta;
> /* Value in dB units */
> s16 txp_cck_ofdm_pwr_delta;
> + bool txp_setup;
> } ah_txpower;
>
> struct {
> diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
> index f84afb4..7c6d7dc 100644
> --- a/drivers/net/wireless/ath/ath5k/phy.c
> +++ b/drivers/net/wireless/ath/ath5k/phy.c
> @@ -3004,6 +3004,8 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah,
> return -EINVAL;
> }
>
> + ah->ah_txpower.txp_setup = true;
> +
> return 0;
> }
>
> @@ -3105,9 +3107,10 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
> */
> static int
> ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> - u8 ee_mode, u8 txpower, bool fast)
> + u8 ee_mode, u8 txpower)
> {
> struct ath5k_rate_pcal_info rate_info;
> + struct ieee80211_channel *curr_channel = ah->ah_current_channel;
> u8 type;
> int ret;
>
> @@ -3138,10 +3141,13 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> return -EINVAL;
> }
>
> - /* If fast is set it means we are on the same channel/mode
> - * so there is no need to recalculate the powertable, we 'll
> - * just use the cached one */
> - if (!fast) {
> + /*
> + * If we don't change channel/mode skip tx powertable calculation
> + * and use the cached one.
> + */
> + if (!ah->ah_txpower.txp_setup ||
> + (channel->hw_value != curr_channel->hw_value) ||
> + (channel->center_freq != curr_channel->center_freq)) {
> /* Reset TX power values */
> memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
> ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
> @@ -3159,8 +3165,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> else
> ath5k_setup_pcdac_table(ah);
>
> -
> -
> /* Limit max power if we have a CTL available */
> ath5k_get_max_ctl_power(ah, channel);
>
> @@ -3238,7 +3242,7 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
> ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
> "changing txpower to %d\n", txpower);
>
> - return ath5k_hw_txpower(ah, channel, ee_mode, txpower, true);
> + return ath5k_hw_txpower(ah, channel, ee_mode, txpower);
> }
>
> /*************\
> @@ -3251,7 +3255,6 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> struct ieee80211_channel *curr_channel;
> int ret, i;
> u32 phy_tst1;
> - bool fast_txp;
> ret = 0;
>
> /*
> @@ -3282,17 +3285,6 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> }
>
> /*
> - * If we don't change channel/mode skip
> - * tx powertable calculation and use the
> - * cached one.
> - */
> - if ((channel->hw_value == curr_channel->hw_value) &&
> - (channel->center_freq == curr_channel->center_freq))
> - fast_txp = true;
> - else
> - fast_txp = false;
> -
> - /*
> * Set TX power
> *
> * Note: We need to do that before we set
> @@ -3300,8 +3292,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
> * properly set curve indices.
> */
> ret = ath5k_hw_txpower(ah, channel, ee_mode,
> - ah->ah_txpower.txp_max_pwr / 2,
> - fast_txp);
> + ah->ah_txpower.txp_max_pwr / 2);
> if (ret)
> return ret;
>
>
>
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick
^ permalink raw reply
* Re: Wireless channel stuck to -1 on mon0 (fix patch submission)
From: Johannes Berg @ 2010-12-21 14:39 UTC (permalink / raw)
To: John W. Linville; +Cc: Gábor Stefanik, CalimeroTeknik, linux-wireless
In-Reply-To: <20101220141134.GA10104@tuxdriver.com>
On Mon, 2010-12-20 at 09:11 -0500, John W. Linville wrote:
> On Sun, Dec 19, 2010 at 10:36:12PM +0100, Johannes Berg wrote:
> > On Sun, 2010-12-19 at 21:58 +0100, Gábor Stefanik wrote:
> > > This is a known problem, that has basically been WONTFIXed a while
> > > ago. I highly disagree with the reasoning, but the decision ultimately
> > > rests on Johannes. In the meantime, check patches.aircrack-ng.org for
> > > a workaround.
> > >
> > > Johannes: I know that you consider reporting the actual channel of the
> > > PHY to be "confusing to users" when running with multiple virtual
> > > PHYs, but apparently this is what most users expect. Perhaps it
> > > *should* be implemented after all.
> >
> > In which case it should be implemented properly, not half-baked like all
> > the patches we've seen so far.
>
> This does continue to pop-up. Do you have a link to a description
> of a proper implementation?
I don't think so -- I don't recall anyone ever asking before ;-)
FWIW, I think right now we need to simply query mac80211's oper_channel
somehow -- that'll be good enough until that goes away for real
multi-channel operation.
Using the channel that was set on the monitor interfaces like these
patches have done is obviously flawed because monitor interfaces have
absolutely no influence on the channel unless that's all there is.
johannes
^ permalink raw reply
* Re: Linux wireless DFS meeting - 2010-12-21 05:00 UTC #linux-wireless freenode
From: Luis R. Rodriguez @ 2010-12-21 14:32 UTC (permalink / raw)
To: linux-wireless, Felix Fietkau
Cc: Kathy Giori, linux-kernel, Michael Green, Amod Bodas, David Quan,
Vipin Mehta
In-Reply-To: <AANLkTikw3i29uwfp7qoejKYrJoNsGBedpO1NGo9UhmZY@mail.gmail.com>
On Tue, Dec 21, 2010 at 9:28 AM, Luis R. Rodriguez <mcgrof@gmail.com> wrote:
> IRC meeting reminder for DFS today at 9am PST time (05:00 UTC, noon
> Eastern time). The meeting will take place on irc.freenode.net on
> #linux-wireless
Correction on UTC time 17:00 UTC
Luis
^ permalink raw reply
* Re: b43 N PHY status report
From: Larry Finger @ 2010-12-21 14:30 UTC (permalink / raw)
To: David Woodhouse; +Cc: Johannes Berg, Gábor Stefanik, wireless, b43-dev
In-Reply-To: <1292923526.2577.53.camel@macbook.infradead.org>
On 12/21/2010 03:25 AM, David Woodhouse wrote:
>
> On-topic:
>
> Anyone working on or testing network device drivers should be using
> IPv6. IPv6 will exercise code paths and network behaviour that Legacy IP
> rarely does, in particular using multicast to do neighbour discovery.
> And on wireless networks when multicast will be handled differently by
> the AP, that makes more difference than on wired where it's mostly the
> MAC filters that get neglected.
>
> I've seen a number of broken drivers because their authors were only
> testing with Legacy IP and not IPv6.
>
> It's not hard to set up IPv6. Larry, if you need any pointers I'd be
> more than happy to help.
I have no problem setting it up. I disabled it mostly to reduce the number of
modules in a kernel recompile. It doesn't make much difference on either of my
multi-core boxes, but some of the lower-powered units already take hours to build.
I take your point, and will be reenabling IPv6.
Larry
^ permalink raw reply
* Linux wireless DFS meeting - 2010-12-21 05:00 UTC #linux-wireless freenode
From: Luis R. Rodriguez @ 2010-12-21 14:28 UTC (permalink / raw)
To: linux-wireless
Cc: Kathy Giori, linux-kernel, Michael Green, Amod Bodas, David Quan,
Vipin Mehta
IRC meeting reminder for DFS today at 9am PST time (05:00 UTC, noon
Eastern time). The meeting will take place on irc.freenode.net on
#linux-wireless
For details please see:
http://wireless.kernel.org/en/developers/DFS
Items I and II on the development roadmap seem to be addressed now but
would like to review it with others on IRC and see if there are any
questions, and hope to coordinate work for items 3 and 4 on the
development roadmap.
Luis
^ permalink raw reply
* Re: [PATCH] mac80211: check for CONFIG_MAC80211_LEDS in the tpt_led_trigger declaration
From: Johannes Berg @ 2010-12-21 14:07 UTC (permalink / raw)
To: luciano.coelho; +Cc: linville, linux-wireless
In-Reply-To: <1292940137-21850-1-git-send-email-luciano.coelho@nokia.com>
On Tue, 2010-12-21 at 16:02 +0200, luciano.coelho@nokia.com wrote:
> From: Luciano Coelho <luciano.coelho@nokia.com>
>
> If CONFIG_MAC80211_LEDS is not set, ieee80211_i.h was failing to compile,
> because struct led_trigger is only declared when CONFIG_LEDS_TRIGGERS is
> set.
>
> This patch adds ifdefs around the tpt_led_trigger declaration in
> ieee80211_i.h to avoid the problem.
>
> Cc: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
> ---
> net/mac80211/ieee80211_i.h | 2 ++
> 1 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
> index 0817ec6..7541d42 100644
> --- a/net/mac80211/ieee80211_i.h
> +++ b/net/mac80211/ieee80211_i.h
> @@ -631,6 +631,7 @@ enum queue_stop_reason {
> IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
> };
>
> +#ifdef CONFIG_MAC80211_LEDS
> struct tpt_led_trigger {
> struct led_trigger trig;
> char name[32];
> @@ -642,6 +643,7 @@ struct tpt_led_trigger {
> unsigned int active, want;
> bool running;
> };
> +#endif
>
> /**
> * mac80211 scan flags - currently active scan mode
^ permalink raw reply
* [PATCH] mac80211: check for CONFIG_MAC80211_LEDS in the tpt_led_trigger declaration
From: luciano.coelho @ 2010-12-21 14:02 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Luciano Coelho, Johannes Berg
From: Luciano Coelho <luciano.coelho@nokia.com>
If CONFIG_MAC80211_LEDS is not set, ieee80211_i.h was failing to compile,
because struct led_trigger is only declared when CONFIG_LEDS_TRIGGERS is
set.
This patch adds ifdefs around the tpt_led_trigger declaration in
ieee80211_i.h to avoid the problem.
Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
net/mac80211/ieee80211_i.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0817ec6..7541d42 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -631,6 +631,7 @@ enum queue_stop_reason {
IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
};
+#ifdef CONFIG_MAC80211_LEDS
struct tpt_led_trigger {
struct led_trigger trig;
char name[32];
@@ -642,6 +643,7 @@ struct tpt_led_trigger {
unsigned int active, want;
bool running;
};
+#endif
/**
* mac80211 scan flags - currently active scan mode
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH 1/2] ath9k_hw: Fix incorrect macversion and macrev checks
From: Senthil Balasubramanian @ 2010-12-21 13:36 UTC (permalink / raw)
To: Felix Fietkau
Cc: Senthilkumar Balasubramanian, linville@tuxdriver.com,
linux-wireless@vger.kernel.org
In-Reply-To: <4D0F9E4C.7090208@openwrt.org>
On Mon, Dec 20, 2010 at 11:49:56PM +0530, Felix Fietkau wrote:
> On 2010-12-20 6:37 PM, Senthil Balasubramanian wrote:
> > There are few places where we are checking for macversion and revsions
> > before RTC is powered ON. However we are reading the macversion and
> > revisions only after RTC is powered ON and so both macversion and
> > revisions are actully zero and this leads to incorrect srev checks.
> >
> > fix this by reading the macversion and revisisons even before we start
> > using them. There is no reason why should we delay reading this info
> > until RTC is powered on as this is just a register information.
> >
> > Cc: Stable Kernel <stable@kernel.org>
> > Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com>
> > ---
> > drivers/net/wireless/ath/ath9k/hw.c | 4 ++--
> > 1 files changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
> > index ddda76f..c9b7f1e 100644
> > --- a/drivers/net/wireless/ath/ath9k/hw.c
> > +++ b/drivers/net/wireless/ath/ath9k/hw.c
> > @@ -1078,13 +1078,13 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
> > return false;
> > }
> >
> > - ath9k_hw_read_revisions(ah);
> > -
> > return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
> > }
> >
> > static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
> > {
> > + ath9k_hw_read_revisions(ah);
> > +
> > if (AR_SREV_9300_20_OR_LATER(ah)) {
> > REG_WRITE(ah, AR_WA, ah->WARegVal);
> > udelay(10);
> Why re-read the revision on every reset?
yes.. not required on every reset and we can read it in __ath9k_hw_init itself
right before ath9k_hw_set_reset_reg().
I just overlooked the reset part for WARM/COLD which is mostly the case except
for ar9280 with olc and just wanted to retain how it was before for POWER_ON.
will send v2 thanks.
>
> - Felix
^ permalink raw reply
* Re: [PATCH] rtl818x: move rtl8180 and rtl8187 to separate subdirectories
From: Herton Ronaldo Krzesinski @ 2010-12-21 13:29 UTC (permalink / raw)
To: Larry Finger; +Cc: John W. Linville, linux-wireless, Hin-Tak Leung
In-Reply-To: <4D0FF4DC.4010409@lwfinger.net>
On Mon, 20 Dec 2010 18:29:16 -0600
Larry Finger <Larry.Finger@lwfinger.net> wrote:
> On 12/20/2010 02:22 PM, John W. Linville wrote:
> > These drivers share one header file, but nothing else. Worse, both
> > drivers use the rtl8225 part with different register settings. The
> > results has been some ugly naming -- let's simplify that.
> >
> > Signed-off-by: John W. Linville <linville@tuxdriver.com>
> > ---
>
> This is a good time to change this as I have heard from Realtek that their
> RTL8187SE driver that uses mac80211 is running, but not yet stable. When it is,
> a decision can be made if it should be in .../rtl818x/rtl8187/ or
> .../rtl818x/rtl8187se/.
>
> The new driver will also allow the staging driver to be removed.
Ack from me too, it stays cleaner with the change.
>
> Larry
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
[]'s
Herton
^ permalink raw reply
* Re: [PATCH 2/2] cfg80211: pass DFS region to drivers through reg_notifier()
From: Luis R. Rodriguez @ 2010-12-21 12:43 UTC (permalink / raw)
To: Johannes Berg
Cc: linville, kathy.giori, amod.bodas, david.quan, michael.green,
linux-wireless
In-Reply-To: <1292928823.3563.4.camel@jlt3.sipsolutions.net>
On Tue, Dec 21, 2010 at 5:53 AM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> On Mon, 2010-12-20 at 12:02 -0500, Luis R. Rodriguez wrote:
>> This grants drivers access to the DFS region that a
>> regulatory domain belongs to.
>>
>> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
>> ---
>> include/net/regulatory.h | 5 +++++
>> net/wireless/reg.c | 4 ++++
>> 2 files changed, 9 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/net/regulatory.h b/include/net/regulatory.h
>> index 9fcb603..3ed16c5 100644
>> --- a/include/net/regulatory.h
>> +++ b/include/net/regulatory.h
>> @@ -40,6 +40,10 @@ enum environment_cap {
>> * 99 - built by driver but a specific alpha2 cannot be determined
>> * 98 - result of an intersection between two regulatory domains
>> * 97 - regulatory domain has not yet been configured
>> + * @dfs_region: If CRDA responded with a regulatory domain that requires
>> + * DFS master operation on a known DFS region (NL80211_CFLAG_DFS_*),
>> + * dfs_region represents that region. Drivers can use this and the
>> + * @alpha2 to adjust their device's DFS parameters as they wish.
>
> The alpha2 is pretty useless -- I don't think you should advocate using
> it. I think it can even be "99" or something at this point.
The alpha2 here is for the request, not what is set though.
Luis
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox