Re: [BUG] mac80211: Using smp_processor_id() in preemptible code: iwd

2018-06-19 Thread Denis Kenzior
Hi Johannes,

> On Jun 15, 2018, at 7:30 AM, Johannes Berg  wrote:
> 
> On Fri, 2018-06-15 at 11:09 +, McGinn, Dan wrote:
>> Hi, I'm newly trying out Intel iwd daemon but I experience regular kernel 
>> errors in 4.17, although WPA2-PSK connection remains stable.  These errors 
>> don't seem to be experienced with wpa_supplicant.  The errors reliably 
>> appear around the following events:
>> netdev_unicast_notify()
>> netdev_control_port_frame_event()
>> netdev_set_rekey_offload()
>> netdev_set_gtk()
>> 
>> @Denkenz in IRC helpfully suggests Johannes could follow the finger of 
>> suspicion to this commit:
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=911806491425d79107cadddbde11b42bbdfe38c8
> 
> It's his code ;-)

Right, but you’re much more aware of all the locking issues than I am.

> 
> Clearly this comes from cfg80211 without any locking other than rtnl, so
> you don't have preemption disabled. That's the minimum needed to get rid
> of the warning you found.

In my defense, I did ask you whether there are any potential locking issues in 
the RFC and you didn’t think there were any.

I posted a fix for this.  Could you please review?

Regards,
-Denis



Re: [PATCH V3 0/2] brcmfmac: initial work for adding monitor mode

2018-06-19 Thread Rafał Miłecki

On 2018-06-19 22:01, Arend van Spriel wrote:

On 6/19/2018 5:48 PM, Rafał Miłecki wrote:

From: Rafał Miłecki 

After a bit long discussions in various e-mail threads I'm coming with
this simple & small patchset. It isn't complete support for monitor 
mode

but just a pair of preparing patches that should be clear & well
discussed by now to make them acceptable.

The main missing bit is code setting MONITOR_FMT_RADIOTAP which I 
expect

Arend to handle soon, as he already has a patch using "sta_monitor"
iovar for that. Then we have to discuss a flag for marking firmwares
which are capable for tagging monitor frames.

While still incomplete, I believe that with my previous patches, we 
can

agree this is a good direction.

Arend: if you find these 2 patches OK, could you ack them, to make it
clear for Kalle if they look OK now (or not yet)? I'd be great if you
could sent your "sta_monitor" work on top of this.


I acked them and I will submit my changes later. Either after these
are applied or simply indicate the dependency.

Now as for where we are with this. With what we have here we know
firmware can monitor packets with and without radiotap. However, we do
not have an indication whether firmware can transport these monitor
packets to the host. What I need to look into next is whether the
802.11 flag in msgbuf is linked to a particular version of the
protocol, but we may need to resort to the fwid table.


Being able to detect if firmware tags monitor packets would be great.

Please let us know if you find anything and thanks a lot for looking at
this patchset!


Re: [PATCH v2] mac80211: Fix wlan freezes under load at rekey

2018-06-19 Thread Alexander Wetzel


> Am I understanding correctly that in the latter (outgoing) case this
> might cause unencrypted packets to be transmitted?

Yes, if we have a driver handling the keys similar to ath9k which is not
implementing drv_flush (correctly) this is a possibility.

This ties somewhat into the discussion what to handle in mac80211 and
what delegate to the drivers. mac80211 itself should drop any packets
trying to use the old outgoing key till the new key is rolled out
correctly with the patch.


>> We can now decrypt and get incoming packets while mac80211 is still on
>> the old key, but the worst (and most likely) case is now, that the
>> replay detection will drop those packets till mac80211 also switch over.
> 
> This actually is somewhat problematic, at least for TKIP it could cause
> countermeasures. Should we exclude TKIP here somehow?
> 
> I don't think we can disable countermeasures because then we could be
> attacked in this time window without starting them, and we have a really
> hard time distinguishing attacks and "fake" replays.
> 
Yes, that is a definitely a possibility. But excluding TKIP seems to be
counterproductive for my understanding: TKIP is due to the weaker cipher
more likely to have unicast rekeying enabled.
So far I was hesitant to add new per packet check for that, but I guess
we have to... I'll add that in the next version, so we can discuss that
with some code.


>> Flushing the queues is not needed for to the logic and only a workaround
>> for drivers like ath9k which can still send out packets for a key which
>> was already deleted. When the driver guarantees that after the key
>> deletion function returns to mac80211 that there will be no more packets
>> send out prepared for the old key it can be removed.
> 
> What will happen for other kinds of packets though?
> 
> For iwlwifi, for example, the key material is added into the key. It
> thus doesn't have this race in the first place, but it will definitely
> send out packets after 

That case is fine. A non-broken remote STA will not be able to decode
the packet if it has already completed the switch to the new key and not
hand over the packet to mac80211 or the equivalent.

> 
> Btw - perhaps that means we should avoid the complicated mechanisms like
> TX aggregation shutdown for keys that the driver marks as being safe?
> Clearly for iwlwifi (at least CCMP and before, not with the longer keys
> in GCMP-256) the race can't possibly happen.

Sounds like that should work and I think I'll just try it out. We'll
lose the side benefit that shutting down TX aggregation will reduce the
risk that a unpatched remote sta freezes the connection, though.
And since I started out to first patch ath9k to drop packets for an
outgoing key: That looks to become either be ugly (delayed work to
complete the key clean up after a given time) or need some API change.

Remember we'll still have to shut down RX aggregation or drop all frames
of a session running during the rekey. We are not able to tell which key
was used to encrypt the frames and which have "old" PNs we can't allow
mac80211 to process after switching to the new key. So I'm not sure that
keeping TX up and running is worth it.

That said I have another working patch which is delaying mac80211 key
deletion from my first misguided attempts to at this issue.
I could repurpose that and keep RX aggregation also up and running,
allowing us to first check if the packet would have been accepted by the
old key and only switch to the new PN counter once it's not. But that
seems to be kind of invasive and overkill.

> 
> In other drivers though, I worry that removing the key will *not* mean
> that there are no more packets transmitted with it. If you have a key
> cache in hardware then it might just be that marking the cache entry as
> invalid means the encryption will be skipped when encountering a packet
> to be transmitted with the key from a given (in the packet) key cache
> index, and then the frame goes out unprotected?
> 
Yes, that is part of the reason I had to add the call to drv_flush for
ath9k. I've experimented with an additional "retire_key" command on top
of the existing to add and delete keys but came to the conclusion that
"replace_key" would make more sense for ath9k at least.

But in order of my preference I see this options:
1) removing a key in HW must also grantee that any packets queued for
this key has either been send or will be dropped after the call returns
to mac80211. (Simply sleeping the max queue and retransmit time would be
an ugly but simple way to implement that)

2) we add a new function/call like "replace_key" for this special case.
But in that case we have to sort out how to handle drivers not
implementing it. Thy only secure way would be to disconnect if someone
tries to rekey...

3) Is what I implemented. We try what we can with the existing API and
any driver not working with that has to be considered buggy.

>> I tried to minimize the changes, but if we can 

lockdep circular lock related to ath10k fw crash

2018-06-19 Thread Ben Greear

This is from my hacked 4.16.15+ kernel, with modified ath10k FW
that likes to crash a lot.

In this case, FW crashed near an ath10k module reload.  I am not sure
if this is a bug in ath10k in particular, or mac80211 locking, or
a combination of both.


ath10k_pci :04:00.0: firmware crashed! (guid 
9e93f19e-db9c-4c4b-98af-826eeb959e98)
ath10k_pci :04:00.0: failed to read firmware dump area: -16
ath10k_pci :04:00.0: Copy Engine register dump:
ath10k_pci :04:00.0: [00]: 0x0004a000   0   0   0   0
ath10k_pci :04:00.0: [01]: 0x0004a400   0   0   0   0
ath10k_pci :04:00.0: [02]: 0x0004a800   0   0   0   0
ath10k_pci :04:00.0: [03]: 0x0004ac00   0   0   0   0
ath10k_pci :04:00.0: [04]: 0x0004b000   0   0   0   0
ath10k_pci :04:00.0: [05]: 0x0004b400   0   0   0   0
ath10k_pci :04:00.0: [06]: 0x0004b800   0   0   0   0
ath10k_pci :04:00.0: [07]: 0x0004bc00   0   0   0   0
ath10k_pci :04:00.0: [08]: 0x0004c000   0   0   0   0
ath10k_pci :04:00.0: [09]: 0x0004c400   0   0   0   0
ath10k_pci :04:00.0: [10]: 0x0004c800   0   0   0   0
ath10k_pci :04:00.0: [11]: 0x0004cc00   0   0   0   0
ath10k_pci :04:00.0: failed to dump debug log area: -28

==
WARNING: possible circular locking dependency detected
4.16.15+ #19 Not tainted
--
ip/17578 is trying to acquire lock:
 ((wq_completion)"%s""ath10k_wq"){+.+.}, at: [<14225455>] 
flush_work+0x2b7/0x5d0

but task is already holding lock:
 (rtnl_mutex){+.+.}, at: [] rtnetlink_rcv_msg+0x29e/0x840

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #2 (rtnl_mutex){+.+.}:
   wiphy_register+0x1120/0x1f90 [cfg80211]
   ieee80211_register_hw+0x114e/0x2d20 [mac80211]
   ath10k_mac_register+0x1b2f/0x2f20 [ath10k_core]
   ath10k_core_register_work+0x22b7/0x3020 [ath10k_core]
   process_one_work+0x5f7/0x14d0
   worker_thread+0xdc/0x12d0
   kthread+0x2cf/0x3c0
   ret_from_fork+0x24/0x30

-> #1 ((work_completion)(>register_work)){+.+.}:
   worker_thread+0xdc/0x12d0
   kthread+0x2cf/0x3c0
   ret_from_fork+0x24/0x30

-> #0 ((wq_completion)"%s""ath10k_wq"){+.+.}:
   flush_work+0x2d7/0x5d0
   __cancel_work_timer+0x21a/0x2e0
   drv_stop+0xc8/0x5a0 [mac80211]
   ieee80211_do_stop+0xc11/0x1910 [mac80211]
   ieee80211_stop+0x11/0x20 [mac80211]
   __dev_close_many+0x178/0x280
   __dev_change_flags+0x1cc/0x4c0
   dev_change_flags+0x75/0x150
   do_setlink+0x929/0x2be0
   rtnl_newlink+0xc33/0x12e0
   rtnetlink_rcv_msg+0x2e6/0x840
   netlink_rcv_skb+0x263/0x3b0
   netlink_unicast+0x3d4/0x560
   netlink_sendmsg+0x73f/0xae0
   sock_sendmsg+0xac/0xe0
   ___sys_sendmsg+0x744/0x8f0
   __sys_sendmsg+0xab/0x120
   do_syscall_64+0x193/0x5e0
   entry_SYSCALL_64_after_hwframe+0x42/0xb7

other info that might help us debug this:

Chain exists of:
  (wq_completion)"%s""ath10k_wq" --> (work_completion)(>register_work) --> 
rtnl_mutex

 Possible unsafe locking scenario:

   CPU0CPU1
   
  lock(rtnl_mutex);
   lock((work_completion)(>register_work));
   lock(rtnl_mutex);
  lock((wq_completion)"%s""ath10k_wq");

 *** DEADLOCK ***

1 lock held by ip/17578:
 #0:  (rtnl_mutex){+.+.}, at: [] rtnetlink_rcv_msg+0x29e/0x840

stack backtrace:
CPU: 1 PID: 17578 Comm: ip Not tainted 4.16.15+ #19
Hardware name: _ _/, BIOS 5.11 08/26/2016
Call Trace:
 dump_stack+0x7c/0xbf
 print_circular_bug.isra.37+0x36f/0x37d
 __lock_acquire_lockdep+0x3486/0x3de0
 ? rcu_read_lock_sched_held+0x9e/0x120
 ? debug_check_no_locks_freed+0x290/0x290
 ? mark_held_locks+0xc0/0x110
 ? trace_hardirqs_on_caller+0x3ea/0x560
 ? trace_hardirqs_on_thunk+0x1a/0x1c
 ? lock_acquire+0x114/0x330
 lock_acquire+0x114/0x330
 ? flush_work+0x2b7/0x5d0
 flush_work+0x2d7/0x5d0
 ? flush_work+0x2b7/0x5d0
 ? drain_workqueue+0x370/0x370
 ? flush_workqueue_prep_pwqs+0x380/0x380
 ? mark_held_locks+0xc0/0x110
 ? __cancel_work_timer+0x1f9/0x2e0
 __cancel_work_timer+0x21a/0x2e0
 ? mod_delayed_work_on+0xf0/0xf0
 ? __mutex_unlock_slowpath+0x341/0x690
 ? wait_for_completion+0x300/0x300
 ? mark_held_locks+0xc0/0x110
 ? __local_bh_enable_ip+0xea/0x1d0
 ? trace_hardirqs_on_caller+0x3ea/0x560
 drv_stop+0xc8/0x5a0 [mac80211]
 ieee80211_do_stop+0xc11/0x1910 [mac80211]
 ? mark_held_locks+0xc0/0x110
 ? ieee80211_add_virtual_monitor+0x8b0/0x8b0 [mac80211]
 ? lockdep_rtnl_is_held+0x11/0x20
 ? dev_deactivate_many+0x707/0x970
 ieee80211_stop+0x11/0x20 [mac80211]
 __dev_close_many+0x178/0x280
 ? netdev_notify_peers+0xb0/0xb0
 ? trace_hardirqs_on_caller+0x3ea/0x560
 __dev_change_flags+0x1cc/0x4c0
 ? dev_set_allmulti+0x10/0x10
 dev_change_flags+0x75/0x150
 do_setlink+0x929/0x2be0
 ? validate_linkmsg+0x670/0x670

Re: [PATCH V3 0/2] brcmfmac: initial work for adding monitor mode

2018-06-19 Thread Arend van Spriel

On 6/19/2018 5:48 PM, Rafał Miłecki wrote:

From: Rafał Miłecki 

After a bit long discussions in various e-mail threads I'm coming with
this simple & small patchset. It isn't complete support for monitor mode
but just a pair of preparing patches that should be clear & well
discussed by now to make them acceptable.

The main missing bit is code setting MONITOR_FMT_RADIOTAP which I expect
Arend to handle soon, as he already has a patch using "sta_monitor"
iovar for that. Then we have to discuss a flag for marking firmwares
which are capable for tagging monitor frames.

While still incomplete, I believe that with my previous patches, we can
agree this is a good direction.

Arend: if you find these 2 patches OK, could you ack them, to make it
clear for Kalle if they look OK now (or not yet)? I'd be great if you
could sent your "sta_monitor" work on top of this.


I acked them and I will submit my changes later. Either after these are 
applied or simply indicate the dependency.


Now as for where we are with this. With what we have here we know 
firmware can monitor packets with and without radiotap. However, we do 
not have an indication whether firmware can transport these monitor 
packets to the host. What I need to look into next is whether the 802.11 
flag in msgbuf is linked to a particular version of the protocol, but we 
may need to resort to the fwid table.


Regards,
Arend



Re: [PATCH V3 2/2] brcmfmac: handle monitor mode marked msgbuf packets

2018-06-19 Thread Arend van Spriel

On 6/19/2018 5:48 PM, Rafał Miłecki wrote:

From: Rafał Miłecki 

New Broadcom firmwares mark monitor mode packets using a newly defined
bit in the flags field. Use it to filter them out and pass to the
monitor interface. These defines were found in bcmmsgbuf.h from SDK.

As not every firmware generates radiotap header this commit introduces
BRCMF_FEAT_MONITOR_FMT_RADIOTAP flag. It has to be has based on firmware
capabilities. If not present brcmf_netif_mon_rx() will assume packet is
a raw 802.11 frame and will prepend it with an empty radiotap header.

This new code is limited to the msgbuf protocol at this point. Adding
support for SDIO/USB devices will require some extra work (possibly a
new firmware release).


Acked-by: Arend van Spriel 

Signed-off-by: Rafał Miłecki 
---
V2: Use cpu_to_le16 when setting it_len
V3: Update TODO comments
 Rename flag (after adding MONITOR)
 Update commit message
---
  .../wireless/broadcom/brcm80211/brcmfmac/core.c| 25 ++
  .../wireless/broadcom/brcm80211/brcmfmac/core.h|  2 ++
  .../wireless/broadcom/brcm80211/brcmfmac/feature.h |  4 +++-
  .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c  | 17 +++
  4 files changed, 47 insertions(+), 1 deletion(-)




Re: [PATCH V3 1/2] brcmfmac: detect firmware support for monitor interface

2018-06-19 Thread Arend van Spriel

On 6/19/2018 5:48 PM, Rafał Miłecki wrote:

From: Rafał Miłecki 

Most of firmwares support creating monitor interface. The newest ones
explicitly /announce/ it using a "monitor" entry in the list of
capabilities.

Check (and store) internally info about monitor mode support using a
new feature flag. Once we sort out all details of handling monitor
interface it will be used when reporting available interfaces to the
cfg80211.


Acked-by: Arend van Spriel 

Signed-off-by: Rafał Miłecki 
---
V3: Patch added to the series
---
  .../wireless/broadcom/brcm80211/brcmfmac/feature.c | 26 ++
  .../wireless/broadcom/brcm80211/brcmfmac/feature.h |  4 +++-
  .../wireless/broadcom/brcm80211/brcmfmac/fwil.h|  2 ++
  3 files changed, 31 insertions(+), 1 deletion(-)




[PATCH V3 2/2] brcmfmac: handle monitor mode marked msgbuf packets

2018-06-19 Thread Rafał Miłecki
From: Rafał Miłecki 

New Broadcom firmwares mark monitor mode packets using a newly defined
bit in the flags field. Use it to filter them out and pass to the
monitor interface. These defines were found in bcmmsgbuf.h from SDK.

As not every firmware generates radiotap header this commit introduces
BRCMF_FEAT_MONITOR_FMT_RADIOTAP flag. It has to be has based on firmware
capabilities. If not present brcmf_netif_mon_rx() will assume packet is
a raw 802.11 frame and will prepend it with an empty radiotap header.

This new code is limited to the msgbuf protocol at this point. Adding
support for SDIO/USB devices will require some extra work (possibly a
new firmware release).

Signed-off-by: Rafał Miłecki 
---
V2: Use cpu_to_le16 when setting it_len
V3: Update TODO comments
Rename flag (after adding MONITOR)
Update commit message
---
 .../wireless/broadcom/brcm80211/brcmfmac/core.c| 25 ++
 .../wireless/broadcom/brcm80211/brcmfmac/core.h|  2 ++
 .../wireless/broadcom/brcm80211/brcmfmac/feature.h |  4 +++-
 .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c  | 17 +++
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 72954fd6df3b..b1f702faff4f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -404,6 +405,30 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff 
*skb)
netif_rx_ni(skb);
 }
 
+void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)
+{
+   if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_RADIOTAP)) {
+   /* Do nothing */
+   } else {
+   struct ieee80211_radiotap_header *radiotap;
+
+   /* TODO: use RX status to fill some radiotap data */
+   radiotap = skb_push(skb, sizeof(*radiotap));
+   memset(radiotap, 0, sizeof(*radiotap));
+   radiotap->it_len = cpu_to_le16(sizeof(*radiotap));
+
+   /* TODO: 4 bytes with receive status? */
+   skb->len -= 4;
+   }
+
+   skb->dev = ifp->ndev;
+   skb_reset_mac_header(skb);
+   skb->pkt_type = PACKET_OTHERHOST;
+   skb->protocol = htons(ETH_P_802_2);
+
+   brcmf_netif_rx(ifp, skb);
+}
+
 static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,
struct brcmf_if **ifp)
 {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index 401f50458686..dcf6e27cc16f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -121,6 +121,7 @@ struct brcmf_pub {
 
struct brcmf_if *iflist[BRCMF_MAX_IFS];
s32 if2bss[BRCMF_MAX_IFS];
+   struct brcmf_if *mon_if;
 
struct mutex proto_block;
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
@@ -216,6 +217,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp,
  enum brcmf_netif_stop_reason reason, bool state);
 void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
 void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
+void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb);
 void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
 int __init brcmf_core_init(void);
 void __exit brcmf_core_exit(void);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
index 6eddb19ca48d..0782f2aa3767 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
@@ -34,6 +34,7 @@
  * GSCAN: enhanced scan offload feature.
  * FWSUP: Firmware supplicant.
  * MONITOR: monitor interface
+ * MONITOR_FMT_RADIOTAP: monitor packets include radiotap header
  */
 #define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \
@@ -50,7 +51,8 @@
BRCMF_FEAT_DEF(MFP) \
BRCMF_FEAT_DEF(GSCAN) \
BRCMF_FEAT_DEF(FWSUP) \
-   BRCMF_FEAT_DEF(MONITOR)
+   BRCMF_FEAT_DEF(MONITOR) \
+   BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP)
 
 /*
  * Quirks:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index c40ba8855cd5..6abf9795930e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -69,6 +69,8 @@
 #define BRCMF_MSGBUF_MAX_EVENTBUF_POST 8
 
 #define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3 0x01
+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_110x02
+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK  0x07
 #define 

[PATCH V3 1/2] brcmfmac: detect firmware support for monitor interface

2018-06-19 Thread Rafał Miłecki
From: Rafał Miłecki 

Most of firmwares support creating monitor interface. The newest ones
explicitly /announce/ it using a "monitor" entry in the list of
capabilities.

Check (and store) internally info about monitor mode support using a
new feature flag. Once we sort out all details of handling monitor
interface it will be used when reporting available interfaces to the
cfg80211.

Signed-off-by: Rafał Miłecki 
---
V3: Patch added to the series
---
 .../wireless/broadcom/brcm80211/brcmfmac/feature.c | 26 ++
 .../wireless/broadcom/brcm80211/brcmfmac/feature.h |  4 +++-
 .../wireless/broadcom/brcm80211/brcmfmac/fwil.h|  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
index 800a423c7bc2..48d7978497b5 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -48,6 +48,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
{ BRCMF_FEAT_MBSS, "mbss" },
{ BRCMF_FEAT_MCHAN, "mchan" },
{ BRCMF_FEAT_P2P, "p2p" },
+   { BRCMF_FEAT_MONITOR, "monitor" },
 };
 
 #ifdef DEBUG
@@ -91,6 +92,26 @@ static int brcmf_feat_debugfs_read(struct seq_file *seq, 
void *data)
 }
 #endif /* DEBUG */
 
+static void brcmf_feat_cmd_int_get(struct brcmf_if *ifp, enum brcmf_feat_id id,
+  u32 cmd)
+{
+   u32 data;
+   int err;
+
+   ifp->fwil_fwerr = true;
+
+   err = brcmf_fil_cmd_int_get(ifp, cmd, );
+   if (err == 0) {
+   brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
+   ifp->drvr->feat_flags |= BIT(id);
+   } else {
+   brcmf_dbg(TRACE, "%s feature check failed: %d\n",
+ brcmf_feat_names[id], err);
+   }
+
+   ifp->fwil_fwerr = false;
+}
+
 /**
  * brcmf_feat_iovar_int_get() - determine feature through iovar query.
  *
@@ -251,6 +272,11 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
}
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
 
+   /* Fallback detection for older firmwares */
+   if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR))
+   brcmf_feat_cmd_int_get(ifp, BRCMF_FEAT_MONITOR,
+  BRCMF_C_GET_MONITOR);
+
/* set chip related quirks */
switch (drvr->bus_if->chip) {
case BRCM_CC_43236_CHIP_ID:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
index d1193825e559..6eddb19ca48d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
@@ -33,6 +33,7 @@
  * MFP: 802.11w Management Frame Protection.
  * GSCAN: enhanced scan offload feature.
  * FWSUP: Firmware supplicant.
+ * MONITOR: monitor interface
  */
 #define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \
@@ -48,7 +49,8 @@
BRCMF_FEAT_DEF(WOWL_ARP_ND) \
BRCMF_FEAT_DEF(MFP) \
BRCMF_FEAT_DEF(GSCAN) \
-   BRCMF_FEAT_DEF(FWSUP)
+   BRCMF_FEAT_DEF(FWSUP) \
+   BRCMF_FEAT_DEF(MONITOR)
 
 /*
  * Quirks:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
index 63b1287e2e6d..0d9492fd758d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
@@ -60,6 +60,8 @@
 #define BRCMF_C_GET_PM 85
 #define BRCMF_C_SET_PM 86
 #define BRCMF_C_GET_REVINFO98
+#define BRCMF_C_GET_MONITOR107
+#define BRCMF_C_SET_MONITOR108
 #define BRCMF_C_GET_CURR_RATESET   114
 #define BRCMF_C_GET_AP 117
 #define BRCMF_C_SET_AP 118
-- 
2.13.7



[PATCH V3 0/2] brcmfmac: initial work for adding monitor mode

2018-06-19 Thread Rafał Miłecki
From: Rafał Miłecki 

After a bit long discussions in various e-mail threads I'm coming with
this simple & small patchset. It isn't complete support for monitor mode
but just a pair of preparing patches that should be clear & well
discussed by now to make them acceptable.

The main missing bit is code setting MONITOR_FMT_RADIOTAP which I expect
Arend to handle soon, as he already has a patch using "sta_monitor"
iovar for that. Then we have to discuss a flag for marking firmwares
which are capable for tagging monitor frames.

While still incomplete, I believe that with my previous patches, we can
agree this is a good direction.

Arend: if you find these 2 patches OK, could you ack them, to make it
clear for Kalle if they look OK now (or not yet)? I'd be great if you
could sent your "sta_monitor" work on top of this.

Rafał Miłecki (2):
  brcmfmac: detect firmware support for monitor interface
  brcmfmac: handle monitor mode marked msgbuf packets

 .../wireless/broadcom/brcm80211/brcmfmac/core.c| 25 +
 .../wireless/broadcom/brcm80211/brcmfmac/core.h|  2 ++
 .../wireless/broadcom/brcm80211/brcmfmac/feature.c | 26 ++
 .../wireless/broadcom/brcm80211/brcmfmac/feature.h |  6 -
 .../wireless/broadcom/brcm80211/brcmfmac/fwil.h|  2 ++
 .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c  | 17 ++
 6 files changed, 77 insertions(+), 1 deletion(-)

-- 
2.13.7



[PATCH] mac80211: Fix oops in ieee80211_tx_control_port

2018-06-19 Thread Denis Kenzior
On pre-emption enabled kernels the following oops was being seen due to
missing local_bh_disable/local_bh_enable calls.  mac80211 assumes that
pre-emption is disabled in the data path.

[ 5365.229756] Call Trace:
[ 5365.229762]  dump_stack+0x5c/0x80
[ 5365.229766]  check_preemption_disabled.cold.0+0x46/0x51
[ 5365.229779]  __ieee80211_subif_start_xmit+0x144/0x210 [mac80211]
[ 5365.229790]  ieee80211_tx_control_port+0x116/0x140 [mac80211]
[ 5365.229806]  nl80211_tx_control_port+0x13c/0x270 [cfg80211]
[ 5365.229810]  genl_family_rcv_msg+0x1c4/0x3a0
[ 5365.229814]  ? nlmon_xmit+0x3c/0x50 [nlmon]
[ 5365.229816]  ? dev_hard_start_xmit+0xa5/0x240
[ 5365.229817]  genl_rcv_msg+0x47/0x90
[ 5365.229818]  ? genl_family_rcv_msg+0x3a0/0x3a0
[ 5365.229820]  netlink_rcv_skb+0x4c/0x120
[ 5365.229821]  genl_rcv+0x24/0x40
[ 5365.229822]  netlink_unicast+0x196/0x240
[ 5365.229824]  netlink_sendmsg+0x1fd/0x3c0
[ 5365.229826]  sock_sendmsg+0x33/0x40
[ 5365.229827]  __sys_sendto+0xee/0x160
[ 5365.229830]  ? __se_sys_epoll_ctl+0x34d/0xe80
[ 5365.229831]  ? do_epoll_wait+0xb0/0xd0
[ 5365.229832]  __x64_sys_sendto+0x24/0x30
[ 5365.229835]  do_syscall_64+0x5b/0x170
[ 5365.229836]  entry_SYSCALL_64_after_hwframe+0x44/0xa9

Signed-off-by: Denis Kenzior 
---
 net/mac80211/tx.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5b93bde248fd..6a79d564de35 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4850,7 +4850,9 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct 
net_device *dev,
skb_reset_network_header(skb);
skb_reset_mac_header(skb);
 
+   local_bh_disable();
__ieee80211_subif_start_xmit(skb, skb->dev, flags);
+   local_bh_enable();
 
return 0;
 }
-- 
2.13.5



[PATCH v3 0/8] wil6210 patches

2018-06-19 Thread Maya Erez
Changes from v2:
- Fix amsdu setting in BA response
- Remove crash dump collection from OTP sectionas it can cause PCIe halt

Changes from v1:
- Removal of module parameters
- Addition of debugfs entries for configuring enhanced DMA
- Fixing kbuild bot error
- Enabling AMSDU by default (based on FW support)
- Fixing L2 translation mode

The following set of patches add support for new wil6210 device (Talyn ver 2.0):
- Definition of the new device ID and memory areas
- New boot flow procedure and reset sequence
- Support new DMA interface - enhanced DMA
- Support new HW offloads, such as TSO, RX reorder and AMSDU

Gidon Studinski (3):
  wil6210: add support for enhanced DMA structures
  wil6210: initialize TX and RX enhanced DMA rings
  wil6210: add support for enhanced DMA RX data flows

Maya Erez (5):
  wil6210: add support for Talyn-MB (Talyn ver 2.0) device
  wil6210: add support for enhanced DMA TX data flows
  wil6210: add support for enhanced DMA debugfs
  wil6210: add support for Talyn-MB boot flow
  wil6210: remove crash dump collection from OTP section

 drivers/net/wireless/ath/wil6210/Makefile |1 +
 drivers/net/wireless/ath/wil6210/cfg80211.c   |   12 +-
 drivers/net/wireless/ath/wil6210/debugfs.c|  490 +--
 drivers/net/wireless/ath/wil6210/ethtool.c|2 +-
 drivers/net/wireless/ath/wil6210/interrupt.c  |  225 ++-
 drivers/net/wireless/ath/wil6210/main.c   |  360 -
 drivers/net/wireless/ath/wil6210/netdev.c |   73 +-
 drivers/net/wireless/ath/wil6210/pcie_bus.c   |   59 +-
 drivers/net/wireless/ath/wil6210/pm.c |6 +-
 drivers/net/wireless/ath/wil6210/rx_reorder.c |   26 +-
 drivers/net/wireless/ath/wil6210/trace.h  |   59 +
 drivers/net/wireless/ath/wil6210/txrx.c   |  649 -
 drivers/net/wireless/ath/wil6210/txrx.h   |  105 +-
 drivers/net/wireless/ath/wil6210/txrx_edma.c  | 1598 +
 drivers/net/wireless/ath/wil6210/txrx_edma.h  |  562 
 drivers/net/wireless/ath/wil6210/wil6210.h|  228 ++-
 drivers/net/wireless/ath/wil6210/wil_crash_dump.c |4 +-
 drivers/net/wireless/ath/wil6210/wmi.c|  502 ++-
 drivers/net/wireless/ath/wil6210/wmi.h|  167 ++-
 19 files changed, 4467 insertions(+), 661 deletions(-)
 create mode 100644 drivers/net/wireless/ath/wil6210/txrx_edma.c
 create mode 100644 drivers/net/wireless/ath/wil6210/txrx_edma.h

-- 
1.9.1



[PATCH v3 1/8] wil6210: add support for Talyn-MB (Talyn ver 2.0) device

2018-06-19 Thread Maya Erez
Add changes to support initialization of Talyn-MB wil6210
device:
- Add definition for Talyn-MB new JTAG id
- Define talyn_mb_fw_mapping array
- Add Talyn-MB reset sequence

Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/main.c | 48 +++--
 drivers/net/wireless/ath/wil6210/pcie_bus.c | 11 +-
 drivers/net/wireless/ath/wil6210/wil6210.h  | 11 +-
 drivers/net/wireless/ath/wil6210/wmi.c  | 55 +
 4 files changed, 113 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/main.c 
b/drivers/net/wireless/ath/wil6210/main.c
index e7006c2..1282e1a 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -736,14 +736,24 @@ static void wil_bl_prepare_halt(struct wil6210_priv *wil)
 
 static inline void wil_halt_cpu(struct wil6210_priv *wil)
 {
-   wil_w(wil, RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST);
-   wil_w(wil, RGF_USER_MAC_CPU_0,  BIT_USER_MAC_CPU_MAN_RST);
+   if (wil->hw_version >= HW_VER_TALYN_MB) {
+   wil_w(wil, RGF_USER_USER_CPU_0_TALYN_MB,
+ BIT_USER_USER_CPU_MAN_RST);
+   wil_w(wil, RGF_USER_MAC_CPU_0_TALYN_MB,
+ BIT_USER_MAC_CPU_MAN_RST);
+   } else {
+   wil_w(wil, RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST);
+   wil_w(wil, RGF_USER_MAC_CPU_0,  BIT_USER_MAC_CPU_MAN_RST);
+   }
 }
 
 static inline void wil_release_cpu(struct wil6210_priv *wil)
 {
/* Start CPU */
-   wil_w(wil, RGF_USER_USER_CPU_0, 1);
+   if (wil->hw_version >= HW_VER_TALYN_MB)
+   wil_w(wil, RGF_USER_USER_CPU_0_TALYN_MB, 1);
+   else
+   wil_w(wil, RGF_USER_USER_CPU_0, 1);
 }
 
 static void wil_set_oob_mode(struct wil6210_priv *wil, u8 mode)
@@ -811,10 +821,17 @@ static int wil_target_reset(struct wil6210_priv *wil, int 
no_flash)
wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf);
 
-   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE00);
-   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x003F);
-   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00f0);
-   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FE00);
+   if (wil->hw_version >= HW_VER_TALYN_MB) {
+   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x7e00);
+   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x003f);
+   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0xc0f0);
+   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xffe7fe00);
+   } else {
+   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xfe00);
+   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x003f);
+   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00f0);
+   wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xffe7fe00);
+   }
 
wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0);
@@ -1042,8 +1059,14 @@ static int wil_get_otp_info(struct wil6210_priv *wil)
struct net_device *ndev = wil->main_ndev;
struct wiphy *wiphy = wil_to_wiphy(wil);
u8 mac[8];
+   int mac_addr;
+
+   if (wil->hw_version >= HW_VER_TALYN_MB)
+   mac_addr = RGF_OTP_MAC_TALYN_MB;
+   else
+   mac_addr = RGF_OTP_MAC;
 
-   wil_memcpy_fromio_32(mac, wil->csr + HOSTADDR(RGF_OTP_MAC),
+   wil_memcpy_fromio_32(mac, wil->csr + HOSTADDR(mac_addr),
 sizeof(mac));
if (!is_valid_ether_addr(mac)) {
wil_err(wil, "Invalid MAC %pM\n", mac);
@@ -1147,8 +1170,13 @@ static void wil_pre_fw_config(struct wil6210_priv *wil)
/* it is W1C, clear by writing back same value */
wil_s(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0);
wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0);
-   /* clear PAL_UNIT_ICR (potential D0->D3 leftover) */
-   wil_s(wil, RGF_PAL_UNIT_ICR + offsetof(struct RGF_ICR, ICR), 0);
+   /* clear PAL_UNIT_ICR (potential D0->D3 leftover)
+* In Talyn-MB host cannot access this register due to
+* access control, hence PAL_UNIT_ICR is cleared by the FW
+*/
+   if (wil->hw_version < HW_VER_TALYN_MB)
+   wil_s(wil, RGF_PAL_UNIT_ICR + offsetof(struct RGF_ICR, ICR),
+ 0);
 
if (wil->fw_calib_result > 0) {
__le32 val = cpu_to_le32(wil->fw_calib_result |
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c 
b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index 19cbc6a..3a7e406 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -85,7 +85,7 @@ int wil_set_capabilities(struct wil6210_priv *wil)
wil->rgf_ucode_assert_code_addr = SPARROW_RGF_UCODE_ASSERT_CODE;
   

[PATCH v3 7/8] wil6210: add support for Talyn-MB boot flow

2018-06-19 Thread Maya Erez
Talyn-MB introduces various of FW download options:
FW download via PCIe, SPI or PBL for secured access.
The boot and FW download path is determined based on the
OTP HW register. Driver reads this register as part of the
SW reset flow and performs the appropriate initialization
sequence.

Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/main.c| 194 -
 drivers/net/wireless/ath/wil6210/wil6210.h |   9 +-
 2 files changed, 171 insertions(+), 32 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/main.c 
b/drivers/net/wireless/ath/wil6210/main.c
index e0072b6..4de19bd 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -112,9 +112,29 @@ static int ring_order_set(const char *val, const struct 
kernel_param *kp)
 module_param_cb(bcast_ring_order, _order_ops, _ring_order, 0444);
 MODULE_PARM_DESC(bcast_ring_order, " Bcast ring order; size = 1 << order");
 
-#define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
+enum {
+   WIL_BOOT_ERR,
+   WIL_BOOT_VANILLA,
+   WIL_BOOT_PRODUCTION,
+   WIL_BOOT_DEVELOPMENT,
+};
+
+enum {
+   WIL_SIG_STATUS_VANILLA = 0x0,
+   WIL_SIG_STATUS_DEVELOPMENT = 0x1,
+   WIL_SIG_STATUS_PRODUCTION = 0x2,
+   WIL_SIG_STATUS_CORRUPTED_PRODUCTION = 0x3,
+};
+
+#define RST_DELAY (20) /* msec, for loop in @wil_wait_device_ready */
 #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
 
+#define PMU_READY_DELAY_MS (4) /* ms, for sleep in @wil_wait_device_ready */
+
+#define OTP_HW_DELAY (200) /* usec, loop in @wil_wait_device_ready_talyn_mb */
+/* round up to be above 2 ms total */
+#define OTP_HW_COUNT (1 + 2000 / OTP_HW_DELAY)
+
 /*
  * Due to a hardware issue,
  * one has to read/write to/from NIC in 32-bit chunks;
@@ -831,11 +851,146 @@ static void wil_set_oob_mode(struct wil6210_priv *wil, 
u8 mode)
}
 }
 
-static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
+static int wil_wait_device_ready(struct wil6210_priv *wil, int no_flash)
 {
int delay = 0;
u32 x, x1 = 0;
 
+   /* wait until device ready. */
+   if (no_flash) {
+   msleep(PMU_READY_DELAY_MS);
+
+   wil_dbg_misc(wil, "Reset completed\n");
+   } else {
+   do {
+   msleep(RST_DELAY);
+   x = wil_r(wil, RGF_USER_BL +
+ offsetof(struct bl_dedicated_registers_v0,
+  boot_loader_ready));
+   if (x1 != x) {
+   wil_dbg_misc(wil, "BL.ready 0x%08x => 0x%08x\n",
+x1, x);
+   x1 = x;
+   }
+   if (delay++ > RST_COUNT) {
+   wil_err(wil, "Reset not completed, bl.ready 
0x%08x\n",
+   x);
+   return -ETIME;
+   }
+   } while (x != BL_READY);
+
+   wil_dbg_misc(wil, "Reset completed in %d ms\n",
+delay * RST_DELAY);
+   }
+
+   return 0;
+}
+
+static int wil_wait_device_ready_talyn_mb(struct wil6210_priv *wil)
+{
+   u32 otp_hw;
+   u8 signature_status;
+   bool otp_signature_err;
+   bool hw_section_done;
+   u32 otp_qc_secured;
+   int delay = 0;
+
+   /* Wait for OTP signature test to complete */
+   usleep_range(2000, 2200);
+
+   wil->boot_config = WIL_BOOT_ERR;
+
+   /* Poll until OTP signature status is valid.
+* In vanilla and development modes, when signature test is complete
+* HW sets BIT_OTP_SIGNATURE_ERR_TALYN_MB.
+* In production mode BIT_OTP_SIGNATURE_ERR_TALYN_MB remains 0, poll
+* for signature status change to 2 or 3.
+*/
+   do {
+   otp_hw = wil_r(wil, RGF_USER_OTP_HW_RD_MACHINE_1);
+   signature_status = WIL_GET_BITS(otp_hw, 8, 9);
+   otp_signature_err = otp_hw & BIT_OTP_SIGNATURE_ERR_TALYN_MB;
+
+   if (otp_signature_err &&
+   signature_status == WIL_SIG_STATUS_VANILLA) {
+   wil->boot_config = WIL_BOOT_VANILLA;
+   break;
+   }
+   if (otp_signature_err &&
+   signature_status == WIL_SIG_STATUS_DEVELOPMENT) {
+   wil->boot_config = WIL_BOOT_DEVELOPMENT;
+   break;
+   }
+   if (!otp_signature_err &&
+   signature_status == WIL_SIG_STATUS_PRODUCTION) {
+   wil->boot_config = WIL_BOOT_PRODUCTION;
+   break;
+   }
+   if  (!otp_signature_err &&
+signature_status ==
+WIL_SIG_STATUS_CORRUPTED_PRODUCTION) {
+   

[PATCH v3 5/8] wil6210: add support for enhanced DMA RX data flows

2018-06-19 Thread Maya Erez
From: Gidon Studinski 

Enhanced DMA RX data path is handled using a single
RX descriptor ring for all VIFs.
Multiple RX status rings are supported, to allow RSS
and multi MSI support.
The driver gets the RX completions via the RX status rings.
The RX status message includes the completed RX buffer ID,
which points to the allocated SKB.

The enhanced DMA RX data flow supports RX chaining, where
multiple SKBs are merged into a single packet.

Enhanced DMA HW supports RX HW reorder offload, enabled by
default for Talyn-MB.

amsdu_en debugfs entry was added to allow control MSDU aggregation.
Use the following command to disable AMSDU (enabled by default):
echo 0 > amsdu_en

Signed-off-by: Gidon Studinski 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/debugfs.c|   1 +
 drivers/net/wireless/ath/wil6210/interrupt.c  |  86 -
 drivers/net/wireless/ath/wil6210/main.c   |   3 +
 drivers/net/wireless/ath/wil6210/netdev.c |  35 +-
 drivers/net/wireless/ath/wil6210/pcie_bus.c   |   1 +
 drivers/net/wireless/ath/wil6210/pm.c |   6 +-
 drivers/net/wireless/ath/wil6210/rx_reorder.c |  24 +-
 drivers/net/wireless/ath/wil6210/trace.h  |  34 ++
 drivers/net/wireless/ath/wil6210/txrx.c   |  53 ++-
 drivers/net/wireless/ath/wil6210/txrx.h   |   7 +
 drivers/net/wireless/ath/wil6210/txrx_edma.c  | 456 ++
 drivers/net/wireless/ath/wil6210/txrx_edma.h  | 189 +++
 drivers/net/wireless/ath/wil6210/wil6210.h|  24 +-
 drivers/net/wireless/ath/wil6210/wmi.c|  59 +++-
 drivers/net/wireless/ath/wil6210/wmi.h|   1 +
 15 files changed, 939 insertions(+), 40 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c 
b/drivers/net/wireless/ath/wil6210/debugfs.c
index 212baf4..8232fdd 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1919,6 +1919,7 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv 
*wil,
WIL_FIELD(rx_status_ring_order, 0644,   doff_u32),
WIL_FIELD(tx_status_ring_order, 0644,   doff_u32),
WIL_FIELD(rx_buff_id_count, 0644,   doff_u32),
+   WIL_FIELD(amsdu_en, 0644,   doff_u8),
{},
 };
 
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c 
b/drivers/net/wireless/ath/wil6210/interrupt.c
index 1603b9f..d7e112d 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -45,6 +45,7 @@
 #define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \
BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
 #define WIL6210_IMC_TX_EDMABIT_TX_STATUS_IRQ
+#define WIL6210_IMC_RX_EDMABIT_RX_STATUS_IRQ
 #define WIL6210_IMC_MISC_NO_HALP   (ISR_MISC_FW_READY | \
 ISR_MISC_MBOX_EVT | \
 ISR_MISC_FW_ERROR)
@@ -100,6 +101,12 @@ static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
  WIL6210_IRQ_DISABLE);
 }
 
+static void wil6210_mask_irq_rx_edma(struct wil6210_priv *wil)
+{
+   wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, IMS),
+ WIL6210_IRQ_DISABLE);
+}
+
 static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp)
 {
wil_dbg_irq(wil, "mask_irq_misc: mask_halp(%s)\n",
@@ -146,6 +153,12 @@ void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
  unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH);
 }
 
+void wil6210_unmask_irq_rx_edma(struct wil6210_priv *wil)
+{
+   wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, IMC),
+ WIL6210_IMC_RX_EDMA);
+}
+
 static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp)
 {
wil_dbg_irq(wil, "unmask_irq_misc: unmask_halp(%s)\n",
@@ -179,6 +192,7 @@ void wil_mask_irq(struct wil6210_priv *wil)
wil6210_mask_irq_tx(wil);
wil6210_mask_irq_tx_edma(wil);
wil6210_mask_irq_rx(wil);
+   wil6210_mask_irq_rx_edma(wil);
wil6210_mask_irq_misc(wil, true);
wil6210_mask_irq_pseudo(wil);
 }
@@ -195,10 +209,13 @@ void wil_unmask_irq(struct wil6210_priv *wil)
  WIL_ICR_ICC_MISC_VALUE);
wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, ICC),
  WIL_ICR_ICC_VALUE);
+   wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, ICC),
+ WIL_ICR_ICC_VALUE);
 
wil6210_unmask_irq_pseudo(wil);
if (wil->use_enhanced_dma_hw) {
wil6210_unmask_irq_tx_edma(wil);
+   wil6210_unmask_irq_rx_edma(wil);
} else {
wil6210_unmask_irq_tx(wil);
wil6210_unmask_irq_rx(wil);
@@ -335,6 +352,54 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
return IRQ_HANDLED;
 }
 
+static irqreturn_t wil6210_irq_rx_edma(int irq, void *cookie)
+{
+   struct wil6210_priv *wil = cookie;
+   u32 isr = wil_ioread32_and_clear(wil->csr 

[PATCH v3 4/8] wil6210: add support for enhanced DMA TX data flows

2018-06-19 Thread Maya Erez
The enhanced DMA TX data path is handled using a descriptor
ring per connection and a single status ring.

The driver gets TX completions via the TX status ring. Each
status message points to the completed descriptor ring and
includes the number of completed descriptors in this ring.

Non TSO enhanced DMA TX descriptors are similar to legacy DMA
TX descriptors, hence the same transmit function can be used.

However, enhanced DMA TSO frames division is performed by the
HW, hence a new function is added to handle enhanced DMA TSO.

Signed-off-by: Gidon Studinski 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/interrupt.c | 126 ++--
 drivers/net/wireless/ath/wil6210/netdev.c|  36 ++-
 drivers/net/wireless/ath/wil6210/trace.h |  25 ++
 drivers/net/wireless/ath/wil6210/txrx.c  | 194 ++--
 drivers/net/wireless/ath/wil6210/txrx.h  |  22 ++
 drivers/net/wireless/ath/wil6210/txrx_edma.c | 427 ++-
 drivers/net/wireless/ath/wil6210/txrx_edma.h |  33 ++-
 drivers/net/wireless/ath/wil6210/wil6210.h   |  15 +
 8 files changed, 750 insertions(+), 128 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c 
b/drivers/net/wireless/ath/wil6210/interrupt.c
index 311d482..1603b9f 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -44,6 +44,7 @@
(~(BIT_DMA_EP_RX_ICR_RX_HTRSH)))
 #define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \
BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
+#define WIL6210_IMC_TX_EDMABIT_TX_STATUS_IRQ
 #define WIL6210_IMC_MISC_NO_HALP   (ISR_MISC_FW_READY | \
 ISR_MISC_MBOX_EVT | \
 ISR_MISC_FW_ERROR)
@@ -87,6 +88,12 @@ static void wil6210_mask_irq_tx(struct wil6210_priv *wil)
  WIL6210_IRQ_DISABLE);
 }
 
+static void wil6210_mask_irq_tx_edma(struct wil6210_priv *wil)
+{
+   wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, IMS),
+ WIL6210_IRQ_DISABLE);
+}
+
 static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
 {
wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMS),
@@ -125,6 +132,12 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil)
  WIL6210_IMC_TX);
 }
 
+void wil6210_unmask_irq_tx_edma(struct wil6210_priv *wil)
+{
+   wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, IMC),
+ WIL6210_IMC_TX_EDMA);
+}
+
 void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
 {
bool unmask_rx_htrsh = atomic_read(>connected_vifs) > 0;
@@ -164,6 +177,7 @@ void wil_mask_irq(struct wil6210_priv *wil)
wil_dbg_irq(wil, "mask_irq\n");
 
wil6210_mask_irq_tx(wil);
+   wil6210_mask_irq_tx_edma(wil);
wil6210_mask_irq_rx(wil);
wil6210_mask_irq_misc(wil, true);
wil6210_mask_irq_pseudo(wil);
@@ -179,10 +193,16 @@ void wil_unmask_irq(struct wil6210_priv *wil)
  WIL_ICR_ICC_VALUE);
wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC),
  WIL_ICR_ICC_MISC_VALUE);
+   wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, ICC),
+ WIL_ICR_ICC_VALUE);
 
wil6210_unmask_irq_pseudo(wil);
-   wil6210_unmask_irq_tx(wil);
-   wil6210_unmask_irq_rx(wil);
+   if (wil->use_enhanced_dma_hw) {
+   wil6210_unmask_irq_tx_edma(wil);
+   } else {
+   wil6210_unmask_irq_tx(wil);
+   wil6210_unmask_irq_rx(wil);
+   }
wil6210_unmask_irq_misc(wil, true);
 }
 
@@ -315,6 +335,49 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
return IRQ_HANDLED;
 }
 
+static irqreturn_t wil6210_irq_tx_edma(int irq, void *cookie)
+{
+   struct wil6210_priv *wil = cookie;
+   u32 isr = wil_ioread32_and_clear(wil->csr +
+HOSTADDR(RGF_INT_GEN_TX_ICR) +
+offsetof(struct RGF_ICR, ICR));
+   bool need_unmask = true;
+
+   trace_wil6210_irq_tx(isr);
+   wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
+
+   if (unlikely(!isr)) {
+   wil_err(wil, "spurious IRQ: TX\n");
+   return IRQ_NONE;
+   }
+
+   wil6210_mask_irq_tx_edma(wil);
+
+   if (likely(isr & BIT_TX_STATUS_IRQ)) {
+   wil_dbg_irq(wil, "TX status ring\n");
+   isr &= ~BIT_TX_STATUS_IRQ;
+   if (likely(test_bit(wil_status_fwready, wil->status))) {
+   wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
+   need_unmask = false;
+   napi_schedule(>napi_tx);
+   } else {
+   wil_err(wil, "Got Tx status ring IRQ while in reset\n");
+   }
+   }
+
+   if (unlikely(isr))
+   wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr);
+
+   /* Tx IRQ will be enabled 

[PATCH v3 6/8] wil6210: add support for enhanced DMA debugfs

2018-06-19 Thread Maya Erez
Add debugfs support for enhanced DMA TX and RX descriptor rings,
TX and RX status rings and RX buffer management.

Run the following command to print the TX and RX status rings:
cat srings

Run the following command in order to select the status ring:
echo STATUS_RING_IDX > dbg_sring_index

Run the following command in order to select the status message:
echo STATUS_MSG_IDX > dbg_status_msg_index

Run the following command in order to print the selected status
message from the selected status ring:
cat status_msg

Run the following command in order to print the RX buffer management
debug information:
cat rx_buff_mgmt

Signed-off-by: Gidon Studinski 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/debugfs.c | 347 +
 1 file changed, 307 insertions(+), 40 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c 
b/drivers/net/wireless/ath/wil6210/debugfs.c
index 8232fdd..58ce044 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -30,6 +30,9 @@
 static u32 mem_addr;
 static u32 dbg_txdesc_index;
 static u32 dbg_ring_index; /* 24+ for Rx, 0..23 for Tx */
+static u32 dbg_status_msg_index;
+/* 0..wil->num_rx_status_rings-1 for Rx, wil->tx_sring_idx for Tx */
+static u32 dbg_sring_index;
 
 enum dbg_off_type {
doff_u32 = 0,
@@ -47,6 +50,36 @@ struct dbg_off {
enum dbg_off_type type;
 };
 
+static void wil_print_desc_edma(struct seq_file *s, struct wil6210_priv *wil,
+   struct wil_ring *ring,
+   char _s, char _h, int idx)
+{
+   u8 num_of_descs;
+   bool has_skb = false;
+
+   if (ring->is_rx) {
+   struct wil_rx_enhanced_desc *rx_d =
+   (struct wil_rx_enhanced_desc *)
+   >va[idx].rx.enhanced;
+   u16 buff_id = le16_to_cpu(rx_d->mac.buff_id);
+
+   has_skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb;
+   seq_printf(s, "%c", (has_skb) ? _h : _s);
+   } else {
+   struct wil_tx_enhanced_desc *d =
+   (struct wil_tx_enhanced_desc *)
+   >va[idx].tx.enhanced;
+
+   num_of_descs = (u8)d->mac.d[2];
+   has_skb = ring->ctx[idx].skb;
+   if (num_of_descs >= 1)
+   seq_printf(s, "%c", ring->ctx[idx].skb ? _h : _s);
+   else
+   /* num_of_descs == 0, it's a frag in a list of descs */
+   seq_printf(s, "%c", has_skb ? 'h' : _s);
+   }
+}
+
 static void wil_print_ring(struct seq_file *s, struct wil6210_priv *wil,
   const char *name, struct wil_ring *ring,
   char _s, char _h)
@@ -58,7 +91,10 @@ static void wil_print_ring(struct seq_file *s, struct 
wil6210_priv *wil,
seq_printf(s, "  pa = %pad\n", >pa);
seq_printf(s, "  va = 0x%p\n", ring->va);
seq_printf(s, "  size   = %d\n", ring->size);
-   seq_printf(s, "  swtail = %d\n", ring->swtail);
+   if (wil->use_enhanced_dma_hw && ring->is_rx)
+   seq_printf(s, "  swtail = %u\n", *ring->edma_rx_swtail.va);
+   else
+   seq_printf(s, "  swtail = %d\n", ring->swtail);
seq_printf(s, "  swhead = %d\n", ring->swhead);
seq_printf(s, "  hwtail = [0x%08x] -> ", ring->hwtail);
if (x) {
@@ -72,13 +108,16 @@ static void wil_print_ring(struct seq_file *s, struct 
wil6210_priv *wil,
uint i;
 
for (i = 0; i < ring->size; i++) {
-   volatile struct vring_tx_desc *d =
-   >va[i].tx.legacy;
-
-   if ((i % 128) == 0 && (i != 0))
+   if ((i % 128) == 0 && i != 0)
seq_puts(s, "\n");
-   seq_printf(s, "%c", (d->dma.status & BIT(0)) ?
-   _s : (ring->ctx[i].skb ? _h : 'h'));
+   if (wil->use_enhanced_dma_hw) {
+   wil_print_desc_edma(s, wil, ring, _s, _h, i);
+   } else {
+   volatile struct vring_tx_desc *d =
+   >va[i].tx.legacy;
+   seq_printf(s, "%c", (d->dma.status & BIT(0)) ?
+  _s : (ring->ctx[i].skb ? _h : 'h'));
+   }
}
seq_puts(s, "\n");
}
@@ -157,6 +196,74 @@ static int wil_ring_seq_open(struct inode *inode, struct 
file *file)
.llseek = seq_lseek,
 };
 
+static void wil_print_sring(struct seq_file *s, struct wil6210_priv *wil,
+   struct wil_status_ring *sring)
+{
+   void __iomem *x = wmi_addr(wil, sring->hwtail);
+   int sring_idx = sring - wil->srings;
+   u32 v;
+
+   seq_printf(s, 

[PATCH v3 3/8] wil6210: initialize TX and RX enhanced DMA rings

2018-06-19 Thread Maya Erez
From: Gidon Studinski 

Enhanced DMA design includes the following rings:
- Single RX descriptor ring is used for all VIFs
- Multiple RX status rings are supported, to allow RSS
- TX descriptor ring is allocated per connection
- A single TX status ring is used for all TX descriptor rings

This patch initializes and frees the above descriptor and
status rings.

The RX SKBs are handled by a new entity of RX buffers manager,
which handles RX buffers, each one points to an allocated SKB.
During Rx completion processing, the driver extracts a buffer
ID which is used as an index to the buffers array.
After the SKB is freed the buffer is moved from the 'active'
list to the 'free' list, indicating it can be used for another
descriptor. During Rx refill, SKBs are allocated and attached
to 'free' buffers. Those buffers are attached to new descriptors
and moved to the 'active' list.

New debugfs entries were added to allow edma configuration:

Run the following command to configure the number of status rings:
echo NUM_OF_STATUS_RINGS > num_rx_status_rings

Run the following command to use extended RX status message for
additional debug fields from HW:
echo 0 > compressed_rx_status

Run the following command to control the size of the TX status ring:
echo TX_STATUS_RING_ORDER > tx_status_ring_order
The status ring size will be 1 << tx_status_ring_order

Run the following command to control the size of the RX status ring:
echo RX_STATUS_RING_ORDER > rx_status_ring_order
Due to HW constrains RX sring order should be bigger than RX ring order
The status ring size will be 1 << rx_status_ring_order

Run the following command to change the number of RX buffer IDs:
echo RX_BUFF_ID_COUNT > rx_buff_id_count

Signed-off-by: Gidon Studinski 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/Makefile|   1 +
 drivers/net/wireless/ath/wil6210/debugfs.c   |  59 +++
 drivers/net/wireless/ath/wil6210/ethtool.c   |   2 +-
 drivers/net/wireless/ath/wil6210/interrupt.c |  21 +
 drivers/net/wireless/ath/wil6210/main.c  |  81 ++-
 drivers/net/wireless/ath/wil6210/pcie_bus.c  |  47 +-
 drivers/net/wireless/ath/wil6210/txrx.c  |  90 ++--
 drivers/net/wireless/ath/wil6210/txrx.h  |   8 +
 drivers/net/wireless/ath/wil6210/txrx_edma.c | 719 +++
 drivers/net/wireless/ath/wil6210/txrx_edma.h |  54 +-
 drivers/net/wireless/ath/wil6210/wil6210.h   |  62 ++-
 drivers/net/wireless/ath/wil6210/wmi.c   | 316 +++-
 drivers/net/wireless/ath/wil6210/wmi.h   | 166 ++-
 13 files changed, 1513 insertions(+), 113 deletions(-)
 create mode 100644 drivers/net/wireless/ath/wil6210/txrx_edma.c

diff --git a/drivers/net/wireless/ath/wil6210/Makefile 
b/drivers/net/wireless/ath/wil6210/Makefile
index 398edd2..d3d61ae 100644
--- a/drivers/net/wireless/ath/wil6210/Makefile
+++ b/drivers/net/wireless/ath/wil6210/Makefile
@@ -9,6 +9,7 @@ wil6210-$(CONFIG_WIL6210_DEBUGFS) += debugfs.o
 wil6210-y += wmi.o
 wil6210-y += interrupt.o
 wil6210-y += txrx.o
+wil6210-y += txrx_edma.o
 wil6210-y += debug.o
 wil6210-y += rx_reorder.o
 wil6210-y += fw.o
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c 
b/drivers/net/wireless/ath/wil6210/debugfs.c
index 55e03e9b..212baf4 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1761,6 +1761,60 @@ static ssize_t wil_read_suspend_stats(struct file *file,
.open  = simple_open,
 };
 
+/*-compressed_rx_status-*/
+static ssize_t wil_compressed_rx_status_write(struct file *file,
+ const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+   struct seq_file *s = file->private_data;
+   struct wil6210_priv *wil = s->private;
+   int compressed_rx_status;
+   int rc;
+
+   rc = kstrtoint_from_user(buf, len, 0, _rx_status);
+   if (rc) {
+   wil_err(wil, "Invalid argument\n");
+   return rc;
+   }
+
+   if (wil_has_active_ifaces(wil, true, false)) {
+   wil_err(wil, "cannot change edma config after iface is up\n");
+   return -EPERM;
+   }
+
+   wil_info(wil, "%sable compressed_rx_status\n",
+compressed_rx_status ? "En" : "Dis");
+
+   wil->use_compressed_rx_status = compressed_rx_status;
+
+   return len;
+}
+
+static int
+wil_compressed_rx_status_show(struct seq_file *s, void *data)
+{
+   struct wil6210_priv *wil = s->private;
+
+   seq_printf(s, "%d\n", wil->use_compressed_rx_status);
+
+   return 0;
+}
+
+static int
+wil_compressed_rx_status_seq_open(struct inode *inode, struct file *file)
+{
+   return single_open(file, wil_compressed_rx_status_show,
+  inode->i_private);
+}
+
+static const struct file_operations fops_compressed_rx_status = {
+   .open  = wil_compressed_rx_status_seq_open,
+   .release = single_release,
+   .read = 

[PATCH v3 8/8] wil6210: remove crash dump collection from OTP section

2018-06-19 Thread Maya Erez
In some cases where the device is stuck, reading from OTP
can timeout. As OTP section is known there is no need to read
it during device crash dump collection.
Adding a new field to struct fw_map to indicate if to include
this section in crash dump collection.

Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/wil6210.h|  1 +
 drivers/net/wireless/ath/wil6210/wil_crash_dump.c |  4 +-
 drivers/net/wireless/ath/wil6210/wmi.c| 86 +++
 3 files changed, 46 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h 
b/drivers/net/wireless/ath/wil6210/wil6210.h
index e639ba7..d963c76 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -403,6 +403,7 @@ struct fw_map {
u32 host; /* PCI/Host address - BAR0 + 0x88 */
const char *name; /* for debugfs */
bool fw; /* true if FW mapping, false if UCODE mapping */
+   bool crash_dump; /* true if should be dumped during crash dump */
 };
 
 /* array size should be in sync with actual definition in the wmi.c */
diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c 
b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
index 1ed3306..654d89e 100644
--- a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
+++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
@@ -36,7 +36,7 @@ static int wil_fw_get_crash_dump_bounds(struct wil6210_priv 
*wil,
for (i = 1; i < ARRAY_SIZE(fw_mapping); i++) {
map = _mapping[i];
 
-   if (!map->fw)
+   if (!map->crash_dump)
continue;
 
if (map->host < host_min)
@@ -85,7 +85,7 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void 
*dest, u32 size)
for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
map = _mapping[i];
 
-   if (!map->fw)
+   if (!map->crash_dump)
continue;
 
data = (void * __force)wil->csr + HOSTADDR(map->host);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c 
b/drivers/net/wireless/ath/wil6210/wmi.c
index 0370b7e..71056c8 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -89,28 +89,28 @@
  */
 const struct fw_map sparrow_fw_mapping[] = {
/* FW code RAM 256k */
-   {0x00, 0x04, 0x8c, "fw_code", true},
+   {0x00, 0x04, 0x8c, "fw_code", true, true},
/* FW data RAM 32k */
-   {0x80, 0x808000, 0x90, "fw_data", true},
+   {0x80, 0x808000, 0x90, "fw_data", true, true},
/* periph data 128k */
-   {0x84, 0x86, 0x908000, "fw_peri", true},
+   {0x84, 0x86, 0x908000, "fw_peri", true, true},
/* various RGF 40k */
-   {0x88, 0x88a000, 0x88, "rgf", true},
+   {0x88, 0x88a000, 0x88, "rgf", true, true},
/* AGC table   4k */
-   {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true},
+   {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
/* Pcie_ext_rgf 4k */
-   {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true},
+   {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
/* mac_ext_rgf 512b */
-   {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true},
+   {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true, true},
/* upper area 548k */
-   {0x8c, 0x949000, 0x8c, "upper", true},
+   {0x8c, 0x949000, 0x8c, "upper", true, true},
/* UCODE areas - accessible by debugfs blobs but not by
 * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
 */
/* ucode code RAM 128k */
-   {0x00, 0x02, 0x92, "uc_code", false},
+   {0x00, 0x02, 0x92, "uc_code", false, false},
/* ucode data RAM 16k */
-   {0x80, 0x804000, 0x94, "uc_data", false},
+   {0x80, 0x804000, 0x94, "uc_data", false, false},
 };
 
 /**
@@ -118,7 +118,7 @@
  * it is a bit larger to support extra features
  */
 const struct fw_map sparrow_d0_mac_rgf_ext = {
-   0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true
+   0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true, true
 };
 
 /**
@@ -134,34 +134,34 @@
  */
 const struct fw_map talyn_fw_mapping[] = {
/* FW code RAM 1M */
-   {0x00, 0x10, 0x90, "fw_code", true},
+   {0x00, 0x10, 0x90, "fw_code", true, true},
/* FW data RAM 128k */
-   {0x80, 0x82, 0xa0, "fw_data", true},
+   {0x80, 0x82, 0xa0, "fw_data", true, true},
/* periph. data RAM 96k */
-   {0x84, 0x858000, 0xa2, "fw_peri", true},
+   {0x84, 0x858000, 0xa2, "fw_peri", true, true},
/* various RGF 40k */
-   {0x88, 0x88a000, 0x88, "rgf", true},
+   {0x88, 0x88a000, 0x88, "rgf", true, true},
/* AGC table 4k */
-   {0x88a000, 

[PATCH v3 2/8] wil6210: add support for enhanced DMA structures

2018-06-19 Thread Maya Erez
From: Gidon Studinski 

In enhanced DMA the vrings are handled internally by the FW
and are not exposed to the driver.
Instead, the driver handles descriptor rings, which are mapped
by the FW to vrings.
The completions of the TX and RX descriptors are notified to
the driver using status rings. Each status ring descriptor
includes information of the completed descriptors and the ring id
of their descriptor ring.

This patch changes struct vring to generic wil_ring to allow
its reuse for enhanced DMA descriptor rings and adds the descriptor
and status rings specific descriptors.

The vring debugfs entries have changed as follows:
- dbg_vring_index has changed to dbg_ring_index
- vrings has changed to rings
- vring_idle_trsh has changed to ring_idle_trsh
- vring_index has changed to ring_index

Signed-off-by: Gidon Studinski 
Signed-off-by: Maya Erez 
---
 drivers/net/wireless/ath/wil6210/cfg80211.c   |  12 +-
 drivers/net/wireless/ath/wil6210/debugfs.c| 111 
 drivers/net/wireless/ath/wil6210/main.c   |  34 +--
 drivers/net/wireless/ath/wil6210/netdev.c |   8 +-
 drivers/net/wireless/ath/wil6210/rx_reorder.c |   2 +-
 drivers/net/wireless/ath/wil6210/txrx.c   | 356 --
 drivers/net/wireless/ath/wil6210/txrx.h   |  68 -
 drivers/net/wireless/ath/wil6210/txrx_edma.h  | 290 +
 drivers/net/wireless/ath/wil6210/wil6210.h| 110 ++--
 drivers/net/wireless/ath/wil6210/wmi.c|  24 +-
 10 files changed, 696 insertions(+), 319 deletions(-)
 create mode 100644 drivers/net/wireless/ath/wil6210/txrx_edma.h

diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c 
b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 78946f2..dfe64b0 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1726,7 +1726,7 @@ static int wil_cfg80211_change_station(struct wiphy 
*wiphy,
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
int authorize;
int cid, i;
-   struct vring_tx_data *txdata = NULL;
+   struct wil_ring_tx_data *txdata = NULL;
 
wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x mid %d\n",
 mac, params->sta_flags_mask, params->sta_flags_set,
@@ -1746,20 +1746,20 @@ static int wil_cfg80211_change_station(struct wiphy 
*wiphy,
return -ENOLINK;
}
 
-   for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++)
-   if (wil->vring2cid_tid[i][0] == cid) {
-   txdata = >vring_tx_data[i];
+   for (i = 0; i < ARRAY_SIZE(wil->ring2cid_tid); i++)
+   if (wil->ring2cid_tid[i][0] == cid) {
+   txdata = >ring_tx_data[i];
break;
}
 
if (!txdata) {
-   wil_err(wil, "vring data not found\n");
+   wil_err(wil, "ring data not found\n");
return -ENOLINK;
}
 
authorize = params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED);
txdata->dot1x_open = authorize ? 1 : 0;
-   wil_dbg_misc(wil, "cid %d vring %d authorize %d\n", cid, i,
+   wil_dbg_misc(wil, "cid %d ring %d authorize %d\n", cid, i,
 txdata->dot1x_open);
 
return 0;
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c 
b/drivers/net/wireless/ath/wil6210/debugfs.c
index ebfdff4..55e03e9b 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -29,7 +29,7 @@
 /* Nasty hack. Better have per device instances */
 static u32 mem_addr;
 static u32 dbg_txdesc_index;
-static u32 dbg_vring_index; /* 24+ for Rx, 0..23 for Tx */
+static u32 dbg_ring_index; /* 24+ for Rx, 0..23 for Tx */
 
 enum dbg_off_type {
doff_u32 = 0,
@@ -47,20 +47,20 @@ struct dbg_off {
enum dbg_off_type type;
 };
 
-static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
-   const char *name, struct vring *vring,
-   char _s, char _h)
+static void wil_print_ring(struct seq_file *s, struct wil6210_priv *wil,
+  const char *name, struct wil_ring *ring,
+  char _s, char _h)
 {
-   void __iomem *x = wmi_addr(wil, vring->hwtail);
+   void __iomem *x = wmi_addr(wil, ring->hwtail);
u32 v;
 
-   seq_printf(s, "VRING %s = {\n", name);
-   seq_printf(s, "  pa = %pad\n", >pa);
-   seq_printf(s, "  va = 0x%p\n", vring->va);
-   seq_printf(s, "  size   = %d\n", vring->size);
-   seq_printf(s, "  swtail = %d\n", vring->swtail);
-   seq_printf(s, "  swhead = %d\n", vring->swhead);
-   seq_printf(s, "  hwtail = [0x%08x] -> ", vring->hwtail);
+   seq_printf(s, "RING %s = {\n", name);
+   seq_printf(s, "  pa = %pad\n", >pa);
+   seq_printf(s, "  va = 0x%p\n", ring->va);
+   seq_printf(s, "  size   = %d\n", ring->size);
+   seq_printf(s, "  swtail 

Good Day; And How Is Your Family.

2018-06-19 Thread SALINAS ROMANS
Good Day;

Dear Respectful One,

I am SALINAS ROMANS  from France. Please go through below my mail and
see if you can Assist for Our mutual benefit, My late Father was a
serving director of the Cocoa exporting board in lvory coast until his
death.

He died in motor accident one week after his trip from Ivory Coast to
negotiate on a cocoa business he wanted to invest in, because of the
sudden death of my father my mother developed heart attack that leads
her to undesirable death last year, Before the death of my late father
he had an account with a well known bank here in lvory coast up to the
sum of ( Eight million Five hundreed Thousand U.S Dollars($8.5m) which
he wanted to invest it into Hotel and Real Estate investment as my
late Mother told me.

so i solicit for your assistance as my late father foreign beneficiary
to enable the bank release the fund to you, If we happen to do this
together, before any thing is done with the total fund, I will give
you (1.5 Million Dollars) out of the total fund as compensation for
your assistance, i look forward to hear from you for more details if
you are willing and Able to handle this transaction also the project.

Thanks and God bless you,
Best regards,
SALINAS ROMANS


Re: Research + questions on brcmfmac and support for monitor mode

2018-06-19 Thread Arend van Spriel

On 6/19/2018 10:32 AM, Rafał Miłecki wrote:

On 19.06.2018 09:53, Arend van Spriel wrote:

On 6/19/2018 9:27 AM, Rafał Miłecki wrote:

On Mon, 11 Jun 2018 at 12:48, Arend van Spriel
 wrote:

On 5/30/2018 1:52 PM, Rafał Miłecki wrote:

I'm providing extra version info of tested firmware images as
requested
by Arend in another e-mail thread.


Looking into our firmware repo it there are two flags, ie. WL_MONITOR
and WL_RADIOTAP. It seems both are set for firmware containing -stamon-
feature. Your list below confirms that. I still plan to add indication
for WL_RADIOTAP in the "cap" iovar, but a stamon feature check could be
used for older firmwares.


I just checked wl.mk (it's an open source file) and found following
line:
WLFILES_SRC_HI += src/wl/sys/wlc_stamon.c
not guarded by any ifeq.


wl.mk is used for NIC driver (softmac) so it is not used for fullmac
firmware.


Weird. I see a few rte references in wl.mk which suggests it's used for
both (softmac & fullmac firmware).


yeah. my mistake.


It appears wlc_stamon.c is always being compiled in. Are you 100% sure
that wlc_stamon.c depends & uses radiotap? Are you sure it's
impossible to include stamon support without radiotap support?

I'm asking because we're going to check "sta_monitor" iovar to find
out if radiotap support is included. I'd like to be sure it's 100%
reliable.


I have already created a patch for this (see below). I will submit it
this week.


Just to be clear could you also answer my above question, please?

Did you check if it's impossible to build firmware *with* stamon.c (and
sta_monitor iovar) and *without WL_RADIOTAP?


Yes. The functions in stamon.c, most importantly wlc_stamon_attach, are 
only invoked in firmware when WL_STA_MONITOR is defined.



diff --git
a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
index f70fec6..67d7fc7 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -207,6 +207,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
  struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
  struct brcmf_pno_macaddr_le pfn_mac;
  struct brcmf_gscan_config gscan_cfg;
+struct brcmf_stamon_sta_config stamon_cfg;
  u32 wowl_cap;
  s32 err;

@@ -217,6 +218,20 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
  brcmf_feat_iovar_data_set(ifp, BRCMF_FEAT_GSCAN,
"pfn_gscan_cfg",
_cfg, sizeof(gscan_cfg));
+
+if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR) ||
+!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RADIOTAP)) {
+ifp->fwil_fwerr = true;
+memset(_cfg, 0, sizeof(stamon_cfg));
+/* iovar requires IOVF_SET_UP so this fails either way */
+err = brcmf_fil_iovar_data_set(ifp, "sta_monitor", _cfg,
+   sizeof(stamon_cfg));


I think it may be simpler (and maybe less invasive) to use
brcmf_fil_iovar_data_get.


Thanks for the comment, but looking at the firmware I can not concur. In 
the get-path there is yet another compile flag that requires different 
query for different firmwares. For the set there is a prerequisite that 
the firmware stack is up and we know it is not upon executing 
brcmf_feat_attach() so it fails before entering the specific iovar 
handler in firmware.


Regards,
Arend


[PATCH 3/8] wlcore: Add support for runtime PM

2018-06-19 Thread Tony Lindgren
We can update wlcore to use PM runtime by adding functions for
wlcore_runtime_suspend() and wlcore_runtime_resume() and replacing
calls to wl1271_ps_elp_wakeup() and wl1271_ps_elp_sleep() with calls
to pm_runtime_get_sync() and pm_runtime_put().

Note that the new wlcore_runtime_suspend() and wlcore_runtime_resume()
functions are based on simplified versions of wl1271_ps_elp_sleep() and
wl1271_ps_elp_wakeup().

We don't want to use the old functions as we can now take advantage of
the runtime PM usage count. And we don't need the old elp_work at all.
And we can also remove WL1271_FLAG_ELP_REQUESTED that is no longer needed.

Pretty much the only place where we are not just converting the existing
functions is wl1271_op_suspend() where we add pm_runtime_put_noidle()
to keep the calls paired.

As the next step is to implement runtime PM autosuspend, let's not add
wrapper functions for the generic runtime PM calls. We would be getting
rid of any wrapper functions anyways.

After autoidle we should be able to start using Linux generic wakeirqs
for the padconf interrupt.

Signed-off-by: Tony Lindgren 
---
 drivers/net/wireless/ti/wl18xx/debugfs.c|  26 +-
 drivers/net/wireless/ti/wlcore/acx.c|   1 -
 drivers/net/wireless/ti/wlcore/cmd.c|  11 +-
 drivers/net/wireless/ti/wlcore/debugfs.c|  79 ++--
 drivers/net/wireless/ti/wlcore/main.c   | 410 ++--
 drivers/net/wireless/ti/wlcore/ps.c | 146 ---
 drivers/net/wireless/ti/wlcore/ps.h |   3 -
 drivers/net/wireless/ti/wlcore/scan.c   |  10 +-
 drivers/net/wireless/ti/wlcore/sysfs.c  |  12 +-
 drivers/net/wireless/ti/wlcore/testmode.c   |  18 +-
 drivers/net/wireless/ti/wlcore/tx.c |   9 +-
 drivers/net/wireless/ti/wlcore/vendor_cmd.c |  27 +-
 drivers/net/wireless/ti/wlcore/wlcore.h |   1 -
 drivers/net/wireless/ti/wlcore/wlcore_i.h   |   1 -
 14 files changed, 416 insertions(+), 338 deletions(-)

diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c 
b/drivers/net/wireless/ti/wl18xx/debugfs.c
--- a/drivers/net/wireless/ti/wl18xx/debugfs.c
+++ b/drivers/net/wireless/ti/wl18xx/debugfs.c
@@ -20,6 +20,8 @@
  *
  */
 
+#include 
+
 #include "../wlcore/debugfs.h"
 #include "../wlcore/wlcore.h"
 #include "../wlcore/debug.h"
@@ -276,15 +278,17 @@ static ssize_t radar_detection_write(struct file *file,
if (unlikely(wl->state != WLCORE_STATE_ON))
goto out;
 
-   ret = wl1271_ps_elp_wakeup(wl);
-   if (ret < 0)
+   ret = pm_runtime_get_sync(wl->dev);
+   if (ret < 0) {
+   pm_runtime_put_noidle(wl->dev);
goto out;
+   }
 
ret = wl18xx_cmd_radar_detection_debug(wl, channel);
if (ret < 0)
count = ret;
 
-   wl1271_ps_elp_sleep(wl);
+   pm_runtime_put(wl->dev);
 out:
mutex_unlock(>mutex);
return count;
@@ -315,15 +319,17 @@ static ssize_t dynamic_fw_traces_write(struct file *file,
if (unlikely(wl->state != WLCORE_STATE_ON))
goto out;
 
-   ret = wl1271_ps_elp_wakeup(wl);
-   if (ret < 0)
+   ret = pm_runtime_get_sync(wl->dev);
+   if (ret < 0) {
+   pm_runtime_put_noidle(wl->dev);
goto out;
+   }
 
ret = wl18xx_acx_dynamic_fw_traces(wl);
if (ret < 0)
count = ret;
 
-   wl1271_ps_elp_sleep(wl);
+   pm_runtime_put(wl->dev);
 out:
mutex_unlock(>mutex);
return count;
@@ -374,9 +380,11 @@ static ssize_t radar_debug_mode_write(struct file *file,
if (unlikely(wl->state != WLCORE_STATE_ON))
goto out;
 
-   ret = wl1271_ps_elp_wakeup(wl);
-   if (ret < 0)
+   ret = pm_runtime_get_sync(wl->dev);
+   if (ret < 0) {
+   pm_runtime_put_noidle(wl->dev);
goto out;
+   }
 
wl12xx_for_each_wlvif_ap(wl, wlvif) {
wlcore_cmd_generic_cfg(wl, wlvif,
@@ -384,7 +392,7 @@ static ssize_t radar_debug_mode_write(struct file *file,
   wl->radar_debug_mode, 0);
}
 
-   wl1271_ps_elp_sleep(wl);
+   pm_runtime_put(wl->dev);
 out:
mutex_unlock(>mutex);
return count;
diff --git a/drivers/net/wireless/ti/wlcore/acx.c 
b/drivers/net/wireless/ti/wlcore/acx.c
--- a/drivers/net/wireless/ti/wlcore/acx.c
+++ b/drivers/net/wireless/ti/wlcore/acx.c
@@ -31,7 +31,6 @@
 #include "wlcore.h"
 #include "debug.h"
 #include "wl12xx_80211.h"
-#include "ps.h"
 #include "hw_ops.h"
 
 int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif,
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c 
b/drivers/net/wireless/ti/wlcore/cmd.c
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -23,6 +23,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -35,7 +36,6 @@
 #include "wl12xx_80211.h"
 #include "cmd.h"
 #include "event.h"
-#include "ps.h"
 #include "tx.h"
 

[PATCH 7/8] wlcore: Make sure firmware is initialized in wl1271_op_add_interface()

2018-06-19 Thread Tony Lindgren
We have wl12xx_boot() call wl12xx_enable_interrupts() and if we have
wl1271_op_add_interface() call pm_runtime_get_sync() before the interrupts
are enabled. And then we get the following error during boot:

wlcore: ERROR ELP wakeup timeout!

Let's fix this by first checking if we need to boot the firmware. And
only after that call pm_runtime_get_sync() when interrupts are enabled.
And only after that do the check for wl12xx_need_fw_change().

Signed-off-by: Tony Lindgren 
---
 drivers/net/wireless/ti/wlcore/main.c | 31 ---
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -2537,11 +2537,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw 
*hw,
wl12xx_get_vif_count(hw, vif, _count);
 
mutex_lock(>mutex);
-   ret = pm_runtime_get_sync(wl->dev);
-   if (ret < 0) {
-   pm_runtime_put_noidle(wl->dev);
-   goto out_unlock;
-   }
 
/*
 * in some very corner case HW recovery scenarios its possible to
@@ -2570,14 +2565,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw 
*hw,
if (ret < 0)
goto out;
 
-   if (wl12xx_need_fw_change(wl, vif_count, true)) {
-   wl12xx_force_active_psm(wl);
-   set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, >flags);
-   mutex_unlock(>mutex);
-   wl1271_recovery_work(>recovery_work);
-   return 0;
-   }
-
/*
 * TODO: after the nvs issue will be solved, move this block
 * to start(), and make sure here the driver is ON.
@@ -2594,6 +2581,24 @@ static int wl1271_op_add_interface(struct ieee80211_hw 
*hw,
goto out;
}
 
+   /*
+* Call runtime PM only after possible wl12xx_init_fw() above
+* is done. Otherwise we do not have interrupts enabled.
+*/
+   ret = pm_runtime_get_sync(wl->dev);
+   if (ret < 0) {
+   pm_runtime_put_noidle(wl->dev);
+   goto out_unlock;
+   }
+
+   if (wl12xx_need_fw_change(wl, vif_count, true)) {
+   wl12xx_force_active_psm(wl);
+   set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, >flags);
+   mutex_unlock(>mutex);
+   wl1271_recovery_work(>recovery_work);
+   return 0;
+   }
+
if (!wlcore_is_p2p_mgmt(wlvif)) {
ret = wl12xx_cmd_role_enable(wl, vif->addr,
 role_type, >role_id);
-- 
2.17.1


[PATCH 8/8] wlcore: Enable runtime PM autosuspend support

2018-06-19 Thread Tony Lindgren
With runtime PM tested working for wlcore with no autosuspend, we can
now enable autosuspend to cut down on enable/disable for interrupts.
Basically we just replace pm_runtime_put() with the autosuspend variants.

Let's use autosuspend delay of 50ms that MMC drivers typically use.

Signed-off-by: Tony Lindgren 
---
 drivers/net/wireless/ti/wl18xx/debugfs.c|   9 +-
 drivers/net/wireless/ti/wlcore/cmd.c|   3 +-
 drivers/net/wireless/ti/wlcore/debugfs.c|  33 --
 drivers/net/wireless/ti/wlcore/main.c   | 111 +---
 drivers/net/wireless/ti/wlcore/scan.c   |   3 +-
 drivers/net/wireless/ti/wlcore/sysfs.c  |   3 +-
 drivers/net/wireless/ti/wlcore/testmode.c   |   6 +-
 drivers/net/wireless/ti/wlcore/tx.c |   3 +-
 drivers/net/wireless/ti/wlcore/vendor_cmd.c |   9 +-
 9 files changed, 121 insertions(+), 59 deletions(-)

diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c 
b/drivers/net/wireless/ti/wl18xx/debugfs.c
--- a/drivers/net/wireless/ti/wl18xx/debugfs.c
+++ b/drivers/net/wireless/ti/wl18xx/debugfs.c
@@ -288,7 +288,8 @@ static ssize_t radar_detection_write(struct file *file,
if (ret < 0)
count = ret;
 
-   pm_runtime_put(wl->dev);
+   pm_runtime_mark_last_busy(wl->dev);
+   pm_runtime_put_autosuspend(wl->dev);
 out:
mutex_unlock(>mutex);
return count;
@@ -329,7 +330,8 @@ static ssize_t dynamic_fw_traces_write(struct file *file,
if (ret < 0)
count = ret;
 
-   pm_runtime_put(wl->dev);
+   pm_runtime_mark_last_busy(wl->dev);
+   pm_runtime_put_autosuspend(wl->dev);
 out:
mutex_unlock(>mutex);
return count;
@@ -392,7 +394,8 @@ static ssize_t radar_debug_mode_write(struct file *file,
   wl->radar_debug_mode, 0);
}
 
-   pm_runtime_put(wl->dev);
+   pm_runtime_mark_last_busy(wl->dev);
+   pm_runtime_put_autosuspend(wl->dev);
 out:
mutex_unlock(>mutex);
return count;
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c 
b/drivers/net/wireless/ti/wlcore/cmd.c
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -230,7 +230,8 @@ int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
} while (!event);
 
 out:
-   pm_runtime_put(wl->dev);
+   pm_runtime_mark_last_busy(wl->dev);
+   pm_runtime_put_autosuspend(wl->dev);
kfree(events_vector);
return ret;
 }
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c 
b/drivers/net/wireless/ti/wlcore/debugfs.c
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -79,7 +79,8 @@ void wl1271_debugfs_update_stats(struct wl1271 *wl)
wl->stats.fw_stats_update = jiffies;
}
 
-   pm_runtime_put(wl->dev);
+   pm_runtime_mark_last_busy(wl->dev);
+   pm_runtime_put_autosuspend(wl->dev);
 
 out:
mutex_unlock(>mutex);
@@ -131,7 +132,8 @@ static void chip_op_handler(struct wl1271 *wl, unsigned 
long value,
chip_op = arg;
chip_op(wl);
 
-   pm_runtime_put(wl->dev);
+   pm_runtime_mark_last_busy(wl->dev);
+   pm_runtime_put_autosuspend(wl->dev);
 }
 
 
@@ -313,7 +315,8 @@ static ssize_t dynamic_ps_timeout_write(struct file *file,
wl1271_ps_set_mode(wl, wlvif, STATION_AUTO_PS_MODE);
}
 
-   pm_runtime_put(wl->dev);
+   pm_runtime_mark_last_busy(wl->dev);
+   pm_runtime_put_autosuspend(wl->dev);
 
 out:
mutex_unlock(>mutex);
@@ -384,7 +387,8 @@ static ssize_t forced_ps_write(struct file *file,
wl1271_ps_set_mode(wl, wlvif, ps_mode);
}
 
-   pm_runtime_put(wl->dev);
+   pm_runtime_mark_last_busy(wl->dev);
+   pm_runtime_put_autosuspend(wl->dev);
 
 out:
mutex_unlock(>mutex);
@@ -858,7 +862,8 @@ static ssize_t rx_streaming_interval_write(struct file 
*file,
wl1271_recalc_rx_streaming(wl, wlvif);
}
 
-   pm_runtime_put(wl->dev);
+   pm_runtime_mark_last_busy(wl->dev);
+   pm_runtime_put_autosuspend(wl->dev);
 out:
mutex_unlock(>mutex);
return count;
@@ -915,7 +920,8 @@ static ssize_t rx_streaming_always_write(struct file *file,
wl1271_recalc_rx_streaming(wl, wlvif);
}
 
-   pm_runtime_put(wl->dev);
+   pm_runtime_mark_last_busy(wl->dev);
+   pm_runtime_put_autosuspend(wl->dev);
 out:
mutex_unlock(>mutex);
return count;
@@ -964,7 +970,8 @@ static ssize_t beacon_filtering_write(struct file *file,
ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value);
}
 
-   pm_runtime_put(wl->dev);
+   pm_runtime_mark_last_busy(wl->dev);
+   pm_runtime_put_autosuspend(wl->dev);
 out:
mutex_unlock(>mutex);
return count;
@@ -1046,7 +1053,8 @@ static ssize_t sleep_auth_write(struct file *file,
goto out_sleep;
 
 out_sleep:
-   

[PATCH 4/8] wlcore: Fix misplaced PM call for scan_complete_work()

2018-06-19 Thread Tony Lindgren
With runtime PM enabled, we now need to have wlcore enabled longer
until after we're done calling wlcore_cmd_regdomain_config_locked():

scan_complete_work()
 wlcore_cmd_regdomain_config_locked()
   wlcore_cmd_send_failsafe()
 wl12xx_sdio_raw_read()

Note that this is not needed before runtime PM support as the
custom PM code had it's own timer. We have not yet enabled runtime
PM autosuspend for wlcore and this is why this issue now shows up.

Let's fix the issues first before we enable runtime PM autosuspend.

Signed-off-by: Tony Lindgren 
---
 drivers/net/wireless/ti/wlcore/scan.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/scan.c 
b/drivers/net/wireless/ti/wlcore/scan.c
--- a/drivers/net/wireless/ti/wlcore/scan.c
+++ b/drivers/net/wireless/ti/wlcore/scan.c
@@ -78,8 +78,6 @@ void wl1271_scan_complete_work(struct work_struct *work)
wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq);
}
 
-   pm_runtime_put(wl->dev);
-
if (wl->scan.failed) {
wl1271_info("Scan completed due to error.");
wl12xx_queue_recovery_work(wl);
@@ -87,6 +85,8 @@ void wl1271_scan_complete_work(struct work_struct *work)
 
wlcore_cmd_regdomain_config_locked(wl);
 
+   pm_runtime_put(wl->dev);
+
ieee80211_scan_completed(wl->hw, );
 
 out:
-- 
2.17.1


[PATCH 6/8] wlcore: Use generic runtime pm calls for wowlan elp configuration

2018-06-19 Thread Tony Lindgren
From: Eyal Reizer 

With runtime PM enabled, we can now use calls to pm_runtime_force_suspend
and pm_runtime_force_resume for enabling elp during suspend when wowlan
is enabled and waking the chip from elp on resume.

Remove the custom API that was used to ensure that the command
that is used to allow ELP during suspend is completed before the system
suspend.

Signed-off-by: Eyal Reizer 
Signed-off-by: Tony Lindgren 
---
 drivers/net/wireless/ti/wlcore/main.c | 51 +++
 1 file changed, 13 insertions(+), 38 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -998,24 +998,6 @@ static int wlcore_fw_wakeup(struct wl1271 *wl)
return wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
 }
 
-static int wlcore_fw_sleep(struct wl1271 *wl)
-{
-   int ret;
-
-   mutex_lock(>mutex);
-   ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP);
-   if (ret < 0) {
-   wl12xx_queue_recovery_work(wl);
-   goto out;
-   }
-   set_bit(WL1271_FLAG_IN_ELP, >flags);
-out:
-   mutex_unlock(>mutex);
-   mdelay(WL1271_SUSPEND_SLEEP);
-
-   return 0;
-}
-
 static int wl1271_setup(struct wl1271 *wl)
 {
wl->raw_fw_status = kzalloc(wl->fw_status_len, GFP_KERNEL);
@@ -1738,6 +1720,7 @@ static int __maybe_unused wl1271_op_suspend(struct 
ieee80211_hw *hw,
 {
struct wl1271 *wl = hw->priv;
struct wl12xx_vif *wlvif;
+   unsigned long flags;
int ret;
 
wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);
@@ -1796,19 +1779,6 @@ static int __maybe_unused wl1271_op_suspend(struct 
ieee80211_hw *hw,
/* flush any remaining work */
wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
 
-   /*
-* disable and re-enable interrupts in order to flush
-* the threaded_irq
-*/
-   wlcore_disable_interrupts(wl);
-
-   /*
-* set suspended flag to avoid triggering a new threaded_irq
-* work. no need for spinlock as interrupts are disabled.
-*/
-   set_bit(WL1271_FLAG_SUSPENDED, >flags);
-
-   wlcore_enable_interrupts(wl);
flush_work(>tx_work);
 
/*
@@ -1818,15 +1788,14 @@ static int __maybe_unused wl1271_op_suspend(struct 
ieee80211_hw *hw,
cancel_delayed_work(>tx_watchdog_work);
 
/*
-* Use an immediate call for allowing the firmware to go into power
-* save during suspend.
-* Using a workque for this last write was only hapenning on resume
-* leaving the firmware with power save disabled during suspend,
-* while consuming full power during wowlan suspend.
+* set suspended flag to avoid triggering a new threaded_irq
+* work.
 */
-   wlcore_fw_sleep(wl);
+   spin_lock_irqsave(>wl_lock, flags);
+   set_bit(WL1271_FLAG_SUSPENDED, >flags);
+   spin_unlock_irqrestore(>wl_lock, flags);
 
-   return 0;
+   return pm_runtime_force_suspend(wl->dev);
 }
 
 static int __maybe_unused wl1271_op_resume(struct ieee80211_hw *hw)
@@ -1841,6 +1810,12 @@ static int __maybe_unused wl1271_op_resume(struct 
ieee80211_hw *hw)
 wl->wow_enabled);
WARN_ON(!wl->wow_enabled);
 
+   ret = pm_runtime_force_resume(wl->dev);
+   if (ret < 0) {
+   wl1271_error("ELP wakeup failure!");
+   goto out_sleep;
+   }
+
/*
 * re-enable irq_work enqueuing, and call irq_work directly if
 * there is a pending work.
-- 
2.17.1


[PATCH 1/8] wlcore: Add missing PM call for wlcore_cmd_wait_for_event_or_timeout()

2018-06-19 Thread Tony Lindgren
Otherwise we can get:

WARNING: CPU: 0 PID: 55 at drivers/net/wireless/ti/wlcore/io.h:84

I've only seen this few times with the runtime PM patches enabled
so this one is probably not needed before that. This seems to
work currently based on the current PM implementation timer. Let's
apply this separately though in case others are hitting this issue.

Signed-off-by: Tony Lindgren 
---
 drivers/net/wireless/ti/wlcore/cmd.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/wireless/ti/wlcore/cmd.c 
b/drivers/net/wireless/ti/wlcore/cmd.c
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -35,6 +35,7 @@
 #include "wl12xx_80211.h"
 #include "cmd.h"
 #include "event.h"
+#include "ps.h"
 #include "tx.h"
 #include "hw_ops.h"
 
@@ -191,6 +192,10 @@ int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
 
timeout_time = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
 
+   ret = wl1271_ps_elp_wakeup(wl);
+   if (ret < 0)
+   return ret;
+
do {
if (time_after(jiffies, timeout_time)) {
wl1271_debug(DEBUG_CMD, "timeout waiting for event %d",
@@ -222,6 +227,7 @@ int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
} while (!event);
 
 out:
+   wl1271_ps_elp_sleep(wl);
kfree(events_vector);
return ret;
 }
-- 
2.17.1


[PATCHv4 0/8] Runtime PM support for wlcore

2018-06-19 Thread Tony Lindgren
Hi all,

Here's the fourth version of wlcore runtime PM changes. Please
test one more time.

For testing, please make sure you have also applied patch
"[PATCHv2] wlcore: sdio: Fix flakey SDIO runtime PM handling"
to avoid bogus errors.

Regards,

Tony

Changes since v3:

- Fixed remaining known issues caused by changes to runtime PM

- Enabled autosuspend

Changes since v2:

- Add fix "wclore: Fix timout errors after recovery" that is not needed
  before runtime PM conversion

- Add fix from Eyal for "wlcore: Use generic runtime pm calls for wowlan
  elp configuration" that is also not needed before runtime PM conversion

- Return early from wlcore_runtime_resume() on ELP timeout to avoid
  clearing WL1271_FLAG_IN_ELP bit

- Tag as RFT as we still need to do more testing and add runtime PM
  autosuspend support before merging

- Drop "wlcore: sdio: Warn about runtime PM suspend errors" that should
  no longer be needed

Changes since v1:

- Fix issues reported by Eyal for recovery

- Add few patches for enable/disable issues found when using runtime PM

- Remove unused ps.h includes


Eyal Reizer (1):
  wlcore: Use generic runtime pm calls for wowlan elp configuration

Tony Lindgren (7):
  wlcore: Add missing PM call for wlcore_cmd_wait_for_event_or_timeout()
  wlcore: Make sure PM calls are paired
  wlcore: Add support for runtime PM
  wlcore: Fix misplaced PM call for scan_complete_work()
  wclore: Fix timout errors after recovery
  wlcore: Make sure firmware is initialized in wl1271_op_add_interface()
  wlcore: Enable runtime PM autosuspend support

 drivers/net/wireless/ti/wl18xx/debugfs.c|  29 +-
 drivers/net/wireless/ti/wlcore/acx.c|   1 -
 drivers/net/wireless/ti/wlcore/cmd.c|  10 +
 drivers/net/wireless/ti/wlcore/debugfs.c|  90 ++--
 drivers/net/wireless/ti/wlcore/main.c   | 526 ++--
 drivers/net/wireless/ti/wlcore/ps.c | 146 --
 drivers/net/wireless/ti/wlcore/ps.h |   3 -
 drivers/net/wireless/ti/wlcore/scan.c   |  13 +-
 drivers/net/wireless/ti/wlcore/sysfs.c  |  13 +-
 drivers/net/wireless/ti/wlcore/testmode.c   |  20 +-
 drivers/net/wireless/ti/wlcore/tx.c |  10 +-
 drivers/net/wireless/ti/wlcore/vendor_cmd.c |  30 +-
 drivers/net/wireless/ti/wlcore/wlcore.h |   1 -
 drivers/net/wireless/ti/wlcore/wlcore_i.h   |   1 -
 14 files changed, 512 insertions(+), 381 deletions(-)

-- 
2.17.1


[PATCH 5/8] wclore: Fix timout errors after recovery

2018-06-19 Thread Tony Lindgren
After enabling runtime PM, if we force hardware reset multiple times with:

# echo 1 > /sys/kernel/debug/ieee80211/phy0/wlcore/start_recovery

We will after few tries get the following error:

wlcore: ERROR timeout waiting for the hardware to complete initialization

And then wlcore is unable to reconnect until after the wlcore related modules
are reloaded.

Let's fix this by moving pm_runtime_put() earlier before we restart the 
hardware.
And let's use the sync version to make sure we're done before we restart.

Note that we still will get -EBUSY warning from wl12xx_sdio_set_power() but 
let's
fix that separately once we know exactly why we get the warning.

Reported-by: Eyal Reizer 
Signed-off-by: Tony Lindgren 
---
 drivers/net/wireless/ti/wlcore/main.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -977,6 +977,7 @@ static void wl1271_recovery_work(struct work_struct *work)
}
 
wlcore_op_stop_locked(wl);
+   pm_runtime_put_sync(wl->dev);
 
ieee80211_restart_hw(wl->hw);
 
@@ -986,8 +987,6 @@ static void wl1271_recovery_work(struct work_struct *work)
 */
wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART);
 
-   pm_runtime_put(wl->dev);
-
 out_unlock:
wl->watchdog_recovery = false;
clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, >flags);
-- 
2.17.1


[PATCH 2/8] wlcore: Make sure PM calls are paired

2018-06-19 Thread Tony Lindgren
The call to wl1271_ps_elp_wakeup() in wl12xx_queue_recovery_work() is
unpaired. Let's remove it and add paired calls to wl1271_recovery_work()
instead in preparation for changing things to use runtime PM.

Signed-off-by: Tony Lindgren 
---
 drivers/net/wireless/ti/wlcore/main.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -796,8 +796,6 @@ void wl12xx_queue_recovery_work(struct wl1271 *wl)
 
wl->state = WLCORE_STATE_RESTARTING;
set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, >flags);
-   wl1271_ps_elp_wakeup(wl);
-   wlcore_disable_interrupts_nosync(wl);
ieee80211_queue_work(wl->hw, >recovery_work);
}
 }
@@ -919,12 +917,18 @@ static void wl1271_recovery_work(struct work_struct *work)
container_of(work, struct wl1271, recovery_work);
struct wl12xx_vif *wlvif;
struct ieee80211_vif *vif;
+   int error;
 
mutex_lock(>mutex);
 
if (wl->state == WLCORE_STATE_OFF || wl->plt)
goto out_unlock;
 
+   error = wl1271_ps_elp_wakeup(wl);
+   if (error < 0)
+   wl1271_warning("Enable for recovery failed");
+   wlcore_disable_interrupts_nosync(wl);
+
if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, >flags)) {
if (wl->conf.fwlog.output == WL12XX_FWLOG_OUTPUT_HOST)
wl12xx_read_fwlog_panic(wl);
@@ -967,6 +971,8 @@ static void wl1271_recovery_work(struct work_struct *work)
 */
wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART);
 
+   wl1271_ps_elp_sleep(wl);
+
 out_unlock:
wl->watchdog_recovery = false;
clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, >flags);
-- 
2.17.1


Re: Research + questions on brcmfmac and support for monitor mode

2018-06-19 Thread Rafał Miłecki

On 19.06.2018 09:53, Arend van Spriel wrote:

On 6/19/2018 9:27 AM, Rafał Miłecki wrote:

On Mon, 11 Jun 2018 at 12:48, Arend van Spriel
 wrote:

On 5/30/2018 1:52 PM, Rafał Miłecki wrote:

I'm providing extra version info of tested firmware images as requested
by Arend in another e-mail thread.


Looking into our firmware repo it there are two flags, ie. WL_MONITOR
and WL_RADIOTAP. It seems both are set for firmware containing -stamon-
feature. Your list below confirms that. I still plan to add indication
for WL_RADIOTAP in the "cap" iovar, but a stamon feature check could be
used for older firmwares.


I just checked wl.mk (it's an open source file) and found following line:
WLFILES_SRC_HI += src/wl/sys/wlc_stamon.c
not guarded by any ifeq.


wl.mk is used for NIC driver (softmac) so it is not used for fullmac firmware.


Weird. I see a few rte references in wl.mk which suggests it's used for
both (softmac & fullmac firmware).



It appears wlc_stamon.c is always being compiled in. Are you 100% sure
that wlc_stamon.c depends & uses radiotap? Are you sure it's
impossible to include stamon support without radiotap support?

I'm asking because we're going to check "sta_monitor" iovar to find
out if radiotap support is included. I'd like to be sure it's 100%
reliable.


I have already created a patch for this (see below). I will submit it this week.


Just to be clear could you also answer my above question, please?

Did you check if it's impossible to build firmware *with* stamon.c (and
sta_monitor iovar) and *without WL_RADIOTAP?



diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
index f70fec6..67d7fc7 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -207,6 +207,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
  struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
  struct brcmf_pno_macaddr_le pfn_mac;
  struct brcmf_gscan_config gscan_cfg;
+    struct brcmf_stamon_sta_config stamon_cfg;
  u32 wowl_cap;
  s32 err;

@@ -217,6 +218,20 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
  brcmf_feat_iovar_data_set(ifp, BRCMF_FEAT_GSCAN,
    "pfn_gscan_cfg",
    _cfg, sizeof(gscan_cfg));
+
+    if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR) ||
+    !brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RADIOTAP)) {
+    ifp->fwil_fwerr = true;
+    memset(_cfg, 0, sizeof(stamon_cfg));
+    /* iovar requires IOVF_SET_UP so this fails either way */
+    err = brcmf_fil_iovar_data_set(ifp, "sta_monitor", _cfg,
+   sizeof(stamon_cfg));


I think it may be simpler (and maybe less invasive) to use
brcmf_fil_iovar_data_get.



+    if (err != BRCMF_FW_UNSUPPORTED) {
+    ifp->drvr->feat_flags |= BRCMF_FEAT_MONITOR;
+    ifp->drvr->feat_flags |= BRCMF_FEAT_RADIOTAP;
+    }
+    ifp->fwil_fwerr = false;
+    }


Re: Research + questions on brcmfmac and support for monitor mode

2018-06-19 Thread Arend van Spriel

On 6/19/2018 9:27 AM, Rafał Miłecki wrote:

On Mon, 11 Jun 2018 at 12:48, Arend van Spriel
 wrote:

On 5/30/2018 1:52 PM, Rafał Miłecki wrote:

I'm providing extra version info of tested firmware images as requested
by Arend in another e-mail thread.


Looking into our firmware repo it there are two flags, ie. WL_MONITOR
and WL_RADIOTAP. It seems both are set for firmware containing -stamon-
feature. Your list below confirms that. I still plan to add indication
for WL_RADIOTAP in the "cap" iovar, but a stamon feature check could be
used for older firmwares.


I just checked wl.mk (it's an open source file) and found following line:
WLFILES_SRC_HI += src/wl/sys/wlc_stamon.c
not guarded by any ifeq.


wl.mk is used for NIC driver (softmac) so it is not used for fullmac 
firmware.



It appears wlc_stamon.c is always being compiled in. Are you 100% sure
that wlc_stamon.c depends & uses radiotap? Are you sure it's
impossible to include stamon support without radiotap support?

I'm asking because we're going to check "sta_monitor" iovar to find
out if radiotap support is included. I'd like to be sure it's 100%
reliable.


I have already created a patch for this (see below). I will submit it 
this week.


Regards,
Arend

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c

index f70fec6..67d7fc7 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -207,6 +207,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
struct brcmf_pno_macaddr_le pfn_mac;
struct brcmf_gscan_config gscan_cfg;
+   struct brcmf_stamon_sta_config stamon_cfg;
u32 wowl_cap;
s32 err;

@@ -217,6 +218,20 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
brcmf_feat_iovar_data_set(ifp, BRCMF_FEAT_GSCAN,
  "pfn_gscan_cfg",
  _cfg, sizeof(gscan_cfg));
+
+   if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR) ||
+   !brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RADIOTAP)) {
+   ifp->fwil_fwerr = true;
+   memset(_cfg, 0, sizeof(stamon_cfg));
+   /* iovar requires IOVF_SET_UP so this fails either way */
+   err = brcmf_fil_iovar_data_set(ifp, "sta_monitor", _cfg,
+  sizeof(stamon_cfg));
+   if (err != BRCMF_FW_UNSUPPORTED) {
+   ifp->drvr->feat_flags |= BRCMF_FEAT_MONITOR;
+   ifp->drvr->feat_flags |= BRCMF_FEAT_RADIOTAP;
+   }
+   ifp->fwil_fwerr = false;
+   }
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
if (drvr->bus_if->wowl_supported)
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
diff --git 
a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h

index 4b29070..e42d296 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -963,4 +963,36 @@ struct brcmf_gscan_config {
struct brcmf_gscan_bucket_config bucket[1];
 };

+enum brcmf_stamon_cfg_cmd {
+STAMON_CFG_CMD_DEL = 0,
+STAMON_CFG_CMD_ADD = 1,
+STAMON_CFG_CMD_ENB = 2,
+STAMON_CFG_CMD_DSB = 3,
+STAMON_CFG_CMD_CNT = 4,
+STAMON_CFG_CMD_RSTCNT = 5,
+STAMON_CFG_CMD_GET_STATS = 6,
+STAMON_CFG_CMD_SET_MONTIME = 7
+};
+
+/**
+ * struct brcmf_stamon_sta_config - configuration data for sta monitor.
+ *
+ * @cmd: subcommand for this configuration (see @enum 
brcmf_stamon_cfg_cmd).

+ * @mac: mac address of sta for which @cmd is intended.
+ * @version: version of this configuration structure.
+ * @length: number of bytes following this field.
+ * @chanspec: not used ?
+ * @mon_time: time for which STA's are monitored (ms).
+ * @offchan_time: timer for which off-channel STA's are monitored.
+ */
+struct brcmf_stamon_sta_config {
+__le32 cmd;
+u8 mac[ETH_ALEN];
+__le16 version;
+__le16 length;
+__le16 chanspec;
+__le32 monitor_time;
+__le32 offchan_time;
+};
+
 #endif /* FWIL_TYPES_H_ */



Re: Research + questions on brcmfmac and support for monitor mode

2018-06-19 Thread Rafał Miłecki
On Mon, 11 Jun 2018 at 12:48, Arend van Spriel
 wrote:
> On 5/30/2018 1:52 PM, Rafał Miłecki wrote:
> > I'm providing extra version info of tested firmware images as requested
> > by Arend in another e-mail thread.
>
> Looking into our firmware repo it there are two flags, ie. WL_MONITOR
> and WL_RADIOTAP. It seems both are set for firmware containing -stamon-
> feature. Your list below confirms that. I still plan to add indication
> for WL_RADIOTAP in the "cap" iovar, but a stamon feature check could be
> used for older firmwares.

I just checked wl.mk (it's an open source file) and found following line:
WLFILES_SRC_HI += src/wl/sys/wlc_stamon.c
not guarded by any ifeq.

It appears wlc_stamon.c is always being compiled in. Are you 100% sure
that wlc_stamon.c depends & uses radiotap? Are you sure it's
impossible to include stamon support without radiotap support?

I'm asking because we're going to check "sta_monitor" iovar to find
out if radiotap support is included. I'd like to be sure it's 100%
reliable.


Re: [PATCH 0/4] cfg80211/mac80211: Add support to configure and monitor txrate threshold

2018-06-19 Thread Tamizh chelvam

On 2018-06-15 17:16, Janusz Dziedzic wrote:
2018-06-14 9:50 GMT+02:00 Arend van Spriel 
:

On 6/13/2018 5:10 PM, Toke Høiland-Jørgensen wrote:


Tamizh Chelvam Raja  writes:


This patchsets introduced new NL command and api to support
configuring txrate threshold for the connected stations and api to
notify userspace application upon crossing the configured txrate
threshold.
This will be useful for the application which requires station's
current capability change information.



What is the intended use case? Asking mostly out of curiosity :)



[Tamizh] This is to monitor txrate change for a station. By 
notifying

userspace when the txrate for a station goes out of configured
threshold, It can take steering decisions on the particular station.



Do we really need kernel notification for that?
You can simple monitor all this information same way iw station dump 
show.


In this case user space application need to fetch the station statistics 
periodically and parse those detail.
Let say AP has more number of stations(like more than 50) in all 
bands(2G and 5G), then the system overhead will be more for fetching the 
detail periodically.
But with this kernel notification we can avoid those overhead and more 
or less this is similar to the CQM(rssi, txe,..) notification in STA 
mode.


Thanks,
Tamizh.


As a metric use tx/rx bitrate, signal or even expected throughput.

Maybe small patch that will average tx/rx bitrate for few seconds
(additional fields in station dump) could be helpful here.

BR
Janusz



Yeah, I got that part. I was curious as to what (userspace) 
application

you were planning to use this for? I.e., what kind of steering
decisions? :)



It sounds like network initiated handover as opposed to station 
roaming.

Suspect the user-space application referred to here is a proprietary
application. At plumbers conf I attended a couple of years ago there 
was an
idea to have a network management application controlling multiple 
hostapd
instances for this type of functionality, but not sure if that project 
ever

got of the ground.

Regards,
Arend



Re: Research + questions on brcmfmac and support for monitor mode

2018-06-19 Thread Rafał Miłecki
On Tue, 19 Jun 2018 at 07:36, Rafał Miłecki  wrote:
> On Mon, 18 Jun 2018 at 23:46, Rafał Miłecki  wrote:
> > On Mon, 18 Jun 2018 at 21:36, Arend van Spriel
> >  wrote:
> > >
> > > On 6/18/2018 1:54 PM, Rafał Miłecki wrote:
> > > > On Mon, 11 Jun 2018 at 12:48, Arend van Spriel
> > > >  wrote:
> > > >> On 5/30/2018 1:52 PM, Rafał Miłecki wrote:
> > > >>> I'm providing extra version info of tested firmware images as 
> > > >>> requested
> > > >>> by Arend in another e-mail thread.
> > > >>
> > > >> Looking into our firmware repo it there are two flags, ie. WL_MONITOR
> > > >> and WL_RADIOTAP. It seems both are set for firmware containing -stamon-
> > > >> feature. Your list below confirms that. I still plan to add indication
> > > >> for WL_RADIOTAP in the "cap" iovar, but a stamon feature check could be
> > > >> used for older firmwares.
> > > >
> > > > The problem is that there isn't a direct mapping between what's
> > > > visible with the "tail" command and what firmware returns for the
> > > > "cap" iovar. Just to be sure I bumped #define MAX_CAPS_BUFFER_SIZE to
> > > > 1024. Firmware that has "stamon" when checked with "tail" command
> > > > doesn't report "stamon" over "cap" iovar. So I can't detect if
> > > > firmware was compiled with WL_MONITOR and WL_RADIOTAP using "cap"
> > > > iovar.
> > >
> > > All true. My suggestion is to look for "monitor" and "rtap" in the "cap"
> > > iovar response to detect if firmware is compiled with WL_MONITOR and
> > > WL_RADIOTAP respectively. When one (or both) of these is not detected,
> > > we could fallback to try a stamon iovar and if it is supported enable
> > > both WL_MONITOR and WL_RADIOTAP. I am looking into a good candidate for
> > > the stamon iovar so I can prepare a patch.
> >
> > Oh, I wasn't aware of the "stamon" iovar (or missed that in your
> > e-mails). If that works, it'll be a very nice fallback way of
> > detecting WL_MONITOR and WL_RADIOTAP!
>
> I just tried "stamon" iovar and it doesn't work. Following call:
> u32 var;
> brcmf_fil_iovar_int_get(ifp, "stamon", );
> returns -52
>
> Can you look at that "stamon" iovar again, please?

I kept looking around and noticed that "wl" user space tool supports
"sta_monitor" command. I tried "sta_monitor" iovar and it worked! I
guess that's the iovar you meant...

-- 
Rafał