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


[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  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 >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[NL80211_A

[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(>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



Re: [PATCH 3/3] mac80211: Implement functionality to monitor station's signal stregnth

2018-10-16 Thread Sergey Matyukevich
> +/*
> + * How many frames need to have been used in average station's
> + * signal strength before checking against the threshold
> + */
> +#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
> +
> +
>  /* there are 40 bytes if you don't need the rateset to be kept */
>  #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40

...

> +static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
> +{
> +   struct sta_info *sta = rx->sta;
> +   struct ieee80211_bss_conf *bss_conf = >sdata->vif.bss_conf;
> +   bool rssi_cross =  false;
> +
> +   if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
> +   NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG))
> +   return;
> +
> +   sta->count_rx_signal++;
> +   if (sta->count_rx_signal < IEEE80211_STA_SIGNAL_AVE_MIN_COUNT)
> +   return;

Could you please clarify count_rx_signal processing and averaging
approach ? I couldn't find where this counter is reset or
modified in any other way.

Regards,
Sergey


Re: [PATCH 1/3] cfg80211: Add support to configure station specific RSSI threshold for AP mode

2018-10-16 Thread Sergey Matyukevich
> Signed-off-by: Tamizh chelvam 
> ---
>  include/net/cfg80211.h   |   28 +
>  include/uapi/linux/nl80211.h |   18 ++
>  net/wireless/nl80211.c   |  131 
> +-
>  net/wireless/rdev-ops.h  |   18 ++
>  4 files changed, 181 insertions(+), 14 deletions(-)

...

> +static int nl80211_set_sta_mon(struct sk_buff *skb, struct genl_info *info)
> +{
> +   struct cfg80211_registered_device *rdev = info->user_ptr[0];
> +   struct net_device *dev = info->user_ptr[1];
> +   struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
> +   bool fixed_thold = false;
> +   struct nlattr *sta_mon;
> +   u8 *addr = NULL;
> +   int err;
> +
> +   if (!wiphy_ext_feature_isset(>wiphy,
> +NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG))
> +   return -EOPNOTSUPP;
> +
> +   sta_mon = info->attrs[NL80211_ATTR_CQM];
> +   if (!sta_mon || !(info->attrs[NL80211_ATTR_MAC]))
> +   return -EINVAL;
> +
> +   err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, sta_mon,
> +  nl80211_attr_cqm_policy, info->extack);
> +   if (err)
> +   return err;
> +
> +   addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
> +   fixed_thold =
> +   nla_get_flag(info->attrs[NL80211_ATTR_STA_MON_FIXED_THOLD]);
> +
> +   if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
> +   attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
> +   const s32 *thresholds =
> +   nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
> +   int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
> +   u32 hysteresis = 
> nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
> +
> +   if (len % 4)
> +   return -EINVAL;
> +
> +   err = nl80211_validate_rssi_tholds(thresholds, len / 4);
> +   if (err)
> +   return err;
> +
> +   return rdev_set_sta_mon_rssi_config(rdev, dev, addr, 
> thresholds,
> +   hysteresis, len / 4,
> +   fixed_thold);
> +   }
> +
> +   return -EINVAL;
> +}

IIUC there is a noticeable overlap between this new command and
existing nl80211_set_cqm_rssi command. Is there any reason why
nl80211_set_cqm_rss can not be adapted for AP case ?

If there is a reason to handle AP case separately, then it looks
like it makes sense to add explicit check for supported iftype
in this new command. Besides, it looks like there is no generic
way to handle disabling of RSSI monitoring in the new command.
As a result, we may end up in multiple driver
specific implementations.

Regards,
Sergey


[PATCH v2 2/2] qtnfmac: add support for Topaz chipsets

2018-10-16 Thread Sergey Matyukevich
This patch adds support for QSR1000/QSR2000 family of chipsets
to qtnfmac_pcie platform driver.

QSR1000/QSR2000 (aka Topaz) is a family of 80MHz, 11ac Wave2,
4x4/2x4/2x2 chips, including single and dual band devices.
Depending on specific chip model and firmware in use, either
STA or both STA and AP modes are supported.

Patch adds Topaz support to qtnfmac_pcie driver. Proper platform
bus will be selected on probing based on chip ID.

Signed-off-by: Igor Mitsyanko 
Signed-off-by: Sergey Matyukevich 
Signed-off-by: Andrey Shevchenko 
---
 drivers/net/wireless/quantenna/qtnfmac/Kconfig |5 +-
 drivers/net/wireless/quantenna/qtnfmac/Makefile|3 +-
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c |5 +-
 .../wireless/quantenna/qtnfmac/pcie/pcie_priv.h|1 +
 .../wireless/quantenna/qtnfmac/pcie/topaz_pcie.c   | 1219 
 .../quantenna/qtnfmac/pcie/topaz_pcie_ipc.h|   94 ++
 .../quantenna/qtnfmac/pcie/topaz_pcie_regs.h   |   45 +
 .../net/wireless/quantenna/qtnfmac/qtn_hw_ids.h|4 +-
 drivers/net/wireless/quantenna/qtnfmac/util.c  |2 +
 9 files changed, 1373 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
 create mode 100644 drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie_ipc.h
 create mode 100644 
drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie_regs.h

diff --git a/drivers/net/wireless/quantenna/qtnfmac/Kconfig 
b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
index 696c50066b53..6cf5202c3666 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/Kconfig
+++ b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
@@ -5,7 +5,7 @@ config QTNFMAC
default y if QTNFMAC_PCIE=y
 
 config QTNFMAC_PCIE
-   tristate "Quantenna QSR10g PCIe support"
+   tristate "Quantenna QSR1000/QSR2000/QSR10g PCIe support"
default n
depends on PCI && CFG80211
select QTNFMAC
@@ -13,7 +13,8 @@ config QTNFMAC_PCIE
select CRC32
help
  This option adds support for wireless adapters based on Quantenna
- 802.11ac QSR10g (aka Pearl) FullMAC chipset running over PCIe.
+ 802.11ac QSR10g (aka Pearl) and QSR1000/QSR2000 (aka Topaz)
+ FullMAC chipsets running over PCIe.
 
  If you choose to build it as a module, two modules will be built:
  qtnfmac.ko and qtnfmac_pcie.ko.
diff --git a/drivers/net/wireless/quantenna/qtnfmac/Makefile 
b/drivers/net/wireless/quantenna/qtnfmac/Makefile
index d7e8185fddab..40dffbd2ea47 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/Makefile
+++ b/drivers/net/wireless/quantenna/qtnfmac/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_QTNFMAC_PCIE) += qtnfmac_pcie.o
 qtnfmac_pcie-objs += \
shm_ipc.o \
pcie/pcie.o \
-   pcie/pearl_pcie.o
+   pcie/pearl_pcie.o \
+   pcie/topaz_pcie.o
 
 qtnfmac_pcie-$(CONFIG_DEBUG_FS) += debug.o
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index 70dd8da5b0dc..c3a32effa6f0 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -330,6 +330,9 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
case QTN_CHIP_ID_PEARL_C:
bus = qtnf_pcie_pearl_alloc(pdev);
break;
+   case QTN_CHIP_ID_TOPAZ:
+   bus = qtnf_pcie_topaz_alloc(pdev);
+   break;
default:
pr_err("unsupported chip ID 0x%x\n", chipid);
return -ENOTSUPP;
@@ -465,7 +468,7 @@ static SIMPLE_DEV_PM_OPS(qtnf_pcie_pm_ops, 
qtnf_pcie_suspend,
 
 static const struct pci_device_id qtnf_pcie_devid_table[] = {
{
-   PCIE_VENDOR_ID_QUANTENNA, PCIE_DEVICE_ID_QTN_PEARL,
+   PCIE_VENDOR_ID_QUANTENNA, PCIE_DEVICE_ID_QSR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
},
{ },
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h
index 7c742c56efaf..bbc074e1f34d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h
@@ -76,6 +76,7 @@ void qtnf_pcie_init_shm_ipc(struct qtnf_pcie_bus_priv *priv,
struct qtnf_shm_ipc_region __iomem *ipc_rx_reg,
const struct qtnf_shm_ipc_int *ipc_int);
 struct qtnf_bus *qtnf_pcie_pearl_alloc(struct pci_dev *pdev);
+struct qtnf_bus *qtnf_pcie_topaz_alloc(struct pci_dev *pdev);
 
 static inline void qtnf_non_posted_write(u32 val, void __iomem *basereg)
 {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
new file mode 100644
index ..598edb814421
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie

[PATCH v2 1/2] qtnfmac_pcie: use single PCIe driver for all platforms

2018-10-16 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Single PCIe driver can identify hardware type by reading CHIP ID at
probe time and invoking a correct initialization sequence.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/Kconfig |  10 +-
 drivers/net/wireless/quantenna/qtnfmac/Makefile|   6 +-
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 279 ++---
 .../wireless/quantenna/qtnfmac/pcie/pcie_priv.h|  19 +-
 .../wireless/quantenna/qtnfmac/pcie/pearl_pcie.c   | 211 +---
 drivers/net/wireless/quantenna/qtnfmac/util.c  |  16 ++
 drivers/net/wireless/quantenna/qtnfmac/util.h  |   2 +
 7 files changed, 292 insertions(+), 251 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/Kconfig 
b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
index b8c12a5f16b4..696c50066b53 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/Kconfig
+++ b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
@@ -1,10 +1,10 @@
 config QTNFMAC
tristate
-   depends on QTNFMAC_PEARL_PCIE
-   default m if QTNFMAC_PEARL_PCIE=m
-   default y if QTNFMAC_PEARL_PCIE=y
+   depends on QTNFMAC_PCIE
+   default m if QTNFMAC_PCIE=m
+   default y if QTNFMAC_PCIE=y
 
-config QTNFMAC_PEARL_PCIE
+config QTNFMAC_PCIE
tristate "Quantenna QSR10g PCIe support"
default n
depends on PCI && CFG80211
@@ -16,4 +16,4 @@ config QTNFMAC_PEARL_PCIE
  802.11ac QSR10g (aka Pearl) FullMAC chipset running over PCIe.
 
  If you choose to build it as a module, two modules will be built:
- qtnfmac.ko and qtnfmac_pearl_pcie.ko.
+ qtnfmac.ko and qtnfmac_pcie.ko.
diff --git a/drivers/net/wireless/quantenna/qtnfmac/Makefile 
b/drivers/net/wireless/quantenna/qtnfmac/Makefile
index 17cd7adb4109..d7e8185fddab 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/Makefile
+++ b/drivers/net/wireless/quantenna/qtnfmac/Makefile
@@ -19,11 +19,11 @@ qtnfmac-objs += \
 
 #
 
-obj-$(CONFIG_QTNFMAC_PEARL_PCIE) += qtnfmac_pearl_pcie.o
+obj-$(CONFIG_QTNFMAC_PCIE) += qtnfmac_pcie.o
 
-qtnfmac_pearl_pcie-objs += \
+qtnfmac_pcie-objs += \
shm_ipc.o \
pcie/pcie.o \
pcie/pearl_pcie.o
 
-qtnfmac_pearl_pcie-$(CONFIG_DEBUG_FS) += debug.o
+qtnfmac_pcie-$(CONFIG_DEBUG_FS) += debug.o
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index 16795dbe475b..70dd8da5b0dc 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /* Copyright (c) 2018 Quantenna Communications, Inc. All rights reserved. */
 
+#include 
 #include 
 #include 
 #include 
@@ -15,14 +16,37 @@
 #include "shm_ipc.h"
 #include "core.h"
 #include "debug.h"
-
-#undef pr_fmt
-#define pr_fmt(fmt)"qtnf_pcie: %s: " fmt, __func__
+#include "util.h"
+#include "qtn_hw_ids.h"
 
 #define QTN_SYSCTL_BAR 0
 #define QTN_SHMEM_BAR  2
 #define QTN_DMA_BAR3
 
+#define QTN_PCIE_MAX_FW_BUFSZ  (1 * 1024 * 1024)
+
+static bool use_msi = true;
+module_param(use_msi, bool, 0644);
+MODULE_PARM_DESC(use_msi, "set 0 to use legacy interrupt");
+
+static unsigned int tx_bd_size_param;
+module_param(tx_bd_size_param, uint, 0644);
+MODULE_PARM_DESC(tx_bd_size_param, "Tx descriptors queue size");
+
+static unsigned int rx_bd_size_param = 256;
+module_param(rx_bd_size_param, uint, 0644);
+MODULE_PARM_DESC(rx_bd_size_param, "Rx descriptors queue size");
+
+static u8 flashboot = 1;
+module_param(flashboot, byte, 0644);
+MODULE_PARM_DESC(flashboot, "set to 0 to use FW binary file on FS");
+
+static unsigned int fw_blksize_param = QTN_PCIE_MAX_FW_BUFSZ;
+module_param(fw_blksize_param, uint, 0644);
+MODULE_PARM_DESC(fw_blksize_param, "firmware loading block size in bytes");
+
+#define DRV_NAME   "qtnfmac_pcie"
+
 int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb)
 {
struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
@@ -58,7 +82,7 @@ int qtnf_pcie_alloc_skb_array(struct qtnf_pcie_bus_priv *priv)
return 0;
 }
 
-void qtnf_pcie_bringup_fw_async(struct qtnf_bus *bus)
+static void qtnf_pcie_bringup_fw_async(struct qtnf_bus *bus)
 {
struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
struct pci_dev *pdev = priv->pdev;
@@ -72,7 +96,7 @@ static int qtnf_dbg_mps_show(struct seq_file *s, void *data)
struct qtnf_bus *bus = dev_get_drvdata(s->private);
struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
 
-   seq_printf(s, "%d\n", priv->mps);
+   seq_printf(s, "%d\n", pcie_get_mps(priv->pdev));
 
return 0;
 }
@@ -104,8 +128,7 @@ 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,
-   const char *drv_name)
+void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success)
 {
struct 

[PATCH v2 0/2] qtnfmac: add support for QSR1000/QSR2000 (aka Topaz) chipsets

2018-10-16 Thread Sergey Matyukevich
Hello Kalle and all, 

Here is the next update for qtnfmac driver. This patchset adds support
for the previous generation of Quantenna wireless cards,
namely QSR1000/QSR2000 family of PCIe devices.

The summary of changes is as follows:
- the last bits of pcie layer unification work:
  -- extract remaining code that can be shared across various PCIe chips
  -- cleanup/rename: get ready to support another chipset
- add support for QSR1000/QSR2000 devices

Regards,
Sergey

Changes v1 -> v2
- simplify Kconfig options for PCIe backend driver

 Kconfig|   15 
 Makefile   |9 
 pcie/pcie.c|  282 +++
 pcie/pcie_priv.h   |   20 
 pcie/pearl_pcie.c  |  211 ++--
 pcie/topaz_pcie.c  | 1219 +
 pcie/topaz_pcie_ipc.h  |   94 +++
 pcie/topaz_pcie_regs.h |   45 +
 qtn_hw_ids.h   |4 
 util.c |   18 
 util.h |2 
 11 files changed, 1664 insertions(+), 255 deletions(-)


Re: [PATCH 5/5] qtnfmac: add support for Topaz chipsets

2018-10-15 Thread Sergey Matyukevich
> > +config QTNFMAC_TOPAZ_PCIE
> > + tristate "Quantenna QSR1000/QSR2000 PCIe support"
> > + default n
> > + depends on PCI && CFG80211
> > + select QTNFMAC
> > + select FW_LOADER
> > + select CRC32
> > + help
> > +   This option adds support for wireless adapters based on Quantenna
> > +   802.11ac QSR1000/QSR2000 (aka Topaz) FullMAC chipset
> > +   running over PCIe.
> > +
> > +   If you choose to build it as a module, two modules will be built:
> > +   qtnfmac.ko and qtnfmac_pcie.ko.

> I'm not really fond of adding a Kconfig option for every supported
> hardware version unless there are very good reasons (memory savings
> etc). So is this really needed?

Yes, the idea was to save some memory building pcie backend for
the requested chip family only.
 
> A much better approach would be to have a generic QTNFMAC_PCIE option
> which can be used to include or exclude all PCI code.

Ok, sounds reasonable. Three Kconfig options for the single qtnfmac_pcie
module is way too much. We will drop chipset specific Kconfig knobs in
v2, keeping single Kconfig option for qtnfmac_pcie backend as a whole.

Thanks,
Sergey


Re: [bug report] qtnfmac: cleanup and unify command error handling

2018-10-10 Thread Sergey Matyukevich
Hello Dan,

> The patch c6ed298ffe09: "qtnfmac: cleanup and unify command error
> handling" from Oct 5, 2018, leads to the following static checker
> warning:
> 
> drivers/net/wireless/quantenna/qtnfmac/commands.c:132 
> qtnf_cmd_send_with_reply()
> warn: variable dereferenced before check 'resp' (see line 117)

Thanks for the report! We will queue a fix into the next patch set.

Regards,
Sergey


Re: [PATCH 5/5] qtnfmac: add support for Topaz chipsets

2018-10-08 Thread Sergey Matyukevich
> > This patch adds support for QSR1000/QSR2000 family of chipsets
> > to qtnfmac_pcie platform driver.
> >
> > QSR1000/QSR2000 (aka Topaz) is a family of 80MHz, 11ac Wave2,
> > 4x4/2x4/2x2 chips, including single and dual band devices.
> > Depending on specific chip model and firmware in use, either
> > STA or both STA and AP modes are supported.
> >
> > Patch adds Topaz support to qtnfmac_pcie driver. It is possible
> > to enable both Topaz and Pearl support in kernel configuration.
> > In that case proper platform bus will be selected on probing
> > based on chip ID.
> >
> > Signed-off-by: Igor Mitsyanko 
> > Signed-off-by: Sergey Matyukevich 
> > Signed-off-by: Andrey Shevchenko 
> 
> [...]
> 
> > --- a/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h
> > +++ b/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h
> > @@ -24,6 +24,7 @@
> >  /* PCIE Device IDs */
> >
> >  #define  PCIE_DEVICE_ID_QTN_PEARL(0x0008)
> > +#define  PCIE_DEVICE_ID_QTN_TOPAZ(0x0008)
> 
> Same ids for both, is this really correct?

Yes, that is correct. This is one of the reasons why we switched
to chip ID for card identification. In fact, it can be configured
in firmware, but default PCI ID values are the same for both chipsets.

Regards,
Sergey


[PATCH 4/5] qtnfmac_pcie: use single PCIe driver for all platforms

2018-10-08 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Single PCIe driver can identify hardware type by reading CHIP ID at
probe time and invoking a correct initialization sequence.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/Kconfig |   8 +-
 drivers/net/wireless/quantenna/qtnfmac/Makefile|  10 +-
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 281 +++--
 .../wireless/quantenna/qtnfmac/pcie/pcie_priv.h|  19 +-
 .../wireless/quantenna/qtnfmac/pcie/pearl_pcie.c   | 211 +---
 drivers/net/wireless/quantenna/qtnfmac/util.c  |  16 ++
 drivers/net/wireless/quantenna/qtnfmac/util.h  |   2 +
 7 files changed, 298 insertions(+), 249 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/Kconfig 
b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
index b8c12a5f16b4..f43b236b7c0b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/Kconfig
+++ b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
@@ -4,6 +4,12 @@ config QTNFMAC
default m if QTNFMAC_PEARL_PCIE=m
default y if QTNFMAC_PEARL_PCIE=y
 
+config QTNFMAC_PCIE
+   tristate
+   depends on QTNFMAC_PEARL_PCIE
+   default m if QTNFMAC_PEARL_PCIE=m
+   default y if QTNFMAC_PEARL_PCIE=y
+
 config QTNFMAC_PEARL_PCIE
tristate "Quantenna QSR10g PCIe support"
default n
@@ -16,4 +22,4 @@ config QTNFMAC_PEARL_PCIE
  802.11ac QSR10g (aka Pearl) FullMAC chipset running over PCIe.
 
  If you choose to build it as a module, two modules will be built:
- qtnfmac.ko and qtnfmac_pearl_pcie.ko.
+ qtnfmac.ko and qtnfmac_pcie.ko.
diff --git a/drivers/net/wireless/quantenna/qtnfmac/Makefile 
b/drivers/net/wireless/quantenna/qtnfmac/Makefile
index 17cd7adb4109..e295aa55619f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/Makefile
+++ b/drivers/net/wireless/quantenna/qtnfmac/Makefile
@@ -19,11 +19,11 @@ qtnfmac-objs += \
 
 #
 
-obj-$(CONFIG_QTNFMAC_PEARL_PCIE) += qtnfmac_pearl_pcie.o
+obj-$(CONFIG_QTNFMAC_PCIE) += qtnfmac_pcie.o
 
-qtnfmac_pearl_pcie-objs += \
+qtnfmac_pcie-objs += \
shm_ipc.o \
-   pcie/pcie.o \
-   pcie/pearl_pcie.o
+   pcie/pcie.o
 
-qtnfmac_pearl_pcie-$(CONFIG_DEBUG_FS) += debug.o
+qtnfmac_pcie-$(CONFIG_DEBUG_FS) += debug.o
+qtnfmac_pcie-$(CONFIG_QTNFMAC_PEARL_PCIE) += pcie/pearl_pcie.o
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index 16795dbe475b..b589c01d9bbe 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /* Copyright (c) 2018 Quantenna Communications, Inc. All rights reserved. */
 
+#include 
 #include 
 #include 
 #include 
@@ -15,14 +16,37 @@
 #include "shm_ipc.h"
 #include "core.h"
 #include "debug.h"
-
-#undef pr_fmt
-#define pr_fmt(fmt)"qtnf_pcie: %s: " fmt, __func__
+#include "util.h"
+#include "qtn_hw_ids.h"
 
 #define QTN_SYSCTL_BAR 0
 #define QTN_SHMEM_BAR  2
 #define QTN_DMA_BAR3
 
+#define QTN_PCIE_MAX_FW_BUFSZ  (1 * 1024 * 1024)
+
+static bool use_msi = true;
+module_param(use_msi, bool, 0644);
+MODULE_PARM_DESC(use_msi, "set 0 to use legacy interrupt");
+
+static unsigned int tx_bd_size_param;
+module_param(tx_bd_size_param, uint, 0644);
+MODULE_PARM_DESC(tx_bd_size_param, "Tx descriptors queue size");
+
+static unsigned int rx_bd_size_param = 256;
+module_param(rx_bd_size_param, uint, 0644);
+MODULE_PARM_DESC(rx_bd_size_param, "Rx descriptors queue size");
+
+static u8 flashboot = 1;
+module_param(flashboot, byte, 0644);
+MODULE_PARM_DESC(flashboot, "set to 0 to use FW binary file on FS");
+
+static unsigned int fw_blksize_param = QTN_PCIE_MAX_FW_BUFSZ;
+module_param(fw_blksize_param, uint, 0644);
+MODULE_PARM_DESC(fw_blksize_param, "firmware loading block size in bytes");
+
+#define DRV_NAME   "qtnfmac_pcie"
+
 int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb)
 {
struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
@@ -58,7 +82,7 @@ int qtnf_pcie_alloc_skb_array(struct qtnf_pcie_bus_priv *priv)
return 0;
 }
 
-void qtnf_pcie_bringup_fw_async(struct qtnf_bus *bus)
+static void qtnf_pcie_bringup_fw_async(struct qtnf_bus *bus)
 {
struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
struct pci_dev *pdev = priv->pdev;
@@ -72,7 +96,7 @@ static int qtnf_dbg_mps_show(struct seq_file *s, void *data)
struct qtnf_bus *bus = dev_get_drvdata(s->private);
struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
 
-   seq_printf(s, "%d\n", priv->mps);
+   seq_printf(s, "%d\n", pcie_get_mps(priv->pdev));
 
return 0;
 }
@@ -104,8 +128,7 @@ 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,
-   const char *drv_name)
+void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool 

[PATCH 0/5] qtnfmac: add support for QSR1000/QSR2000 (aka Topaz) chipsets

2018-10-08 Thread Sergey Matyukevich
Hello Kalle and all, 

Here is the next update for qtnfmac driver. This patch set adds
support for the previous generation of Quantenna wireless cards,
namely QSR1000/QSR2000 family of devices.

The summary of changes is as follows:
- the last bits of pcie layer unification work:
  -- extract remaining code that can be shared across various PCIe chips
  -- cleanup/rename: get ready to support another chipset
- add support for QSR1000/QSR2000 devices
- minor cleanups: Kconfig, SPDX, unused register definitions

Regards,
Sergey

 Kconfig|2 
 qtnfmac/Kconfig|   31 -
 qtnfmac/Makefile   |   11 
 qtnfmac/pcie/pcie.c|  286 ++---
 qtnfmac/pcie/pcie_priv.h   |   20 
 qtnfmac/pcie/pearl_pcie.c  |  228 ++-
 qtnfmac/pcie/pearl_pcie_ipc.h  |   22 
 qtnfmac/pcie/pearl_pcie_regs.h |  245 
 qtnfmac/pcie/topaz_pcie.c  | 1219 +
 qtnfmac/pcie/topaz_pcie_ipc.h  |   94 +++
 qtnfmac/pcie/topaz_pcie_regs.h |   45 +
 qtnfmac/qtn_hw_ids.h   |3 
 qtnfmac/util.c |   18 
 qtnfmac/util.h |2 
 14 files changed, 1697 insertions(+), 529 deletions(-)


[PATCH 1/5] qtnfmac: use 'help' in Kconfig

2018-10-08 Thread Sergey Matyukevich
Fix checkpatch warning: use preferred 'help' option in Kconfig.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/Kconfig | 2 +-
 drivers/net/wireless/quantenna/qtnfmac/Kconfig | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/Kconfig 
b/drivers/net/wireless/quantenna/Kconfig
index de84ce125c26..7628d9c1ea6a 100644
--- a/drivers/net/wireless/quantenna/Kconfig
+++ b/drivers/net/wireless/quantenna/Kconfig
@@ -1,7 +1,7 @@
 config WLAN_VENDOR_QUANTENNA
bool "Quantenna wireless cards support"
default y
-   ---help---
+   help
  If you have a wireless card belonging to this class, say Y.
 
  Note that the answer to this question doesn't directly affect the
diff --git a/drivers/net/wireless/quantenna/qtnfmac/Kconfig 
b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
index 8d1492a90bd1..b8c12a5f16b4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/Kconfig
+++ b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
@@ -11,7 +11,7 @@ config QTNFMAC_PEARL_PCIE
select QTNFMAC
select FW_LOADER
select CRC32
-   ---help---
+   help
  This option adds support for wireless adapters based on Quantenna
  802.11ac QSR10g (aka Pearl) FullMAC chipset running over PCIe.
 
-- 
2.11.0



[PATCH 3/5] qtnfmac_pcie: cleanup Pearl platform headers

2018-10-08 Thread Sergey Matyukevich
Remove redundant information from Pearl platform headers.

Signed-off-by: Sergey Matyukevich 
---
 .../quantenna/qtnfmac/pcie/pearl_pcie_ipc.h|   5 -
 .../quantenna/qtnfmac/pcie/pearl_pcie_regs.h   | 228 +
 2 files changed, 3 insertions(+), 230 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h
index 7ecaa69fe018..634480fe6a64 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h
@@ -72,11 +72,6 @@
 
 #define QTN_EP_LHOST_TQE_PORT  4
 
-enum qtnf_pcie_bda_ipc_flags {
-   QTN_PCIE_IPC_FLAG_HBM_MAGIC = BIT(0),
-   QTN_PCIE_IPC_FLAG_SHM_PIO   = BIT(1),
-};
-
 enum qtnf_fw_loadtype {
QTN_FW_DBEGIN,
QTN_FW_DSUB,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h
index 1e6693c17006..6e9a5c61d46f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h
@@ -4,12 +4,7 @@
 #ifndef __PEARL_PCIE_H
 #define __PEARL_PCIE_H
 
-#definePCIE_GEN2_BASE  (0xe900)
-#definePCIE_GEN3_BASE  (0xe700)
-
-#define PEARL_CUR_PCIE_BASE(PCIE_GEN2_BASE)
-#define PCIE_HDP_OFFSET(0x2000)
-
+/* Pearl PCIe HDP registers */
 #define PCIE_HDP_CTRL(base)((base) + 0x2c00)
 #define PCIE_HDP_AXI_CTRL(base)((base) + 0x2c04)
 #define PCIE_HDP_HOST_WR_DESC0(base)   ((base) + 0x2c10)
@@ -73,7 +68,7 @@
 #define PCIE_HDP_TX_HOST_Q_RD_PTR(base)((base) + 0x2d3c)
 #define PCIE_HDP_TX_HOST_Q_STS(base)   ((base) + 0x2d40)
 
-/* Host HBM pool registers */
+/* Pearl PCIe HBM pool registers */
 #define PCIE_HHBM_CSR_REG(base)((base) + 0x2e00)
 #define PCIE_HHBM_Q_BASE_REG(base) ((base) + 0x2e04)
 #define PCIE_HHBM_Q_LIMIT_REG(base)((base) + 0x2e08)
@@ -91,230 +86,13 @@
 #define HBM_INT_STATUS(base)   ((base) + 0x2f9c)
 #define PCIE_HHBM_POOL_CNFIG(base) ((base) + 0x2f9c)
 
-/* host HBM bit field definition */
+/* Pearl PCIe HBM bit field definitions */
 #define HHBM_CONFIG_SOFT_RESET (BIT(8))
 #define HHBM_WR_REQ(BIT(0))
 #define HHBM_RD_REQ(BIT(1))
 #define HHBM_DONE  (BIT(31))
 #define HHBM_64BIT (BIT(10))
 
-/* offsets for dual PCIE */
-#define PCIE_PORT_LINK_CTL(base)   ((base) + 0x0710)
-#define PCIE_GEN2_CTL(base)((base) + 0x080C)
-#define PCIE_GEN3_OFF(base)((base) + 0x0890)
-#define PCIE_ATU_CTRL1(base)   ((base) + 0x0904)
-#define PCIE_ATU_CTRL2(base)   ((base) + 0x0908)
-#define PCIE_ATU_BASE_LOW(base)((base) + 0x090C)
-#define PCIE_ATU_BASE_HIGH(base)   ((base) + 0x0910)
-#define PCIE_ATU_BASE_LIMIT(base)  ((base) + 0x0914)
-#define PCIE_ATU_TGT_LOW(base) ((base) + 0x0918)
-#define PCIE_ATU_TGT_HIGH(base)((base) + 0x091C)
-#define PCIE_DMA_WR_ENABLE(base)   ((base) + 0x097C)
-#define PCIE_DMA_WR_CHWTLOW(base)  ((base) + 0x0988)
-#define PCIE_DMA_WR_CHWTHIG(base)  ((base) + 0x098C)
-#define PCIE_DMA_WR_INTSTS(base)   ((base) + 0x09BC)
-#define PCIE_DMA_WR_INTMASK(base)  ((base) + 0x09C4)
-#define PCIE_DMA_WR_INTCLER(base)  ((base) + 0x09C8)
-#define PCIE_DMA_WR_DONE_IMWR_ADDR_L(base) ((base) + 0x09D0)
-#define PCIE_DMA_WR_DONE_IMWR_ADDR_H(base) ((base) + 0x09D4)
-#define PCIE_DMA_WR_ABORT_IMWR_ADDR_L(base)((base) + 0x09D8)
-#define PCIE_DMA_WR_ABORT_IMWR_ADDR_H(base)((base) + 0x09DC)
-#define PCIE_DMA_WR_IMWR_DATA(base)((base) + 0x09E0)
-#define PCIE_DMA_WR_LL_ERR_EN(base)((base) + 0x0A00)
-#define PCIE_DMA_WR_DOORBELL(base) ((base) + 0x0980)
-#define PCIE_DMA_RD_ENABLE(base)   ((base) + 0x099C)
-#define PCIE_DMA_RD_DOORBELL(base) ((base) + 0x09A0)
-#define PCIE_DMA_RD_CHWTLOW(base)  ((base) + 0x09A8)
-#define PCIE_DMA_RD_CHWTHIG(base)  ((base) + 0x09AC)
-#define PCIE_DMA_RD_INTSTS(base)   ((base) + 0x0A10)
-#define PCIE_DMA_RD_INTMASK(base)  ((base) + 0x0A18)
-#define PCIE_DMA_RD_INTCLER(base)  ((base) + 0x0A1C)
-#define PCIE_DMA_RD_ERR_STS_L(base)((base) + 0x0A24)
-#define PCIE_DMA_RD_ERR_STS_H(base)((base) + 0x0A28)
-#define PCIE_DMA_RD_LL_ERR_EN(base)((base) + 0x0A34)
-#define PCIE_DMA_RD_DONE_IMWR_ADDR_L(base) ((base

[PATCH 2/5] qtnfmac: use SPDX identifier for pcie bus layer files

2018-10-08 Thread Sergey Matyukevich
Change pcie bus layer licensing information to SPDX format.

Signed-off-by: Sergey Matyukevich 
---
 .../net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c| 17 ++---
 .../wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h| 17 ++---
 .../wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h   | 17 ++---
 3 files changed, 6 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
index 5aca12a51fe3..95c7b95c6f8a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 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) 2018 Quantenna Communications */
 
 #include 
 #include 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h
index f21e97ede090..7ecaa69fe018 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015-2016 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 */
 
 #ifndef _QTN_FMAC_PCIE_IPC_H_
 #define _QTN_FMAC_PCIE_IPC_H_
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h
index 0bfe285b6b48..1e6693c17006 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2015 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 Quantenna Communications */
 
 #ifndef __PEARL_PCIE_H
 #define __PEARL_PCIE_H
-- 
2.11.0



[PATCH 5/5] qtnfmac: add support for Topaz chipsets

2018-10-08 Thread Sergey Matyukevich
This patch adds support for QSR1000/QSR2000 family of chipsets
to qtnfmac_pcie platform driver.

QSR1000/QSR2000 (aka Topaz) is a family of 80MHz, 11ac Wave2,
4x4/2x4/2x2 chips, including single and dual band devices.
Depending on specific chip model and firmware in use, either
STA or both STA and AP modes are supported.

Patch adds Topaz support to qtnfmac_pcie driver. It is possible
to enable both Topaz and Pearl support in kernel configuration.
In that case proper platform bus will be selected on probing
based on chip ID.

Signed-off-by: Igor Mitsyanko 
Signed-off-by: Sergey Matyukevich 
Signed-off-by: Andrey Shevchenko 
---
 drivers/net/wireless/quantenna/qtnfmac/Kconfig |   27 +-
 drivers/net/wireless/quantenna/qtnfmac/Makefile|1 +
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c |5 +
 .../wireless/quantenna/qtnfmac/pcie/pcie_priv.h|1 +
 .../wireless/quantenna/qtnfmac/pcie/topaz_pcie.c   | 1219 
 .../quantenna/qtnfmac/pcie/topaz_pcie_ipc.h|   94 ++
 .../quantenna/qtnfmac/pcie/topaz_pcie_regs.h   |   45 +
 .../net/wireless/quantenna/qtnfmac/qtn_hw_ids.h|3 +
 drivers/net/wireless/quantenna/qtnfmac/util.c  |2 +
 9 files changed, 1391 insertions(+), 6 deletions(-)
 create mode 100644 drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
 create mode 100644 drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie_ipc.h
 create mode 100644 
drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie_regs.h

diff --git a/drivers/net/wireless/quantenna/qtnfmac/Kconfig 
b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
index f43b236b7c0b..df2fd0a1ab5c 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/Kconfig
+++ b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
@@ -1,14 +1,14 @@
 config QTNFMAC
tristate
-   depends on QTNFMAC_PEARL_PCIE
-   default m if QTNFMAC_PEARL_PCIE=m
-   default y if QTNFMAC_PEARL_PCIE=y
+   depends on QTNFMAC_PEARL_PCIE || QTNFMAC_TOPAZ_PCIE
+   default m if QTNFMAC_PEARL_PCIE=m || QTNFMAC_TOPAZ_PCIE=m
+   default y if QTNFMAC_PEARL_PCIE=y || QTNFMAC_TOPAZ_PCIE=y
 
 config QTNFMAC_PCIE
tristate
-   depends on QTNFMAC_PEARL_PCIE
-   default m if QTNFMAC_PEARL_PCIE=m
-   default y if QTNFMAC_PEARL_PCIE=y
+   depends on QTNFMAC_PEARL_PCIE || QTNFMAC_TOPAZ_PCIE
+   default m if QTNFMAC_PEARL_PCIE=m || QTNFMAC_TOPAZ_PCIE=m
+   default y if QTNFMAC_PEARL_PCIE=y || QTNFMAC_TOPAZ_PCIE=y
 
 config QTNFMAC_PEARL_PCIE
tristate "Quantenna QSR10g PCIe support"
@@ -23,3 +23,18 @@ config QTNFMAC_PEARL_PCIE
 
  If you choose to build it as a module, two modules will be built:
  qtnfmac.ko and qtnfmac_pcie.ko.
+
+config QTNFMAC_TOPAZ_PCIE
+   tristate "Quantenna QSR1000/QSR2000 PCIe support"
+   default n
+   depends on PCI && CFG80211
+   select QTNFMAC
+   select FW_LOADER
+   select CRC32
+   help
+ This option adds support for wireless adapters based on Quantenna
+ 802.11ac QSR1000/QSR2000 (aka Topaz) FullMAC chipset
+ running over PCIe.
+
+ If you choose to build it as a module, two modules will be built:
+ qtnfmac.ko and qtnfmac_pcie.ko.
diff --git a/drivers/net/wireless/quantenna/qtnfmac/Makefile 
b/drivers/net/wireless/quantenna/qtnfmac/Makefile
index e295aa55619f..4de95330e793 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/Makefile
+++ b/drivers/net/wireless/quantenna/qtnfmac/Makefile
@@ -27,3 +27,4 @@ qtnfmac_pcie-objs += \
 
 qtnfmac_pcie-$(CONFIG_DEBUG_FS) += debug.o
 qtnfmac_pcie-$(CONFIG_QTNFMAC_PEARL_PCIE) += pcie/pearl_pcie.o
+qtnfmac_pcie-$(CONFIG_QTNFMAC_TOPAZ_PCIE) += pcie/topaz_pcie.o
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index b589c01d9bbe..a139db398fd4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -332,6 +332,11 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
bus = qtnf_pcie_pearl_alloc(pdev);
break;
 #endif
+#if IS_ENABLED(CONFIG_QTNFMAC_TOPAZ_PCIE)
+   case QTN_CHIP_ID_TOPAZ:
+   bus = qtnf_pcie_topaz_alloc(pdev);
+   break;
+#endif
default:
pr_err("unsupported chip ID 0x%x\n", chipid);
return -ENOTSUPP;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h
index 7c742c56efaf..bbc074e1f34d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h
@@ -76,6 +76,7 @@ void qtnf_pcie_init_shm_ipc(struct qtnf_pcie_bus_priv *priv,
struct qtnf_shm_ipc_region __iomem *ipc_rx_reg,
const struct qtnf_shm_ipc_int *ipc_int);
 struct 

[PATCH v2 11/13] qtnfmac: add support for scan dwell time configuration

2018-10-05 Thread Sergey Matyukevich
Firmware supports scan dwell time tuning for various types of scans.
Enable support for this feature:
- advertise capability to configure channel dwell time to host
- pass scan dwell parameters to wireless card in scan request

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 9845cf287118..18179965bd38 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1101,6 +1101,10 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
 
+   if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_DWELL)
+   wiphy_ext_feature_set(wiphy,
+ NL80211_EXT_FEATURE_SET_SCAN_DWELL);
+
wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 8fb15cbf5005..bfdc1ad30c13 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2203,6 +2203,15 @@ 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 699157100309..8d62addea895 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -80,6 +80,7 @@ enum qlink_hw_capab {
QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR = BIT(3),
QLINK_HW_CAPAB_PWR_MGMT = BIT(4),
QLINK_HW_CAPAB_OBSS_SCAN= BIT(5),
+   QLINK_HW_CAPAB_SCAN_DWELL   = BIT(6),
 };
 
 enum qlink_iface_type {
@@ -1152,6 +1153,7 @@ enum qlink_tlv_id {
QTN_TLV_ID_WOWLAN_CAPAB = 0x0410,
QTN_TLV_ID_WOWLAN_PATTERN   = 0x0411,
QTN_TLV_ID_SCAN_FLUSH   = 0x0412,
+   QTN_TLV_ID_SCAN_DWELL   = 0x0413,
 };
 
 struct qlink_tlv_hdr {
-- 
2.11.0



[PATCH v2 12/13] qtnfmac: drop redundant data copy in control path

2018-10-05 Thread Sergey Matyukevich
Command responses and events from the firmware are copied twice in
control path: at first in shm core (qtnf_shm_handle_new_data) and
then in pcie bus drivers (qtnf_pcie_control_rx_callback). There
is no need to copy this data twice, it can be done only once
in rx callbacks.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c |  5 +++--
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c   | 13 ++---
 drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h   |  4 +---
 3 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index d1637f2354a6..16795dbe475b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -242,7 +242,8 @@ static int qtnf_pcie_init_memory(struct qtnf_pcie_bus_priv 
*priv)
return 0;
 }
 
-static void qtnf_pcie_control_rx_callback(void *arg, const u8 *buf, size_t len)
+static void qtnf_pcie_control_rx_callback(void *arg, const u8 __iomem *buf,
+ size_t len)
 {
struct qtnf_pcie_bus_priv *priv = arg;
struct qtnf_bus *bus = pci_get_drvdata(priv->pdev);
@@ -260,7 +261,7 @@ static void qtnf_pcie_control_rx_callback(void *arg, const 
u8 *buf, size_t len)
return;
}
 
-   skb_put_data(skb, buf, len);
+   memcpy_fromio(skb_put(skb, len), buf, len);
 
qtnf_trans_handle_rx_ctl_packet(bus, skb);
 }
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c 
b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
index aa106dd0a14b..2ec334199c2b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
@@ -42,19 +42,18 @@ static void qtnf_shm_handle_new_data(struct qtnf_shm_ipc 
*ipc)
if (unlikely(size == 0 || size > QTN_IPC_MAX_DATA_SZ)) {
pr_err("wrong rx packet size: %zu\n", size);
rx_buff_ok = false;
-   } else {
-   memcpy_fromio(ipc->rx_data, ipc->shm_region->data, size);
+   }
+
+   if (likely(rx_buff_ok)) {
+   ipc->rx_packet_count++;
+   ipc->rx_callback.fn(ipc->rx_callback.arg,
+   ipc->shm_region->data, size);
}
 
writel(QTNF_SHM_IPC_ACK, _reg_hdr->flags);
readl(_reg_hdr->flags); /* flush PCIe write */
 
ipc->interrupt.fn(ipc->interrupt.arg);
-
-   if (likely(rx_buff_ok)) {
-   ipc->rx_packet_count++;
-   ipc->rx_callback.fn(ipc->rx_callback.arg, ipc->rx_data, size);
-   }
 }
 
 static void qtnf_shm_ipc_irq_work(struct work_struct *work)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h 
b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
index 453dd6477b12..c2a3702a9ee7 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
@@ -32,7 +32,7 @@ struct qtnf_shm_ipc_int {
 };
 
 struct qtnf_shm_ipc_rx_callback {
-   void (*fn)(void *arg, const u8 *buf, size_t len);
+   void (*fn)(void *arg, const u8 __iomem *buf, size_t len);
void *arg;
 };
 
@@ -51,8 +51,6 @@ struct qtnf_shm_ipc {
 
u8 waiting_for_ack;
 
-   u8 rx_data[QTN_IPC_MAX_DATA_SZ] __aligned(sizeof(u32));
-
struct qtnf_shm_ipc_int interrupt;
struct qtnf_shm_ipc_rx_callback rx_callback;
 
-- 
2.11.0



[PATCH v2 13/13] qtnfmac: implement dump_station support for STA mode

2018-10-05 Thread Sergey Matyukevich
Current implementation of dump_station cfg80211 callback supports
AP mode only. Add support for STA mode as well: by default in STA
mode this callback is supposed to return AP on managed interface.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 30 ---
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 18179965bd38..51b33ec78fac 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -480,19 +480,31 @@ qtnf_dump_station(struct wiphy *wiphy, struct net_device 
*dev,
const struct qtnf_sta_node *sta_node;
int ret;
 
-   sta_node = qtnf_sta_list_lookup_index(>sta_list, idx);
+   switch (vif->wdev.iftype) {
+   case NL80211_IFTYPE_STATION:
+   if (idx != 0 || !vif->wdev.current_bss)
+   return -ENOENT;
 
-   if (unlikely(!sta_node))
-   return -ENOENT;
+   ether_addr_copy(mac, vif->bssid);
+   break;
+   case NL80211_IFTYPE_AP:
+   sta_node = qtnf_sta_list_lookup_index(>sta_list, idx);
+   if (unlikely(!sta_node))
+   return -ENOENT;
 
-   ether_addr_copy(mac, sta_node->mac_addr);
+   ether_addr_copy(mac, sta_node->mac_addr);
+   break;
+   default:
+   return -ENOTSUPP;
+   }
 
-   ret = qtnf_cmd_get_sta_info(vif, sta_node->mac_addr, sinfo);
+   ret = qtnf_cmd_get_sta_info(vif, mac, sinfo);
 
-   if (unlikely(ret == -ENOENT)) {
-   qtnf_sta_list_del(vif, mac);
-   cfg80211_del_sta(vif->netdev, mac, GFP_KERNEL);
-   sinfo->filled = 0;
+   if (vif->wdev.iftype == NL80211_IFTYPE_AP) {
+   if (ret == -ENOENT) {
+   cfg80211_del_sta(vif->netdev, mac, GFP_KERNEL);
+   sinfo->filled = 0;
+   }
}
 
sinfo->generation = vif->generation;
-- 
2.11.0



[PATCH v2 09/13] qtnfmac: drop error reports for out-of-bounds key indexes

2018-10-05 Thread Sergey Matyukevich
On disconnect wireless core attempts to remove all the supported keys.
Following cfg80211_ops conventions, firmware returns -ENOENT code
for the out-of-bound key indexes. This is a normal behavior,
so no need to report errors for this case.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 8ecd37ddc0f9..9845cf287118 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -523,9 +523,16 @@ static int qtnf_del_key(struct wiphy *wiphy, struct 
net_device *dev,
int ret;
 
ret = qtnf_cmd_send_del_key(vif, key_index, pairwise, mac_addr);
-   if (ret)
-   pr_err("VIF%u.%u: failed to delete key: idx=%u pw=%u\n",
-  vif->mac->macid, vif->vifid, key_index, pairwise);
+   if (ret) {
+   if (ret == -ENOENT) {
+   pr_debug("VIF%u.%u: key index %d out of bounds\n",
+vif->mac->macid, vif->vifid, key_index);
+   } else {
+   pr_err("VIF%u.%u: failed to delete key: idx=%u pw=%u\n",
+  vif->mac->macid, vif->vifid,
+  key_index, pairwise);
+   }
+   }
 
return ret;
 }
-- 
2.11.0



[PATCH v2 03/13] qtnfmac: request userspace to do OBSS scanning if FW can not

2018-10-05 Thread Sergey Matyukevich
From: Igor Mitsyanko 

In case firmware reports that it can not do OBSS scanning for 40MHz
2.4GHz channels itself, tell userpsace to do that instead by setting
NL80211_FEATURE_NEED_OBSS_SCAN flag.

Signed-off-by: Igor mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 3 +++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 2 ++
 2 files changed, 5 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 87f48b7fb673..c4961e16d91a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1099,6 +1099,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR)
wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
 
+   if (!(hw_info->hw_capab & QLINK_HW_CAPAB_OBSS_SCAN))
+   wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN;
+
 #ifdef CONFIG_PM
if (macinfo->wowlan)
wiphy->wowlan = macinfo->wowlan;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 99d37e3efba6..c5ae4ea9a47a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -71,6 +71,7 @@ struct qlink_msg_header {
  * @QLINK_HW_CAPAB_DFS_OFFLOAD: device implements DFS offload functionality
  * @QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR: device supports MAC Address
  * Randomization in probe requests.
+ * @QLINK_HW_CAPAB_OBSS_SCAN: device can perform OBSS scanning.
  */
 enum qlink_hw_capab {
QLINK_HW_CAPAB_REG_UPDATE   = BIT(0),
@@ -78,6 +79,7 @@ enum qlink_hw_capab {
QLINK_HW_CAPAB_DFS_OFFLOAD  = BIT(2),
QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR = BIT(3),
QLINK_HW_CAPAB_PWR_MGMT = BIT(4),
+   QLINK_HW_CAPAB_OBSS_SCAN= BIT(5),
 };
 
 enum qlink_iface_type {
-- 
2.11.0



[PATCH v2 08/13] qtnfmac: inform wireless core about supported extended capabilities

2018-10-05 Thread Sergey Matyukevich
Driver retrieves information about supported extended capabilities
from wireless card. However this information is not propagated
further to Linux wireless core. Fix this by setting extended
capabilities fields of wiphy structure.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |  9 +
 drivers/net/wireless/quantenna/qtnfmac/commands.c |  3 +--
 drivers/net/wireless/quantenna/qtnfmac/core.c | 16 ++--
 drivers/net/wireless/quantenna/qtnfmac/core.h |  1 +
 4 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 8b30d651cbe3..8ecd37ddc0f9 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1129,6 +1129,15 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
}
 
+   if (mac->macinfo.extended_capabilities_len) {
+   wiphy->extended_capabilities =
+   mac->macinfo.extended_capabilities;
+   wiphy->extended_capabilities_mask =
+   mac->macinfo.extended_capabilities_mask;
+   wiphy->extended_capabilities_len =
+   mac->macinfo.extended_capabilities_len;
+   }
+
strlcpy(wiphy->fw_version, hw_info->fw_version,
sizeof(wiphy->fw_version));
wiphy->hw_version = hw_info->hw_version;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 74edb5a0ae19..8dbd6c45c233 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1273,8 +1273,7 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac 
*mac,
ext_capa_mask = NULL;
}
 
-   kfree(mac->macinfo.extended_capabilities);
-   kfree(mac->macinfo.extended_capabilities_mask);
+   qtnf_mac_ext_caps_free(mac);
mac->macinfo.extended_capabilities = ext_capa;
mac->macinfo.extended_capabilities_mask = ext_capa_mask;
mac->macinfo.extended_capabilities_len = ext_capa_len;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
b/drivers/net/wireless/quantenna/qtnfmac/core.c
index aaa218eb70c8..5d18a4a917c9 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -304,6 +304,19 @@ void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac)
}
 }
 
+void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac)
+{
+   if (mac->macinfo.extended_capabilities_len) {
+   kfree(mac->macinfo.extended_capabilities);
+   mac->macinfo.extended_capabilities = NULL;
+
+   kfree(mac->macinfo.extended_capabilities_mask);
+   mac->macinfo.extended_capabilities_mask = NULL;
+
+   mac->macinfo.extended_capabilities_len = 0;
+   }
+}
+
 static void qtnf_vif_reset_handler(struct work_struct *work)
 {
struct qtnf_vif *vif = container_of(work, struct qtnf_vif, reset_work);
@@ -496,8 +509,7 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, 
unsigned int macid)
}
 
qtnf_mac_iface_comb_free(mac);
-   kfree(mac->macinfo.extended_capabilities);
-   kfree(mac->macinfo.extended_capabilities_mask);
+   qtnf_mac_ext_caps_free(mac);
kfree(mac->macinfo.wowlan);
wiphy_free(wiphy);
bus->mac[macid] = NULL;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h 
b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 1722aecf7633..293055049caa 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -144,6 +144,7 @@ struct qtnf_hw_info {
 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);
 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);
-- 
2.11.0



[PATCH v2 04/13] qtnfmac: do not initialize per-MAC data multiple times

2018-10-05 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Several members of pwr-MAC structure are re-initialized several times
together with per-VIF initialization. Fix that and simplify the code.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
b/drivers/net/wireless/quantenna/qtnfmac/core.c
index 19abbc4e23e0..aaa218eb70c8 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -370,6 +370,7 @@ static void qtnf_mac_scan_timeout(struct work_struct *work)
 static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
 unsigned int macid)
 {
+   struct qtnf_vif *vif;
struct wiphy *wiphy;
struct qtnf_wmac *mac;
unsigned int i;
@@ -382,18 +383,20 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct 
qtnf_bus *bus,
 
mac->macid = macid;
mac->bus = bus;
+   mutex_init(>mac_lock);
+   INIT_DELAYED_WORK(>scan_timeout, qtnf_mac_scan_timeout);
 
for (i = 0; i < QTNF_MAX_INTF; i++) {
-   memset(>iflist[i], 0, sizeof(struct qtnf_vif));
-   mac->iflist[i].wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-   mac->iflist[i].mac = mac;
-   mac->iflist[i].vifid = i;
-   qtnf_sta_list_init(>iflist[i].sta_list);
-   mutex_init(>mac_lock);
-   INIT_DELAYED_WORK(>scan_timeout, qtnf_mac_scan_timeout);
-   mac->iflist[i].stats64 =
-   netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
-   if (!mac->iflist[i].stats64)
+   vif = >iflist[i];
+
+   memset(vif, 0, sizeof(*vif));
+   vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+   vif->mac = mac;
+   vif->vifid = i;
+   qtnf_sta_list_init(>sta_list);
+
+   vif->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+   if (!vif->stats64)
pr_warn("VIF%u.%u: per cpu stats allocation failed\n",
macid, i);
}
-- 
2.11.0



[PATCH v2 05/13] qtnfmac: cleanup and unify command error handling

2018-10-05 Thread Sergey Matyukevich
Unify command error handling using qtnf_cmd_resp_result_decode
function. Do not duplicate error messages in command handlers
and cfg80211 callbacks: report 'cmd exec fail' only on control
path internal failure. Remove redundant 'unlikely' macros.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index c4961e16d91a..4631277092bf 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -141,8 +141,8 @@ qtnf_change_virtual_intf(struct wiphy *wiphy,
 
ret = qtnf_cmd_send_change_intf_type(vif, type, mac_addr);
if (ret) {
-   pr_err("VIF%u.%u: failed to change VIF type: %d\n",
-  vif->mac->macid, vif->vifid, ret);
+   pr_err("VIF%u.%u: failed to change type to %d\n",
+  vif->mac->macid, vif->vifid, type);
return ret;
}
 
@@ -228,18 +228,22 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct 
wiphy *wiphy,
if (params)
mac_addr = params->macaddr;
 
-   if (qtnf_cmd_send_add_intf(vif, type, mac_addr)) {
-   pr_err("VIF%u.%u: failed to add VIF\n", mac->macid, vif->vifid);
+   ret = qtnf_cmd_send_add_intf(vif, type, mac_addr);
+   if (ret) {
+   pr_err("VIF%u.%u: failed to add VIF %pM\n",
+  mac->macid, vif->vifid, mac_addr);
goto err_cmd;
}
 
if (!is_valid_ether_addr(vif->mac_addr)) {
pr_err("VIF%u.%u: FW reported bad MAC: %pM\n",
   mac->macid, vif->vifid, vif->mac_addr);
+   ret = -EINVAL;
goto err_mac;
}
 
-   if (qtnf_core_net_attach(mac, vif, name, name_assign_t)) {
+   ret = qtnf_core_net_attach(mac, vif, name, name_assign_t);
+   if (ret) {
pr_err("VIF%u.%u: failed to attach netdev\n", mac->macid,
   vif->vifid);
goto err_net;
@@ -255,7 +259,7 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct 
wiphy *wiphy,
 err_cmd:
vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
 
-   return ERR_PTR(-EFAULT);
+   return ERR_PTR(ret);
 }
 
 static int qtnf_mgmt_set_appie(struct qtnf_vif *vif,
@@ -334,12 +338,11 @@ static int qtnf_stop_ap(struct wiphy *wiphy, struct 
net_device *dev)
qtnf_scan_done(vif->mac, true);
 
ret = qtnf_cmd_send_stop_ap(vif);
-   if (ret) {
+   if (ret)
pr_err("VIF%u.%u: failed to stop AP operation in FW\n",
   vif->mac->macid, vif->vifid);
 
-   netif_carrier_off(vif->netdev);
-   }
+   netif_carrier_off(vif->netdev);
 
return ret;
 }
@@ -589,6 +592,7 @@ qtnf_del_station(struct wiphy *wiphy, struct net_device 
*dev,
if (ret)
pr_err("VIF%u.%u: failed to delete STA %pM\n",
   vif->mac->macid, vif->vifid, params->mac);
+
return ret;
 }
 
@@ -596,21 +600,25 @@ static int
 qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 {
struct qtnf_wmac *mac = wiphy_priv(wiphy);
+   int ret;
 
cancel_delayed_work_sync(>scan_timeout);
 
mac->scan_req = request;
 
-   if (qtnf_cmd_send_scan(mac)) {
+   ret = qtnf_cmd_send_scan(mac);
+   if (ret) {
pr_err("MAC%u: failed to start scan\n", mac->macid);
mac->scan_req = NULL;
-   return -EFAULT;
+   goto out;
}
 
+   pr_debug("MAC%u: scan started\n", mac->macid);
queue_delayed_work(mac->bus->workqueue, >scan_timeout,
   QTNF_SCAN_TIMEOUT_SEC * HZ);
 
-   return 0;
+out:
+   return ret;
 }
 
 static int
@@ -630,12 +638,13 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
 
ret = qtnf_cmd_send_connect(vif, sme);
if (ret) {
-   pr_err("VIF%u.%u: failed to connect\n", vif->mac->macid,
-  vif->vifid);
-   return ret;
+   pr_err("VIF%u.%u: failed to connect\n",
+  vif->mac->macid, vif->vifid);
+   goto out;
}
 
-   return 0;
+out:
+   return ret;
 }
 
 static int
@@ -661,8 +670,8 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
 
ret = qtnf_cmd_send_disconnect(vif, reason_code);
if (ret)
-   pr_err("VIF%u.%u: failed to dis

[PATCH v2 02/13] qtnfmac: generate local disconnect event in disconnect callback

2018-10-05 Thread Sergey Matyukevich
From: Igor Mitsyanko 

When cfg80211 disconnect callback is triggered and command is
processed by firmware, disconnect event with local parameter
set must be sent immediately. Indicating that it's a "local"
event (not from AP) will help upper layers to process this
event correctly.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 776cfba7396e..87f48b7fb673 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -660,10 +660,14 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device 
*dev,
qtnf_scan_done(mac, true);
 
ret = qtnf_cmd_send_disconnect(vif, reason_code);
-   if (ret) {
+   if (ret)
pr_err("VIF%u.%u: failed to disconnect\n", mac->macid,
   vif->vifid);
-   goto out;
+
+   if (vif->wdev.current_bss) {
+   netif_carrier_off(vif->netdev);
+   cfg80211_disconnected(vif->netdev, reason_code,
+ NULL, 0, true, GFP_KERNEL);
}
 
 out:
@@ -1140,12 +1144,9 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev)
struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
struct qtnf_wmac *mac = wiphy_priv(vif->wdev.wiphy);
 
-   if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
-   cfg80211_disconnected(vif->netdev, WLAN_REASON_DEAUTH_LEAVING,
- NULL, 0, 1, GFP_KERNEL);
+   if (vif->wdev.iftype == NL80211_IFTYPE_STATION)
qtnf_disconnect(vif->wdev.wiphy, ndev,
WLAN_REASON_DEAUTH_LEAVING);
-   }
 
qtnf_scan_done(mac, true);
 }
-- 
2.11.0



[PATCH v2 10/13] qtnfmac: add support for scan flush

2018-10-05 Thread Sergey Matyukevich
Notify firmware to flush cache before scanning when needed.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 8dbd6c45c233..8fb15cbf5005 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2197,6 +2197,12 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
 scan_req->mac_addr_mask);
}
 
+   if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH) {
+   pr_debug("MAC%u: flush cache before scan\n", mac->macid);
+
+   qtnf_cmd_skb_put_tlv_tag(cmd_skb, QTN_TLV_ID_SCAN_FLUSH);
+   }
+
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 c5ae4ea9a47a..699157100309 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -1151,6 +1151,7 @@ enum qlink_tlv_id {
QTN_TLV_ID_MAX_SCAN_SSIDS   = 0x0409,
QTN_TLV_ID_WOWLAN_CAPAB = 0x0410,
QTN_TLV_ID_WOWLAN_PATTERN   = 0x0411,
+   QTN_TLV_ID_SCAN_FLUSH   = 0x0412,
 };
 
 struct qlink_tlv_hdr {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
index 54caeb38917c..960d5d97492f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -40,6 +40,14 @@ static inline void qtnf_cmd_skb_put_tlv_arr(struct sk_buff 
*skb,
memcpy(hdr->val, arr, arr_len);
 }
 
+static inline void qtnf_cmd_skb_put_tlv_tag(struct sk_buff *skb, u16 tlv_id)
+{
+   struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr));
+
+   hdr->type = cpu_to_le16(tlv_id);
+   hdr->len = cpu_to_le16(0);
+}
+
 static inline void qtnf_cmd_skb_put_tlv_u8(struct sk_buff *skb, u16 tlv_id,
   u8 value)
 {
-- 
2.11.0



[PATCH v2 06/13] qtnfmac: do not cancel scan in disconnect callback

2018-10-05 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Do not cancel scan in disconnect callback. If there is an active scan,
it will be cancelled by firmware, then host driver will be properly
notified by event.

Cancelling scan in disconnect callback occasionally may lead to the
following race issue. Host is able to queue one scan after scan
abort in disconnect callback, and another scan after scan abort
in event handler. As a result, firmware receives second scan
before the first scan completes.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 4631277092bf..8b30d651cbe3 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -666,8 +666,6 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
goto out;
}
 
-   qtnf_scan_done(mac, true);
-
ret = qtnf_cmd_send_disconnect(vif, reason_code);
if (ret)
pr_err("VIF%u.%u: failed to disconnect\n",
-- 
2.11.0



[PATCH v2 01/13] qtnfmac: do not track STA states in driver

2018-10-05 Thread Sergey Matyukevich
Remove STA connection states tracking from driver.
Leave it wireless core on host and to firmware.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 59 +++
 drivers/net/wireless/quantenna/qtnfmac/core.h |  7 ---
 drivers/net/wireless/quantenna/qtnfmac/event.c| 18 +--
 3 files changed, 8 insertions(+), 76 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 452d4b7c832d..776cfba7396e 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -216,7 +216,6 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct 
wiphy *wiphy,
eth_zero_addr(vif->mac_addr);
eth_zero_addr(vif->bssid);
vif->bss_priority = QTNF_DEF_BSS_PRIORITY;
-   vif->sta_state = QTNF_STA_DISCONNECTED;
memset(>wdev, 0, sizeof(vif->wdev));
vif->wdev.wiphy = wiphy;
vif->wdev.iftype = type;
@@ -624,9 +623,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
 
-   if (vif->sta_state != QTNF_STA_DISCONNECTED)
-   return -EBUSY;
-
if (sme->bssid)
ether_addr_copy(vif->bssid, sme->bssid);
else
@@ -639,7 +635,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
return ret;
}
 
-   vif->sta_state = QTNF_STA_CONNECTING;
return 0;
 }
 
@@ -664,9 +659,6 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
 
qtnf_scan_done(mac, true);
 
-   if (vif->sta_state == QTNF_STA_DISCONNECTED)
-   goto out;
-
ret = qtnf_cmd_send_disconnect(vif, reason_code);
if (ret) {
pr_err("VIF%u.%u: failed to disconnect\n", mac->macid,
@@ -675,9 +667,6 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
}
 
 out:
-   if (vif->sta_state == QTNF_STA_CONNECTING)
-   vif->sta_state = QTNF_STA_DISCONNECTED;
-
return ret;
 }
 
@@ -1152,28 +1141,10 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev)
struct qtnf_wmac *mac = wiphy_priv(vif->wdev.wiphy);
 
if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
-   switch (vif->sta_state) {
-   case QTNF_STA_DISCONNECTED:
-   break;
-   case QTNF_STA_CONNECTING:
-   cfg80211_connect_result(vif->netdev,
-   vif->bssid, NULL, 0,
-   NULL, 0,
-   WLAN_STATUS_UNSPECIFIED_FAILURE,
-   GFP_KERNEL);
-   qtnf_disconnect(vif->wdev.wiphy, ndev,
-   WLAN_REASON_DEAUTH_LEAVING);
-   break;
-   case QTNF_STA_CONNECTED:
-   cfg80211_disconnected(vif->netdev,
- WLAN_REASON_DEAUTH_LEAVING,
- NULL, 0, 1, GFP_KERNEL);
-   qtnf_disconnect(vif->wdev.wiphy, ndev,
-   WLAN_REASON_DEAUTH_LEAVING);
-   break;
-   }
-
-   vif->sta_state = QTNF_STA_DISCONNECTED;
+   cfg80211_disconnected(vif->netdev, WLAN_REASON_DEAUTH_LEAVING,
+ NULL, 0, 1, GFP_KERNEL);
+   qtnf_disconnect(vif->wdev.wiphy, ndev,
+   WLAN_REASON_DEAUTH_LEAVING);
}
 
qtnf_scan_done(mac, true);
@@ -1181,27 +1152,11 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev)
 
 void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif)
 {
-   if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
-   switch (vif->sta_state) {
-   case QTNF_STA_CONNECTING:
-   cfg80211_connect_result(vif->netdev,
-   vif->bssid, NULL, 0,
-   NULL, 0,
-   WLAN_STATUS_UNSPECIFIED_FAILURE,
-   GFP_KERNEL);
-   break;
-   case QTNF_STA_CONNECTED:
-   cfg80211_disconnected(vif->netdev,
- WLAN_REASON_DEAUTH_LEAVING,
- NULL, 0, 1, GFP_KERNEL);
-   break;
-   case QTNF_STA_DISCONNECTED:
-   break;
-   }
-  

[PATCH v2 07/13] qtnfmac: pass sgi rate info flag to wireless core

2018-10-05 Thread Sergey Matyukevich
SGI should be passed to wireless core as a part of rate structure.
Otherwise wireless core performs incorrect rate calculation when
SGI is enabled in hardware but not reported to host.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 63d93cf3ace0..74edb5a0ae19 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -498,6 +498,9 @@ qtnf_sta_info_parse_rate(struct rate_info *rate_dst,
rate_dst->flags |= RATE_INFO_FLAGS_MCS;
else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_VHT_MCS)
rate_dst->flags |= RATE_INFO_FLAGS_VHT_MCS;
+
+   if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_SHORT_GI)
+   rate_dst->flags |= RATE_INFO_FLAGS_SHORT_GI;
 }
 
 static void
-- 
2.11.0



[PATCH v2 00/13] qtnfmac: fixes and cleanups for STA mode

2018-10-05 Thread Sergey Matyukevich
Hello Kalle and all, 

Here is the next  patch set with fixes and cleanups for qtnfmac driver.
This set mostly consists of multiple fixes and improvements for STA
mode. The major changes include the following items:
- fixes for 'iw' output: rates for enabled SGI, 'dump station'
- expose more scan features to host: scan flush and dwell time
- inform host wireless core when OBSS is not supported by firmware
- command processing cleanup: unify and get rid of 'unlikely' macros

Regards,
Sergey

Changes v1->v2:
- fix email addresses: drop "OS" string

Igor Mitsyanko (4)
  qtnfmac: do not cancel scan in disconnect callback
  qtnfmac: do not initialize per-MAC data multiple times
  qtnfmac: request userspace to do OBSS scanning if FW can not
  qtnfmac: generate local disconnect event in disconnect callback

Sergey Matyukevich (9)
  qtnfmac: implement dump_station support for STA mode
  qtnfmac: drop redundant data copy in control path
  qtnfmac: add support for scan dwell time configuration
  qtnfmac: add support for scan flush
  qtnfmac: drop error reports for out-of-bounds key indexes
  qtnfmac: inform wireless core about supported extended capabilities
  qtnfmac: pass sgi rate info flag to wireless core
  qtnfmac: cleanup and unify command error handling
  qtnfmac: do not track STA states in driver


 cfg80211.c   |  193 ++---
 commands.c   |  535 +--
 core.c   |   39 ++--
 core.h   |8 
 event.c  |   18 -
 pcie/pcie.c  |5 
 qlink.h  |5 
 qlink_util.h |8 
 shm_ipc.c|   13 -
 shm_ipc.h|4 
 10 files changed, 277 insertions(+), 551 deletions(-)


Re: [PATCH 00/13] qtnfmac: fixes and cleanups for STA mode

2018-10-05 Thread Sergey Matyukevich
> Sergey Matyukevich OS  writes:
> 
> > Hello Kalle and all,
> >
> > Here is the next  patch set with fixes and cleanups for qtnfmac driver.
> > This set mostly consists of multiple fixes and improvements for STA
> > mode. The major changes include the following items:
> > - fixes for 'iw' output: rates for enabled SGI, 'dump station'
> > - expose more scan features to host: scan flush and dwell time
> > - inform host wireless core when OBSS is not supported by firmware
> > - command processing cleanup: unify and get rid of 'unlikely' macros
> 
> The string "OS" is again in the from field. Can you fix that and resend, 
> please?

Ok, thanks for catching. Will do now.

Regards,
Sergey


[PATCH 04/13] qtnfmac: do not initialize per-MAC data multiple times

2018-10-02 Thread Sergey Matyukevich OS
From: Igor Mitsyanko 

Several members of pwr-MAC structure are re-initialized several times
together with per-VIF initialization. Fix that and simplify the code.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
b/drivers/net/wireless/quantenna/qtnfmac/core.c
index 19abbc4e23e0..aaa218eb70c8 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -370,6 +370,7 @@ static void qtnf_mac_scan_timeout(struct work_struct *work)
 static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
 unsigned int macid)
 {
+   struct qtnf_vif *vif;
struct wiphy *wiphy;
struct qtnf_wmac *mac;
unsigned int i;
@@ -382,18 +383,20 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct 
qtnf_bus *bus,
 
mac->macid = macid;
mac->bus = bus;
+   mutex_init(>mac_lock);
+   INIT_DELAYED_WORK(>scan_timeout, qtnf_mac_scan_timeout);
 
for (i = 0; i < QTNF_MAX_INTF; i++) {
-   memset(>iflist[i], 0, sizeof(struct qtnf_vif));
-   mac->iflist[i].wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-   mac->iflist[i].mac = mac;
-   mac->iflist[i].vifid = i;
-   qtnf_sta_list_init(>iflist[i].sta_list);
-   mutex_init(>mac_lock);
-   INIT_DELAYED_WORK(>scan_timeout, qtnf_mac_scan_timeout);
-   mac->iflist[i].stats64 =
-   netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
-   if (!mac->iflist[i].stats64)
+   vif = >iflist[i];
+
+   memset(vif, 0, sizeof(*vif));
+   vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+   vif->mac = mac;
+   vif->vifid = i;
+   qtnf_sta_list_init(>sta_list);
+
+   vif->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+   if (!vif->stats64)
pr_warn("VIF%u.%u: per cpu stats allocation failed\n",
macid, i);
}
-- 
2.11.0



[PATCH 06/13] qtnfmac: do not cancel scan in disconnect callback

2018-10-02 Thread Sergey Matyukevich OS
From: Igor Mitsyanko 

Do not cancel scan in disconnect callback. If there is an active scan,
it will be cancelled by firmware, then host driver will be properly
notified by event.

Cancelling scan in disconnect callback occasionally may lead to the
following race issue. Host is able to queue one scan after scan
abort in disconnect callback, and another scan after scan abort
in event handler. As a result, firmware receives second scan
before the first scan completes.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 4631277092bf..8b30d651cbe3 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -666,8 +666,6 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
goto out;
}
 
-   qtnf_scan_done(mac, true);
-
ret = qtnf_cmd_send_disconnect(vif, reason_code);
if (ret)
pr_err("VIF%u.%u: failed to disconnect\n",
-- 
2.11.0



[PATCH 05/13] qtnfmac: cleanup and unify command error handling

2018-10-02 Thread Sergey Matyukevich OS
Unify command error handling using qtnf_cmd_resp_result_decode
function. Do not duplicate error messages in command handlers
and cfg80211 callbacks: report 'cmd exec fail' only on control
path internal failure. Remove redundant 'unlikely' macros.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index c4961e16d91a..4631277092bf 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -141,8 +141,8 @@ qtnf_change_virtual_intf(struct wiphy *wiphy,
 
ret = qtnf_cmd_send_change_intf_type(vif, type, mac_addr);
if (ret) {
-   pr_err("VIF%u.%u: failed to change VIF type: %d\n",
-  vif->mac->macid, vif->vifid, ret);
+   pr_err("VIF%u.%u: failed to change type to %d\n",
+  vif->mac->macid, vif->vifid, type);
return ret;
}
 
@@ -228,18 +228,22 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct 
wiphy *wiphy,
if (params)
mac_addr = params->macaddr;
 
-   if (qtnf_cmd_send_add_intf(vif, type, mac_addr)) {
-   pr_err("VIF%u.%u: failed to add VIF\n", mac->macid, vif->vifid);
+   ret = qtnf_cmd_send_add_intf(vif, type, mac_addr);
+   if (ret) {
+   pr_err("VIF%u.%u: failed to add VIF %pM\n",
+  mac->macid, vif->vifid, mac_addr);
goto err_cmd;
}
 
if (!is_valid_ether_addr(vif->mac_addr)) {
pr_err("VIF%u.%u: FW reported bad MAC: %pM\n",
   mac->macid, vif->vifid, vif->mac_addr);
+   ret = -EINVAL;
goto err_mac;
}
 
-   if (qtnf_core_net_attach(mac, vif, name, name_assign_t)) {
+   ret = qtnf_core_net_attach(mac, vif, name, name_assign_t);
+   if (ret) {
pr_err("VIF%u.%u: failed to attach netdev\n", mac->macid,
   vif->vifid);
goto err_net;
@@ -255,7 +259,7 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct 
wiphy *wiphy,
 err_cmd:
vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
 
-   return ERR_PTR(-EFAULT);
+   return ERR_PTR(ret);
 }
 
 static int qtnf_mgmt_set_appie(struct qtnf_vif *vif,
@@ -334,12 +338,11 @@ static int qtnf_stop_ap(struct wiphy *wiphy, struct 
net_device *dev)
qtnf_scan_done(vif->mac, true);
 
ret = qtnf_cmd_send_stop_ap(vif);
-   if (ret) {
+   if (ret)
pr_err("VIF%u.%u: failed to stop AP operation in FW\n",
   vif->mac->macid, vif->vifid);
 
-   netif_carrier_off(vif->netdev);
-   }
+   netif_carrier_off(vif->netdev);
 
return ret;
 }
@@ -589,6 +592,7 @@ qtnf_del_station(struct wiphy *wiphy, struct net_device 
*dev,
if (ret)
pr_err("VIF%u.%u: failed to delete STA %pM\n",
   vif->mac->macid, vif->vifid, params->mac);
+
return ret;
 }
 
@@ -596,21 +600,25 @@ static int
 qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 {
struct qtnf_wmac *mac = wiphy_priv(wiphy);
+   int ret;
 
cancel_delayed_work_sync(>scan_timeout);
 
mac->scan_req = request;
 
-   if (qtnf_cmd_send_scan(mac)) {
+   ret = qtnf_cmd_send_scan(mac);
+   if (ret) {
pr_err("MAC%u: failed to start scan\n", mac->macid);
mac->scan_req = NULL;
-   return -EFAULT;
+   goto out;
}
 
+   pr_debug("MAC%u: scan started\n", mac->macid);
queue_delayed_work(mac->bus->workqueue, >scan_timeout,
   QTNF_SCAN_TIMEOUT_SEC * HZ);
 
-   return 0;
+out:
+   return ret;
 }
 
 static int
@@ -630,12 +638,13 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
 
ret = qtnf_cmd_send_connect(vif, sme);
if (ret) {
-   pr_err("VIF%u.%u: failed to connect\n", vif->mac->macid,
-  vif->vifid);
-   return ret;
+   pr_err("VIF%u.%u: failed to connect\n",
+  vif->mac->macid, vif->vifid);
+   goto out;
}
 
-   return 0;
+out:
+   return ret;
 }
 
 static int
@@ -661,8 +670,8 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
 
ret = qtnf_cmd_send_disconnect(vif, reason_code);
if (ret)
-   pr_err("VIF%u.%u: failed to dis

[PATCH 11/13] qtnfmac: add support for scan dwell time configuration

2018-10-02 Thread Sergey Matyukevich OS
Firmware supports scan dwell time tuning for various types of scans.
Enable support for this feature:
- advertise capability to configure channel dwell time to host
- pass scan dwell parameters to wireless card in scan request

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 9845cf287118..18179965bd38 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1101,6 +1101,10 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
 
+   if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_DWELL)
+   wiphy_ext_feature_set(wiphy,
+ NL80211_EXT_FEATURE_SET_SCAN_DWELL);
+
wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 8fb15cbf5005..bfdc1ad30c13 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2203,6 +2203,15 @@ 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 699157100309..8d62addea895 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -80,6 +80,7 @@ enum qlink_hw_capab {
QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR = BIT(3),
QLINK_HW_CAPAB_PWR_MGMT = BIT(4),
QLINK_HW_CAPAB_OBSS_SCAN= BIT(5),
+   QLINK_HW_CAPAB_SCAN_DWELL   = BIT(6),
 };
 
 enum qlink_iface_type {
@@ -1152,6 +1153,7 @@ enum qlink_tlv_id {
QTN_TLV_ID_WOWLAN_CAPAB = 0x0410,
QTN_TLV_ID_WOWLAN_PATTERN   = 0x0411,
QTN_TLV_ID_SCAN_FLUSH   = 0x0412,
+   QTN_TLV_ID_SCAN_DWELL   = 0x0413,
 };
 
 struct qlink_tlv_hdr {
-- 
2.11.0



[PATCH 09/13] qtnfmac: drop error reports for out-of-bounds key indexes

2018-10-02 Thread Sergey Matyukevich OS
On disconnect wireless core attempts to remove all the supported keys.
Following cfg80211_ops conventions, firmware returns -ENOENT code
for the out-of-bound key indexes. This is a normal behavior,
so no need to report errors for this case.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 8ecd37ddc0f9..9845cf287118 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -523,9 +523,16 @@ static int qtnf_del_key(struct wiphy *wiphy, struct 
net_device *dev,
int ret;
 
ret = qtnf_cmd_send_del_key(vif, key_index, pairwise, mac_addr);
-   if (ret)
-   pr_err("VIF%u.%u: failed to delete key: idx=%u pw=%u\n",
-  vif->mac->macid, vif->vifid, key_index, pairwise);
+   if (ret) {
+   if (ret == -ENOENT) {
+   pr_debug("VIF%u.%u: key index %d out of bounds\n",
+vif->mac->macid, vif->vifid, key_index);
+   } else {
+   pr_err("VIF%u.%u: failed to delete key: idx=%u pw=%u\n",
+  vif->mac->macid, vif->vifid,
+  key_index, pairwise);
+   }
+   }
 
return ret;
 }
-- 
2.11.0



[PATCH 08/13] qtnfmac: pass supported extended capabilities to wiphy

2018-10-02 Thread Sergey Matyukevich OS
Driver retrieves information about supported extended capabilities
from wireless card. However this information is not propagated
further to Linux wireless core. Fix this by setting extended
capabilities fields of wiphy structure.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |  9 +
 drivers/net/wireless/quantenna/qtnfmac/commands.c |  3 +--
 drivers/net/wireless/quantenna/qtnfmac/core.c | 16 ++--
 drivers/net/wireless/quantenna/qtnfmac/core.h |  1 +
 4 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 8b30d651cbe3..8ecd37ddc0f9 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1129,6 +1129,15 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
}
 
+   if (mac->macinfo.extended_capabilities_len) {
+   wiphy->extended_capabilities =
+   mac->macinfo.extended_capabilities;
+   wiphy->extended_capabilities_mask =
+   mac->macinfo.extended_capabilities_mask;
+   wiphy->extended_capabilities_len =
+   mac->macinfo.extended_capabilities_len;
+   }
+
strlcpy(wiphy->fw_version, hw_info->fw_version,
sizeof(wiphy->fw_version));
wiphy->hw_version = hw_info->hw_version;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 74edb5a0ae19..8dbd6c45c233 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1273,8 +1273,7 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac 
*mac,
ext_capa_mask = NULL;
}
 
-   kfree(mac->macinfo.extended_capabilities);
-   kfree(mac->macinfo.extended_capabilities_mask);
+   qtnf_mac_ext_caps_free(mac);
mac->macinfo.extended_capabilities = ext_capa;
mac->macinfo.extended_capabilities_mask = ext_capa_mask;
mac->macinfo.extended_capabilities_len = ext_capa_len;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
b/drivers/net/wireless/quantenna/qtnfmac/core.c
index aaa218eb70c8..5d18a4a917c9 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -304,6 +304,19 @@ void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac)
}
 }
 
+void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac)
+{
+   if (mac->macinfo.extended_capabilities_len) {
+   kfree(mac->macinfo.extended_capabilities);
+   mac->macinfo.extended_capabilities = NULL;
+
+   kfree(mac->macinfo.extended_capabilities_mask);
+   mac->macinfo.extended_capabilities_mask = NULL;
+
+   mac->macinfo.extended_capabilities_len = 0;
+   }
+}
+
 static void qtnf_vif_reset_handler(struct work_struct *work)
 {
struct qtnf_vif *vif = container_of(work, struct qtnf_vif, reset_work);
@@ -496,8 +509,7 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, 
unsigned int macid)
}
 
qtnf_mac_iface_comb_free(mac);
-   kfree(mac->macinfo.extended_capabilities);
-   kfree(mac->macinfo.extended_capabilities_mask);
+   qtnf_mac_ext_caps_free(mac);
kfree(mac->macinfo.wowlan);
wiphy_free(wiphy);
bus->mac[macid] = NULL;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h 
b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 1722aecf7633..293055049caa 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -144,6 +144,7 @@ struct qtnf_hw_info {
 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);
 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);
-- 
2.11.0



[PATCH 13/13] qtnfmac: implement dump_station support for STA mode

2018-10-02 Thread Sergey Matyukevich OS
Current implementation of dump_station cfg80211 callback supports
AP mode only. Add support for STA mode as well: by default in STA
mode this callback is supposed to return AP on managed interface.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 30 ---
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 18179965bd38..51b33ec78fac 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -480,19 +480,31 @@ qtnf_dump_station(struct wiphy *wiphy, struct net_device 
*dev,
const struct qtnf_sta_node *sta_node;
int ret;
 
-   sta_node = qtnf_sta_list_lookup_index(>sta_list, idx);
+   switch (vif->wdev.iftype) {
+   case NL80211_IFTYPE_STATION:
+   if (idx != 0 || !vif->wdev.current_bss)
+   return -ENOENT;
 
-   if (unlikely(!sta_node))
-   return -ENOENT;
+   ether_addr_copy(mac, vif->bssid);
+   break;
+   case NL80211_IFTYPE_AP:
+   sta_node = qtnf_sta_list_lookup_index(>sta_list, idx);
+   if (unlikely(!sta_node))
+   return -ENOENT;
 
-   ether_addr_copy(mac, sta_node->mac_addr);
+   ether_addr_copy(mac, sta_node->mac_addr);
+   break;
+   default:
+   return -ENOTSUPP;
+   }
 
-   ret = qtnf_cmd_get_sta_info(vif, sta_node->mac_addr, sinfo);
+   ret = qtnf_cmd_get_sta_info(vif, mac, sinfo);
 
-   if (unlikely(ret == -ENOENT)) {
-   qtnf_sta_list_del(vif, mac);
-   cfg80211_del_sta(vif->netdev, mac, GFP_KERNEL);
-   sinfo->filled = 0;
+   if (vif->wdev.iftype == NL80211_IFTYPE_AP) {
+   if (ret == -ENOENT) {
+   cfg80211_del_sta(vif->netdev, mac, GFP_KERNEL);
+   sinfo->filled = 0;
+   }
}
 
sinfo->generation = vif->generation;
-- 
2.11.0



[PATCH 01/13] qtnfmac: do not track STA states in driver

2018-10-02 Thread Sergey Matyukevich OS
Remove STA connection states tracking from driver.
Leave it wireless core on host and to firmware.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 59 +++
 drivers/net/wireless/quantenna/qtnfmac/core.h |  7 ---
 drivers/net/wireless/quantenna/qtnfmac/event.c| 18 +--
 3 files changed, 8 insertions(+), 76 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 452d4b7c832d..776cfba7396e 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -216,7 +216,6 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct 
wiphy *wiphy,
eth_zero_addr(vif->mac_addr);
eth_zero_addr(vif->bssid);
vif->bss_priority = QTNF_DEF_BSS_PRIORITY;
-   vif->sta_state = QTNF_STA_DISCONNECTED;
memset(>wdev, 0, sizeof(vif->wdev));
vif->wdev.wiphy = wiphy;
vif->wdev.iftype = type;
@@ -624,9 +623,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
 
-   if (vif->sta_state != QTNF_STA_DISCONNECTED)
-   return -EBUSY;
-
if (sme->bssid)
ether_addr_copy(vif->bssid, sme->bssid);
else
@@ -639,7 +635,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
return ret;
}
 
-   vif->sta_state = QTNF_STA_CONNECTING;
return 0;
 }
 
@@ -664,9 +659,6 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
 
qtnf_scan_done(mac, true);
 
-   if (vif->sta_state == QTNF_STA_DISCONNECTED)
-   goto out;
-
ret = qtnf_cmd_send_disconnect(vif, reason_code);
if (ret) {
pr_err("VIF%u.%u: failed to disconnect\n", mac->macid,
@@ -675,9 +667,6 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
}
 
 out:
-   if (vif->sta_state == QTNF_STA_CONNECTING)
-   vif->sta_state = QTNF_STA_DISCONNECTED;
-
return ret;
 }
 
@@ -1152,28 +1141,10 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev)
struct qtnf_wmac *mac = wiphy_priv(vif->wdev.wiphy);
 
if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
-   switch (vif->sta_state) {
-   case QTNF_STA_DISCONNECTED:
-   break;
-   case QTNF_STA_CONNECTING:
-   cfg80211_connect_result(vif->netdev,
-   vif->bssid, NULL, 0,
-   NULL, 0,
-   WLAN_STATUS_UNSPECIFIED_FAILURE,
-   GFP_KERNEL);
-   qtnf_disconnect(vif->wdev.wiphy, ndev,
-   WLAN_REASON_DEAUTH_LEAVING);
-   break;
-   case QTNF_STA_CONNECTED:
-   cfg80211_disconnected(vif->netdev,
- WLAN_REASON_DEAUTH_LEAVING,
- NULL, 0, 1, GFP_KERNEL);
-   qtnf_disconnect(vif->wdev.wiphy, ndev,
-   WLAN_REASON_DEAUTH_LEAVING);
-   break;
-   }
-
-   vif->sta_state = QTNF_STA_DISCONNECTED;
+   cfg80211_disconnected(vif->netdev, WLAN_REASON_DEAUTH_LEAVING,
+ NULL, 0, 1, GFP_KERNEL);
+   qtnf_disconnect(vif->wdev.wiphy, ndev,
+   WLAN_REASON_DEAUTH_LEAVING);
}
 
qtnf_scan_done(mac, true);
@@ -1181,27 +1152,11 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev)
 
 void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif)
 {
-   if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
-   switch (vif->sta_state) {
-   case QTNF_STA_CONNECTING:
-   cfg80211_connect_result(vif->netdev,
-   vif->bssid, NULL, 0,
-   NULL, 0,
-   WLAN_STATUS_UNSPECIFIED_FAILURE,
-   GFP_KERNEL);
-   break;
-   case QTNF_STA_CONNECTED:
-   cfg80211_disconnected(vif->netdev,
- WLAN_REASON_DEAUTH_LEAVING,
- NULL, 0, 1, GFP_KERNEL);
-   break;
-   case QTNF_STA_DISCONNECTED:
-   break;
-   }
-  

[PATCH 07/13] qtnfmac: pass sgi rate info flag to wireless core

2018-10-02 Thread Sergey Matyukevich OS
SGI should be passed to wireless core as a part of rate structure.
Otherwise wireless core performs incorrect rate calculation when
SGI is enabled in hardware but not reported to host.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 63d93cf3ace0..74edb5a0ae19 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -498,6 +498,9 @@ qtnf_sta_info_parse_rate(struct rate_info *rate_dst,
rate_dst->flags |= RATE_INFO_FLAGS_MCS;
else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_VHT_MCS)
rate_dst->flags |= RATE_INFO_FLAGS_VHT_MCS;
+
+   if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_SHORT_GI)
+   rate_dst->flags |= RATE_INFO_FLAGS_SHORT_GI;
 }
 
 static void
-- 
2.11.0



[PATCH 03/13] qtnfmac: request userspace to do OBSS scanning if FW can not

2018-10-02 Thread Sergey Matyukevich OS
From: Igor Mitsyanko 

In case firmware reports that it can not do OBSS scanning for 40MHz
2.4GHz channels itself, tell userpsace to do that instead by setting
NL80211_FEATURE_NEED_OBSS_SCAN flag.

Signed-off-by: Igor mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 3 +++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 2 ++
 2 files changed, 5 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 87f48b7fb673..c4961e16d91a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1099,6 +1099,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR)
wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
 
+   if (!(hw_info->hw_capab & QLINK_HW_CAPAB_OBSS_SCAN))
+   wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN;
+
 #ifdef CONFIG_PM
if (macinfo->wowlan)
wiphy->wowlan = macinfo->wowlan;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 99d37e3efba6..c5ae4ea9a47a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -71,6 +71,7 @@ struct qlink_msg_header {
  * @QLINK_HW_CAPAB_DFS_OFFLOAD: device implements DFS offload functionality
  * @QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR: device supports MAC Address
  * Randomization in probe requests.
+ * @QLINK_HW_CAPAB_OBSS_SCAN: device can perform OBSS scanning.
  */
 enum qlink_hw_capab {
QLINK_HW_CAPAB_REG_UPDATE   = BIT(0),
@@ -78,6 +79,7 @@ enum qlink_hw_capab {
QLINK_HW_CAPAB_DFS_OFFLOAD  = BIT(2),
QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR = BIT(3),
QLINK_HW_CAPAB_PWR_MGMT = BIT(4),
+   QLINK_HW_CAPAB_OBSS_SCAN= BIT(5),
 };
 
 enum qlink_iface_type {
-- 
2.11.0



[PATCH 10/13] qtnfmac: add support for scan flush

2018-10-02 Thread Sergey Matyukevich OS
Notify firmware to flush cache before scanning when needed.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 8dbd6c45c233..8fb15cbf5005 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2197,6 +2197,12 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
 scan_req->mac_addr_mask);
}
 
+   if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH) {
+   pr_debug("MAC%u: flush cache before scan\n", mac->macid);
+
+   qtnf_cmd_skb_put_tlv_tag(cmd_skb, QTN_TLV_ID_SCAN_FLUSH);
+   }
+
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 c5ae4ea9a47a..699157100309 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -1151,6 +1151,7 @@ enum qlink_tlv_id {
QTN_TLV_ID_MAX_SCAN_SSIDS   = 0x0409,
QTN_TLV_ID_WOWLAN_CAPAB = 0x0410,
QTN_TLV_ID_WOWLAN_PATTERN   = 0x0411,
+   QTN_TLV_ID_SCAN_FLUSH   = 0x0412,
 };
 
 struct qlink_tlv_hdr {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
index 54caeb38917c..960d5d97492f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -40,6 +40,14 @@ static inline void qtnf_cmd_skb_put_tlv_arr(struct sk_buff 
*skb,
memcpy(hdr->val, arr, arr_len);
 }
 
+static inline void qtnf_cmd_skb_put_tlv_tag(struct sk_buff *skb, u16 tlv_id)
+{
+   struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr));
+
+   hdr->type = cpu_to_le16(tlv_id);
+   hdr->len = cpu_to_le16(0);
+}
+
 static inline void qtnf_cmd_skb_put_tlv_u8(struct sk_buff *skb, u16 tlv_id,
   u8 value)
 {
-- 
2.11.0



[PATCH 00/13] qtnfmac: fixes and cleanups for STA mode

2018-10-02 Thread Sergey Matyukevich OS
Hello Kalle and all, 

Here is the next  patch set with fixes and cleanups for qtnfmac driver.
This set mostly consists of multiple fixes and improvements for STA
mode. The major changes include the following items:
- fixes for 'iw' output: rates for enabled SGI, 'dump station'
- expose more scan features to host: scan flush and dwell time
- inform host wireless core when OBSS is not supported by firmware
- command processing cleanup: unify and get rid of 'unlikely' macros

Regards,
Sergey


Igor Mitsyanko (4)
  qtnfmac: do not cancel scan in disconnect callback
  qtnfmac: do not initialize per-MAC data multiple times
  qtnfmac: request userspace to do OBSS scanning if FW can not
  qtnfmac: generate local disconnect event in disconnect callback

Sergey Matyukevich (9)
  qtnfmac: implement dump_station support for STA mode
  qtnfmac: drop redundant data copy in control path
  qtnfmac: add support for scan dwell time configuration
  qtnfmac: add support for scan flush
  qtnfmac: drop error reports for out-of-bounds key indexes
  qtnfmac: inform wireless core about supported extended capabilities
  qtnfmac: pass sgi rate info flag to wireless core
  qtnfmac: cleanup and unify command error handling
  qtnfmac: do not track STA states in driver


 cfg80211.c   |  193 ++---
 commands.c   |  535 +--
 core.c   |   39 ++--
 core.h   |8 
 event.c  |   18 -
 pcie/pcie.c  |5 
 qlink.h  |5 
 qlink_util.h |8 
 shm_ipc.c|   13 -
 shm_ipc.h|4 
 10 files changed, 277 insertions(+), 551 deletions(-)


[PATCH 02/13] qtnfmac: generate local disconnect event in disconnect callback

2018-10-02 Thread Sergey Matyukevich OS
From: Igor Mitsyanko 

When cfg80211 disconnect callback is triggered and command is
processed by firmware, disconnect event with local parameter
set must be sent immediately. Indicating that it's a "local"
event (not from AP) will help upper layers to process this
event correctly.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 776cfba7396e..87f48b7fb673 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -660,10 +660,14 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device 
*dev,
qtnf_scan_done(mac, true);
 
ret = qtnf_cmd_send_disconnect(vif, reason_code);
-   if (ret) {
+   if (ret)
pr_err("VIF%u.%u: failed to disconnect\n", mac->macid,
   vif->vifid);
-   goto out;
+
+   if (vif->wdev.current_bss) {
+   netif_carrier_off(vif->netdev);
+   cfg80211_disconnected(vif->netdev, reason_code,
+ NULL, 0, true, GFP_KERNEL);
}
 
 out:
@@ -1140,12 +1144,9 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev)
struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
struct qtnf_wmac *mac = wiphy_priv(vif->wdev.wiphy);
 
-   if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
-   cfg80211_disconnected(vif->netdev, WLAN_REASON_DEAUTH_LEAVING,
- NULL, 0, 1, GFP_KERNEL);
+   if (vif->wdev.iftype == NL80211_IFTYPE_STATION)
qtnf_disconnect(vif->wdev.wiphy, ndev,
WLAN_REASON_DEAUTH_LEAVING);
-   }
 
qtnf_scan_done(mac, true);
 }
-- 
2.11.0



Re: [PATCH] iw: scan: fix crash when driver doesn't report frame type

2018-08-08 Thread Sergey Matyukevich
> If driver does not know what kind of frame has been received from BSS,
> then it is possible to specify CFG80211_BSS_FTYPE_UNKNOWN
> in cfg80211_inform_bss[_width].
> 
> In this case neither NL80211_BSS_BEACON_IES nor NL80211_BSS_PRESP_DATA
> will be reported to userspace.

The fix is for iw tool, so the patch title is a bit confusing.
It should have been something like this:
[PATCH] iw: scan: fix crash when driver doesn't report frame type

Regards,
Sergey


Re: [PATCH 5/6] qtnfmac: add support for PTA configuration

2018-08-05 Thread Sergey Matyukevich
> > > > > Implement support for PTA (Packet Traffic Arbitration) configuration.
> > > > > The PTA mechanism is used to coordinate sharing of the medium between
> > > > > WiFi and other 2.4 wireless networks, e.g. Bluetooth or ZigBee.
> > > > > 
> > > > > This patch implements core infrastructure and vendor specific commands
> > > > > to control PTA functionality in firmware.
> > > > 
> > > > And no description of the actual interface which would have helped with
> > > > the review.
> > > > 
> > > > Anyway, the vendor commands are pain and they just make me grumpy. The
> > > > original idea was that upstream drivers should not support them at all,
> > > > later we flexed the rules so that low level hardware specific interfaces
> > > > might be ok, for example we added one in wil6210.
> > > > 
> > > > If I would even consider applying a patch which adds a vendor command it
> > > > needs a really good commit log with a proper description of the actual
> > > > interface and good justifications why a generic nl80211 command won't
> > > > work. I don't see anything even remotely close here.
> > > > 
> > > > Sorry for being grumpy, I just hate these vendor commands. Especially
> > > > when I see that a generic nl80211 command has not even be consired at
> > > > all.
> > > 
> > > For what it is worth, looking at part of the patch:
> > > 
> > > +/**
> > > + * enum qlink_pta_mode - Packet Traffic Arbiter operating modes
> > > + *
> > > + * @QLINK_PTA_MODE_DISABLED: PTA is disabled
> > > + * @QLINK_PTA_MODE_2_WIRE: enable PTA 2-wire mode
> > > + */
> > > +enum qlink_pta_mode {
> > > +   QLINK_PTA_MODE_DISABLED = 0,
> > > +   QLINK_PTA_MODE_2_WIRE = 2
> > > +};
> > > +
> > > 
> > > it smells very much like low-level btcoex. The question is whether this
> > > needs to be conveyed from user-space or should these be device
> > > configuration, eg. like DT properties.
> > 
> > Hello Arend,
> > 
> > Yes, this is some kind of low-level BT coexistence mechanism, when WiFi and
> > BT cards coordinate access to wireless media in 2.4G using gpio lines.
> > Those lines connect WiFi and BT cards directly w/o host mediation.
> 
> Right.
> 
> > As for DT properties, the qustion still remains the same: how to propagate
> > those settings to WiFi card. AFAIK there is no 'standard' interface for
> > this kind of things. So using vendor commands looked like the only option.
> 
> So DT properties are available to the kernel so it is just between
> device driver and wifi card. There is no involvement with user-space needed.

Ok, makes sense. But IIUC this approach with DT
does not cover PCIe/USB wireless cards.

Regards,
Sergey


[PATCH] scan: fix crash when driver doesn't report frame type

2018-08-04 Thread Sergey Matyukevich
If driver does not know what kind of frame has been received from BSS,
then it is possible to specify CFG80211_BSS_FTYPE_UNKNOWN
in cfg80211_inform_bss[_width].

In this case neither NL80211_BSS_BEACON_IES nor NL80211_BSS_PRESP_DATA
will be reported to userspace.

Signed-off-by: Sergey Matyukevich 
---
 scan.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scan.c b/scan.c
index 09b04a5..d9681f3 100644
--- a/scan.c
+++ b/scan.c
@@ -2188,8 +2188,8 @@ static int print_bss_handler(struct nl_msg *msg, void 
*arg)
struct nlattr *bcnies = bss[NL80211_BSS_BEACON_IES];
 
if (bss[NL80211_BSS_PRESP_DATA] ||
-   nla_len(ies) != nla_len(bcnies) ||
-   memcmp(nla_data(ies), nla_data(bcnies), nla_len(ies)))
+   (bcnies && (nla_len(ies) != nla_len(bcnies) ||
+   memcmp(nla_data(ies), nla_data(bcnies), nla_len(ies)
printf("\tInformation elements from Probe Response "
   "frame:\n");
print_ies(nla_data(ies), nla_len(ies),
-- 
2.11.0



[PATCH v2] qtnfmac: implement basic WoWLAN support

2018-08-02 Thread Sergey Matyukevich
This patch implements basic WoWLAN support in qtnfmac driver, including
processing of WoWLAN features reported by firmware and implementation
of cfg80211 suspend/resume/wakeup callbacks. Currently the following
WoWLAN triggers are supported: disconnect, magic packet,
custom pattern packet.

Signed-off-by: Sergey Matyukevich 
---

Hello Kalle and all,

The first four patches from the original patch set has been accepted.
So the changes for v2 are as follows:
- drop patch with vendor speicific commands for PTA
  -- to be clarified and resend separately
- rebase WoWLAN patch on top of wireless-drivers-next

Regards,
Sergey

 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |  76 +++
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 112 ++
 drivers/net/wireless/quantenna/qtnfmac/commands.h |   2 +
 drivers/net/wireless/quantenna/qtnfmac/core.c |   1 +
 drivers/net/wireless/quantenna/qtnfmac/core.h |   1 +
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|  56 +++
 6 files changed, 248 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 0032fa9f..4aa332f4646b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -859,6 +859,72 @@ static int qtnf_set_power_mgmt(struct wiphy *wiphy, struct 
net_device *dev,
return ret;
 }
 
+#ifdef CONFIG_PM
+static int qtnf_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wowlan)
+{
+   struct qtnf_wmac *mac = wiphy_priv(wiphy);
+   struct qtnf_vif *vif;
+   int ret = 0;
+
+   vif = qtnf_mac_get_base_vif(mac);
+   if (!vif) {
+   pr_err("MAC%u: primary VIF is not configured\n", mac->macid);
+   ret = -EFAULT;
+   goto exit;
+   }
+
+   if (!wowlan) {
+   pr_debug("WoWLAN triggers are not enabled\n");
+   qtnf_virtual_intf_cleanup(vif->netdev);
+   goto exit;
+   }
+
+   qtnf_scan_done(vif->mac, true);
+
+   ret = qtnf_cmd_send_wowlan_set(vif, wowlan);
+   if (ret) {
+   pr_err("MAC%u: failed to set WoWLAN triggers\n",
+  mac->macid);
+   goto exit;
+   }
+
+exit:
+   return ret;
+}
+
+static int qtnf_resume(struct wiphy *wiphy)
+{
+   struct qtnf_wmac *mac = wiphy_priv(wiphy);
+   struct qtnf_vif *vif;
+   int ret = 0;
+
+   vif = qtnf_mac_get_base_vif(mac);
+   if (!vif) {
+   pr_err("MAC%u: primary VIF is not configured\n", mac->macid);
+   ret = -EFAULT;
+   goto exit;
+   }
+
+   ret = qtnf_cmd_send_wowlan_set(vif, NULL);
+   if (ret) {
+   pr_err("MAC%u: failed to reset WoWLAN triggers\n",
+  mac->macid);
+   goto exit;
+   }
+
+exit:
+   return ret;
+}
+
+static void qtnf_set_wakeup(struct wiphy *wiphy, bool enabled)
+{
+   struct qtnf_wmac *mac = wiphy_priv(wiphy);
+   struct qtnf_bus *bus = mac->bus;
+
+   device_set_wakeup_enable(bus->dev, enabled);
+}
+#endif
+
 static struct cfg80211_ops qtn_cfg80211_ops = {
.add_virtual_intf   = qtnf_add_virtual_intf,
.change_virtual_intf= qtnf_change_virtual_intf,
@@ -886,6 +952,11 @@ static struct cfg80211_ops qtn_cfg80211_ops = {
.start_radar_detection  = qtnf_start_radar_detection,
.set_mac_acl= qtnf_set_mac_acl,
.set_power_mgmt = qtnf_set_power_mgmt,
+#ifdef CONFIG_PM
+   .suspend= qtnf_suspend,
+   .resume = qtnf_resume,
+   .set_wakeup = qtnf_set_wakeup,
+#endif
 };
 
 static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
@@ -1038,6 +1109,11 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR)
wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
 
+#ifdef CONFIG_PM
+   if (macinfo->wowlan)
+   wiphy->wowlan = macinfo->wowlan;
+#endif
+
if (hw_info->hw_capab & QLINK_HW_CAPAB_REG_UPDATE) {
wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
REGULATORY_CUSTOM_REG;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 7942261961d6..ae9e77300533 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1138,6 +1138,37 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
return 0;
 }
 
+static void
+qtnf_parse_wowlan_info(struct qtnf_wmac *mac,
+  const struct qlink_wowlan_capab_data *wowlan)
+{
+   struct qtnf_mac_info *mac_info = >macinfo;
+

Re: [PATCH 5/6] qtnfmac: add support for PTA configuration

2018-08-01 Thread Sergey Matyukevich
> > > Implement support for PTA (Packet Traffic Arbitration) configuration.
> > > The PTA mechanism is used to coordinate sharing of the medium between
> > > WiFi and other 2.4 wireless networks, e.g. Bluetooth or ZigBee.
> > > 
> > > This patch implements core infrastructure and vendor specific commands
> > > to control PTA functionality in firmware.
> > 
> > And no description of the actual interface which would have helped with
> > the review.
> > 
> > Anyway, the vendor commands are pain and they just make me grumpy. The
> > original idea was that upstream drivers should not support them at all,
> > later we flexed the rules so that low level hardware specific interfaces
> > might be ok, for example we added one in wil6210.
> > 
> > If I would even consider applying a patch which adds a vendor command it
> > needs a really good commit log with a proper description of the actual
> > interface and good justifications why a generic nl80211 command won't
> > work. I don't see anything even remotely close here.
> > 
> > Sorry for being grumpy, I just hate these vendor commands. Especially
> > when I see that a generic nl80211 command has not even be consired at
> > all.
> 
> For what it is worth, looking at part of the patch:
> 
> +/**
> + * enum qlink_pta_mode - Packet Traffic Arbiter operating modes
> + *
> + * @QLINK_PTA_MODE_DISABLED: PTA is disabled
> + * @QLINK_PTA_MODE_2_WIRE: enable PTA 2-wire mode
> + */
> +enum qlink_pta_mode {
> +   QLINK_PTA_MODE_DISABLED = 0,
> +   QLINK_PTA_MODE_2_WIRE = 2
> +};
> +
> 
> it smells very much like low-level btcoex. The question is whether this
> needs to be conveyed from user-space or should these be device
> configuration, eg. like DT properties.

Hello Arend,

Yes, this is some kind of low-level BT coexistence mechanism, when WiFi and
BT cards coordinate access to wireless media in 2.4G using gpio lines.
Those lines connect WiFi and BT cards directly w/o host mediation.

As for DT properties, the qustion still remains the same: how to propagate
those settings to WiFi card. AFAIK there is no 'standard' interface for
this kind of things. So using vendor commands looked like the only option.

Regards,
Sergey


Re: [PATCH 6/6] qtnfmac: implement basic WoWLAN support

2018-07-31 Thread Sergey Matyukevich


Hello Kalle,

> > This patch implements core WoWLAN support in qtnfmac driver, including
> > processing of WoWLAN features reported by firmware and implementation
> > of cfg80211 suspend/resume/wakeup callbacks. Currently the following
> > WoWLAN triggers are supported: disconnect, magic packet,
> > custom pattern packet.
> >
> > Signed-off-by: Sergey Matyukevich 
> 
> Doesn't apply anymore as I dropped patch 5
> 
> fatal: sha1 information is lacking or useless 
> (drivers/net/wireless/quantenna/qtnfmac/cfg80211.c).
> error: could not build fake ancestor
> Applying: qtnfmac: implement basic WoWLAN support
> Patch failed at 0001 qtnfmac: implement basic WoWLAN support
> The copy of the patch that failed is found in: .git/rebase-apply/patch
> 
> Patch set to Changes Requested.

Thanks for review. I will rebase the remaining patches on top of your
up-to-date tree and resubmit.

As for the patch with vendor specific commands, I will split it into
a separate discussion and make another attempt to convince you, adding
proper description. IIRC there is no generic functionality suitable
for this particular usecase.

Regards,
Sergey


Re: [1/6] qtnfmac: implement net_device_ops callback to set MAC address

2018-06-29 Thread Sergey Matyukevich
> Sergey Matyukevich  writes:
> 
> >> Sergey Matyukevich  wrote:
> >>
> >> > From: Igor Mitsyanko 
> >> >
> >> > Implement net_device_ops::ndo_set_mac_address callback to allow for
> >> > setting interface MAC address. Implementation is done through existing
> >> > CHANGE_INTF firmware command. All validation is to be done by firmware.
> >> >
> >> > Signed-off-by: Igor Mitsyanko 
> >>
> >> 2 patches applied to wireless-drivers-next.git, thanks.
> >>
> >> ed9f34bb9d33 qtnfmac: implement net_device_ops callback to set MAC address
> >> 6fbef9540af0 qtnfmac: enable source MAC address randomization support
> >
> > Hello Kalle,
> >
> > I see the other 4 patches in this series are in 'Deferred' state. Could you
> > please clarify what that means. Do you have any concerns about those
> > remaining patches or any actions are needed from our side ?
> 
> I saw there was a comment on one patch and other patch used vendor
> commands which I need to review carefully. I didn't have time at the
> time so I put them to deferred and try to get back soon.

Ok, understood.

Regards,
Sergey


Re: [wireless-drivers-next:master 54/55] drivers/net/wireless/quantenna/qtnfmac/cfg80211.c:679:10-19: ERROR: vif is NULL but dereferenced. (fwd)

2018-06-15 Thread Sergey Matyukevich


Hello Julia,

> This report is a bit old, so perahsp the problem is already addressed.  In
> any case, the goto out on line 658 will lead to a null pointer
> dereference.
> 
> julia

Thanks for the issue report !

We have already received similar issue report together with the fix for it.
Fix has not yet been applied to wireless-drivers-next/master.
But, according to Kalle, it will be queued for 4.18.

By the way, the previous issue report was based on Coverity analysis.
Could you please clarify what kind of tool was used by kbuild robot
for analysis ? I couldn't figure this out from your logs.

Regards,
Sergey


Re: [PATCH 3/6] qtnfmac: implement cfg80211 power management callback

2018-06-04 Thread Sergey Matyukevich
Hello Igor,

> > Implement set_power_mgmt() callback that forwards power saving
> > settings to the device firmware.
> > 
> > Signed-off-by: Sergei Maksimenko 
> > ---
> >   static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
> > @@ -922,6 +939,9 @@ struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus)
> > if (bus->hw_info.hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)
> > qtn_cfg80211_ops.start_radar_detection = NULL;
> > +   if (!(bus->hw_info.hw_capab & QLINK_HW_CAPAB_PWR_MGMT))
> > +   qtn_cfg80211_ops.set_power_mgmt = NULL;
> > +
> 
> I think it's better be moved somewhere out of qtnf_wiphy_allocate() as OPS
> are global for all MACs, while qtnf_wiphy_allocate() is called for each MAC
> separately.

Consider the case of splitting hardware capabilities into two groups:
global and per-wmac. In this case we may need to register different
subsets of cfg80211 operations for each wmac. In such a case, function
qtnf_wiphy_allocate looks like a reasonable point where to merge both
capability groups and customize cfg80211_ops structure for each wmac.

Regards,
Sergey


Re: [PATCH 0/6] qtnfmac: enable more features

2018-05-31 Thread Sergey Matyukevich
Hello Kalle,

> > Here is the next update for qtnfmac driver which enables more wireless
> > features. The major changes include the following items:
> > - cfg80211 power management callback
> > - net_device_ops set MAC addr callback
> > - advanced scan features: multiple SSIDs and randomized source MACs
> > - basic WoWLAN support: disconnect/magic/pattern triggers
> >   -- not yet: PCIe backend suspend/resume, reporting wakeup reason
> 
> BTW, most likely the merge window will start on Sunday and I'm planning
> to send the last w-d-next pull request to Dave today. So you just missed
> the window to get these to 4.18 by a day.

Ok. Thanks for letting us know. I assume that our previous 'fixes' patch
series (which you applied today) will be included into your
4.18 pull request. Correct ?

Regards,
Sergey


[PATCH 5/6] qtnfmac: add support for PTA configuration

2018-05-31 Thread Sergey Matyukevich
From: Andrey Shevchenko 

Implement support for PTA (Packet Traffic Arbitration) configuration.
The PTA mechanism is used to coordinate sharing of the medium between
WiFi and other 2.4 wireless networks, e.g. Bluetooth or ZigBee.

This patch implements core infrastructure and vendor specific commands
to control PTA functionality in firmware.

Signed-off-by: Andrey Shevchenko 
---
 drivers/net/wireless/quantenna/qtnfmac/Makefile   |   4 +-
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |   4 +
 drivers/net/wireless/quantenna/qtnfmac/commands.c |  51 
 drivers/net/wireless/quantenna/qtnfmac/commands.h |   3 +-
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|  60 +
 drivers/net/wireless/quantenna/qtnfmac/vendor.c   | 145 ++
 drivers/net/wireless/quantenna/qtnfmac/vendor.h   |  35 ++
 7 files changed, 299 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/wireless/quantenna/qtnfmac/vendor.c
 create mode 100644 drivers/net/wireless/quantenna/qtnfmac/vendor.h

diff --git a/drivers/net/wireless/quantenna/qtnfmac/Makefile 
b/drivers/net/wireless/quantenna/qtnfmac/Makefile
index 97f760a3d599..9e058617d694 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/Makefile
+++ b/drivers/net/wireless/quantenna/qtnfmac/Makefile
@@ -15,8 +15,8 @@ qtnfmac-objs += \
cfg80211.o \
event.o \
util.o \
-   qlink_util.o
-
+   qlink_util.o \
+   vendor.o
 #
 
 obj-$(CONFIG_QTNFMAC_PEARL_PCIE) += qtnfmac_pearl_pcie.o
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 307ab5c59bfd..956852748cb1 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -26,6 +26,7 @@
 #include "core.h"
 #include "util.h"
 #include "bus.h"
+#include "vendor.h"
 
 /* Supported rates to be advertised to the cfg80211 */
 static struct ieee80211_rate qtnf_rates_2g[] = {
@@ -1052,6 +1053,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
sizeof(wiphy->fw_version));
wiphy->hw_version = hw_info->hw_version;
 
+   wiphy->vendor_commands = qtnf_vendor_cmds;
+   wiphy->n_vendor_commands = qtnf_vendor_get_cmds_number();
+
ret = wiphy_register(wiphy);
if (ret < 0)
goto out;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 10836695c5f5..45a2effa3eab 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -22,6 +22,7 @@
 #include "qlink_util.h"
 #include "bus.h"
 #include "commands.h"
+#include "vendor.h"
 
 static int qtnf_cmd_check_reply_header(const struct qlink_resp *resp,
   u16 cmd_id, u8 mac_id, u8 vif_id,
@@ -2831,3 +2832,53 @@ int qtnf_cmd_send_pm_set(const struct qtnf_vif *vif, u8 
pm_mode, int timeout)
qtnf_bus_unlock(bus);
return ret;
 }
+
+int qtnf_cmd_setget_pta_param(struct qtnf_wmac *mac,
+ int param_id, bool set_op, int *param_val)
+{
+   struct sk_buff *cmd_skb;
+   struct qlink_cmd_pta_param *cmd;
+   const struct qlink_resp_pta_param *resp;
+   struct sk_buff *resp_skb = NULL;
+   u16 res_code;
+   int ret;
+
+   if (!param_val)
+   return -EINVAL;
+
+   cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
+   QLINK_CMD_PTA_PARAM,
+   sizeof(*cmd));
+   if (!cmd_skb)
+   return -ENOMEM;
+
+   cmd = (struct qlink_cmd_pta_param *)cmd_skb->data;
+   cmd->pta_param_id = param_id;
+   if (set_op) {
+   cmd->set_op = 1;
+   cmd->pta_param_value = cpu_to_le32(*param_val);
+   } else {
+   cmd->set_op = 0;
+   }
+
+   qtnf_bus_lock(mac->bus);
+   ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, _skb,
+  _code, sizeof(*resp), NULL);
+   qtnf_bus_unlock(mac->bus);
+
+   if (ret)
+   goto out;
+
+   if (res_code != QLINK_CMD_RESULT_OK) {
+   pr_err("cmd exec failed: 0x%x\n", res_code);
+   ret = -EFAULT;
+   goto out;
+   }
+
+   resp = (const struct qlink_resp_pta_param *)resp_skb->data;
+
+   *param_val = le32_to_cpu(resp->pta_param_value);
+out:
+   consume_skb(resp_skb);
+   return ret;
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h 
b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index 03a57e37a665..59e86db5e982 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -77,5 +77,6 @@ int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
 int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
 

[PATCH 6/6] qtnfmac: implement basic WoWLAN support

2018-05-31 Thread Sergey Matyukevich
This patch implements core WoWLAN support in qtnfmac driver, including
processing of WoWLAN features reported by firmware and implementation
of cfg80211 suspend/resume/wakeup callbacks. Currently the following
WoWLAN triggers are supported: disconnect, magic packet,
custom pattern packet.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |  76 +++
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 112 ++
 drivers/net/wireless/quantenna/qtnfmac/commands.h |   3 +
 drivers/net/wireless/quantenna/qtnfmac/core.c |   1 +
 drivers/net/wireless/quantenna/qtnfmac/core.h |   1 +
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|  56 +++
 6 files changed, 249 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 956852748cb1..c0d5ca37168b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -861,6 +861,72 @@ static int qtnf_set_power_mgmt(struct wiphy *wiphy, struct 
net_device *dev,
return ret;
 }
 
+#ifdef CONFIG_PM
+static int qtnf_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wowlan)
+{
+   struct qtnf_wmac *mac = wiphy_priv(wiphy);
+   struct qtnf_vif *vif;
+   int ret = 0;
+
+   vif = qtnf_mac_get_base_vif(mac);
+   if (!vif) {
+   pr_err("MAC%u: primary VIF is not configured\n", mac->macid);
+   ret = -EFAULT;
+   goto exit;
+   }
+
+   if (!wowlan) {
+   pr_debug("WoWLAN triggers are not enabled\n");
+   qtnf_virtual_intf_cleanup(vif->netdev);
+   goto exit;
+   }
+
+   qtnf_scan_done(vif->mac, true);
+
+   ret = qtnf_cmd_send_wowlan_set(vif, wowlan);
+   if (ret) {
+   pr_err("MAC%u: failed to set WoWLAN triggers\n",
+  mac->macid);
+   goto exit;
+   }
+
+exit:
+   return ret;
+}
+
+static int qtnf_resume(struct wiphy *wiphy)
+{
+   struct qtnf_wmac *mac = wiphy_priv(wiphy);
+   struct qtnf_vif *vif;
+   int ret = 0;
+
+   vif = qtnf_mac_get_base_vif(mac);
+   if (!vif) {
+   pr_err("MAC%u: primary VIF is not configured\n", mac->macid);
+   ret = -EFAULT;
+   goto exit;
+   }
+
+   ret = qtnf_cmd_send_wowlan_set(vif, NULL);
+   if (ret) {
+   pr_err("MAC%u: failed to reset WoWLAN triggers\n",
+  mac->macid);
+   goto exit;
+   }
+
+exit:
+   return ret;
+}
+
+static void qtnf_set_wakeup(struct wiphy *wiphy, bool enabled)
+{
+   struct qtnf_wmac *mac = wiphy_priv(wiphy);
+   struct qtnf_bus *bus = mac->bus;
+
+   device_set_wakeup_enable(bus->dev, enabled);
+}
+#endif
+
 static struct cfg80211_ops qtn_cfg80211_ops = {
.add_virtual_intf   = qtnf_add_virtual_intf,
.change_virtual_intf= qtnf_change_virtual_intf,
@@ -888,6 +954,11 @@ static struct cfg80211_ops qtn_cfg80211_ops = {
.start_radar_detection  = qtnf_start_radar_detection,
.set_mac_acl= qtnf_set_mac_acl,
.set_power_mgmt = qtnf_set_power_mgmt,
+#ifdef CONFIG_PM
+   .suspend= qtnf_suspend,
+   .resume = qtnf_resume,
+   .set_wakeup = qtnf_set_wakeup,
+#endif
 };
 
 static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
@@ -1040,6 +,11 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR)
wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
 
+#ifdef CONFIG_PM
+   if (macinfo->wowlan)
+   wiphy->wowlan = macinfo->wowlan;
+#endif
+
if (hw_info->hw_capab & QLINK_HW_CAPAB_REG_UPDATE) {
wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
REGULATORY_CUSTOM_REG;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 45a2effa3eab..d9540edf78de 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1139,6 +1139,37 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
return 0;
 }
 
+static void
+qtnf_parse_wowlan_info(struct qtnf_wmac *mac,
+  const struct qlink_wowlan_capab_data *wowlan)
+{
+   struct qtnf_mac_info *mac_info = >macinfo;
+   const struct qlink_wowlan_support *data1;
+   struct wiphy_wowlan_support *supp;
+
+   supp = kzalloc(sizeof(*supp), GFP_KERNEL);
+   if (!supp)
+   return;
+
+   switch (le16_to_cpu(wowlan->version)) {
+   case 0x1:
+   data1 = (struct qlink_wo

[PATCH 4/6] qtnfmac: enable multiple SSIDs scan support

2018-05-31 Thread Sergey Matyukevich
From: Andrey Shevchenko 

Enable support for multiple SSIDs scans. Get max number of supported
SSIDs from firmware and report to cfg80211 core.

Signed-off-by: Andrey Shevchenko 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 3 ++-
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 8 +++-
 drivers/net/wireless/quantenna/qtnfmac/core.h | 2 +-
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 3 +++
 4 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 15bc26c9933f..307ab5c59bfd 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -996,7 +996,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
wiphy->retry_long = macinfo->lretry_limit;
wiphy->coverage_class = macinfo->coverage_class;
 
-   wiphy->max_scan_ssids = QTNF_MAX_SSID_LIST_LENGTH;
+   wiphy->max_scan_ssids =
+   (hw_info->max_scan_ssids) ? hw_info->max_scan_ssids : 1;
wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN;
wiphy->mgmt_stypes = qtnf_mgmt_stypes;
wiphy->max_remain_on_channel_duration = 5000;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index a96d58f72c07..10836695c5f5 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1092,6 +1092,9 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
case QTN_TLV_ID_UBOOT_VER:
uboot_ver = (const void *)tlv->val;
break;
+   case QTN_TLV_ID_MAX_SCAN_SSIDS:
+   hwinfo->max_scan_ssids = *tlv->val;
+   break;
default:
break;
}
@@ -2260,11 +2263,6 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
int count = 0;
int ret;
 
-   if (scan_req->n_ssids > QTNF_MAX_SSID_LIST_LENGTH) {
-   pr_err("MAC%u: too many SSIDs in scan request\n", mac->macid);
-   return -EINVAL;
-   }
-
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
QLINK_CMD_SCAN,
sizeof(struct qlink_cmd));
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h 
b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 214435448335..c4808f1ba8b0 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -40,7 +40,6 @@
 #undef pr_fmt
 #define pr_fmt(fmt)KBUILD_MODNAME ": %s: " fmt, __func__
 
-#define QTNF_MAX_SSID_LIST_LENGTH  2
 #define QTNF_MAX_VSIE_LEN  255
 #define QTNF_MAX_INTF  8
 #define QTNF_MAX_EVENT_QUEUE_LEN   255
@@ -145,6 +144,7 @@ struct qtnf_hw_info {
u8 total_rx_chain;
char fw_version[ETHTOOL_FWVERS_LEN];
u32 hw_version;
+   u8 max_scan_ssids;
 };
 
 struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index cbdebf0410df..8fbef67fbbb8 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -1091,6 +1091,8 @@ struct qlink_event_radar {
  * @QTN_TLV_ID_STA_STATS: per-STA statistics as defined by
  *  qlink_sta_stats. Valid values are marked as such in a bitmap
  * 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.
  */
 enum qlink_tlv_id {
QTN_TLV_ID_FRAG_THRESH  = 0x0201,
@@ -1119,6 +1121,7 @@ enum qlink_tlv_id {
QTN_TLV_ID_CALIBRATION_VER  = 0x0406,
QTN_TLV_ID_UBOOT_VER= 0x0407,
QTN_TLV_ID_RANDOM_MAC_ADDR  = 0x0408,
+   QTN_TLV_ID_MAX_SCAN_SSIDS   = 0x0409,
 };
 
 struct qlink_tlv_hdr {
-- 
2.11.0



[PATCH 2/6] qtnfmac: enable source MAC address randomization support

2018-05-31 Thread Sergey Matyukevich
From: Andrey Shevchenko 

Enable support for source MAC address randomization of probe request
frames. Pass addr/mask randomization parameters to firmware.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 220e2b710208..23366be9e394 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -1014,6 +1014,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
if (hw_info->hw_capab & QLINK_HW_CAPAB_STA_INACT_TIMEOUT)
wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
 
+   if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR)
+   wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
+
if (hw_info->hw_capab & QLINK_HW_CAPAB_REG_UPDATE) {
wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
REGULATORY_CUSTOM_REG;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 5eb143667539..710806466bd9 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2234,6 +2234,22 @@ static void qtnf_cmd_channel_tlv_add(struct sk_buff 
*cmd_skb,
qchan->chan.flags = cpu_to_le32(flags);
 }
 
+static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb,
+const u8 *mac_addr,
+const u8 *mac_addr_mask)
+{
+   struct qlink_random_mac_addr *randmac;
+   struct qlink_tlv_hdr *hdr =
+   skb_put(cmd_skb, sizeof(*hdr) + sizeof(*randmac));
+
+   hdr->type = cpu_to_le16(QTN_TLV_ID_RANDOM_MAC_ADDR);
+   hdr->len = cpu_to_le16(sizeof(*randmac));
+   randmac = (struct qlink_random_mac_addr *)hdr->val;
+
+   memcpy(randmac->mac_addr, mac_addr, ETH_ALEN);
+   memcpy(randmac->mac_addr_mask, mac_addr_mask, ETH_ALEN);
+}
+
 int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
 {
struct sk_buff *cmd_skb;
@@ -2291,6 +2307,15 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
}
}
 
+   if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
+   pr_debug("MAC%u: scan with random addr=%pM, mask=%pM\n",
+mac->macid,
+scan_req->mac_addr, scan_req->mac_addr_mask);
+
+   qtnf_cmd_randmac_tlv_add(cmd_skb, scan_req->mac_addr,
+scan_req->mac_addr_mask);
+   }
+
ret = qtnf_cmd_send(mac->bus, cmd_skb, _code);
 
if (unlikely(ret))
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index f85deda703fb..4a32967d0479 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -69,11 +69,14 @@ struct qlink_msg_header {
  * associated STAs due to inactivity. Inactivity timeout period is taken
  * from QLINK_CMD_START_AP parameters.
  * @QLINK_HW_CAPAB_DFS_OFFLOAD: device implements DFS offload functionality
+ * @QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR: device supports MAC Address
+ * Randomization in probe requests.
  */
 enum qlink_hw_capab {
QLINK_HW_CAPAB_REG_UPDATE   = BIT(0),
QLINK_HW_CAPAB_STA_INACT_TIMEOUT= BIT(1),
QLINK_HW_CAPAB_DFS_OFFLOAD  = BIT(2),
+   QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR = BIT(3),
 };
 
 enum qlink_iface_type {
@@ -1089,6 +1092,7 @@ enum qlink_tlv_id {
QTN_TLV_ID_HW_ID= 0x0405,
QTN_TLV_ID_CALIBRATION_VER  = 0x0406,
QTN_TLV_ID_UBOOT_VER= 0x0407,
+   QTN_TLV_ID_RANDOM_MAC_ADDR  = 0x0408,
 };
 
 struct qlink_tlv_hdr {
@@ -1360,4 +1364,20 @@ struct qlink_sta_stats {
u8 rsvd[1];
 };
 
+/**
+ * struct qlink_random_mac_addr - data for QTN_TLV_ID_RANDOM_MAC_ADDR TLV
+ *
+ * Specifies MAC address mask/value for generation random MAC address
+ * during scan.
+ *
+ * @mac_addr: MAC address used with randomisation
+ * @mac_addr_mask: MAC address mask used with randomisation, bits that
+ * are 0 in the mask should be randomised, bits that are 1 should
+ * be taken from the @mac_addr
+ */
+struct qlink_random_mac_addr {
+   u8 mac_addr[ETH_ALEN];
+   u8 mac_addr_mask[ETH_ALEN];
+} __packed;
+
 #endif /* _QTN_QLINK_H_ */
-- 
2.11.0



[PATCH 1/6] qtnfmac: implement net_device_ops callback to set MAC address

2018-05-31 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Implement net_device_ops::ndo_set_mac_address callback to allow for
setting interface MAC address. Implementation is done through existing
CHANGE_INTF firmware command. All validation is to be done by firmware.

Signed-off-by: Igor Mitsyanko 
---
 drivers/net/wireless/quantenna/qtnfmac/core.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
b/drivers/net/wireless/quantenna/qtnfmac/core.c
index a6a450984f9a..c318340e1bd5 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -179,6 +179,30 @@ static void qtnf_netdev_tx_timeout(struct net_device *ndev)
}
 }
 
+static int qtnf_netdev_set_mac_address(struct net_device *ndev, void *addr)
+{
+   struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
+   struct sockaddr *sa = addr;
+   int ret;
+   unsigned char old_addr[ETH_ALEN];
+
+   memcpy(old_addr, sa->sa_data, sizeof(old_addr));
+
+   ret = eth_mac_addr(ndev, sa);
+   if (ret)
+   return ret;
+
+   qtnf_scan_done(vif->mac, true);
+
+   ret = qtnf_cmd_send_change_intf_type(vif, vif->wdev.iftype,
+sa->sa_data);
+
+   if (ret)
+   memcpy(ndev->dev_addr, old_addr, ETH_ALEN);
+
+   return ret;
+}
+
 /* Network device ops handlers */
 const struct net_device_ops qtnf_netdev_ops = {
.ndo_open = qtnf_netdev_open,
@@ -186,6 +210,7 @@ const struct net_device_ops qtnf_netdev_ops = {
.ndo_start_xmit = qtnf_netdev_hard_start_xmit,
.ndo_tx_timeout = qtnf_netdev_tx_timeout,
.ndo_get_stats64 = qtnf_netdev_get_stats64,
+   .ndo_set_mac_address = qtnf_netdev_set_mac_address,
 };
 
 static int qtnf_mac_init_single_band(struct wiphy *wiphy,
-- 
2.11.0



[PATCH 0/6] qtnfmac: enable more features

2018-05-31 Thread Sergey Matyukevich
Hello Kalle and all,

Here is the next update for qtnfmac driver which enables more wireless
features. The major changes include the following items:
- cfg80211 power management callback
- net_device_ops set MAC addr callback
- advanced scan features: multiple SSIDs and randomized source MACs
- basic WoWLAN support: disconnect/magic/pattern triggers
  -- not yet: PCIe backend suspend/resume, reporting wakeup reason

Regards,
Sergey

Sergei Maksimenko (1)
  qtnfmac: implement cfg80211 power management callback

Sergey Matyukevich (1)
  qtnfmac: implement basic WoWLAN support

Igor Mitsyanko (1)
  qtnfmac: implement net_device_ops callback to set MAC address

Andrey Shevchenko (3)
  qtnfmac: add support for PTA configuration
  qtnfmac: enable multiple SSIDs scan support
  qtnfmac: enable source MAC address randomization support


 Makefile   |4 -
 cfg80211.c |  107 
 commands.c |  230 +++--
 commands.h |5 +
 core.c |   26 ++
 core.h |3 
 qlink.h|  165 +++
 vendor.c   |  145 ++
 vendor.h   |   35 +
 9 files changed, 711 insertions(+), 9 deletions(-)


[PATCH 7/9] qtnfmac: fix bg_scan_period parameter processing

2018-05-29 Thread Sergey Matyukevich
From: Andrey Shevchenko 

Do not process bg_scan_period parameter in qtnfmac driver.
Pass correct values as is. In the case of invalid values
pass default value. Leave further processing to firmware.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index e2fc57be1cdd..5eb143667539 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2339,13 +2339,11 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
else
eth_zero_addr(cmd->prev_bssid);
 
-   if ((sme->bg_scan_period > 0) &&
-   (sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD))
+   if ((sme->bg_scan_period >= 0) &&
+   (sme->bg_scan_period <= SHRT_MAX))
cmd->bg_scan_period = cpu_to_le16(sme->bg_scan_period);
-   else if (sme->bg_scan_period == -1)
-   cmd->bg_scan_period = cpu_to_le16(QTNF_DEFAULT_BG_SCAN_PERIOD);
else
-   cmd->bg_scan_period = 0; /* disabled */
+   cmd->bg_scan_period = cpu_to_le16(-1); /* use default value */
 
if (sme->flags & ASSOC_REQ_DISABLE_HT)
connect_flags |= QLINK_STA_CONNECT_DISABLE_HT;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h 
b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 3b884c80b6ab..214435448335 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -44,8 +44,6 @@
 #define QTNF_MAX_VSIE_LEN  255
 #define QTNF_MAX_INTF  8
 #define QTNF_MAX_EVENT_QUEUE_LEN   255
-#define QTNF_DEFAULT_BG_SCAN_PERIOD300
-#define QTNF_MAX_BG_SCAN_PERIOD0x
 #define QTNF_SCAN_TIMEOUT_SEC  15
 
 #define QTNF_DEF_BSS_PRIORITY  0
-- 
2.11.0



[PATCH 3/9] qtnfmac: decode error codes from firmware replies

2018-05-29 Thread Sergey Matyukevich
From: Igor Mitsyanko 

Introduce a function that will map an error code reported in reply
to a firmware command, into one of standard errno codes.
Use additional error codes to improve error reporting
for MAC address changes.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index deca0060eb27..9dc4560be5d8 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -55,6 +55,28 @@ static int qtnf_cmd_check_reply_header(const struct 
qlink_resp *resp,
return 0;
 }
 
+static int qtnf_cmd_resp_result_decode(enum qlink_cmd_result qcode)
+{
+   switch (qcode) {
+   case QLINK_CMD_RESULT_OK:
+   return 0;
+   case QLINK_CMD_RESULT_INVALID:
+   return -EINVAL;
+   case QLINK_CMD_RESULT_ENOTSUPP:
+   return -ENOTSUPP;
+   case QLINK_CMD_RESULT_ENOTFOUND:
+   return -ENOENT;
+   case QLINK_CMD_RESULT_EALREADY:
+   return -EALREADY;
+   case QLINK_CMD_RESULT_EADDRINUSE:
+   return -EADDRINUSE;
+   case QLINK_CMD_RESULT_EADDRNOTAVAIL:
+   return -EADDRNOTAVAIL;
+   default:
+   return -EFAULT;
+   }
+}
+
 static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
struct sk_buff *cmd_skb,
struct sk_buff **response_skb,
@@ -810,10 +832,10 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif 
*vif,
if (unlikely(ret))
goto out;
 
-   if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+   ret = qtnf_cmd_resp_result_decode(res_code);
+   if (ret) {
pr_err("VIF%u.%u: CMD %d failed: %u\n", vif->mac->macid,
   vif->vifid, cmd_type, res_code);
-   ret = -EFAULT;
goto out;
}
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 9ab27e158023..f85deda703fb 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -674,6 +674,8 @@ enum qlink_cmd_result {
QLINK_CMD_RESULT_ENOTSUPP,
QLINK_CMD_RESULT_ENOTFOUND,
QLINK_CMD_RESULT_EALREADY,
+   QLINK_CMD_RESULT_EADDRINUSE,
+   QLINK_CMD_RESULT_EADDRNOTAVAIL,
 };
 
 /**
-- 
2.11.0



[PATCH 8/9] qtnfmac: cancel scan on disconnect

2018-05-29 Thread Sergey Matyukevich
From: Andrey Shevchenko 

Cancel scan operation on STA disconnect.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 2089cb095283..1fcd94bf7c59 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -660,6 +660,8 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
 
+   qtnf_scan_done(mac, true);
+
if (vif->sta_state == QTNF_STA_DISCONNECTED)
return 0;
 
-- 
2.11.0



[PATCH 9/9] qtnfmac: fix invalid STA state on EAPOL failure

2018-05-29 Thread Sergey Matyukevich
Driver switches vif sta_state into QTNF_STA_CONNECTING when cfg80211
core initiates connect procedure. Further this state is changed either
to QTNF_STA_CONNECTED or to QTNF_STA_DISCONNECTED by BSS_JOIN and
BSS_LEAVE events from firmware. However it is possible that no such
events will be sent by firmware, e.g. if EAPOL timed out.

In this case vif sta_mode will remain in QTNF_STA_CONNECTING state and
all subsequent connection attempts will fail with -EBUSY error code.
Fix this by perfroming STA state transition from QTNF_STA_CONNECTING
to QTNF_STA_DISCONNECTED in cfg80211 disconnect callback.
No need to rely upon firmware events in this case.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 1fcd94bf7c59..220e2b710208 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -649,30 +649,37 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device 
*dev,
 {
struct qtnf_wmac *mac = wiphy_priv(wiphy);
struct qtnf_vif *vif;
-   int ret;
+   int ret = 0;
 
vif = qtnf_mac_get_base_vif(mac);
if (!vif) {
pr_err("MAC%u: primary VIF is not configured\n", mac->macid);
-   return -EFAULT;
+   ret = -EFAULT;
+   goto out;
}
 
-   if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
-   return -EOPNOTSUPP;
+   if (vif->wdev.iftype != NL80211_IFTYPE_STATION) {
+   ret = -EOPNOTSUPP;
+   goto out;
+   }
 
qtnf_scan_done(mac, true);
 
if (vif->sta_state == QTNF_STA_DISCONNECTED)
-   return 0;
+   goto out;
 
ret = qtnf_cmd_send_disconnect(vif, reason_code);
if (ret) {
pr_err("VIF%u.%u: failed to disconnect\n", mac->macid,
   vif->vifid);
-   return ret;
+   goto out;
}
 
-   return 0;
+out:
+   if (vif->sta_state == QTNF_STA_CONNECTING)
+   vif->sta_state = QTNF_STA_DISCONNECTED;
+
+   return ret;
 }
 
 static int
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c 
b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 16617c44f81b..68da81bec4e9 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -211,11 +211,9 @@ qtnf_event_handle_bss_leave(struct qtnf_vif *vif,
return -EPROTO;
}
 
-   if (vif->sta_state != QTNF_STA_CONNECTED) {
-   pr_err("VIF%u.%u: BSS_LEAVE event when STA is not connected\n",
-  vif->mac->macid, vif->vifid);
-   return -EPROTO;
-   }
+   if (vif->sta_state != QTNF_STA_CONNECTED)
+   pr_warn("VIF%u.%u: BSS_LEAVE event when STA is not connected\n",
+   vif->mac->macid, vif->vifid);
 
pr_debug("VIF%u.%u: disconnected\n", vif->mac->macid, vif->vifid);
 
-- 
2.11.0



[PATCH 4/9] qtnfmac: cleanup wdev structure between its uses

2018-05-29 Thread Sergey Matyukevich
Driver uses statically allocated wdev structures for each virtual
interface. However wdev structure is not properly cleaned up between
its uses. As a result, various bugs appear when userspace tools
like hostapd were not gracefully stopped.

In particular, this commit fixes the following issue:
- start hostapd with more than 2 mBSS
- kill hostapd using SIGKILL
- start again hostapd with more than 2 mBSS
However only two mBSS entities will be started: primary
and the last BSS listed in hostapd config.

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

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index bf624d975953..2089cb095283 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -177,8 +177,6 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct 
wireless_dev *wdev)
vif->netdev->ieee80211_ptr = NULL;
vif->netdev = NULL;
vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-   eth_zero_addr(vif->mac_addr);
-   eth_zero_addr(vif->bssid);
 
return 0;
 }
@@ -216,10 +214,12 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct 
wiphy *wiphy,
}
 
eth_zero_addr(vif->mac_addr);
+   eth_zero_addr(vif->bssid);
vif->bss_priority = QTNF_DEF_BSS_PRIORITY;
+   vif->sta_state = QTNF_STA_DISCONNECTED;
+   memset(>wdev, 0, sizeof(vif->wdev));
vif->wdev.wiphy = wiphy;
vif->wdev.iftype = type;
-   vif->sta_state = QTNF_STA_DISCONNECTED;
break;
default:
pr_err("MAC%u: unsupported IF type %d\n", mac->macid, type);
@@ -255,8 +255,6 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct 
wiphy *wiphy,
qtnf_cmd_send_del_intf(vif);
 err_cmd:
vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-   eth_zero_addr(vif->mac_addr);
-   eth_zero_addr(vif->bssid);
 
return ERR_PTR(-EFAULT);
 }
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
b/drivers/net/wireless/quantenna/qtnfmac/core.c
index b3bfb4faa918..3ccbc427cf56 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -394,7 +394,6 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct 
qtnf_vif *vif,
dev = alloc_netdev_mqs(sizeof(struct qtnf_vif *), name,
   name_assign_type, ether_setup, 1, 1);
if (!dev) {
-   memset(>wdev, 0, sizeof(vif->wdev));
vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
return -ENOMEM;
}
-- 
2.11.0



[PATCH 6/9] qtnfmac: fix firmware command error path

2018-05-29 Thread Sergey Matyukevich
From: Dmitry Lebed 

Free command skb if bus state is not QTNF_FW_STATE_ACTIVE.

Signed-off-by: Dmitry Lebed 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 1 +
 drivers/net/wireless/quantenna/qtnfmac/trans.c| 4 +++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 9dc4560be5d8..e2fc57be1cdd 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -102,6 +102,7 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
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);
+   dev_kfree_skb(cmd_skb);
return -ENODEV;
}
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/trans.c 
b/drivers/net/wireless/quantenna/qtnfmac/trans.c
index ccddfebc508a..345f34ec9750 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/trans.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/trans.c
@@ -35,8 +35,10 @@ int qtnf_trans_send_cmd_with_resp(struct qtnf_bus *bus, 
struct sk_buff *cmd_skb,
bool resp_not_handled = true;
struct sk_buff *resp_skb = NULL;
 
-   if (unlikely(!response_skb))
+   if (unlikely(!response_skb)) {
+   dev_kfree_skb(cmd_skb);
return -EFAULT;
+   }
 
spin_lock(_node->resp_lock);
ctl_node->seq_num++;
-- 
2.11.0



[PATCH 1/9] qtnfmac: remove unused function declarations

2018-05-29 Thread Sergey Matyukevich
From: Andrey Shevchenko 

Functions qtnf_cmd_resp_parse and qtnf_cmd_resp_check have
been removed. Remove their declarations as well.

Signed-off-by: Andrey Shevchenko 
---
 drivers/net/wireless/quantenna/qtnfmac/commands.h | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h 
b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index 69a7d56f7e58..cf9274add26d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -58,11 +58,6 @@ int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 
*mac,
 struct station_parameters *params);
 int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
  struct station_del_parameters *params);
-
-int qtnf_cmd_resp_parse(struct qtnf_bus *bus, struct sk_buff *resp_skb);
-int qtnf_cmd_resp_check(const struct qtnf_vif *vif,
-   const struct sk_buff *resp_skb, u16 cmd_id,
-   u16 *result, const u8 **payload, size_t *payload_size);
 int qtnf_cmd_send_scan(struct qtnf_wmac *mac);
 int qtnf_cmd_send_connect(struct qtnf_vif *vif,
  struct cfg80211_connect_params *sme);
-- 
2.11.0



[PATCH 2/9] qtnfmac: simplify notation

2018-05-29 Thread Sergey Matyukevich
Shorten line lengths using a more compact notation to access mac info.

Signed-off-by: Sergey Matyukevich 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 25 ---
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 5122dc798064..bf624d975953 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -955,6 +955,7 @@ qtnf_wiphy_setup_if_comb(struct wiphy *wiphy, struct 
qtnf_mac_info *mac_info)
 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 = >macinfo;
int ret;
 
if (!wiphy) {
@@ -962,20 +963,20 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
return -EFAULT;
}
 
-   wiphy->frag_threshold = mac->macinfo.frag_thr;
-   wiphy->rts_threshold = mac->macinfo.rts_thr;
-   wiphy->retry_short = mac->macinfo.sretry_limit;
-   wiphy->retry_long = mac->macinfo.lretry_limit;
-   wiphy->coverage_class = mac->macinfo.coverage_class;
+   wiphy->frag_threshold = macinfo->frag_thr;
+   wiphy->rts_threshold = macinfo->rts_thr;
+   wiphy->retry_short = macinfo->sretry_limit;
+   wiphy->retry_long = macinfo->lretry_limit;
+   wiphy->coverage_class = macinfo->coverage_class;
 
wiphy->max_scan_ssids = QTNF_MAX_SSID_LIST_LENGTH;
wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN;
wiphy->mgmt_stypes = qtnf_mgmt_stypes;
wiphy->max_remain_on_channel_duration = 5000;
-   wiphy->max_acl_mac_addrs = mac->macinfo.max_acl_mac_addrs;
+   wiphy->max_acl_mac_addrs = macinfo->max_acl_mac_addrs;
wiphy->max_num_csa_counters = 2;
 
-   ret = qtnf_wiphy_setup_if_comb(wiphy, >macinfo);
+   ret = qtnf_wiphy_setup_if_comb(wiphy, macinfo);
if (ret)
goto out;
 
@@ -994,12 +995,12 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
 
-   wiphy->available_antennas_tx = mac->macinfo.num_tx_chain;
-   wiphy->available_antennas_rx = mac->macinfo.num_rx_chain;
+   wiphy->available_antennas_tx = macinfo->num_tx_chain;
+   wiphy->available_antennas_rx = macinfo->num_rx_chain;
 
-   wiphy->max_ap_assoc_sta = mac->macinfo.max_ap_assoc_sta;
-   wiphy->ht_capa_mod_mask = >macinfo.ht_cap_mod_mask;
-   wiphy->vht_capa_mod_mask = >macinfo.vht_cap_mod_mask;
+   wiphy->max_ap_assoc_sta = macinfo->max_ap_assoc_sta;
+   wiphy->ht_capa_mod_mask = >ht_cap_mod_mask;
+   wiphy->vht_capa_mod_mask = >vht_cap_mod_mask;
 
ether_addr_copy(wiphy->perm_addr, mac->macaddr);
 
-- 
2.11.0



[PATCH 0/9] qtnfmac: bugfixes and cleanups

2018-05-29 Thread Sergey Matyukevich
Hello Kalle and all,

Here is a patch set with various minor fixes and enhancments for qtnfmac driver.

Regards,
Sergey

Andrey Shevchenko (3)
  qtnfmac: cancel scan on disconnect
  qtnfmac: fix bg_scan_period parameter processing
  qtnfmac: remove unused function declarations

Dmitry Lebed (2)
  qtnfmac: fix firmware command error path
  qtnfmac: improve control path timeout handling

Igor Mitsyanko (1)
  qtnfmac: decode error codes from firmware replies

Sergey Matyukevich (3)
  qtnfmac: fix invalid STA state on EAPOL failure
  qtnfmac: cleanup wdev structure between its uses
  qtnfmac: simplify notation


 bus.h|3 ++-
 cfg80211.c   |   56 
 commands.c   |   35 ---
 commands.h   |5 -
 core.c   |3 +--
 core.h   |2 --
 event.c  |8 +++-
 pearl/pcie.c |   15 ---
 qlink.h  |2 ++
 trans.c  |4 +++-
 10 files changed, 83 insertions(+), 50 deletions(-)


Re: [PATCH v4] wireless-drivers: Dynamically allocate struct station_info

2018-05-10 Thread Sergey Matyukevich
> Since the addition of the TXQ stats to cfg80211, the station_info struct
> has grown to be quite large, which results in warnings when allocated on
> the stack. Fix the affected places to do dynamic allocations instead.
> 
> Fixes: 52539ca89f36 ("cfg80211: Expose TXQ stats and parameters to userspace")
> Signed-off-by: Toke Høiland-Jørgensen <t...@toke.dk>
> ---
> v4:
>   - Add missing kfree before return in qtnfmac, as pointed out by Sergey
> Matyukevich.
> 
>  drivers/net/wireless/ath/ath6kl/main.c |   14 ---
>  drivers/net/wireless/ath/wil6210/debugfs.c |   22 +++
>  drivers/net/wireless/ath/wil6210/wmi.c |   19 ++---
>  .../broadcom/brcm80211/brcmfmac/cfg80211.c |   18 ++---
>  drivers/net/wireless/marvell/mwifiex/uap_event.c   |   25 
>  drivers/net/wireless/quantenna/qtnfmac/event.c |   41 
> +---
>  6 files changed, 90 insertions(+), 49 deletions(-)

Reviewed-by: Sergey Matyukevich <sergey.matyukevich...@quantenna.com>

Thanks!
Sergey


Re: [PATCH v2 1/3] wireless-drivers: Dynamically allocate struct station_info

2018-05-10 Thread Sergey Matyukevich
Hello Toke and all,

> Since the addition of the TXQ stats to cfg80211, the station_info struct
> has grown to be quite large, which results in warnings when allocated on
> the stack. Fix the affected places to do dynamic allocations instead.
> 
> Fixes: 52539ca89f36 ("cfg80211: Expose TXQ stats and parameters to userspace")
> Signed-off-by: Toke Høiland-Jørgensen 
> ---
>  drivers/net/wireless/ath/ath6kl/main.c |   14 ++
>  drivers/net/wireless/ath/wil6210/debugfs.c |   22 ++-
>  drivers/net/wireless/ath/wil6210/wmi.c |   19 -
>  .../broadcom/brcm80211/brcmfmac/cfg80211.c |   18 
>  drivers/net/wireless/marvell/mwifiex/uap_event.c   |   25 +++--
>  drivers/net/wireless/quantenna/qtnfmac/event.c |   29 
> +---
>  6 files changed, 82 insertions(+), 45 deletions(-)

Thanks for taking care of this. As for qtnfmac part, there are two
more EINVALs returned during payload processing. So they should be
modified as well to avoid memleaks. Here is a fixup on top of your
patch:

diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c 
b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 969b6fc7128a..16617c44f81b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -78,15 +78,19 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct 
qtnf_vif *vif,
tlv_value_len = le16_to_cpu(tlv->len);
tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
 
-   if (tlv_full_len > payload_len)
-   return -EINVAL;
+   if (tlv_full_len > payload_len) {
+   ret = -EINVAL;
+   goto out;
+   }
 
if (tlv_type == QTN_TLV_ID_IE_SET) {
const struct qlink_tlv_ie_set *ie_set;
unsigned int ie_len;
 
-   if (payload_len < sizeof(*ie_set))
-   return -EINVAL;
+   if (payload_len < sizeof(*ie_set)) {
+   ret = -EINVAL;
+   goto out;
+   }
 
ie_set = (const struct qlink_tlv_ie_set *)tlv;
ie_len = tlv_value_len -

Regards,
Sergey


Re: [PATCH] qtnfmac: fix qtnf_netdev_hard_start_xmit()'s return type

2018-04-25 Thread Sergey Matyukevich
Hi Luc and all,

> The method ndo_start_xmit() is defined as returning an 'netdev_tx_t',
> which is a typedef for an enum type, but the implementation in this
> driver returns an 'int'.
> 
> Fix this by returning 'netdev_tx_t' in this driver too.
> 
> Signed-off-by: Luc Van Oostenryck <luc.vanoostenr...@gmail.com>
> ---
>  drivers/net/wireless/quantenna/qtnfmac/core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
> b/drivers/net/wireless/quantenna/qtnfmac/core.c
> index cf26c15a8..b3bfb4faa 100644
> --- a/drivers/net/wireless/quantenna/qtnfmac/core.c
> +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
> @@ -76,7 +76,7 @@ static int qtnf_netdev_close(struct net_device *ndev)
> 
>  /* Netdev handler for data transmission.
>   */
> -static int
> +static netdev_tx_t
>  qtnf_netdev_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
>  {
> struct qtnf_vif *vif;

Previous ACK from Igor slipped through the cracks due to
outlook/exchange issues. So here is another one.

Reviewed-by: Sergey Matyukevich <sergey.matyukevich...@quantenna.com>

Thanks for the fix !

Regards,
Sergey


Re: [PATCH] qtnfmac: pearl: pcie: fix memory leak in qtnf_fw_work_handler

2018-04-05 Thread Sergey Matyukevich
Hello Gustavo,

> In case memory resources for fw were succesfully allocated, release
> them before jumping to fw_load_fail.
> 
> Addresses-Coverity-ID: 1466092 ("Resource leak")
> Fixes: c3b2f7ca4186 ("qtnfmac: implement asynchronous firmware loading")
> Signed-off-by: Gustavo A. R. Silva <gust...@embeddedor.com>
> ---
>  drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c | 4 
>  1 file changed, 4 insertions(+)

Thanks for the patch!

Reviewed-by: Sergey Matyukevich <sergey.matyukevich...@quantenna.com>

Regards,
Sergey


[PATCH 1/3] cfg80211: fix CAC_STARTED event handling

2018-03-26 Thread Sergey Matyukevich
From: Dmitry Lebed 

Exclude CAC_STARTED event from !wdev->cac_started check,
since cac_started will be set later in the same function.

Signed-off-by: Dmitry Lebed 
---
 net/wireless/mlme.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 6b6818dd76bd..12b3edf70a7b 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -872,7 +872,7 @@ void cfg80211_cac_event(struct net_device *netdev,
 
trace_cfg80211_cac_event(netdev, event);
 
-   if (WARN_ON(!wdev->cac_started))
+   if (WARN_ON(!wdev->cac_started && event != NL80211_RADAR_CAC_STARTED))
return;
 
if (WARN_ON(!wdev->chandef.chan))
-- 
2.11.0



[PATCH 3/3] qtnfmac: add DFS offload support

2018-03-26 Thread Sergey Matyukevich
From: Dmitry Lebed 

DFS offload support implemented:
- DFS_OFFLOAD feature is advertised depending on HW capabilities
- CAC_STARTED event forwarding from HW implemented
- start_radar_detection() callback now returning -ENOTSUPP
  if DFS_OFFLOAD is enabled

Signed-off-by: Dmitry Lebed 
---
 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |  9 +
 drivers/net/wireless/quantenna/qtnfmac/event.c| 11 +++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|  7 +--
 3 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c 
b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 0398bece5782..5122dc798064 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -813,6 +813,9 @@ static int qtnf_start_radar_detection(struct wiphy *wiphy,
struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
int ret;
 
+   if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
+   return -ENOTSUPP;
+
ret = qtnf_cmd_start_cac(vif, chandef, cac_time_ms);
if (ret)
pr_err("%s: failed to start CAC ret=%d\n", ndev->name, ret);
@@ -909,6 +912,9 @@ struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus)
 {
struct wiphy *wiphy;
 
+   if (bus->hw_info.hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)
+   qtn_cfg80211_ops.start_radar_detection = NULL;
+
wiphy = wiphy_new(_cfg80211_ops, sizeof(struct qtnf_wmac));
if (!wiphy)
return NULL;
@@ -982,6 +988,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, 
struct qtnf_wmac *mac)
WIPHY_FLAG_AP_UAPSD |
WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 
+   if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)
+   wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
+
wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
 
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c 
b/drivers/net/wireless/quantenna/qtnfmac/event.c
index bcd415f96412..cb2a6c12f870 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -443,6 +443,17 @@ static int qtnf_event_handle_radar(struct qtnf_vif *vif,
cfg80211_cac_event(vif->netdev, ,
   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
break;
+   case QLINK_RADAR_CAC_STARTED:
+   if (vif->wdev.cac_started)
+   break;
+
+   if (!wiphy_ext_feature_isset(wiphy,
+NL80211_EXT_FEATURE_DFS_OFFLOAD))
+   break;
+
+   cfg80211_cac_event(vif->netdev, ,
+  NL80211_RADAR_CAC_STARTED, GFP_KERNEL);
+   break;
default:
pr_warn("%s: unhandled radar event %u\n",
vif->netdev->name, ev->event);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h 
b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 9bf3ae4d1b3b..9ab27e158023 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -68,10 +68,12 @@ struct qlink_msg_header {
  * @QLINK_HW_CAPAB_STA_INACT_TIMEOUT: device implements a logic to kick-out
  * associated STAs due to inactivity. Inactivity timeout period is taken
  * from QLINK_CMD_START_AP parameters.
+ * @QLINK_HW_CAPAB_DFS_OFFLOAD: device implements DFS offload functionality
  */
 enum qlink_hw_capab {
-   QLINK_HW_CAPAB_REG_UPDATE = BIT(0),
-   QLINK_HW_CAPAB_STA_INACT_TIMEOUT = BIT(1),
+   QLINK_HW_CAPAB_REG_UPDATE   = BIT(0),
+   QLINK_HW_CAPAB_STA_INACT_TIMEOUT= BIT(1),
+   QLINK_HW_CAPAB_DFS_OFFLOAD  = BIT(2),
 };
 
 enum qlink_iface_type {
@@ -1031,6 +1033,7 @@ enum qlink_radar_event {
QLINK_RADAR_CAC_ABORTED,
QLINK_RADAR_NOP_FINISHED,
QLINK_RADAR_PRE_CAC_EXPIRED,
+   QLINK_RADAR_CAC_STARTED,
 };
 
 /**
-- 
2.11.0



[PATCH 2/3] cfg80211: enable use of non-cleared DFS channels for DFS offload

2018-03-26 Thread Sergey Matyukevich
From: Dmitry Lebed 

Currently channel switch/start_ap to DFS channel cannot be done to
non-CAC-cleared channel even if DFS offload if enabled.
Make non-cleared DFS channels available if DFS offload is enabled.
CAC will be started by HW after channel change, start_ap call, etc.

Signed-off-by: Dmitry Lebed 
---
 net/wireless/chan.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index a48859982a32..2db713d18f71 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -579,6 +579,10 @@ static bool cfg80211_get_chans_dfs_available(struct wiphy 
*wiphy,
 {
struct ieee80211_channel *c;
u32 freq, start_freq, end_freq;
+   bool dfs_offload;
+
+   dfs_offload = wiphy_ext_feature_isset(wiphy,
+ NL80211_EXT_FEATURE_DFS_OFFLOAD);
 
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
@@ -596,8 +600,9 @@ static bool cfg80211_get_chans_dfs_available(struct wiphy 
*wiphy,
if (c->flags & IEEE80211_CHAN_DISABLED)
return false;
 
-   if ((c->flags & IEEE80211_CHAN_RADAR)  &&
-   (c->dfs_state != NL80211_DFS_AVAILABLE))
+   if ((c->flags & IEEE80211_CHAN_RADAR) &&
+   (c->dfs_state != NL80211_DFS_AVAILABLE) &&
+   !(c->dfs_state == NL80211_DFS_USABLE && dfs_offload))
return false;
}
 
-- 
2.11.0



[PATCH 0/3] cfg80211: further work on DFS offload enablement

2018-03-26 Thread Sergey Matyukevich
Hello Johannes and all,

Here is a patch set with minor cleanups/updates needed to enable
DFS offload in cfg80211. 

Note that the third patch enables DFS offload for qtnfmac driver.
We assume that it should go through wireless-drivers tree after
all cfg80211/nl80211 changes are reviewed and merged. So it is
posted here for reference purposes only.

Besides, minimal set of user-space changes for hostapd has been
already posted to hostapd mailing list.

Thanks,
Sergey

Dmitrii Lebed (3):
  cfg80211: fix CAC_STARTED event handling
  cfg80211: enable use of non-cleared DFS channels for DFS
  qtnfmac: add DFS offload support

 drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |9 +
 drivers/net/wireless/quantenna/qtnfmac/event.c|   11 +++
 drivers/net/wireless/quantenna/qtnfmac/qlink.h|7 +--
 net/wireless/chan.c   |9 +++--
 net/wireless/mlme.c   |2 +-
 5 files changed, 33 insertions(+), 5 deletions(-)


[PATCH v3 2/2] cfg80211/nl80211: add CAC_STARTED event

2018-03-01 Thread Sergey Matyukevich
From: Dmitry Lebed 

CAC_STARTED event is needed for DFS offload feature and
should be generated by driver/HW if DFS_OFFLOAD is enabled.

Signed-off-by: Dmitry Lebed 
---
 include/uapi/linux/nl80211.h | 3 +++
 net/wireless/mlme.c  | 7 +--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 811928ce4e1c..1633c8b8494a 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -5137,6 +5137,8 @@ enum nl80211_smps_mode {
  * non-operating channel is expired and no longer valid. New CAC must
  * be done on this channel before starting the operation. This is not
  * applicable for ETSI dfs domain where pre-CAC is valid for ever.
+ * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
+ * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
  */
 enum nl80211_radar_event {
NL80211_RADAR_DETECTED,
@@ -5144,6 +5146,7 @@ enum nl80211_radar_event {
NL80211_RADAR_CAC_ABORTED,
NL80211_RADAR_NOP_FINISHED,
NL80211_RADAR_PRE_CAC_EXPIRED,
+   NL80211_RADAR_CAC_STARTED,
 };
 
 /**
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index a877b4d3e5d2..ce5bb624bf01 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -914,14 +914,17 @@ void cfg80211_cac_event(struct net_device *netdev,
   sizeof(struct cfg80211_chan_def));
queue_work(cfg80211_wq, >propagate_cac_done_wk);
cfg80211_sched_dfs_chan_update(rdev);
-   break;
+   /* fall through */
case NL80211_RADAR_CAC_ABORTED:
+   wdev->cac_started = false;
+   break;
+   case NL80211_RADAR_CAC_STARTED:
+   wdev->cac_started = true;
break;
default:
WARN_ON(1);
return;
}
-   wdev->cac_started = false;
 
nl80211_radar_notify(rdev, chandef, event, netdev, gfp);
 }
-- 
2.11.0



[PATCH v3 0/2] cfg80211/nl80211: prepare DFS offload

2018-03-01 Thread Sergey Matyukevich
Hello Johannes and all,

Here is a patch set preparing DFS offload feature. The final purpose is
to enable DFS offload when hardware/driver does all the DFS activities
on its own without any support from user-space tools, e.g. hostapd.
In this case user-space will be only informed about results, e.g.
when CAC started/stopped, radar detected, etc...

User-space functionality is already available in hostapd in the form
of  vendor-specific (QCA) OUI advertising DFS offload support. The
idea is to add missing pieces to kernel and then to convert relevant
hostapd functionality into a vendor neutral form.

Thanks,
Sergey

Changes v2 -> v3
- add patch with CAC_STARTED event

Dmitrii Lebed (2):
  cfg80211/nl80211: add DFS offload flag
  cfg80211/nl80211: add CAC_STARTED event

 include/uapi/linux/nl80211.h |   10 ++
 net/wireless/mlme.c  |7 +--
 net/wireless/nl80211.c   |   12 
 3 files changed, 23 insertions(+), 6 deletions(-)


[PATCH v3 1/2] cfg80211/nl80211: add DFS offload flag

2018-03-01 Thread Sergey Matyukevich
From: Dmitry Lebed 

Add wiphy EXT_FEATURE flag to indicate that HW or driver does
all DFS actions by itself.
User-space functionality already implemented in hostapd using
vendor-specific (QCA) OUI to advertise DFS offload support.
Need to introduce generic flag to inform about DFS offload support.
For deivces with DFS_OFFLOAD flag set user-space will no longer
need to issue CAC or do any actions in response to
"radar detected" events. HW will do everything by itself and send
events to user-space to indicate that CAC was started/finished, etc.

Signed-off-by: Dmitrii Lebed 
---
 include/uapi/linux/nl80211.h |  7 +++
 net/wireless/nl80211.c   | 12 
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 22cca373161d..811928ce4e1c 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4948,6 +4948,12 @@ enum nl80211_feature_flags {
  * probe request tx deferral and suppression
  * @NL80211_EXT_FEATURE_MFP_OPTIONAL: Driver supports the %NL80211_MFP_OPTIONAL
  * value in %NL80211_ATTR_USE_MFP.
+ * @NL80211_EXT_FEATURE_DFS_OFFLOAD: HW/driver will offload DFS actions.
+ * Device or driver will do all DFS-related actions by itself,
+ * informing user-space about CAC progress, radar detection event,
+ * channel change triggered by radar detection event.
+ * No need to start CAC from user-space, no need to react to
+ * "radar detected" event.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4975,6 +4981,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE,
NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
NL80211_EXT_FEATURE_MFP_OPTIONAL,
+   NL80211_EXT_FEATURE_DFS_OFFLOAD,
 
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b5e613d14d6a..d57aba58a418 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7786,12 +7786,13 @@ static int nl80211_start_radar_detection(struct sk_buff 
*skb,
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
struct wireless_dev *wdev = dev->ieee80211_ptr;
+   struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_chan_def chandef;
enum nl80211_dfs_regions dfs_region;
unsigned int cac_time_ms;
int err;
 
-   dfs_region = reg_get_dfs_region(wdev->wiphy);
+   dfs_region = reg_get_dfs_region(wiphy);
if (dfs_region == NL80211_DFS_UNSET)
return -EINVAL;
 
@@ -7805,17 +7806,20 @@ static int nl80211_start_radar_detection(struct sk_buff 
*skb,
if (wdev->cac_started)
return -EBUSY;
 
-   err = cfg80211_chandef_dfs_required(wdev->wiphy, ,
-   wdev->iftype);
+   err = cfg80211_chandef_dfs_required(wiphy, , wdev->iftype);
if (err < 0)
return err;
 
if (err == 0)
return -EINVAL;
 
-   if (!cfg80211_chandef_dfs_usable(wdev->wiphy, ))
+   if (!cfg80211_chandef_dfs_usable(wiphy, ))
return -EINVAL;
 
+   /* CAC start is offloaded to HW and can't be started manually */
+   if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
+   return -EOPNOTSUPP;
+
if (!rdev->ops->start_radar_detection)
return -EOPNOTSUPP;
 
-- 
2.11.0



Re: [PATCH v2] cfg80211/nl80211: add DFS offload flag

2018-03-01 Thread Sergey Matyukevich

Hello Johannes,

> > Add wiphy EXT_FEATURE flag to indicate that HW or driver does
> > all DFS actions by itself.
> > User-space functionality already implemented in hostapd using
> > vendor-specific (QCA) OUI to advertise DFS offload support.
> > Need to introduce generic flag to inform about DFS offload support.
> > For deivces with DFS_OFFLOAD flag set user-space will no longer
> > need to issue CAC or do any actions in response to
> > "radar detected" events. HW will do everything by itself and send
> > events to user-space to indicate that CAC was started/finished, etc.
> >
> > + * @NL80211_EXT_FEATURE_DFS_OFFLOAD: HW/driver will offload DFS actions.
> > + *   Device or driver will do all DFS-related actions by itself,
> > + *   informing user-space about CAC progress, radar detection event,
> > + *   channel change triggered by radar detection event.
> > + *   No need to start CAC from user-space, no need to react to
> > + *   "radar detected" event.
> 
> The "channel change" part bothers me a bit - isn't normally hostapd
> very much in control of the channel? How does it even get notified of
> the new channel? How can you configure the parameters like how many
> beacons to include the (E)CSA IE for, and whether to add ECSA or not
> etc?

We are about to send v3 for this feature. Could you please clarify
your preferences in terms of patchwork procedure ? Should we mark
previous patch versions as superseded for nl80211/cfg80211 patches ?

Regards,
Sergey


Re: [PATCH v2 4/4] qtnfmac: enable networked standby mode on device inactivity

2018-02-27 Thread Sergey Matyukevich
> Sergey Matyukevich <sergey.matyukevich...@quantenna.com> writes:
> 
> > From: Sergei Maksimenko <smaksime...@quantenna.com>
> >
> > Enable support of networked standby mode (NSM) on qsr10g devices.
> > Networked standby is a power saving mode when the device keeps
> > all existing network connections and returns to full power mode
> > on a network activity. When enabled, device enters standby mode
> > after 15 min of inactivity (no associated stations or no trattic).
> > This period can be changed by setting sysfs attribute standby_timeout
> > (0 disables NSM support). A module parameter auto_standby
> > (defaults to 1) controls enabling NSM support on module loading.
> >
> > Signed-off-by: Sergei Maksimenko <smaksime...@quantenna.com>
> 
> Adding a new sysfs file for a wireless driver is usually a bad idea, I
> don't even remember when we had a case where it was ok to do that. In
> principle we want everything to go through cfg80211 using nl80211.
> 
> Also I'm not really fond of the module parameter just to disable a
> feature. And there isn't even any justification why it's needed.

Ok, noted. Then we will take a break and look for better ways to integrate
this feature. Meanwhile, if you have no concerns regarding the first three
patches in the series, is it possible to apply them ? Or I better send v3 ?

Regards,
Sergey


Re: [PATCH 0/6] qtnfmac: qsr10g pcie backend updates

2018-02-27 Thread Sergey Matyukevich
Hello Kalle,

> BTW, I don't see this patchset on patchwork.kernel.org[1], strangely I
> only see v2. I don't know if it's because of problems on patchwork or
> the submitter deleted the patches, but in case someone did delete these
> please do not that. I want to see the old versions from patchwork to
> check the old discussions etc.
> 
> [1] 
> https://patchwork.kernel.org/project/linux-wireless/list/?state=*=qtnfmac

I guess that was me. After the first review round we reworked the patch set.
So I posted v2 and marked v1 as 'Superseded' in Patchwork.

Regards,
Sergey


[PATCH v2] cfg80211/nl80211: add DFS offload flag

2018-02-22 Thread Sergey Matyukevich
From: Dmitry Lebed 

Add wiphy EXT_FEATURE flag to indicate that HW or driver does
all DFS actions by itself.
User-space functionality already implemented in hostapd using
vendor-specific (QCA) OUI to advertise DFS offload support.
Need to introduce generic flag to inform about DFS offload support.
For deivces with DFS_OFFLOAD flag set user-space will no longer
need to issue CAC or do any actions in response to
"radar detected" events. HW will do everything by itself and send
events to user-space to indicate that CAC was started/finished, etc.

Signed-off-by: Dmitrii Lebed 
---
V1->V2 changes:
- moved from wiphy_flags to ext_features flags usage

include/uapi/linux/nl80211.h |  7 +++
 net/wireless/nl80211.c   | 12 
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 22cca373161d..811928ce4e1c 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4948,6 +4948,12 @@ enum nl80211_feature_flags {
  * probe request tx deferral and suppression
  * @NL80211_EXT_FEATURE_MFP_OPTIONAL: Driver supports the %NL80211_MFP_OPTIONAL
  * value in %NL80211_ATTR_USE_MFP.
+ * @NL80211_EXT_FEATURE_DFS_OFFLOAD: HW/driver will offload DFS actions.
+ * Device or driver will do all DFS-related actions by itself,
+ * informing user-space about CAC progress, radar detection event,
+ * channel change triggered by radar detection event.
+ * No need to start CAC from user-space, no need to react to
+ * "radar detected" event.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4975,6 +4981,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE,
NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
NL80211_EXT_FEATURE_MFP_OPTIONAL,
+   NL80211_EXT_FEATURE_DFS_OFFLOAD,
 
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b5e613d14d6a..d57aba58a418 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7786,12 +7786,13 @@ static int nl80211_start_radar_detection(struct sk_buff 
*skb,
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
struct wireless_dev *wdev = dev->ieee80211_ptr;
+   struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_chan_def chandef;
enum nl80211_dfs_regions dfs_region;
unsigned int cac_time_ms;
int err;
 
-   dfs_region = reg_get_dfs_region(wdev->wiphy);
+   dfs_region = reg_get_dfs_region(wiphy);
if (dfs_region == NL80211_DFS_UNSET)
return -EINVAL;
 
@@ -7805,17 +7806,20 @@ static int nl80211_start_radar_detection(struct sk_buff 
*skb,
if (wdev->cac_started)
return -EBUSY;
 
-   err = cfg80211_chandef_dfs_required(wdev->wiphy, ,
-   wdev->iftype);
+   err = cfg80211_chandef_dfs_required(wiphy, , wdev->iftype);
if (err < 0)
return err;
 
if (err == 0)
return -EINVAL;
 
-   if (!cfg80211_chandef_dfs_usable(wdev->wiphy, ))
+   if (!cfg80211_chandef_dfs_usable(wiphy, ))
return -EINVAL;
 
+   /* CAC start is offloaded to HW and can't be started manually */
+   if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
+   return -EOPNOTSUPP;
+
if (!rdev->ops->start_radar_detection)
return -EOPNOTSUPP;
 
-- 
2.16.1



Re: [PATCH] cfg80211/nl80211: add DFS offload flag

2018-02-22 Thread Sergey Matyukevich
Hello Kalle,

> > Friendly advice: you may want to avoid using this footer in emails on
> > the kernel.org mailing lists.
> 
> Indeed. Most of the time I don't even reply to mails with such
> disclaimers and patches containing that will be automatically dropped.

Based on our previous experience we already know that sending patches from
our 'normal' emails with disclaimer is being frowned upon. So all the
patches are being sent from 'oss' emails. But so far we had impression
that participating in further discussion was allowed even from email
addresses with disclaimer.

If this is a problem, we will do the following. Patches will be posted
from 'oss' emails, and authors will participate in discussions from
their personal emails for the time being. Meanwhile we will work with
our management to get 'oss' emails for all the engineers in the team.

Regards,
Sergey


[PATCH] cfg80211/nl80211: add DFS offload flag

2018-02-21 Thread Sergey Matyukevich
From: Dmitry Lebed 

Add wiphy flag to indicate that HW does all DFS actions by itself.
User-space functionality already implemented in hostapd using
vendor-specific (QCA) OUI to advertise HW support.
Need to introduce generic flag to inform about DFS offload support.
For deivces with DFS_OFFLOAD flag set user-space will no longer
need to issue CAC or do any actions in response to
"radar detected" events. HW will do everything by itself and send
events to user-space to idicate that CAC was started/finished, etc.

Signed-off-by: Dmitrii Lebed 
---
 include/net/cfg80211.h   | 7 ++-
 include/uapi/linux/nl80211.h | 9 +
 net/wireless/nl80211.c   | 7 +++
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ed3a28105d6c..b2d17993ae4d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3241,6 +3241,11 @@ struct cfg80211_ops {
  * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN.
  * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing
  * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH.
+ * @WIPHY_FLAG_DFS_OFFLOAD: Device will do all DFS-related actions by itself,
+ * informing user-space about CAC progress, radar detection event,
+ * channel change triggered by radar detection event.
+ * No need to start CAC from user-space, no need to react to
+ * "radar detected" event.
  * @WIPHY_FLAG_SUPPORTS_FW_ROAM: The device supports roaming feature in the
  * firmware.
  * @WIPHY_FLAG_AP_UAPSD: The device supports uapsd on AP.
@@ -3275,7 +3280,7 @@ enum wiphy_flags {
WIPHY_FLAG_CONTROL_PORT_PROTOCOL= BIT(7),
WIPHY_FLAG_IBSS_RSN = BIT(8),
WIPHY_FLAG_MESH_AUTH= BIT(10),
-   /* use hole at 11 */
+   WIPHY_FLAG_DFS_OFFLOAD  = BIT(11),
/* use hole at 12 */
WIPHY_FLAG_SUPPORTS_FW_ROAM = BIT(13),
WIPHY_FLAG_AP_UAPSD = BIT(14),
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 22cca373161d..c53281397be6 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2156,6 +2156,13 @@ enum nl80211_commands {
  * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT.
  * @NL80211_ATTR_PORT_AUTHORIZED: (reserved)
  *
+ * @NL80211_ATTR_DFS_OFFLOAD: Indicates that the HW will offload DFS actions.
+ * Device will do all DFS-related actions by itself,
+ * informing user-space about CAC progress, radar detection event,
+ * channel change triggered by radar detection event.
+ * No need to start CAC from user-space, no need to react to
+ * "radar detected" event.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2582,6 +2589,8 @@ enum nl80211_attrs {
NL80211_ATTR_PMKR0_NAME,
NL80211_ATTR_PORT_AUTHORIZED,
 
+   NL80211_ATTR_DFS_OFFLOAD,
+
/* add attributes here, update the policy in nl80211.c */
 
__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b5e613d14d6a..635bf4143d03 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1530,6 +1530,9 @@ static int nl80211_send_wiphy(struct 
cfg80211_registered_device *rdev,
if ((rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
goto nla_put_failure;
+   if ((rdev->wiphy.flags & WIPHY_FLAG_DFS_OFFLOAD) &&
+   nla_put_flag(msg, NL80211_ATTR_DFS_OFFLOAD))
+   goto nla_put_failure;
state->split_start++;
if (state->split)
break;
@@ -7816,6 +7819,10 @@ static int nl80211_start_radar_detection(struct sk_buff 
*skb,
if (!cfg80211_chandef_dfs_usable(wdev->wiphy, ))
return -EINVAL;
 
+   /* CAC start is offloaded to HW and can't be started manually */
+   if (wdev->wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD)
+   return -EOPNOTSUPP;
+
if (!rdev->ops->start_radar_detection)
return -EOPNOTSUPP;
 
-- 
2.11.0



[PATCH v2 3/4] qtnfmac: implement asynchronous firmware loading

2018-02-10 Thread Sergey Matyukevich
In pci probe() function start firmware loading, protocol handshake
and driver core initialization, and not wait for completion.

Signed-off-by: Sergei Maksimenko 
---
 drivers/net/wireless/quantenna/qtnfmac/bus.h   |   3 +-
 .../net/wireless/quantenna/qtnfmac/pearl/pcie.c| 375 ++---
 2 files changed, 180 insertions(+), 198 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h 
b/drivers/net/wireless/quantenna/qtnfmac/bus.h
index 56e5fed92a2a..0a1604683bab 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/bus.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h
@@ -59,8 +59,9 @@ struct qtnf_bus {
char fwname[32];
struct napi_struct mux_napi;
struct net_device mux_dev;
-   struct completion request_firmware_complete;
+   struct completion firmware_init_complete;
struct workqueue_struct *workqueue;
+   struct work_struct fw_work;
struct work_struct event_work;
struct mutex bus_lock; /* lock during command/event processing */
struct dentry *dbg_dir;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
index 7aa86d8e..f117904d9120 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
@@ -127,7 +127,7 @@ static inline void qtnf_dis_txdone_irq(struct 
qtnf_pcie_bus_priv *priv)
spin_unlock_irqrestore(>irq_lock, flags);
 }
 
-static int qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv)
+static void qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv)
 {
struct pci_dev *pdev = priv->pdev;
 
@@ -148,8 +148,6 @@ static int qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv 
*priv)
pr_warn("legacy PCIE interrupts enabled\n");
pci_intx(pdev, 1);
}
-
-   return 0;
 }
 
 static void qtnf_deassert_intx(struct qtnf_pcie_bus_priv *priv)
@@ -956,6 +954,98 @@ static const struct qtnf_bus_ops qtnf_pcie_bus_ops = {
.data_rx_stop   = qtnf_pcie_data_rx_stop,
 };
 
+static int qtnf_dbg_mps_show(struct seq_file *s, void *data)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(s->private);
+   struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+   seq_printf(s, "%d\n", priv->mps);
+
+   return 0;
+}
+
+static int qtnf_dbg_msi_show(struct seq_file *s, void *data)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(s->private);
+   struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+   seq_printf(s, "%u\n", priv->msi_enabled);
+
+   return 0;
+}
+
+static int qtnf_dbg_irq_stats(struct seq_file *s, void *data)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(s->private);
+   struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+   u32 reg = readl(PCIE_HDP_INT_EN(priv->pcie_reg_base));
+   u32 status;
+
+   seq_printf(s, "pcie_irq_count(%u)\n", priv->pcie_irq_count);
+   seq_printf(s, "pcie_irq_tx_count(%u)\n", priv->pcie_irq_tx_count);
+   status = reg &  PCIE_HDP_INT_TX_BITS;
+   seq_printf(s, "pcie_irq_tx_status(%s)\n",
+  (status == PCIE_HDP_INT_TX_BITS) ? "EN" : "DIS");
+   seq_printf(s, "pcie_irq_rx_count(%u)\n", priv->pcie_irq_rx_count);
+   status = reg &  PCIE_HDP_INT_RX_BITS;
+   seq_printf(s, "pcie_irq_rx_status(%s)\n",
+  (status == PCIE_HDP_INT_RX_BITS) ? "EN" : "DIS");
+   seq_printf(s, "pcie_irq_uf_count(%u)\n", priv->pcie_irq_uf_count);
+   status = reg &  PCIE_HDP_INT_HHBM_UF;
+   seq_printf(s, "pcie_irq_hhbm_uf_status(%s)\n",
+  (status == PCIE_HDP_INT_HHBM_UF) ? "EN" : "DIS");
+
+   return 0;
+}
+
+static int qtnf_dbg_hdp_stats(struct seq_file *s, void *data)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(s->private);
+   struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+   seq_printf(s, "tx_full_count(%u)\n", priv->tx_full_count);
+   seq_printf(s, "tx_done_count(%u)\n", priv->tx_done_count);
+   seq_printf(s, "tx_reclaim_done(%u)\n", priv->tx_reclaim_done);
+   seq_printf(s, "tx_reclaim_req(%u)\n", priv->tx_reclaim_req);
+
+   seq_printf(s, "tx_bd_r_index(%u)\n", priv->tx_bd_r_index);
+   seq_printf(s, "tx_bd_p_index(%u)\n",
+  readl(PCIE_HDP_RX0DMA_CNT(priv->pcie_reg_base))
+   & (priv->tx_bd_num - 1));
+   seq_printf(s, "tx_bd_w_index(%u)\n", priv->tx_bd_w_index);
+   seq_printf(s, "tx queue len(%u)\n",
+  CIRC_CNT(priv->tx_bd_w_index, priv->tx_bd_r_index,
+   priv->tx_bd_num));
+
+   seq_printf(s, "rx_bd_r_index(%u)\n", priv->rx_bd_r_index);
+   seq_printf(s, "rx_bd_p_index(%u)\n",
+  readl(PCIE_HDP_TX0DMA_CNT(priv->pcie_reg_base))
+   & (priv->rx_bd_num - 1));
+   seq_printf(s, "rx_bd_w_index(%u)\n", priv->rx_bd_w_index);
+   seq_printf(s, "rx alloc queue len(%u)\n",

[PATCH v2 1/4] qtnfmac: fix releasing Tx/Rx data buffers

2018-02-10 Thread Sergey Matyukevich
Add missing PCI unmap for Tx buffers and release all buffers explicitly.
Managed release using devm_add_action is not suitable for qtnfmac Tx/Rx
data buffers. The reason is in ordering and dependencies: buffers
should be released after transmission is stopped but before PCI
device resources and DMA allocations are released.

Signed-off-by: Sergey Matyukevich <sergey.matyukevich...@quantenna.com>
---
 .../net/wireless/quantenna/qtnfmac/pearl/pcie.c| 30 +-
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
index 6f6190964320..be5813aa1486 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
@@ -478,10 +478,11 @@ static int alloc_rx_buffers(struct qtnf_pcie_bus_priv 
*priv)
 }
 
 /* all rx/tx activity should have ceased before calling this function */
-static void free_xfer_buffers(void *data)
+static void qtnf_free_xfer_buffers(struct qtnf_pcie_bus_priv *priv)
 {
-   struct qtnf_pcie_bus_priv *priv = (struct qtnf_pcie_bus_priv *)data;
+   struct qtnf_tx_bd *txbd;
struct qtnf_rx_bd *rxbd;
+   struct sk_buff *skb;
dma_addr_t paddr;
int i;
 
@@ -489,19 +490,26 @@ static void free_xfer_buffers(void *data)
for (i = 0; i < priv->rx_bd_num; i++) {
if (priv->rx_skb && priv->rx_skb[i]) {
rxbd = >rx_bd_vbase[i];
+   skb = priv->rx_skb[i];
paddr = QTN_HOST_ADDR(le32_to_cpu(rxbd->addr_h),
  le32_to_cpu(rxbd->addr));
pci_unmap_single(priv->pdev, paddr, SKB_BUF_SIZE,
 PCI_DMA_FROMDEVICE);
-
-   dev_kfree_skb_any(priv->rx_skb[i]);
+   dev_kfree_skb_any(skb);
+   priv->rx_skb[i] = NULL;
}
}
 
/* free tx buffers */
for (i = 0; i < priv->tx_bd_num; i++) {
if (priv->tx_skb && priv->tx_skb[i]) {
-   dev_kfree_skb_any(priv->tx_skb[i]);
+   txbd = >tx_bd_vbase[i];
+   skb = priv->tx_skb[i];
+   paddr = QTN_HOST_ADDR(le32_to_cpu(txbd->addr_h),
+ le32_to_cpu(txbd->addr));
+   pci_unmap_single(priv->pdev, paddr, skb->len,
+PCI_DMA_TODEVICE);
+   dev_kfree_skb_any(skb);
priv->tx_skb[i] = NULL;
}
}
@@ -1321,12 +1329,6 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
goto err_base;
}
 
-   ret = devm_add_action(>dev, free_xfer_buffers, (void *)pcie_priv);
-   if (ret) {
-   pr_err("custom release callback init failed\n");
-   goto err_base;
-   }
-
ret = qtnf_pcie_init_xfer(pcie_priv);
if (ret) {
pr_err("PCIE xfer init failed\n");
@@ -1343,7 +1345,7 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
   "qtnf_pcie_irq", (void *)bus);
if (ret) {
pr_err("failed to request pcie irq %d\n", pdev->irq);
-   goto err_base;
+   goto err_xfer;
}
 
tasklet_init(_priv->reclaim_tq, qtnf_reclaim_tasklet_fn,
@@ -1387,6 +1389,9 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
 err_bringup_fw:
netif_napi_del(>mux_napi);
 
+err_xfer:
+   qtnf_free_xfer_buffers(pcie_priv);
+
 err_base:
flush_workqueue(pcie_priv->workqueue);
destroy_workqueue(pcie_priv->workqueue);
@@ -1416,6 +1421,7 @@ static void qtnf_pcie_remove(struct pci_dev *pdev)
destroy_workqueue(priv->workqueue);
tasklet_kill(>reclaim_tq);
 
+   qtnf_free_xfer_buffers(priv);
qtnf_debugfs_remove(bus);
 
qtnf_pcie_free_shm_ipc(priv);
-- 
2.11.0



[PATCH v2 2/4] qtnfmac: enable reloading of qtnfmac kernel modules

2018-02-10 Thread Sergey Matyukevich
From: Sergei Maksimenko <smaksime...@quantenna.com>

This patch enables rmmod/insmod for qtnfmac kernel modules:
- do not 'pin' pci device in order to disable it on module unload
- implement card reset procedure
- restore PCI bar addresses for restarted wireless card

Signed-off-by: Sergei Maksimenko <smaksime...@quantenna.com>
Signed-off-by: Sergey Matyukevich <sergey.matyukevich...@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c   | 15 ++-
 drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h   |  1 +
 .../wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h|  1 +
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
index be5813aa1486..7aa86d8e 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
@@ -162,6 +162,17 @@ static void qtnf_deassert_intx(struct qtnf_pcie_bus_priv 
*priv)
qtnf_non_posted_write(cfg, reg);
 }
 
+static void qtnf_reset_card(struct qtnf_pcie_bus_priv *priv)
+{
+   const u32 data = QTN_PEARL_IPC_IRQ_WORD(QTN_PEARL_LHOST_EP_RESET);
+   void __iomem *reg = priv->sysctl_bar +
+   QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET;
+
+   qtnf_non_posted_write(data, reg);
+   msleep(QTN_EP_RESET_WAIT_MS);
+   pci_restore_state(priv->pdev);
+}
+
 static void qtnf_ipc_gen_ep_int(void *arg)
 {
const struct qtnf_pcie_bus_priv *priv = arg;
@@ -1308,7 +1319,6 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
goto err_base;
}
 
-   pcim_pin_device(pdev);
pci_set_master(pdev);
 
ret = qtnf_pcie_init_irq(pcie_priv);
@@ -1323,6 +1333,8 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
goto err_base;
}
 
+   pci_save_state(pdev);
+
ret = qtnf_pcie_init_shm_ipc(pcie_priv);
if (ret < 0) {
pr_err("PCIE SHM IPC init failed\n");
@@ -1425,6 +1437,7 @@ static void qtnf_pcie_remove(struct pci_dev *pdev)
qtnf_debugfs_remove(bus);
 
qtnf_pcie_free_shm_ipc(priv);
+   qtnf_reset_card(priv);
 }
 
 #ifdef CONFIG_PM_SLEEP
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h 
b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h
index c5a4e46d26ef..00bb21a1c47a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h
@@ -46,6 +46,7 @@
 /* state transition timeouts */
 #define QTN_FW_DL_TIMEOUT_MS   3000
 #define QTN_FW_QLINK_TIMEOUT_MS3
+#define QTN_EP_RESET_WAIT_MS   1000
 
 #define PCIE_HDP_INT_RX_BITS (0\
| PCIE_HDP_INT_EP_TXDMA \
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h 
b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h
index 5b48b425fa7f..0bfe285b6b48 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h
@@ -351,5 +351,6 @@
 
 #define QTN_PEARL_IPC_IRQ_WORD(irq)(BIT(irq) | BIT(irq + 16))
 #define QTN_PEARL_LHOST_IPC_IRQ(6)
+#define QTN_PEARL_LHOST_EP_RESET   (7)
 
 #endif /* __PEARL_PCIE_H */
-- 
2.11.0



[PATCH v2 4/4] qtnfmac: enable networked standby mode on device inactivity

2018-02-10 Thread Sergey Matyukevich
From: Sergei Maksimenko 

Enable support of networked standby mode (NSM) on qsr10g devices.
Networked standby is a power saving mode when the device keeps
all existing network connections and returns to full power mode
on a network activity. When enabled, device enters standby mode
after 15 min of inactivity (no associated stations or no trattic).
This period can be changed by setting sysfs attribute standby_timeout
(0 disables NSM support). A module parameter auto_standby
(defaults to 1) controls enabling NSM support on module loading.

Signed-off-by: Sergei Maksimenko 
---
 drivers/net/wireless/quantenna/qtnfmac/bus.h  |  1 +
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 33 ++
 drivers/net/wireless/quantenna/qtnfmac/commands.h |  1 +
 drivers/net/wireless/quantenna/qtnfmac/core.c | 77 +++
 drivers/net/wireless/quantenna/qtnfmac/core.h |  2 +
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 30 +
 6 files changed, 144 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h 
b/drivers/net/wireless/quantenna/qtnfmac/bus.h
index 0a1604683bab..7a27ffc6c7a7 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/bus.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h
@@ -65,6 +65,7 @@ struct qtnf_bus {
struct work_struct event_work;
struct mutex bus_lock; /* lock during command/event processing */
struct dentry *dbg_dir;
+   u32 standby_timeout;
/* bus private data */
char bus_priv[0] __aligned(sizeof(void *));
 };
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index deca0060eb27..1e730c9fa371 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2753,3 +2753,36 @@ int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
 
return ret;
 }
+
+int qtnf_cmd_send_pm_set(struct qtnf_bus *bus, u8 pm_mode, u32 timeout)
+{
+   struct sk_buff *cmd_skb;
+   u16 res_code = QLINK_CMD_RESULT_OK;
+   struct qlink_cmd_pm_set *cmd;
+   int ret = 0;
+
+   cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
+   QLINK_CMD_PM_SET, sizeof(*cmd));
+   if (!cmd_skb)
+   return -ENOMEM;
+
+   cmd = (struct qlink_cmd_pm_set *)cmd_skb->data;
+   cmd->pm_mode = pm_mode;
+   cmd->pm_standby_timer = cpu_to_le32(timeout);
+
+   qtnf_bus_lock(bus);
+
+   ret = qtnf_cmd_send(bus, cmd_skb, _code);
+
+   if (unlikely(ret))
+   goto out;
+
+   if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+   pr_err("cmd exec failed: 0x%.4X\n", res_code);
+   ret = -EFAULT;
+   }
+
+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 69a7d56f7e58..a06e6a96c35d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -81,5 +81,6 @@ int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
   u32 cac_time_ms);
 int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
 const struct cfg80211_acl_data *params);
+int qtnf_cmd_send_pm_set(struct qtnf_bus *bus, u8 pm_mode, u32 timeout);
 
 #endif /* QLINK_COMMANDS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
b/drivers/net/wireless/quantenna/qtnfmac/core.c
index cf26c15a84f8..10c4e3ea2404 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -26,6 +26,10 @@
 #include "event.h"
 #include "util.h"
 
+static bool auto_standby = true;
+module_param(auto_standby, bool, 0644);
+MODULE_PARM_DESC(auto_standby, "set to 0 to disable auto standby mode");
+
 #define QTNF_DMP_MAX_LEN 48
 #define QTNF_PRIMARY_VIF_IDX   0
 
@@ -552,6 +556,53 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, 
unsigned int macid)
return ret;
 }
 
+static ssize_t qtnf_pm_standby_timeout_show(struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(dev);
+
+   sprintf(buf, "%u\n", bus->standby_timeout);
+   return strlen(buf);
+}
+
+static ssize_t qtnf_pm_standby_timeout_store(struct device *dev,
+struct device_attribute *attr,
+const char *buf, size_t count)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(dev);
+   int timeout;
+
+   if (count < 1)
+   goto out;
+
+   if (kstrtoint(buf, 0, ))
+   goto out;
+
+   if (timeout < 0)
+   timeout = 0;
+   else if (timeout > S32_MAX)

[PATCH v2 0/4] qtnfmac: qsr10g pcie backend updates

2018-02-10 Thread Sergey Matyukevich
Hello Kalle and all,

Here is a patch set with various fixes and enhacements for qsr10g
PCIe backend driver. The major changes include the following two
items:
- make rmmod/insmod work properly for qtnfmac_pcie driver
- provide configuration knobs to control NSM (networked standby mode)

NSM (networked standby mode) is not related to WiFi standard. This is
a term that has been introduced by European Commission in regulation
No. 1275/2008. Simplifying things a bit, that regulation specifies
ecodesing requirements for various operating modes. In that document
‘networked standby’ is defined as a condition in which the equipment
is able to resume a function by way of a remotely initiated trigger
from a network connection.

Regards,
Sergey


Changes v1 -> v2
- do not perform fw check using request_firmware (Arend)
- meld rmmod/insmod fixes into async fw async load patch
  -- those fixes are reworked by that patch anyway


Sergei Maksimenko (3)
  qtnfmac: implement asynchronous firmware loading
  qtnfmac: enable reloading of qtnfmac kernel modules
  qtnfmac: enable networked standby mode on device

Sergey Matyukevich (1)
  qtnfmac: fix releasing Tx/Rx data buffers


 bus.h   |4 
 commands.c  |   33 +++
 commands.h  |1 
 core.c  |   77 
 core.h  |2 
 pearl/pcie.c|  418 
 pearl/pcie_ipc.h|1 
 pearl/pcie_regs_pearl.h |1 
 qlink.h |   30 +++
 9 files changed, 357 insertions(+), 210 deletions(-)


Re: [PATCH 4/6] qtnfmac: fix rmmod for missing firmware

2018-02-08 Thread Sergey Matyukevich
Hello Arend,

Thanks for review.

> > Check that firmware exists prior to starting firmware download.
> 
> Why would you do that? It seems expensive given that you obtain the
> firmware and discard it immediately just to check it exists. Especially,
> given that such a call can take 60 seconds to complete depending on
> kernel config.
> 
> Apart from that see minor comment below although I would seriously
> reconsider this patch altogether.

The idea behind this approach is simple: to quit early and to avoid starting
asynchronous card boot if no firmware file exists. However I didn't realize that
such a long delay may occur. What makes me worried is that the worst case
scenario may happen if firmware actually exists: we make two calls of
request_firmware, each of them taking long time.

I agree that it makes a lot of sense to reimplement this approach requesting
firmware only once. Will do for v2.

Regards,
Sergey


[PATCH 6/6] qtnfmac: enable networked standby mode on device inactivity

2018-02-05 Thread Sergey Matyukevich
From: Sergei Maksimenko 

Enable support of networked standby mode (NSM) on qsr10g devices.
Networked standby is a power saving mode when the device keeps
all existing network connections and returns to full power mode
on a network activity. When enabled, device enters standby mode
after 15 min of inactivity (no associated stations or no trattic).
This period can be changed by setting sysfs attribute standby_timeout
(0 disables NSM support). A module parameter auto_standby
(defaults to 1) controls enabling NSM support on module loading.

Signed-off-by: Sergei Maksimenko 
---
 drivers/net/wireless/quantenna/qtnfmac/bus.h  |  1 +
 drivers/net/wireless/quantenna/qtnfmac/commands.c | 33 ++
 drivers/net/wireless/quantenna/qtnfmac/commands.h |  1 +
 drivers/net/wireless/quantenna/qtnfmac/core.c | 77 +++
 drivers/net/wireless/quantenna/qtnfmac/core.h |  2 +
 drivers/net/wireless/quantenna/qtnfmac/qlink.h| 30 +
 6 files changed, 144 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h 
b/drivers/net/wireless/quantenna/qtnfmac/bus.h
index 0a1604683bab..7a27ffc6c7a7 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/bus.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h
@@ -65,6 +65,7 @@ struct qtnf_bus {
struct work_struct event_work;
struct mutex bus_lock; /* lock during command/event processing */
struct dentry *dbg_dir;
+   u32 standby_timeout;
/* bus private data */
char bus_priv[0] __aligned(sizeof(void *));
 };
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c 
b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index deca0060eb27..1e730c9fa371 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2753,3 +2753,36 @@ int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
 
return ret;
 }
+
+int qtnf_cmd_send_pm_set(struct qtnf_bus *bus, u8 pm_mode, u32 timeout)
+{
+   struct sk_buff *cmd_skb;
+   u16 res_code = QLINK_CMD_RESULT_OK;
+   struct qlink_cmd_pm_set *cmd;
+   int ret = 0;
+
+   cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
+   QLINK_CMD_PM_SET, sizeof(*cmd));
+   if (!cmd_skb)
+   return -ENOMEM;
+
+   cmd = (struct qlink_cmd_pm_set *)cmd_skb->data;
+   cmd->pm_mode = pm_mode;
+   cmd->pm_standby_timer = cpu_to_le32(timeout);
+
+   qtnf_bus_lock(bus);
+
+   ret = qtnf_cmd_send(bus, cmd_skb, _code);
+
+   if (unlikely(ret))
+   goto out;
+
+   if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+   pr_err("cmd exec failed: 0x%.4X\n", res_code);
+   ret = -EFAULT;
+   }
+
+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 69a7d56f7e58..a06e6a96c35d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -81,5 +81,6 @@ int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
   u32 cac_time_ms);
 int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
 const struct cfg80211_acl_data *params);
+int qtnf_cmd_send_pm_set(struct qtnf_bus *bus, u8 pm_mode, u32 timeout);
 
 #endif /* QLINK_COMMANDS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c 
b/drivers/net/wireless/quantenna/qtnfmac/core.c
index cf26c15a84f8..10c4e3ea2404 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -26,6 +26,10 @@
 #include "event.h"
 #include "util.h"
 
+static bool auto_standby = true;
+module_param(auto_standby, bool, 0644);
+MODULE_PARM_DESC(auto_standby, "set to 0 to disable auto standby mode");
+
 #define QTNF_DMP_MAX_LEN 48
 #define QTNF_PRIMARY_VIF_IDX   0
 
@@ -552,6 +556,53 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, 
unsigned int macid)
return ret;
 }
 
+static ssize_t qtnf_pm_standby_timeout_show(struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(dev);
+
+   sprintf(buf, "%u\n", bus->standby_timeout);
+   return strlen(buf);
+}
+
+static ssize_t qtnf_pm_standby_timeout_store(struct device *dev,
+struct device_attribute *attr,
+const char *buf, size_t count)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(dev);
+   int timeout;
+
+   if (count < 1)
+   goto out;
+
+   if (kstrtoint(buf, 0, ))
+   goto out;
+
+   if (timeout < 0)
+   timeout = 0;
+   else if (timeout > S32_MAX)

[PATCH 4/6] qtnfmac: fix rmmod for missing firmware

2018-02-05 Thread Sergey Matyukevich
Check that firmware exists prior to starting firmware download.

Signed-off-by: Sergey Matyukevich <sergey.matyukevich...@quantenna.com>
---
 drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
index c0d1c5d94ef0..86368e345276 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
@@ -1104,6 +1104,20 @@ static void qtnf_firmware_load(const struct firmware 
*fw, void *context)
complete(>request_firmware_complete);
 }
 
+static int qtnf_fw_exists(struct qtnf_bus *bus)
+{
+   struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+   struct pci_dev *pdev = priv->pdev;
+   const struct firmware *fw;
+   int ret;
+
+   ret = request_firmware(, bus->fwname, >dev);
+   if (!ret)
+   release_firmware(fw);
+
+   return !ret;
+}
+
 static int qtnf_bringup_fw(struct qtnf_bus *bus)
 {
struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
@@ -1358,6 +1372,12 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
netif_napi_add(>mux_dev, >mux_napi,
   qtnf_rx_poll, 10);
 
+   if (!flashboot && !qtnf_fw_exists(bus)) {
+   pr_err("failed to get firmware %s\n", bus->fwname);
+   ret = -ENOENT;
+   goto err_fw;
+   }
+
ret = qtnf_bringup_fw(bus);
if (ret < 0)
goto err_fw;
-- 
2.11.0



[PATCH 5/6] qtnfmac: implement asynchronous firmware loading

2018-02-05 Thread Sergey Matyukevich
From: Sergei Maksimenko 

In pci probe() function start firmware loading, protocol handshake
and driver core initialization, and not wait for completion.

Signed-off-by: Sergei Maksimenko 
---
 drivers/net/wireless/quantenna/qtnfmac/bus.h   |   3 +-
 .../net/wireless/quantenna/qtnfmac/pearl/pcie.c| 326 ++---
 2 files changed, 159 insertions(+), 170 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h 
b/drivers/net/wireless/quantenna/qtnfmac/bus.h
index 56e5fed92a2a..0a1604683bab 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/bus.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h
@@ -59,8 +59,9 @@ struct qtnf_bus {
char fwname[32];
struct napi_struct mux_napi;
struct net_device mux_dev;
-   struct completion request_firmware_complete;
+   struct completion firmware_init_complete;
struct workqueue_struct *workqueue;
+   struct work_struct fw_work;
struct work_struct event_work;
struct mutex bus_lock; /* lock during command/event processing */
struct dentry *dbg_dir;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
index 86368e345276..3be5a79cbca0 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
@@ -954,6 +954,98 @@ static const struct qtnf_bus_ops qtnf_pcie_bus_ops = {
.data_rx_stop   = qtnf_pcie_data_rx_stop,
 };
 
+static int qtnf_dbg_mps_show(struct seq_file *s, void *data)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(s->private);
+   struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+   seq_printf(s, "%d\n", priv->mps);
+
+   return 0;
+}
+
+static int qtnf_dbg_msi_show(struct seq_file *s, void *data)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(s->private);
+   struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+   seq_printf(s, "%u\n", priv->msi_enabled);
+
+   return 0;
+}
+
+static int qtnf_dbg_irq_stats(struct seq_file *s, void *data)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(s->private);
+   struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+   u32 reg = readl(PCIE_HDP_INT_EN(priv->pcie_reg_base));
+   u32 status;
+
+   seq_printf(s, "pcie_irq_count(%u)\n", priv->pcie_irq_count);
+   seq_printf(s, "pcie_irq_tx_count(%u)\n", priv->pcie_irq_tx_count);
+   status = reg &  PCIE_HDP_INT_TX_BITS;
+   seq_printf(s, "pcie_irq_tx_status(%s)\n",
+  (status == PCIE_HDP_INT_TX_BITS) ? "EN" : "DIS");
+   seq_printf(s, "pcie_irq_rx_count(%u)\n", priv->pcie_irq_rx_count);
+   status = reg &  PCIE_HDP_INT_RX_BITS;
+   seq_printf(s, "pcie_irq_rx_status(%s)\n",
+  (status == PCIE_HDP_INT_RX_BITS) ? "EN" : "DIS");
+   seq_printf(s, "pcie_irq_uf_count(%u)\n", priv->pcie_irq_uf_count);
+   status = reg &  PCIE_HDP_INT_HHBM_UF;
+   seq_printf(s, "pcie_irq_hhbm_uf_status(%s)\n",
+  (status == PCIE_HDP_INT_HHBM_UF) ? "EN" : "DIS");
+
+   return 0;
+}
+
+static int qtnf_dbg_hdp_stats(struct seq_file *s, void *data)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(s->private);
+   struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+   seq_printf(s, "tx_full_count(%u)\n", priv->tx_full_count);
+   seq_printf(s, "tx_done_count(%u)\n", priv->tx_done_count);
+   seq_printf(s, "tx_reclaim_done(%u)\n", priv->tx_reclaim_done);
+   seq_printf(s, "tx_reclaim_req(%u)\n", priv->tx_reclaim_req);
+
+   seq_printf(s, "tx_bd_r_index(%u)\n", priv->tx_bd_r_index);
+   seq_printf(s, "tx_bd_p_index(%u)\n",
+  readl(PCIE_HDP_RX0DMA_CNT(priv->pcie_reg_base))
+   & (priv->tx_bd_num - 1));
+   seq_printf(s, "tx_bd_w_index(%u)\n", priv->tx_bd_w_index);
+   seq_printf(s, "tx queue len(%u)\n",
+  CIRC_CNT(priv->tx_bd_w_index, priv->tx_bd_r_index,
+   priv->tx_bd_num));
+
+   seq_printf(s, "rx_bd_r_index(%u)\n", priv->rx_bd_r_index);
+   seq_printf(s, "rx_bd_p_index(%u)\n",
+  readl(PCIE_HDP_TX0DMA_CNT(priv->pcie_reg_base))
+   & (priv->rx_bd_num - 1));
+   seq_printf(s, "rx_bd_w_index(%u)\n", priv->rx_bd_w_index);
+   seq_printf(s, "rx alloc queue len(%u)\n",
+  CIRC_SPACE(priv->rx_bd_w_index, priv->rx_bd_r_index,
+ priv->rx_bd_num));
+
+   return 0;
+}
+
+static int qtnf_dbg_shm_stats(struct seq_file *s, void *data)
+{
+   struct qtnf_bus *bus = dev_get_drvdata(s->private);
+   struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+   seq_printf(s, "shm_ipc_ep_in.tx_packet_count(%zu)\n",
+  priv->shm_ipc_ep_in.tx_packet_count);
+   seq_printf(s, "shm_ipc_ep_in.rx_packet_count(%zu)\n",
+  

  1   2   3   >