Skip to contentSkip to conversation

Add spectral scan support for Atheros AR92xx/AR93xx

RFC In review Simon Wunderlich 7 participants 26 messages Nov 27, 2012 – Dec 17, 2012

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover Add spectral scan support for Atheros AR92xx/AR93xx

This patchset is a first request for comments for the upcoming spectral scan feature. It adds a new attribute to nl80211 to ask for a spectral scan while scanning, because we cycle through the channels anyway at this time. If enabled by the driver, spectral scan results will be collected. This feature has been enabled for AR92xx and AR93xx based chipsets. As the FFT samples are very hardware dependent, they are only provided via a debugfs file for further evaluation.

We've also written a visual evaluation program for these samples (see screenshot [1] and sourcecode [2]).

Many details are not known due to the fact that I don't have access to Atheros specifications and details. Many things are done by guessing and might be wrong. I'm therefore requesting help from Qualcomm/Atheros guys to confirm or correct my findings. Apart from that, after discussion I think we could integrate this patchset to allow other people to work on this as well, even if it is experimental now.

Questions from my end:
1. There are many TODOs/Comments in the patches regarding details, please answer if you can. :)
2. The output format is very Atheros-dependent. If my finding that byte n-4 is some kind of offset/exponent, I'd integrate this in the debugfs output as well
3. The data length varies pretty much, there might be some false positives/PHY errors which are not FFT data - what should be the correct length?
4. Is there any special handling for HT40? At least the proprietary driver symbol names suggest so [3]

(Possible) further work:
1. Integrate this patchset, confirm/correct findings
2. If anyone would like: Atheros proprietary driver seems to support some kind of classification [3] (is this microwave? cordless phone? whatever?)
3. If other devices also offer spectral scan support: define a common interface to use it (not debugfs).

[1] http://packetmixer.de/sdl_spec_scan2.png
[2] https://github.com/simonwunderlich/FFT_eval
[3] http://www.wehavemorefun.de/fritzbox/Ath_spectral.ko#Symbole

Simon Wunderlich (3):
nl80211: add spec scan flag
mac80211: add spectral_scan function, hook it up in scanning
ath9k: add spectral scan feature

 drivers/net/wireless/ath/ath9k/ar9002_phy.c |   37 +++++++++++++
 drivers/net/wireless/ath/ath9k/ar9003_phy.c |   37 +++++++++++++
 drivers/net/wireless/ath/ath9k/ath9k.h      |   12 ++++
 drivers/net/wireless/ath/ath9k/debug.c      |   79 +++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/hw.h         |    4 ++
 drivers/net/wireless/ath/ath9k/init.c       |   13 +++++
 drivers/net/wireless/ath/ath9k/mac.h        |    7 ++-
 drivers/net/wireless/ath/ath9k/main.c       |   29 ++++++++++
 drivers/net/wireless/ath/ath9k/recv.c       |   34 ++++++++++++
 include/net/cfg80211.h                      |    2 +
 include/net/mac80211.h                      |    6 ++
 include/uapi/linux/nl80211.h                |    5 ++
 net/mac80211/driver-ops.h                   |   10 ++++
 net/mac80211/scan.c                         |    3 +
 net/mac80211/trace.h                        |    5 ++
 net/wireless/nl80211.c                      |    3 +
 16 files changed, 284 insertions(+), 2 deletions(-)
Signature · 1 line
1.7.10.4
#1 lore raw

RFC 1/3 nl80211: add spec scan flag

This flag indicates that a spectrum scan is requested, if supported.

---
 include/net/cfg80211.h       |    2 ++
 include/uapi/linux/nl80211.h |    5 +++++
 net/wireless/nl80211.c       |    3 +++
 3 files changed, 10 insertions(+)
include/net/cfg80211.h +2 -0
index 8a1aec5..ce19e59 100644
@@ -1009,6 +1009,7 @@ struct cfg80211_ssid {
  * @wdev: the wireless device to scan for
  * @aborted: (internal) scan request was notified as aborted
  * @no_cck: used to send probe requests at non CCK rate in 2GHz band
+ * @spec_scan: indicates that spectral scan is requested while scanning.
  */
 struct cfg80211_scan_request {
 	struct cfg80211_ssid *ssids;
@@ -1027,6 +1028,7 @@ struct cfg80211_scan_request {
 	unsigned long scan_start;
 	bool aborted;
 	bool no_cck;
+	bool spec_scan;
 
 	/* keep last */
 	struct ieee80211_channel *channels[0];
include/uapi/linux/nl80211.h +5 -0
index 1a9a819..7da847f 100644
@@ -1292,6 +1292,9 @@ enum nl80211_commands {
  *
  * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32)
  *
+ * @NL80211_ATTR_TX_SPEC_SCAN: Indicates whether a spectrum scan should be
+ *	performed while scanning. Used with %NL80211_CMD_TRIGGER_SCAN command.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1555,6 +1558,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_SCAN_FLAGS,
 
+	NL80211_ATTR_TX_SPEC_SCAN,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
net/wireless/nl80211.c +3 -0
index 4c427fa..2524509 100644
@@ -337,6 +337,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
 	[NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
 	[NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
+	[NL80211_ATTR_TX_SPEC_SCAN] = { .type = NLA_FLAG },
 	[NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
 	[NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
 	[NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
@@ -4396,6 +4397,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 
 	request->no_cck =
 		nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
+	request->spec_scan =
+		nla_get_flag(info->attrs[NL80211_ATTR_TX_SPEC_SCAN]);
 
 	request->wdev = wdev;
 	request->wiphy = &rdev->wiphy;
Signature · 1 line
1.7.10.4
maintainer
#2 lore raw

RFC 1/3 nl80211: add spec scan flag

Quoted 1 line · Simon Wunderlich

This flag indicates that a spectrum scan is requested, if supported.

That "if supported" here is pretty problematic. There's no way to know. Feature flag maybe?

Also, there are scan flags now. However, I don't see that this should (ab)use the scan function. It doesn't seem likely that you want to do this while you're sending probe requests, etc. OTOH, it seems likely you'd want identical dwell times on all channels to have comparable values, which isn't the case here.

I really think you need to decouple the API for this from scanning.

johannes

maintainer
#3 lore raw

RFC 1/3 nl80211: add spec scan flag

Quoted 6 lines · Johannes Berg
Quoted 1 line · Simon Wunderlich

This flag indicates that a spectrum scan is requested, if supported.

That "if supported" here is pretty problematic. There's no way to know. Feature flag maybe?

Quoted 7 lines

Also, there are scan flags now. However, I don't see that this should (ab)use the scan function. It doesn't seem likely that you want to do this while you're sending probe requests, etc. OTOH, it seems likely you'd want identical dwell times on all channels to have comparable values, which isn't the case here.

I really think you need to decouple the API for this from scanning.

And then you can also define APIs to get the data out. While I realize that the data is implementation-dependent, you could have an enum that indicates the data format and describes it:

@NL80211_SPECTRAL_DATA_ATHEROS: u8 rssi,ext_rssi,noise,fft_data[] ...

enum nl80211_spectral_data {
	NL80211_SPECTRAL_DATA_ATHEROS,
	...
};

Then you can define a function to send the data to the userspace socket that asked for it (yes, if you have a separate command you can send it only to that app... wohoo! :P ) and don't even have to store it in the kernel...

So bottom line is that I think there are two choices:
1) for a proof of concept, implement it in debugfs only, in ath9k only, with e.g. a debugfs file that sets a flag that then triggers the spectral scan when you do a scan (using sw_scan_start, config hooks) --> no need to modify nl80211 at all
2) implement some well-defined API in nl80211, but don't tie it to scanning or a debugfs implementation of getting the data out, with versioning of the FFT data packets etc. so it can be updated later without breaking everything

This hybrid isn't a good approach at all.

johannes

#4 lore raw

RFC 1/3 nl80211: add spec scan flag

Hello Johannes,

Quoted 6 lines · Johannes Berg
Quoted 5 lines · Johannes Berg
Quoted 1 line · Simon Wunderlich

This flag indicates that a spectrum scan is requested, if supported.

That "if supported" here is pretty problematic. There's no way to know. Feature flag maybe?

Hmm, I could certainly add a WIPHY_FLAG for that.

Quoted 6 lines
Quoted 6 lines

Also, there are scan flags now. However, I don't see that this should (ab)use the scan function. It doesn't seem likely that you want to do this while you're sending probe requests, etc. OTOH, it seems likely you'd want identical dwell times on all channels to have comparable values, which isn't the case here.

The times are not a big problem - at least for now, the spectral scan is only done for a very short time [tm] when the channel is changed.

The main reason why I wanted to use this function is that it can be used while operation, that is sending power save, forbidding payload tx, etc.

Quoted 14 lines
Quoted 2 lines

I really think you need to decouple the API for this from scanning.

And then you can also define APIs to get the data out. While I realize that the data is implementation-dependent, you could have an enum that indicates the data format and describes it:

@NL80211_SPECTRAL_DATA_ATHEROS: u8 rssi,ext_rssi,noise,fft_data[] ...

enum nl80211_spectral_data {
	NL80211_SPECTRAL_DATA_ATHEROS,
	...
};
Quoted 4 lines

Then you can define a function to send the data to the userspace socket that asked for it (yes, if you have a separate command you can send it only to that app... wohoo! :P ) and don't even have to store it in the kernel...

Calling the spectral scan and RX the FFT data are different things, but yes, having everything in one application would be much better than "trigger at X, receive at Y".

Quoted 6 lines

So bottom line is that I think there are two choices:
1) for a proof of concept, implement it in debugfs only, in ath9k only, with e.g. a debugfs file that sets a flag that then triggers the spectral scan when you do a scan (using sw_scan_start, config hooks) --> no need to modify nl80211 at all

So the idea is something like:
* open debugfs-file (e.g. with cat)
* start scan "normally", without any flags
* read debugfs results, and close it

Mhm, this is definitely possible, although not too beautiful as well. :)

It seems there is no way to trigger a scan from within ath9k/debugfs, right?

sw_scan_start() is currently undefined in ath9k, but we could add that. By "config hooks" you mean the general config driver call to set the channel etc?

I could also cycle channels within ath9k, but the main problem I see is that I can't turn off TX/go into power save mode from the driver, or would you see anything feasible?

Quoted 4 lines

2) implement some well-defined API in nl80211, but don't tie it to scanning or a debugfs implementation of getting the data out, with versioning of the FFT data packets etc. so it can be updated later without breaking everything

I guess if we implement this in iw, this would be done similarly to scan, e.g. trigger the scan and wait on the socket for results? Or would we use events instead?

This would roughly mean:
* duplicate the mac80211 scan part for spectral scan to cycle channels/be quite while doing this
* duplicate iw scan (at least some parts), the interface could look very similar:
trigger scan, on receive scan results on another socket, wait for completion (although iw still has this "warning, it's racy" thing inside. :] )

This looks like a whole lot of work, and would duplicate some code which we need for scan and spec_scan (at least it looks like it). On the plus side, this would be easier to change in the future (e.g. adding parameters for spec scan, etc).

Quoted 2 lines

This hybrid isn't a good approach at all.

I don't like hybrid approach as well, but hoped that it could be "good enough" for a proof of concept. If someone ever implements pattern matching, the interface will probably change again as well.

Maybe you could find this idea acceptable: Keep on using the scan command plus some flag/and or attribute, but send "FFT result" as events or within the scan socket instead of using debugfs. What do you think?

Thanks for your review and suggestions! I'd like to discuss the alternatives to fully understand them and then choose one. :)

Cheers,
Simon
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
Url : http://lists.ath9k.org/pipermail/ath9k-devel/attachments/20121128/2405002c/attachment.pgp

#5 lore raw

RFC 1/3 nl80211: add spec scan flag

Quoted 2 lines · Simon Wunderlich

The main reason why I wanted to use this function is that it can be used while operation, that is sending power save, forbidding payload tx, etc.

Have you looked at the remain-on-channel commands?

Quoted 2 lines

It seems there is no way to trigger a scan from within ath9k/debugfs, right?

I don't think there is nor that there should be.. Do you really need scan operating for this? I would use remain-on-channel commands from a user space app to go through the channels you want to analyze.

Quoted 5 lines

I could also cycle channels within ath9k, but the main problem I see is that
I can't turn off TX/go into power save mode from the driver, or would you see
anything feasible?

Remain-on-channel should take care of that, but yes, that would not be triggered from ath9k, but from user space.

- Jouni

#6 lore raw

RFC 1/3 nl80211: add spec scan flag

Hey Jouni,

Quoted 10 lines · Jouni
Quoted 2 lines · Simon Wunderlich

The main reason why I wanted to use this function is that it can be used while operation, that is sending power save, forbidding payload tx, etc.

Have you looked at the remain-on-channel commands?

TBH, today was the first time I've had a more close look. :)

Quoted 7 lines
Quoted 2 lines

It seems there is no way to trigger a scan from within ath9k/debugfs, right?

I don't think there is nor that there should be.. Do you really need scan operating for this? I would use remain-on-channel commands from a user space app to go through the channels you want to analyze.

Hmm, that would be possible as well ... Using the scan function is very convenient as I don't have to think about cycling, channel lists, etc. But putting more control to userspace is also possible, if we can ask the driver to just have a "quick spectral peek" on another channel.

Anyway, you'd suggest to use the NL80211 remain on channel command for that? Or add a new "spectral scan" nl80211 command to do a spectral scan on this (or multiple) channels, and use the various functions from mac80211/offchannel.c?

BTW, is there any limitation to remain on channel commands, like will they work on AP ifaces, Ad-Hoc ifaces, MultiSSID in general, etc?

Quoted 8 lines
Quoted 5 lines

I could also cycle channels within ath9k, but the main problem I see is that
I can't turn off TX/go into power save mode from the driver, or would you see
anything feasible?

Remain-on-channel should take care of that, but yes, that would not be triggered from ath9k, but from user space.

That sounds good. :)

Thanks for the hint!
Simon
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
Url : http://lists.ath9k.org/pipermail/ath9k-devel/attachments/20121128/84b18988/attachment.pgp

#7 lore raw

RFC 1/3 nl80211: add spec scan flag

Quoted 4 lines · Simon Wunderlich

Hmm, that would be possible as well ... Using the scan function is very convenient as I don't have to think about cycling, channel lists, etc. But putting more control to userspace is also possible, if we can ask the driver to just have a "quick spectral peek" on another channel.

Well, you may not need to think about channel cycling etc. for scan operations, but you won't get much control over the timing or dwell duration for that matter. Remain-on-channel gives you that.

Quoted 2 lines

Anyway, you'd suggest to use the NL80211 remain on channel command for that?

Yes.

Quoted 3 lines

Or add a new "spectral scan" nl80211 command to do a spectral scan on this (or multiple) channels, and use the various functions from mac80211/offchannel.c?

I would rather add a flag to the existing r-o-c command to indicate that spectral scan functionality is to be enabled (well, assuming Johannes is fine with this).

Quoted 2 lines

BTW, is there any limitation to remain on channel commands, like will they work on AP ifaces, Ad-Hoc ifaces, MultiSSID in general, etc?

I hope not. There may be some practical issues with not all drivers supporting this, but remain-on-channel is the mechanism we use for supporting concurrent operations (e.g., P2P negotiations or GAS/ANQP) and making this work in all combinations would be important regardless.

- Jouni

maintainer
#8 lore raw

RFC 1/3 nl80211: add spec scan flag

Quoted 6 lines
Quoted 3 lines

Anyway, you'd suggest to use the NL80211 remain on channel command for that?

Yes.

Quoted 7 lines
Quoted 3 lines

Or add a new "spectral scan" nl80211 command to do a spectral scan on this (or multiple) channels, and use the various functions from mac80211/offchannel.c?

I would rather add a flag to the existing r-o-c command to indicate that spectral scan functionality is to be enabled (well, assuming Johannes is fine with this).

Ultimately I don't really care all that much whether it's ROC-like or SCAN-like, though it didn't seem like the timing mattered because all the data was just collected inside the callback while it was running, i.e. synchronously, and thus extended the scan timing?

For ROC I guess an argument could be made that it could just be a flag, for SCAN I don't think so since none of the other scan functionality applies. As far as the implementation is concerned, I don't really care, but I do want to keep the userspace API clean.

scan could be more efficient since it doesn't always go back to the same channel and can do multiple in a row, unlike ROC.

Quoted 7 lines
Quoted 2 lines

BTW, is there any limitation to remain on channel commands, like will they work on AP ifaces, Ad-Hoc ifaces, MultiSSID in general, etc?

I hope not. There may be some practical issues with not all drivers supporting this, but remain-on-channel is the mechanism we use for supporting concurrent operations (e.g., P2P negotiations or GAS/ANQP) and making this work in all combinations would be important regardless.

FWIW, right now our plan for iwlwifi is to only really support it with the P2P Device wdev, but I'm not sure what implications that has in terms of support for GAS/ANQP etc. We might have to revisit that.

Maybe we should start advertising where it's supported so wpa_s/hostapd can disable/enable features appropriately?

johannes

#9 lore raw

RFC 1/3 nl80211: add spec scan flag

Quoted 10 lines · Johannes Berg
Quoted 9 lines
Quoted 3 lines

BTW, is there any limitation to remain on channel commands, like will they
work on AP ifaces, Ad-Hoc ifaces, MultiSSID in general, etc?

I hope not. There may be some practical issues with not all drivers supporting this, but remain-on-channel is the mechanism we use for supporting concurrent operations (e.g., P2P negotiations or GAS/ANQP) and
making this work in all combinations would be important regardless.

Quoted 3 lines

FWIW, right now our plan for iwlwifi is to only really support it with the P2P Device wdev, but I'm not sure what implications that has in terms of support for GAS/ANQP etc. We might have to revisit that.

GAS/ANQP is pre-association if that makes any difference. Anyway, quite a few new things will start depending on off channel Action frames and everything I'm working on this area will most likely be using r-o-c..

Quoted 2 lines

Maybe we should start advertising where it's supported so wpa_s/hostapd can disable/enable features appropriately?

Yeah, sounds reasonable. I guess you could also reject the r-o-c command, but it is cleaner if this can be determined beforehand.

- Jouni

maintainer
#10 lore raw

RFC 1/3 nl80211: add spec scan flag

Quoted 7 lines · Jouni
Quoted 3 lines

FWIW, right now our plan for iwlwifi is to only really support it with the P2P Device wdev, but I'm not sure what implications that has in terms of support for GAS/ANQP etc. We might have to revisit that.

GAS/ANQP is pre-association if that makes any difference. Anyway, quite a few new things will start depending on off channel Action frames and everything I'm working on this area will most likely be using r-o-c..

Yes, pre-association might make a difference. I think it's entirely reasonable to implement it all using ROC, I just don't know whether or not we can support it right now out of the box.

Quoted 5 lines
Quoted 2 lines

Maybe we should start advertising where it's supported so wpa_s/hostapd can disable/enable features appropriately?

Yeah, sounds reasonable. I guess you could also reject the r-o-c command, but it is cleaner if this can be determined beforehand.

We do that today. Actually, in the current driver we do allow it but it's rather messy so I might remove the ability once we have P2P Device support, not sure. In the future we'll have it only on P2P Device, though making it work on unassociated interfaces should not be a big issue.

johannes

maintainer
#11 lore raw

RFC 1/3 nl80211: add spec scan flag

In reply to Simon Wunderlich
Quoted 5 lines
Quoted 3 lines
Quoted 3 lines

That "if supported" here is pretty problematic. There's no way to know. Feature flag maybe?

Hmm, I could certainly add a WIPHY_FLAG for that.

nl80211 feature flag would be better

Quoted 11 lines
Quoted 5 lines
Quoted 5 lines

Also, there are scan flags now. However, I don't see that this should (ab)use the scan function. It doesn't seem likely that you want to do this while you're sending probe requests, etc. OTOH, it seems likely you'd want identical dwell times on all channels to have comparable values, which isn't the case here.

The times are not a big problem - at least for now, the spectral scan is only done for a very short time [tm] when the channel is changed.

The main reason why I wanted to use this function is that it can be used while operation, that is sending power save, forbidding payload tx, etc.

That's not an argument for using the scan API. That might be an argument for piggy-backing on the scan *implementation*, but that's an orthogonal issue. Note how I didn't comment on patch 2 -- I do think piggy-backing on the scan implementation would be acceptable.

Quoted 6 lines
Quoted 5 lines

So bottom line is that I think there are two choices:
1) for a proof of concept, implement it in debugfs only, in ath9k only, with e.g. a debugfs file that sets a flag that then triggers the spectral scan when you do a scan (using sw_scan_start, config hooks) --> no need to modify nl80211 at all

Quoted 8 lines

So the idea is something like:
* open debugfs-file (e.g. with cat)
* start scan "normally", without any flags
* read debugfs results, and close it

Mhm, this is definitely possible, although not too beautiful as well. :)

It seems there is no way to trigger a scan from within ath9k/debugfs, right?

No.

Quoted 3 lines

sw_scan_start() is currently undefined in ath9k, but we could add that. By "config hooks" you mean the general config driver call to set the channel etc?

I meant to trigger the data collection there.

Quoted 3 lines

I could also cycle channels within ath9k, but the main problem I see is that I can't turn off TX/go into power save mode from the driver, or would you see anything feasible?

Triggering it all from the driver doesn't seem possible, no. You could have the function take effect on the next scan, but it's still kinda hybrid. However, it wouldn't "pollute" nl80211 that way.

Quoted 5 lines
Quoted 4 lines

2) implement some well-defined API in nl80211, but don't tie it to scanning or a debugfs implementation of getting the data out, with versioning of the FFT data packets etc. so it can be updated later without breaking everything

Quoted 7 lines

I guess if we implement this in iw, this would be done similarly to scan, e.g. trigger the scan and wait on the socket for results? Or would we use events instead?

This would roughly mean:
* duplicate the mac80211 scan part for spectral scan to cycle channels/be quite while doing this

No, I didn't say this. I said the API should be different, the implementation in mac80211 could very well just be "either going to send probes & wait, or collect spectral scan data and continue to the next channel"

Quoted 3 lines

* duplicate iw scan (at least some parts), the interface could look very similar:
trigger scan, on receive scan results on another socket, wait for completion (although iw still has this "warning, it's racy" thing inside. :] )

Actually you need a separate application anyway, to interpret the results, so that application would
* open a socket
* send the spectral scan command
* read the results on the socket

johannes

#12 lore raw

RFC 1/3 nl80211: add spec scan flag

Quoted 8 lines · Johannes Berg
Quoted 5 lines
Quoted 3 lines
Quoted 3 lines

That "if supported" here is pretty problematic. There's no way to know. Feature flag maybe?

Hmm, I could certainly add a WIPHY_FLAG for that.

nl80211 feature flag would be better

OK, that would work too. Just that there are some Atheros Chips which don't support spectral scan, like AR9160, but are supported by ath9k. I guess I'd just set the feature if the chip revision is supported, from within ath9k.

Quoted 9 lines
Quoted 9 lines
Quoted 5 lines
Quoted 5 lines

Also, there are scan flags now. However, I don't see that this should (ab)use the scan function. It doesn't seem likely that you want to do this while you're sending probe requests, etc. OTOH, it seems likely you'd want identical dwell times on all channels to have comparable values, which isn't the case here.

The times are not a big problem - at least for now, the spectral scan is only done for a very short time [tm] when the channel is changed.

Quoted 7 lines
Quoted 2 lines

The main reason why I wanted to use this function is that it can be used while operation, that is sending power save, forbidding payload tx, etc.

That's not an argument for using the scan API. That might be an argument for piggy-backing on the scan *implementation*, but that's an orthogonal issue. Note how I didn't comment on patch 2 -- I do think piggy-backing on the scan implementation would be acceptable.

OK

Quoted 24 lines
Quoted 7 lines
Quoted 6 lines

So bottom line is that I think there are two choices:
1) for a proof of concept, implement it in debugfs only, in ath9k only, with e.g. a debugfs file that sets a flag that then triggers the spectral scan when you do a scan (using sw_scan_start, config hooks) --> no need to modify nl80211 at all

Quoted 8 lines

So the idea is something like:
* open debugfs-file (e.g. with cat)
* start scan "normally", without any flags
* read debugfs results, and close it

Mhm, this is definitely possible, although not too beautiful as well. :)

It seems there is no way to trigger a scan from within ath9k/debugfs, right?

No.

Quoted 3 lines

sw_scan_start() is currently undefined in ath9k, but we could add that. By "config hooks" you mean the general config driver call to set the channel etc?

I meant to trigger the data collection there.

Quoted 8 lines
Quoted 3 lines

I could also cycle channels within ath9k, but the main problem I see is that I can't turn off TX/go into power save mode from the driver, or would you see anything feasible?

Triggering it all from the driver doesn't seem possible, no. You could have the function take effect on the next scan, but it's still kinda hybrid. However, it wouldn't "pollute" nl80211 that way.

OK, so it could look like:

echo start > debugfs/ath9k/spectral_scan
iw dev wlan0 scan
cat debugfs/ath9k/spectral_scan
[... get output ...]
echo stop > debugfs/ath9k/spectral_scan

yeah, that's still hybrid, but still simple.

Quoted 22 lines
Quoted 5 lines
Quoted 4 lines

2) implement some well-defined API in nl80211, but don't tie it to scanning or a debugfs implementation of getting the data out, with versioning of the FFT data packets etc. so it can be updated later without breaking everything

Quoted 7 lines

I guess if we implement this in iw, this would be done similarly to scan, e.g. trigger the scan and wait on the socket for results? Or would we use events instead?

This would roughly mean:
* duplicate the mac80211 scan part for spectral scan to cycle channels/be quite while doing this

No, I didn't say this. I said the API should be different, the implementation in mac80211 could very well just be "either going to send probes & wait, or collect spectral scan data and continue to the next channel"

Quoted 3 lines

* duplicate iw scan (at least some parts), the interface could look very similar:
trigger scan, on receive scan results on another socket, wait for completion (although iw still has this "warning, it's racy" thing inside. :] )

Quoted 5 lines

Actually you need a separate application anyway, to interpret the results, so that application would
* open a socket
* send the spectral scan command
* read the results on the socket

Ah OK, so we would have a new nl80211 spectral scan command which then calls the mac80211/scan stuff, but with special flags which the normal scan wouldn't do. It could then return the results, and the current scan command wouldn't be harmed. I hope I got this right? :)

Also, putting all this into iw to dump the raw data would be feasible, no? Right now I'm dumping the data on some AP, but display it on another computer (with a screen :] ), so this intermediate step is needed anyways.

Actually, the ath9k-only way seems to be faster for now. I'm not sure about the data interpretation (offset/exponents etc), and I'd like to have this confirmed/corrected before exporting results via nl80211 - I don't want to change the data format all the time. Maybe some ath9k fellow can comment on that, or if they like the debugfs-only idea. :)

Thanks again,
Simon
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
Url : http://lists.ath9k.org/pipermail/ath9k-devel/attachments/20121128/c329a1e6/attachment-0001.pgp

#13 lore raw

RFC 2/3 mac80211: add spectral_scan function, hook it up in scanning

In reply to Simon Wunderlich

Add spectral_scan function to driver functions, and hook it up in the scanning code.

Using the spectral scan from within the scan function has the charme that it already does all the channel surfing for us.

---
 include/net/mac80211.h    |    6 ++++++
 net/mac80211/driver-ops.h |   10 ++++++++++
 net/mac80211/scan.c       |    3 +++
 net/mac80211/trace.h      |    5 +++++
 4 files changed, 24 insertions(+)
include/net/mac80211.h +6 -0
index e1293c7..8104b7d 100644
@@ -2428,6 +2428,10 @@ enum ieee80211_rate_control_changed {
  * @restart_complete: Called after a call to ieee80211_restart_hw(), when the
  *	reconfiguration has completed. This can help the driver implement the
  *	reconfiguration step. This callback may sleep.
+ *
+ * @spectral_scan: Asks the driver to perform a spectral scan on the currently
+ *      selected channel. Results are stored in the drivers internal structures
+ *      currently.
  */
 struct ieee80211_ops {
 	void (*tx)(struct ieee80211_hw *hw,
@@ -2602,6 +2606,8 @@ struct ieee80211_ops {
 				     struct ieee80211_chanctx_conf *ctx);
 
 	void (*restart_complete)(struct ieee80211_hw *hw);
+
+	void	(*spectral_scan)(struct ieee80211_hw *hw);
 };
 
 /**
net/mac80211/driver-ops.h +10 -0
index 68c27aa..df6d582 100644
@@ -1004,4 +1004,14 @@ static inline void drv_restart_complete(struct ieee80211_local *local)
 	trace_drv_return_void(local);
 }
 
+static inline void drv_spectral_scan(struct ieee80211_local *local)
+{
+	might_sleep();
+
+	trace_drv_spectral_scan(local);
+	if (local->ops->spectral_scan)
+		local->ops->spectral_scan(&local->hw);
+	trace_drv_return_void(local);
+}
+
 #endif /* __MAC80211_DRIVER_OPS */
net/mac80211/scan.c +3 -0
index 8e9bb168..cd8a17b 100644
@@ -665,6 +665,9 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
 		return;
 	}
 
+	if (local->scan_req->spec_scan && local->ops->spectral_scan)
+		drv_spectral_scan(local);
+
 	/*
 	 * Probe delay is used to update the NAV, cf. 11.1.3.2.2
 	 * (which unfortunately doesn't say _why_ step a) is done,
net/mac80211/trace.h +5 -0
index e9579b7..7efd325 100644
@@ -1421,6 +1421,11 @@ DEFINE_EVENT(local_only_evt, drv_restart_complete,
 	TP_ARGS(local)
 );
 
+DEFINE_EVENT(local_only_evt, drv_spectral_scan,
+	TP_PROTO(struct ieee80211_local *local),
+	TP_ARGS(local)
+);
+
 /*
  * Tracing for API calls that drivers call.
  */
Signature · 1 line
1.7.10.4
#14 lore raw

RFC 3/3 ath9k: add spectral scan feature

In reply to Simon Wunderlich

Adds the spectral scan feature for ath9k. AR92xx and AR93xx chips are supported for now. The spectral scan is triggered within a channel scan from mac80211, results can be gathered via debugfs.

---
 drivers/net/wireless/ath/ath9k/ar9002_phy.c |   37 +++++++++++++
 drivers/net/wireless/ath/ath9k/ar9003_phy.c |   37 +++++++++++++
 drivers/net/wireless/ath/ath9k/ath9k.h      |   12 ++++
 drivers/net/wireless/ath/ath9k/debug.c      |   79 +++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/hw.h         |    4 ++
 drivers/net/wireless/ath/ath9k/init.c       |   13 +++++
 drivers/net/wireless/ath/ath9k/mac.h        |    7 ++-
 drivers/net/wireless/ath/ath9k/main.c       |   29 ++++++++++
 drivers/net/wireless/ath/ath9k/recv.c       |   34 ++++++++++++
 9 files changed, 250 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath9k/ar9002_phy.c +37 -0
index 846dd79..9d8199d 100644
@@ -555,6 +555,42 @@ static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah,
 	REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
 }
 
+void ar9002_hw_spectral_scan(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA);
+
+	/* NOTE: this will generate a few samples ... lacking documentation,
+	 * I'm not really sure what these parameters mean.
+	 */
+	REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
+	REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+		    AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
+	REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+		      AR_PHY_SPECTRAL_SCAN_COUNT, 8);
+	REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+		      AR_PHY_SPECTRAL_SCAN_PERIOD, 0xF);
+	REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+		      AR_PHY_SPECTRAL_SCAN_FFT_PERIOD, 0xFF);
+
+	/* Activate spectral scan */
+	REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+		    AR_PHY_SPECTRAL_SCAN_ACTIVE);
+
+	/* Poll for spectral scan complete */
+	if (!ath9k_hw_wait(ah, AR_PHY_SPECTRAL_SCAN,
+			   AR_PHY_SPECTRAL_SCAN_ACTIVE,
+			   0, AH_WAIT_TIMEOUT)) {
+		ath_err(common, "spectral scan wait failed\n");
+		return;
+	}
+
+	/* Disable spectral scan */
+	REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+		    AR_PHY_SPECTRAL_SCAN_ENABLE);
+}
+
 void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
 {
 	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
@@ -571,6 +607,7 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
 
 	ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get;
 	ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set;
+	ops->spectral_scan = ar9002_hw_spectral_scan;
 
 	ar9002_hw_set_nf_limits(ah);
 }
drivers/net/wireless/ath/ath9k/ar9003_phy.c +37 -0
index ce19c09..c79d701 100644
@@ -1450,6 +1450,42 @@ set_rfmode:
 	return 0;
 }
 
+void ar9003_hw_spectral_scan(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA);
+
+	/* NOTE: this will generate a few samples ... lacking documentation,
+	 * I'm not really sure what these parameters mean.
+	 */
+	REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
+	REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+		    AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
+	REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+		      AR_PHY_SPECTRAL_SCAN_COUNT, 8);
+	REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+		      AR_PHY_SPECTRAL_SCAN_PERIOD, 0xF);
+	REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+		      AR_PHY_SPECTRAL_SCAN_FFT_PERIOD, 0xFF);
+
+	/* Activate spectral scan */
+	REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+		    AR_PHY_SPECTRAL_SCAN_ACTIVE);
+
+	/* Poll for spectral scan complete */
+	if (!ath9k_hw_wait(ah, AR_PHY_SPECTRAL_SCAN,
+			   AR_PHY_SPECTRAL_SCAN_ACTIVE,
+			   0, AH_WAIT_TIMEOUT)) {
+		ath_err(common, "spectral scan wait failed\n");
+		return;
+	}
+
+	/* Disable spectral scan */
+	REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+		    AR_PHY_SPECTRAL_SCAN_ENABLE);
+}
+
 void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
 {
 	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
@@ -1483,6 +1519,7 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
 	ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
 	ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
 	ops->antctrl_shared_chain_lnadiv = ar9003_hw_antctrl_shared_chain_lnadiv;
+	ops->spectral_scan = ar9003_hw_spectral_scan;
 
 	ar9003_hw_set_nf_limits(ah);
 	ar9003_hw_set_radar_conf(ah);
drivers/net/wireless/ath/ath9k/ath9k.h +12 -0
index 80bab1b..3a7789a 100644
@@ -738,6 +738,8 @@ struct ath_softc {
 	u8 ant_tx, ant_rx;
 	struct dfs_pattern_detector *dfs_detector;
 	u32 wow_enabled;
+	struct list_head fft_list;
+	int fft_list_n;
 
 #ifdef CONFIG_PM_SLEEP
 	atomic_t wow_got_bmiss_intr;
@@ -746,6 +748,16 @@ struct ath_softc {
 #endif
 };
 
+struct fft_sample {
+	struct list_head list;
+	u16 freq;
+	u8 rssi;
+	u8 ext_rssi;
+	u8 noise;
+	u8 *data;
+	s16 size;
+};
+
 void ath9k_tasklet(unsigned long data);
 int ath_cabq_update(struct ath_softc *);
 
drivers/net/wireless/ath/ath9k/debug.c +79 -0

91 lines not on this page · raw message

drivers/net/wireless/ath/ath9k/hw.h +4 -0
index 3636dab..7f5a917 100644
@@ -20,6 +20,7 @@
 #include <linux/if_ether.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/list.h>
 
 #include "mac.h"
 #include "ani.h"
@@ -666,6 +667,8 @@ struct ath_hw_private_ops {
  *
  * @config_pci_powersave:
  * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
+ *
+ * @spectral_scan: initiate a spectral scan on the current channel
  */
 struct ath_hw_ops {
 	void (*config_pci_powersave)(struct ath_hw *ah,
@@ -686,6 +689,7 @@ struct ath_hw_ops {
 	void (*antdiv_comb_conf_set)(struct ath_hw *ah,
 			struct ath_hw_antcomb_conf *antconf);
 	void (*antctrl_shared_chain_lnadiv)(struct ath_hw *hw, bool enable);
+	void (*spectral_scan)(struct ath_hw *ah);
 };
 
 struct ath_nf_limits {
drivers/net/wireless/ath/ath9k/init.c +13 -0
index 80cae53..e4384a8 100644
@@ -528,6 +528,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
 	sc->sc_ah = ah;
 
 	sc->dfs_detector = dfs_pattern_detector_init(NL80211_DFS_UNSET);
+	INIT_LIST_HEAD(&sc->fft_list);
+	sc->fft_list_n = 0;
 
 	if (!pdata) {
 		ah->ah_flags |= AH_USE_EEPROM;
@@ -878,6 +880,17 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
 		if (ATH_TXQ_SETUP(sc, i))
 			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
 
+	while (!list_empty(&sc->fft_list)) {
+		struct fft_sample *fft_sample;
+		fft_sample = list_first_entry(&sc->fft_list,
+					      struct fft_sample,
+					      list);
+		list_del(&fft_sample->list);
+		kfree(fft_sample->data);
+		kfree(fft_sample);
+	}
+
+	INIT_LIST_HEAD(&sc->fft_list);
 	ath9k_hw_deinit(sc->sc_ah);
 	if (sc->dfs_detector != NULL)
 		sc->dfs_detector->exit(sc->dfs_detector);
drivers/net/wireless/ath/ath9k/mac.h +5 -2
index 4a745e6..5cad975 100644
@@ -225,8 +225,11 @@ enum ath9k_phyerr {
 	ATH9K_PHYERR_HT_CRC_ERROR         = 34,
 	ATH9K_PHYERR_HT_LENGTH_ILLEGAL    = 35,
 	ATH9K_PHYERR_HT_RATE_ILLEGAL      = 36,
-
-	ATH9K_PHYERR_MAX                  = 37,
+	ATH9K_PHYERR_FFT_REPORT		  = 38, /* can anyone with the specs
+						 * confirm this please?
+						 * Obviously AR9003 only.
+						 */
+	ATH9K_PHYERR_MAX                  = 39,
 };
 
 struct ath_desc {
drivers/net/wireless/ath/ath9k/main.c +29 -0
index 0653dbc..8f64415 100644
@@ -2365,6 +2365,33 @@ static void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled)
 
 #endif
 
+static void ath9k_spectral_scan(struct ieee80211_hw *hw)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	u32 rxfilter;
+
+	if (!ath9k_hw_ops(ah)->spectral_scan) {
+		ath_err(common, "spectrum analyzer not implemented on this hardware\n");
+		return;
+	}
+
+	ath9k_ps_wakeup(sc);
+	rxfilter = ath9k_hw_getrxfilter(ah);
+	ath9k_hw_setrxfilter(ah, rxfilter |
+				 ATH9K_RX_FILTER_PHYRADAR |
+				 ATH9K_RX_FILTER_PHYERR);
+	ath9k_ps_restore(sc);
+
+	ath9k_hw_ops(ah)->spectral_scan(ah);
+
+	/* restore rxfilter */
+	ath9k_ps_wakeup(sc);
+	ath9k_hw_setrxfilter(sc->sc_ah, rxfilter);
+	ath9k_ps_restore(sc);
+}
+
 struct ieee80211_ops ath9k_ops = {
 	.tx 		    = ath9k_tx,
 	.start 		    = ath9k_start,
@@ -2405,4 +2432,6 @@ struct ieee80211_ops ath9k_ops = {
 	.get_et_stats  = ath9k_get_et_stats,
 	.get_et_strings  = ath9k_get_et_strings,
 #endif
+
+	.spectral_scan = ath9k_spectral_scan,
 };
drivers/net/wireless/ath/ath9k/recv.c +34 -0
index 6aafbb7..793fc91 100644
@@ -1034,6 +1034,35 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
 		rxs->flag &= ~RX_FLAG_DECRYPTED;
 }
 
+static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
+			    struct ath_rx_status *rs)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct fft_sample *fft_sample;
+
+	/* too short data is probably something else */
+	if (rs->rs_datalen < 30)
+		return;
+
+	/* don't bloat memory if userspace is lazy collecting fft data */
+	if (sc->fft_list_n > 10000)
+		return;
+
+	fft_sample = kmalloc(sizeof(*fft_sample), GFP_ATOMIC);
+	INIT_LIST_HEAD(&fft_sample->list);
+
+	fft_sample->freq = ah->curchan->chan->center_freq;
+	fft_sample->size = rs->rs_datalen;
+	fft_sample->rssi = rs->rs_rssi_ctl0;
+	fft_sample->ext_rssi = rs->rs_rssi_ext0;
+	fft_sample->noise = ah->noise;
+	fft_sample->data = kmalloc(fft_sample->size, GFP_ATOMIC);
+	memcpy(fft_sample->data, (u8 *)hdr, fft_sample->size);
+
+	list_add_tail(&fft_sample->list, &sc->fft_list);
+	sc->fft_list_n++;
+}
+
 int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 {
 	struct ath_buf *bf;
@@ -1131,6 +1160,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		    unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
 			rxs->mactime += 0x100000000ULL;
 
+		if ((rs.rs_status & ATH9K_RXERR_PHY) &&
+		    (rs.rs_phyerr == ATH9K_PHYERR_RADAR ||
+		     rs.rs_phyerr == ATH9K_PHYERR_FFT_REPORT))
+			ath_process_fft(sc, hdr, &rs);
+
 		retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
 						 rxs, &decrypt_error);
 		if (retval)
Signature · 1 line
1.7.10.4
#15 lore raw

RFC 3/3 ath9k: add spectral scan feature

Not that I'm specifically getting into this in any deep way right now, but..

On 27 November 2012 11:01, Simon Wunderlich
<[email protected]> wrote:

[snip] - this should apply to AR9380 and later I think.

Quoted 26 lines
drivers/net/wireless/ath/ath9k/ar9002_phy.c +26 -0
+void ar9002_hw_spectral_scan(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA);
+
+       /* NOTE: this will generate a few samples ... lacking documentation,
+        * I'm not really sure what these parameters mean.
+        */
+       REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
+       REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+                   AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
+       REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+                     AR_PHY_SPECTRAL_SCAN_COUNT, 8);
+       REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+                     AR_PHY_SPECTRAL_SCAN_PERIOD, 0xF);
+       REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+                     AR_PHY_SPECTRAL_SCAN_FFT_PERIOD, 0xFF);
+
+       /* Activate spectral scan */
+       REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+                   AR_PHY_SPECTRAL_SCAN_ACTIVE);
+
+       /* Poll for spectral scan complete */
+       if (!ath9k_hw_wait(ah, AR_PHY_SPECTRAL_SCAN,
+                          AR_PHY_SPECTRAL_SCAN_ACTIVE,

drivers/net/wireless/ath/ath9k/ar9002_phy.c static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah, · line 593

Quoted 10 lines
drivers/net/wireless/ath/ath9k/ar9002_phy.c +10 -0
+                          0, AH_WAIT_TIMEOUT)) {
+               ath_err(common, "spectral scan wait failed\n");
+               return;
+       }
+
+       /* Disable spectral scan */
+       REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+                   AR_PHY_SPECTRAL_SCAN_ENABLE);
+}
+

You shouldn't have to do this. There's two spectral scan modes (well, three) -

* when you're not decoding things, and you meet these parameters, please send me some events (I think the patent mentions this);
* trigger _now_ and send me "X" events; then clear the spectral scan bit;
* trigger _now_ and just send me infinite events - on earlier chips (AR9280 I think) the magic value may be 0; on the later values it may be 255. Someone should experiment.

I suggest you separate out "configure/enable/disable" and "trigger" as options.

Grr, mumble mumble open source developers mumble mumble.. :-)

I suggest experimenting around with those particular parameters. You should be able to coax out specific numbers of spectral scan events when you set the COUNT parameter to something other than 8. But polling that bit isn't needed. It should be asynchronous.

Good luck,

Adrian

Adrian

#16 lore raw

RFC 3/3 ath9k: add spectral scan feature

Adrian,

thanks a lot for your feedback!

Quoted 7 lines · Adrian Chadd

Not that I'm specifically getting into this in any deep way right now, but..

On 27 November 2012 11:01, Simon Wunderlich
<[email protected]> wrote:

[snip] - this should apply to AR9380 and later I think.

Actually I have pretty much the same code in both ar9002_phy.c and ar9003_phy.c, because they get different register definitions (addresses etc) from their respective header files.

You think that this wouldn't apply for AR9280? Is there something wrong or different with the register access?

I have put scan count of 8 in here, but on AR9380 I get much more samples (more like 256). I haven't played with this very much, because "a couple" of samples was all I needed for my graphical analyzer.

Quoted 39 lines
Quoted 26 lines
drivers/net/wireless/ath/ath9k/ar9002_phy.c +26 -0
+void ar9002_hw_spectral_scan(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA);
+
+       /* NOTE: this will generate a few samples ... lacking documentation,
+        * I'm not really sure what these parameters mean.
+        */
+       REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
+       REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+                   AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
+       REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+                     AR_PHY_SPECTRAL_SCAN_COUNT, 8);
+       REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+                     AR_PHY_SPECTRAL_SCAN_PERIOD, 0xF);
+       REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+                     AR_PHY_SPECTRAL_SCAN_FFT_PERIOD, 0xFF);
+
+       /* Activate spectral scan */
+       REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+                   AR_PHY_SPECTRAL_SCAN_ACTIVE);
+
+       /* Poll for spectral scan complete */
+       if (!ath9k_hw_wait(ah, AR_PHY_SPECTRAL_SCAN,
+                          AR_PHY_SPECTRAL_SCAN_ACTIVE,

drivers/net/wireless/ath/ath9k/ar9002_phy.c static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah, · line 593

Quoted 10 lines
drivers/net/wireless/ath/ath9k/ar9002_phy.c +10 -0
+                          0, AH_WAIT_TIMEOUT)) {
+               ath_err(common, "spectral scan wait failed\n");
+               return;
+       }
+
+       /* Disable spectral scan */
+       REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+                   AR_PHY_SPECTRAL_SCAN_ENABLE);
+}
+

You shouldn't have to do this. There's two spectral scan modes (well, three) -

Quoted 8 lines

* when you're not decoding things, and you meet these parameters, please send me some events (I think the patent mentions this);
* trigger _now_ and send me "X" events; then clear the spectral scan bit;
* trigger _now_ and just send me infinite events - on earlier chips (AR9280 I think) the magic value may be 0; on the later values it may be 255. Someone should experiment.

I suggest you separate out "configure/enable/disable" and "trigger" as options.

OK, yeah I can do that - guess we should have different function calls for this then, too. Don't know if all of this should be callable from mac80211 as well.

Quoted 2 lines

Grr, mumble mumble open source developers mumble mumble.. :-)

What are you muttering about? :D

Should we rather keep this wonderful feature to the closed source world? I don't think so :)

Quoted 5 lines

I suggest experimenting around with those particular parameters. You should be able to coax out specific numbers of spectral scan events when you set the COUNT parameter to something other than 8. But polling that bit isn't needed. It should be asynchronous.

As I said, on AR9220 it appears I get 8 samples when doing setting AR_PHY_SPECTRAL_SCAN_COUNT to 8 (plus maybe some other "stuff"/non-samples). On AR9380 I'm not so sure. Probably need to play with it a little more. Also, I don't know what "SHORT REPEAT" is supposed to mean, etc.

About polling, you mean the SCAN_ACTIVE bit? It is probably only needed when I want to trigger for few samples and want to be informed when it's finished - which is a good thing when doing spectral scan (change channel, start and wait for samples, change again). But we probably don't need to wait for the "background spectral scanning" mode, that's right. If someone wants to implement detection for interfering radio users, that mode would be useful. I don't need it, but can prepare the neccesary functions.

So I'd repost then:
* ath9k/debugfs only patch for now, as Johannes suggested - I think we should concentrate on this for now (their are still a lot of open questions in my initial mail regarding sample interpretation etc)
* split commands into enable/disable/configure/trigger
* maybe add some defines for magic values (if I find any)

I'd like this patchset to make the graphical spectral scan possible (as a Ubiquiti Airview), and give others the opportunity to add own features (pattern matching etc) on top of it. However I (currently) don't plan to do the latter myself.

Quoted 6 lines

Good luck,

Adrian

Thanks!
Simon

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
Url : http://lists.ath9k.org/pipermail/ath9k-devel/attachments/20121205/70112a57/attachment.pgp

#17 lore raw

RFC 3/3 ath9k: add spectral scan feature

Quoted 25 lines · Simon Wunderlich
Quoted 4 lines

I suggest experimenting around with those particular parameters. You should be able to coax out specific numbers of spectral scan events when you set the COUNT parameter to something other than 8. But polling that bit isn't needed. It should be asynchronous.

As I said, on AR9220 it appears I get 8 samples when doing setting AR_PHY_SPECTRAL_SCAN_COUNT to 8 (plus maybe some other "stuff"/non-samples). On AR9380 I'm not so sure. Probably need to play with it a little more. Also, I don't know what "SHORT REPEAT" is supposed to mean, etc.

About polling, you mean the SCAN_ACTIVE bit? It is probably only needed when I want to trigger for few samples and want to be informed when it's finished - which is a good thing when doing spectral scan (change channel, start and wait for samples, change again). But we probably don't need to wait for the "background spectral scanning" mode, that's right. If someone wants to implement detection for interfering radio users, that mode would be useful. I don't need it, but can prepare the neccesary functions.

So I'd repost then:
* ath9k/debugfs only patch for now, as Johannes suggested - I think we should concentrate on this for now (their are still a lot of open questions in my initial mail regarding sample interpretation etc)
* split commands into enable/disable/configure/trigger
* maybe add some defines for magic values (if I find any)

Quoted 4 lines

I'd like this patchset to make the graphical spectral scan possible (as a Ubiquiti Airview), and give others the opportunity to add own features (pattern matching etc) on top of it. However I (currently) don't plan to do the latter myself.

How about using relay (Documentation/filesystems/relay.txt) to stream sample data to user space via the debugfs file?
That way you don't have to keep a linked list of small struct fft_sample buffers in the kernel and you can stream much more data efficiently with little kernel side overhead.
It also makes pushing the streaming data to a network socket via sendfile much more efficient.

- Felix

#18 lore raw

RFC 3/3 ath9k: add spectral scan feature

Quoted 7 lines · Felix Fietkau

How about using relay (Documentation/filesystems/relay.txt) to stream sample data to user space via the debugfs file?
That way you don't have to keep a linked list of small struct fft_sample buffers in the kernel and you can stream much more data efficiently with little kernel side overhead.
It also makes pushing the streaming data to a network socket via sendfile much more efficient.

Yes, please do this.

When *cough* I do this for FreeBSD, I'll just have people expose this via BPF. I already have code to pull radar PHY errors out via BPF, so this becomes just as trivial to do.

Adrian

#19 lore raw

RFC 3/3 ath9k: add spectral scan feature

Hi,

I'll repost this, as it seems emailing lists.ath9k.org doesn't seem to work out.

The formats are as follows. Please note that if a pulse terminates during an FFT, the final entry may be truncated. So yes, you may not always get an integer multiple of the relevant frame length.

Note that you shift each of the readings by max_exp to get a total reading. max_index and max_magnitude I think are just derived from the existing dataset; they're just a shortcut for software so it doesn't have to parse the whole frame looking for the peak.

Static 20 mode:

0  bin -28 magnitude[7:0] = (|i| + |q|) >> max_exp
1  bin -27 magnitude[7:0] = (|i| + |q|) >> max_exp
2 - 53  ?
54  bin  26 magnitude[7:0] = (|i| + |q|) >> max_exp
55  bin  27 magnitude[7:0] = (|i| + |q|) >> max_exp
56  [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]}
57  [7:0]: all bins  max_magnitude[9:2]
58  [7:0]: all bins {max_index[5:0], max_magnitude[11:10]}
59  [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)

Dynamic 20/40 mode:

0  bin -64 magnitude[7:0] = (|i| + |q|) >> max_exp  or  power (in dBm)
1  bin -63 magnitude[7:0] = (|i| + |q|) >> max_exp  or  power (in dBm)
2 - 125  ?
126  bin  62 magnitude[7:0] = (|i| + |q|) >> max_exp  or  power (in dBm)
127  bin  63 magnitude[7:0] = (|i| + |q|) >> max_exp  or  power (in dBm)
128  [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]}
Baseband DFS 2 (Radar) Micro-Architecture
129  [7:0]: lower bins  max_magnitude[9:2]
130  [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]}
131  [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]}
132  [7:0]: upper bins  max_magnitude[9:2]
133  [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]}
134  [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)

Ok, now for radar it's a tad different. There's a bit that is set if the signal is above a certain threshold. If so, the bit is set to 1. There's also a 3 bit magnitude value which is calculated against the maximum magnitude value (floor(m(i) * 8 / max magnitude.)

Adrian

#20 lore raw

RFC 1/1 iw: add spectral scan attribute to scan function

In reply to Simon Wunderlich
---
 scan.c |   12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
scan.c +9 -3
index 05bad0b..3e28722 100644
@@ -70,7 +70,7 @@ static int handle_scan(struct nl80211_state *state,
 		DONE,
 	} parse = NONE;
 	int freq;
-	bool passive = false, have_ssids = false, have_freqs = false;
+	bool passive = false, have_ssids = false, have_freqs = false, spec_scan = false;
 	size_t tmp;
 	unsigned char *ies;
 	int flags = 0;
@@ -115,6 +115,10 @@ static int handle_scan(struct nl80211_state *state,
 				parse = DONE;
 				passive = true;
 				break;
+			} else if (strcmp(argv[i], "spec-scan") == 0) {
+				parse = NONE;
+				spec_scan = true;
+				break;
 			}
 		case DONE:
 			return 1;
@@ -151,6 +155,8 @@ static int handle_scan(struct nl80211_state *state,
 		nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
 	if (flags)
 		NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS, flags);
+	if (spec_scan)
+                NLA_PUT_FLAG(msg, NL80211_ATTR_TX_SPEC_SCAN);
 
 	err = 0;
  nla_put_failure:
@@ -1450,7 +1456,7 @@ static int handle_scan_combined(struct nl80211_state *state,
 	dump_argv[0] = argv[0];
 	return handle_cmd(state, id, dump_argc, dump_argv);
 }
-TOPLEVEL(scan, "[-u] [freq <freq>*] [ies <hex as 00:11:..>] [lowpri,flush,ap-force] [ssid <ssid>*|passive]", 0, 0,
+TOPLEVEL(scan, "[-u] [freq <freq>*] [ies <hex as 00:11:..>] [lowpri,flush,ap-force,spec-scan] [ssid <ssid>*|passive]", 0, 0,
 	 CIB_NETDEV, handle_scan_combined,
 	 "Scan on the given frequencies and probe for the given SSIDs\n"
 	 "(or wildcard if not given) unless passive scanning is requested.\n"
@@ -1460,7 +1466,7 @@ COMMAND(scan, dump, "[-u]",
 	NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump,
 	"Dump the current scan results. If -u is specified, print unknown\n"
 	"data in scan results.");
-COMMAND(scan, trigger, "[freq <freq>*] [ies <hex as 00:11:..>] [lowpri,flush,ap-force] [ssid <ssid>*|passive]",
+COMMAND(scan, trigger, "[freq <freq>*] [ies <hex as 00:11:..>] [lowpri,flush,ap-force,spec-scan] [ssid <ssid>*|passive]",
 	NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan,
 	 "Trigger a scan on the given frequencies with probing for the given\n"
 	 "SSIDs (or wildcard if not given) unless passive scanning is requested.");
Signature · 1 line
1.7.10.4
#21 lore raw
In reply to Simon Wunderlich
Quoted 9 lines · Simon Wunderlich

This patchset is a first request for comments for the upcoming spectral scan feature. It adds a new attribute to nl80211 to ask for a spectral scan while scanning, because we cycle through the channels anyway at this time. If enabled by the driver, spectral scan results will be collected. This feature has been enabled for AR92xx and AR93xx based chipsets. As the FFT samples are very hardware dependent, they are only provided via a debugfs file for further evaluation.

[3] http://www.wehavemorefun.de/fritzbox/Ath_spectral.ko#Symbole

Erm. Just a quick question, since you mentioned this fritzbox ath_spectral.ko module... Is your "work" based or related to it, i.e.: did you peek at the assembler listings of it, or did someone else write a spec. and you just implemented it?

#22 lore raw
Quoted 10 lines · Martin Schleier
Quoted 8 lines · Simon Wunderlich

This patchset is a first request for comments for the upcoming spectral scan feature. It adds a new attribute to nl80211 to ask for a spectral scan while scanning, because we cycle through the channels anyway at this time. If enabled by the driver, spectral scan results will be collected. This feature has been enabled for AR92xx and AR93xx based chipsets. As the FFT samples are very hardware dependent, they are only provided via a debugfs file for further evaluation.

Quoted 6 lines
Quoted 1 line

[3] http://www.wehavemorefun.de/fritzbox/Ath_spectral.ko#Symbole

Erm. Just a quick question, since you mentioned this fritzbox ath_spectral.ko module... Is your "work" based or related to it, i.e.: did you peek at the assembler listings of it, or did someone else write a spec. and you just implemented it?

I didn't peek in assembler listings or anything, I've mostly followed hints given on this mailing list or on the web and did some research who else did implement spectrum scanning. Some of my sources:

http://permalink.gmane.org/gmane.linux.drivers.ath9k.devel/4834
http://comments.gmane.org/gmane.linux.drivers.ath9k.devel/8409
http://wiki.mikrotik.com/wiki/Manual:Spectrum_analyzer

From this, one can grasp that the AR_PHY_SPECTRAL_SCAN has to be used and some phy errors have to be interpreted (phy error 5 and 38). The rest was mostly trial and error, including the interpretation of the data - most of this is guessing and comparing to the Ubiquiti AirView [1] Spectrum analyzer USB dongle when using an analogue wireless camera. :)

The goal of this was to create the spectral scan feature based on public information, so the results are probably not optimal yet, but I hope that this will help to move Qualcomm/Atheros disclosing some information (this seems to be planned anyway[2]). Otherwise, maybe other people can help reverse-engineering this. :)

Cheers,
Simon

[1] http://www.ubnt.com/airview
[2] http://thread.gmane.org/gmane.linux.drivers.ath9k.devel/8409/focus=8411

#23 lore raw
Quoted 7 lines · Simon Wunderlich

[...]

The goal of this was to create the spectral scan feature based on public information, so the results are probably not optimal yet, but I hope that this will help to move Qualcomm/Atheros disclosing some information (this seems to be planned anyway[2]). Otherwise, maybe other people can help reverse-engineering this. :)

Just to clarify: I don't mean anyone should disassemble proprietary object files or use proprietary source code and re-use these findings without permission to create this feature - this would probably be illegal anyway.

By reverse-engineering, I mean we can already dump data spectral scan data with this patchset, but the hard part is to interpret this data correctly - as you'll find in the patches, there are a lot of bits which we don't know what they mean, and maybe there is even more info hidden in these bits. I've uploaded some samples taken on my hardware to the github repo, so anyone can use my program, matlab, or just stare at these heaps of bytes to find some patterns and try to interpret it. Actually I was just staring at the bytes myself and wrote this visualizer to get a better idea what they could mean.

Of course, if we can some docs or support from QCA officially, this would be even better. :)

Cheers,
Simon

#24 lore raw

Hi Simon,

Quoted 21 lines · Simon Wunderlich
Quoted 7 lines · Simon Wunderlich

[...]

The goal of this was to create the spectral scan feature based on public information, so the results are probably not optimal yet, but I hope that this will help to move Qualcomm/Atheros disclosing some information (this seems to be planned anyway[2]). Otherwise, maybe other people can help reverse-engineering this. :)

Just to clarify: I don't mean anyone should disassemble proprietary object files or use proprietary source code and re-use these findings without permission to create this feature - this would probably be illegal anyway.

By reverse-engineering, I mean we can already dump data spectral scan data with this patchset, but the hard part is to interpret this data correctly - as you'll find in the patches, there are a lot of bits which we don't know what they mean, and maybe there is even more info hidden in these bits. I've uploaded some samples taken on my hardware to the github repo, so anyone can use my program, matlab, or just stare at these heaps of bytes to find some patterns and try to interpret it. Actually I was just staring at the bytes myself and wrote this visualizer to get a better idea what they could mean.

Quoted 5 lines

Of course, if we can some docs or support from QCA officially, this would be even better. :)

Cheers,
Simon

A search brought me to their patent application. The Drawings on their patent application contain some more information on the signal classifications. Hopefully this will be able to help you or someone else.

http://www.google.com/patents/US7929508

#25 lore raw

Hello Johnathan,

Quoted 27 lines · Jonathan Bither

Hi Simon,

Quoted 24 lines · Simon Wunderlich
Quoted 7 lines · Simon Wunderlich

[...]

The goal of this was to create the spectral scan feature based on public information, so the results are probably not optimal yet, but I hope that this will help to move Qualcomm/Atheros disclosing some information (this seems to be planned anyway[2]). Otherwise, maybe other people can help reverse-engineering this. :)

Just to clarify: I don't mean anyone should disassemble proprietary object files or use proprietary source code and re-use these findings without permission to create this feature - this would probably be illegal anyway.

By reverse-engineering, I mean we can already dump data spectral scan data with this patchset, but the hard part is to interpret this data correctly - as you'll find in the patches, there are a lot of bits which we don't know what they mean, and maybe there is even more info hidden in these bits. I've uploaded some samples taken on my hardware to the github repo, so anyone can use my program, matlab, or just stare at these heaps of bytes to find some patterns and try to interpret it. Actually I was just staring at the bytes myself and wrote this visualizer to get a better idea what they could mean.

Of course, if we can some docs or support from QCA officially, this would be even better. :)

Quoted 9 lines
Quoted 2 lines

Cheers,
Simon

A search brought me to their patent application. The Drawings on their patent application contain some more information on the signal classifications. Hopefully this will be able to help you or someone else.

http://www.google.com/patents/US7929508

thanks for pointing that out! This doc gives a pretty good general idea how things are working, although it isn't too helpful in details. It also describes some pattern matching related things.

If you anyone is interested in the pattern matching things, also the airshark paper is definitely worth to be read:

http://pages.cs.wisc.edu/~suman/pubs/airshark.pdf
(some AR9280 details are to be found at section 3.1)

Cheers,
Simon