Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH] RFC: Universal scan proposal
From: Arend Van Spriel @ 2016-11-22 20:41 UTC (permalink / raw)
  To: Dmitry Shmidt, Luca Coelho; +Cc: linux-wireless
In-Reply-To: <CAH7ZN-z+QytCTHDs3dkU172hMio=T2Mhr8y=mXKXu=DRA1vA3A@mail.gmail.com>

On 22-11-2016 18:29, Dmitry Shmidt wrote:
> Hi Luca,
> 
> On Mon, Nov 21, 2016 at 11:24 PM, Luca Coelho <luca@coelho.fi> wrote:
>> Hi Dmitry,
>> On Wed, 2016-11-16 at 22:47 +0000, dimitrysh@google.com wrote:
>>>  From 68a9d37a4c7e9dc7a90a6e922cdea52737a98d66 Mon Sep 17 00:00:00 2001
>>> From: Dmitry Shmidt <dimitrysh@google.com>
>>> Date: Wed, 16 Nov 2016 14:27:26 -0800
>>> Subject: [PATCH] RFC: Universal scan proposal
>>>
>>>    Currently we have sched scan with possibility of various
>>> intervals. We would like to extend it to support also
>>> different types of scan.
>>>    In case of powerful wlan CPU, all this functionality
>>> can be offloaded.
>>>    In general case FW processes additional scan requests
>>> and puts them into queue based on start time and interval.
>>> Once current request is fulfilled, FW adds it (if interval != 0)
>>> again to the queue with proper interval. If requests are
>>> overlapping, new request can be combined with either one before,
>>> or one after, assuming that requests are not mutually exclusive.
>>>    Combining requests is done by combining scan channels, ssids,
>>> bssids and types of scan result. Once combined request was fulfilled
>>> it will be reinserted as two (or three) different requests based on
>>> their type and interval.
>>>    Each request has attribute:
>>> Type: connectivity / location
>>> Report: none / batch / immediate
>>>    Request may have priority and can be inserted into
>>> the head of the queue.
>>>    Types of scans:
>>> - Normal scan
>>> - Scheduled scan
>>> - Hotlist (BSSID scan)
>>> - Roaming
>>> - AutoJoin
>>>
>>> Change-Id: I9f3e4c975784f1c1c5156887144d80fc5a26bffa
>>> Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
>>> ---
>>
>> I like the initiative and I think this is definitely something that can
>> improve concurrent scanning instances.  But IMHO the most important is
>> to discuss the semantics of this change, such as which scans can be
>> combined, who makes the decisions of combining them, how priorities are
>> sorted out etc.  I think the types of scan are not relevant in the
>> nl80211 API, but the characteristics of the scans are.  For instance,
>> "urgent scan" (for initial connection), best-effort scan for roaming...
>> and latency requirements, such as low-latency for location and initial
>> connection and high-latency for scheduled scan.  Then we decided, in
>> the kernel, how to combine and prioritize them according to their
>> characteristics, instead of having to map scan types to these
>> characteristics.
>>
>> What do you think?
> 
> 1. Combining scans.
> There are two scenarios in general: combine scans that can be offload
> and scans that can not be offload due to "weak" FW / wlan SoC. In last
> case this approach maybe not attractive at all - non-mobile device
> may not need all these different types of scan.
> In case of offload - it will be FW code decision - I just wanted to propose
> the way how to do this efficiently.

I think Luca is looking at it as a way to deal with multiple user-space
entities request the device to perform a scan. Ignoring the scan types
on android it can be wifi-hal and wpa_supplicant.

> 2. Priority - very good point, we need to have it. I am just not sure
> that we need like scale priority - maybe just flag - urgent / not urgent.
> Urgent one will be inserted in queue as is and conflicting request
> should be postponed or combined.

What if we get another urgent one?

> 3. Scan types - I am not sure I fully understood your question, but
> if the idea is for kernel to decide about type of scan based on its
> characteristics instead of specific type request performance may
> cause confusion to wifi manager.
> However, it would definitely simplify kernel API. Still I am not sure
> if userspace wifi manager will "like" it.

Actually the idea is to hide the notion of scan type entirely from the
API and kernel code. If you add the scan type as an attribute in the
API, you still need to provide additional attributes for that scan type
so the question is what the scan type itself provides, ie. how does it
affect the scan itself.

> 4. There is an interesting question: to separate scan results for
> connection and location or not? The problem is how to "trust" them.
> I mean scan results are scan results, but for location we may decide
> to look for fewer channels and even maybe specific BSSIDs, i.e. not
> full scan results, and we may need to indicate that right now
> scan results are not full in order not to confuse wifi manager.

Regards,
Arend

>> --
>> Cheers,
>> Luca.

^ permalink raw reply

* Re: [PATCH] nl80211: provide minimum scheduled scan (plan) interval
From: Arend Van Spriel @ 2016-11-22 20:06 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1479821915.9021.4.camel@sipsolutions.net>

On 22-11-2016 14:38, Johannes Berg wrote:
> 
>> +		if (wiphy->min_sched_scan_plan_interval &&
>> +		    request->scan_plans[i].interval <
>> +		    wiphy->min_sched_scan_plan_interval)
>> +			return -EINVAL;
>>
> I'm not sure we should break the API that way - just move it up if it's
> smaller?

Are we? Currently, the minimum is not checked in nl80211, but that does
not say anything about the driver which might validate the interval as
well and return an error.

What made me start looking at this is that in brcmfmac the interval in
the request was ignored and a fixed interval was provisioned in the
device. I wanted to fix that but was not sure if I needed to check it
against our firmware min..max range and what the appropriate error
handling should be. If silently changing what user-space is requesting
is fine for this, I am happy to make it so. Preferably in nl80211.

Regards,
Arend

^ permalink raw reply

* Re: wl1251 & mac address & calibration data
From: Pali Rohár @ 2016-11-22 17:05 UTC (permalink / raw)
  To: Michal Kazior
  Cc: Kalle Valo, Pavel Machek, Ivaylo Dimitrov, Sebastian Reichel,
	Aaro Koskinen, Tony Lindgren, linux-wireless, Network Development,
	linux-kernel
In-Reply-To: <CA+BoTQkSOJ85PiT=pjmH234sviCj-LVWWM=64KbCe4AG9CMNUg@mail.gmail.com>

[-- Attachment #1: Type: Text/Plain, Size: 4860 bytes --]

On Tuesday 22 November 2016 17:14:28 Michal Kazior wrote:
> On 22 November 2016 at 16:31, Pali Rohár <pali.rohar@gmail.com> wrote:
> > On Tuesday 22 November 2016 16:22:57 Michal Kazior wrote:
> >> On 21 November 2016 at 16:51, Pali Rohár <pali.rohar@gmail.com>
> >> wrote:
> >> > On Friday 11 November 2016 18:20:50 Pali Rohár wrote:
> >> >> Hi! I will open discussion about mac address and calibration
> >> >> data for wl1251 wireless chip again...
> >> >> 
> >> >> Problem: Mac address & calibration data for wl1251 chip on
> >> >> Nokia N900 are stored on second nand partition (mtd1) in
> >> >> special proprietary format which is used only for Nokia N900
> >> >> (probably on N8x0 and N9 too). Wireless driver wl1251.ko
> >> >> cannot work without mac address and calibration data.
> >> 
> >> Same problem applies to some ath9k/ath10k supported routers. Some
> >> even carry mac address as implicit offset from ethernet mac
> >> address. As far as I understand OpenWRT cooks cal blobs on first
> >> boot prior to loading modules.
> > 
> > So... wl1251 on Nokia N900 is not alone and this problem is there
> > for more drivers and devices. Which means we should come up with
> > some generic solution.
> 
> This isn't particularly a problem for ath9k/ath10k.
> 
> Let me give you more background on ath10k.
> 
> ath10k devices can come with caldata and macaddr stored in their
> OTP/EEPROM. In that case a generic "template" board file is used.
> Userspace doesn't need to do anything special.
> 
> Some vendors however decide to use flash partition to store caldata.
> In that case ath10k expects userspace to prepare
> cal-$bus-$devname.bin files, each for a different radio (you can
> have multiple radios on a system).
> 
> Now translating this for wl1251 I would expect it should also use
> something like wl1251-nvs-sdio-0x0001.bin for devices like N900 that
> have caldata on flash partition (instead of the generic
> wl1251-nvs.bin). I'm not sure if wl1251-nvs.bin is something
> comparable to (the generic) board.bin ath10k has though. Maybe the
> entire idea behind wl1251-nvs.bin is flawed as it's supposed to be
> device specific and is oblivious to possibility of having multiple
> wl1251 radios on one system (probably sane assumption from practical
> standpoint but still).

Basically nvs data are device specific, in ideal case they should be 
generated in factory by some calibration process (or so).

> >> >> Absence of mac address cause that driver generates random mac
> >> >> address at every kernel boot which has couple of problems
> >> >> (unstable identifier of wireless device due to udev permanent
> >> >> storage rules; unpredictable behaviour for dhcp mac address
> >> >> assignment, mac address filtering, ...).
> >> >> 
> >> >> Currently there is no way to set (permanent) mac address for
> >> >> network interface from userspace. And it does not make sense
> >> >> to implement in linux kernel large parser for proprietary
> >> >> format of second nand partition where is mac address stored
> >> >> only for one device -- Nokia N900.
> >> >> 
> >> >> Driver wl1251.ko loads calibration data via request_firmware()
> >> >> for file wl1251-nvs.bin. There are some "example" calibration
> >> >> file in linux- firmware repository, but it is not suitable for
> >> >> normal usage as real calibration data are per-device specific.
> >> 
> >> You could hook up a script that cooks up the cal/mac file via
> >> modprobe's install hook, no?
> > 
> > Via modprobe hook I can either pass custom module parameter or call
> > any other system (shell) commands.
> > 
> > As wl1251.ko does not accept mac_address as module parameter, such
> > modprobe hook does not help -- as there is absolutely no way from
> > userspace to set or change (permanent) mac address.
> 
> Quoting modprobe.d manual:
> >       install modulename command...
> >       
> >           This command instructs modprobe to run your
> >           command instead of inserting the module in the
> >           kernel as normal. The command can be any shell
> >           command: this allows you to do any kind of
> >           complex processing you might wish. [...]

I know. But this do not allow me to send mac address to kernel -- as 
kernel does not support such command yet (reason for my first question).

> You can hook up a script that cooks up wl1251-nvs.bin (caldata,
> macaddr) and then insmod the actual wl1251.ko module. Or you can just
> cook up the nvs on first device boot and store it in /lib/firmware
> (possibly overwriting the "generic" wl1251 from linux-firmware).

This is what I would like to prevent -- overwriting (possible readonly) 
system files with some device specific. It is really bad idea!

-- 
Pali Rohár
pali.rohar@gmail.com

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* Re: [PATCH] RFC: Universal scan proposal
From: Dmitry Shmidt @ 2016-11-22 17:29 UTC (permalink / raw)
  To: Luca Coelho; +Cc: linux-wireless
In-Reply-To: <1479799452.2517.39.camel@coelho.fi>

Hi Luca,

On Mon, Nov 21, 2016 at 11:24 PM, Luca Coelho <luca@coelho.fi> wrote:
> Hi Dmitry,
> On Wed, 2016-11-16 at 22:47 +0000, dimitrysh@google.com wrote:
>>  From 68a9d37a4c7e9dc7a90a6e922cdea52737a98d66 Mon Sep 17 00:00:00 2001
>> From: Dmitry Shmidt <dimitrysh@google.com>
>> Date: Wed, 16 Nov 2016 14:27:26 -0800
>> Subject: [PATCH] RFC: Universal scan proposal
>>
>>    Currently we have sched scan with possibility of various
>> intervals. We would like to extend it to support also
>> different types of scan.
>>    In case of powerful wlan CPU, all this functionality
>> can be offloaded.
>>    In general case FW processes additional scan requests
>> and puts them into queue based on start time and interval.
>> Once current request is fulfilled, FW adds it (if interval != 0)
>> again to the queue with proper interval. If requests are
>> overlapping, new request can be combined with either one before,
>> or one after, assuming that requests are not mutually exclusive.
>>    Combining requests is done by combining scan channels, ssids,
>> bssids and types of scan result. Once combined request was fulfilled
>> it will be reinserted as two (or three) different requests based on
>> their type and interval.
>>    Each request has attribute:
>> Type: connectivity / location
>> Report: none / batch / immediate
>>    Request may have priority and can be inserted into
>> the head of the queue.
>>    Types of scans:
>> - Normal scan
>> - Scheduled scan
>> - Hotlist (BSSID scan)
>> - Roaming
>> - AutoJoin
>>
>> Change-Id: I9f3e4c975784f1c1c5156887144d80fc5a26bffa
>> Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
>> ---
>
> I like the initiative and I think this is definitely something that can
> improve concurrent scanning instances.  But IMHO the most important is
> to discuss the semantics of this change, such as which scans can be
> combined, who makes the decisions of combining them, how priorities are
> sorted out etc.  I think the types of scan are not relevant in the
> nl80211 API, but the characteristics of the scans are.  For instance,
> "urgent scan" (for initial connection), best-effort scan for roaming...
> and latency requirements, such as low-latency for location and initial
> connection and high-latency for scheduled scan.  Then we decided, in
> the kernel, how to combine and prioritize them according to their
> characteristics, instead of having to map scan types to these
> characteristics.
>
> What do you think?

1. Combining scans.
There are two scenarios in general: combine scans that can be offload
and scans that can not be offload due to "weak" FW / wlan SoC. In last
case this approach maybe not attractive at all - non-mobile device
may not need all these different types of scan.
In case of offload - it will be FW code decision - I just wanted to propose
the way how to do this efficiently.

2. Priority - very good point, we need to have it. I am just not sure
that we need like scale priority - maybe just flag - urgent / not urgent.
Urgent one will be inserted in queue as is and conflicting request
should be postponed or combined.

3. Scan types - I am not sure I fully understood your question, but
if the idea is for kernel to decide about type of scan based on its
characteristics instead of specific type request performance may
cause confusion to wifi manager.
However, it would definitely simplify kernel API. Still I am not sure
if userspace wifi manager will "like" it.

4. There is an interesting question: to separate scan results for
connection and location or not? The problem is how to "trust" them.
I mean scan results are scan results, but for location we may decide
to look for fewer channels and even maybe specific BSSIDs, i.e. not
full scan results, and we may need to indicate that right now
scan results are not full in order not to confuse wifi manager.

> --
> Cheers,
> Luca.

^ permalink raw reply

* Re: Break-it testing for wifi
From: Ben Greear @ 2016-11-22 16:59 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless@vger.kernel.org
In-Reply-To: <1479812215.9021.3.camel@sipsolutions.net>



On 11/22/2016 02:56 AM, Johannes Berg wrote:
> On Mon, 2016-11-21 at 08:10 -0800, Ben Greear wrote:
>
>> I am thinking about adding some sort of framework to wpa_supplicant
>> and/or the mac80211 stack to allow purposefully creating bad station
>> behaviour in order to test robustness of APs.
>
> I'm interested in this.
>
> Have you seen the fuzzer stuff in wpa_s/hostapd?
>
> See
>
> https://w1.fi/cgit/hostap/commit/?id=7d3f18d72c3c883112ee927fc402c0eaed09ff65
>
> for example for something Jouni did after our discussions recently.

I have not seen that yet.  I'll look at that more closely soon.

>
>> Some ideas so far:
>>
>> 1)  Allow supplicant to do bad state-machine transitions (start 4-way
>> before associating, for instance).
>
> Why would you do that? In order to test the AP implementation?

Yes.  And really, you should be able to do similar things on the AP to test stations,
or on IBSS/Mesh devices, etc.  hostapd already has some options to corrupt or
drop a percentage of various management frames.  Supplicant does not as far
as I know.

>
>> 2)  Randomly corrupt mgt frames in driver and/or mac80211 stack
>> and/or supplicant.
>
> I think fuzzing the input path for those frames would be more useful
> than just corrupting things.

Random corruptions, especially by code that had at least some understanding
of management frames should be fast and easy to use.  It would not be as good
as a really clever fuzzer or hand-crafted frames, but for many users, hand-crafting
attacks would be well beyond what they could ever accomplish.

>
>> 3)  Possibly allow user to make specific corruptions.  This would
>> probably be in supplicant
>>       only, and I am not sure how this would be configured.  Maybe
>> allow user to over-ride
>>       existing IEs and add bogus ones of their own choosing.
>
> No idea what you really mean by this :)

Currently, supplicant can (at least with some small patches that I carry),
add custom information elements to probe requests and similar.  But, some things
are built by mac80211 (rate-sets advertised, for instance).  So, I was thinking of slightly extending
the API so that user-space could over-ride whatever mac80211 might normally
build itself.  That lets you more properly fuzz things from user space.

>
>> 4)  Maybe some specific tests like putting in over-flow sized lengths
>> of IEs.
>
> Again, fuzzing would cover this?

Yes, but for ease of use, and to cover frames generated by mac80211, I
was thinking:

echo 0.25 > /debug/.../wlan0/mgt_fuzzer

The fuzzer would then corrupt 25% of the management frames.  And instead of just randomly
scribbling, it could also parse the frames and do some more clever (and still pseudo-random)
modifications to the frames, like re-writing IEs with bad lengths, flipping bits in specific portions of the
frame we feel might find problems, etc.

I think if the tool became useful, then it could grow more clever over time.

>
>> Has anyone done anything similar they would like to share?
>>
>> Johannes:  Any interest in having such a framework in upstream
>> kernels?
>
> I suspect you have something entirely different in mind, like testing a
> (remote) AP implementation?

Yes.

>
> All of the local testing is probably better done via hwsim?

Well, there is a decent chance you could crash some firmware if you sent
corrupted EAPOL frames to it.  And just possibly some drivers inspect packets as well,
so I was thinking that fully transmitting the frames out of the system might
have some use.  And specifically for me, I am trying to test remote systems,
so hwsim would not be useful for that.

But, if local Linux (and local userspace) itself is the test target, then hwsim should give some very good
test coverage.

Thanks,
Ben

>
> johannes
>

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

^ permalink raw reply

* Re: wl1251 & mac address & calibration data
From: Michal Kazior @ 2016-11-22 16:14 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Kalle Valo, Pavel Machek, Ivaylo Dimitrov, Sebastian Reichel,
	Aaro Koskinen, Tony Lindgren, linux-wireless, Network Development,
	linux-kernel
In-Reply-To: <20161122153141.GT13735@pali>

On 22 November 2016 at 16:31, Pali Roh=C3=A1r <pali.rohar@gmail.com> wrote:
> On Tuesday 22 November 2016 16:22:57 Michal Kazior wrote:
>> On 21 November 2016 at 16:51, Pali Roh=C3=A1r <pali.rohar@gmail.com> wro=
te:
>> > On Friday 11 November 2016 18:20:50 Pali Roh=C3=A1r wrote:
>> >> Hi! I will open discussion about mac address and calibration data for
>> >> wl1251 wireless chip again...
>> >>
>> >> Problem: Mac address & calibration data for wl1251 chip on Nokia N900
>> >> are stored on second nand partition (mtd1) in special proprietary for=
mat
>> >> which is used only for Nokia N900 (probably on N8x0 and N9 too).
>> >> Wireless driver wl1251.ko cannot work without mac address and
>> >> calibration data.
>>
>> Same problem applies to some ath9k/ath10k supported routers. Some even
>> carry mac address as implicit offset from ethernet mac address. As far
>> as I understand OpenWRT cooks cal blobs on first boot prior to loading
>> modules.
>
> So... wl1251 on Nokia N900 is not alone and this problem is there for
> more drivers and devices. Which means we should come up with some
> generic solution.

This isn't particularly a problem for ath9k/ath10k.

Let me give you more background on ath10k.

ath10k devices can come with caldata and macaddr stored in their
OTP/EEPROM. In that case a generic "template" board file is used.
Userspace doesn't need to do anything special.

Some vendors however decide to use flash partition to store caldata.
In that case ath10k expects userspace to prepare cal-$bus-$devname.bin
files, each for a different radio (you can have multiple radios on a
system).

Now translating this for wl1251 I would expect it should also use
something like wl1251-nvs-sdio-0x0001.bin for devices like N900 that
have caldata on flash partition (instead of the generic
wl1251-nvs.bin). I'm not sure if wl1251-nvs.bin is something
comparable to (the generic) board.bin ath10k has though. Maybe the
entire idea behind wl1251-nvs.bin is flawed as it's supposed to be
device specific and is oblivious to possibility of having multiple
wl1251 radios on one system (probably sane assumption from practical
standpoint but still).


>> >> Absence of mac address cause that driver generates random mac address=
 at
>> >> every kernel boot which has couple of problems (unstable identifier o=
f
>> >> wireless device due to udev permanent storage rules; unpredictable
>> >> behaviour for dhcp mac address assignment, mac address filtering, ...=
).
>> >>
>> >> Currently there is no way to set (permanent) mac address for network
>> >> interface from userspace. And it does not make sense to implement in
>> >> linux kernel large parser for proprietary format of second nand
>> >> partition where is mac address stored only for one device -- Nokia N9=
00.
>> >>
>> >> Driver wl1251.ko loads calibration data via request_firmware() for fi=
le
>> >> wl1251-nvs.bin. There are some "example" calibration file in linux-
>> >> firmware repository, but it is not suitable for normal usage as real
>> >> calibration data are per-device specific.
>>
>> You could hook up a script that cooks up the cal/mac file via
>> modprobe's install hook, no?
>
> Via modprobe hook I can either pass custom module parameter or call any
> other system (shell) commands.
>
> As wl1251.ko does not accept mac_address as module parameter, such
> modprobe hook does not help -- as there is absolutely no way from
> userspace to set or change (permanent) mac address.

Quoting modprobe.d manual:

>       install modulename command...
>           This command instructs modprobe to run your
>           command instead of inserting the module in the
>           kernel as normal. The command can be any shell
>           command: this allows you to do any kind of
>           complex processing you might wish. [...]

You can hook up a script that cooks up wl1251-nvs.bin (caldata,
macaddr) and then insmod the actual wl1251.ko module. Or you can just
cook up the nvs on first device boot and store it in /lib/firmware
(possibly overwriting the "generic" wl1251 from linux-firmware).


Michal

^ permalink raw reply

* Re: wl1251 & mac address & calibration data
From: Pali Rohár @ 2016-11-22 15:31 UTC (permalink / raw)
  To: Michal Kazior
  Cc: Kalle Valo, Pavel Machek, Ivaylo Dimitrov, Sebastian Reichel,
	Aaro Koskinen, Tony Lindgren, linux-wireless, Network Development,
	linux-kernel
In-Reply-To: <CA+BoTQm5yZYccMherMnmxZ0_b2PqkCWf_0nBoRLzsro-Ujz1eQ@mail.gmail.com>

On Tuesday 22 November 2016 16:22:57 Michal Kazior wrote:
> On 21 November 2016 at 16:51, Pali Rohár <pali.rohar@gmail.com> wrote:
> > On Friday 11 November 2016 18:20:50 Pali Rohár wrote:
> >> Hi! I will open discussion about mac address and calibration data for
> >> wl1251 wireless chip again...
> >>
> >> Problem: Mac address & calibration data for wl1251 chip on Nokia N900
> >> are stored on second nand partition (mtd1) in special proprietary format
> >> which is used only for Nokia N900 (probably on N8x0 and N9 too).
> >> Wireless driver wl1251.ko cannot work without mac address and
> >> calibration data.
> 
> Same problem applies to some ath9k/ath10k supported routers. Some even
> carry mac address as implicit offset from ethernet mac address. As far
> as I understand OpenWRT cooks cal blobs on first boot prior to loading
> modules.

So... wl1251 on Nokia N900 is not alone and this problem is there for
more drivers and devices. Which means we should come up with some
generic solution.

> >> Absence of mac address cause that driver generates random mac address at
> >> every kernel boot which has couple of problems (unstable identifier of
> >> wireless device due to udev permanent storage rules; unpredictable
> >> behaviour for dhcp mac address assignment, mac address filtering, ...).
> >>
> >> Currently there is no way to set (permanent) mac address for network
> >> interface from userspace. And it does not make sense to implement in
> >> linux kernel large parser for proprietary format of second nand
> >> partition where is mac address stored only for one device -- Nokia N900.
> >>
> >> Driver wl1251.ko loads calibration data via request_firmware() for file
> >> wl1251-nvs.bin. There are some "example" calibration file in linux-
> >> firmware repository, but it is not suitable for normal usage as real
> >> calibration data are per-device specific.
> 
> You could hook up a script that cooks up the cal/mac file via
> modprobe's install hook, no?

Via modprobe hook I can either pass custom module parameter or call any
other system (shell) commands.

As wl1251.ko does not accept mac_address as module parameter, such
modprobe hook does not help -- as there is absolutely no way from
userspace to set or change (permanent) mac address.

-- 
Pali Rohár
pali.rohar@gmail.com

^ permalink raw reply

* Re: wl1251 & mac address & calibration data
From: Michal Kazior @ 2016-11-22 15:22 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Kalle Valo, Pavel Machek, Ivaylo Dimitrov, Sebastian Reichel,
	Aaro Koskinen, Tony Lindgren, linux-wireless, Network Development,
	linux-kernel
In-Reply-To: <20161121155153.GM13735@pali>

On 21 November 2016 at 16:51, Pali Roh=C3=A1r <pali.rohar@gmail.com> wrote:
> On Friday 11 November 2016 18:20:50 Pali Roh=C3=A1r wrote:
>> Hi! I will open discussion about mac address and calibration data for
>> wl1251 wireless chip again...
>>
>> Problem: Mac address & calibration data for wl1251 chip on Nokia N900
>> are stored on second nand partition (mtd1) in special proprietary format
>> which is used only for Nokia N900 (probably on N8x0 and N9 too).
>> Wireless driver wl1251.ko cannot work without mac address and
>> calibration data.

Same problem applies to some ath9k/ath10k supported routers. Some even
carry mac address as implicit offset from ethernet mac address. As far
as I understand OpenWRT cooks cal blobs on first boot prior to loading
modules.


>> Absence of mac address cause that driver generates random mac address at
>> every kernel boot which has couple of problems (unstable identifier of
>> wireless device due to udev permanent storage rules; unpredictable
>> behaviour for dhcp mac address assignment, mac address filtering, ...).
>>
>> Currently there is no way to set (permanent) mac address for network
>> interface from userspace. And it does not make sense to implement in
>> linux kernel large parser for proprietary format of second nand
>> partition where is mac address stored only for one device -- Nokia N900.
>>
>> Driver wl1251.ko loads calibration data via request_firmware() for file
>> wl1251-nvs.bin. There are some "example" calibration file in linux-
>> firmware repository, but it is not suitable for normal usage as real
>> calibration data are per-device specific.

You could hook up a script that cooks up the cal/mac file via
modprobe's install hook, no?


Micha=C5=82

^ permalink raw reply

* Re: ath10k stuck in mesh mode
From: Michal Kazior @ 2016-11-22 15:20 UTC (permalink / raw)
  To: Matteo Grandi; +Cc: Bob Copeland, LinuxWireless Mailing List
In-Reply-To: <CAHdg3xadDx=+Yc+vPKtyOG6-w-BRa09OyrE_N09p9juipuur0w@mail.gmail.com>

On 22 November 2016 at 10:43, Matteo Grandi <iu5bdp@gmail.com> wrote:
> Dear Bob, Michal, all
>
> I've finally managed to have a 80MHz channel bandwidth, thanks to your hint!
> The problem was related to the CRDA that even if it looks correctly
> installed, it actually doesn't work as supposed.
> I downloaded and recompiled the CRDA-3.18
> (http://drvbp1.linux-foundation.org/~mcgrof/rel-html/crda/) and set-up
> the regulatory domain.
> Notice that without setting up the reg. domain all the available
> channels have the "passive scanning" label because the CRDA prevent
> beaconing so mesh mode is not possible (maybe it's otherwise possible
> to operate in STA mode that doesn't require to send frames(?)).

STA can be allowed to transmit via beacon hints as far as I understand.


> Now I can have a mesh communication using 80MHz channel bandwidth, but
> MIMO still doesn't work.
> In fact the highest MCS reached was MCS9 that is the highest MCS with
> Single Spatial Stream, and I can't managed to have MIMO.

11n used mcs to imply nss. 11ac treats mcs and nss separately.
Therefore saying "MCS9 is 1SS" is incorrect. How are you checking
this? What device are you using for verifying?


> I played with the antennas position and distance, with the
> polarization and the presence or not of LOS, but by sniffing the
> transmissions I sow only MCS9 even if in the radiotap header field
> there are Antenna 0 and Antenna 1.
> However the radio information field report "Spatial streams: 1".
>
> Does anyone experienced something similar with the use of MIMO in mesh
> mode with the ath10k fw?
> I will thank any light you can shed to this!
> Thank you very much

You might want to debug peer_assoc commands sent to firmware. They may
be, for some reason, be requesting nss=1. Maybe sta_rc_update() isn't
properly updating peer in firmware. Driver debugs/dumps
(debug_mask=0xffffffffff) would be useful.


Michal

^ permalink raw reply

* Re: [PATCH] rtl8xxxu: Fix failure to reconnect to AP
From: Jes Sorensen @ 2016-11-22 15:01 UTC (permalink / raw)
  To: Barry Day; +Cc: Kalle Valo, linux-wireless
In-Reply-To: <20161122125300.GB23278@testbox>

Barry Day <briselec@gmail.com> writes:
> On Mon, Nov 21, 2016 at 11:57:22AM -0500, Jes Sorensen wrote:
>> Jes Sorensen <Jes.Sorensen@redhat.com> writes:
>> >>  void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv)
>> >> @@ -4515,6 +4523,8 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>> >>  				sgi = 1;
>> >>  			rcu_read_unlock();
>> >>  
>> >> +			rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff);
>> >> +
>> >>  			priv->fops->update_rate_mask(priv, ramask, sgi);
>> >>  
>> >>  			rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
>> 
>> I believe this change only matters because you disable RXFLTMAP2
>> above. If we really have to write to RXFLTMAP2 to make this work, I
>> suspect we need to keep some sort of state information.
>> 
>> I would also be curious if RXFLTMAP2 gets reset somehow by the firmware,
>> and we do not account for that.
>> 
>> Cheers,
>> Jes
>
> I'll redo the patch without touching REG_RXFLTMAP2. I don't think it's needed
> to fix the fail to reconnect issue.
>
> I haven't had a proper look at the 8723 chips yet but the vendor drivers for
> the others don't do a h2c cmd for disconnect but I'll test leaving it in to see
> if it makes any difference. A 8723bu arrived in the mail today so now I can
> test it too and I discovered yesterday I have a 8723au but it's in a cheap
> Android tablet.

Let me know what you find out - if the h2c command causes the failure
that would be very bizarre but certainly interesting to learn.

Cheers,
Jes

^ permalink raw reply

* Re: [v5,1/5] soc: qcom: smem_state: Fix include for ERR_PTR()
From: Valo, Kalle @ 2016-11-22 14:55 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: k.eugene.e@gmail.com, Andy Gross, wcn36xx@lists.infradead.org,
	linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org
In-Reply-To: <20161118183541.GI28340@tuxbot>

Bjorn Andersson <bjorn.andersson@linaro.org> writes:

> On Wed 16 Nov 10:49 PST 2016, Kalle Valo wrote:
>
>> Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
>> > The correct include file for getting errno constants and ERR_PTR() is
>> > linux/err.h, rather than linux/errno.h, so fix the include.
>> >=20
>> > Fixes: e8b123e60084 ("soc: qcom: smem_state: Add stubs for disabled sm=
em_state")
>> > Acked-by: Andy Gross <andy.gross@linaro.org>
>> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
>>=20
>> For some reason this fails to compile now. Can you take a look, please?
>>=20
>> ERROR: "qcom_wcnss_open_channel" [drivers/net/wireless/ath/wcn36xx/wcn36=
xx.ko] undefined!
>> make[1]: *** [__modpost] Error 1
>> make: *** [modules] Error 2
>>=20
>> 5 patches set to Changes Requested.
>>=20
>> 9429045 [v5,1/5] soc: qcom: smem_state: Fix include for ERR_PTR()
>> 9429047 [v5,2/5] wcn36xx: Transition driver to SMD client
>
> This patch was updated with the necessary depends in Kconfig to catch
> this exact issue and when I pull in your .config (which has QCOM_SMD=3Dn,
> QCOM_WCNSS_CTRL=3Dn and WCN36XX=3Dy) I can build this just fine.
>
> I've tested the various combinations and it seems to work fine. Do you
> have any other patches in your tree?

This was with the pending branch of my ath.git tree. There are other
wireless patches (ath10k etc) but I would guess they don't affect here.

> Any stale objects?

Not sure what you mean with this question, but I didn't run 'make clean'
if that's what you are asking.

> Would you mind retesting this, before I invest more time in trying to
> reproduce the issue you're seeing?

Sure, I'll take a look but that might take few days.

--=20
Kalle Valo=

^ permalink raw reply

* Re: [RFC] qtn: add FullMAC firmware for Quantenna QSR10G wifi device
From: IgorMitsyanko @ 2016-11-22 14:44 UTC (permalink / raw)
  To: Ben Hutchings, Kyle McMartin
  Cc: Johannes Berg, linux-wireless, btherthala, hwang, smaksimenko,
	dlebed, Igor Mitsyanko, Kamlesh Rath, Sergey Matyukevich,
	Avinash Patil
In-Reply-To: <1478864146.4129.4.camel@sipsolutions.net>

Hi Ben, Kyle,
could you please share what is the position of linux-firmware regarding 
firmware binaries that include GPL components? Does it require entire 
GPL components codebase be present in linux-firmware tree, or maybe 
having this clause in license file is enough:
+Open Source Software. The Software may include components that are licensed
+pursuant to open source software (“Open Source Components”). Information
+regarding the Open Source Components included with the Software is 
available
+upon request to oslegal@quantenna.com. To the extent such Open Source
+Components are required to be licensed to you under the terms of a separate
+license (such as an open source license) then such other terms shall 
apply, and
+nothing herein shall be deemed or interpreted to limit any rights you 
may have
+under any such applicable license.

 From technical perspective, size of the codebase used to build 
Quantenna firmware is a few hundred MBs, it seems too much to include 
into linux-firmware tree.

On 11/11/2016 02:35 PM, Johannes Berg wrote:
> Adding linux-firmware people to Cc, since presumably they don't
> necessarily read linux-wireless...
>
>> Johannes, from that perspective, who are the "redistributors"?
>> Specifically, is linux-firmware git repository considered a
>> redistributor or its just hosting files? I mean, at what moment
>> someone else other then Quantenna will start to be legally obliged to
>> make GPL code used in firmware available for others?
> Look, I don't know. I'd assume people who ship it, like any regular
> distro, would be (re)distributors thereof. "Normal" (non-GPL) firmware
> images come with a redistribution license, but that obviously can't
> work here.
>
> There's some info from Ben here regarding the carl9170 case:
> http://lkml.iu.edu/hypermail/linux/kernel/1605.3/01176.html
>
>> Personally I still hope that linux-firmware itself is not legally
>> concerned with what is the content of firmware its hosting, but looks
>> like there already was a precedent case  with carl9170 driver and
>> we have to somehow deal with it.
> That's really all I wanted to bring up. I'm not involved with the
> linux-firmware git tree.
>
>> There still may be a difference though: Quantenna is semiconductor
>> company only, software
>> used on actual products based on Quantenna chipsets is released by
>> other
>> companies.
>> I just want to present our legal team with a clear case (and position
>> of
>> Linux maintainers) so that they can
>> work with it and make decision on how to proceed.
>>
>>   From technical perspective, as I mentioned, SDK is quite huge and
>> include a lot of opensource
>> components including full Linux, I don't think its reasonable to have
>> it
>> inside linux-firmware tree.
>> What are the options to share it other then providing it on request
>> basis:
>> - git repository
>> - store tarball somewhere on official website
> Clearly that wasn't deemed appropriate for carl9170, so I don't see why
> it'd be different here.
>
> johannes

^ permalink raw reply

* Re: [PATCH] nl80211: provide minimum scheduled scan (plan) interval
From: Johannes Berg @ 2016-11-22 13:38 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linux-wireless
In-Reply-To: <1479821515-13261-1-git-send-email-arend.vanspriel@broadcom.com>


> +		if (wiphy->min_sched_scan_plan_interval &&
> +		    request->scan_plans[i].interval <
> +		    wiphy->min_sched_scan_plan_interval)
> +			return -EINVAL;
> 
I'm not sure we should break the API that way - just move it up if it's
smaller?

johannes

^ permalink raw reply

* [PATCH] nl80211: provide minimum scheduled scan (plan) interval
From: Arend van Spriel @ 2016-11-22 13:31 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Arend van Spriel

The interval for scheduled scan may have a minimum value for
the device. Allow drivers to specify a minimum value in the
struct wiphy so user-space interval values can be validated
against it.

Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
---
 include/net/cfg80211.h       |  3 +++
 include/uapi/linux/nl80211.h |  2 ++
 net/wireless/nl80211.c       | 12 ++++++++++++
 3 files changed, 17 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2019310..ef5d6ab 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3427,6 +3427,8 @@ struct wiphy_iftype_ext_capab {
  *	scans
  * @max_sched_scan_plans: maximum number of scan plans (scan interval and number
  *	of iterations) for scheduled scan supported by the device.
+ * @min_sched_scan_plan_interval: minimum interval (in seconds) for a
+ *	single scan plan supported by the device.
  * @max_sched_scan_plan_interval: maximum interval (in seconds) for a
  *	single scan plan supported by the device.
  * @max_sched_scan_plan_iterations: maximum number of iterations for a single
@@ -3552,6 +3554,7 @@ struct wiphy {
 	u16 max_scan_ie_len;
 	u16 max_sched_scan_ie_len;
 	u32 max_sched_scan_plans;
+	u32 min_sched_scan_plan_interval;
 	u32 max_sched_scan_plan_interval;
 	u32 max_sched_scan_plan_iterations;
 
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 259c9c7..77fc77a 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2381,6 +2381,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED,
 
+	NL80211_ATTR_MIN_SCAN_PLAN_INTERVAL,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 24ab199..47aca56 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1474,6 +1474,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
 				rdev->wiphy.max_sched_scan_plans) ||
 		    nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
 				rdev->wiphy.max_sched_scan_plan_interval) ||
+		    nla_put_u32(msg, NL80211_ATTR_MIN_SCAN_PLAN_INTERVAL,
+				rdev->wiphy.min_sched_scan_plan_interval) ||
 		    nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
 				rdev->wiphy.max_sched_scan_plan_iterations))
 			goto nla_put_failure;
@@ -6777,6 +6779,12 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
 		if (!request->scan_plans[0].interval)
 			return -EINVAL;
 
+		if (wiphy->min_sched_scan_plan_interval &&
+		    request->scan_plans[0].interval <
+		    wiphy->min_sched_scan_plan_interval)
+			request->scan_plans[0].interval =
+				wiphy->min_sched_scan_plan_interval;
+
 		if (request->scan_plans[0].interval >
 		    wiphy->max_sched_scan_plan_interval)
 			request->scan_plans[0].interval =
@@ -6805,6 +6813,10 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
 		    request->scan_plans[i].interval >
 		    wiphy->max_sched_scan_plan_interval)
 			return -EINVAL;
+		if (wiphy->min_sched_scan_plan_interval &&
+		    request->scan_plans[i].interval <
+		    wiphy->min_sched_scan_plan_interval)
+			return -EINVAL;
 
 		if (plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]) {
 			request->scan_plans[i].iterations =
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH] nl80211: change validation of scheduled scan interval values
From: Luca Coelho @ 2016-11-22 13:17 UTC (permalink / raw)
  To: Arend Van Spriel, Johannes Berg; +Cc: linux-wireless
In-Reply-To: <9fa76f2c-44b2-9782-8636-09afd1d59927@broadcom.com>

On Tue, 2016-11-22 at 14:12 +0100, Arend Van Spriel wrote:
> On 22-11-2016 11:22, Arend van Spriel wrote:
> > When user-space does not provide scheduled scan plans, ie. uses the
> > old scheduled scan API containing NL80211_ATTR_SCHED_SCAN_INTERVAL.
> > The interval value passed by user-space is validated against
> > struct wiphy::max_sched_scan_plan_interval and if it is exceeding
> > it the interval is set to struct wiphy::max_sched_scan_plan_interval.
> > However, when the driver does not set this limit the interval the
> > interval in the request will always be zero. Hence add a check to
> > see whether the driver set struct wiphy::max_sched_scan_plan_interval.
> > 
> > For the new API, ie. for scheduled scan plans, the interval validation
> > has been simalarly adjusted to assure the limit is non-zero.
> 
> Actually turns out that max_sched_scan_plan_interval is always set in
> wiphy_new_nm() which is used by all drivers so please drop this patch.

Right, I mixed mac80211 into the picture and got confused.

--
Luca.

^ permalink raw reply

* Re: [PATCH] nl80211: change validation of scheduled scan interval values
From: Arend Van Spriel @ 2016-11-22 13:12 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1479810126-28492-1-git-send-email-arend.vanspriel@broadcom.com>

On 22-11-2016 11:22, Arend van Spriel wrote:
> When user-space does not provide scheduled scan plans, ie. uses the
> old scheduled scan API containing NL80211_ATTR_SCHED_SCAN_INTERVAL.
> The interval value passed by user-space is validated against
> struct wiphy::max_sched_scan_plan_interval and if it is exceeding
> it the interval is set to struct wiphy::max_sched_scan_plan_interval.
> However, when the driver does not set this limit the interval the
> interval in the request will always be zero. Hence add a check to
> see whether the driver set struct wiphy::max_sched_scan_plan_interval.
> 
> For the new API, ie. for scheduled scan plans, the interval validation
> has been simalarly adjusted to assure the limit is non-zero.

Actually turns out that max_sched_scan_plan_interval is always set in
wiphy_new_nm() which is used by all drivers so please drop this patch.

Regards,
Arend

> Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> ---
>  net/wireless/nl80211.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 24ab199..e621554 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -6777,7 +6777,8 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
>  		if (!request->scan_plans[0].interval)
>  			return -EINVAL;
>  
> -		if (request->scan_plans[0].interval >
> +		if (wiphy->max_sched_scan_plan_interval &&
> +		    request->scan_plans[0].interval >
>  		    wiphy->max_sched_scan_plan_interval)
>  			request->scan_plans[0].interval =
>  				wiphy->max_sched_scan_plan_interval;
> @@ -6801,7 +6802,10 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
>  
>  		request->scan_plans[i].interval =
>  			nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_INTERVAL]);
> -		if (!request->scan_plans[i].interval ||
> +		if (!request->scan_plans[i].interval)
> +			return -EINVAL;
> +
> +		if (wiphy->max_sched_scan_plan_interval &&
>  		    request->scan_plans[i].interval >
>  		    wiphy->max_sched_scan_plan_interval)
>  			return -EINVAL;
> 

^ permalink raw reply

* Re: scheduled scan interval
From: Arend Van Spriel @ 2016-11-22 13:09 UTC (permalink / raw)
  To: Luca Coelho, Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1479806342.2517.44.camel@coelho.fi>

On 22-11-2016 10:19, Luca Coelho wrote:
> On Tue, 2016-11-22 at 10:10 +0100, Arend Van Spriel wrote:
>> On 22-11-2016 6:59, Luca Coelho wrote:
>>> Oh, I see.  The problem is that the "max_sched_scan_plan_interval" was
>>> introduced later.  If the userspace passes
>>> NL80211__ATTR_SCHED_SCAN_INTERVAL, it probably means that it doesn't
>>> know about NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL (i.e. it's only using an
>>> old API).  If it is also, for some reason, passing a very large number,
>>> we shouldn't suddenly make it fail with -EINVALID, because that would
>>> be a break of UABI.  And since we know the driver cannot support such a
>>> large number, we cap it because it's the best we can do.
>>>
>>> Now, if the userspace uses NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL, it
>>> means that it knows the new API (and was written after the new API was
>>> introduced), so we can be stricter and assume it must have checked
>>> NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL.
>>>
>>> Makes sense?
>>
>> Not really. As you say if user-space passes
>> NL80211_ATTR_SCHED_SCAN_INTERVAL it is using old API. Otherwise it
>> should pass NL80211_ATTR_SCHED_SCAN_PLANS.
> 
> Errr... I meant "if the userspace uses NL80211_ATTR_SCHED_SCAN_PLANS",
> pasted the wrong thing. ;)
> 
> 
>> If the driver doesn't set the max_sched_scan_plan_interval, mac80211's
>>> default of MAX_U32 will be used:
>>>
>>> struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
>>> 			   const char *requested_name)
>>> {
>>> [...]
>>> 	rdev->wiphy.max_sched_scan_plans = 1;
>>> 	rdev->wiphy.max_sched_scan_plan_interval = U32_MAX;
>>>
>>> 	return &rdev->wiphy;
>>> }
>>> EXPORT_SYMBOL(wiphy_new_nm);
>>>
>>> ...so max_sched_scan_plan_interval will never be zero, unless the
>>> driver explicitly sets it to zero.
>>
>> I think you are overlooking the cfg80211-based drivers here. According
>> to lxr at least brcmfmac, mwifiex, and ath6kl are not specifying it.
>> "Funny" detail is that scheduled scan support in mwifiex seems to be
>> introduced after the scan plan API change.
> 
> You're right, I did overlook non-mac80211 drivers.

Actually, you are referring to wiphy_new_nm() which is obviously used
for cfg80211-based drivers as well. So I will ask to drop my patch.

Regards,
Arend

^ permalink raw reply

* Re: [PATCH] rtl8xxxu: Fix failure to reconnect to AP
From: Barry Day @ 2016-11-22 12:53 UTC (permalink / raw)
  To: Jes Sorensen; +Cc: Kalle Valo, linux-wireless
In-Reply-To: <wrfjbmx87oul.fsf@redhat.com>

On Mon, Nov 21, 2016 at 11:57:22AM -0500, Jes Sorensen wrote:
> Jes Sorensen <Jes.Sorensen@redhat.com> writes:
> > Barry Day <briselec@gmail.com> writes:
> >> The rtl8192e and rtl8723 fail to reconnect to an AP after being
> >> disconnected. Ths patch fixes that without affecting the rtl8192cu.
> >> I don't have a rtl8723 to test but it has been tested on a rtl8192eu.
> >> After going through the orginal realtek code for the rtl8723, I am
> >> confident the patch is applicable to both.
> >>
> >> Signed-off-by: Barry Day <briselec@gmail.com>
> >> ---
> >>  rtl8xxxu_core.c | 18 ++++++++++++++----
> >>  1 file changed, 14 insertions(+), 4 deletions(-)
> >
> > Hi Barry,
> >
> > Thank you for the patch. There are a couple of items which I am not
> > 100% sure about the order of.
> >
> >> diff --git a/rtl8xxxu_core.c b/rtl8xxxu_core.c
> >> index 04141e5..6ac10d2 100644
> >> --- a/rtl8xxxu_core.c
> >> +++ b/rtl8xxxu_core.c
> >> @@ -4372,17 +4372,25 @@ void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
> >>  void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
> >>  				  u8 macid, bool connect)
> >>  {
> >> +	u8 val8;
> >>  	struct h2c_cmd h2c;
> >>  
> >>  	memset(&h2c, 0, sizeof(struct h2c_cmd));
> >>  
> >>  	h2c.media_status_rpt.cmd = H2C_8723B_MEDIA_STATUS_RPT;
> >> -	if (connect)
> >> +	if (connect) {
> >>  		h2c.media_status_rpt.parm |= BIT(0);
> >> -	else
> >> -		h2c.media_status_rpt.parm &= ~BIT(0);
> >> +		rtl8xxxu_gen2_h2c_cmd(priv, &h2c,
> >> +					sizeof(h2c.media_status_rpt));
> >> +	} else {
> >> +		val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
> >> +		val8 &= ~BEACON_FUNCTION_ENABLE;
> >> +
> >> +		rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
> >> +		rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x00);
> >> +		rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
> >> +	}
> >>  
> >> -	rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt));
> >>  }
> 
> Barry,
> 
> So looking at this again, I am pretty sure you will break monitor mode
> with this. By setting REG_RXFLTMAP2 to 0x0000 you stop reception of all
> data frames.
> 
> The other thing here is that you change removes the part notifying the
> firmware that we disconnected since you now only send the
> media_start_rpt command on connect, but not on disconnect.
> 
> I am curious if the problem goes away if you simply add the BEACON_CTRL
> and REG_DUAL_TSF_RST parts?
> 
> >
> > This only affects 8192eu and not 8192cu - we left RXFLTMAP2 out of here
> > on purpose for monitor mode, but you now disable it for 8192eu/8723bu.
> >
> >>  void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv)
> >> @@ -4515,6 +4523,8 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> >>  				sgi = 1;
> >>  			rcu_read_unlock();
> >>  
> >> +			rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff);
> >> +
> >>  			priv->fops->update_rate_mask(priv, ramask, sgi);
> >>  
> >>  			rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
> 
> I believe this change only matters because you disable RXFLTMAP2
> above. If we really have to write to RXFLTMAP2 to make this work, I
> suspect we need to keep some sort of state information.
> 
> I would also be curious if RXFLTMAP2 gets reset somehow by the firmware,
> and we do not account for that.
> 
> Cheers,
> Jes
> 

I'll redo the patch without touching REG_RXFLTMAP2. I don't think it's needed
to fix the fail to reconnect issue.

I haven't had a proper look at the 8723 chips yet but the vendor drivers for
the others don't do a h2c cmd for disconnect but I'll test leaving it in to see
if it makes any difference. A 8723bu arrived in the mail today so now I can
test it too and I discovered yesterday I have a 8723au but it's in a cheap
Android tablet.

Barry

^ permalink raw reply

* Re: [PATCH 0/7] rtl8xxxu: Pending patches
From: Barry Day @ 2016-11-22 12:26 UTC (permalink / raw)
  To: Jes Sorensen; +Cc: linux-wireless, kvalo, Larry.Finger
In-Reply-To: <wrfj7f7w7oqk.fsf@redhat.com>

On Mon, Nov 21, 2016 at 11:59:47AM -0500, Jes Sorensen wrote:
> Barry Day <briselec@gmail.com> writes:
> > On Sat, Nov 19, 2016 at 06:53:42PM -0500, Jes Sorensen wrote:
> >> Barry Day <briselec@gmail.com> writes:
> >> > On Fri, Nov 18, 2016 at 09:00:10PM -0500, Jes Sorensen wrote:
> >> >> Barry Day <briselec@gmail.com> writes:
> >> >> > On Fri, Nov 18, 2016 at 04:44:21PM -0500, Jes.Sorensen@redhat.com wrote:
> >> >> >> From: Jes Sorensen <Jes.Sorensen@redhat.com>
> >> >> >> 
> >> >> >> Kalle,
> >> >> >> 
> >> >> >> Please find attached a number of patches for the rtl8xxxu
> >> >> >> driver.
> >> >> >> 
> >> >> >> The issues reported with wpa_supplicant on 8723bu still needs further
> >> >> >> investigation.
> >> >> >> 
> >> >> >
> >> >> > The patch I posted that you want tested more will also fix the
> >> >> > wpa_supplicant issue.  Currently I'm looking at why the tx rate is not
> >> >> > what it should be. I feel fixing that first will be beneficial for
> >> >> > fixing any other issues.
> >> >> 
> >> >> Interesting, I was thinking that might be the case. I do want to dig
> >> >> into this further to understand it better. If we use your solution I
> >> >> will want to make sure we cover both gen1 and gen2 parts.
> >> >> 
> >> >> > The recent merge has made my local branch of rtl8xxxu-devel 14
> >> >> > commits ahead.
> >> >> > Do I need to do a reset and submit a new patch for the DWA-131 dongle?
> >> >> 
> >> >> In general you need to use 'git pull --rebase' on my tree. I rebase it
> >> >> to stay in sync with Kalle's tree.
> >> >> 
> >> >> The DWA-131 is the 8192eu? Sorry a bit behind and my mind is losing
> >> >> bits. If it's the patch you posted earlier I can dig it out and play
> >> >> with it - I am still catching up though, so please be patient.
> >> >
> >> > yes it's an 8192eu.
> >> 
> >> Gotcha - how do you do your testing to reproduce the problem btw? Most
> >> of my testing is using the 8723au as a primary device and the next
> >> device as a follow-on, so I may not see as long a run with the device
> >> active as you see.
> >> 
> >
> > Testing is simple. Connect to an AP in the usual
> > manner..disconnect..reconnect.  The 8192eu will fail to reconnect and
> > John Heenan reported the 8723bu also fails to reconnect. Even though
> > he was directly stopping and restarting wpa_supplicant, it's the same
> > thing to the driver - connect..disconnect..reconnect.
> 
> Thanks for the details - I'll have a look shortly.
> 
> > With using a usb_device pointer, each message starts with the usb bus
> > address.  Plug it into a different port and that address could
> > change. By using a pointer to the device associated with the wiphy
> > each message will begin with the driver name. Just makes it easier for
> > the average user to report what's in the log because he can just grep
> > for "rtl8xxxu".
> 
> I see - that would be problematic for me as I quite often have 3-4 of
> these things plugged in at the same time. Not knowing which port spits
> out the message would make it a lot harder to track. In fact my primary
> devel box for this (Lenovo Yoga 13) has an rtl8723au soldered on the
> motherboard, so the moment I plug in any other dongle I'll have two.
> 
> The alternative would be to add a prefer to the individual messages.
> 
> Cheers,
> Jes

I should have mentioned it also places the usb address after the driver name.

^ permalink raw reply

* [PATCH] ath9k: feed only active spectral / dfs-detector
From: Zefir Kurtisi @ 2016-11-22 11:05 UTC (permalink / raw)
  To: linux-wireless; +Cc: kvalo, michal.kazior, benjamin

Radar pulse and spectral scan reports are provided by the HW
with the ATH9K_RXERR_PHY flag set. Those are forwarded to
the dfs-detector and spectral module for further processing.

For some older chips, the pre-conditions checked in those
modules are ambiguous, since ATH9K_PHYERR_RADAR is used to
tag both types. As a result, spectral frames are fed into
the dfs-detector and vice versa.

This could lead to a false radar detection on a non-DFS
channel (which is uncritical), but more relevant it causes
useless CPU load for processing invalid frames.

This commit ensures that the dfs-detector and spectral
collector are only fed when they are active.

Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
---
 drivers/net/wireless/ath/ath9k/recv.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 6697342..48f8af1 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -867,10 +867,21 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
 	 * can be dropped.
 	 */
 	if (rx_stats->rs_status & ATH9K_RXERR_PHY) {
-		ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime);
-		if (ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats, rx_status->mactime))
+		/*
+		 * DFS and spectral are mutually exclusive
+		 *
+		 * Since some chips use PHYERR_RADAR as indication for both, we
+		 * need to double check which feature is enabled to prevent
+		 * feeding spectral or dfs-detector with wrong frames.
+		 */
+		if (hw->conf.radar_enabled) {
+			ath9k_dfs_process_phyerr(sc, hdr, rx_stats,
+						 rx_status->mactime);
+		} else if (sc->spec_priv.spectral_mode != SPECTRAL_DISABLED &&
+			   ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats,
+					       rx_status->mactime)) {
 			RX_STAT_INC(rx_spectral);
-
+		}
 		return -EINVAL;
 	}
 
-- 
2.7.4

^ permalink raw reply related

* Re: Break-it testing for wifi
From: Johannes Berg @ 2016-11-22 10:56 UTC (permalink / raw)
  To: Ben Greear, linux-wireless@vger.kernel.org
In-Reply-To: <a60dac22-655e-ea93-61c2-73db05a47572@candelatech.com>

On Mon, 2016-11-21 at 08:10 -0800, Ben Greear wrote:

> I am thinking about adding some sort of framework to wpa_supplicant
> and/or the mac80211 stack to allow purposefully creating bad station
> behaviour in order to test robustness of APs.

I'm interested in this.

Have you seen the fuzzer stuff in wpa_s/hostapd?

See

https://w1.fi/cgit/hostap/commit/?id=7d3f18d72c3c883112ee927fc402c0eaed09ff65

for example for something Jouni did after our discussions recently.

> Some ideas so far:
> 
> 1)  Allow supplicant to do bad state-machine transitions (start 4-way 
> before associating, for instance).

Why would you do that? In order to test the AP implementation?

> 2)  Randomly corrupt mgt frames in driver and/or mac80211 stack
> and/or supplicant.

I think fuzzing the input path for those frames would be more useful
than just corrupting things.

> 3)  Possibly allow user to make specific corruptions.  This would
> probably be in supplicant
>      only, and I am not sure how this would be configured.  Maybe
> allow user to over-ride
>      existing IEs and add bogus ones of their own choosing.

No idea what you really mean by this :)

> 4)  Maybe some specific tests like putting in over-flow sized lengths
> of IEs.

Again, fuzzing would cover this?

> Has anyone done anything similar they would like to share?
> 
> Johannes:  Any interest in having such a framework in upstream
> kernels?

I suspect you have something entirely different in mind, like testing a
(remote) AP implementation?

All of the local testing is probably better done via hwsim?

johannes

^ permalink raw reply

* [PATCH v8] mac80211: multicast to unicast conversion
From: Michael Braun @ 2016-11-22 10:52 UTC (permalink / raw)
  To: johannes; +Cc: Michael Braun, linux-wireless, netdev, projekt-wlan

Add the ability for an AP (and associated VLANs) to perform
multicast-to-unicast conversion for ARP, IPv4 and IPv6 frames
(possibly within 802.1Q). If enabled, such frames are to be sent
to each station separately, with the DA replaced by their own
MAC address rather than the group address.

Note that this may break certain expectations of the receiver,
such as the ability to drop unicast IP packets received within
multicast L2 frames, or the ability to not send ICMP destination
unreachable messages for packets received in L2 multicast (which
is required, but the receiver can't tell the difference if this
new option is enabled.)

This also doesn't implement the 802.11 DMS (directed multicast
service).

Signed-off-by: Michael Braun <michael-dev@fami-braun.de>

--
v8:
  - remove superflous check
  - change return type to bool
v7:
  - avoid recursion
  - style and description
v5:
  - rename bss->unicast to bss->multicast_to_unicast
  - access sdata->bss only after checking iftype
v4:
  - rename MULTICAST_TO_UNICAST to MULTICAST_TO_UNICAST
v3: fix compile error for trace.h
v2: add nl80211 toggle
    rename tx_dnat to change_da
    change int to bool unicast
---
 net/mac80211/cfg.c            |  12 +++++
 net/mac80211/debugfs_netdev.c |   3 ++
 net/mac80211/ieee80211_i.h    |   1 +
 net/mac80211/tx.c             | 122 +++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 137 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1edb017..7de342a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3345,6 +3345,17 @@ static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
 	return -ENOENT;
 }
 
+static int ieee80211_set_multicast_to_unicast(struct wiphy *wiphy,
+					      struct net_device *dev,
+					      const bool enabled)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	sdata->u.ap.multicast_to_unicast = enabled;
+
+	return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -3430,4 +3441,5 @@ const struct cfg80211_ops mac80211_config_ops = {
 	.set_ap_chanwidth = ieee80211_set_ap_chanwidth,
 	.add_tx_ts = ieee80211_add_tx_ts,
 	.del_tx_ts = ieee80211_del_tx_ts,
+	.set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
 };
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ed7bff4..509c6c3 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -487,6 +487,8 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast(
 }
 IEEE80211_IF_FILE_R(num_buffered_multicast);
 
+IEEE80211_IF_FILE(multicast_to_unicast, u.ap.multicast_to_unicast, HEX);
+
 /* IBSS attributes */
 static ssize_t ieee80211_if_fmt_tsf(
 	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
@@ -642,6 +644,7 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
 	DEBUGFS_ADD(dtim_count);
 	DEBUGFS_ADD(num_buffered_multicast);
 	DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
+	DEBUGFS_ADD_MODE(multicast_to_unicast, 0600);
 }
 
 static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 70c0963..84374ed 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -293,6 +293,7 @@ struct ieee80211_if_ap {
 			 driver_smps_mode; /* smps mode request */
 
 	struct work_struct request_smps_work;
+	bool multicast_to_unicast;
 };
 
 struct ieee80211_if_wds {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c3ce86e..5effffd 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/skbuff.h>
+#include <linux/if_vlan.h>
 #include <linux/etherdevice.h>
 #include <linux/bitmap.h>
 #include <linux/rcupdate.h>
@@ -3418,6 +3419,115 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
 	rcu_read_unlock();
 }
 
+static int ieee80211_change_da(struct sk_buff *skb, struct sta_info *sta)
+{
+	struct ethhdr *eth;
+	int err;
+
+	err = skb_ensure_writable(skb, ETH_HLEN);
+	if (unlikely(err))
+		return err;
+
+	eth = (void *)skb->data;
+	ether_addr_copy(eth->h_dest, sta->sta.addr);
+
+	return 0;
+}
+
+static inline bool
+ieee80211_multicast_to_unicast(struct sk_buff *skb, struct net_device *dev)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	const struct ethhdr *eth = (void *)skb->data;
+	const struct vlan_ethhdr *ethvlan = (void *)skb->data;
+	u16 ethertype;
+
+	if (likely(!is_multicast_ether_addr(eth->h_dest)))
+		return 0;
+
+	switch (sdata->vif.type) {
+	case NL80211_IFTYPE_AP_VLAN:
+		if (sdata->u.vlan.sta)
+			return 0;
+		if (sdata->wdev.use_4addr)
+			return 0;
+		/* fall through */
+	case NL80211_IFTYPE_AP:
+		/* check runtime toggle for this bss */
+		if (!sdata->bss->multicast_to_unicast)
+			return 0;
+		break;
+	default:
+		return 0;
+	}
+
+	/* multicast to unicast conversion only for some payload */
+	ethertype = ntohs(eth->h_proto);
+	if (ethertype == ETH_P_8021Q && skb->len >= VLAN_ETH_HLEN)
+		ethertype = ntohs(ethvlan->h_vlan_encapsulated_proto);
+	switch (ethertype) {
+	case ETH_P_ARP:
+	case ETH_P_IP:
+	case ETH_P_IPV6:
+		break;
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+static void
+ieee80211_convert_to_unicast(struct sk_buff *skb, struct net_device *dev,
+			     struct sk_buff_head *queue)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_local *local = sdata->local;
+	const struct ethhdr *eth = (struct ethhdr *)skb->data;
+	struct sta_info *sta, *first = NULL;
+	struct sk_buff *cloned_skb;
+
+	rcu_read_lock();
+
+	list_for_each_entry_rcu(sta, &local->sta_list, list) {
+		if (sdata != sta->sdata)
+			/* AP-VLAN mismatch */
+			continue;
+		if (unlikely(ether_addr_equal(eth->h_source, sta->sta.addr)))
+			/* do not send back to source */
+			continue;
+		if (!first) {
+			first = sta;
+			continue;
+		}
+		cloned_skb = skb_clone(skb, GFP_ATOMIC);
+		if (!cloned_skb)
+			goto unicast;
+		if (unlikely(ieee80211_change_da(cloned_skb, sta))) {
+			dev_kfree_skb(cloned_skb);
+			goto unicast;
+		}
+		__skb_queue_tail(queue, cloned_skb);
+	}
+
+	if (likely(first)) {
+		if (unlikely(ieee80211_change_da(skb, first)))
+			goto unicast;
+		__skb_queue_tail(queue, skb);
+	} else {
+		/* no STA connected, drop */
+		kfree_skb(skb);
+		skb = NULL;
+	}
+
+	goto out;
+unicast:
+	__skb_queue_purge(queue);
+	__skb_queue_tail(queue, skb);
+out:
+	rcu_read_unlock();
+}
+
 /**
  * ieee80211_subif_start_xmit - netif start_xmit function for 802.3 vifs
  * @skb: packet to be sent
@@ -3428,7 +3538,17 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
 netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 				       struct net_device *dev)
 {
-	__ieee80211_subif_start_xmit(skb, dev, 0);
+	if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) {
+		struct sk_buff_head queue;
+
+		__skb_queue_head_init(&queue);
+		ieee80211_convert_to_unicast(skb, dev, &queue);
+		while ((skb = __skb_dequeue(&queue)))
+			__ieee80211_subif_start_xmit(skb, dev, 0);
+	} else {
+		__ieee80211_subif_start_xmit(skb, dev, 0);
+	}
+
 	return NETDEV_TX_OK;
 }
 
-- 
2.1.4

^ permalink raw reply related

* [PATCH 3/3][RESEND][RFC] nl80211/mac80211: Accept multiple RSSI thresholds for CQM
From: Andrew Zaborowski @ 2016-11-22 10:29 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <1479810592-2474-1-git-send-email-andrew.zaborowski@intel.com>

Change the SET CQM command RSSI threshold attribute semantic to accept
any number of thresholds as a sorted array.  The API should be backwards
compatible so that if one s32 threshold value is passed, the old
mechanism is enabled.  The netlink event generated is the same too.

cfg80211 handles an arbitrary number of RSSI thresholds but drivers have
to provide a method (set_cqm_rssi_range_config) that configures a range
set by a high and a low value.  Drivers have to call back when the RSSI
goes out of that range and there's no additional event every time the
range is reconfigured.  There's no reason that the whole mechanism with
more than 2 thresholds couldn't be offloaded if the was hardware
available.

I added only a mac80211 implementation of the set_cqm_rssi_range_config
method as an illustration and because I can't run-time test any other
driver.  In this patch there's also no API for mac80211-based drivers
that do beacon filtering to offload this but that would be the intended
use.
---
 include/net/cfg80211.h       |  12 ++++
 include/net/mac80211.h       |   6 ++
 include/uapi/linux/nl80211.h |   4 +-
 net/mac80211/cfg.c           |  28 +++++++++
 net/mac80211/mlme.c          |  24 ++++++++
 net/wireless/core.c          |  13 ++++
 net/wireless/core.h          |   9 +++
 net/wireless/nl80211.c       | 137 +++++++++++++++++++++++++++++++++++++++----
 net/wireless/rdev-ops.h      |  12 ++++
 net/wireless/trace.h         |  22 +++++++
 10 files changed, 255 insertions(+), 12 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 632dce1..0105e86 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2604,6 +2604,10 @@ struct cfg80211_nan_func {
  *	the current level is above/below the configured threshold; this may
  *	need some care when the configuration is changed (without first being
  *	disabled.)
+ * @set_cqm_rssi_range_config: Configure two RSSI thresholds in the
+ *	connection quality monitor.  Even if the driver implements both the
+ *	single threshold and low/high thresholds mechanisms, it should assume
+ *	only one is active at any time.
  * @set_cqm_txe_config: Configure connection quality monitor TX error
  *	thresholds.
  * @sched_scan_start: Tell the driver to start a scheduled scan.
@@ -2887,6 +2891,10 @@ struct cfg80211_ops {
 				       struct net_device *dev,
 				       s32 rssi_thold, u32 rssi_hyst);
 
+	int	(*set_cqm_rssi_range_config)(struct wiphy *wiphy,
+					     struct net_device *dev,
+					     s32 rssi_low, s32 rssi_high);
+
 	int	(*set_cqm_txe_config)(struct wiphy *wiphy,
 				      struct net_device *dev,
 				      u32 rate, u32 pkts, u32 intvl);
@@ -3709,6 +3717,7 @@ void wiphy_free(struct wiphy *wiphy);
 struct cfg80211_conn;
 struct cfg80211_internal_bss;
 struct cfg80211_cached_keys;
+struct cfg80211_cqm_config;
 
 /**
  * struct wireless_dev - wireless device state
@@ -3769,6 +3778,7 @@ struct cfg80211_cached_keys;
  * @event_list: (private) list for internal event processing
  * @event_lock: (private) lock for event list
  * @owner_nlportid: (private) owner socket port ID
+ * @cqm_config: (private) nl80211 RSSI monitor state
  */
 struct wireless_dev {
 	struct wiphy *wiphy;
@@ -3833,6 +3843,8 @@ struct wireless_dev {
 		bool prev_bssid_valid;
 	} wext;
 #endif
+
+	struct cfg80211_cqm_config *cqm_config;
 };
 
 static inline u8 *wdev_address(struct wireless_dev *wdev)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 33026e1..7da1056 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -502,6 +502,10 @@ struct ieee80211_mu_group_data {
  *	implies disabled. As with the cfg80211 callback, a change here should
  *	cause an event to be sent indicating where the current value is in
  *	relation to the newly configured threshold.
+ * @cqm_rssi_low: Connection quality monitor RSSI lower threshold, a zero value
+ *	implies disabled.  This is an alternative mechanism to the single
+ *	threshold event and can't be enabled simultaneously.
+ * @cqm_rssi_low: Connection quality monitor RSSI upper threshold.
  * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis
  * @arp_addr_list: List of IPv4 addresses for hardware ARP filtering. The
  *	may filter ARP queries targeted for other addresses than listed here.
@@ -554,6 +558,8 @@ struct ieee80211_bss_conf {
 	u16 ht_operation_mode;
 	s32 cqm_rssi_thold;
 	u32 cqm_rssi_hyst;
+	s32 cqm_rssi_low;
+	s32 cqm_rssi_high;
 	struct cfg80211_chan_def chandef;
 	struct ieee80211_mu_group_data mu_group;
 	__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 48108fd..d632c6a 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3839,7 +3839,9 @@ enum nl80211_ps_state {
  * @__NL80211_ATTR_CQM_INVALID: invalid
  * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies
  *	the threshold for the RSSI level at which an event will be sent. Zero
- *	to disable.
+ *	to disable.  Alternatively multiple values can be supplied as a
+ *	low-to-high sorted array of thresholds in dBm.  Events will be sent
+ *	when the RSSI value crosses any of the thresholds.
  * @NL80211_ATTR_CQM_RSSI_HYST: RSSI hysteresis in dBm. This value specifies
  *	the minimum amount the RSSI level must change after an event before a
  *	new event may be issued (to reduce effects of RSSI oscillation).
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index fd6541f..6ac0523 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2647,6 +2647,33 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
 
 	bss_conf->cqm_rssi_thold = rssi_thold;
 	bss_conf->cqm_rssi_hyst = rssi_hyst;
+	bss_conf->cqm_rssi_low = 0;
+	bss_conf->cqm_rssi_high = 0;
+	sdata->u.mgd.last_cqm_event_signal = 0;
+
+	/* tell the driver upon association, unless already associated */
+	if (sdata->u.mgd.associated &&
+	    sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
+		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
+
+	return 0;
+}
+
+static int ieee80211_set_cqm_rssi_range_config(struct wiphy *wiphy,
+					       struct net_device *dev,
+					       s32 rssi_low, s32 rssi_high)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_vif *vif = &sdata->vif;
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+
+	if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
+		return -EOPNOTSUPP;
+
+	bss_conf->cqm_rssi_low = rssi_low;
+	bss_conf->cqm_rssi_high = rssi_high;
+	bss_conf->cqm_rssi_thold = 0;
+	bss_conf->cqm_rssi_hyst = 0;
 	sdata->u.mgd.last_cqm_event_signal = 0;
 
 	/* tell the driver upon association, unless already associated */
@@ -3645,6 +3672,7 @@ const struct cfg80211_ops mac80211_config_ops = {
 	.mgmt_tx = ieee80211_mgmt_tx,
 	.mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,
 	.set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
+	.set_cqm_rssi_range_config = ieee80211_set_cqm_rssi_range_config,
 	.mgmt_frame_register = ieee80211_mgmt_frame_register,
 	.set_antenna = ieee80211_set_antenna,
 	.get_antenna = ieee80211_get_antenna,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6898ecb..7f99918 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3416,6 +3416,30 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 		}
 	}
 
+	if (bss_conf->cqm_rssi_low &&
+	    ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
+		int sig = -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal);
+		int last_event = ifmgd->last_cqm_event_signal;
+		int low = bss_conf->cqm_rssi_low;
+		int high = bss_conf->cqm_rssi_high;
+
+		if (sig < low &&
+		    (last_event == 0 || last_event >= low)) {
+			ifmgd->last_cqm_event_signal = sig;
+			ieee80211_cqm_rssi_notify(
+				&sdata->vif,
+				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+				sig, GFP_KERNEL);
+		} else if (sig > high &&
+			   (last_event == 0 || last_event <= high)) {
+			ifmgd->last_cqm_event_signal = sig;
+			ieee80211_cqm_rssi_notify(
+				&sdata->vif,
+				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+				sig, GFP_KERNEL);
+		}
+	}
+
 	if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) {
 		mlme_dbg_ratelimited(sdata,
 				     "cancelling AP probe due to a received beacon\n");
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 8201e6d..f6c1bf2 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -928,6 +928,16 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
 }
 EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
 
+void cfg80211_cqm_config_free(struct wireless_dev *wdev)
+{
+	if (!wdev->cqm_config)
+		return;
+
+	kfree(wdev->cqm_config->rssi_thresholds);
+	kfree(wdev->cqm_config);
+	wdev->cqm_config = NULL;
+}
+
 void cfg80211_unregister_wdev(struct wireless_dev *wdev)
 {
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
@@ -954,6 +964,8 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
 		WARN_ON_ONCE(1);
 		break;
 	}
+
+	cfg80211_cqm_config_free(wdev);
 }
 EXPORT_SYMBOL(cfg80211_unregister_wdev);
 
@@ -1205,6 +1217,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 #ifdef CONFIG_CFG80211_WEXT
 			kzfree(wdev->wext.keys);
 #endif
+			cfg80211_cqm_config_free(wdev);
 		}
 		/*
 		 * synchronise (so that we won't find this netdev
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 08d2e94..75fc334 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -270,6 +270,13 @@ struct cfg80211_iface_destroy {
 	u32 nlportid;
 };
 
+struct cfg80211_cqm_config {
+	s32 *rssi_thresholds;
+	int n_rssi_thresholds;
+	u32 rssi_hyst;
+	s32 last_rssi_event_value;
+};
+
 void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev);
 
 /* free object */
@@ -504,4 +511,6 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
 #define CFG80211_DEV_WARN_ON(cond)	({bool __r = (cond); __r; })
 #endif
 
+void cfg80211_cqm_config_free(struct wireless_dev *wdev);
+
 #endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5d10774..907bd2a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -9272,7 +9272,7 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
 
 static const struct nla_policy
 nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
-	[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
+	[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
 	[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
 	[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
 	[NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
@@ -9301,28 +9301,127 @@ static int nl80211_set_cqm_txe(struct genl_info *info,
 	return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
 }
 
+static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
+				    struct net_device *dev)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	s32 last, low, high;
+	u32 hyst;
+	int i, n;
+	int err;
+
+	/* RSSI reporting disabled? */
+	if (!wdev->cqm_config)
+		return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
+
+	/*
+	 * Obtain current RSSI value if possible, if not and no RSSI threshold
+	 * event has been received yet, we should receive an event after a
+	 * connection is established and enough beacons received to calculate
+	 * the average.
+	 */
+	if (!wdev->cqm_config->last_rssi_event_value && wdev->current_bss) {
+		struct station_info sinfo;
+		u8 *mac_addr;
+
+		mac_addr = wdev->current_bss->pub.bssid;
+
+		err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
+		if (err)
+			return err;
+
+		if (sinfo.filled & BIT(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
+			wdev->cqm_config->last_rssi_event_value =
+				(s8) sinfo.rx_beacon_signal_avg;
+	}
+
+	last = wdev->cqm_config->last_rssi_event_value;
+	hyst = wdev->cqm_config->rssi_hyst;
+	n = wdev->cqm_config->n_rssi_thresholds;
+
+	for (i = 0; i < n; i++)
+		if (last < wdev->cqm_config->rssi_thresholds[i])
+			break;
+
+	low = i > 0 ? wdev->cqm_config->rssi_thresholds[i - 1] : S32_MIN;
+	high = i < n ? wdev->cqm_config->rssi_thresholds[i] : S32_MAX;
+
+	if (low > (s32) (last - hyst))
+		low = last - hyst;
+	if (high < (s32) (last + hyst))
+		high = last + hyst;
+
+	return rdev_set_cqm_rssi_range_config(rdev, dev, low, high - 1);
+}
+
 static int nl80211_set_cqm_rssi(struct genl_info *info,
-				s32 threshold, u32 hysteresis)
+				const s32 *thresholds, int n_thresholds,
+				u32 hysteresis)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct net_device *dev = info->user_ptr[1];
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	int i, err;
+	s32 prev = S32_MIN;
 
-	if (threshold > 0)
-		return -EINVAL;
+	/* Check all values negative and sorted */
+	for (i = 0; i < n_thresholds; i++) {
+		if (thresholds[i] > 0 || thresholds[i] <= prev)
+			return -EINVAL;
+
+		prev = thresholds[i];
+	}
+
+	if (n_thresholds == 1 && thresholds[0] == 0)
+		n_thresholds = 0;
 
 	/* disabling - hysteresis should also be zero then */
-	if (threshold == 0)
+	if (n_thresholds == 0)
 		hysteresis = 0;
 
-	if (!rdev->ops->set_cqm_rssi_config)
-		return -EOPNOTSUPP;
-
 	if (wdev->iftype != NL80211_IFTYPE_STATION &&
 	    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
 		return -EOPNOTSUPP;
 
-	return rdev_set_cqm_rssi_config(rdev, dev, threshold, hysteresis);
+	wdev_lock(wdev);
+	cfg80211_cqm_config_free(wdev);
+	wdev_unlock(wdev);
+
+	if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
+		const s32 disable = 0;
+
+		if (n_thresholds == 0) {
+			n_thresholds = 1;
+			thresholds = &disable;
+		}
+
+		return rdev_set_cqm_rssi_config(rdev, dev,
+						thresholds[0], hysteresis);
+	}
+
+	if (!rdev->ops->set_cqm_rssi_range_config || !rdev->ops->get_station)
+		return -EOPNOTSUPP;
+
+	wdev_lock(wdev);
+	if (n_thresholds) {
+		struct cfg80211_cqm_config *cqm_config;
+
+		cqm_config = kzalloc(sizeof(struct cfg80211_cqm_config),
+					   GFP_KERNEL);
+		cqm_config->rssi_thresholds =
+			kmemdup(thresholds, n_thresholds * sizeof(s32),
+				GFP_KERNEL);
+		cqm_config->n_rssi_thresholds = n_thresholds;
+		cqm_config->rssi_hyst = hysteresis;
+
+		wdev->cqm_config = cqm_config;
+	}
+
+	err = cfg80211_cqm_rssi_update(rdev, dev);
+
+	wdev_unlock(wdev);
+
+	return err;
 }
 
 static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
@@ -9342,10 +9441,15 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
 
 	if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
 	    attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
-		s32 threshold = nla_get_s32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
+		s32 *thresholds = nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
+		int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
 		u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
 
-		return nl80211_set_cqm_rssi(info, threshold, hysteresis);
+		if (len % 4)
+			return -EINVAL;
+
+		return nl80211_set_cqm_rssi(info, thresholds, len / 4,
+					    hysteresis);
 	}
 
 	if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
@@ -13741,6 +13845,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
 			      s32 rssi_level, gfp_t gfp)
 {
 	struct sk_buff *msg;
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 
 	trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
 
@@ -13748,6 +13854,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
 		    rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
 		return;
 
+	if (wdev->cqm_config) {
+		wdev->cqm_config->last_rssi_event_value = rssi_level;
+
+		cfg80211_cqm_rssi_update(rdev, dev);
+
+		if (rssi_level == 0)
+			rssi_level = wdev->cqm_config->last_rssi_event_value;
+	}
+
 	msg = cfg80211_prepare_cqm(dev, NULL, gfp);
 	if (!msg)
 		return;
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 11cf83c..ae180f3 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -726,6 +726,18 @@ rdev_set_cqm_rssi_config(struct cfg80211_registered_device *rdev,
 }
 
 static inline int
+rdev_set_cqm_rssi_range_config(struct cfg80211_registered_device *rdev,
+			       struct net_device *dev, s32 low, s32 high)
+{
+	int ret;
+	trace_rdev_set_cqm_rssi_range_config(&rdev->wiphy, dev, low, high);
+	ret = rdev->ops->set_cqm_rssi_range_config(&rdev->wiphy, dev,
+						   low, high);
+	trace_rdev_return_int(&rdev->wiphy, ret);
+	return ret;
+}
+
+static inline int
 rdev_set_cqm_txe_config(struct cfg80211_registered_device *rdev,
 			struct net_device *dev, u32 rate, u32 pkts, u32 intvl)
 {
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 6ac46a0..993f661 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1304,6 +1304,28 @@ TRACE_EVENT(rdev_set_cqm_rssi_config,
 		 __entry->rssi_thold, __entry->rssi_hyst)
 );
 
+TRACE_EVENT(rdev_set_cqm_rssi_range_config,
+	TP_PROTO(struct wiphy *wiphy,
+		 struct net_device *netdev, s32 low, s32 high),
+	TP_ARGS(wiphy, netdev, low, high),
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		NETDEV_ENTRY
+		__field(s32, rssi_low)
+		__field(s32, rssi_high)
+	),
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		NETDEV_ASSIGN;
+		__entry->rssi_low = low;
+		__entry->rssi_high = high;
+	),
+	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT
+		  ", range: %d - %d ",
+		  WIPHY_PR_ARG, NETDEV_PR_ARG,
+		  __entry->rssi_low, __entry->rssi_high)
+);
+
 TRACE_EVENT(rdev_set_cqm_txe_config,
 	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 rate,
 		 u32 pkts, u32 intvl),
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/3][RESEND] cfg80211: Pass new RSSI level in CQM RSSI notification
From: Andrew Zaborowski @ 2016-11-22 10:29 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <1479810592-2474-1-git-send-email-andrew.zaborowski@intel.com>

Update the drivers to pass the RSSI level as a cfg80211_cqm_rssi_notify
parameter and pass this value to userspace in a new nl80211 attribute.
This helps both userspace and also helps in the implementation of the
multiple RSSI thresholds CQM mechanism.

Note for marvell/mwifiexe I pass 0 for the RSSI value because the new
RSSI value is not available to the driver at the time of the
cfg80211_cqm_rssi_notify call, but the driver queries the new value
immediately after that, so it is actually available just a moment later
if we wanted to defer caling cfg80211_cqm_rssi_notify until that moment.
Without this, the new cfg80211 code (patch 3) will call .get_station
which will send a duplicate HostCmd_CMD_RSSI_INFO command to the hardware.
---
 drivers/net/wireless/marvell/mwifiex/sta_event.c |  4 ++--
 drivers/net/wireless/rndis_wlan.c                |  2 +-
 include/net/cfg80211.h                           |  3 ++-
 include/uapi/linux/nl80211.h                     |  3 +++
 net/mac80211/mlme.c                              |  2 +-
 net/wireless/nl80211.c                           |  9 +++++++--
 net/wireless/trace.h                             | 11 +++++++----
 7 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
index 9df0c4d..5cc3aa7 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -824,7 +824,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 	case EVENT_RSSI_LOW:
 		cfg80211_cqm_rssi_notify(priv->netdev,
 					 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
-					 GFP_KERNEL);
+					 0, GFP_KERNEL);
 		mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
 				 HostCmd_ACT_GEN_GET, 0, NULL, false);
 		priv->subsc_evt_rssi_state = RSSI_LOW_RECVD;
@@ -839,7 +839,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 	case EVENT_RSSI_HIGH:
 		cfg80211_cqm_rssi_notify(priv->netdev,
 					 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
-					 GFP_KERNEL);
+					 0, GFP_KERNEL);
 		mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
 				 HostCmd_ACT_GEN_GET, 0, NULL, false);
 		priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD;
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 603c904..785334f 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -3187,7 +3187,7 @@ static void rndis_do_cqm(struct usbnet *usbdev, s32 rssi)
 		return;
 
 	priv->last_cqm_event_rssi = rssi;
-	cfg80211_cqm_rssi_notify(usbdev->net, event, GFP_KERNEL);
+	cfg80211_cqm_rssi_notify(usbdev->net, event, rssi, GFP_KERNEL);
 }
 
 #define DEVICE_POLLER_JIFFIES (HZ)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bd19faa..632dce1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5167,6 +5167,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
  * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event
  * @dev: network device
  * @rssi_event: the triggered RSSI event
+ * @rssi_level: new RSSI level value or 0 if not available
  * @gfp: context flags
  *
  * This function is called when a configured connection quality monitoring
@@ -5174,7 +5175,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
  */
 void cfg80211_cqm_rssi_notify(struct net_device *dev,
 			      enum nl80211_cqm_rssi_threshold_event rssi_event,
-			      gfp_t gfp);
+			      s32 rssi_level, gfp_t gfp);
 
 /**
  * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 56368e9..48108fd 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3859,6 +3859,8 @@ enum nl80211_ps_state {
  *	%NL80211_CMD_NOTIFY_CQM. Set to 0 to turn off TX error reporting.
  * @NL80211_ATTR_CQM_BEACON_LOSS_EVENT: flag attribute that's set in a beacon
  *	loss event
+ * @NL80211_ATTR_CQM_RSSI_LEVEL: the RSSI value in dBm that triggered the
+ *	RSSI threshold event.
  * @__NL80211_ATTR_CQM_AFTER_LAST: internal
  * @NL80211_ATTR_CQM_MAX: highest key attribute
  */
@@ -3872,6 +3874,7 @@ enum nl80211_attr_cqm {
 	NL80211_ATTR_CQM_TXE_PKTS,
 	NL80211_ATTR_CQM_TXE_INTVL,
 	NL80211_ATTR_CQM_BEACON_LOSS_EVENT,
+	NL80211_ATTR_CQM_RSSI_LEVEL,
 
 	/* keep last */
 	__NL80211_ATTR_CQM_AFTER_LAST,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a55cdd7..6898ecb 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -5007,7 +5007,7 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
 
 	trace_api_cqm_rssi_notify(sdata, rssi_event, rssi_level);
 
-	cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
+	cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, rssi_level, gfp);
 }
 EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c510810..5d10774 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -9278,6 +9278,7 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
 	[NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
 	[NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
 	[NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
+	[NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
 };
 
 static int nl80211_set_cqm_txe(struct genl_info *info,
@@ -13737,11 +13738,11 @@ static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
 
 void cfg80211_cqm_rssi_notify(struct net_device *dev,
 			      enum nl80211_cqm_rssi_threshold_event rssi_event,
-			      gfp_t gfp)
+			      s32 rssi_level, gfp_t gfp)
 {
 	struct sk_buff *msg;
 
-	trace_cfg80211_cqm_rssi_notify(dev, rssi_event);
+	trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
 
 	if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
 		    rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
@@ -13755,6 +13756,10 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
 			rssi_event))
 		goto nla_put_failure;
 
+	if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL,
+				      rssi_level))
+		goto nla_put_failure;
+
 	cfg80211_send_cqm(msg, gfp);
 
 	return;
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index a3d0a91..6ac46a0 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2472,18 +2472,21 @@ TRACE_EVENT(cfg80211_mgmt_tx_status,
 
 TRACE_EVENT(cfg80211_cqm_rssi_notify,
 	TP_PROTO(struct net_device *netdev,
-		 enum nl80211_cqm_rssi_threshold_event rssi_event),
-	TP_ARGS(netdev, rssi_event),
+		 enum nl80211_cqm_rssi_threshold_event rssi_event,
+		 s32 rssi_level),
+	TP_ARGS(netdev, rssi_event, rssi_level),
 	TP_STRUCT__entry(
 		NETDEV_ENTRY
 		__field(enum nl80211_cqm_rssi_threshold_event, rssi_event)
+		__field(s32, rssi_level)
 	),
 	TP_fast_assign(
 		NETDEV_ASSIGN;
 		__entry->rssi_event = rssi_event;
+		__entry->rssi_level = rssi_level;
 	),
-	TP_printk(NETDEV_PR_FMT ", rssi event: %d",
-		  NETDEV_PR_ARG, __entry->rssi_event)
+	TP_printk(NETDEV_PR_FMT ", rssi event: %d, level: %d",
+		  NETDEV_PR_ARG, __entry->rssi_event, __entry->rssi_level)
 );
 
 TRACE_EVENT(cfg80211_reg_can_beacon,
-- 
2.7.4

^ permalink raw reply related

* [PATCH 1/3][RESEND] mac80211: Pass new RSSI level in CQM RSSI notification
From: Andrew Zaborowski @ 2016-11-22 10:29 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <1479810592-2474-1-git-send-email-andrew.zaborowski@intel.com>

---
 drivers/net/wireless/intel/iwlwifi/mvm/rx.c |  2 ++
 drivers/net/wireless/rsi/rsi_91x_mac80211.c |  2 +-
 drivers/net/wireless/st/cw1200/sta.c        |  2 +-
 drivers/net/wireless/ti/wl1251/event.c      |  4 ++--
 drivers/net/wireless/ti/wlcore/event.c      |  3 ++-
 include/net/mac80211.h                      |  2 ++
 net/mac80211/mlme.c                         |  7 ++++---
 net/mac80211/trace.h                        | 11 +++++++----
 8 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 0e60e38..e06a2e3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -571,6 +571,7 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
 		ieee80211_cqm_rssi_notify(
 			vif,
 			NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+			sig,
 			GFP_KERNEL);
 	} else if (sig > thold &&
 		   (last_event == 0 || sig > last_event + hyst)) {
@@ -580,6 +581,7 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
 		ieee80211_cqm_rssi_notify(
 			vif,
 			NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+			sig,
 			GFP_KERNEL);
 	}
 }
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index dbb2389..3e260b4 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -818,7 +818,7 @@ static void rsi_perform_cqm(struct rsi_common *common,
 
 	common->cqm_info.last_cqm_event_rssi = rssi;
 	rsi_dbg(INFO_ZONE, "CQM: Notifying event: %d\n", event);
-	ieee80211_cqm_rssi_notify(adapter->vifs[0], event, GFP_KERNEL);
+	ieee80211_cqm_rssi_notify(adapter->vifs[0], event, rssi, GFP_KERNEL);
 
 	return;
 }
diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c
index daf06a4..a522248 100644
--- a/drivers/net/wireless/st/cw1200/sta.c
+++ b/drivers/net/wireless/st/cw1200/sta.c
@@ -1019,7 +1019,7 @@ void cw1200_event_handler(struct work_struct *work)
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW :
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
 			pr_debug("[CQM] RSSI event: %d.\n", rcpi_rssi);
-			ieee80211_cqm_rssi_notify(priv->vif, cqm_evt,
+			ieee80211_cqm_rssi_notify(priv->vif, cqm_evt, rcpi_rssi,
 						  GFP_KERNEL);
 			break;
 		}
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c
index d0593bc..f5acd24 100644
--- a/drivers/net/wireless/ti/wl1251/event.c
+++ b/drivers/net/wireless/ti/wl1251/event.c
@@ -150,7 +150,7 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
 				     "ROAMING_TRIGGER_LOW_RSSI_EVENT");
 			ieee80211_cqm_rssi_notify(wl->vif,
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
-				GFP_KERNEL);
+				0, GFP_KERNEL);
 		}
 
 		if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID) {
@@ -158,7 +158,7 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
 				     "ROAMING_TRIGGER_REGAINED_RSSI_EVENT");
 			ieee80211_cqm_rssi_notify(wl->vif,
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
-				GFP_KERNEL);
+				0, GFP_KERNEL);
 		}
 	}
 
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index 4b59f67..f2e90d2 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -129,7 +129,8 @@ void wlcore_event_rssi_trigger(struct wl1271 *wl, s8 *metric_arr)
 
 		vif = wl12xx_wlvif_to_vif(wlvif);
 		if (event != wlvif->last_rssi_event)
-			ieee80211_cqm_rssi_notify(vif, event, GFP_KERNEL);
+			ieee80211_cqm_rssi_notify(vif, event, metric,
+						  GFP_KERNEL);
 		wlvif->last_rssi_event = event;
 	}
 }
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a810dfc..33026e1 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -5244,6 +5244,7 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif);
  *
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
  * @rssi_event: the RSSI trigger event type
+ * @rssi_level: new RSSI level value or 0 if not available
  * @gfp: context flags
  *
  * When the %IEEE80211_VIF_SUPPORTS_CQM_RSSI is set, and a connection quality
@@ -5252,6 +5253,7 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif);
  */
 void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
 			       enum nl80211_cqm_rssi_threshold_event rssi_event,
+			       s32 rssi_level,
 			       gfp_t gfp);
 
 /**
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7486f2d..a55cdd7 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3405,14 +3405,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 			ieee80211_cqm_rssi_notify(
 				&sdata->vif,
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
-				GFP_KERNEL);
+				sig, GFP_KERNEL);
 		} else if (sig > thold &&
 			   (last_event == 0 || sig > last_event + hyst)) {
 			ifmgd->last_cqm_event_signal = sig;
 			ieee80211_cqm_rssi_notify(
 				&sdata->vif,
 				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
-				GFP_KERNEL);
+				sig, GFP_KERNEL);
 		}
 	}
 
@@ -5000,11 +5000,12 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
 
 void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
 			       enum nl80211_cqm_rssi_threshold_event rssi_event,
+			       s32 rssi_level,
 			       gfp_t gfp)
 {
 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 
-	trace_api_cqm_rssi_notify(sdata, rssi_event);
+	trace_api_cqm_rssi_notify(sdata, rssi_event, rssi_level);
 
 	cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
 }
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 92a47af..f78d9f4 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1996,23 +1996,26 @@ TRACE_EVENT(api_connection_loss,
 
 TRACE_EVENT(api_cqm_rssi_notify,
 	TP_PROTO(struct ieee80211_sub_if_data *sdata,
-		 enum nl80211_cqm_rssi_threshold_event rssi_event),
+		 enum nl80211_cqm_rssi_threshold_event rssi_event,
+		 s32 rssi_level),
 
-	TP_ARGS(sdata, rssi_event),
+	TP_ARGS(sdata, rssi_event, rssi_level),
 
 	TP_STRUCT__entry(
 		VIF_ENTRY
 		__field(u32, rssi_event)
+		__field(s32, rssi_level)
 	),
 
 	TP_fast_assign(
 		VIF_ASSIGN;
 		__entry->rssi_event = rssi_event;
+		__entry->rssi_level = rssi_level;
 	),
 
 	TP_printk(
-		VIF_PR_FMT " event:%d",
-		VIF_PR_ARG, __entry->rssi_event
+		VIF_PR_FMT " event:%d rssi:%d",
+		VIF_PR_ARG, __entry->rssi_event, __entry->rssi_level
 	)
 );
 
-- 
2.7.4

^ permalink raw reply related


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