Re: AX200 crash on udp upload, cannot restart

2019-10-08 Thread Sergey Matyukevich
> > On Tue, 2019-10-08 at 07:33 +, Sergey Matyukevich wrote:
> > > > We have a system with several of the AX200 NICs in it, kernel is 
> > > > 5.2.14+.  We ran a udp upload
> > > > test of 10Mbps across all radios, and after about 10 minutes one of the 
> > > > radios crashed and could
> > > > not be restarted.  The others continued to run so far.
> > > > 
> > > > I will open a bug in the kernel bug tracker.
> > > 
> > > Hello Ben,
> > > 
> > > We observed similar issues in our tests as well. All the details
> > > have been described in kernel bugzilla issue:
> > > https://urldefense.proofpoint.com/v2/url?u=https-3A__bugzilla.kernel.org_show-5Fbug.cgi-3Fid-3D205061&d=DwIFAg&c=MHZppzMdXMt3JYjCV71UsQ&r=RFH8dgrFzz0_hnNXpEl_u3TZqD-B6kYLzfvbDuCKw3U&m=opeh64GEVevn0071vriL-kH2B_orc25yacBPa3YdgLI&s=CKuyBZ0VdAQocDiZGOIDyDC6GG9w4E7OikmGvzblazU&e=
> > >  
> > 
> > Thanks for the reports!
> > 
> > Ben also added a bug in bugzilla[1], let's use that one for tracking
> > (I'll mark Sergey's as a duplicate).
> > 
> > This is a know issue and our PHY team is already working on it
> > internally.  I don't have much more details at the moment, but I'll
> > update the bugzilla entry as soon as we know more.
> 
> Actually the bug Sergey pointed out is not the same.  It's a different
> sysassert, 0x103C and it will be investigated separately.
 
Hi Luca,

By the way, could you please clarify if current firmware for AX200
supports 160MHz band in 11ax ?

Regards,
Sergey


Re: AX200 crash on udp upload, cannot restart

2019-10-08 Thread Sergey Matyukevich
> We have a system with several of the AX200 NICs in it, kernel is 5.2.14+.  We 
> ran a udp upload
> test of 10Mbps across all radios, and after about 10 minutes one of the 
> radios crashed and could
> not be restarted.  The others continued to run so far.
> 
> I will open a bug in the kernel bug tracker.

Hello Ben,

We observed similar issues in our tests as well. All the details
have been described in kernel bugzilla issue:
https://urldefense.proofpoint.com/v2/url?u=https-3A__bugzilla.kernel.org_show-5Fbug.cgi-3Fid-3D205061&d=DwIFAg&c=MHZppzMdXMt3JYjCV71UsQ&r=RFH8dgrFzz0_hnNXpEl_u3TZqD-B6kYLzfvbDuCKw3U&m=opeh64GEVevn0071vriL-kH2B_orc25yacBPa3YdgLI&s=CKuyBZ0VdAQocDiZGOIDyDC6GG9w4E7OikmGvzblazU&e=
 

Regards,
Sergey


ax200ngw firmware crash: where to report

2019-10-01 Thread Sergey Matyukevich
Hello Johannes,

We are using AX1650x (200NGW) wireless card as a client for 11ax
testing. Firmware version is 48.4fa0041f.0. Simple iperf UDP UL
test on 100 Mbps works fine, but on 120 Mbps firmware crashes.

I would like to support bug report for this behavior. Looking
to wireless wiki, bug reports should be submitted to Linux
kernel bugzilla, adding linuxw...@intel.com to recipients.
Is this procedure still up-to-date ?

Regards,
Sergey



Re: ax200ngw firmware crash: where to report

2019-10-01 Thread Sergey Matyukevich
> > Hello Johannes,
> > 
> > We are using AX1650x (200NGW) wireless card as a client for 11ax
> > testing. Firmware version is 48.4fa0041f.0. Simple iperf UDP UL
> > test on 100 Mbps works fine, but on 120 Mbps firmware crashes.
> > 
> > I would like to support bug report for this behavior. Looking
> > to wireless wiki, bug reports should be submitted to Linux
> > kernel bugzilla, adding linuxw...@intel.com to recipients.
> > Is this procedure still up-to-date ?
> 
> Hi Sergey,
> 
> Yes, please submit an bug report in bugzilla.  And don't forget to
> attach dmesg logs.
> 
> --
> Cheers,
> Luca.

Hi Luca,

Thanks for your confirmation. We will submit the issue and attach dmesg.

Regards,
Sergey


[PATCH v4 2/2] cfg80211: fix duplicated scan entries after channel switch

2019-07-26 Thread Sergey Matyukevich
When associated BSS completes channel switch procedure, its channel
record needs to be updated. The existing mac80211 solution was
extended to cfg80211 in commit 5dc8cdce1d72 ("mac80211/cfg80211:
update bss channel on channel switch").

However that solution still appears to be incomplete as it may lead
to duplicated scan entries for associated BSS after channel switch.
The root cause of the problem is as follows. Each BSS entry is
included into the following data structures:
- bss list rdev->bss_list
- bss search tree rdev->bss_tree
Updating BSS channel record without rebuilding bss_tree may break
tree search since cmp_bss considers all of the following: channel,
bssid, ssid. When BSS channel is updated, but its location in bss_tree
is not updated, then subsequent search operations may fail to locate
this BSS since they will be traversing bss_tree in wrong direction.
As a result, for scan performed after associated BSS channel switch,
cfg80211_bss_update may add the second entry for the same BSS to both
bss_list and bss_tree, rather then update the existing one.

To summarize, if BSS channel needs to be updated, then bss_tree should
be rebuilt in order to put updated BSS entry into a proper location.

This commit suggests the following straightforward solution:
- if new entry has been already created for BSS after channel switch,
  then use its IEs to update known BSS entry and then remove new
  entry completely
- use rb_erase/rb_insert_bss reinstall updated BSS in bss_tree
- for nontransmit BSS entry, the whole transmit BSS hierarchy
  is updated

Signed-off-by: Sergey Matyukevich 
---
 net/wireless/core.h|  2 ++
 net/wireless/nl80211.c |  2 +-
 net/wireless/scan.c| 79 ++
 3 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/net/wireless/core.h b/net/wireless/core.h
index ee8388fe4a92..77556c58d9ac 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -306,6 +306,8 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
 void cfg80211_bss_expire(struct cfg80211_registered_device *rdev);
 void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
   unsigned long age_secs);
+void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
+struct ieee80211_channel *channel);
 
 /* IBSS */
 int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 10b57aa10227..a8d4b2b6b3ec 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16116,7 +16116,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
 
if (wdev->iftype == NL80211_IFTYPE_STATION &&
!WARN_ON(!wdev->current_bss))
-   wdev->current_bss->pub.channel = chandef->chan;
+   cfg80211_update_assoc_bss_entry(wdev, chandef->chan);
 
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
 NL80211_CMD_CH_SWITCH_NOTIFY, 0);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 9119f5ce3677..5e38f8092917 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -2001,6 +2001,85 @@ void cfg80211_bss_iter(struct wiphy *wiphy,
 }
 EXPORT_SYMBOL(cfg80211_bss_iter);
 
+void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
+struct ieee80211_channel *chan)
+{
+   struct wiphy *wiphy = wdev->wiphy;
+   struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+   struct cfg80211_internal_bss *cbss = wdev->current_bss;
+   struct cfg80211_internal_bss *new = NULL;
+   struct cfg80211_internal_bss *bss;
+   struct cfg80211_bss *nontrans_bss;
+   struct cfg80211_bss *tmp;
+
+   spin_lock_bh(&rdev->bss_lock);
+
+   if (WARN_ON(cbss->pub.channel == chan))
+   goto done;
+
+   /* use transmitting bss */
+   if (cbss->pub.transmitted_bss)
+   cbss = container_of(cbss->pub.transmitted_bss,
+   struct cfg80211_internal_bss,
+   pub);
+
+   cbss->pub.channel = chan;
+
+   list_for_each_entry(bss, &rdev->bss_list, list) {
+   if (!cfg80211_bss_type_match(bss->pub.capability,
+bss->pub.channel->band,
+wdev->conn_bss_type))
+   continue;
+
+   if (bss == cbss)
+   continue;
+
+   if (!cmp_bss(&bss->pub, &cbss->pub, BSS_CMP_REGULAR)) {
+   new = bss;
+   break;
+   }
+   }
+
+   if (new) {
+   /* to save time, update IEs for transmitting bss only */
+   if (cfg80211_update_known_bss(rdev, cbss, new, false)) {
+

[PATCH v4 0/2] cfg80211: fix duplicated scan entries after channel switch

2019-07-26 Thread Sergey Matyukevich
Hi Johannes and all,

This is v4 patch fixing duplicated scan entries after channel switch.

Regards,
Sergey

v1 -> v2
- use IEs of new BSS entry to update known BSS entry
  for this purpose extract BSS update code from cfg80211_bss_update
  into a separate function cfg80211_update_known_bss

v2 -> v3
- minor cleanup according to review comments
- split cfg80211_update_known_bss function into a separate patch
- update channel and location in rb-tree for nontransmit bss entries

v3 -> v4
- rebase on top of the latest mac80211-next tree
- drop RFC tag


Sergey Matyukevich (2):
  cfg80211: refactor cfg80211_bss_update
  cfg80211: fix duplicated scan entries after channel switch

 net/wireless/core.h|   2 +
 net/wireless/nl80211.c |   2 +-
 net/wireless/scan.c| 250 +
 3 files changed, 171 insertions(+), 83 deletions(-)

-- 
2.11.0



[PATCH v4 1/2] cfg80211: refactor cfg80211_bss_update

2019-07-26 Thread Sergey Matyukevich
This patch implements minor refactoring for cfg80211_bss_update function.
Code path for updating known BSS is extracted into dedicated
cfg80211_update_known_bss function.

Signed-off-by: Sergey Matyukevich 
---
 net/wireless/scan.c | 171 +++-
 1 file changed, 89 insertions(+), 82 deletions(-)

diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index a98dabab557a..9119f5ce3677 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1091,6 +1091,93 @@ struct cfg80211_non_tx_bss {
u8 bssid_index;
 };
 
+static bool
+cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
+ struct cfg80211_internal_bss *known,
+ struct cfg80211_internal_bss *new,
+ bool signal_valid)
+{
+   lockdep_assert_held(&rdev->bss_lock);
+
+   /* Update IEs */
+   if (rcu_access_pointer(new->pub.proberesp_ies)) {
+   const struct cfg80211_bss_ies *old;
+
+   old = rcu_access_pointer(known->pub.proberesp_ies);
+
+   rcu_assign_pointer(known->pub.proberesp_ies,
+  new->pub.proberesp_ies);
+   /* Override possible earlier Beacon frame IEs */
+   rcu_assign_pointer(known->pub.ies,
+  new->pub.proberesp_ies);
+   if (old)
+   kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
+   } else if (rcu_access_pointer(new->pub.beacon_ies)) {
+   const struct cfg80211_bss_ies *old;
+   struct cfg80211_internal_bss *bss;
+
+   if (known->pub.hidden_beacon_bss &&
+   !list_empty(&known->hidden_list)) {
+   const struct cfg80211_bss_ies *f;
+
+   /* The known BSS struct is one of the probe
+* response members of a group, but we're
+* receiving a beacon (beacon_ies in the new
+* bss is used). This can only mean that the
+* AP changed its beacon from not having an
+* SSID to showing it, which is confusing so
+* drop this information.
+*/
+
+   f = rcu_access_pointer(new->pub.beacon_ies);
+   kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head);
+   return false;
+   }
+
+   old = rcu_access_pointer(known->pub.beacon_ies);
+
+   rcu_assign_pointer(known->pub.beacon_ies, new->pub.beacon_ies);
+
+   /* Override IEs if they were from a beacon before */
+   if (old == rcu_access_pointer(known->pub.ies))
+   rcu_assign_pointer(known->pub.ies, new->pub.beacon_ies);
+
+   /* Assign beacon IEs to all sub entries */
+   list_for_each_entry(bss, &known->hidden_list, hidden_list) {
+   const struct cfg80211_bss_ies *ies;
+
+   ies = rcu_access_pointer(bss->pub.beacon_ies);
+   WARN_ON(ies != old);
+
+   rcu_assign_pointer(bss->pub.beacon_ies,
+  new->pub.beacon_ies);
+   }
+
+   if (old)
+   kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
+   }
+
+   known->pub.beacon_interval = new->pub.beacon_interval;
+
+   /* don't update the signal if beacon was heard on
+* adjacent channel.
+*/
+   if (signal_valid)
+   known->pub.signal = new->pub.signal;
+   known->pub.capability = new->pub.capability;
+   known->ts = new->ts;
+   known->ts_boottime = new->ts_boottime;
+   known->parent_tsf = new->parent_tsf;
+   known->pub.chains = new->pub.chains;
+   memcpy(known->pub.chain_signal, new->pub.chain_signal,
+  IEEE80211_MAX_CHAINS);
+   ether_addr_copy(known->parent_bssid, new->parent_bssid);
+   known->pub.max_bssid_indicator = new->pub.max_bssid_indicator;
+   known->pub.bssid_index = new->pub.bssid_index;
+
+   return true;
+}
+
 /* Returned bss is reference counted and must be cleaned up appropriately. */
 struct cfg80211_internal_bss *
 cfg80211_bss_update(struct cfg80211_registered_device *rdev,
@@ -1114,88 +1201,8 @@ cfg80211_bss_update(struct cfg80211_registered_device 
*rdev,
found = rb_find_bss(rdev, tmp, BSS_CMP_REGULAR);
 
if (found) {
-   /* Update IEs */
-   if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
-   const struct cfg80211_bss_ies *old;
-
-   old = rcu_access_pointer(found->pub.proberesp_ies);
-
-   

Re: [RFC PATCH v3 2/2] cfg80211: fix duplicated scan entries after channel switch

2019-07-26 Thread Sergey Matyukevich
> Umm, regarding multi-BSSID, I'm clearly just not paying any attention
> ... sorry about that.
> 
> 
> This looks good to me, can you resend as just PATCH?

Sure, I will rebase on top of latest mac80211-next and resend.

Regards,
Sergey


Re: [RFC PATCH v3 0/2] cfg80211: fix duplicated scan entries after channel switch

2019-07-26 Thread Sergey Matyukevich
Hello Johannes,

> > > Right, it will be updated on RX. But then if we chanswitch, we would
> > > probably (mac80211 using a pointer to the non-transmitting BSS) update
> > > only one of the nontransmitting BSSes?
> > > 
> > > Just saying that maybe we need to be careful there - or your wording
> > > might be incorrect. We might end up updating a *nontransmitting* BSS,
> > > and then its transmitting/other non-tx ones only later?
> > 
> > Hmmm... I am not sure we are on the same page here. Could you please
> > clarify your concerns here ?
> 
> I'm trying to say we might have this:
> 
> cfg80211
>  * transmitting BSS 0
>- nontx BSS 1
>- nontx BSS 2
>- nontx BSS 3
> mac80211
>  * ifmgd->associated (and cfg80211's wdev->current_bss?) = nontx BSS 2

Yes, this is the use-case that I tried to address in the last revision
of the patch. Suggested approach is similar to what is done for normal
case:
- to keep this hierarchy updating channels and location in rb-tree
- remove newly added hierarchy of the same transmitting BSS on the new
  channel

Note that here we update/remove not only transmitting BSSs, but their
nontx BSS hierarchies as well.

> 
> 
> Now, things like the channel information etc. will always be identical
> between the 4 BSSes, by definition.
> 
> However, if you chanswitch and mac80211 just lets cfg80211 know about
> the current_bss, then you may end up in a situation where the channel
> information is no longer the same, which is very surprising.
> 
> 
> > The normal (non multi-BSSID) BSS usecase seem to be clear: keep old and
> > remove new (if any), since it is not easy to update ifmgd->associated.
> 
> Right.
> 
> > Now let me take another look at the usecase when STA is connected to
> > a transmitting or non-transmitting BSS of a multi-BSS AP. At the moment
> > suggested code does the following. If STA is connected to the 
> > non-transmitting
> > BSS, then we switch to its transmitting BSS, instead of working with
> > current_bss directly.
> 
> We switch? Where? Maybe I missed that.

If you take a look at the top of new cfg80211_update_assoc_bss_entry
function:

+   /* use transmitting bss */
+   if (cbss->pub.transmitted_bss)
+   cbss = container_of(cbss->pub.transmitted_bss,
+   struct cfg80211_internal_bss,
+   pub);

> > So we look for the new entry (with new channel) of the transmitting BSS.
> > If it exists, then we remove it and _all_ of its non-transmitting BSSs.
> > Finally, we update channel and location in rb-tree of the existing (old)
> > transmitting BSS as well as _all_ of its non-transmitting entries.
> 
> That would indeed address the scenario I was thinking of ...

Ok! Let me know if you have any other concerns or questions.

Actually one of the major concerns is the lack of testing for the 'multi-BSSID'
scenario. I verified the 'normal' scenario using both mac80211 (iwlwifi) and
FullMAC (qtnfmac) cards. But at the moment I don't have any mac80211 card
supporting multi-BSSID.

Regards,
Sergey


Re: [RFC PATCH v3 0/2] cfg80211: fix duplicated scan entries after channel switch

2019-07-12 Thread Sergey Matyukevich
> > > [External Email]: This email arrived from an external source - Please 
> > > exercise caution when opening any attachments or clicking on links.
> 
> Heh, you have a not so fun email system that rewrites mails ...

:(
 
> > > > Suggested approach to handle non-transmitting BSS entries is simplified 
> > > > in the
> > > > following sense. If new entries have been already created after channel 
> > > > switch,
> > > > only transmitting bss will be updated using IEs of new entry for the 
> > > > same
> > > > transmitting bss. Non-transmitting bss entries will be updated as soon 
> > > > as
> > > > new mgmt frames are received. Updating non-transmitting bss entries 
> > > > seems
> > > > too expensive: nested nontrans_list traversing is needed since we can 
> > > > not
> > > > rely on the same order of old and new non-transmitting entries.
> > > 
> > > That sounds like a reasonable trade-off. I do wonder though what happens
> > > if we're connected to a non-transmitting BSS?
> > 
> > Well, here I rely upon the assumption that CSA IEs of non-transmitting BSS
> > are handled correctly by mac80211 or any FullMAC firmware. And if we are
> > connected to non-transmitting BSS rather than transmitting one, the
> > following code in the beginning of new cfg80211_update_assoc_bss_entry
> > function is supposed to care about this use-case:
> 
> Right, it will be updated on RX. But then if we chanswitch, we would
> probably (mac80211 using a pointer to the non-transmitting BSS) update
> only one of the nontransmitting BSSes?
> 
> Just saying that maybe we need to be careful there - or your wording
> might be incorrect. We might end up updating a *nontransmitting* BSS,
> and then its transmitting/other non-tx ones only later?

Hmmm... I am not sure we are on the same page here. Could you please
clarify your concerns here ?

The normal (non multi-BSSID) BSS usecase seem to be clear: keep old and
remove new (if any), since it is not easy to update ifmgd->associated.

Now let me take another look at the usecase when STA is connected to
a transmitting or non-transmitting BSS of a multi-BSS AP. At the moment
suggested code does the following. If STA is connected to the non-transmitting
BSS, then we switch to its transmitting BSS, instead of working with
current_bss directly.

So we look for the new entry (with new channel) of the transmitting BSS.
If it exists, then we remove it and _all_ of its non-transmitting BSSs.
Finally, we update channel and location in rb-tree of the existing (old)
transmitting BSS as well as _all_ of its non-transmitting entries.

Regards,
Sergey


Re: [RFC PATCH v3 0/2] cfg80211: fix duplicated scan entries after channel switch

2019-07-12 Thread Sergey Matyukevich
On Fri, Jul 12, 2019 at 11:11:19AM +0200, Johannes Berg wrote:
> 
> [External Email]: This email arrived from an external source - Please 
> exercise caution when opening any attachments or clicking on links.
> 
> > Suggested approach to handle non-transmitting BSS entries is simplified in 
> > the
> > following sense. If new entries have been already created after channel 
> > switch,
> > only transmitting bss will be updated using IEs of new entry for the same
> > transmitting bss. Non-transmitting bss entries will be updated as soon as
> > new mgmt frames are received. Updating non-transmitting bss entries seems
> > too expensive: nested nontrans_list traversing is needed since we can not
> > rely on the same order of old and new non-transmitting entries.
> 
> That sounds like a reasonable trade-off. I do wonder though what happens
> if we're connected to a non-transmitting BSS?

Well, here I rely upon the assumption that CSA IEs of non-transmitting BSS
are handled correctly by mac80211 or any FullMAC firmware. And if we are
connected to non-transmitting BSS rather than transmitting one, the
following code in the beginning of new cfg80211_update_assoc_bss_entry
function is supposed to care about this use-case:

+   /* use transmitting bss */
+   if (cbss->pub.transmitted_bss)
+   cbss = container_of(cbss->pub.transmitted_bss,
+   struct cfg80211_internal_bss,
+   pub);

In other words, regardless of which BSS we are connected to, the whole
hierarchy of non-transmitting BSS entries will be updated, including
their channels and location in rb-tree.

Regards,
Sergey


Re: [PATCH 1/3] cfg80211: clean up cfg80211_inform_single_bss_frame_data()

2019-07-11 Thread Sergey Matyukevich
> From: Johannes Berg 
> 
> cfg80211_inform_single_bss_frame_data() doesn't need the
> non_tx_data data argument since it's always NULL.
> 
> Signed-off-by: Johannes Berg 
 
For all 3 patches:

Reviewed-by: Sergey Matyukevich 

Regards,
Sergey


[RFC PATCH v3 1/2] cfg80211: refactor cfg80211_bss_update

2019-07-10 Thread Sergey Matyukevich
This patch implements minor refactoring for cfg80211_bss_update function.
Code path for updating known BSS is extracted into dedicated
cfg80211_update_known_bss function.

Signed-off-by: Sergey Matyukevich 
---
 net/wireless/scan.c | 171 +++-
 1 file changed, 89 insertions(+), 82 deletions(-)

diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index d66e6d4b7555..9f21162f05e9 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1091,6 +1091,93 @@ struct cfg80211_non_tx_bss {
u8 bssid_index;
 };
 
+static bool
+cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
+ struct cfg80211_internal_bss *known,
+ struct cfg80211_internal_bss *new,
+ bool signal_valid)
+{
+   lockdep_assert_held(&rdev->bss_lock);
+
+   /* Update IEs */
+   if (rcu_access_pointer(new->pub.proberesp_ies)) {
+   const struct cfg80211_bss_ies *old;
+
+   old = rcu_access_pointer(known->pub.proberesp_ies);
+
+   rcu_assign_pointer(known->pub.proberesp_ies,
+  new->pub.proberesp_ies);
+   /* Override possible earlier Beacon frame IEs */
+   rcu_assign_pointer(known->pub.ies,
+  new->pub.proberesp_ies);
+   if (old)
+   kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
+   } else if (rcu_access_pointer(new->pub.beacon_ies)) {
+   const struct cfg80211_bss_ies *old;
+   struct cfg80211_internal_bss *bss;
+
+   if (known->pub.hidden_beacon_bss &&
+   !list_empty(&known->hidden_list)) {
+   const struct cfg80211_bss_ies *f;
+
+   /* The known BSS struct is one of the probe
+* response members of a group, but we're
+* receiving a beacon (beacon_ies in the new
+* bss is used). This can only mean that the
+* AP changed its beacon from not having an
+* SSID to showing it, which is confusing so
+* drop this information.
+*/
+
+   f = rcu_access_pointer(new->pub.beacon_ies);
+   kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head);
+   return false;
+   }
+
+   old = rcu_access_pointer(known->pub.beacon_ies);
+
+   rcu_assign_pointer(known->pub.beacon_ies, new->pub.beacon_ies);
+
+   /* Override IEs if they were from a beacon before */
+   if (old == rcu_access_pointer(known->pub.ies))
+   rcu_assign_pointer(known->pub.ies, new->pub.beacon_ies);
+
+   /* Assign beacon IEs to all sub entries */
+   list_for_each_entry(bss, &known->hidden_list, hidden_list) {
+   const struct cfg80211_bss_ies *ies;
+
+   ies = rcu_access_pointer(bss->pub.beacon_ies);
+   WARN_ON(ies != old);
+
+   rcu_assign_pointer(bss->pub.beacon_ies,
+  new->pub.beacon_ies);
+   }
+
+   if (old)
+   kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
+   }
+
+   known->pub.beacon_interval = new->pub.beacon_interval;
+
+   /* don't update the signal if beacon was heard on
+* adjacent channel.
+*/
+   if (signal_valid)
+   known->pub.signal = new->pub.signal;
+   known->pub.capability = new->pub.capability;
+   known->ts = new->ts;
+   known->ts_boottime = new->ts_boottime;
+   known->parent_tsf = new->parent_tsf;
+   known->pub.chains = new->pub.chains;
+   memcpy(known->pub.chain_signal, new->pub.chain_signal,
+  IEEE80211_MAX_CHAINS);
+   ether_addr_copy(known->parent_bssid, new->parent_bssid);
+   known->pub.max_bssid_indicator = new->pub.max_bssid_indicator;
+   known->pub.bssid_index = new->pub.bssid_index;
+
+   return true;
+}
+
 /* Returned bss is reference counted and must be cleaned up appropriately. */
 struct cfg80211_internal_bss *
 cfg80211_bss_update(struct cfg80211_registered_device *rdev,
@@ -1114,88 +1201,8 @@ cfg80211_bss_update(struct cfg80211_registered_device 
*rdev,
found = rb_find_bss(rdev, tmp, BSS_CMP_REGULAR);
 
if (found) {
-   /* Update IEs */
-   if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
-   const struct cfg80211_bss_ies *old;
-
-   old = rcu_access_pointer(found->pub.proberesp_ies);
-
-   

[RFC PATCH v3 0/2] cfg80211: fix duplicated scan entries after channel switch

2019-07-10 Thread Sergey Matyukevich
Hi Johannes and all,

This is v3 of RFC patch aimed at fixing duplicated scan entries after channel
switch. The major change is updating non-transmitting bss entries. Since such
a bss cannot change channel without its transmitting bss (and vice versa),
the whole hierarchy of transmitting bss is updated, including channel and
location in rb-tree.

Suggested approach to handle non-transmitting BSS entries is simplified in the
following sense. If new entries have been already created after channel switch,
only transmitting bss will be updated using IEs of new entry for the same
transmitting bss. Non-transmitting bss entries will be updated as soon as
new mgmt frames are received. Updating non-transmitting bss entries seems
too expensive: nested nontrans_list traversing is needed since we can not
rely on the same order of old and new non-transmitting entries.

Basic use-case tested using both iwlwifi and qtnfmac.
However multi-BSSID support has not yet been tested. 

Regards,
Sergey

v1 -> v2
- use IEs of new BSS entry to update known BSS entry
  for this purpose extract BSS update code from cfg80211_bss_update
  into a separate function cfg80211_update_known_bss

v2 -> v3
- minor cleanup according to review comments
- split cfg80211_update_known_bss function into a separate patch
- update channel and location in rb-tree for nontransmit bss entries

Sergey Matyukevich (2):
  cfg80211: refactor cfg80211_bss_update
  cfg80211: fix duplicated scan entries after channel switch

 net/wireless/core.h|   2 +
 net/wireless/nl80211.c |   2 +-
 net/wireless/scan.c| 250 +
 3 files changed, 171 insertions(+), 83 deletions(-)

-- 
2.11.0



[RFC PATCH v3 2/2] cfg80211: fix duplicated scan entries after channel switch

2019-07-10 Thread Sergey Matyukevich
When associated BSS completes channel switch procedure, its channel record
needs to be updated. The existing mac80211 solution was extended to
cfg80211 in commit 5dc8cdce1d72 ("mac80211/cfg80211: update bss
channel on channel switch")

However that solution still appears to be incomplete as it may lead
to duplicated scan entries for associated BSS after channel switch.
The root cause of the problem is as follows. Each BSS entry is
included into the following data structures:
- bss list rdev->bss_list
- bss search tree rdev->bss_tree
Updating BSS channel record without rebuilding bss_tree may break
tree search since cmp_bss considers all of the following: channel,
bssid, ssid. When BSS channel is updated, but its location in bss_tree
is not updated, then subsequent search operations may fail to locate
this BSS since they will be traversing bss_tree in wrong direction.
As a result, for scan performed after associated BSS channel switch,
cfg80211_bss_update may add the second entry for the same BSS to both
bss_list and bss_tree, rather then update the existing one.

To summarize, if BSS channel needs to be updated, then bss_tree should
be rebuilt in order to put updated BSS entry into a proper location.

This commit suggests the following straightforward solution:
- if new entry has been already created for BSS after channel switch,
  then use its IEs to update known BSS entry and then remove new
  entry completely
- use rb_erase/rb_insert_bss reinstall updated BSS in bss_tree
- update channel and location in rb-tree for non-transmitting bss entries

Signed-off-by: Sergey Matyukevich 
---

Cover email is not attached to patchwork, so duplicate it here as well...

Suggested approach to handle non-transmitting BSS entries is simplified in the
following sense. If new entries have been already created after channel switch,
only transmitting bss will be updated using IEs of new entry for the same
transmitting bss. Non-transmitting bss entries will be updated as soon as
new mgmt frames are received. Updating non-transmitting bss entries seems
too expensive: nested nontrans_list traversing is needed since we can not
rely on the same order of old and new non-transmitting entries.

Basic use-case tested using both iwlwifi and qtnfmac. However multi-BSSID
support has not yet been tested. 

v1 -> v2
- use IEs of new BSS entry to update known BSS entry
  for this purpose extract BSS update code from cfg80211_bss_update
  into a separate function cfg80211_update_known_bss

v2 -> v3
- minor cleanup according to review comments
- split cfg80211_update_known_bss function into a separate patch
- update channel and location in rb-tree for nontransmit bss entries


Regards,
Sergey

---
 net/wireless/core.h|  2 ++
 net/wireless/nl80211.c |  2 +-
 net/wireless/scan.c| 79 ++
 3 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/net/wireless/core.h b/net/wireless/core.h
index ee8388fe4a92..77556c58d9ac 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -306,6 +306,8 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
 void cfg80211_bss_expire(struct cfg80211_registered_device *rdev);
 void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
   unsigned long age_secs);
+void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
+struct ieee80211_channel *channel);
 
 /* IBSS */
 int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index fc83dd179c1a..6ebb427883d0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16092,7 +16092,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
 
if (wdev->iftype == NL80211_IFTYPE_STATION &&
!WARN_ON(!wdev->current_bss))
-   wdev->current_bss->pub.channel = chandef->chan;
+   cfg80211_update_assoc_bss_entry(wdev, chandef->chan);
 
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
 NL80211_CMD_CH_SWITCH_NOTIFY, 0);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 9f21162f05e9..30932b955ebc 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -2002,6 +2002,85 @@ void cfg80211_bss_iter(struct wiphy *wiphy,
 }
 EXPORT_SYMBOL(cfg80211_bss_iter);
 
+void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
+struct ieee80211_channel *chan)
+{
+   struct wiphy *wiphy = wdev->wiphy;
+   struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+   struct cfg80211_internal_bss *cbss = wdev->current_bss;
+   struct cfg80211_internal_bss *new = NULL;
+   struct cfg80211_internal_bss *bss;
+   struct cfg80211_bss *nontrans_bss;
+   struct cfg80211_bss *tmp;
+
+   spin_lock_bh(&rdev->bss_lock);
+
+   if (

[RFC PATCH v2] cfg80211: fix duplicated scan entries after channel switch

2019-07-03 Thread Sergey Matyukevich
When associated BSS completes channel switch procedure, its channel
record needs to be updated. The existing mac80211 solution was
extended to cfg80211 in commit 5dc8cdce1d72 ("mac80211/cfg80211:
update bss channel on channel switch")

However that solution still appears to be incomplete as it may lead
to duplicated scan entries for associated BSS after channel switch.
The root cause of the problem is as follows. Each BSS entry is
included into the following data structures:
- bss list rdev->bss_list
- bss search tree rdev->bss_tree
Updating BSS channel record without rebuilding bss_tree may break
tree search since cmp_bss considers all of the following: channel,
bssid, ssid. When BSS channel is updated, but its location in bss_tree
is not updated, then subsequent search operations may fail to locate
this BSS. As a result, for scan performed after associated BSS channel
switch, cfg80211_bss_update may add the second entry for the same BSS
to both bss_list and bss_tree, rather then update the existing one.

To summarize, if BSS channel needs to be updated, then bss_tree should
be rebuilt in order to put updated BSS entry into a proper location.

This commit suggests the following straightforward solution:
- if new entry has been already created for BSS after channel switch,
  then use its IEs to update known BSS entry and then remove new
  entry completely
- use rb_erase/rb_insert_bss reinstall updated BSS in bss_tree

Signed-off-by: Sergey Matyukevich 

---

v1 -> v2
- use IEs of new BSS entry to update known BSS entry
  for this purpose extract BSS update code from cfg80211_bss_update
  into a separate function cfg80211_update_known_bss

Tested on both iwlwifi and qtnfmac.

>From my perspective, primary reason for RFC tag is nontrans_list bss handling.
I am not sure whether nontrans_bss should be removed for new entry or not.
The approach varies between cfg80211 API functions. For instance,
cfg80211_unlink_bss removes them, while cfg80211_bss_expire does not.
I would appreciate any comments in this regard.

Regards,
Sergey

---
 net/wireless/core.h|   2 +
 net/wireless/nl80211.c |   5 +-
 net/wireless/scan.c| 221 +++--
 3 files changed, 144 insertions(+), 84 deletions(-)

diff --git a/net/wireless/core.h b/net/wireless/core.h
index ee8388fe4a92..77556c58d9ac 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -306,6 +306,8 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
 void cfg80211_bss_expire(struct cfg80211_registered_device *rdev);
 void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
   unsigned long age_secs);
+void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
+struct ieee80211_channel *channel);
 
 /* IBSS */
 int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index fc83dd179c1a..9bc4999a8c59 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16091,8 +16091,9 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
wdev->preset_chandef = *chandef;
 
if (wdev->iftype == NL80211_IFTYPE_STATION &&
-   !WARN_ON(!wdev->current_bss))
-   wdev->current_bss->pub.channel = chandef->chan;
+   !WARN_ON(!wdev->current_bss)) {
+   cfg80211_update_assoc_bss_entry(wdev, chandef->chan);
+   }
 
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
 NL80211_CMD_CH_SWITCH_NOTIFY, 0);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index d66e6d4b7555..53c07f69365d 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1091,6 +1091,93 @@ struct cfg80211_non_tx_bss {
u8 bssid_index;
 };
 
+static bool
+cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
+ struct cfg80211_internal_bss *known,
+ struct cfg80211_internal_bss *new,
+ bool signal_valid)
+{
+   lockdep_assert_held(&rdev->bss_lock);
+
+   /* Update IEs */
+   if (rcu_access_pointer(new->pub.proberesp_ies)) {
+   const struct cfg80211_bss_ies *old;
+
+   old = rcu_access_pointer(known->pub.proberesp_ies);
+
+   rcu_assign_pointer(known->pub.proberesp_ies,
+  new->pub.proberesp_ies);
+   /* Override possible earlier Beacon frame IEs */
+   rcu_assign_pointer(known->pub.ies,
+  new->pub.proberesp_ies);
+   if (old)
+   kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
+   } else if (rcu_access_pointer(new->pub.beacon_ies)) {
+   const struct cfg80211_bss_ies *old;
+   struct cfg80211_internal_bss *bss;
+
+   if (k

Re: [RFC PATCH] cfg80211: fix duplicated scan entries after channel switch

2019-07-02 Thread Sergey Matyukevich
...

> > To summarize, if BSS channel needs to be updated, then bss_tree should
> > be rebuilt in order to put updated BSS entry into a proper location.
> 
> Good catch!
> 
> > This commit suggests the following straightforward solution:
> > - if new entry has been already created for BSS after channel switch,
> >   then remove it completely
> 
> Shouldn't we prefer the new entry?
> 
> OTOH, the old entry will likely have a "hold", so it doesn't get removed
> while we're connected ... and the driver etc. might be referencing it.
> So I guess the old entry should be updated with info from the newer one?
> 
> > Finally, next scan operation will find BSS entry in expected location
> > in rb_tree. So all the IEs, including HT/VHT operation IEs,
> > will be properly updated.
> 
> Right. Although if it was there before, then it already has been updated
> in a sense... But I guess it's a corner case to even get there?
> 
> > 1. Tested using iwlwifi and qtnfmac drivers, looks good
> 
> Great.
> 
> > 2. Alternative approach: remove old BSS entry and keep new a one
> > This approach may have certain benefits for mac80211 drivers.
> > For instance, in this case HT/VHT operation IEs are going to be
> > valid from the start, no need to wait for the next scan.
> 
> > However the following procedure for replacing current_bss, protected
> > by wdev->mtx and rdev->bss_lock locks, seems to be insufficient:
> > 
> >   bss_ref_get(rdev, new);
> >   cfg80211_hold_bss(new);
> >   wdev->current_bss = new;
> > 
> >   cfg80211_unhold_bss(old);
> >   bss_ref_put(rdev, old);
> >   __cfg80211_unlink_bss(rdev, old);
> > 
> > When testing this alternative approach using iwlwifi driver,
> > occasional general protection fault crashes have been observed
> > on ieee80211_rx_mgmt_beacon/ieee80211_bss_info_update code paths.
> > So far I haven't yet root caused them.
> 
> At the very least you'd also have to update ifmgd->associated in
> mac80211, and that's basically not really possible? Well, I guess we
> could change the channel switch API to return the new one or something.
> 
> I guess the better thing would be to go update the old entry with the
> new one's data, before killing the new one.
> 
> Not sure it's worth the extra complexity though.

Hello Johannes,

Thanks for review! Summarizing your comments, here are the options
and some of their highlights:

1. replace old entry with the new entry
   - no easy way to update ifmgd->associated w/o rework of mac80211 csa

2. keep old entry, remove new entry
   - this is what suggested RFC patch does
   - works, but update of current_bss entry after csa may be delayed

3. keep old entry, update it using data from new entry, then remove new entry
   - this looks like a better approach

Unless I am missing something, the last option can be implemented on top of
the current RFC patch w/o extra complexity. The required bss entry update is
what cfg80211_bss_update function does when bss in question already exists.
So it should be possible to reuse that code.

I will post RFC patch v2 after more testing for both mac80211 and
fullmac cases.

Regards,
Sergey


[RFC PATCH] cfg80211: fix duplicated scan entries after channel switch

2019-06-13 Thread Sergey Matyukevich
When associated BSS completes channel switch procedure, its channel record
needs to be updated. The existing mac80211 solution was extended to
cfg80211 in commit 5dc8cdce1d72 ("mac80211/cfg80211: update bss
channel on channel switch")

However this solution appears to be incomplete as it may lead to
duplicated scan entries for associated BSS after channel switch.
The root cause of the problem is as follows. Each BSS entry is
included into the following data structures:
- bss list rdev->bss_list
- bss search tree rdev->bss_tree
Updating BSS channel record without rebuilding bss_tree may break
tree search since cmp_bss considers all of the following: channel,
bssid, ssid. When BSS channel is updated, but its location in bss_tree
is not updated, then subsequent search operations may fail to locate
this BSS since they will be traversing bss_tree in wrong direction.
As a result, for scan performed after associated BSS channel switch,
cfg80211_bss_update may add the second entry for the same BSS to both
bss_list and bss_tree, rather then update the existing one.

To summarize, if BSS channel needs to be updated, then bss_tree should
be rebuilt in order to put updated BSS entry into a proper location.

This commit suggests the following straightforward solution:
- if new entry has been already created for BSS after channel switch,
  then remove it completely
- use rb_erase/rb_insert_bss reinstall updated BSS in bss_tree

Finally, next scan operation will find BSS entry in expected location
in rb_tree. So all the IEs, including HT/VHT operation IEs,
will be properly updated.

Signed-off-by: Sergey Matyukevich 

---

Misc notes.

1. Tested using iwlwifi and qtnfmac drivers, looks good

2. Alternative approach: remove old BSS entry and keep new a one
This approach may have certain benefits for mac80211 drivers.
For instance, in this case HT/VHT operation IEs are going to be
valid from the start, no need to wait for the next scan.

However the following procedure for replacing current_bss, protected
by wdev->mtx and rdev->bss_lock locks, seems to be insufficient:

  bss_ref_get(rdev, new);
  cfg80211_hold_bss(new);
  wdev->current_bss = new;

  cfg80211_unhold_bss(old);
  bss_ref_put(rdev, old);
  __cfg80211_unlink_bss(rdev, old);

When testing this alternative approach using iwlwifi driver,
occasional general protection fault crashes have been observed
on ieee80211_rx_mgmt_beacon/ieee80211_bss_info_update code paths.
So far I haven't yet root caused them.

---
 net/wireless/core.h|  2 ++
 net/wireless/nl80211.c |  5 +++--
 net/wireless/scan.c| 45 +
 3 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/net/wireless/core.h b/net/wireless/core.h
index 84d36ca7a7ab..763edce6b34f 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -306,6 +306,8 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
 void cfg80211_bss_expire(struct cfg80211_registered_device *rdev);
 void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
   unsigned long age_secs);
+void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
+struct ieee80211_channel *channel);
 
 /* IBSS */
 int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c391b560d986..b3b13131e42e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -15971,8 +15971,9 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
wdev->preset_chandef = *chandef;
 
if (wdev->iftype == NL80211_IFTYPE_STATION &&
-   !WARN_ON(!wdev->current_bss))
-   wdev->current_bss->pub.channel = chandef->chan;
+   !WARN_ON(!wdev->current_bss)) {
+   cfg80211_update_assoc_bss_entry(wdev, chandef->chan);
+   }
 
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
 NL80211_CMD_CH_SWITCH_NOTIFY, 0);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index c04f5451f89b..9a16c42296d0 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1972,6 +1972,51 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct 
cfg80211_bss *pub)
 }
 EXPORT_SYMBOL(cfg80211_unlink_bss);
 
+void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
+struct ieee80211_channel *chan)
+{
+   struct wiphy *wiphy = wdev->wiphy;
+   struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+   struct cfg80211_internal_bss *cbss = wdev->current_bss;
+   struct cfg80211_internal_bss *new = NULL;
+   struct cfg80211_internal_bss *bss;
+
+   spin_lock_bh(&rdev->bss_lock);
+
+   if (WARN_ON(cbss->pub.channel == chan))
+   goto done;
+
+   cbss->pub.channel = chan;
+   cbss->ts = jiffies;
+
+   list_for_each_

Re: NL80211_SCAN_FLAG_RANDOM_ADDR ?

2019-04-12 Thread Sergey Matyukevich
> I've been poking around at how this flag is used and I noticed this
> check in net/wireless/nl80211.c:
> 
> nl80211_check_scan_flags()
> 
> if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
> int err;
> 
> if (!(wiphy->features & randomness_flag) ||
> (wdev && wdev->current_bss))
> return -EOPNOTSUPP;
> 
> 
> The above disallows the use of RANDOM_ADDR for scans while connected.
> The nl80211.h uapi header seems to concur:
> 
>  "@NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR: This device/driver supports
> using a random MAC address during scan (if the device is unassociated);"
> 
> However, if I create a P2P Device (in addition to the default STA
> device), the kernel happily lets me scan on the wdev while the STA
> interface is connected.
> 
> sudo iw phy0 interface add p2p type __p2pdev
> sudo iw wdev 0x2 p2p start
> sudo iw wdev 0x2 scan randomize
> 
> So the immediate question I have is, should the RANDOM_ADDR flag indeed
> be limited to unassociated STA interfaces?  It would seem the hardware
> is capable randomizing even when connected? Please educate me :)

Hello Denis,

IIUC, this feature could be introduced to support Android Compatibility
Definition Document (CDD). Those documents are available at the
following page: https://source.android.com/compatibility/cdd

For instance, in the latest CDD randomized scan requirements are described
in the section 7.4.2. It looks like current high level nl80211 API follows
those recommendations. Probably it has been implemented with STA use-case
in mind, that is why you can use that flag for P2P connection. But, as
Ben pointed out, actual application of this flag may depend on
implementation in firwmare and hardware.

Regards,
Sergey


Re: question: crda timeout in cfg80211

2019-04-11 Thread Sergey Matyukevich
> > Indeed, it is PI. I should have known. But instead I spent some time
> > digging through 802.11 specs :)
> 
> Oops :)
> 
> > Well, as I mentioned in my question, regulatory update/reset operations
> > shall be completed in ~pi seconds for _all_ the wireless cards in the
> > system. In our case, regulatory reset operation may be fairly costly.
> > As a result, we end up with recurring reset timeout, when more than one
> > qtn card is installed in a single pcie host. One option for us is to
> > optimize regulatory reset operations in firmware.
> >
> > But what do you think about converting crda_timeout into a per-wiphy
> > timeout in the case when all wiphy-s are being processed, e.g.
> > in update_all_wiphy_regulatory.
> 
> Maybe we should parallelize it? But I don't know how easy that would be.
> 
> I'm a little worried just making it longer will cause users to really be
> wondering what's going on?

Hello Johannes,

Calling regulatory notifiers in parallel sounds like a good idea.
But I haven't yet looked into the details as well. Before fixing
the timeout issue, I was trying to figure out why that regulatory
reset was needed at all.

Here is a simple usecase: Linux distro sets regulatory region to US,
STA is connected to AP. Any STA disconnect (including an attempt to
reconnect to another AP) leads to regulatory reset cycle: US -> 00 -> US.
This reset cycle is not supposed to be done for the wireless cards that
specify REGULATORY_COUNTRY_IE_IGNORE flag. However regulatory reset will
be applied anyway if at least one card in the system does not specify
that flag.

Hence two questions:
Do we really need this kind of reset when we remain
in the same regulatory domain ? 

Does it make sense to track when restore_regulatory_settings performs
reset, and to skip reset for the cards that specify
REGULATORY_COUNTRY_IE_IGNORE ?

Regards,
Sergey


Re: [PATCH v2] mac80211: fix RX STBC override byte order

2019-04-09 Thread Sergey Matyukevich
> The original patch neglected to take byte order conversions
> into account, fix that.
> 
> Fixes: d9bb410888ce ("mac80211: allow overriding HT STBC capabilities")
> Signed-off-by: Johannes Berg 
> ---
>  net/mac80211/ht.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
> index e03c46ac8e4d..c62101857b9b 100644
> --- a/net/mac80211/ht.c
> +++ b/net/mac80211/ht.c
> @@ -112,8 +112,9 @@ void ieee80211_apply_htcap_overrides(struct 
> ieee80211_sub_if_data *sdata,
>  IEEE80211_HT_CAP_TX_STBC);
> 
> /* Allow user to configure RX STBC bits */
> -   if (ht_capa_mask->cap_info & IEEE80211_HT_CAP_RX_STBC)
> -   ht_cap->cap |= ht_capa->cap_info & IEEE80211_HT_CAP_RX_STBC;
> +   if (ht_capa_mask->cap_info & cpu_to_le16(IEEE80211_HT_CAP_RX_STBC))
> +   ht_cap->cap |= le16_to_cpu(ht_capa->cap_info) &
> +   IEEE80211_HT_CAP_RX_STBC;
> 
> /* Allow user to decrease AMPDU factor */
> if (ht_capa_mask->ampdu_params_info &

Thanks for fixing this!

Reviewed-by: Sergey Matyukevich 

Regards,
Sergey


Re: question: crda timeout in cfg80211

2019-04-09 Thread Sergey Matyukevich
> > Linux cfg80211 regulatory subsystem uses CRDA timeout to ensure completion
> > of regulatory updates, performed by user-space software. See call_crda
> > functon in net/wireless/reg.c:
> >
> > static int call_crda(const char *alpha2)
> > {
> >   ...
> >
> >   queue_delayed_work(system_power_efficient_wq,
> >   &crda_timeout, msecs_to_jiffies(3142));
> >   return 0;
> > }
> >
> > So regulatory update/reset operations shall be completed in 3142 msec.
> > And that includes processing of regulatory notifiers for all the
> > wireless cards in the system.
> >
> > It is not quite clear where this specific timeout value came from.
> > Original commit (a90c7a313a1c5b) doesn't go into details about it.
> >
> > Any ideas where it could come from ?
> 
> No particular reason. It's just ~pi seconds, and IIRC Luis thought that
> was funny :-)

Indeed, it is PI. I should have known. But instead I spent some time
digging through 802.11 specs :)

> Are you seeing any issues with that?
 
Well, as I mentioned in my question, regulatory update/reset operations
shall be completed in ~pi seconds for _all_ the wireless cards in the
system. In our case, regulatory reset operation may be fairly costly.
As a result, we end up with recurring reset timeout, when more than one
qtn card is installed in a single pcie host. One option for us is to
optimize regulatory reset operations in firmware.

But what do you think about converting crda_timeout into a per-wiphy
timeout in the case when all wiphy-s are being processed, e.g.
in update_all_wiphy_regulatory.

Regards,
Sergey


[PATCH 3/3] qtnfmac: modify debugfs to support multiple cards

2019-04-09 Thread Sergey Matyukevich
This patch modifies location of debugfs entries and their naming
conventions to support multiple wireless cards on pcie host.
Selected approach is to use separate directories for different
wireless cards in top-level qtnfmac debugfs directory.

Here is an example that clarifies the chosen naming conventions:

 $ sudo ls /sys/kernel/debug/qtnfmac/
   qtnfmac_pcie::01:00.0

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/core.c  | 26 ++
 drivers/net/wireless/quantenna/qtnfmac/core.h  |  1 +
 drivers/net/wireless/quantenna/qtnfmac/debug.c |  4 +++-
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
b/drivers/net/wireless/quantenna/qtnfmac/core.c
index ad0c9e012056..8d699cc03d26 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -20,6 +20,8 @@ static bool slave_radar = true;
 module_param(slave_radar, bool, 0644);
 MODULE_PARM_DESC(slave_radar, "set 0 to disable radar detection in slave 
mode");
 
+static struct dentry *qtnf_debugfs_dir;
+
 struct qtnf_frame_meta_info {
u8 magic_s;
u8 ifidx;
@@ -848,6 +850,30 @@ void qtnf_packet_send_hi_pri(struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(qtnf_packet_send_hi_pri);
 
+struct dentry *qtnf_get_debugfs_dir(void)
+{
+   return qtnf_debugfs_dir;
+}
+EXPORT_SYMBOL_GPL(qtnf_get_debugfs_dir);
+
+static int __init qtnf_core_register(void)
+{
+   qtnf_debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+
+   if (IS_ERR(qtnf_debugfs_dir))
+   qtnf_debugfs_dir = NULL;
+
+   return 0;
+}
+
+static void __exit qtnf_core_exit(void)
+{
+   debugfs_remove(qtnf_debugfs_dir);
+}
+
+module_init(qtnf_core_register);
+module_exit(qtnf_core_exit);
+
 MODULE_AUTHOR("Quantenna Communications");
 MODULE_DESCRIPTION("Quantenna 802.11 wireless LAN FullMAC driver.");
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h 
b/drivers/net/wireless/quantenna/qtnfmac/core.h
index d5caff45ac47..322858df600c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -153,6 +153,7 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev);
 void qtnf_netdev_updown(struct net_device *ndev, bool up);
 void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted);
 void qtnf_packet_send_hi_pri(struct sk_buff *skb);
+struct dentry *qtnf_get_debugfs_dir(void);
 
 static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev)
 {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/debug.c 
b/drivers/net/wireless/quantenna/qtnfmac/debug.c
index 598ece753a4b..2d3574c1f10e 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/debug.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/debug.c
@@ -5,7 +5,9 @@
 
 void qtnf_debugfs_init(struct qtnf_bus *bus, const char *name)
 {
-   bus->dbg_dir = debugfs_create_dir(name, NULL);
+   struct dentry *parent = qtnf_get_debugfs_dir();
+
+   bus->dbg_dir = debugfs_create_dir(name, parent);
 }
 
 void qtnf_debugfs_remove(struct qtnf_bus *bus)
-- 
2.11.0



[PATCH 0/3] qtnfmac: debugfs update and other misc fixes

2019-04-09 Thread Sergey Matyukevich
Hello Kalle and all,

Here is the patch set with minor fixes and enhancements for qtnfmac driver,
that were not included into the previous larger series.

The major changes include the following items:
- updating debugfs structure to support multiple cards on a single host
- add kernel module param to control DFS slave radar detection behavior

Regards,
Sergey


Igor Mitsyanko (1):
  qtnfmac: allow to control DFS slave radar detection

Sergey Matyukevich (2):
  qtnfmac: handle channel switch events for connected stations only
  qtnfmac: modify debugfs to support multiple cards

 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |  2 +-
 drivers/net/wireless/quantenna/qtnfmac/commands.c |  4 ++-
 drivers/net/wireless/quantenna/qtnfmac/commands.h |  3 +-
 drivers/net/wireless/quantenna/qtnfmac/core.c | 35 +++
 drivers/net/wireless/quantenna/qtnfmac/core.h |  2 ++
 drivers/net/wireless/quantenna/qtnfmac/debug.c|  4 ++-
 drivers/net/wireless/quantenna/qtnfmac/event.c| 16 +++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|  4 ++-
 8 files changed, 60 insertions(+), 10 deletions(-)

-- 
2.11.0



[PATCH 2/3] qtnfmac: allow to control DFS slave radar detection

2019-04-09 Thread Sergey Matyukevich
From: Igor Mitsyanko 

In ETSI region DFS slave device can operate in two modes on DFS channels:
 - do on-channel radar detection and use higher Tx power
 - don't do radar detection and use lower Tx power as a consequence

Allow user to control that behavior through qtnfmac module parameter.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 2 +-
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 4 +++-
 drivers/net/wireless/quantenna/qtnfmac/commands.h | 3 ++-
 drivers/net/wireless/quantenna/qtnfmac/core.c | 9 +
 drivers/net/wireless/quantenna/qtnfmac/core.h | 1 +
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 4 +++-
 6 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index c78500bcaa2d..d90016125dfc 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1008,7 +1008,7 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy 
*wiphy,
pr_debug("MAC%u: initiator=%d alpha=%c%c\n", mac->macid, req->initiator,
 req->alpha2[0], req->alpha2[1]);
 
-   ret = qtnf_cmd_reg_notify(mac, req);
+   ret = qtnf_cmd_reg_notify(mac, req, qtnf_mac_slave_radar_get(wiphy));
if (ret) {
pr_err("MAC%u: failed to update region to %c%c: %d\n",
   mac->macid, req->alpha2[0], req->alpha2[1], ret);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 22313a46c3ae..459f6b81d2eb 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2367,7 +2367,8 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool 
up)
return ret;
 }
 
-int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req)
+int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req,
+   bool slave_radar)
 {
struct wiphy *wiphy = priv_to_wiphy(mac);
struct qtnf_bus *bus = mac->bus;
@@ -2429,6 +2430,7 @@ int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct 
regulatory_request *req)
break;
}
 
+   cmd->slave_radar = slave_radar;
cmd->num_channels = 0;
 
for (band = 0; band < NUM_NL80211_BANDS; band++) {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h 
b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index 6406365287fc..88d7a3cd90d2 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -57,7 +57,8 @@ int qtnf_cmd_send_disconnect(struct qtnf_vif *vif,
 u16 reason_code);
 int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif,
  bool up);
-int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req);
+int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req,
+   bool slave_radar);
 int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
struct qtnf_chan_stats *stats);
 int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
b/drivers/net/wireless/quantenna/qtnfmac/core.c
index 54ea86ae4959..ad0c9e012056 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -16,6 +16,10 @@
 #define QTNF_DMP_MAX_LEN 48
 #define QTNF_PRIMARY_VIF_IDX   0
 
+static bool slave_radar = true;
+module_param(slave_radar, bool, 0644);
+MODULE_PARM_DESC(slave_radar, "set 0 to disable radar detection in slave 
mode");
+
 struct qtnf_frame_meta_info {
u8 magic_s;
u8 ifidx;
@@ -426,6 +430,11 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct 
qtnf_bus *bus,
return mac;
 }
 
+bool qtnf_mac_slave_radar_get(struct wiphy *wiphy)
+{
+   return slave_radar;
+}
+
 static const struct ethtool_ops qtnf_ethtool_ops = {
.get_drvinfo = cfg80211_get_drvinfo,
 };
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h 
b/drivers/net/wireless/quantenna/qtnfmac/core.h
index af8372dfb927..d5caff45ac47 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -134,6 +134,7 @@ struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac 
*mac);
 struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac);
 void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac);
 void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac);
+bool qtnf_mac_slave_radar_get(struct wiphy *wiphy);
 struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus);
 int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv,
 const char *name, unsigned char name_assign_type);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/q

[PATCH 1/3] qtnfmac: handle channel switch events for connected stations only

2019-04-09 Thread Sergey Matyukevich
Channel switch events from firmware should be processed only when STA
is already connected to BSS. On connect this notification is not needed
since full BSS info will be supplied by cfg80211_connect_result.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/event.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c 
b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 6c1b886339ac..b57c8c18a8d0 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -493,14 +493,20 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
 
for (i = 0; i < QTNF_MAX_INTF; i++) {
vif = &mac->iflist[i];
+
if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)
continue;
 
-   if (vif->netdev) {
-   mutex_lock(&vif->wdev.mtx);
-   cfg80211_ch_switch_notify(vif->netdev, &chandef);
-   mutex_unlock(&vif->wdev.mtx);
-   }
+   if (vif->wdev.iftype == NL80211_IFTYPE_STATION &&
+   !vif->wdev.current_bss)
+   continue;
+
+   if (!vif->netdev)
+   continue;
+
+   mutex_lock(&vif->wdev.mtx);
+   cfg80211_ch_switch_notify(vif->netdev, &chandef);
+   mutex_unlock(&vif->wdev.mtx);
}
 
return 0;
-- 
2.11.0



question: crda timeout in cfg80211

2019-03-26 Thread Sergey Matyukevich
Hi all,

Linux cfg80211 regulatory subsystem uses CRDA timeout to ensure completion
of regulatory updates, performed by user-space software. See call_crda
functon in net/wireless/reg.c:

static int call_crda(const char *alpha2)
{
...

queue_delayed_work(system_power_efficient_wq,
&crda_timeout, msecs_to_jiffies(3142));
return 0;
}

So regulatory update/reset operations shall be completed in 3142 msec.
And that includes processing of regulatory notifiers for all the
wireless cards in the system.

It is not quite clear where this specific timeout value came from.
Original commit (a90c7a313a1c5b) doesn't go into details about it.

Any ideas where it could come from ?

Regards,
Sergey


[PATCH v2] mac80211/cfg80211: update bss channel on channel switch

2019-03-26 Thread Sergey Matyukevich
FullMAC STAs have no way to update bss channel after CSA channel switch
completion. As a result, user-space tools may provide inconsistent
channel info. For instance, consider the following two commands:
$ sudo iw dev wlan0 link
$ sudo iw dev wlan0 info
The latter command gets channel info from the hardware, so most probably
its output will be correct. However the former command gets channel info
from scan cache, so its output will contain outdated channel info.
In fact, current bss channel info will not be updated until the
next [re-]connect.

Note that mac80211 STAs have a workaround for this, but it requires
access to internal cfg80211 data, see ieee80211_chswitch_work:

/* XXX: shouldn't really modify cfg80211-owned data! */
ifmgd->associated->channel = sdata->csa_chandef.chan;

This patch suggests to convert mac80211 workaround into cfg80211 behavior
and to update current bss channel in cfg80211_ch_switch_notify.

Signed-off-by: Sergey Matyukevich 

---
v1 -> v2:
- as per suggestion by Johannes, use !WARN_ON(!wdev->current_bss)


---
 net/mac80211/mlme.c| 3 ---
 net/wireless/nl80211.c | 5 +
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2dbcf5d5512e..b7a9fe3d5fcb 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1188,9 +1188,6 @@ static void ieee80211_chswitch_work(struct work_struct 
*work)
goto out;
}
 
-   /* XXX: shouldn't really modify cfg80211-owned data! */
-   ifmgd->associated->channel = sdata->csa_chandef.chan;
-
ifmgd->csa_waiting_bcn = true;
 
ieee80211_sta_reset_beacon_monitor(sdata);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 25a9e3b5c154..b108b635e2f3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -15721,6 +15721,11 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
 
wdev->chandef = *chandef;
wdev->preset_chandef = *chandef;
+
+   if (wdev->iftype == NL80211_IFTYPE_STATION &&
+   !WARN_ON(!wdev->current_bss))
+   wdev->current_bss->pub.channel = chandef->chan;
+
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
 NL80211_CMD_CH_SWITCH_NOTIFY, 0);
 }
-- 
2.11.0



Re: [RFC PATCH] mac80211/cfg80211: update bss channel on channel switch

2019-03-25 Thread Sergey Matyukevich
> > FullMAC STAs have no way to update bss channel after CSA channel switch
> > completion. As a result, user-space tools may provide inconsistent
> > channel info. For instance, consider the following two commands:
> > $ sudo iw dev wlan0 link
> > $ sudo iw dev wlan0 info
> > The latter command gets channel info from the hardware, so most probably
> > its output will be correct. However the former command gets channel info
> > from scan cache, so its output will contain outdated channel info.
> > In fact, current bss channel info will not be updated until the
> > next [re-]connect.
> >
> > Note that mac80211 STAs have a workaround for this, but it requires
> > access to internal cfg80211 data, see ieee80211_chswitch_work:
> >
> >   /* XXX: shouldn't really modify cfg80211-owned data! */
> >   ifmgd->associated->channel = sdata->csa_chandef.chan;
> >
> > This patch suggests to convert mac80211 workaround to cfg80211 behavior
> > and to update current bss channel in cfg80211_ch_switch_notify.
> >
> > Signed-off-by: Sergey Matyukevich 
> >
> > ---
> >
> > This issue has been observed for both qtnfmac and brcmfmac. Fix tested
> > for qtnfmac and iwlwifi, to make sure there is no regression for mac80211.
> > However this is not going to be enough to fix brcmfmac behavior as it
> > does not use cfg80211_ch_switch_notify. This issue may also affect
> > ath6kl and mwifiex, but I have no hardware to check.
> 
> Yeah, I think this makes sense.
> 
> > + if (wdev->iftype == NL80211_IFTYPE_STATION) {
> > + if (wdev->current_bss)
> > + wdev->current_bss->pub.channel = chandef->chan;
> > + }
> 
> Maybe do
> 
> if (wdev->iftype == ... &&
> !WARN_ON(!wdev->current_bss))
> wdev->current_bss->... = ...
> 
> I worry slightly about locking too, since there's no protection on the
> wdev->current_bss pointer here.

Ok, I will add WARN_ON. As for locking, this function is supposed to be
called with wdev->mtx held, see ASSERT_WDEV_LOCK. Do you think this may
not be enough ? 

I need to check mwifiex more carefully, but other cfg80211_ch_switch_notify
users (mac80211, ath6kl, qtnfmac) seem to do that locking properly.

Regards,
Sergey


Re: [PATCH 12/14] qtnfmac: fix debugfs entries for multiple cards on the same host

2019-03-21 Thread Sergey Matyukevich
> > > > > Fix creation of debugfs entries for qtnfmac wireless card: use 
> > > > > separate
> > > > > directories for different wireless cards. This commit enables support
> > > > > for multiple qtnfmac wireless cards on the same PCIe host.
> > > > > 
> > > > > Signed-off-by: Sergey Matyukevich 
> > > > > 
> > > > > ---
> > > > >   drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 6 +-
> > > > >   1 file changed, 5 insertions(+), 1 deletion(-)
> > > > > 
> > > > > diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
> > > > > b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
> > > > > index b561b75e4433..56fc6d49c121 100644
> > > > > --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
> > > > > +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
> > > > > @@ -130,6 +130,8 @@ static int qtnf_dbg_shm_stats(struct seq_file *s, 
> > > > > void *data)
> > > > > 
> > > > >   int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus)
> > > > >   {
> > > > > + struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
> > > > > + char card_id[64];
> > > > >int ret;
> > > > > 
> > > > >bus->fw_state = QTNF_FW_STATE_BOOT_DONE;
> > > > > @@ -137,7 +139,9 @@ int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus)
> > > > >if (ret) {
> > > > >pr_err("failed to attach core\n");
> > > > >} else {
> > > > > - qtnf_debugfs_init(bus, DRV_NAME);
> > > > > + snprintf(card_id, sizeof(card_id), "%s:%s",
> > > > > +  DRV_NAME, pci_name(priv->pdev));
> > > > 
> > > > Can you give an example for the path?
> > > > 
> > > 
> > > For instance:  /sys/kernel/debug/qtnfmac_pcie::01:00.0
> > 
> > TBH not really fond of that. What about
> > "/sys/kernel/debug/qtnfmac/pcie::01:00.0"? IIRC iwlwifi used
> > something like that.


Hello Arend,

> In brcmfmac we used to have it like that, but I changed it to use wiphy
> debugfs, ie. /sys/kernel/debug/ieee80211/phyX/.

Yes, I saw the patches for brcmfmac. In fact, looking at those patches
we figured out that we have a problem before we started testing
two cards in one pcie host :)

But /sys/kernel/debug/eee80211/phyX approach does not fit well for our
use-case. We may have up to 3 phy-s for single card, but counters
exported via debugfs are for pcie device as a whole.

Thanks,
Sergey


[RFC PATCH] mac80211/cfg80211: update bss channel on channel switch

2019-03-21 Thread Sergey Matyukevich
FullMAC STAs have no way to update bss channel after CSA channel switch
completion. As a result, user-space tools may provide inconsistent
channel info. For instance, consider the following two commands:
$ sudo iw dev wlan0 link
$ sudo iw dev wlan0 info
The latter command gets channel info from the hardware, so most probably
its output will be correct. However the former command gets channel info
from scan cache, so its output will contain outdated channel info.
In fact, current bss channel info will not be updated until the
next [re-]connect.

Note that mac80211 STAs have a workaround for this, but it requires
access to internal cfg80211 data, see ieee80211_chswitch_work:

/* XXX: shouldn't really modify cfg80211-owned data! */
ifmgd->associated->channel = sdata->csa_chandef.chan;

This patch suggests to convert mac80211 workaround to cfg80211 behavior
and to update current bss channel in cfg80211_ch_switch_notify.

Signed-off-by: Sergey Matyukevich 

---

This issue has been observed for both qtnfmac and brcmfmac. Fix tested
for qtnfmac and iwlwifi, to make sure there is no regression for mac80211.
However this is not going to be enough to fix brcmfmac behavior as it
does not use cfg80211_ch_switch_notify. This issue may also affect
ath6kl and mwifiex, but I have no hardware to check.

---
 net/mac80211/mlme.c| 3 ---
 net/wireless/nl80211.c | 6 ++
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2dbcf5d5512e..b7a9fe3d5fcb 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1188,9 +1188,6 @@ static void ieee80211_chswitch_work(struct work_struct 
*work)
goto out;
}
 
-   /* XXX: shouldn't really modify cfg80211-owned data! */
-   ifmgd->associated->channel = sdata->csa_chandef.chan;
-
ifmgd->csa_waiting_bcn = true;
 
ieee80211_sta_reset_beacon_monitor(sdata);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 25a9e3b5c154..1ca6930ddac0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -15721,6 +15721,12 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
 
wdev->chandef = *chandef;
wdev->preset_chandef = *chandef;
+
+   if (wdev->iftype == NL80211_IFTYPE_STATION) {
+   if (wdev->current_bss)
+   wdev->current_bss->pub.channel = chandef->chan;
+   }
+
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
 NL80211_CMD_CH_SWITCH_NOTIFY, 0);
 }
-- 
2.11.0



Re: [PATCH 12/14] qtnfmac: fix debugfs entries for multiple cards on the same host

2019-03-21 Thread Sergey Matyukevich
Hello Kalle,

> >> > Fix creation of debugfs entries for qtnfmac wireless card: use separate
> >> > directories for different wireless cards. This commit enables support
> >> > for multiple qtnfmac wireless cards on the same PCIe host.
> >> >
> >> > Signed-off-by: Sergey Matyukevich 
> >> > ---
> >> >  drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 6 +-
> >> >  1 file changed, 5 insertions(+), 1 deletion(-)
> >> >
> >> > diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
> >> > b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
> >> > index b561b75e4433..56fc6d49c121 100644
> >> > --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
> >> > +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
> >> > @@ -130,6 +130,8 @@ static int qtnf_dbg_shm_stats(struct seq_file *s, 
> >> > void *data)
> >> >
> >> >  int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus)
> >> >  {
> >> > + struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
> >> > + char card_id[64];
> >> >   int ret;
> >> >
> >> >   bus->fw_state = QTNF_FW_STATE_BOOT_DONE;
> >> > @@ -137,7 +139,9 @@ int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus)
> >> >   if (ret) {
> >> >   pr_err("failed to attach core\n");
> >> >   } else {
> >> > - qtnf_debugfs_init(bus, DRV_NAME);
> >> > + snprintf(card_id, sizeof(card_id), "%s:%s",
> >> > +  DRV_NAME, pci_name(priv->pdev));
> >>
> >> Can you give an example for the path?
> >>
> >
> > For instance:  /sys/kernel/debug/qtnfmac_pcie::01:00.0
> 
> TBH not really fond of that. What about
> "/sys/kernel/debug/qtnfmac/pcie::01:00.0"? IIRC iwlwifi used
> something like that.
> 
> And please add an example path to the commit log.

Ok, will be fixed and resubmitted in v2.

Or, alternatively, if the other patches are ok for you,
feel free to drop the questionable ones and apply all
the others. I will rework the rejected pieces and
resubmit them, adding more pending fixes.

Regards,
Sergey


Re: [PATCH 14/14] qtnfmac: use scan duration param for different scan types

2019-03-20 Thread Sergey Matyukevich
> > From: Igor Mitsyanko 
> >
> > Use scan duration param for both active and passive scan dwell times.
> > Document what different types of dwell times are used for. Explicitly
> > specify that if unset, automatic selection by device firmware
> > will be used.
> >
> > Signed-off-by: Igor Mitsyanko 
> > ---
> >  drivers/net/wireless/quantenna/qtnfmac/commands.c | 49 
> > ++-
> >  drivers/net/wireless/quantenna/qtnfmac/qlink.h| 11 -
> >  2 files changed, 49 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
> > b/drivers/net/wireless/quantenna/qtnfmac/commands.c
> > index 62edddb8551e..e58495403dde 100644
> > --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
> > +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
> > @@ -11,6 +11,13 @@
> >  #include "bus.h"
> >  #include "commands.h"
> >
> > +#define QTNF_SCAN_TIME_AUTO  0
> > +
> > +/* Let device itself to select best values for current conditions */
> > +#define QTNF_SCAN_DWELL_ACTIVE_DEFAULT   QTNF_SCAN_TIME_AUTO
> > +#define QTNF_SCAN_DWELL_PASSIVE_DEFAULT  QTNF_SCAN_TIME_AUTO
> > +#define QTNF_SCAN_SAMPLE_DURATION_DEFAULTQTNF_SCAN_TIME_AUTO
> 
> These three defines look odd. Why not just use QTNF_SCAN_TIME_AUTO
> directly?

Well, this is to be able to tweak their defaults independently if needed.

Regards,
Sergey


Re: [PATCH 12/14] qtnfmac: fix debugfs entries for multiple cards on the same host

2019-03-20 Thread Sergey Matyukevich
> > Fix creation of debugfs entries for qtnfmac wireless card: use separate
> > directories for different wireless cards. This commit enables support
> > for multiple qtnfmac wireless cards on the same PCIe host.
> >
> > Signed-off-by: Sergey Matyukevich 
> > ---
> >  drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 6 +-
> >  1 file changed, 5 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
> > b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
> > index b561b75e4433..56fc6d49c121 100644
> > --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
> > +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
> > @@ -130,6 +130,8 @@ static int qtnf_dbg_shm_stats(struct seq_file *s, void 
> > *data)
> >
> >  int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus)
> >  {
> > + struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
> > + char card_id[64];
> >   int ret;
> >
> >   bus->fw_state = QTNF_FW_STATE_BOOT_DONE;
> > @@ -137,7 +139,9 @@ int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus)
> >   if (ret) {
> >   pr_err("failed to attach core\n");
> >   } else {
> > - qtnf_debugfs_init(bus, DRV_NAME);
> > + snprintf(card_id, sizeof(card_id), "%s:%s",
> > +  DRV_NAME, pci_name(priv->pdev));
> 
> Can you give an example for the path?
> 

For instance:  /sys/kernel/debug/qtnfmac_pcie::01:00.0

Regards,
Sergey


[PATCH 14/14] qtnfmac: use scan duration param for different scan types

2019-03-20 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Use scan duration param for both active and passive scan dwell times.
Document what different types of dwell times are used for. Explicitly
specify that if unset, automatic selection by device firmware
will be used.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 49 ++-
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 11 -
 2 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 62edddb8551e..e58495403dde 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -11,6 +11,13 @@
 #include "bus.h"
 #include "commands.h"
 
+#define QTNF_SCAN_TIME_AUTO0
+
+/* Let device itself to select best values for current conditions */
+#define QTNF_SCAN_DWELL_ACTIVE_DEFAULT QTNF_SCAN_TIME_AUTO
+#define QTNF_SCAN_DWELL_PASSIVE_DEFAULTQTNF_SCAN_TIME_AUTO
+#define QTNF_SCAN_SAMPLE_DURATION_DEFAULT  QTNF_SCAN_TIME_AUTO
+
 static int qtnf_cmd_check_reply_header(const struct qlink_resp *resp,
   u16 cmd_id, u8 mac_id, u8 vif_id,
   size_t resp_size)
@@ -938,7 +945,7 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
"\nHardware ID:   %s"  \
"\nCalibration version:   %s"  \
"\nU-Boot version:%s"  \
-   "\nHardware version:  0x%08x",
+   "\nHardware version:  0x%08x\n",
bld_name, bld_rev, bld_type, bld_label,
(unsigned long)bld_tmstamp,
(unsigned long)plat_id,
@@ -2082,6 +2089,35 @@ static void qtnf_cmd_randmac_tlv_add(struct sk_buff 
*cmd_skb,
memcpy(randmac->mac_addr_mask, mac_addr_mask, ETH_ALEN);
 }
 
+static void qtnf_cmd_scan_set_dwell(struct qtnf_wmac *mac,
+   struct sk_buff *cmd_skb)
+{
+   struct cfg80211_scan_request *scan_req = mac->scan_req;
+   u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT;
+   u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT;
+   u16 duration = QTNF_SCAN_SAMPLE_DURATION_DEFAULT;
+
+   if (scan_req->duration) {
+   dwell_active = scan_req->duration;
+   dwell_passive = scan_req->duration;
+   }
+
+   pr_debug("MAC%u: %s scan dwell active=%u, passive=%u, duration=%u\n",
+mac->macid,
+scan_req->duration_mandatory ? "mandatory" : "max",
+dwell_active, dwell_passive, duration);
+
+   qtnf_cmd_skb_put_tlv_u16(cmd_skb,
+QTN_TLV_ID_SCAN_DWELL_ACTIVE,
+dwell_active);
+   qtnf_cmd_skb_put_tlv_u16(cmd_skb,
+QTN_TLV_ID_SCAN_DWELL_PASSIVE,
+dwell_passive);
+   qtnf_cmd_skb_put_tlv_u16(cmd_skb,
+QTN_TLV_ID_SCAN_SAMPLE_DURATION,
+duration);
+}
+
 int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
 {
struct sk_buff *cmd_skb;
@@ -2133,6 +2169,8 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
}
}
 
+   qtnf_cmd_scan_set_dwell(mac, cmd_skb);
+
if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
pr_debug("MAC%u: scan with random addr=%pM, mask=%pM\n",
 mac->macid,
@@ -2148,15 +2186,6 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
qtnf_cmd_skb_put_tlv_tag(cmd_skb, QTN_TLV_ID_SCAN_FLUSH);
}
 
-   if (scan_req->duration) {
-   pr_debug("MAC%u: %s scan duration %u\n", mac->macid,
-scan_req->duration_mandatory ? "mandatory" : "max",
-scan_req->duration);
-
-   qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_SCAN_DWELL,
-scan_req->duration);
-   }
-
ret = qtnf_cmd_send(mac->bus, cmd_skb);
if (ret)
goto out;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 2fe71adc221a..158c9eba20ef 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -1162,6 +1162,13 @@ struct qlink_event_external_auth {
  * carried by QTN_TLV_ID_STA_STATS_MAP.
  * @QTN_TLV_ID_MAX_SCAN_SSIDS: maximum number of SSIDs the device can scan
  * for in any given scan.
+ * @QTN_TLV_ID_SCAN_DWELL_ACTIVE: time spent on a single channel for an active
+ * scan.
+ * @QTN_TLV_ID_SCAN_DWELL_PASSIVE: time spent on a single channel for a passive
+ * scan.
+ * @QTN_TLV_ID_SCAN_SAMPLE_DURATION: total duration of sampling a single 
channel
+ * during a scan including off-channel dwell time and operating channel
+ *   

[PATCH 13/14] qtnfmac: send EAPOL frames via control path

2019-03-20 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Use control path to send EAPOL frames to make sure they are
sent with higher priority with aggregation disabled.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/bus.h   |  1 +
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c  | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/commands.c  | 10 ++---
 drivers/net/wireless/quantenna/qtnfmac/commands.h  |  4 +-
 drivers/net/wireless/quantenna/qtnfmac/core.c  | 45 --
 drivers/net/wireless/quantenna/qtnfmac/core.h  |  3 ++
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c |  1 +
 .../wireless/quantenna/qtnfmac/pcie/pcie_priv.h|  1 +
 .../wireless/quantenna/qtnfmac/pcie/topaz_pcie.c   |  8 
 drivers/net/wireless/quantenna/qtnfmac/qlink.h | 24 +++-
 10 files changed, 89 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h 
b/drivers/net/wireless/quantenna/qtnfmac/bus.h
index dc1bd32d4827..7cea08f71838 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/bus.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h
@@ -49,6 +49,7 @@ struct qtnf_bus {
struct napi_struct mux_napi;
struct net_device mux_dev;
struct workqueue_struct *workqueue;
+   struct workqueue_struct *hprio_workqueue;
struct work_struct fw_work;
struct work_struct event_work;
struct mutex bus_lock; /* lock during command/event processing */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 95572555ed6a..c78500bcaa2d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -144,6 +144,7 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct 
wireless_dev *wdev)
 {
struct net_device *netdev =  wdev->netdev;
struct qtnf_vif *vif;
+   struct sk_buff *skb;
 
if (WARN_ON(!netdev))
return -EFAULT;
@@ -157,6 +158,11 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct 
wireless_dev *wdev)
if (netif_carrier_ok(netdev))
netif_carrier_off(netdev);
 
+   while ((skb = skb_dequeue(&vif->high_pri_tx_queue)))
+   dev_kfree_skb_any(skb);
+
+   cancel_work_sync(&vif->high_pri_tx_work);
+
if (netdev->reg_state == NETREG_REGISTERED)
unregister_netdevice(netdev);
 
@@ -424,13 +430,13 @@ qtnf_mgmt_tx(struct wiphy *wiphy, struct wireless_dev 
*wdev,
*cookie = short_cookie;
 
if (params->offchan)
-   flags |= QLINK_MGMT_FRAME_TX_FLAG_OFFCHAN;
+   flags |= QLINK_FRAME_TX_FLAG_OFFCHAN;
 
if (params->no_cck)
-   flags |= QLINK_MGMT_FRAME_TX_FLAG_NO_CCK;
+   flags |= QLINK_FRAME_TX_FLAG_NO_CCK;
 
if (params->dont_wait_for_ack)
-   flags |= QLINK_MGMT_FRAME_TX_FLAG_ACK_NOWAIT;
+   flags |= QLINK_FRAME_TX_FLAG_ACK_NOWAIT;
 
/* If channel is not specified, pass "freq = 0" to tell device
 * firmware to use current channel.
@@ -445,9 +451,8 @@ qtnf_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 le16_to_cpu(mgmt_frame->frame_control), mgmt_frame->da,
 params->len, short_cookie, flags);
 
-   return qtnf_cmd_send_mgmt_frame(vif, short_cookie, flags,
-   freq,
-   params->buf, params->len);
+   return qtnf_cmd_send_frame(vif, short_cookie, flags,
+  freq, params->buf, params->len);
 }
 
 static int
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index a04321305ebc..62edddb8551e 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -381,11 +381,11 @@ int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 
frame_type, bool reg)
return ret;
 }
 
-int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
-u16 freq, const u8 *buf, size_t len)
+int qtnf_cmd_send_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
+   u16 freq, const u8 *buf, size_t len)
 {
struct sk_buff *cmd_skb;
-   struct qlink_cmd_mgmt_frame_tx *cmd;
+   struct qlink_cmd_frame_tx *cmd;
int ret;
 
if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
@@ -395,14 +395,14 @@ int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 
cookie, u16 flags,
}
 
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
-   QLINK_CMD_SEND_MGMT_FRAME,
+   QLINK_CMD_SEND_FRAME,
sizeof(*cmd));
if (!cmd_skb)
return -ENOMEM;
 
qtnf_bus_lock(vif->mac->bus);
 
-   cmd

[PATCH 07/14] qtnfmac: pass DFS region to firmware on region update

2019-03-20 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Pass DFS region as requested by regulatory core directly to firmware
so it can initialize radar detection block accordingly.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 15 +++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|  6 --
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 1a248d9f2e4c..cc7f74333f48 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2376,6 +2376,21 @@ int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct 
regulatory_request *req)
break;
}
 
+   switch (req->dfs_region) {
+   case NL80211_DFS_FCC:
+   cmd->dfs_region = QLINK_DFS_FCC;
+   break;
+   case NL80211_DFS_ETSI:
+   cmd->dfs_region = QLINK_DFS_ETSI;
+   break;
+   case NL80211_DFS_JP:
+   cmd->dfs_region = QLINK_DFS_JP;
+   break;
+   default:
+   cmd->dfs_region = QLINK_DFS_UNSET;
+   break;
+   }
+
cmd->num_channels = 0;
 
for (band = 0; band < NUM_NL80211_BANDS; band++) {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 6951f6370985..f6d30069ef3a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -582,6 +582,7 @@ enum qlink_user_reg_hint_type {
  * of &enum qlink_user_reg_hint_type.
  * @num_channels: number of &struct qlink_tlv_channel in a variable portion of 
a
  * payload.
+ * @dfs_region: one of &enum qlink_dfs_regions.
  * @info: variable portion of regulatory notifier callback.
  */
 struct qlink_cmd_reg_notify {
@@ -590,7 +591,8 @@ struct qlink_cmd_reg_notify {
u8 initiator;
u8 user_reg_hint_type;
u8 num_channels;
-   u8 rsvd[3];
+   u8 dfs_region;
+   u8 rsvd[2];
u8 info[0];
 } __packed;
 
@@ -800,7 +802,7 @@ enum qlink_dfs_regions {
  * @alpha2: country code ID firmware is configured to.
  * @n_reg_rules: number of regulatory rules TLVs in variable portion of the
  * message.
- * @dfs_region: regulatory DFS region, one of @enum qlink_dfs_region.
+ * @dfs_region: regulatory DFS region, one of &enum qlink_dfs_regions.
  * @var_info: variable-length WMAC info data.
  */
 struct qlink_resp_get_mac_info {
-- 
2.11.0



[PATCH 02/14] qtnfmac: simplify error reporting in regulatory notifier

2019-03-20 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Error reporting in qtnf_cfg80211_reg_notifier only requires to print
one type of message and an error code. Firmware will report success
for an attempt to set regulatory region to the same value,
so no special handling is required for this case.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 295890b2673c..ae08b37d81d2 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1005,16 +1005,8 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy 
*wiphy,
 
ret = qtnf_cmd_reg_notify(mac, req);
if (ret) {
-   if (ret == -EOPNOTSUPP) {
-   pr_warn("reg update not supported\n");
-   } else if (ret == -EALREADY) {
-   pr_info("regulatory domain is already set to %c%c",
-   req->alpha2[0], req->alpha2[1]);
-   } else {
-   pr_err("failed to update reg domain to %c%c\n",
-  req->alpha2[0], req->alpha2[1]);
-   }
-
+   pr_err("MAC%u: failed to update region to %c%c: %d\n",
+  mac->macid, req->alpha2[0], req->alpha2[1], ret);
return;
}
 
-- 
2.11.0



[PATCH 00/14] qtnfmac: regulatory rework and misc fixes

2019-03-20 Thread Sergey Matyukevich
Hello Kalle and all,

Here is the patch set with fixes and enhancements for qtnfmac driver.
The major changes include the following items:
- regulatory rework patches
- use high priority path for EAPOL frames
- fixes to support multiple cards on the same pcie host

Regards,
Sergey

Igor Mitsyanko (10):
  qtnfmac: make regulatory notifier work on per-phy basis
  qtnfmac: simplify error reporting in regulatory notifier
  qtnfmac: include full channels info to regulatory notifier
  qtnfmac: pass complete channel info in regulatory notifier
  qtnfmac: flexible regulatory domain registration logic
  qtnfmac: allow each MAC to specify its own regulatory rules
  qtnfmac: pass DFS region to firmware on region update
  qtnfmac: update bands information on CHANGE_INTF command
  qtnfmac: send EAPOL frames via control path
  qtnfmac: use scan duration param for different scan types

Sergey Matyukevich (4):
  qtnfmac: fix core attach error path in pcie backend
  qtnfmac: simplify firmware state tracking
  qtnfmac: allow changing the netns
  qtnfmac: fix debugfs entries for multiple cards on the same host

 drivers/net/wireless/quantenna/qtnfmac/bus.h   |  25 +-
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c  |  86 +++--
 drivers/net/wireless/quantenna/qtnfmac/commands.c  | 362 +++--
 drivers/net/wireless/quantenna/qtnfmac/commands.h  |   6 +-
 drivers/net/wireless/quantenna/qtnfmac/core.c  |  56 +++-
 drivers/net/wireless/quantenna/qtnfmac/core.h  |   5 +-
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c |  36 +-
 .../wireless/quantenna/qtnfmac/pcie/pcie_priv.h|   3 +-
 .../wireless/quantenna/qtnfmac/pcie/pearl_pcie.c   |  23 +-
 .../wireless/quantenna/qtnfmac/pcie/topaz_pcie.c   |  31 +-
 drivers/net/wireless/quantenna/qtnfmac/qlink.h |  85 +++--
 .../net/wireless/quantenna/qtnfmac/qlink_util.c| 117 +++
 .../net/wireless/quantenna/qtnfmac/qlink_util.h|   5 +
 13 files changed, 523 insertions(+), 317 deletions(-)

-- 
2.11.0



[PATCH 01/14] qtnfmac: make regulatory notifier work on per-phy basis

2019-03-20 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Wireless core calls regulatory notifier for each wiphy and it only
guarantees that bands info is updated for this particular wiphy prior
to calling a notifier. Hence updating all wiphy which belong to driver
in a single notifier callback is redundant and incorrect.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 32 +++
 drivers/net/wireless/quantenna/qtnfmac/commands.c |  9 +++
 drivers/net/wireless/quantenna/qtnfmac/commands.h |  2 +-
 3 files changed, 13 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index dcb0991432f4..295890b2673c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -993,20 +993,17 @@ static struct cfg80211_ops qtn_cfg80211_ops = {
 #endif
 };
 
-static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
+static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy,
   struct regulatory_request *req)
 {
-   struct qtnf_wmac *mac = wiphy_priv(wiphy_in);
-   struct qtnf_bus *bus = mac->bus;
-   struct wiphy *wiphy;
-   unsigned int mac_idx;
+   struct qtnf_wmac *mac = wiphy_priv(wiphy);
enum nl80211_band band;
int ret;
 
pr_debug("MAC%u: initiator=%d alpha=%c%c\n", mac->macid, req->initiator,
 req->alpha2[0], req->alpha2[1]);
 
-   ret = qtnf_cmd_reg_notify(bus, req);
+   ret = qtnf_cmd_reg_notify(mac, req);
if (ret) {
if (ret == -EOPNOTSUPP) {
pr_warn("reg update not supported\n");
@@ -1021,25 +1018,14 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy 
*wiphy_in,
return;
}
 
-   for (mac_idx = 0; mac_idx < QTNF_MAX_MAC; ++mac_idx) {
-   if (!(bus->hw_info.mac_bitmap & (1 << mac_idx)))
-   continue;
-
-   mac = bus->mac[mac_idx];
-   if (!mac)
+   for (band = 0; band < NUM_NL80211_BANDS; ++band) {
+   if (!wiphy->bands[band])
continue;
 
-   wiphy = priv_to_wiphy(mac);
-
-   for (band = 0; band < NUM_NL80211_BANDS; ++band) {
-   if (!wiphy->bands[band])
-   continue;
-
-   ret = qtnf_cmd_band_info_get(mac, wiphy->bands[band]);
-   if (ret)
-   pr_err("failed to get chan info for mac %u band 
%u\n",
-  mac_idx, band);
-   }
+   ret = qtnf_cmd_band_info_get(mac, wiphy->bands[band]);
+   if (ret)
+   pr_err("MAC%u: failed to update band %u\n",
+  mac->macid, band);
}
 }
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 85a2a58f4c16..9aabba7429ed 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2404,13 +2404,14 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, 
bool up)
return ret;
 }
 
-int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req)
+int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req)
 {
+   struct qtnf_bus *bus = mac->bus;
struct sk_buff *cmd_skb;
int ret;
struct qlink_cmd_reg_notify *cmd;
 
-   cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
+   cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
QLINK_CMD_REG_NOTIFY,
sizeof(*cmd));
if (!cmd_skb)
@@ -2449,10 +2450,6 @@ int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct 
regulatory_request *req)
 
qtnf_bus_lock(bus);
ret = qtnf_cmd_send(bus, cmd_skb);
-   if (ret)
-   goto out;
-
-out:
qtnf_bus_unlock(bus);
 
return ret;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h 
b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index 64f0b9dc8a14..050f9a49d16c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -57,7 +57,7 @@ int qtnf_cmd_send_disconnect(struct qtnf_vif *vif,
 u16 reason_code);
 int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif,
  bool up);
-int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req);
+int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req);
 int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
struct qtnf_chan_stats *stats);
 int qtnf_cmd_send_chan_switch(struct qtnf_vif 

[PATCH 09/14] qtnfmac: fix core attach error path in pcie backend

2019-03-20 Thread Sergey Matyukevich
Report that firmware is up and running only for successful firmware
download. Simplify qtnf_pcie_fw_boot_done: modify error path so that
no need to pass firmware dowload result to this function. Finally,
do not create debugfs entries if firmware download succeeded,
but core attach failed.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 25 +++---
 .../wireless/quantenna/qtnfmac/pcie/pcie_priv.h|  2 +-
 .../wireless/quantenna/qtnfmac/pcie/pearl_pcie.c   | 23 ++--
 .../wireless/quantenna/qtnfmac/pcie/topaz_pcie.c   | 23 
 4 files changed, 34 insertions(+), 39 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index c3a32effa6f0..a693667a83d7 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -128,32 +128,23 @@ static int qtnf_dbg_shm_stats(struct seq_file *s, void 
*data)
return 0;
 }
 
-void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success)
+int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus)
 {
-   struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
-   struct pci_dev *pdev = priv->pdev;
int ret;
 
-   if (boot_success) {
-   bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE;
-
-   ret = qtnf_core_attach(bus);
-   if (ret) {
-   pr_err("failed to attach core\n");
-   boot_success = false;
-   }
-   }
-
-   if (boot_success) {
+   bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE;
+   ret = qtnf_core_attach(bus);
+   if (ret) {
+   pr_err("failed to attach core\n");
+   bus->fw_state = QTNF_FW_STATE_DETACHED;
+   } else {
qtnf_debugfs_init(bus, DRV_NAME);
qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show);
qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show);
qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats);
-   } else {
-   bus->fw_state = QTNF_FW_STATE_DETACHED;
}
 
-   put_device(&pdev->dev);
+   return ret;
 }
 
 static void qtnf_tune_pcie_mps(struct pci_dev *pdev)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h
index bbc074e1f34d..b21de4f52a9d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h
@@ -70,7 +70,7 @@ struct qtnf_pcie_bus_priv {
 
 int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb);
 int qtnf_pcie_alloc_skb_array(struct qtnf_pcie_bus_priv *priv);
-void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success);
+int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus);
 void qtnf_pcie_init_shm_ipc(struct qtnf_pcie_bus_priv *priv,
struct qtnf_shm_ipc_region __iomem *ipc_tx_reg,
struct qtnf_shm_ipc_region __iomem *ipc_rx_reg,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
index 1f5facbb8905..3aa3714d4dfd 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
@@ -980,12 +980,11 @@ static void qtnf_pearl_fw_work_handler(struct work_struct 
*work)
 {
struct qtnf_bus *bus = container_of(work, struct qtnf_bus, fw_work);
struct qtnf_pcie_pearl_state *ps = (void *)get_bus_priv(bus);
+   u32 state = QTN_RC_FW_LOADRDY | QTN_RC_FW_QLINK;
+   const char *fwname = QTN_PCI_PEARL_FW_NAME;
struct pci_dev *pdev = ps->base.pdev;
const struct firmware *fw;
int ret;
-   u32 state = QTN_RC_FW_LOADRDY | QTN_RC_FW_QLINK;
-   const char *fwname = QTN_PCI_PEARL_FW_NAME;
-   bool fw_boot_success = false;
 
if (ps->base.flashboot) {
state |= QTN_RC_FW_FLASHBOOT;
@@ -1031,23 +1030,23 @@ static void qtnf_pearl_fw_work_handler(struct 
work_struct *work)
goto fw_load_exit;
}
 
-   pr_info("firmware is up and running\n");
-
if (qtnf_poll_state(&ps->bda->bda_ep_state,
QTN_EP_FW_QLINK_DONE, QTN_FW_QLINK_TIMEOUT_MS)) {
pr_err("firmware runtime failure\n");
goto fw_load_exit;
}
 
-   fw_boot_success = true;
+   pr_info("firmware is up and running\n");
 
-fw_load_exit:
-   qtnf_pcie_fw_boot_done(bus, fw_boot_success);
+   ret = qtnf_pcie_fw_boot_done(bus);
+   if (ret)
+   goto fw_load_exit;
 
-   if (fw_boot_success) {
-   qtnf_debugfs_add_en

[PATCH 11/14] qtnfmac: allow changing the netns

2019-03-20 Thread Sergey Matyukevich
Allow to change netns for wireless interfaces created by qtnfmac driver.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index cea948466744..95572555ed6a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1106,7 +1106,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
WIPHY_FLAG_AP_UAPSD |
WIPHY_FLAG_HAS_CHANNEL_SWITCH |
-   WIPHY_FLAG_4ADDR_STATION;
+   WIPHY_FLAG_4ADDR_STATION |
+   WIPHY_FLAG_NETNS_OK;
wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)
-- 
2.11.0



[PATCH 04/14] qtnfmac: pass complete channel info in regulatory notifier

2019-03-20 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Currently only a portion of per-channel information is passed to
firmware. Extend logic to pass all useful per-channel data.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c  | 49 +++
 .../net/wireless/quantenna/qtnfmac/qlink_util.c| 55 ++
 .../net/wireless/quantenna/qtnfmac/qlink_util.h|  3 ++
 3 files changed, 76 insertions(+), 31 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index b1b622019f12..e61bec7c5d8a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1709,21 +1709,7 @@ int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
struct qlink_resp_band_info_get *resp;
size_t info_len = 0;
int ret = 0;
-   u8 qband;
-
-   switch (band->band) {
-   case NL80211_BAND_2GHZ:
-   qband = QLINK_BAND_2GHZ;
-   break;
-   case NL80211_BAND_5GHZ:
-   qband = QLINK_BAND_5GHZ;
-   break;
-   case NL80211_BAND_60GHZ:
-   qband = QLINK_BAND_60GHZ;
-   break;
-   default:
-   return -EINVAL;
-   }
+   u8 qband = qlink_utils_band_cfg2q(band->band);
 
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
QLINK_CMD_BAND_INFO_GET,
@@ -2107,22 +2093,23 @@ int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
 static void qtnf_cmd_channel_tlv_add(struct sk_buff *cmd_skb,
 const struct ieee80211_channel *sc)
 {
-   struct qlink_tlv_channel *qchan;
-   u32 flags = 0;
-
-   qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
-   qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
-   qchan->hdr.len = cpu_to_le16(sizeof(*qchan) - sizeof(qchan->hdr));
-   qchan->chan.center_freq = cpu_to_le16(sc->center_freq);
-   qchan->chan.hw_value = cpu_to_le16(sc->hw_value);
-
-   if (sc->flags & IEEE80211_CHAN_NO_IR)
-   flags |= QLINK_CHAN_NO_IR;
-
-   if (sc->flags & IEEE80211_CHAN_RADAR)
-   flags |= QLINK_CHAN_RADAR;
-
-   qchan->chan.flags = cpu_to_le32(flags);
+   struct qlink_tlv_channel *tlv;
+   struct qlink_channel *qch;
+
+   tlv = skb_put_zero(cmd_skb, sizeof(*tlv));
+   qch = &tlv->chan;
+   tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
+   tlv->hdr.len = cpu_to_le16(sizeof(*qch));
+
+   qch->center_freq = cpu_to_le16(sc->center_freq);
+   qch->hw_value = cpu_to_le16(sc->hw_value);
+   qch->band = qlink_utils_band_cfg2q(sc->band);
+   qch->max_power = sc->max_power;
+   qch->max_reg_power = sc->max_reg_power;
+   qch->max_antenna_gain = sc->max_antenna_gain;
+   qch->beacon_found = sc->beacon_found;
+   qch->dfs_state = qlink_utils_dfs_state_cfg2q(sc->dfs_state);
+   qch->flags = cpu_to_le32(qlink_utils_chflags_cfg2q(sc->flags));
 }
 
 static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c 
b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
index 72bfd17cb687..8cae9d8d1ab6 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
@@ -182,3 +182,58 @@ void qlink_acl_data_cfg2q(const struct cfg80211_acl_data 
*acl,
memcpy(qacl->mac_addrs, acl->mac_addrs,
   acl->n_acl_entries * sizeof(*qacl->mac_addrs));
 }
+
+enum qlink_band qlink_utils_band_cfg2q(enum nl80211_band band)
+{
+   switch (band) {
+   case NL80211_BAND_2GHZ:
+   return QLINK_BAND_2GHZ;
+   case NL80211_BAND_5GHZ:
+   return QLINK_BAND_5GHZ;
+   case NL80211_BAND_60GHZ:
+   return QLINK_BAND_60GHZ;
+   default:
+   return -EINVAL;
+   }
+}
+
+enum qlink_dfs_state qlink_utils_dfs_state_cfg2q(enum nl80211_dfs_state state)
+{
+   switch (state) {
+   case NL80211_DFS_USABLE:
+   return QLINK_DFS_USABLE;
+   case NL80211_DFS_AVAILABLE:
+   return QLINK_DFS_AVAILABLE;
+   case NL80211_DFS_UNAVAILABLE:
+   default:
+   return QLINK_DFS_UNAVAILABLE;
+   }
+}
+
+u32 qlink_utils_chflags_cfg2q(u32 cfgflags)
+{
+   u32 flags = 0;
+
+   if (cfgflags & IEEE80211_CHAN_DISABLED)
+   flags |= QLINK_CHAN_DISABLED;
+
+   if (cfgflags & IEEE80211_CHAN_NO_IR)
+   flags |= QLINK_CHAN_NO_IR;
+
+   if (cfgflags & IEEE80211_CHAN_RADAR)
+   flags |= QLINK_CHAN_RADAR;
+
+   if (cfgflags & IEEE80211_CHAN_NO_HT40PLUS)
+   flags |= QLINK_CHAN_NO_HT40PLUS;
+
+   if (cfgflags & IEEE80211_CHAN_NO_HT40MINUS)
+   flags |= QLINK_CHAN_NO_HT40MINUS;
+
+   if (cfgflags & IEEE80211_CHAN_NO_80MHZ)
+   flags |= QLINK_CHAN_NO_80MHZ;
+
+  

[PATCH 03/14] qtnfmac: include full channels info to regulatory notifier

2019-03-20 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Before regulatory notifier is invoked by a wireless core, it will
update band information for the wiphy. Pass this information to
firmware together with new region alpha2 code.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 20 
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|  8 +++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 9aabba7429ed..b1b622019f12 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2406,10 +2406,13 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, 
bool up)
 
 int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req)
 {
+   struct wiphy *wiphy = priv_to_wiphy(mac);
struct qtnf_bus *bus = mac->bus;
struct sk_buff *cmd_skb;
int ret;
struct qlink_cmd_reg_notify *cmd;
+   enum nl80211_band band;
+   const struct ieee80211_supported_band *cfg_band;
 
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
QLINK_CMD_REG_NOTIFY,
@@ -2448,6 +2451,23 @@ int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct 
regulatory_request *req)
break;
}
 
+   cmd->num_channels = 0;
+
+   for (band = 0; band < NUM_NL80211_BANDS; band++) {
+   unsigned int i;
+
+   cfg_band = wiphy->bands[band];
+   if (!cfg_band)
+   continue;
+
+   cmd->num_channels += cfg_band->n_channels;
+
+   for (i = 0; i < cfg_band->n_channels; ++i) {
+   qtnf_cmd_channel_tlv_add(cmd_skb,
+&cfg_band->channels[i]);
+   }
+   }
+
qtnf_bus_lock(bus);
ret = qtnf_cmd_send(bus, cmd_skb);
qtnf_bus_unlock(bus);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 7798edcf7980..ca84684a1a93 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -6,7 +6,7 @@
 
 #include 
 
-#define QLINK_PROTO_VER13
+#define QLINK_PROTO_VER14
 
 #define QLINK_MACID_RSVD   0xFF
 #define QLINK_VIFID_RSVD   0xFF
@@ -580,12 +580,18 @@ enum qlink_user_reg_hint_type {
  * @initiator: which entity sent the request, one of &enum qlink_reg_initiator.
  * @user_reg_hint_type: type of hint for QLINK_REGDOM_SET_BY_USER request, one
  * of &enum qlink_user_reg_hint_type.
+ * @num_channels: number of &struct qlink_tlv_channel in a variable portion of 
a
+ * payload.
+ * @info: variable portion of regulatory notifier callback.
  */
 struct qlink_cmd_reg_notify {
struct qlink_cmd chdr;
u8 alpha2[2];
u8 initiator;
u8 user_reg_hint_type;
+   u8 num_channels;
+   u8 rsvd[3];
+   u8 info[0];
 } __packed;
 
 /**
-- 
2.11.0



[PATCH 10/14] qtnfmac: simplify firmware state tracking

2019-03-20 Thread Sergey Matyukevich
This patch streamlines firmware state tracking. In particular, state
QTNF_FW_STATE_FW_DNLD_DONE is removed, states QTNF_FW_STATE_RESET and
QTNF_FW_STATE_DETACHED are merged into a single state. Besides, new
state QTNF_FW_STATE_RUNNING is introduced to distinguish between
the following two cases:
- firmware load succeeded, firmware init process is ongoing
- firmware init succeeded, firmware is fully functional

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/bus.h   | 24 ++
 drivers/net/wireless/quantenna/qtnfmac/commands.c  |  3 +--
 drivers/net/wireless/quantenna/qtnfmac/core.c  |  8 +---
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 10 -
 4 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h 
b/drivers/net/wireless/quantenna/qtnfmac/bus.h
index 14b569b6d1b5..dc1bd32d4827 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/bus.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h
@@ -13,12 +13,11 @@
 #define QTNF_MAX_MAC   3
 
 enum qtnf_fw_state {
-   QTNF_FW_STATE_RESET,
-   QTNF_FW_STATE_FW_DNLD_DONE,
+   QTNF_FW_STATE_DETACHED,
QTNF_FW_STATE_BOOT_DONE,
QTNF_FW_STATE_ACTIVE,
-   QTNF_FW_STATE_DETACHED,
-   QTNF_FW_STATE_EP_DEAD,
+   QTNF_FW_STATE_RUNNING,
+   QTNF_FW_STATE_DEAD,
 };
 
 struct qtnf_bus;
@@ -58,6 +57,23 @@ struct qtnf_bus {
char bus_priv[0] __aligned(sizeof(void *));
 };
 
+static inline bool qtnf_fw_is_up(struct qtnf_bus *bus)
+{
+   enum qtnf_fw_state state = bus->fw_state;
+
+   return ((state == QTNF_FW_STATE_ACTIVE) ||
+   (state == QTNF_FW_STATE_RUNNING));
+}
+
+static inline bool qtnf_fw_is_attached(struct qtnf_bus *bus)
+{
+   enum qtnf_fw_state state = bus->fw_state;
+
+   return ((state == QTNF_FW_STATE_ACTIVE) ||
+   (state == QTNF_FW_STATE_RUNNING) ||
+   (state == QTNF_FW_STATE_DEAD));
+}
+
 static inline void *get_bus_priv(struct qtnf_bus *bus)
 {
if (WARN(!bus, "qtnfmac: invalid bus pointer"))
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 2e658e394dc6..a04321305ebc 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -89,8 +89,7 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
 
pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, cmd_id);
 
-   if (bus->fw_state != QTNF_FW_STATE_ACTIVE &&
-   cmd_id != QLINK_CMD_FW_INIT) {
+   if (!qtnf_fw_is_up(bus) && cmd_id != QLINK_CMD_FW_INIT) {
pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n",
mac_id, vif_id, cmd_id, bus->fw_state);
dev_kfree_skb(cmd_skb);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
b/drivers/net/wireless/quantenna/qtnfmac/core.c
index f04f4e1f7d68..eed12e4dec65 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -589,8 +589,6 @@ int qtnf_core_attach(struct qtnf_bus *bus)
int ret;
 
qtnf_trans_init(bus);
-
-   bus->fw_state = QTNF_FW_STATE_BOOT_DONE;
qtnf_bus_data_rx_start(bus);
 
bus->workqueue = alloc_ordered_workqueue("QTNF_BUS", 0);
@@ -639,6 +637,7 @@ int qtnf_core_attach(struct qtnf_bus *bus)
}
}
 
+   bus->fw_state = QTNF_FW_STATE_RUNNING;
return 0;
 
 error:
@@ -657,7 +656,7 @@ void qtnf_core_detach(struct qtnf_bus *bus)
for (macid = 0; macid < QTNF_MAX_MAC; macid++)
qtnf_core_mac_detach(bus, macid);
 
-   if (bus->fw_state == QTNF_FW_STATE_ACTIVE)
+   if (qtnf_fw_is_up(bus))
qtnf_cmd_send_deinit_fw(bus);
 
bus->fw_state = QTNF_FW_STATE_DETACHED;
@@ -683,6 +682,9 @@ struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, 
struct sk_buff *skb)
struct qtnf_wmac *mac;
struct qtnf_vif *vif;
 
+   if (unlikely(bus->fw_state != QTNF_FW_STATE_RUNNING))
+   return NULL;
+
meta = (struct qtnf_frame_meta_info *)
(skb_tail_pointer(skb) - sizeof(*meta));
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index a693667a83d7..b561b75e4433 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -56,7 +56,7 @@ int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff 
*skb)
 
if (ret == -ETIMEDOUT) {
pr_err("EP firmware is dead\n");
-   bus->fw_state = QTNF_FW_STATE_EP_DEAD;
+   bus->fw_state = QTNF_FW_STATE_DEAD;
}
 
return ret;
@@ -132,11 +132,10 @@ int qtnf_pcie_fw

[PATCH 05/14] qtnfmac: flexible regulatory domain registration logic

2019-03-20 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Use REGULATORY_CUSTOM_REG flag only if firmware advertised a custom
regulatory domain prior to wiphy registration. Use REGULATORY_STRICT_REG
flag only if firmware knows its regulatory domain.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 19 ++-
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index ae08b37d81d2..3131ced8801f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1073,6 +1073,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
struct wiphy *wiphy = priv_to_wiphy(mac);
struct qtnf_mac_info *macinfo = &mac->macinfo;
int ret;
+   bool regdomain_is_known;
 
if (!wiphy) {
pr_err("invalid wiphy pointer\n");
@@ -1144,11 +1145,20 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
wiphy->wowlan = macinfo->wowlan;
 #endif
 
+   regdomain_is_known = isalpha(hw_info->rd->alpha2[0]) &&
+   isalpha(hw_info->rd->alpha2[1]);
+
if (hw_info->hw_capab & QLINK_HW_CAPAB_REG_UPDATE) {
-   wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
-   REGULATORY_CUSTOM_REG;
wiphy->reg_notifier = qtnf_cfg80211_reg_notifier;
-   wiphy_apply_custom_regulatory(wiphy, hw_info->rd);
+
+   if (hw_info->rd->alpha2[0] == '9' &&
+   hw_info->rd->alpha2[1] == '9') {
+   wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+   REGULATORY_STRICT_REG;
+   wiphy_apply_custom_regulatory(wiphy, hw_info->rd);
+   } else if (regdomain_is_known) {
+   wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
+   }
} else {
wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
}
@@ -1172,8 +1182,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
 
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
ret = regulatory_set_wiphy_regd(wiphy, hw_info->rd);
-   else if (isalpha(hw_info->rd->alpha2[0]) &&
-isalpha(hw_info->rd->alpha2[1]))
+   else if (regdomain_is_known)
ret = regulatory_hint(wiphy, hw_info->rd->alpha2);
 
 out:
-- 
2.11.0



[PATCH 08/14] qtnfmac: update bands information on CHANGE_INTF command

2019-03-20 Thread Sergey Matyukevich
From: Igor Mitsyanko 

In some regions, different regulatory limits (like max Tx power) may be
defined for different operating modes. As an example: in ETSI regions
DFS master devices may use higher transmit powers compared to DFS slave
devices. Update bands information in CHANGE_INTF command if mode of
operation changes.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index cc7f74333f48..2e658e394dc6 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -786,8 +786,25 @@ int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
   int use4addr,
   u8 *mac_addr)
 {
-   return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
-QLINK_CMD_CHANGE_INTF);
+   int ret;
+
+   ret = qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
+   QLINK_CMD_CHANGE_INTF);
+
+   /* Regulatory settings may be different for different interface types */
+   if (ret == 0 && vif->wdev.iftype != iftype) {
+   enum nl80211_band band;
+   struct wiphy *wiphy = priv_to_wiphy(vif->mac);
+
+   for (band = 0; band < NUM_NL80211_BANDS; ++band) {
+   if (!wiphy->bands[band])
+   continue;
+
+   qtnf_cmd_band_info_get(vif->mac, wiphy->bands[band]);
+   }
+   }
+
+   return ret;
 }
 
 int qtnf_cmd_send_del_intf(struct qtnf_vif *vif)
-- 
2.11.0



[PATCH 06/14] qtnfmac: allow each MAC to specify its own regulatory rules

2019-03-20 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Currently driver uses the same regulatory rules to register all wiphy
instances. This is not logically correct since each wiphy may have
different capabilities (different supported bands, EIRP etc).
Allow firmware to pass regulatory rules for each MAC separately.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c  |  13 +-
 drivers/net/wireless/quantenna/qtnfmac/commands.c  | 186 +++--
 drivers/net/wireless/quantenna/qtnfmac/core.c  |   5 +-
 drivers/net/wireless/quantenna/qtnfmac/core.h  |   2 +-
 drivers/net/wireless/quantenna/qtnfmac/qlink.h |  42 ++---
 .../net/wireless/quantenna/qtnfmac/qlink_util.c|  62 +++
 .../net/wireless/quantenna/qtnfmac/qlink_util.h|   2 +
 7 files changed, 156 insertions(+), 156 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 3131ced8801f..cea948466744 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1145,17 +1145,16 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
wiphy->wowlan = macinfo->wowlan;
 #endif
 
-   regdomain_is_known = isalpha(hw_info->rd->alpha2[0]) &&
-   isalpha(hw_info->rd->alpha2[1]);
+   regdomain_is_known = isalpha(mac->rd->alpha2[0]) &&
+   isalpha(mac->rd->alpha2[1]);
 
if (hw_info->hw_capab & QLINK_HW_CAPAB_REG_UPDATE) {
wiphy->reg_notifier = qtnf_cfg80211_reg_notifier;
 
-   if (hw_info->rd->alpha2[0] == '9' &&
-   hw_info->rd->alpha2[1] == '9') {
+   if (mac->rd->alpha2[0] == '9' && mac->rd->alpha2[1] == '9') {
wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
REGULATORY_STRICT_REG;
-   wiphy_apply_custom_regulatory(wiphy, hw_info->rd);
+   wiphy_apply_custom_regulatory(wiphy, mac->rd);
} else if (regdomain_is_known) {
wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
}
@@ -1181,9 +1180,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
goto out;
 
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
-   ret = regulatory_set_wiphy_regd(wiphy, hw_info->rd);
+   ret = regulatory_set_wiphy_regd(wiphy, mac->rd);
else if (regdomain_is_known)
-   ret = regulatory_hint(wiphy, hw_info->rd->alpha2);
+   ret = regulatory_hint(wiphy, mac->rd->alpha2);
 
 out:
return ret;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index e61bec7c5d8a..1a248d9f2e4c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -831,55 +831,6 @@ int qtnf_cmd_send_del_intf(struct qtnf_vif *vif)
return ret;
 }
 
-static u32 qtnf_cmd_resp_reg_rule_flags_parse(u32 qflags)
-{
-   u32 flags = 0;
-
-   if (qflags & QLINK_RRF_NO_OFDM)
-   flags |= NL80211_RRF_NO_OFDM;
-
-   if (qflags & QLINK_RRF_NO_CCK)
-   flags |= NL80211_RRF_NO_CCK;
-
-   if (qflags & QLINK_RRF_NO_INDOOR)
-   flags |= NL80211_RRF_NO_INDOOR;
-
-   if (qflags & QLINK_RRF_NO_OUTDOOR)
-   flags |= NL80211_RRF_NO_OUTDOOR;
-
-   if (qflags & QLINK_RRF_DFS)
-   flags |= NL80211_RRF_DFS;
-
-   if (qflags & QLINK_RRF_PTP_ONLY)
-   flags |= NL80211_RRF_PTP_ONLY;
-
-   if (qflags & QLINK_RRF_PTMP_ONLY)
-   flags |= NL80211_RRF_PTMP_ONLY;
-
-   if (qflags & QLINK_RRF_NO_IR)
-   flags |= NL80211_RRF_NO_IR;
-
-   if (qflags & QLINK_RRF_AUTO_BW)
-   flags |= NL80211_RRF_AUTO_BW;
-
-   if (qflags & QLINK_RRF_IR_CONCURRENT)
-   flags |= NL80211_RRF_IR_CONCURRENT;
-
-   if (qflags & QLINK_RRF_NO_HT40MINUS)
-   flags |= NL80211_RRF_NO_HT40MINUS;
-
-   if (qflags & QLINK_RRF_NO_HT40PLUS)
-   flags |= NL80211_RRF_NO_HT40PLUS;
-
-   if (qflags & QLINK_RRF_NO_80MHZ)
-   flags |= NL80211_RRF_NO_80MHZ;
-
-   if (qflags & QLINK_RRF_NO_160MHZ)
-   flags |= NL80211_RRF_NO_160MHZ;
-
-   return flags;
-}
-
 static int
 qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
   const struct qlink_resp_get_hw_info *resp,
@@ -887,7 +838,6 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
 {
struct qtnf_hw_info *hwinfo = &bus->hw_info;
const struct qlink_tlv_hdr *tlv;
-   const struct qlink_tlv_reg_rule *tlv_rule;
const char *bld_name = NULL;
const char *bld_rev = NULL;
const char *bld_type = NULL;
@@ -898,19 +848,8 @@ qtnf_cmd_resp_proc_h

[PATCH 12/14] qtnfmac: fix debugfs entries for multiple cards on the same host

2019-03-20 Thread Sergey Matyukevich
Fix creation of debugfs entries for qtnfmac wireless card: use separate
directories for different wireless cards. This commit enables support
for multiple qtnfmac wireless cards on the same PCIe host.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index b561b75e4433..56fc6d49c121 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -130,6 +130,8 @@ static int qtnf_dbg_shm_stats(struct seq_file *s, void 
*data)
 
 int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus)
 {
+   struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+   char card_id[64];
int ret;
 
bus->fw_state = QTNF_FW_STATE_BOOT_DONE;
@@ -137,7 +139,9 @@ int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus)
if (ret) {
pr_err("failed to attach core\n");
} else {
-   qtnf_debugfs_init(bus, DRV_NAME);
+   snprintf(card_id, sizeof(card_id), "%s:%s",
+DRV_NAME, pci_name(priv->pdev));
+   qtnf_debugfs_init(bus, card_id);
qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show);
qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show);
qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats);
-- 
2.11.0



Re: [PATCHv3 0/9] cfg80211/mac80211: Add support for TID specific configuration

2019-03-08 Thread Sergey Matyukevich
Hello Tamizh,

> Add infrastructure to support per TID configurations like noack policy,
> retry count, AMPDU control(disable/enable), RTSCTS control(enable/disable)
> and TX rate mask configurations.
> This will be useful for the driver which can supports data TID
> specific configuration rather than phy level configurations.
> Here NL80211_CMD_SET_TID_CONFIG added to support this operation by
> accepting TID configuration.
> This command can accept STA mac addreess to make the configuration
> station specific rather than applying to all the connected stations
> to the netdev.
> And this nested command configuration can accept multiple number of
> data TID specific configuration in a single command,
> enum ieee80211_tid_conf_mask used to notify the driver that which
> configuration got modified for the TID.
> 
> Tamizh chelvam (9):
>   nl80211: New netlink command for TID specific configuration
>   nl80211: Add new netlink attribute for TID speicific retry count
>   nl80211: Add netlink attribute for AMPDU aggregation enable/disable
>   nl80211: Add netlink attribute to enable/disable RTS_CTS
>   nl80211: Add netlink attribute to configure TID specific tx rate
>   mac80211: Add api to support configuring TID specific configuration
>   ath10k: Add wmi command support for station specific TID config
>   ath10k: Add new api to support TID specific configuration
>   ath10k: Add extended TID configuration support
> 
> v3:
>   * Modified "nl80211: Add netlink attribute to configure TID specific tx 
> rate" patch
> to accept multiple TX rate configuration at a time.
>   * Modified noack and ampdu variable data type to int in
> "mac80211: Add api to support configuring TID specific configuration" 
> patch to store
> default configuration.
>   * Modified "ath10k: Add new api to support TID specific configuration" 
> patch to handle
> default values for noack and ampdu. And added sta pointer sanity check in
> ath10k_mac_tid_bitrate_config function.
>   * Fixed "ath10k: Add extended TID configuration support" wmi command 
> parameters
> assigned part.
> 
> v2:
>   * Added support to accept multiple TID configuration
>   * Added support to configure TX rate and RTSCTS control
> 
>  drivers/net/wireless/ath/ath10k/core.c|   4 +
>  drivers/net/wireless/ath/ath10k/core.h|   6 +
>  drivers/net/wireless/ath/ath10k/mac.c | 679 
> ++
>  drivers/net/wireless/ath/ath10k/wmi-ops.h |  19 +
>  drivers/net/wireless/ath/ath10k/wmi.c |  35 ++
>  drivers/net/wireless/ath/ath10k/wmi.h |  72 
>  include/net/cfg80211.h|  57 +++
>  include/net/mac80211.h|  35 ++
>  include/uapi/linux/nl80211.h  | 182 
>  net/mac80211/cfg.c|  28 ++
>  net/mac80211/driver-ops.h |  15 +
>  net/wireless/nl80211.c| 253 ++-
>  net/wireless/rdev-ops.h       |  11 +
>  net/wireless/trace.h  |  18 +
>  14 files changed, 1316 insertions(+), 98 deletions(-)

I am not familiar with ath10k driver internals. But for cfg80211/nl80211:
Reviewed-by: Sergey Matyukevich 

Regards,
Sergey


Re: [PATCHv2 1/9] nl80211: New netlink command for TID specific configuration

2019-02-27 Thread Sergey Matyukevich
Hi Tamizh,

> Hi Sergey,
> > 
> > > Signed-off-by: Tamizh chelvam 
> > > ---
> > >  include/net/cfg80211.h   |  35 +++
> > >  include/uapi/linux/nl80211.h |  51 ++
> > >  net/wireless/nl80211.c   | 102
> > > +++
> > >  net/wireless/rdev-ops.h  |  11 +
> > >  net/wireless/trace.h |  18 
> > >  5 files changed, 217 insertions(+)
> > 
> > ...
> > 
> > > diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> > > index 82d5e1e..352eb4a2 100644
> > > --- a/net/wireless/nl80211.c
> > > +++ b/net/wireless/nl80211.c
> > > @@ -280,6 +280,13 @@ static int validate_ie_attr(const struct nlattr
> > > *attr,
> > > 
> > > NLA_POLICY_NESTED_ARRAY(nl80211_psmr_peer_attr_policy),
> > >  };
> > > 
> > > +static const struct nla_policy
> > > +nl80211_attr_tid_config_policy[NL80211_ATTR_TID_CONFIG_MAX + 1] = {
> > > +   [NL80211_ATTR_TID_CONFIG_TID] = NLA_POLICY_MAX(NLA_U8, 7),
> > 
> > Such a policy permits configuration of per-TID settings, either
> > for per-STA or for all the STAs. However it is not possible to
> > perform configuration for all TIDs at once, e.g. passing -1 value
> > to driver.
> > 
> > Maybe simplify policy and use .type = NLA_U8 ?
> > 
> > Sanity check, if needed, can be performed by driver or even by
> > firmware.
> > 
> Sure, we can have like that. And do you feel driver should advertise
> support to perform configuration for all TIDs(like accepting tid -1) ?

Do you think this additional level of granularity is needed ?
IIUC if driver/firmware supports per TID feature configuration,
then can handle all-TIDs configuration as well. Anyway, attempt
for global feature configuration can be rejected on driver
or firmware level if needed.

> > > +   [NL80211_ATTR_TID_CONFIG_NOACK] =
> > > +   NLA_POLICY_MAX(NLA_U8,
> > > NL80211_TID_CONFIG_DISABLE),
> > > +};
> > > +
> > >  const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
> > > [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
> > > [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
> > > @@ -541,6 +548,8 @@ static int validate_ie_attr(const struct nlattr
> > > *attr,
> > > [NL80211_ATTR_PEER_MEASUREMENTS] =
> > > NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
> > > [NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
> > > +   [NL80211_ATTR_TID_CONFIG] =
> > > +
> > > NLA_POLICY_NESTED(nl80211_attr_tid_config_policy),
> > >  };
> > 
> > ...
> > 
> > > +static int nl80211_set_tid_config(struct sk_buff *skb,
> > > + struct genl_info *info)
> > > +{
> > > +   struct cfg80211_registered_device *rdev = info->user_ptr[0];
> > > +   struct nlattr *attrs[NL80211_ATTR_TID_CONFIG_MAX + 1];
> > > +   struct net_device *dev = info->user_ptr[1];
> > > +   struct ieee80211_tid_config *tid_conf;
> > > +   struct nlattr *tid;
> > > +   int conf_idx = 0, rem_conf;
> > > +   u32 num_conf = 0, size_of_conf;
> > > +   int ret = -EINVAL;
> > > +
> > > +   if (!info->attrs[NL80211_ATTR_TID_CONFIG])
> > > +   return -EINVAL;
> > > +
> > > +   if (!rdev->ops->set_tid_config)
> > > +   return -EOPNOTSUPP;
> > > +
> > > +   nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
> > > +   rem_conf)
> > > +   num_conf++;
> > > +
> > > +   size_of_conf = sizeof(struct ieee80211_tid_config) +
> > > +   num_conf * sizeof(struct ieee80211_tid_cfg);
> > > +
> > > +   tid_conf = kzalloc(size_of_conf, GFP_KERNEL);
> > > +   if (!tid_conf)
> > > +   return -ENOMEM;
> > > +
> > > +   tid_conf->n_tid_conf = num_conf;
> > > +
> > > +   if (info->attrs[NL80211_ATTR_MAC])
> > > +   tid_conf->peer =
> > > nla_data(info->attrs[NL80211_ATTR_MAC]);
> > > +   else
> > > +   tid_conf->peer = NULL;
> > > +
> > > +   nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
> > > +   rem_conf) {
> > > +   ret = nla_parse_nested(attrs,
> > > NL80211_ATTR_TID_CONFIG_MAX, tid,
> > > +  NULL, NULL);
> > > +
> > > +   if (ret)
> > > +   return ret;
> > > +
> > > +   if (!attrs[NL80211_ATTR_TID_CONFIG_TID])
> > > +   return -EINVAL;
> > > +
> > > +   ret = parse_tid_conf(rdev, attrs,
> > > &tid_conf->tid_conf[conf_idx],
> > > +tid_conf->peer);
> > > +   if (ret)
> > > +   goto bad_tid_conf;
> > > +
> > > +   conf_idx++;
> > > +   }
> > > +
> > > +   return rdev_set_tid_config(rdev, dev, tid_conf);
> > 
> > What is the ownership rule for tid_conf ? In other words, who is
> > responsible for freeing this structure ?
> > 
> > Unless I am missing something, in t

Re: [PATCHv2 1/9] nl80211: New netlink command for TID specific configuration

2019-02-26 Thread Sergey Matyukevich


Hello Tamizh,

> Signed-off-by: Tamizh chelvam 
> ---
>  include/net/cfg80211.h   |  35 +++
>  include/uapi/linux/nl80211.h |  51 ++
>  net/wireless/nl80211.c   | 102 
> +++
>  net/wireless/rdev-ops.h  |  11 +
>  net/wireless/trace.h |  18 
>  5 files changed, 217 insertions(+)

...

> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 82d5e1e..352eb4a2 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -280,6 +280,13 @@ static int validate_ie_attr(const struct nlattr *attr,
> NLA_POLICY_NESTED_ARRAY(nl80211_psmr_peer_attr_policy),
>  };
> 
> +static const struct nla_policy
> +nl80211_attr_tid_config_policy[NL80211_ATTR_TID_CONFIG_MAX + 1] = {
> +   [NL80211_ATTR_TID_CONFIG_TID] = NLA_POLICY_MAX(NLA_U8, 7),

Such a policy permits configuration of per-TID settings, either
for per-STA or for all the STAs. However it is not possible to
perform configuration for all TIDs at once, e.g. passing -1 value
to driver.

Maybe simplify policy and use .type = NLA_U8 ?

Sanity check, if needed, can be performed by driver or even by firmware.

> +   [NL80211_ATTR_TID_CONFIG_NOACK] =
> +   NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
> +};
> +
>  const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
> [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
> [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
> @@ -541,6 +548,8 @@ static int validate_ie_attr(const struct nlattr *attr,
> [NL80211_ATTR_PEER_MEASUREMENTS] =
> NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
> [NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
> +   [NL80211_ATTR_TID_CONFIG] =
> +   NLA_POLICY_NESTED(nl80211_attr_tid_config_policy),
>  };

...

> +static int nl80211_set_tid_config(struct sk_buff *skb,
> + struct genl_info *info)
> +{
> +   struct cfg80211_registered_device *rdev = info->user_ptr[0];
> +   struct nlattr *attrs[NL80211_ATTR_TID_CONFIG_MAX + 1];
> +   struct net_device *dev = info->user_ptr[1];
> +   struct ieee80211_tid_config *tid_conf;
> +   struct nlattr *tid;
> +   int conf_idx = 0, rem_conf;
> +   u32 num_conf = 0, size_of_conf;
> +   int ret = -EINVAL;
> +
> +   if (!info->attrs[NL80211_ATTR_TID_CONFIG])
> +   return -EINVAL;
> +
> +   if (!rdev->ops->set_tid_config)
> +   return -EOPNOTSUPP;
> +
> +   nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
> +   rem_conf)
> +   num_conf++;
> +
> +   size_of_conf = sizeof(struct ieee80211_tid_config) +
> +   num_conf * sizeof(struct ieee80211_tid_cfg);
> +
> +   tid_conf = kzalloc(size_of_conf, GFP_KERNEL);
> +   if (!tid_conf)
> +   return -ENOMEM;
> +
> +   tid_conf->n_tid_conf = num_conf;
> +
> +   if (info->attrs[NL80211_ATTR_MAC])
> +   tid_conf->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
> +   else
> +   tid_conf->peer = NULL;
> +
> +   nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
> +   rem_conf) {
> +   ret = nla_parse_nested(attrs, NL80211_ATTR_TID_CONFIG_MAX, 
> tid,
> +  NULL, NULL);
> +
> +   if (ret)
> +   return ret;
> +
> +   if (!attrs[NL80211_ATTR_TID_CONFIG_TID])
> +   return -EINVAL;
> +
> +   ret = parse_tid_conf(rdev, attrs, 
> &tid_conf->tid_conf[conf_idx],
> +tid_conf->peer);
> +   if (ret)
> +   goto bad_tid_conf;
> +
> +   conf_idx++;
> +   }
> +
> +   return rdev_set_tid_config(rdev, dev, tid_conf);

What is the ownership rule for tid_conf ? In other words, who is
responsible for freeing this structure ?

Unless I am missing something, in the suggested patches there is no
kfree for this structure and all the nested structures (see Tx bitrate
patch), neither in cfg80211/mac80211 nor in ath10k.

As far as I understand, we have two options here. One option is to
explicitly specify that ownership is passed to the caller, similar
to nl80211_set_reg. Another option is to release memory in this
function after driver makes copies of all necessary fields,
e.g. see nl80211_set_mac_acl.

> +
> +bad_tid_conf:
> +   kfree(tid_conf);
> +   return ret;
> +}

Regards,
Sergey


Re: [PATCHv2 8/9] ath10k: Add new api to support TID specific configuration

2019-02-26 Thread Sergey Matyukevich
Hello Tamizh,

> This patch add ops for set_tid_config to support TID
> specific configuration. STA information along with the
> TID config change mask to notify driver that which configuration
> needs to be applied for this current command.
> If the STA info not available in the command then the
> configuration will be applied for all connected stations
> in the vif. TID specific noack configuration requires
> aggregation disabled and rate for the data TID packets
> should be basic rates. So, if the TID already configured
> with noack policy then driver will ignore the aggregation
> or TX rate related configuration for the same data TID.
> In TX rate configuration should be applied with highest
> preamble configuration(HT rates should not be applied
> for the station which supports vht rates).
> 
> Vif specific TID configuration will be applied for all
> the connected stations except for the station which
> already applied with the same configuration for the TID
> through station specific command. Newly connecting stations
> will be applied with vif TID configuration which will be stored
> in ieee80211_vif.
> 
> Testing:
> * Tested HW: QCA9888
> * Tested FW: 10.4-3.5.1-00052
> 
> Signed-off-by: Tamizh chelvam 
> ---
>  drivers/net/wireless/ath/ath10k/core.h |   7 +
>  drivers/net/wireless/ath/ath10k/mac.c  | 602 
> -
>  2 files changed, 529 insertions(+), 80 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/core.h 
> b/drivers/net/wireless/ath/ath10k/core.h
> index 27ec555..c25c426 100644
> --- a/drivers/net/wireless/ath/ath10k/core.h
> +++ b/drivers/net/wireless/ath/ath10k/core.h
> @@ -82,6 +82,9 @@
>  /* Default Airtime weight multipler (Tuned for multiclient performance) */
>  #define ATH10K_AIRTIME_WEIGHT_MULTIPLIER  4
> 
> +#define ATH10K_MAX_RETRY_COUNT 30
> +#define ATH10K_MAX_TIDS8

Is there any reason why you don't use IEEE80211_TID_MAX here ?

Regards,
Sergey


Re: [PATCH] cfg80211/nl80211: Offload OWE processing to user space in AP mode

2019-02-15 Thread Sergey Matyukevich
Hi Srinivas,

>  include/net/cfg80211.h   | 42 ++
>  include/uapi/linux/nl80211.h |  7 +
>  net/wireless/nl80211.c   | 72 
> 
>  net/wireless/rdev-ops.h  | 13 
>  net/wireless/trace.h | 38 +++
>  5 files changed, 172 insertions(+)

...

> +void cfg80211_update_owe_info_event(struct net_device *netdev,
> +   struct cfg80211_update_owe_info *owe_info,
> +   gfp_t gfp)
> +{
> +   struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
> +   struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
> +   struct sk_buff *msg;
> +   void *hdr;
> +
> +   trace_cfg80211_update_owe_info_event(wiphy, netdev, owe_info);
> +
> +   msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
> +   if (!msg)
> +   return;
> +
> +   hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UPDATE_OWE_INFO);
> +   if (!hdr)
> +   goto nla_put_failure;
> +
> +   if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
> +   nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
> +   nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, owe_info->peer))
> +   goto nla_put_failure;
> +
> +   if (nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
> +   goto nla_put_failure;

Maybe worth adding sanity check if IE length is non-zero ?


Reviewed-by: Sergey Matyukevich 

Regards,
Sergey


Re: [PATCH 0/4] cfg80211/mac80211: Add support for TID specific configuration

2019-02-13 Thread Sergey Matyukevich
Hello Tamizh,

> Add infrastructure for per TID aggregation/retry count configurations
> such as retry count and AMPDU aggregation control(disable/enable).
> In some scenario reducing the number of retry count for a specific data
> traffic can reduce the latency by proceeding with the next packet
> instead of retrying the same packet more time. This will be useful
> where the next packet can resume the operation without an issue.
> Here added NL80211_CMD_SET_TID_CONFIG to support this operation by
> accepting retry count and AMPDU aggregation control.
> This command can accept STA mac addreess to make the configuration
> station specific rather than applying to all the connected stations
> to the netdev.
> 
> Tamizh chelvam (3):
>   nl80211: Add netlink attribute for AMPDU aggregation enable/disable
>   tid conf 3
>   ath10k: Add support to configure TID specific configuration
> 
> Vasanthakumar Thiagarajan (1):
>   New netlink command for TID specific configuration

Could you please share your further plans regarding this patch series ?
Do you plan to send next revision in the forseable future ?
Or have you decided to abandon this approach ?

Regards,
Sergey


[PATCH 1/2] qtnfmac: enable WPA3 OWE support

2019-02-05 Thread Sergey Matyukevich
In the case of OWE, STA should be able to pass DH IEs from AP assoc
responses to wpa_s for processing. For this purpose DH IEs are
received from firmware in BSS_JOIN events and passed to wireless
core and then to wpa_s as additional optional rsp_ies parameter
for cfg80211_connect_result.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/event.c | 144 +
 drivers/net/wireless/quantenna/qtnfmac/qlink.h |   1 +
 2 files changed, 102 insertions(+), 43 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c 
b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 3fd1a9217737..944729b74f17 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -150,6 +150,13 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
struct cfg80211_chan_def chandef;
struct cfg80211_bss *bss = NULL;
u8 *ie = NULL;
+   size_t payload_len;
+   u16 tlv_type;
+   u16 tlv_value_len;
+   size_t tlv_full_len;
+   const struct qlink_tlv_hdr *tlv;
+   const u8 *rsp_ies = NULL;
+   size_t rsp_ies_len = 0;
 
if (unlikely(len < sizeof(*join_info))) {
pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
@@ -167,67 +174,118 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
pr_debug("VIF%u.%u: BSSID:%pM status:%u\n",
 vif->mac->macid, vif->vifid, join_info->bssid, status);
 
-   if (status == WLAN_STATUS_SUCCESS) {
-   qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef);
-   if (!cfg80211_chandef_valid(&chandef)) {
-   pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u 
bw=%u\n",
+   if (status != WLAN_STATUS_SUCCESS)
+   goto done;
+
+   qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef);
+   if (!cfg80211_chandef_valid(&chandef)) {
+   pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
+   vif->mac->macid, vif->vifid,
+   chandef.chan->center_freq,
+   chandef.center_freq1,
+   chandef.center_freq2,
+   chandef.width);
+   status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+   goto done;
+   }
+
+   bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid,
+  NULL, 0, IEEE80211_BSS_TYPE_ESS,
+  IEEE80211_PRIVACY_ANY);
+   if (!bss) {
+   pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n",
+   vif->mac->macid, vif->vifid,
+   join_info->bssid, chandef.chan->hw_value);
+
+   if (!vif->wdev.ssid_len) {
+   pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n",
+   vif->mac->macid, vif->vifid,
+   join_info->bssid);
+   status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+   goto done;
+   }
+
+   ie = kzalloc(2 + vif->wdev.ssid_len, GFP_KERNEL);
+   if (!ie) {
+   pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n",
vif->mac->macid, vif->vifid,
-   chandef.chan->center_freq,
-   chandef.center_freq1,
-   chandef.center_freq2,
-   chandef.width);
+   join_info->bssid);
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto done;
}
 
-   bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid,
-  NULL, 0, IEEE80211_BSS_TYPE_ESS,
-  IEEE80211_PRIVACY_ANY);
+   ie[0] = WLAN_EID_SSID;
+   ie[1] = vif->wdev.ssid_len;
+   memcpy(ie + 2, vif->wdev.ssid, vif->wdev.ssid_len);
+
+   bss = cfg80211_inform_bss(wiphy, chandef.chan,
+ CFG80211_BSS_FTYPE_UNKNOWN,
+ join_info->bssid, 0,
+ WLAN_CAPABILITY_ESS, 100,
+ ie, 2 + vif->wdev.ssid_len,
+ 0, GFP_KERNEL);
if (!bss) {
-   pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n",
+   pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n",
vif->mac->macid, vif->vifid,
-   join_info->bssid, cha

[PATCH 2/2] qtnfmac: enable WPA3 SAE support

2019-02-05 Thread Sergey Matyukevich
In the case of SAE AP, drivers offload authentication to user-space
software, e.g. hostapd. For FullMAC drivers the procedure is as follows.
If auth_type is SAE and user space indicates external authentication
capability, then driver requests authentication offload to user-space
software using cfg80211_external_auth_request call. From that point,
auth frame exchange is performed transparently for driver: user-space
software sends/receives mgmt frames using mgmt_tx/mgmt_frame_register
cfg80211 callbacks. As soon as authenitcation is completed, user-space
software notifies driver about its status using external_auth cfg80211
callback.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 40 --
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 29 
 drivers/net/wireless/quantenna/qtnfmac/commands.h |  2 ++
 drivers/net/wireless/quantenna/qtnfmac/event.c| 41 +++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 35 +++
 5 files changed, 145 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 45f4cef7de9c..dcb0991432f4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -53,9 +53,11 @@ static const u32 qtnf_cipher_suites[] = {
 static const struct ieee80211_txrx_stypes
 qtnf_mgmt_stypes[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_STATION] = {
-   .tx = BIT(IEEE80211_STYPE_ACTION >> 4),
+   .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4),
.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4),
},
[NL80211_IFTYPE_AP] = {
.tx = BIT(IEEE80211_STYPE_ACTION >> 4),
@@ -636,6 +638,12 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
 
+   if (sme->auth_type == NL80211_AUTHTYPE_SAE &&
+   !(sme->flags & CONNECT_REQ_EXTERNAL_AUTH_SUPPORT)) {
+   pr_err("can not offload authentication to userspace\n");
+   return -EOPNOTSUPP;
+   }
+
if (sme->bssid)
ether_addr_copy(vif->bssid, sme->bssid);
else
@@ -653,6 +661,30 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int
+qtnf_external_auth(struct wiphy *wiphy, struct net_device *dev,
+  struct cfg80211_external_auth_params *auth)
+{
+   struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+   int ret;
+
+   if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
+   return -EOPNOTSUPP;
+
+   if (!ether_addr_equal(vif->bssid, auth->bssid))
+   pr_warn("unexpected bssid: %pM", auth->bssid);
+
+   ret = qtnf_cmd_send_external_auth(vif, auth);
+   if (ret) {
+   pr_err("VIF%u.%u: failed to report external auth\n",
+  vif->mac->macid, vif->vifid);
+   goto out;
+   }
+
+out:
+   return ret;
+}
+
+static int
 qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
u16 reason_code)
 {
@@ -946,6 +978,7 @@ static struct cfg80211_ops qtn_cfg80211_ops = {
.set_default_mgmt_key   = qtnf_set_default_mgmt_key,
.scan   = qtnf_scan,
.connect= qtnf_connect,
+   .external_auth  = qtnf_external_auth,
.disconnect = qtnf_disconnect,
.dump_survey= qtnf_dump_survey,
.get_channel= qtnf_get_channel,
@@ -1125,6 +1158,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
if (!(hw_info->hw_capab & QLINK_HW_CAPAB_OBSS_SCAN))
wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN;
 
+   if (hw_info->hw_capab & QLINK_HW_CAPAB_SAE)
+   wiphy->features |= NL80211_FEATURE_SAE;
+
 #ifdef CONFIG_PM
if (macinfo->wowlan)
wiphy->wowlan = macinfo->wowlan;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 0f48f541de41..85a2a58f4c16 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2322,6 +2322,35 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
return ret;
 }
 
+int qtnf_cmd_send_external_auth(struct qtnf_vif *vif,
+   struct cfg80211_external_auth_params *auth)
+{
+   st

[PATCH 0/2] qtnfmac: enable WPA3 SAE/OWE support

2019-02-05 Thread Sergey Matyukevich
Hello Kalle and all,

These two patches enable WPA3 support for qtnfmac driver including
SAE, OWE, as well as their transition modes.

Sergey Matyukevich (2):
  qtnfmac: enable WPA3 OWE support
  qtnfmac: enable WPA3 SAE support

 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |  40 -
 drivers/net/wireless/quantenna/qtnfmac/commands.c |  29 
 drivers/net/wireless/quantenna/qtnfmac/commands.h |   2 +
 drivers/net/wireless/quantenna/qtnfmac/event.c| 185 +-
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|  36 +
 5 files changed, 247 insertions(+), 45 deletions(-)

-- 
2.11.0



Re: [PATCH] quantenna: no need to check return value of debugfs_create functions

2019-01-23 Thread Sergey Matyukevich
> When calling debugfs functions, there is no need to ever check the
> return value.  The function can work or not, but the code logic should
> never do something different based on this.
> 
> Cc: Igor Mitsyanko 
> Cc: Avinash Patil 
> Cc: Sergey Matyukevich 
> Cc: Kalle Valo 
> Cc: linux-wireless@vger.kernel.org
> Signed-off-by: Greg Kroah-Hartman 
> ---
>  drivers/net/wireless/quantenna/qtnfmac/debug.c | 14 +-
>  1 file changed, 1 insertion(+), 13 deletions(-)

Reviewed-by: Sergey Matyukevich 

Regards,
Sergey


[PATCH v2 7/9] qtnfmac: add missing bss record to host scan cache

2019-01-14 Thread Sergey Matyukevich
Make sure that valid BSS entry exists in wireless core record
even in the case of successful connect reported by firmware.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/event.c | 79 --
 drivers/net/wireless/quantenna/qtnfmac/qlink.h |  4 +-
 2 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c 
b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 3038a000c287..3fd1a9217737 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -145,6 +145,12 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
   const struct qlink_event_bss_join *join_info,
   u16 len)
 {
+   struct wiphy *wiphy = priv_to_wiphy(vif->mac);
+   enum ieee80211_statuscode status = le16_to_cpu(join_info->status);
+   struct cfg80211_chan_def chandef;
+   struct cfg80211_bss *bss = NULL;
+   u8 *ie = NULL;
+
if (unlikely(len < sizeof(*join_info))) {
pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
   vif->mac->macid, vif->vifid, len,
@@ -158,15 +164,80 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
return -EPROTO;
}
 
-   pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid,
-join_info->bssid);
+   pr_debug("VIF%u.%u: BSSID:%pM status:%u\n",
+vif->mac->macid, vif->vifid, join_info->bssid, status);
+
+   if (status == WLAN_STATUS_SUCCESS) {
+   qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef);
+   if (!cfg80211_chandef_valid(&chandef)) {
+   pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u 
bw=%u\n",
+   vif->mac->macid, vif->vifid,
+   chandef.chan->center_freq,
+   chandef.center_freq1,
+   chandef.center_freq2,
+   chandef.width);
+   status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+   goto done;
+   }
 
+   bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid,
+  NULL, 0, IEEE80211_BSS_TYPE_ESS,
+  IEEE80211_PRIVACY_ANY);
+   if (!bss) {
+   pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n",
+   vif->mac->macid, vif->vifid,
+   join_info->bssid, chandef.chan->hw_value);
+
+   if (!vif->wdev.ssid_len) {
+   pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n",
+   vif->mac->macid, vif->vifid,
+   join_info->bssid);
+   status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+   goto done;
+   }
+
+   ie = kzalloc(2 + vif->wdev.ssid_len, GFP_KERNEL);
+   if (!ie) {
+   pr_warn("VIF%u.%u: IE alloc failed for 
BSS:%pM\n",
+   vif->mac->macid, vif->vifid,
+   join_info->bssid);
+   status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+   goto done;
+   }
+
+   ie[0] = WLAN_EID_SSID;
+   ie[1] = vif->wdev.ssid_len;
+   memcpy(ie + 2, vif->wdev.ssid, vif->wdev.ssid_len);
+
+   bss = cfg80211_inform_bss(wiphy, chandef.chan,
+ CFG80211_BSS_FTYPE_UNKNOWN,
+ join_info->bssid, 0,
+ WLAN_CAPABILITY_ESS, 100,
+ ie, 2 + vif->wdev.ssid_len,
+ 0, GFP_KERNEL);
+   if (!bss) {
+   pr_warn("VIF%u.%u: can't connect to unknown 
BSS: %pM\n",
+   vif->mac->macid, vif->vifid,
+   join_info->bssid);
+   status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+   goto done;
+   }
+   }
+   }
+
+done:
cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL,
-   0, le16_to_cpu(join_info->status), GFP_KERNEL);
+   

[PATCH v2 8/9] qtnfmac: remove unused declarations

2019-01-14 Thread Sergey Matyukevich
Remove declarations for inexistent functions from bus.h header.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/bus.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h 
b/drivers/net/wireless/quantenna/qtnfmac/bus.h
index 7bd906cc7023..14b569b6d1b5 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/bus.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h
@@ -122,7 +122,5 @@ static __always_inline void qtnf_bus_unlock(struct qtnf_bus 
*bus)
 
 int qtnf_core_attach(struct qtnf_bus *bus);
 void qtnf_core_detach(struct qtnf_bus *bus);
-void qtnf_txflowblock(struct device *dev, bool state);
-void qtnf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
 
 #endif /* QTNFMAC_BUS_H */
-- 
2.11.0



[PATCH v2 4/9] qtnfmac: switch to 32bit values for RTS/FRAG thresholds

2019-01-14 Thread Sergey Matyukevich
Host wireless stack uses u32 type for RTS/FRAG threshold values.
Switch to u32 in driver: pass u32 values to firmware and let
firmware properly adapt these values according to its
internal representation.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c   |  8 
 drivers/net/wireless/quantenna/qtnfmac/qlink.h  |  4 ++--
 drivers/net/wireless/quantenna/qtnfmac/qlink_util.h | 11 +++
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 0748a756cc1c..66cb05dfdba5 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1564,11 +1564,11 @@ static int qtnf_cmd_resp_proc_phy_params(struct 
qtnf_wmac *mac,
switch (tlv_type) {
case QTN_TLV_ID_FRAG_THRESH:
phy_thr = (void *)tlv;
-   mac_info->frag_thr = (u32)le16_to_cpu(phy_thr->thr);
+   mac_info->frag_thr = le32_to_cpu(phy_thr->thr);
break;
case QTN_TLV_ID_RTS_THRESH:
phy_thr = (void *)tlv;
-   mac_info->rts_thr = (u32)le16_to_cpu(phy_thr->thr);
+   mac_info->rts_thr = le32_to_cpu(phy_thr->thr);
break;
case QTN_TLV_ID_SRETRY_LIMIT:
limit = (void *)tlv;
@@ -1816,10 +1816,10 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac 
*mac, u32 changed)
qtnf_bus_lock(mac->bus);
 
if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
-   qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_FRAG_THRESH,
+   qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_FRAG_THRESH,
 wiphy->frag_threshold);
if (changed & WIPHY_PARAM_RTS_THRESHOLD)
-   qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_RTS_THRESH,
+   qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_RTS_THRESH,
 wiphy->rts_threshold);
if (changed & WIPHY_PARAM_COVERAGE_CLASS)
qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index a78cb9e05068..ace52e9d421d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -19,7 +19,7 @@
 
 #include 
 
-#define QLINK_PROTO_VER11
+#define QLINK_PROTO_VER12
 
 #define QLINK_MACID_RSVD   0xFF
 #define QLINK_VIFID_RSVD   0xFF
@@ -1184,7 +1184,7 @@ struct qlink_iface_limit_record {
 
 struct qlink_tlv_frag_rts_thr {
struct qlink_tlv_hdr hdr;
-   __le16 thr;
+   __le32 thr;
 } __packed;
 
 struct qlink_tlv_rlimit {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
index 960d5d97492f..fc87827cb49c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -69,6 +69,17 @@ static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff 
*skb,
memcpy(hdr->val, &tmp, sizeof(tmp));
 }
 
+static inline void qtnf_cmd_skb_put_tlv_u32(struct sk_buff *skb,
+   u16 tlv_id, u32 value)
+{
+   struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + sizeof(value));
+   __le32 tmp = cpu_to_le32(value);
+
+   hdr->type = cpu_to_le16(tlv_id);
+   hdr->len = cpu_to_le16(sizeof(value));
+   memcpy(hdr->val, &tmp, sizeof(tmp));
+}
+
 u16 qlink_iface_type_to_nl_mask(u16 qlink_type);
 u8 qlink_chan_width_mask_to_nl(u16 qlink_mask);
 void qlink_chandef_q2cfg(struct wiphy *wiphy,
-- 
2.11.0



[PATCH v2 5/9] qtnfmac: do not reject retry changes in driver

2019-01-14 Thread Sergey Matyukevich
Do not reject RETRY changes in driver. This decision
should belong to firmware.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 5 -
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 8 
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index a43f8120df3c..1b02096934f8 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -363,11 +363,6 @@ static int qtnf_set_wiphy_params(struct wiphy *wiphy, u32 
changed)
return -EFAULT;
}
 
-   if (changed & (WIPHY_PARAM_RETRY_LONG | WIPHY_PARAM_RETRY_SHORT)) {
-   pr_err("MAC%u: can't modify retry params\n", mac->macid);
-   return -EOPNOTSUPP;
-   }
-
ret = qtnf_cmd_send_update_phy_params(mac, changed);
if (ret)
pr_err("MAC%u: failed to update PHY params\n", mac->macid);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 66cb05dfdba5..3f0a0b6abf01 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1825,6 +1825,14 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac 
*mac, u32 changed)
qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
wiphy->coverage_class);
 
+   if (changed & WIPHY_PARAM_RETRY_LONG)
+   qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT,
+   wiphy->retry_long);
+
+   if (changed & WIPHY_PARAM_RETRY_SHORT)
+   qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT,
+   wiphy->retry_short);
+
ret = qtnf_cmd_send(mac->bus, cmd_skb);
if (ret)
goto out;
-- 
2.11.0



[PATCH v2 6/9] qtnfmac: convert to SPDX license identifiers

2019-01-14 Thread Sergey Matyukevich
Replace textual license with SPDX-License-Identifier.
Add an SPDX-License-Identifier for the Makefile.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/Makefile   |  1 +
 drivers/net/wireless/quantenna/qtnfmac/bus.h  | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.h | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 16 ++--
 drivers/net/wireless/quantenna/qtnfmac/commands.h | 16 ++--
 drivers/net/wireless/quantenna/qtnfmac/core.c | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/core.h | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/debug.c| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/debug.h| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/event.c| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/event.h| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/qlink_util.c   | 16 ++--
 drivers/net/wireless/quantenna/qtnfmac/qlink_util.h   | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h   | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c  | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h  | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/trans.c| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/trans.h| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/util.c | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/util.h | 17 ++---
 23 files changed, 45 insertions(+), 327 deletions(-)

diff --git a/drivers/net/wireless/quantenna/Makefile 
b/drivers/net/wireless/quantenna/Makefile
index baebfbde119e..cea83d178d2e 100644
--- a/drivers/net/wireless/quantenna/Makefile
+++ b/drivers/net/wireless/quantenna/Makefile
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Copyright (c) 2015-2016 Quantenna Communications, Inc.
 # All rights reserved.
diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h 
b/drivers/net/wireless/quantenna/qtnfmac/bus.h
index 528ca7f5e070..7bd906cc7023 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/bus.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015 Quantenna Communications
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015 Quantenna Communications. All rights reserved. */
 
 #ifndef QTNFMAC_BUS_H
 #define QTNFMAC_BUS_H
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 1b02096934f8..45f4cef7de9c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012-2012 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
 
 #include 
 #include 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
index b73425122a10..c374857283ac 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * This 

[PATCH v2 9/9] qtnfmac: qtnf_cmd_send_with_reply cleanup

2019-01-14 Thread Sergey Matyukevich
Use existing variable with dereferenced cmd_id field.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 009a4e4f4c7a..9b3019b0f108 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -87,14 +87,12 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
vif_id = cmd->vifid;
cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
 
-   pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id,
-le16_to_cpu(cmd->cmd_id));
+   pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, cmd_id);
 
if (bus->fw_state != QTNF_FW_STATE_ACTIVE &&
-   le16_to_cpu(cmd->cmd_id) != QLINK_CMD_FW_INIT) {
+   cmd_id != QLINK_CMD_FW_INIT) {
pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n",
-   mac_id, vif_id, le16_to_cpu(cmd->cmd_id),
-   bus->fw_state);
+   mac_id, vif_id, cmd_id, bus->fw_state);
dev_kfree_skb(cmd_skb);
return -ENODEV;
}
@@ -128,7 +126,7 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
return qtnf_cmd_resp_result_decode(le16_to_cpu(resp->result));
 
pr_warn("VIF%u.%u: cmd 0x%.4X failed: %d\n",
-   mac_id, vif_id, le16_to_cpu(cmd->cmd_id), ret);
+   mac_id, vif_id, cmd_id, ret);
 
return ret;
 }
-- 
2.11.0



[PATCH v2 3/9] qtnfmac: add support for 4addr mode

2019-01-14 Thread Sergey Matyukevich
Advertise WIPHY_FLAG_4ADDR_STATION capability to wireless core. Send
use4addr interface change flag to firmware in change_virtual_intf
cfg80211 callback.

In order to enable adding wireless station interface to bridge
one should turn on 4addr mode using the following command:
$ iw dev wlan0 set 4addr on
$ brctl addif br0 wlan0

If this commands succeeds, then interface can be added to bridge.
Note that when wireless interface is added to bridge, wpa_supplicant
should be started with appropriate -b  parameter, e.g:
$ wpa_supplicant -Dnl80211 -iwlan0 -c/path/to/wpa.conf -b br0

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 21 +
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 14 +-
 drivers/net/wireless/quantenna/qtnfmac/commands.h |  6 --
 drivers/net/wireless/quantenna/qtnfmac/core.c |  4 +++-
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|  3 ++-
 5 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 51b33ec78fac..a43f8120df3c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -122,7 +122,8 @@ qtnf_change_virtual_intf(struct wiphy *wiphy,
 struct vif_params *params)
 {
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
-   u8 *mac_addr;
+   u8 *mac_addr = NULL;
+   int use4addr = 0;
int ret;
 
ret = qtnf_validate_iface_combinations(wiphy, vif, type);
@@ -132,14 +133,14 @@ qtnf_change_virtual_intf(struct wiphy *wiphy,
return ret;
}
 
-   if (params)
+   if (params) {
mac_addr = params->macaddr;
-   else
-   mac_addr = NULL;
+   use4addr = params->use_4addr;
+   }
 
qtnf_scan_done(vif->mac, true);
 
-   ret = qtnf_cmd_send_change_intf_type(vif, type, mac_addr);
+   ret = qtnf_cmd_send_change_intf_type(vif, type, use4addr, mac_addr);
if (ret) {
pr_err("VIF%u.%u: failed to change type to %d\n",
   vif->mac->macid, vif->vifid, type);
@@ -190,6 +191,7 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct 
wiphy *wiphy,
struct qtnf_wmac *mac;
struct qtnf_vif *vif;
u8 *mac_addr = NULL;
+   int use4addr = 0;
int ret;
 
mac = wiphy_priv(wiphy);
@@ -225,10 +227,12 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct 
wiphy *wiphy,
return ERR_PTR(-ENOTSUPP);
}
 
-   if (params)
+   if (params) {
mac_addr = params->macaddr;
+   use4addr = params->use_4addr;
+   }
 
-   ret = qtnf_cmd_send_add_intf(vif, type, mac_addr);
+   ret = qtnf_cmd_send_add_intf(vif, type, use4addr, mac_addr);
if (ret) {
pr_err("VIF%u.%u: failed to add VIF %pM\n",
   mac->macid, vif->vifid, mac_addr);
@@ -1107,7 +,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
WIPHY_FLAG_AP_UAPSD |
-   WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+   WIPHY_FLAG_HAS_CHANNEL_SWITCH |
+   WIPHY_FLAG_4ADDR_STATION;
wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index c2f085589f54..0748a756cc1c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -734,6 +734,7 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 
*sta_mac,
 
 static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
 enum nl80211_iftype iftype,
+int use4addr,
 u8 *mac_addr,
 enum qlink_cmd_type cmd_type)
 {
@@ -751,6 +752,7 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif 
*vif,
qtnf_bus_lock(vif->mac->bus);
 
cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
+   cmd->intf_info.use4addr = use4addr;
 
switch (iftype) {
case NL80211_IFTYPE_AP:
@@ -786,17 +788,19 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif 
*vif,
return ret;
 }
 
-int qtnf_cmd_send_add_intf(struct qtnf_vif *vif,
-  enum nl80211_iftype iftype, u8 *mac_addr)
+int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype,
+  int use4addr, u8 *

[PATCH v2 0/7] qtnfmac: fixes and minor enhancements

2019-01-14 Thread Sergey Matyukevich
Hello Kalle and all,

Here is the patch set with fixes and enhancements for qtnfmac driver.
The major changes include the following items:
- final conversion to SPDX license format
- 4addr mode support
- PCIe INTx fix

Regards,
Sergey

v1 -> v2:
- remove remaining textual license from cfg80211.h header
- fix smatch warning for 4addr mode patch
- queue two more trivial cleanup patches to the series


Andrey Shevchenko (1):
  qtnfmac: support EBUSY errcode for QLINK protocol

Sergey Matyukevich (8):
  qtnfmac: fix legacy PCIe interrupt handling
  qtnfmac: add support for 4addr mode
  qtnfmac: switch to 32bit values for RTS/FRAG thresholds
  qtnfmac: do not reject retry changes in driver
  qtnfmac: convert to SPDX license identifiers
  qtnfmac: add missing bss record to host scan cache
  qtnfmac: remove unused declarations
  qtnfmac: minor cleanup in qtnf_cmd_send_with_reply

 drivers/net/wireless/quantenna/Makefile|  1 +
 drivers/net/wireless/quantenna/qtnfmac/bus.h   | 19 +
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c  | 43 --
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.h  | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/commands.c  | 58 ++---
 drivers/net/wireless/quantenna/qtnfmac/commands.h  | 22 ++---
 drivers/net/wireless/quantenna/qtnfmac/core.c  | 21 ++---
 drivers/net/wireless/quantenna/qtnfmac/core.h  | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/debug.c | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/debug.h | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/event.c | 96 +-
 drivers/net/wireless/quantenna/qtnfmac/event.h | 17 +---
 .../wireless/quantenna/qtnfmac/pcie/topaz_pcie.c   |  6 +-
 drivers/net/wireless/quantenna/qtnfmac/qlink.h | 27 ++
 .../net/wireless/quantenna/qtnfmac/qlink_util.c| 16 +---
 .../net/wireless/quantenna/qtnfmac/qlink_util.h| 28 +++
 .../net/wireless/quantenna/qtnfmac/qtn_hw_ids.h| 17 +---
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c   | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h   | 17 +---
 .../net/wireless/quantenna/qtnfmac/shm_ipc_defs.h  | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/trans.c | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/trans.h | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/util.c  | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/util.h  | 17 +---
 24 files changed, 188 insertions(+), 370 deletions(-)

-- 
2.11.0



[PATCH v2 1/9] qtnfmac: support EBUSY errcode for QLINK protocol

2019-01-14 Thread Sergey Matyukevich
From: Andrey Shevchenko 

Add support of EBUSY error code for remote procedures over QLINK protocol.

Signed-off-by: Andrey Shevchenko 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 2 ++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 659e7649fe22..c2f085589f54 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -72,6 +72,8 @@ static int qtnf_cmd_resp_result_decode(enum qlink_cmd_result 
qcode)
return -EADDRINUSE;
case QLINK_CMD_RESULT_EADDRNOTAVAIL:
return -EADDRNOTAVAIL;
+   case QLINK_CMD_RESULT_EBUSY:
+   return -EBUSY;
default:
return -EFAULT;
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 8d62addea895..f9c7f87afaf8 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -733,6 +733,7 @@ enum qlink_cmd_result {
QLINK_CMD_RESULT_EALREADY,
QLINK_CMD_RESULT_EADDRINUSE,
QLINK_CMD_RESULT_EADDRNOTAVAIL,
+   QLINK_CMD_RESULT_EBUSY,
 };
 
 /**
-- 
2.11.0



[PATCH v2 2/9] qtnfmac: fix INTx interrupt handling

2019-01-14 Thread Sergey Matyukevich
In the current implementation INTx interrupt is deasserted after the
control path processing. However this may lead to missed interrupts
from the wireless card. For instance, this may happen as a result
of control path activity, when another interrupt arrives before
INTx is deasserted.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
index 598edb814421..cbcda57105f3 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
@@ -559,6 +559,9 @@ static irqreturn_t qtnf_pcie_topaz_interrupt(int irq, void 
*data)
if (!priv->msi_enabled && !qtnf_topaz_intx_asserted(ts))
return IRQ_NONE;
 
+   if (!priv->msi_enabled)
+   qtnf_deassert_intx(ts);
+
priv->pcie_irq_count++;
 
qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_in);
@@ -571,9 +574,6 @@ static irqreturn_t qtnf_pcie_topaz_interrupt(int irq, void 
*data)
 
tasklet_hi_schedule(&priv->reclaim_tq);
 
-   if (!priv->msi_enabled)
-   qtnf_deassert_intx(ts);
-
return IRQ_HANDLED;
 }
 
-- 
2.11.0



Re: [PATCH] mac80211: allow overriding HT STBC capabilities

2019-01-14 Thread Sergey Matyukevich
> From: Sergey Matyukevich 
> 
> Allow user to override STBC configuration for Rx and Tx spatial streams.
> In practice RX/TX STBC settings can be modified using appropriate
> options in wpa_supplicant configuration file:
>   tx_stbc=-1..1
>   rx_stbc=-1..3
> 
> This functionality has been added to wpa_supplicant in commit cdeea70f59d0.
> 
> In FullMAC case these STBC options are passed to drivers by cfg80211
> connect callback in fields of cfg80211_connect_params structure.
> However for mac80211 drivers, e.g. for mac80211_hwsim,
> overrides for STBC settings are ignored.

...

> Signed-off-by: Sergey Matyukevich 
> ---
>  net/mac80211/ht.c   | 8 
>  net/mac80211/main.c | 2 ++
>  2 files changed, 10 insertions(+)

FWIW, the accompanying RFC patch extending STBC tests in hwsim hostapd test
suite has been posted to hostapd mailing list:

http://lists.infradead.org/pipermail/hostap/2019-January/039274.html

Regards,
Sergey


Re: [PATCH 6/7] qtnfmac: convert to SPDX license identifiers

2019-01-10 Thread Sergey Matyukevich
Hello Kalle,

> Sergey Matyukevich  writes:
> 
> > Replace textual license with SPDX-License-Identifier.
> > Add an SPDX-License-Identifier for the Makefile.
> >
> > Signed-off-by: Sergey Matyukevich 
> 
> [...]
> 
> > --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
> > +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
> > @@ -1,3 +1,6 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. 
> > */
> > +
> >  /*
> >   * Copyright (c) 2015-2016 Quantenna Communications, Inc.
> >   * All rights reserved.
> 
> This doesn't look correct, please check.

Oh, I missed that one. Thanks for catching. All the other SPDX changes
looks ok. This issue is fixed and will be queued into v2 of this patch set.


Regards,
Sergey


[PATCH 3/7] qtnfmac: add support for 4addr mode

2019-01-09 Thread Sergey Matyukevich
Advertise WIPHY_FLAG_4ADDR_STATION capability to wireless core. Send
use4addr interface change flag to firmware in change_virtual_intf
cfg80211 callback.

In order to enable adding wireless station interface to bridge
one should turn on 4addr mode using the following command:
$ iw dev wlan0 set 4addr on
$ brctl addif br0 wlan0

If this commands succeeds, then interface can be added to bridge.
Note that when wireless interface is added to bridge, wpa_supplicant
should be started with appropriate -b  parameter, e.g:
$ wpa_supplicant -Dnl80211 -iwlan0 -c/path/to/wpa_s.conf -b br0

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |  8 +---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 14 +-
 drivers/net/wireless/quantenna/qtnfmac/commands.h |  6 --
 drivers/net/wireless/quantenna/qtnfmac/core.c |  4 +++-
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|  3 ++-
 5 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 51b33ec78fac..9e0ac1744be7 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -139,7 +139,8 @@ qtnf_change_virtual_intf(struct wiphy *wiphy,
 
qtnf_scan_done(vif->mac, true);
 
-   ret = qtnf_cmd_send_change_intf_type(vif, type, mac_addr);
+   ret = qtnf_cmd_send_change_intf_type(vif, type, params->use_4addr,
+mac_addr);
if (ret) {
pr_err("VIF%u.%u: failed to change type to %d\n",
   vif->mac->macid, vif->vifid, type);
@@ -228,7 +229,7 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct 
wiphy *wiphy,
if (params)
mac_addr = params->macaddr;
 
-   ret = qtnf_cmd_send_add_intf(vif, type, mac_addr);
+   ret = qtnf_cmd_send_add_intf(vif, type, params->use_4addr, mac_addr);
if (ret) {
pr_err("VIF%u.%u: failed to add VIF %pM\n",
   mac->macid, vif->vifid, mac_addr);
@@ -1107,7 +1108,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
WIPHY_FLAG_AP_UAPSD |
-   WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+   WIPHY_FLAG_HAS_CHANNEL_SWITCH |
+   WIPHY_FLAG_4ADDR_STATION;
wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index c2f085589f54..0748a756cc1c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -734,6 +734,7 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 
*sta_mac,
 
 static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
 enum nl80211_iftype iftype,
+int use4addr,
 u8 *mac_addr,
 enum qlink_cmd_type cmd_type)
 {
@@ -751,6 +752,7 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif 
*vif,
qtnf_bus_lock(vif->mac->bus);
 
cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
+   cmd->intf_info.use4addr = use4addr;
 
switch (iftype) {
case NL80211_IFTYPE_AP:
@@ -786,17 +788,19 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif 
*vif,
return ret;
 }
 
-int qtnf_cmd_send_add_intf(struct qtnf_vif *vif,
-  enum nl80211_iftype iftype, u8 *mac_addr)
+int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype,
+  int use4addr, u8 *mac_addr)
 {
-   return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr,
+   return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
QLINK_CMD_ADD_INTF);
 }
 
 int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
-  enum nl80211_iftype iftype, u8 *mac_addr)
+  enum nl80211_iftype iftype,
+  int use4addr,
+  u8 *mac_addr)
 {
-   return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr,
+   return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr,
 QLINK_CMD_CHANGE_INTF);
 }
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h 
b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index 1ac41156c192..1c25e7905e9a 100644
--- a/drivers/net/wireless/quantenn

[PATCH 6/7] qtnfmac: convert to SPDX license identifiers

2019-01-09 Thread Sergey Matyukevich
Replace textual license with SPDX-License-Identifier.
Add an SPDX-License-Identifier for the Makefile.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/Makefile   |  1 +
 drivers/net/wireless/quantenna/qtnfmac/bus.h  | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.h |  3 +++
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 16 ++--
 drivers/net/wireless/quantenna/qtnfmac/commands.h | 16 ++--
 drivers/net/wireless/quantenna/qtnfmac/core.c | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/core.h | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/debug.c| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/debug.h| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/event.c| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/event.h| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/qlink_util.c   | 16 ++--
 drivers/net/wireless/quantenna/qtnfmac/qlink_util.h   | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h   | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c  | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h  | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/trans.c| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/trans.h| 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/util.c | 17 ++---
 drivers/net/wireless/quantenna/qtnfmac/util.h | 17 ++---
 23 files changed, 46 insertions(+), 312 deletions(-)

diff --git a/drivers/net/wireless/quantenna/Makefile 
b/drivers/net/wireless/quantenna/Makefile
index baebfbde119e..cea83d178d2e 100644
--- a/drivers/net/wireless/quantenna/Makefile
+++ b/drivers/net/wireless/quantenna/Makefile
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Copyright (c) 2015-2016 Quantenna Communications, Inc.
 # All rights reserved.
diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h 
b/drivers/net/wireless/quantenna/qtnfmac/bus.h
index 528ca7f5e070..7bd906cc7023 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/bus.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015 Quantenna Communications
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015 Quantenna Communications. All rights reserved. */
 
 #ifndef QTNFMAC_BUS_H
 #define QTNFMAC_BUS_H
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 422b79a5b98d..e9bef621a7d6 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012-2012 Quantenna Communications, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
 
 #include 
 #include 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
index b73425122a10..7f223d0fbbd3 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
@@ -1,3 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2015-2016 Quantenna Communications. All right

[PATCH 7/7] qtnfmac: add missing bss record to host scan cache

2019-01-09 Thread Sergey Matyukevich
Make sure that valid BSS entry exists in wireless core scan records
even in the case of successful connect reported by firmware.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/event.c | 79 --
 drivers/net/wireless/quantenna/qtnfmac/qlink.h |  4 +-
 2 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c 
b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 3038a000c287..3fd1a9217737 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -145,6 +145,12 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
   const struct qlink_event_bss_join *join_info,
   u16 len)
 {
+   struct wiphy *wiphy = priv_to_wiphy(vif->mac);
+   enum ieee80211_statuscode status = le16_to_cpu(join_info->status);
+   struct cfg80211_chan_def chandef;
+   struct cfg80211_bss *bss = NULL;
+   u8 *ie = NULL;
+
if (unlikely(len < sizeof(*join_info))) {
pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
   vif->mac->macid, vif->vifid, len,
@@ -158,15 +164,80 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
return -EPROTO;
}
 
-   pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid,
-join_info->bssid);
+   pr_debug("VIF%u.%u: BSSID:%pM status:%u\n",
+vif->mac->macid, vif->vifid, join_info->bssid, status);
+
+   if (status == WLAN_STATUS_SUCCESS) {
+   qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef);
+   if (!cfg80211_chandef_valid(&chandef)) {
+   pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u 
bw=%u\n",
+   vif->mac->macid, vif->vifid,
+   chandef.chan->center_freq,
+   chandef.center_freq1,
+   chandef.center_freq2,
+   chandef.width);
+   status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+   goto done;
+   }
 
+   bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid,
+  NULL, 0, IEEE80211_BSS_TYPE_ESS,
+  IEEE80211_PRIVACY_ANY);
+   if (!bss) {
+   pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n",
+   vif->mac->macid, vif->vifid,
+   join_info->bssid, chandef.chan->hw_value);
+
+   if (!vif->wdev.ssid_len) {
+   pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n",
+   vif->mac->macid, vif->vifid,
+   join_info->bssid);
+   status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+   goto done;
+   }
+
+   ie = kzalloc(2 + vif->wdev.ssid_len, GFP_KERNEL);
+   if (!ie) {
+   pr_warn("VIF%u.%u: IE alloc failed for 
BSS:%pM\n",
+   vif->mac->macid, vif->vifid,
+   join_info->bssid);
+   status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+   goto done;
+   }
+
+   ie[0] = WLAN_EID_SSID;
+   ie[1] = vif->wdev.ssid_len;
+   memcpy(ie + 2, vif->wdev.ssid, vif->wdev.ssid_len);
+
+   bss = cfg80211_inform_bss(wiphy, chandef.chan,
+ CFG80211_BSS_FTYPE_UNKNOWN,
+ join_info->bssid, 0,
+ WLAN_CAPABILITY_ESS, 100,
+ ie, 2 + vif->wdev.ssid_len,
+ 0, GFP_KERNEL);
+   if (!bss) {
+   pr_warn("VIF%u.%u: can't connect to unknown 
BSS: %pM\n",
+   vif->mac->macid, vif->vifid,
+   join_info->bssid);
+   status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+   goto done;
+   }
+   }
+   }
+
+done:
cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL,
-   0, le16_to_cpu(join_info->status), GFP_KERNEL);
+ 

[PATCH 5/7] qtnfmac: do not reject retry changes in driver

2019-01-09 Thread Sergey Matyukevich
Do not reject RETRY changes in driver. This decision
should belong to firmware.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 5 -
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 8 
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 9e0ac1744be7..422b79a5b98d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -360,11 +360,6 @@ static int qtnf_set_wiphy_params(struct wiphy *wiphy, u32 
changed)
return -EFAULT;
}
 
-   if (changed & (WIPHY_PARAM_RETRY_LONG | WIPHY_PARAM_RETRY_SHORT)) {
-   pr_err("MAC%u: can't modify retry params\n", mac->macid);
-   return -EOPNOTSUPP;
-   }
-
ret = qtnf_cmd_send_update_phy_params(mac, changed);
if (ret)
pr_err("MAC%u: failed to update PHY params\n", mac->macid);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 66cb05dfdba5..3f0a0b6abf01 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1825,6 +1825,14 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac 
*mac, u32 changed)
qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
wiphy->coverage_class);
 
+   if (changed & WIPHY_PARAM_RETRY_LONG)
+   qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT,
+   wiphy->retry_long);
+
+   if (changed & WIPHY_PARAM_RETRY_SHORT)
+   qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT,
+   wiphy->retry_short);
+
ret = qtnf_cmd_send(mac->bus, cmd_skb);
if (ret)
goto out;
-- 
2.11.0



[PATCH 4/7] qtnfmac: switch to 32bit values for RTS/FRAG thresholds

2019-01-09 Thread Sergey Matyukevich
Host wireless stack uses u32 type for RTS/FRAG threshold values.
Switch to u32 in driver: pass u32 values to firmware and let
firmware properly adapt these values according to its
internal representation.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c   |  8 
 drivers/net/wireless/quantenna/qtnfmac/qlink.h  |  4 ++--
 drivers/net/wireless/quantenna/qtnfmac/qlink_util.h | 11 +++
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 0748a756cc1c..66cb05dfdba5 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1564,11 +1564,11 @@ static int qtnf_cmd_resp_proc_phy_params(struct 
qtnf_wmac *mac,
switch (tlv_type) {
case QTN_TLV_ID_FRAG_THRESH:
phy_thr = (void *)tlv;
-   mac_info->frag_thr = (u32)le16_to_cpu(phy_thr->thr);
+   mac_info->frag_thr = le32_to_cpu(phy_thr->thr);
break;
case QTN_TLV_ID_RTS_THRESH:
phy_thr = (void *)tlv;
-   mac_info->rts_thr = (u32)le16_to_cpu(phy_thr->thr);
+   mac_info->rts_thr = le32_to_cpu(phy_thr->thr);
break;
case QTN_TLV_ID_SRETRY_LIMIT:
limit = (void *)tlv;
@@ -1816,10 +1816,10 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac 
*mac, u32 changed)
qtnf_bus_lock(mac->bus);
 
if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
-   qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_FRAG_THRESH,
+   qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_FRAG_THRESH,
 wiphy->frag_threshold);
if (changed & WIPHY_PARAM_RTS_THRESHOLD)
-   qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_RTS_THRESH,
+   qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_RTS_THRESH,
 wiphy->rts_threshold);
if (changed & WIPHY_PARAM_COVERAGE_CLASS)
qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index a78cb9e05068..ace52e9d421d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -19,7 +19,7 @@
 
 #include 
 
-#define QLINK_PROTO_VER11
+#define QLINK_PROTO_VER12
 
 #define QLINK_MACID_RSVD   0xFF
 #define QLINK_VIFID_RSVD   0xFF
@@ -1184,7 +1184,7 @@ struct qlink_iface_limit_record {
 
 struct qlink_tlv_frag_rts_thr {
struct qlink_tlv_hdr hdr;
-   __le16 thr;
+   __le32 thr;
 } __packed;
 
 struct qlink_tlv_rlimit {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
index 960d5d97492f..fc87827cb49c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -69,6 +69,17 @@ static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff 
*skb,
memcpy(hdr->val, &tmp, sizeof(tmp));
 }
 
+static inline void qtnf_cmd_skb_put_tlv_u32(struct sk_buff *skb,
+   u16 tlv_id, u32 value)
+{
+   struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + sizeof(value));
+   __le32 tmp = cpu_to_le32(value);
+
+   hdr->type = cpu_to_le16(tlv_id);
+   hdr->len = cpu_to_le16(sizeof(value));
+   memcpy(hdr->val, &tmp, sizeof(tmp));
+}
+
 u16 qlink_iface_type_to_nl_mask(u16 qlink_type);
 u8 qlink_chan_width_mask_to_nl(u16 qlink_mask);
 void qlink_chandef_q2cfg(struct wiphy *wiphy,
-- 
2.11.0



[PATCH 2/7] qtnfmac: fix legacy PCIe interrupt handling

2019-01-09 Thread Sergey Matyukevich
In the current implementation INTx interrupt is deasserted after the
control path processing. However this leads to missed interrupts
from the wireless card. For instance, this may happen as a result
of control path activity, when another interrupt arrives before
INTx is deasserted.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
index 598edb814421..cbcda57105f3 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
@@ -559,6 +559,9 @@ static irqreturn_t qtnf_pcie_topaz_interrupt(int irq, void 
*data)
if (!priv->msi_enabled && !qtnf_topaz_intx_asserted(ts))
return IRQ_NONE;
 
+   if (!priv->msi_enabled)
+   qtnf_deassert_intx(ts);
+
priv->pcie_irq_count++;
 
qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_in);
@@ -571,9 +574,6 @@ static irqreturn_t qtnf_pcie_topaz_interrupt(int irq, void 
*data)
 
tasklet_hi_schedule(&priv->reclaim_tq);
 
-   if (!priv->msi_enabled)
-   qtnf_deassert_intx(ts);
-
return IRQ_HANDLED;
 }
 
-- 
2.11.0



[PATCH 0/7] qtnfmac: fixes and minor enhancements

2019-01-09 Thread Sergey Matyukevich
Hello Kalle and all,

Here is the patch set with fixes and enhancements for qtnfmac driver.
The major changes include the following items:
- final conversion to SPDX license format
- 4addr mode support
- PCIe INTx fix

Regards,
Sergey


Andrey Shevchenko (1):
  qtnfmac: support EBUSY errcode for QLINK protocol

Sergey Matyukevich (6):
  qtnfmac: fix legacy PCIe interrupt handling
  qtnfmac: add support for 4addr mode
  qtnfmac: switch to 32bit values for RTS/FRAG thresholds
  qtnfmac: do not reject retry changes in driver
  qtnfmac: convert to SPDX license identifiers
  qtnfmac: add missing bss record to host scan cache

 drivers/net/wireless/quantenna/Makefile|  1 +
 drivers/net/wireless/quantenna/qtnfmac/bus.h   | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c  | 30 ++-
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.h  |  3 +
 drivers/net/wireless/quantenna/qtnfmac/commands.c  | 48 +--
 drivers/net/wireless/quantenna/qtnfmac/commands.h  | 22 ++---
 drivers/net/wireless/quantenna/qtnfmac/core.c  | 21 ++---
 drivers/net/wireless/quantenna/qtnfmac/core.h  | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/debug.c | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/debug.h | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/event.c | 96 +-
 drivers/net/wireless/quantenna/qtnfmac/event.h | 17 +---
 .../wireless/quantenna/qtnfmac/pcie/topaz_pcie.c   |  6 +-
 drivers/net/wireless/quantenna/qtnfmac/qlink.h | 27 ++
 .../net/wireless/quantenna/qtnfmac/qlink_util.c| 16 +---
 .../net/wireless/quantenna/qtnfmac/qlink_util.h| 28 +++
 .../net/wireless/quantenna/qtnfmac/qtn_hw_ids.h| 17 +---
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c   | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h   | 17 +---
 .../net/wireless/quantenna/qtnfmac/shm_ipc_defs.h  | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/trans.c | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/trans.h | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/util.c  | 17 +---
 drivers/net/wireless/quantenna/qtnfmac/util.h  | 17 +---
 24 files changed, 177 insertions(+), 342 deletions(-)

-- 
2.11.0



[PATCH 1/7] qtnfmac: support EBUSY errcode for QLINK protocol

2019-01-09 Thread Sergey Matyukevich
From: Andrey Shevchenko 

Add support of EBUSY error code for remote procedures over QLINK protocol.

Signed-off-by: Andrey Shevchenko 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 2 ++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 659e7649fe22..c2f085589f54 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -72,6 +72,8 @@ static int qtnf_cmd_resp_result_decode(enum qlink_cmd_result 
qcode)
return -EADDRINUSE;
case QLINK_CMD_RESULT_EADDRNOTAVAIL:
return -EADDRNOTAVAIL;
+   case QLINK_CMD_RESULT_EBUSY:
+   return -EBUSY;
default:
return -EFAULT;
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 8d62addea895..f9c7f87afaf8 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -733,6 +733,7 @@ enum qlink_cmd_result {
QLINK_CMD_RESULT_EALREADY,
QLINK_CMD_RESULT_EADDRINUSE,
QLINK_CMD_RESULT_EADDRNOTAVAIL,
+   QLINK_CMD_RESULT_EBUSY,
 };
 
 /**
-- 
2.11.0



Re: [PATCH] qtnfmac: use struct_size() in kzalloc()

2019-01-09 Thread Sergey Matyukevich
> One of the more common cases of allocation size calculations is finding the
> size of a structure that has a zero-sized array at the end, along with memory
> for some number of elements for that array. For example:
> 
> struct foo {
> int stuff;
> void *entry[];
> };

...

> Signed-off-by: Gustavo A. R. Silva 
> ---
>  drivers/net/wireless/quantenna/qtnfmac/commands.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
> b/drivers/net/wireless/quantenna/qtnfmac/commands.c
> index 659e7649fe22..cf386f579060 100644
> --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
> +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
> @@ -914,9 +914,8 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
> if (WARN_ON(resp->n_reg_rules > NL80211_MAX_SUPP_REG_RULES))
> return -E2BIG;
> 
> -   hwinfo->rd = kzalloc(sizeof(*hwinfo->rd)
> -+ sizeof(struct ieee80211_reg_rule)
> -* resp->n_reg_rules, GFP_KERNEL);
> +   hwinfo->rd = kzalloc(struct_size(hwinfo->rd, reg_rules,
> +resp->n_reg_rules), GFP_KERNEL);
> 
> if (!hwinfo->rd)
> return -ENOMEM;

Thanks!

Reviewed-by: Sergey Matyukevich 

Regards,
Sergey


[PATCH] mac80211: allow overriding HT STBC capabilities

2019-01-08 Thread Sergey Matyukevich
From: Sergey Matyukevich 

Allow user to override STBC configuration for Rx and Tx spatial streams.
In practice RX/TX STBC settings can be modified using appropriate
options in wpa_supplicant configuration file:
  tx_stbc=-1..1
  rx_stbc=-1..3

This functionality has been added to wpa_supplicant in commit cdeea70f59d0.

In FullMAC case these STBC options are passed to drivers by cfg80211
connect callback in fields of cfg80211_connect_params structure.
However for mac80211 drivers, e.g. for mac80211_hwsim,
overrides for STBC settings are ignored.

The reason why RX/TX STBC capabilities are not modified for mac80211
drivers is as follows. All drivers need to specify supported HT/VHT
overrides explicitly: see ht_capa_mod_mask and vht_capa_mod_mask fields
of wiphy structure. Only supported overrides will be passed to drivers by
cfg80211_connect and cfg80211_mlme_assoc operations: see bitwise 'AND'
performed by cfg80211_oper_and_ht_capa and cfg80211_oper_and_vht_capa.

This commit adds RX/TX STBC HT capabilities to mac80211_ht_capa_mod_mask,
allowing their modifications, as well as applies requested STBC
modifications in function ieee80211_apply_htcap_overrides.

Signed-off-by: Sergey Matyukevich 
---
 net/mac80211/ht.c   | 8 
 net/mac80211/main.c | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index f849ea814993..e03c46ac8e4d 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -107,6 +107,14 @@ void ieee80211_apply_htcap_overrides(struct 
ieee80211_sub_if_data *sdata,
__check_htcap_enable(ht_capa, ht_capa_mask, ht_cap,
 IEEE80211_HT_CAP_40MHZ_INTOLERANT);
 
+   /* Allow user to enable TX STBC bit  */
+   __check_htcap_enable(ht_capa, ht_capa_mask, ht_cap,
+IEEE80211_HT_CAP_TX_STBC);
+
+   /* Allow user to configure RX STBC bits */
+   if (ht_capa_mask->cap_info & IEEE80211_HT_CAP_RX_STBC)
+   ht_cap->cap |= ht_capa->cap_info & IEEE80211_HT_CAP_RX_STBC;
+
/* Allow user to decrease AMPDU factor */
if (ht_capa_mask->ampdu_params_info &
IEEE80211_HT_AMPDU_PARM_FACTOR) {
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 87a729926734..1114ee217bd6 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -478,6 +478,8 @@ static const struct ieee80211_ht_cap 
mac80211_ht_capa_mod_mask = {
IEEE80211_HT_CAP_MAX_AMSDU |
IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40 |
+   IEEE80211_HT_CAP_TX_STBC |
+   IEEE80211_HT_CAP_RX_STBC |
IEEE80211_HT_CAP_LDPC_CODING |
IEEE80211_HT_CAP_40MHZ_INTOLERANT),
.mcs = {
-- 
2.20.1



Re: [RFC PATCH v1] cfg80211/nl80211: add support for AID assignment by driver

2018-12-19 Thread Sergey Matyukevich
Hi,

> Add support for getting and free association ID if the station
> association ID management handled by the WLAN driver/firmware.
> 
> Add cfg80211 driver ops and nl80211 API and CMD to request
> the WLAN driver to assign an AID for a station during association
> and release the AID of the station from the WLAN driver/firmware
> station database on disassociation from the AP.
> 
> Signed-off-by: Sarada Prasanna Garnayak 
> ---
>  include/net/cfg80211.h   | 12 +++
>  include/uapi/linux/nl80211.h | 11 +++
>  net/wireless/nl80211.c   | 74 
> 
>  net/wireless/rdev-ops.h  | 22 +
>  net/wireless/trace.h | 36 +
>  5 files changed, 155 insertions(+)

Could you please clarify the use-cases for this feature and its potential
users ? Besides, why existing nl80211_set_station can't be used ? It turns
out that there exists station AID field among numerous
'struct station_parameters' fields.

Regards,
Sergey


Re: question: ip forwarding and fq/mq qdisc

2018-12-14 Thread Sergey Matyukevich
> > Hi all,
> > 
> > I have been running 4.18-rc8 kernel with enabled IP forwarding between
> > wired and wireless interfaces, where both interfaces
> > were configured as fq qdisc.
> > 
> > However after moving to 4.20-rc1 kernel the same configuration does not
> > work anymore: pass-through packets are not forwarded in both directions.
> > Forwarding starts working again only if I change qdisc of _both_ interfaces
> > to anything but fq/mq. For instance any combination of 
> > pfifo/fq_codel/noqueue
> > works fine.
> > 
> > Does it look like a regression or it is a known change in behavior ?
> > 
> > Regards,
> > Sergey
> > 
> 
> Hi Sergey
> 
> I guess EDT model broke this use case.
> 
> I was under the impression skb->tstamp was cleared when forwarding packets, 
> maybe I was wrong.
> 
> Can you try the following ?
> 
> diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
> index 
> 06ee4696703c0ce72ea914403b739839e60f1584..00ec819f949b5e76ea96be901a697f4e12d5cf4d
>  100644
> --- a/net/ipv4/ip_forward.c
> +++ b/net/ipv4/ip_forward.c
> @@ -79,6 +79,7 @@ static int ip_forward_finish(struct net *net, struct sock 
> *sk, struct sk_buff *s
> if (unlikely(opt->optlen))
> ip_forward_options(skb);
>  
> +   skb->tstamp = 0;
> return dst_output(net, sk, skb);
>  }

Hi Eric,

This patch fixes the issue: ip forwarding works for fq/mq qdisc.

Thanks,
Sergey


question: ip forwarding and fq/mq qdisc

2018-12-14 Thread Sergey Matyukevich
Hi all,

I have been running 4.18-rc8 kernel with enabled IP forwarding between
wired and wireless interfaces, where both interfaces
were configured as fq qdisc.

However after moving to 4.20-rc1 kernel the same configuration does not
work anymore: pass-through packets are not forwarded in both directions.
Forwarding starts working again only if I change qdisc of _both_ interfaces
to anything but fq/mq. For instance any combination of pfifo/fq_codel/noqueue
works fine.

Does it look like a regression or it is a known change in behavior ?

Regards,
Sergey


Re: [PATCH 1/4] New netlink command for TID specific configuration

2018-11-09 Thread Sergey Matyukevich
Hello Tamizh,

> > > Co-Developed-by: Tamizh Chelvam 
> > > Signed-off-by: Vasanthakumar Thiagarajan 
> > > Signed-off-by: Tamizh chelvam 
> > > ---
> > >  include/net/cfg80211.h   |   14 +++
> > >  include/uapi/linux/nl80211.h |   69 +
> > >  net/wireless/nl80211.c   |   86
> > > ++
> > >  net/wireless/rdev-ops.h  |   15 
> > >  net/wireless/trace.h |   27 +
> > >  5 files changed, 211 insertions(+)

...

> > >  /**
> > > @@ -4035,6 +4044,9 @@ struct wiphy_iftype_ext_capab {
> > >   * @txq_limit: configuration of internal TX queue frame limit
> > >   * @txq_memory_limit: configuration internal TX queue memory limit
> > >   * @txq_quantum: configuration of internal TX queue scheduler quantum
> > > + *
> > > + * @max_data_retry_count: Maximum limit can be configured as retry
> > > count
> > > + * for a TID.
> > >   */
> > >  struct wiphy {
> > > /* assign these fields before you register the wiphy */
> > > @@ -4171,6 +4183,8 @@ struct wiphy {
> > > u32 txq_memory_limit;
> > > u32 txq_quantum;
> > > 
> > > +   u8 max_data_retry_count;
> > > +
> > > char priv[0] __aligned(NETDEV_ALIGN);
> > >  };
> > 
> > Could you please clarify why do you define max_data_retry_count instead
> > of
> > making use of existing wiphy params: retry_short (dot11ShortRetryLimit)
> > and retry_long (dot11LongRetryLimit) ?
> 
> max_data_retry_count added to validate the max limit for the retry count
> supported by the driver.
> existing wiphy parames: retry_short and retry_long can be modified
> through user command.
> So, I've added this param for validation purpose. Correct me If I'm
> wrong.

Well, but then it probably makes sense to use max_data_retry_count value
to validate retry_short and retry_long values in nl80211_set_wiphy.

Regards,
Sergey


Re: [PATCH 1/4] New netlink command for TID specific configuration

2018-11-09 Thread Sergey Matyukevich
Hello Tamizh,

...

> > > +static int nl80211_set_tid_config(struct sk_buff *skb,
> > > + struct genl_info *info)
> > > +{
> > > +   struct cfg80211_registered_device *rdev = info->user_ptr[0];
> > > +   struct nlattr *attrs[NL80211_ATTR_TID_MAX + 1];
> > > +   struct nlattr *tid;
> > > +   struct net_device *dev = info->user_ptr[1];
> > > +   const char *peer = NULL;
> > > +   u8 tid_no;
> > > +   int ret = -EINVAL, retry_short = -1, retry_long = -1;
> > > +
> > > +   tid = info->attrs[NL80211_ATTR_TID_CONFIG];
> > > +   if (!tid)
> > > +   return -EINVAL;
> > > +
> > > +   ret = nla_parse_nested(attrs, NL80211_ATTR_TID_MAX, tid,
> > > +  nl80211_attr_tid_policy, info->extack);
> > > +   if (ret)
> > > +   return ret;
> > > +
> > > +   if (!attrs[NL80211_ATTR_TID])
> > > +   return -EINVAL;
> > > +
> > > +   if (attrs[NL80211_ATTR_TID_RETRY_SHORT]) {
> > > +   retry_short =
> > > nla_get_u8(attrs[NL80211_ATTR_TID_RETRY_SHORT]);
> > > +   if (!retry_short ||
> > > +   retry_short > rdev->wiphy.max_data_retry_count)
> > > +   return -EINVAL;
> > > +   }
> > > +
> > > +   if (attrs[NL80211_ATTR_TID_RETRY_LONG]) {
> > > +   retry_long =
> > > nla_get_u8(attrs[NL80211_ATTR_TID_RETRY_LONG]);
> > > +   if (!retry_long ||
> > > +   retry_long > rdev->wiphy.max_data_retry_count)
> > > +   return -EINVAL;
> > > +   }
> > > +
> > > +   tid_no = nla_get_u8(attrs[NL80211_ATTR_TID]);
> > > +   if (tid_no >= IEEE80211_FIRST_TSPEC_TSID)
> > > +   return -EINVAL;
> > > +
> > > +   if (info->attrs[NL80211_ATTR_MAC])
> > > +   peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
> > > +
> > > +   if (nla_get_flag(attrs[NL80211_ATTR_TID_RETRY_CONFIG])) {
> > 
> > Do we really need this additional flag to indicate retry data ?
> > Maybe we can simply check retry attrs or even retry data, e.g.:
> 
> Yes, because this implementation gives provision to set default retry
> count for TID traffic type for a station.
> Since we use single NL command for all TID configurations, this flag
> will be useful to notify the driver about
> retry TID configuration change.

Ok. So if driver receives retry value (-1), it should reset to some
default value known to driver or firmware. IMHO it worth making it
more explicit: in its current form this convention will not be obvious
for driver authors. Though I don't have a good idea how to do it.
Maybe merge both aggregation and retry cfg80211 callbacks into one
and use structure for params and bitmask for operations...

> > 
> > if (attrs[NL80211_ATTR_TID_RETRY_LONG] ||
> > attrs[NL80211_ATTR_TID_RETRY_SHORT]) {
> > ...
> > 
> > if ((retry_short > 0) || (retry_long > 0)) {
> > ...

Regards,
Sergey


Re: [PATCH 4/4] ath10k: Add support to configure TID specific configuration

2018-11-09 Thread Sergey Matyukevich


Hello Tamizh,

> Signed-off-by: Tamizh chelvam 
> ---
>  drivers/net/wireless/ath/ath10k/core.h |  23 
>  drivers/net/wireless/ath/ath10k/mac.c  | 240 
> +
>  drivers/net/wireless/ath/ath10k/wmi.c  |   6 +-
>  drivers/net/wireless/ath/ath10k/wmi.h  |   1 +
>  4 files changed, 245 insertions(+), 25 deletions(-)

...

> +static int ath10k_mac_op_set_tid_conf(struct ieee80211_hw *hw,
> + struct ieee80211_vif *vif,
> + struct ieee80211_sta *sta,
> + struct ieee80211_tid_conf *tid_conf,
> + u8 changed)
> +{
> +   int ret;
> +   struct ath10k *ar = hw->priv;
> +   struct ath10k_vif *arvif = (void *)vif->drv_priv;
> +   struct ath10k_mac_iter_tid_config data = {};
> +   struct wmi_per_peer_per_tid_cfg_arg arg = {};
> +   struct ath10k_sta *arsta;
> +
> +   if (!(changed & TID_RETRY_CONF_CHANGED) &&
> +   !(changed & TID_AGGR_CONF_CHANGED))
> +   return 0;
> +
> +   mutex_lock(&ar->conf_mutex);
> +   arg.vdev_id = arvif->vdev_id;
> +   arg.tid = tid_conf->tid;
> +
> +   if (sta) {
> +   arsta = (struct ath10k_sta *)sta->drv_priv;
> +   ether_addr_copy(arg.peer_macaddr.addr, sta->addr);
> +
> +   if (changed & TID_RETRY_CONF_CHANGED) {
> +   if (tid_conf->retry_long ==
> +   arsta->retry_count[arg.tid]) {
> +   ret = 0;
> +   goto exit;
> +   }
> +
> +   if (tid_conf->retry_long == -1) {
> +   if (arvif->retry_count[arg.tid])
> +   arg.retry_count =
> +   arvif->retry_count[arg.tid];
> +   else
> +   arg.retry_count =
> +   ATH10K_MAX_RETRY_COUNT;
> +   } else {
> +   arg.retry_count = tid_conf->retry_long;
> +   }
> +   }
> +   if (changed & TID_AGGR_CONF_CHANGED) {
> +   if (tid_conf->aggr)
> +   arg.aggr_control =
> +   WMI_TID_CONFIG_AGGR_CONTROL_ENABLE;
> +   else
> +   arg.aggr_control =
> +   WMI_TID_CONFIG_AGGR_CONTROL_DISABLE;
> +   }
> +
> +   ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg);
> +   if (!ret) {
> +   /* Store the configured parameters in success case */
> +   if (changed & TID_RETRY_CONF_CHANGED)
> +   arsta->retry_count[arg.tid] =
> +   tid_conf->retry_long;
> +   if (changed & TID_AGGR_CONF_CHANGED)
> +   arsta->aggr_ctrl[arg.tid] = arg.aggr_control;
> +   }
> +
> +   goto exit;
> +   }
> +
> +   ret = 0;
> +
> +   if (changed & TID_RETRY_CONF_CHANGED)
> +   arvif->retry_count[tid_conf->tid] = tid_conf->retry_long;

Shouldn't it use default ATH10K_MAX_RETRY_COUNT value when
incoming retry_long value is -1 ?

Regards,
Sergey


Re: [PATCH 1/4] New netlink command for TID specific configuration

2018-11-07 Thread Sergey Matyukevich
Hello Tamizh,

> Co-Developed-by: Tamizh Chelvam 
> Signed-off-by: Vasanthakumar Thiagarajan 
> Signed-off-by: Tamizh chelvam 
> ---
>  include/net/cfg80211.h   |   14 +++
>  include/uapi/linux/nl80211.h |   69 +
>  net/wireless/nl80211.c   |   86 
> ++
>  net/wireless/rdev-ops.h  |   15 
>  net/wireless/trace.h |   27 +
>  5 files changed, 211 insertions(+)

...

> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index d744388..d386ad7 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c

...

> +static int nl80211_set_tid_config(struct sk_buff *skb,
> + struct genl_info *info)
> +{
> +   struct cfg80211_registered_device *rdev = info->user_ptr[0];
> +   struct nlattr *attrs[NL80211_ATTR_TID_MAX + 1];
> +   struct nlattr *tid;
> +   struct net_device *dev = info->user_ptr[1];
> +   const char *peer = NULL;
> +   u8 tid_no;
> +   int ret = -EINVAL, retry_short = -1, retry_long = -1;
> +
> +   tid = info->attrs[NL80211_ATTR_TID_CONFIG];
> +   if (!tid)
> +   return -EINVAL;
> +
> +   ret = nla_parse_nested(attrs, NL80211_ATTR_TID_MAX, tid,
> +  nl80211_attr_tid_policy, info->extack);
> +   if (ret)
> +   return ret;
> +
> +   if (!attrs[NL80211_ATTR_TID])
> +   return -EINVAL;
> +
> +   if (attrs[NL80211_ATTR_TID_RETRY_SHORT]) {
> +   retry_short = nla_get_u8(attrs[NL80211_ATTR_TID_RETRY_SHORT]);
> +   if (!retry_short ||
> +   retry_short > rdev->wiphy.max_data_retry_count)
> +   return -EINVAL;
> +   }
> +
> +   if (attrs[NL80211_ATTR_TID_RETRY_LONG]) {
> +   retry_long = nla_get_u8(attrs[NL80211_ATTR_TID_RETRY_LONG]);
> +   if (!retry_long ||
> +   retry_long > rdev->wiphy.max_data_retry_count)
> +   return -EINVAL;
> +   }
> +
> +   tid_no = nla_get_u8(attrs[NL80211_ATTR_TID]);
> +   if (tid_no >= IEEE80211_FIRST_TSPEC_TSID)
> +   return -EINVAL;
> +
> +   if (info->attrs[NL80211_ATTR_MAC])
> +   peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
> +
> +   if (nla_get_flag(attrs[NL80211_ATTR_TID_RETRY_CONFIG])) {

Do we really need this additional flag to indicate retry data ?
Maybe we can simply check retry attrs or even retry data, e.g.:

if (attrs[NL80211_ATTR_TID_RETRY_LONG] ||
attrs[NL80211_ATTR_TID_RETRY_SHORT]) {
...

if ((retry_short > 0) || (retry_long > 0)) {
...

> +   if (!wiphy_ext_feature_isset(
> +   &rdev->wiphy,
> +   NL80211_EXT_FEATURE_PER_TID_RETRY_CONFIG))
> +   return -EOPNOTSUPP;
> +
> +   if (peer && !wiphy_ext_feature_isset(
> +   &rdev->wiphy,
> +   NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG))
> +   return -EOPNOTSUPP;
> +
> +   if (!rdev->ops->set_data_retry_count ||
> +   !rdev->wiphy.max_data_retry_count)
> +   return -EOPNOTSUPP;
> +
> +   ret = rdev_set_data_retry_count(rdev, dev, peer, tid_no,
> +   retry_short, retry_long);
> +   }
> +
> +   return ret;
> +}

Regards,
Sergey


Re: [PATCH 0/4] cfg80211/mac80211: Add support for TID specific configuration

2018-11-06 Thread Sergey Matyukevich
On Tue, Nov 06, 2018 at 12:28:11PM +0100, Johannes Berg wrote:
> 
> WARNING: External email to Quantenna Communications. Please exercise caution!
> 
> 
> Hi,
> 
> On Tue, 2018-11-06 at 10:45 +0000, Sergey Matyukevich wrote:
> > > On Mon, 2018-10-22 at 23:25 +0530, Tamizh chelvam wrote:
> > > > Add infrastructure for per TID aggregation/retry count configurations
> > > > such as retry count and AMPDU aggregation control(disable/enable).
> > > > In some scenario reducing the number of retry count for a specific data
> > > > traffic can reduce the latency by proceeding with the next packet
> > > > instead of retrying the same packet more time. This will be useful
> > > > where the next packet can resume the operation without an issue.
> > >
> > > Not sure I understand this, how can you expect to control something on a
> > > per-packet basis using this?
> > >
> > > Sergey, looks like your A-MPDU control is already in here per RA/TID,
> > > and A-MSDU could be added easily?
> 
> > Thanks for pointing me at this patch series. Indeed, it looks like an
> > exact match for proper RA/TID aware implementation of AMPDU control.
> > AMSDU can be added following the same approach.
> >
> 
> Great. I guess if you could take a look that'd be nice, and perhaps also
> see if you could actually implement it? Your driver patch seemed to
> imply the firmware only has global control, rather than per RA/TID.
> 
> Also, do you think A-MPDU length control would be something useful?
> Perhaps that should be instead of enable/disable (since setting length
> to 0 or 1 could easily mean "no A-MPDU")

Hello Johannes,

I will send a follow-up A-MSDU patch after this patch set lands in your tree.
And then qtnfmac driver patches for both A-MPDU/A-MSDU changes.

As for A-MPDU chain length control, I don't think we have any practical
use-case for this feature at the moment. However Ben Greear suggested
one possible use-case: to decrease A-MPDU chain length for voice TID
in order to decrease latency. Anyways, current A-MPDU patches can be
easily adapted to support it if needed.

Regards,
Sergey


Re: [RFC 0/3] cfg80211/nl80211/iw: add basic AMPDU/AMSDU controls

2018-11-06 Thread Sergey Matyukevich
> On 11/05/2018 02:49 PM, Igor Mitsyanko wrote:
> > On 11/05/2018 12:45 PM, Ben Greear wrote:
> > > > 
> > > > I see you don't implement it this way in the driver, but wouldn't it
> > > > make more sense to have this as a per-STA (RA) setting? That's really
> > > > the granularity it can be done on, I think?
> > > > 
> > > > Arguably even per-RA/TID, though that seems a little excessive?
> > > 
> > > I like the idea of providing this API per peer/tid.  And, just allow
> > > peer == -1, tid == -1 or similar to mean 'all' so that you can still set
> > > the entire device
> > > to one particular setting w/out having to iterate through all peers if you
> > > don't want to iterate...
> > 
> > Maye I'm wrong, but isn't the setting we're discussing are for the
> > device itself, not for its peers? I mean, disabling AMSDU, AMPDU implies
> > we need to update capabilities advertised in our information elements,
> > which are common for all devices, and it affects both Tx and Rx.
> > 
> > And per-node/per-TID aggregation settings are a separate configuration
> > option related to rate adaptation on Tx path only..
> 
> You can advertise your maximum capabilities, but just because you advertise
> that you can do large AMPDU chains doesn't mean you are required to send
> them.
> 
> So, to advertise stuff, it is per vdev (not per radio), but once you associate
> a peer, you might decide to configure it so that you always send no more than 
> 5
> frames in an AMPDU chain, for instance.
> 
> And, you might decide that BE gets up to 32 AMPDU chain, but VI should be 
> limitted to 16
> to decrease latency just a bit.

Hi all,

Thanks for the comments. It turns out that RA/TID-aware approach to
AMPDU configuration has been already posted. Johannes pointed me at
the patch set adding support for TID specific configuration:
https://patchwork.kernel.org/project/linux-wireless/list/?series=33855

That patch set enables per-TID and per-STA configuration. AFAICS it
can be easily extended to support AMSDU and even configurable
AMPDU chain depth.

Regards,
Sergey


Re: [PATCH 0/4] cfg80211/mac80211: Add support for TID specific configuration

2018-11-06 Thread Sergey Matyukevich
> On Mon, 2018-10-22 at 23:25 +0530, Tamizh chelvam wrote:
> > Add infrastructure for per TID aggregation/retry count configurations
> > such as retry count and AMPDU aggregation control(disable/enable).
> > In some scenario reducing the number of retry count for a specific data
> > traffic can reduce the latency by proceeding with the next packet
> > instead of retrying the same packet more time. This will be useful
> > where the next packet can resume the operation without an issue.
> 
> Not sure I understand this, how can you expect to control something on a
> per-packet basis using this?
> 
> Sergey, looks like your A-MPDU control is already in here per RA/TID,
> and A-MSDU could be added easily?

Hello Johannes,

Thanks for pointing me at this patch series. Indeed, it looks like an
exact match for proper RA/TID aware implementation of AMPDU control.
AMSDU can be added following the same approach.

Regards,
Sergey


Re: [PATCH 3/4] mac80211: Add api to support configuring TID specific configuration

2018-11-06 Thread Sergey Matyukevich
> Signed-off-by: Tamizh chelvam 
> ---
>  include/net/mac80211.h|   40 +
>  net/mac80211/cfg.c|   71 
> +
>  net/mac80211/driver-ops.h |   16 ++
>  net/mac80211/trace.h  |   34 ++
>  4 files changed, 161 insertions(+)
> 
> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> index b6cc3e33..7fa7e25 100644
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -1478,6 +1478,35 @@ struct ieee80211_channel_switch {
> u8 count;
>  };
> 
> +/*
> + * enum ieee80211_tid_conf_change - TID change configuration notification 
> flags
> + *
> + * These flags are used with the set_tid_conf() callback
> + * to indicate which TID configuration parameter changed.
> + *
> + * @TID_RETRY_CONF_CHANGED: retry configuration changed.
> + * @TID_AGGR_CONF_CHANGED: Aggregation config changed for the TID.
> + */
> +enum ieee80211_tid_conf_change {
> +   TID_RETRY_CONF_CHANGED  = BIT(0),
> +   TID_AGGR_CONF_CHANGED   = BIT(1),
> +};

Following your approach, AMSDU support can be added in addition to
AMPDU. So I would suggest to replace AGGR by AMPDU right away.

> +
> +/*
> + * struct ieee80211_tid_conf - holds the tid configiuration data
> + * The information provided in the structure is required for the driver
> + * to configure TID specific configuration.
> + * @tid: TID number
> + * @retry_short: retry count value
> + * @retry_long: retry count value
> + * @aggr: enable/disable aggregation
> + */
> +struct ieee80211_tid_conf {
> +   u8 tid;
> +   int retry_short;
> +   int retry_long;
> +   bool aggr;
> +};

ditto: aggr -> ampdu

Regards,
Sergey


Re: [PATCH 2/4] nl80211: Add netlink attribute for AMPDU aggregation enable/disable

2018-11-06 Thread Sergey Matyukevich


Hello Tamizh,

> Signed-off-by: Tamizh chelvam 
> ---
>  include/net/cfg80211.h   |6 ++
>  include/uapi/linux/nl80211.h |   21 +
>  net/wireless/nl80211.c   |   17 +
>  net/wireless/rdev-ops.h  |   15 +++
>  net/wireless/trace.h |   23 +++
>  5 files changed, 82 insertions(+)
...

> diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
> index 9dfcf0a6..7ba0fb7 100644
> --- a/include/uapi/linux/nl80211.h
> +++ b/include/uapi/linux/nl80211.h
> @@ -4449,6 +4449,20 @@ enum nl80211_ps_state {
>   * the max value should be advertised by the driver through
>   * max_data_retry_count. when this attribute is not present, the driver
>   * would use the default configuration.
> + * @NL80211_ATTR_TID_AMPDU_AGGR_CTRL: Enable/Disable aggregation for the TID
> + * specified in %%NL80211_ATTR_TID. Its type is u8, if the peer MAC 
> address
> + * is passed in %NL80211_ATTR_MAC, the aggregation configuration is 
> applied
> + * to the data frame for the tid to that connected station.
> + * Station specific aggregation configuration is valid only for STA's
> + * current connection. i.e. the configuration will be reset to default 
> when
> + * the station connects back after disconnection/roaming.
> + * when user-space does not include %NL80211_ATTR_MAC, this configuration
> + * should be treated as per-netdev configuration. This configuration will
> + * be cleared when the interface goes down and on the disconnection from 
> a
> + * BSS. Driver supporting this feature should advertise
> + * NL80211_EXT_FEATURE_PER_STA_AMPDU_AGGR_CTRL and supporting per station

typo: should be NL80211_EXT_FEATURE_PER_TID_AMPDU_AGGR_CTRL

> + * aggregation configuration should advertise
> + * NL80211_EXT_FEATURE_PER_STA_AMPDU_AGGR_CTRL.
>   */

Regards,
Sergey


Re: [PATCH 1/4] New netlink command for TID specific configuration

2018-11-06 Thread Sergey Matyukevich
Hello Tamizh,

> Co-Developed-by: Tamizh Chelvam 
> Signed-off-by: Vasanthakumar Thiagarajan 
> Signed-off-by: Tamizh chelvam 
> ---
>  include/net/cfg80211.h   |   14 +++
>  include/uapi/linux/nl80211.h |   69 +
>  net/wireless/nl80211.c   |   86 
> ++
>  net/wireless/rdev-ops.h  |   15 
>  net/wireless/trace.h |   27 +
>  5 files changed, 211 insertions(+)

...

> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index 5801d76..dd024da 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h

...

>  /**
> @@ -4035,6 +4044,9 @@ struct wiphy_iftype_ext_capab {
>   * @txq_limit: configuration of internal TX queue frame limit
>   * @txq_memory_limit: configuration internal TX queue memory limit
>   * @txq_quantum: configuration of internal TX queue scheduler quantum
> + *
> + * @max_data_retry_count: Maximum limit can be configured as retry count
> + * for a TID.
>   */
>  struct wiphy {
> /* assign these fields before you register the wiphy */
> @@ -4171,6 +4183,8 @@ struct wiphy {
> u32 txq_memory_limit;
> u32 txq_quantum;
> 
> +   u8 max_data_retry_count;
> +
> char priv[0] __aligned(NETDEV_ALIGN);
>  };

Could you please clarify why do you define max_data_retry_count instead of
making use of existing wiphy params: retry_short (dot11ShortRetryLimit)
and retry_long (dot11LongRetryLimit) ?

> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index d744388..d386ad7 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c

...

> +static int nl80211_set_tid_config(struct sk_buff *skb,
> + struct genl_info *info)
> +{
> +   struct cfg80211_registered_device *rdev = info->user_ptr[0];
> +   struct nlattr *attrs[NL80211_ATTR_TID_MAX + 1];
> +   struct nlattr *tid;
> +   struct net_device *dev = info->user_ptr[1];
> +   const char *peer = NULL;
> +   u8 tid_no;
> +   int ret = -EINVAL, retry_short = -1, retry_long = -1;
> +
> +   tid = info->attrs[NL80211_ATTR_TID_CONFIG];
> +   if (!tid)
> +   return -EINVAL;
> +
> +   ret = nla_parse_nested(attrs, NL80211_ATTR_TID_MAX, tid,
> +  nl80211_attr_tid_policy, info->extack);
> +   if (ret)
> +   return ret;
> +
> +   if (!attrs[NL80211_ATTR_TID])
> +   return -EINVAL;
> +
> +   if (attrs[NL80211_ATTR_TID_RETRY_SHORT]) {
> +   retry_short = nla_get_u8(attrs[NL80211_ATTR_TID_RETRY_SHORT]);
> +   if (!retry_short ||
> +   retry_short > rdev->wiphy.max_data_retry_count)
> +   return -EINVAL;
> +   }
> +
> +   if (attrs[NL80211_ATTR_TID_RETRY_LONG]) {
> +   retry_long = nla_get_u8(attrs[NL80211_ATTR_TID_RETRY_LONG]);
> +   if (!retry_long ||
> +   retry_long > rdev->wiphy.max_data_retry_count)
> +   return -EINVAL;
> +   }
> +
> +   tid_no = nla_get_u8(attrs[NL80211_ATTR_TID]);
> +   if (tid_no >= IEEE80211_FIRST_TSPEC_TSID)
> +   return -EINVAL;

Not that important, but this tid_no check can be placed after
attrs[NL80211_ATTR_TID].

BTW, some special tid_no value (e.g. (u8)-1) could be used to notify driver
that retry settings should be applied for all the TIDs. IIUC the only
required change would be to modify this tid_no sanity check.

Regards,
Sergey


[RFC 2/3] iw: add phy subcommands to configure aggregation

2018-11-05 Thread Sergey Matyukevich
Add phy subcommands to enable/disable AMPDU/AMSDU aggregation.

Signed-off-by: Sergey Matyukevich 
---
 nl80211.h |  6 ++
 phy.c | 60 
 2 files changed, 66 insertions(+)

diff --git a/nl80211.h b/nl80211.h
index 1766a12..41eec4a 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -2241,6 +2241,9 @@ enum nl80211_commands {
  * association request when used with NL80211_CMD_NEW_STATION). Can be set
  * only if %NL80211_STA_FLAG_WME is set.
  *
+ * @NL80211_ATTR_WIPHY_AMPDU_ENABLED: enable/disable AMPDU aggregation.
+ * @NL80211_ATTR_WIPHY_AMSDU_ENABLED: enable/disable AMSDU aggregation.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2682,6 +2685,9 @@ enum nl80211_attrs {
 
NL80211_ATTR_HE_CAPABILITY,
 
+   NL80211_ATTR_WIPHY_AMPDU_ENABLED,
+   NL80211_ATTR_WIPHY_AMSDU_ENABLED,
+
/* add attributes here, update the policy in nl80211.c */
 
__NL80211_ATTR_AFTER_LAST,
diff --git a/phy.c b/phy.c
index 77df7a7..be949e7 100644
--- a/phy.c
+++ b/phy.c
@@ -843,3 +843,63 @@ static int handle_get_txq(struct nl80211_state *state,
 COMMAND(get, txq, "",
NL80211_CMD_GET_WIPHY, 0, CIB_PHY, handle_get_txq,
"Get TXQ parameters.");
+
+static int handle_ampdu(struct nl80211_state *state,
+   struct nl_msg *msg,
+   int argc, char **argv,
+   enum id_input id)
+{
+   unsigned int ampdu;
+
+   if (argc != 1)
+   return 1;
+
+   if (strcmp(argv[0], "on") == 0)
+   ampdu = 1;
+   else if (strcmp(argv[0], "off") == 0)
+   ampdu = 0;
+   else {
+   printf("Invalid parameter: %s\n", argv[0]);
+   return 2;
+   }
+
+   NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_AMPDU_ENABLED, ampdu);
+
+   return 0;
+
+ nla_put_failure:
+   return -ENOBUFS;
+}
+COMMAND(set, ampdu, "",
+   NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_ampdu,
+   "Enable/disable AMPDU aggregation.");
+
+static int handle_amsdu(struct nl80211_state *state,
+   struct nl_msg *msg,
+   int argc, char **argv,
+   enum id_input id)
+{
+   unsigned int amsdu;
+
+   if (argc != 1)
+   return 1;
+
+   if (strcmp(argv[0], "on") == 0)
+   amsdu = 1;
+   else if (strcmp(argv[0], "off") == 0)
+   amsdu = 0;
+   else {
+   printf("Invalid parameter: %s\n", argv[0]);
+   return 2;
+   }
+
+   NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_AMSDU_ENABLED, amsdu);
+
+   return 0;
+
+ nla_put_failure:
+   return -ENOBUFS;
+}
+COMMAND(set, amsdu, "",
+   NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_amsdu,
+   "Enable/disable AMSDU aggregation.");
-- 
2.11.0



[RFC 3/3] qtnfmac: add support for basic aggregation control

2018-11-05 Thread Sergey Matyukevich
Add support for basic AMPDU/AMSDU aggregation control:
- report initial aggregation configuration to cfg80211 core
- pass AMPDU/AMSDU aggregation changes to wireless card
  using set_wiphy_params cfg80211 callback

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |  2 ++
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 17 +
 drivers/net/wireless/quantenna/qtnfmac/core.h |  2 ++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|  7 +++
 4 files changed, 28 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 51b33ec78fac..98bd0a3d29db 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1087,6 +1087,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
wiphy->retry_short = macinfo->sretry_limit;
wiphy->retry_long = macinfo->lretry_limit;
wiphy->coverage_class = macinfo->coverage_class;
+   wiphy->ampdu_enabled = macinfo->ampdu_enabled;
+   wiphy->amsdu_enabled = macinfo->amsdu_enabled;
 
wiphy->max_scan_ssids =
(hw_info->max_scan_ssids) ? hw_info->max_scan_ssids : 1;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index bfdc1ad30c13..6ab0a25b917f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1531,6 +1531,7 @@ static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac 
*mac,
struct qlink_tlv_frag_rts_thr *phy_thr;
struct qlink_tlv_rlimit *limit;
struct qlink_tlv_cclass *class;
+   struct qlink_tlv_aggr *aggr;
u16 tlv_type;
u16 tlv_value_len;
size_t tlv_full_len;
@@ -1571,6 +1572,14 @@ static int qtnf_cmd_resp_proc_phy_params(struct 
qtnf_wmac *mac,
class = (void *)tlv;
mac_info->coverage_class = class->cclass;
break;
+   case QTN_TLV_ID_AMPDU_ENABLED:
+   aggr = (void *)tlv;
+   mac_info->ampdu_enabled = aggr->aggr;
+   break;
+   case QTN_TLV_ID_AMSDU_ENABLED:
+   aggr = (void *)tlv;
+   mac_info->amsdu_enabled = aggr->aggr;
+   break;
default:
pr_err("MAC%u: Unknown TLV type: %#x\n", mac->macid,
   le16_to_cpu(tlv->type));
@@ -1814,6 +1823,14 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac 
*mac, u32 changed)
qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
wiphy->coverage_class);
 
+   if (changed & WIPHY_PARAM_AMPDU_ENABLED)
+   qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_AMPDU_ENABLED,
+   wiphy->ampdu_enabled);
+
+   if (changed & WIPHY_PARAM_AMSDU_ENABLED)
+   qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_AMSDU_ENABLED,
+   wiphy->amsdu_enabled);
+
ret = qtnf_cmd_send(mac->bus, cmd_skb);
if (ret)
goto out;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h 
b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 293055049caa..e6752faf0f50 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -94,6 +94,8 @@ struct qtnf_mac_info {
u8 lretry_limit;
u8 sretry_limit;
u8 coverage_class;
+   u8 amsdu_enabled;
+   u8 ampdu_enabled;
u8 radar_detect_widths;
u32 max_acl_mac_addrs;
struct ieee80211_ht_cap ht_cap_mod_mask;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 8d62addea895..7dede44c75d7 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -1154,6 +1154,8 @@ enum qlink_tlv_id {
QTN_TLV_ID_WOWLAN_PATTERN   = 0x0411,
QTN_TLV_ID_SCAN_FLUSH   = 0x0412,
QTN_TLV_ID_SCAN_DWELL   = 0x0413,
+   QTN_TLV_ID_AMPDU_ENABLED= 0x0414,
+   QTN_TLV_ID_AMSDU_ENABLED= 0x0415,
 };
 
 struct qlink_tlv_hdr {
@@ -1195,6 +1197,11 @@ struct qlink_tlv_cclass {
u8 cclass;
 } __packed;
 
+struct qlink_tlv_aggr {
+   struct qlink_tlv_hdr hdr;
+   u8 aggr;
+} __packed;
+
 /**
  * enum qlink_reg_rule_flags - regulatory rule flags
  *
-- 
2.11.0



[RFC 0/3] cfg80211/nl80211/iw: add basic AMPDU/AMSDU controls

2018-11-05 Thread Sergey Matyukevich
Hello Johannes and all, 

Here are several RFC patches providing simple high-level controls of AMSDU/AMPDU
aggregation. The primary purpose of this functionality is an attempt to fill
missing gaps in nl80211 interface for basic WFA certification tests.

We experimented with QCA sigma-dut tool: https://github.com/qca/sigma-dut.
The purpose was to cover basic HT/VHT WFA STA tests for cfg80211 driver
controlled by wpa_supplicant  w/o adding any vendor specific commands.
Multiple WFA test parameters (e.g. STBC, NSS, SGI, LDPC) can be configured
by overriding HT/VHT capabilities in wpa_supplicant and applying them on
connect in cfg80211_connect callback. Others (e.g. RTS params) can be
configured using iw tool or NL80211_CMD_SET_WIPHY directly. These patches
implement simpe high-level switches for AMSDU/AMPDU aggregation.

It would be interesting to collect comments/concerns regarding this approach.
Does it make sense to enhance nl80211 in order to cover all the missing pieces
required for WFA certification tests ? Or maybe it makes sense to use
NL80211_TESTMODE subcommands for this kind of testing.


The summary of changes is as follows:
- nl80211/cfg80211: new wiphy flags and minimal set_wiphy/get_wiphy changes
- iw: new phy subcommands to enable/disable aggregation
- qtnfmac: minimal driver example - get/set aggregation

Regards,
Sergey


kernel:
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |2 +
 drivers/net/wireless/quantenna/qtnfmac/commands.c |   17 
 drivers/net/wireless/quantenna/qtnfmac/core.h |2 +
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|7 
 include/net/cfg80211.h|7 
 include/uapi/linux/nl80211.h  |6 
 net/wireless/core.c   |3 ++
 net/wireless/nl80211.c|   31 ++
 9 files changed, 76 insertions(+), 1 deletion(-)

iw:
 nl80211.h |6 ++
 phy.c |   60 
 2 files changed, 66 insertions(+)


[RFC 1/3] cfg80211/nl80211: add wiphy flags to control aggregation

2018-11-05 Thread Sergey Matyukevich
Add two top-level switches to wiphy structure to control AMSDU and AMPDU
aggregation. Enable read/update of AMSDU and AMPDU aggregation from
the userspace using set_wiphy/get_wiphy commands.

Signed-off-by: Sergey Matyukevich 
---
 include/net/cfg80211.h   |  7 +++
 include/uapi/linux/nl80211.h |  6 ++
 net/wireless/core.c  |  3 +++
 net/wireless/nl80211.c   | 31 +++
 4 files changed, 47 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1fa41b7a1be3..fbf01d156069 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2368,6 +2368,8 @@ enum cfg80211_connect_params_changed {
  * @WIPHY_PARAM_TXQ_LIMIT: TXQ packet limit has been changed
  * @WIPHY_PARAM_TXQ_MEMORY_LIMIT: TXQ memory limit has been changed
  * @WIPHY_PARAM_TXQ_QUANTUM: TXQ scheduler quantum
+ * @WIPHY_PARAM_AMPDU_ENABLED: wiphy->ampdu_enabled has changed
+ * @WIPHY_PARAM_AMSDU_ENABLED: wiphy->amsdu_enabled has changed
  */
 enum wiphy_params_flags {
WIPHY_PARAM_RETRY_SHORT = 1 << 0,
@@ -2379,6 +2381,8 @@ enum wiphy_params_flags {
WIPHY_PARAM_TXQ_LIMIT   = 1 << 6,
WIPHY_PARAM_TXQ_MEMORY_LIMIT= 1 << 7,
WIPHY_PARAM_TXQ_QUANTUM = 1 << 8,
+   WIPHY_PARAM_AMPDU_ENABLED   = 1 << 9,
+   WIPHY_PARAM_AMSDU_ENABLED   = 1 << 10,
 };
 
 /**
@@ -4163,6 +4167,9 @@ struct wiphy {
u32 txq_memory_limit;
u32 txq_quantum;
 
+   u8 ampdu_enabled;
+   u8 amsdu_enabled;
+
char priv[0] __aligned(NETDEV_ALIGN);
 };
 
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 6d610bae30a9..a9f8fa814ecd 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2254,6 +2254,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_FTM_RESPONDER_STATS: Nested attribute with FTM responder
  * statistics, see &enum nl80211_ftm_responder_stats.
  *
+ * @NL80211_ATTR_WIPHY_AMPDU_ENABLED: enable/disable AMPDU aggregation.
+ * @NL80211_ATTR_WIPHY_AMSDU_ENABLED: enable/disable AMSDU aggregation.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2699,6 +2702,9 @@ enum nl80211_attrs {
 
NL80211_ATTR_FTM_RESPONDER_STATS,
 
+   NL80211_ATTR_WIPHY_AMPDU_ENABLED,
+   NL80211_ATTR_WIPHY_AMSDU_ENABLED,
+
/* add attributes here, update the policy in nl80211.c */
 
__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 5bd01058b9e6..182f8f04166d 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -524,6 +524,9 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, 
int sizeof_priv,
rdev->wiphy.max_sched_scan_plans = 1;
rdev->wiphy.max_sched_scan_plan_interval = U32_MAX;
 
+   rdev->wiphy.ampdu_enabled = 1;
+   rdev->wiphy.amsdu_enabled = 1;
+
return &rdev->wiphy;
 }
 EXPORT_SYMBOL(wiphy_new_nm);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 744b5851bbf9..5c04b6996e64 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -497,6 +497,9 @@ static const struct nla_policy 
nl80211_policy[NUM_NL80211_ATTR] = {
.type = NLA_NESTED,
.validation_data = nl80211_ftm_responder_policy,
},
+
+   [NL80211_ATTR_WIPHY_AMPDU_ENABLED] = { .type = NLA_U8 },
+   [NL80211_ATTR_WIPHY_AMSDU_ENABLED] = { .type = NLA_U8 },
 };
 
 /* policy for the key attributes */
@@ -2118,6 +2121,14 @@ static int nl80211_send_wiphy(struct 
cfg80211_registered_device *rdev,
goto nla_put_failure;
}
 
+   if (nla_put_u8(msg, NL80211_ATTR_WIPHY_AMPDU_ENABLED,
+  rdev->wiphy.ampdu_enabled))
+   goto nla_put_failure;
+
+   if (nla_put_u8(msg, NL80211_ATTR_WIPHY_AMSDU_ENABLED,
+  rdev->wiphy.amsdu_enabled))
+   goto nla_put_failure;
+
/* done */
state->split_start = 0;
break;
@@ -2514,6 +2525,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct 
genl_info *info)
u32 frag_threshold = 0, rts_threshold = 0;
u8 coverage_class = 0;
u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
+   u8 amsdu = 0, ampdu = 0;
 
ASSERT_RTNL();
 
@@ -2743,11 +2755,22 @@ static int nl80211_set_wiphy(struct sk_buff *skb, 
struct genl_info *info)
changed |= WIPHY_PARAM_TXQ_QUANTUM;
}
 
+   if (info->attrs[NL80211_ATTR_WIPHY_AMPDU_ENABLED]) {
+   ampdu = 
nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_AMPDU_ENABLED]);
+   changed |= WIPHY_PARAM_AMPDU_ENABLED;
+   }
+
+   if (info->attrs[N

[PATCH] cfg80211: add missing constraint for user-supplied VHT mask

2018-10-19 Thread Sergey Matyukevich
Do a logical vht_capa &= vht_capa_mask of user-supplied VHT mask with
the driver-supplied mask of modifiable VHT capabilities.
Fix whitespaces and comment typos.

Signed-off-by: Sergey Matyukevich 
---
 net/wireless/mlme.c | 4 ++--
 net/wireless/sme.c  | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 12b3edf70a7b..1615e503f8e3 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -272,11 +272,11 @@ void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap 
*ht_capa,
 
p1 = (u8*)(ht_capa);
p2 = (u8*)(ht_capa_mask);
-   for (i = 0; iht_capa_mask,
  rdev->wiphy.ht_capa_mod_mask);
+   cfg80211_oper_and_vht_capa(&connect->vht_capa_mask,
+  rdev->wiphy.vht_capa_mod_mask);
 
if (connkeys && connkeys->def >= 0) {
int idx;
-- 
2.11.0



[PATCH] qtnfmac: fix error handling in control path

2018-10-17 Thread Sergey Matyukevich
This patch fixes the following warnings:

- smatch
drivers/net/wireless/quantenna/qtnfmac/commands.c:132 
qtnf_cmd_send_with_reply() warn: variable dereferenced before check 'resp' (see 
line 117)
drivers/net/wireless/quantenna/qtnfmac/commands.c:716  qtnf_cmd_get_sta_info() 
error: uninitialized symbol 'var_resp_len'.
drivers/net/wireless/quantenna/qtnfmac/commands.c:1668 qtnf_cmd_get_mac_info() 
error: uninitialized symbol 'var_data_len'.
drivers/net/wireless/quantenna/qtnfmac/commands.c:1697 qtnf_cmd_get_hw_info() 
error: uninitialized symbol 'info_len'.
drivers/net/wireless/quantenna/qtnfmac/commands.c:1753 qtnf_cmd_band_info_get() 
error: uninitialized symbol 'info_len'.
drivers/net/wireless/quantenna/qtnfmac/commands.c:1782 
qtnf_cmd_send_get_phy_params() error: uninitialized symbol 'response_size'.
drivers/net/wireless/quantenna/qtnfmac/commands.c:2438 
qtnf_cmd_get_chan_stats() error: uninitialized symbol 'var_data_len'.

- gcc-8.2.1
drivers/net/wireless/quantenna/qtnfmac/commands.c: In function 
'qtnf_cmd_send_with_reply':
drivers/net/wireless/quantenna/qtnfmac/commands.c:133:54: error: 'resp' may be 
used uninitialized in this function [-Werror=maybe-uninitialized]

Reported-by: Dan Carpenter 
Reported-by: Arnd Bergmann 
Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 21 +
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index bfdc1ad30c13..659e7649fe22 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -84,7 +84,7 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
size_t *var_resp_size)
 {
struct qlink_cmd *cmd;
-   const struct qlink_resp *resp;
+   struct qlink_resp *resp = NULL;
struct sk_buff *resp_skb = NULL;
u16 cmd_id;
u8 mac_id;
@@ -113,7 +113,12 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
if (ret)
goto out;
 
-   resp = (const struct qlink_resp *)resp_skb->data;
+   if (WARN_ON(!resp_skb || !resp_skb->data)) {
+   ret = -EFAULT;
+   goto out;
+   }
+
+   resp = (struct qlink_resp *)resp_skb->data;
ret = qtnf_cmd_check_reply_header(resp, cmd_id, mac_id, vif_id,
  const_resp_size);
if (ret)
@@ -686,7 +691,7 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 
*sta_mac,
struct sk_buff *cmd_skb, *resp_skb = NULL;
struct qlink_cmd_get_sta_info *cmd;
const struct qlink_resp_get_sta_info *resp;
-   size_t var_resp_len;
+   size_t var_resp_len = 0;
int ret = 0;
 
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
@@ -1650,7 +1655,7 @@ int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac)
 {
struct sk_buff *cmd_skb, *resp_skb = NULL;
const struct qlink_resp_get_mac_info *resp;
-   size_t var_data_len;
+   size_t var_data_len = 0;
int ret = 0;
 
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
@@ -1680,8 +1685,8 @@ int qtnf_cmd_get_hw_info(struct qtnf_bus *bus)
 {
struct sk_buff *cmd_skb, *resp_skb = NULL;
const struct qlink_resp_get_hw_info *resp;
+   size_t info_len = 0;
int ret = 0;
-   size_t info_len;
 
cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
QLINK_CMD_GET_HW_INFO,
@@ -1709,9 +1714,9 @@ int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
   struct ieee80211_supported_band *band)
 {
struct sk_buff *cmd_skb, *resp_skb = NULL;
-   size_t info_len;
struct qlink_cmd_band_info_get *cmd;
struct qlink_resp_band_info_get *resp;
+   size_t info_len = 0;
int ret = 0;
u8 qband;
 
@@ -1764,8 +1769,8 @@ int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
 int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac)
 {
struct sk_buff *cmd_skb, *resp_skb = NULL;
-   size_t response_size;
struct qlink_resp_phy_params *resp;
+   size_t response_size = 0;
int ret = 0;
 
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
@@ -2431,7 +2436,7 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 
channel,
struct sk_buff *cmd_skb, *resp_skb = NULL;
struct qlink_cmd_get_chan_stats *cmd;
struct qlink_resp_get_chan_stats *resp;
-   size_t var_data_len;
+   size_t var_data_len = 0;
int ret = 0;
 
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
-- 
2.11.0



  1   2   3   4   >