2017-08-25 02:30:40

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 00/27] qtnfmac: allow to configure channel, BW, HT/VHT caps

From: Igor Mitsyanko <[email protected]>

This patchset has a goal to make operational parameters (channel, BW,
HT/VHT capabilities) configuration possible for qtnfmac driver.
Basically the idea is to make driver level as thin as possible, and let
everything to be handled by userspace/nl80211 and wireless device itself.


Tested by trying various parameters combinations in hostapd.conf.

Set channel=36, bw=20, HT=0, VHT=0:
hw_mode=a
channel=36
Set channel=36, bw=20, HT=1, VHT=0:
ieee80211n=1
Set channel=36, bw=40 with secondary channel above, HT=1, VHT=0:
ieee80211n=1
ht_capab=[HT40+][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]
Set channel=36, bw=40 with secondary channel below, HT=1, VHT=0:
channel=40
ieee80211n=1
ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]
Set channel=36, bw=40, HT=1, VHT=1:
ieee80211n=1
ht_capab=[HT40+][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]
ieee80211ac=1
vht_capab=[SHORT-GI-80][MAX-MPDU-11454][MAX-A-MPDU-LEN-EXP-7][SU-BEAMFORMER][SU-BEAMFORMEE]
vht_oper_chwidth=0
Set channel=36, bw=80, HT=1, VHT=1:
ieee80211ac=1
vht_capab=[SHORT-GI-80][MAX-MPDU-11454][MAX-A-MPDU-LEN-EXP-7][SU-BEAMFORMER][SU-BEAMFORMEE]
vht_oper_chwidth=1
vht_oper_centr_freq_seg0_idx=42


Igor Mitsyanko (27):
qtnfmac: qlink: convert channel width from bitfiled to simple enum
qtnfmac: make "Channel change" event report full channel info
qtnfmac: retreive current channel info from EP
qtnfmac: do not cache AP settings in driver structures
qtnfmac: pass all AP settings to wireless card for processing
qtnfmac: pass full channel definition to device on start_ap command
qtnfmac: get rid of QTNF_STATE_AP_CONFIG
qtnfmac: get rid of QTNF_STATE_AP_START usage
qtnfmac: do not cache BSS state in per-VIF structure
qtnfmac: do not cache channel info from "connect" command
qtnfmac: make encryption info a part of "connect" command.
qtnfmac: let wifi card handle channel switch request to the same chan
qtnfmac: pass VIF info to SendChannel command
qtnfmac: do not cache CSA chandef info
qtnfmac: remove unused mac::status field
qtnfmac: stop using private driver info about current channel
qtnfmac: do not report channel changes until wiphy is registered
qtnfmac: use per-band HT/VHT info from wireless device
qtnfmac: initialize HT/VHT caps "can override" masks
qtnfmac: get rid of PHYMODE capabilities flags
qtnfmac: extend "IE set" TLV to include frame type info
qtnfmac: SCAN results: retreive frame type information from "IE set"
TLV
qtnfmac: convert "Append IEs" command to QTN_TLV_ID_IE_SET usage
qtnfmac: configure and start AP interface with a single command
nl80211: look for HT/VHT capabilities in beacon's tail
qtnfmac: include HTCAP and VHTCAP into config AP command
qtnfmac: pass all CONNECT cmd params to wireless card for processing

drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 234 ++--------
drivers/net/wireless/quantenna/qtnfmac/commands.c | 470 ++++++++++++++-------
drivers/net/wireless/quantenna/qtnfmac/commands.h | 11 +-
drivers/net/wireless/quantenna/qtnfmac/core.c | 3 +-
drivers/net/wireless/quantenna/qtnfmac/core.h | 35 +-
drivers/net/wireless/quantenna/qtnfmac/event.c | 134 +++---
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 265 ++++++++----
.../net/wireless/quantenna/qtnfmac/qlink_util.c | 113 ++++-
.../net/wireless/quantenna/qtnfmac/qlink_util.h | 7 +
net/wireless/nl80211.c | 4 +-
10 files changed, 709 insertions(+), 567 deletions(-)

--
2.9.5


2017-08-30 12:35:19

by Sergey Matyukevich

[permalink] [raw]
Subject: Re: [PATCH 23/27] qtnfmac: convert "Append IEs" command to QTN_TLV_ID_IE_SET usage

> - if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
> + if (len > QTNF_MAX_CMD_BUF_SIZE) {
> pr_warn("VIF%u.%u: %u frame is too big: %zu\n", vif->mac->macid,
> vif->vifid, frame_type, len);
> return -E2BIG;

It looks like we need the following check here:
sizeof(struct qlink_tlv_ie_set) + len > QTNF_MAX_CMD_BUF_SIZE

2017-08-25 02:30:54

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 08/27] qtnfmac: get rid of QTNF_STATE_AP_START usage

From: Igor Mitsyanko <[email protected]>

QTNF_STATE_AP_START usage is redundant and imposes additional state
synchronization maintenance. We may as well leave state checking up
to network card and upper layers (cfg80211, nl80211 and userspace).

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 29 +----------------------
drivers/net/wireless/quantenna/qtnfmac/commands.c | 3 ---
drivers/net/wireless/quantenna/qtnfmac/core.h | 3 +--
drivers/net/wireless/quantenna/qtnfmac/event.c | 12 ----------
4 files changed, 2 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 26caaf6..999f1bd 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -254,11 +254,6 @@ static int qtnf_change_beacon(struct wiphy *wiphy, struct net_device *dev,
{
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);

- if (!(vif->bss_status & QTNF_STATE_AP_START)) {
- pr_err("VIF%u.%u: not started\n", vif->mac->macid, vif->vifid);
- return -EFAULT;
- }
-
return qtnf_mgmt_set_appie(vif, info);
}

@@ -283,17 +278,9 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev,
}

ret = qtnf_cmd_send_start_ap(vif);
- if (ret) {
+ if (ret)
pr_err("VIF%u.%u: failed to start AP\n", vif->mac->macid,
vif->vifid);
- goto out;
- }
-
- if (!(vif->bss_status & QTNF_STATE_AP_START)) {
- pr_err("VIF%u.%u: FW failed to start AP operation\n",
- vif->mac->macid, vif->vifid);
- ret = -EFAULT;
- }

out:
return ret;
@@ -308,7 +295,6 @@ static int qtnf_stop_ap(struct wiphy *wiphy, struct net_device *dev)
if (ret) {
pr_err("VIF%u.%u: failed to stop AP operation in FW\n",
vif->mac->macid, vif->vifid);
- vif->bss_status &= ~QTNF_STATE_AP_START;

netif_carrier_off(vif->netdev);
}
@@ -797,19 +783,6 @@ static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev,
params->chandef.chan->hw_value, params->count,
params->radar_required, params->block_tx);

- switch (vif->wdev.iftype) {
- case NL80211_IFTYPE_AP:
- if (!(vif->bss_status & QTNF_STATE_AP_START)) {
- pr_warn("AP not started on %s\n", dev->name);
- return -ENOTCONN;
- }
- break;
- default:
- pr_err("unsupported vif type (%d) on %s\n",
- vif->wdev.iftype, dev->name);
- return -EOPNOTSUPP;
- }
-
if (vif->vifid != 0) {
if (!(mac->status & QTNF_MAC_CSA_ACTIVE))
return -EOPNOTSUPP;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 6b4ccf7..cb9632b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -173,7 +173,6 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif)
goto out;
}

- vif->bss_status |= QTNF_STATE_AP_START;
netif_carrier_on(vif->netdev);

out:
@@ -286,8 +285,6 @@ int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif)
goto out;
}

- vif->bss_status &= ~QTNF_STATE_AP_START;
-
netif_carrier_off(vif->netdev);

out:
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 4d3e036..a40295e 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -52,9 +52,8 @@
#define QTNF_DEF_WDOG_TIMEOUT 5
#define QTNF_TX_TIMEOUT_TRSHLD 100

-#define QTNF_STATE_AP_START BIT(1)
-
extern const struct net_device_ops qtnf_netdev_ops;
+
struct qtnf_bus;
struct qtnf_vif;

diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 52e2652..7435986 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -53,12 +53,6 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
return -EPROTO;
}

- if (!(vif->bss_status & QTNF_STATE_AP_START)) {
- pr_err("VIF%u.%u: STA_ASSOC event when AP is not started\n",
- mac->macid, vif->vifid);
- return -EPROTO;
- }
-
sta_addr = sta_assoc->sta_addr;
frame_control = le16_to_cpu(sta_assoc->frame_control);

@@ -127,12 +121,6 @@ qtnf_event_handle_sta_deauth(struct qtnf_wmac *mac, struct qtnf_vif *vif,
return -EPROTO;
}

- if (!(vif->bss_status & QTNF_STATE_AP_START)) {
- pr_err("VIF%u.%u: STA_DEAUTH event when AP is not started\n",
- mac->macid, vif->vifid);
- return -EPROTO;
- }
-
sta_addr = sta_deauth->sta_addr;
reason = le16_to_cpu(sta_deauth->reason);

--
2.9.5

2017-08-30 16:16:43

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 00/27] qtnfmac: allow to configure channel, BW, HT/VHT caps

[email protected] writes:

> This patchset has a goal to make operational parameters (channel, BW,
> HT/VHT capabilities) configuration possible for qtnfmac driver.
> Basically the idea is to make driver level as thin as possible, and let
> everything to be handled by userspace/nl80211 and wireless device itself.

This patchset is just too big and pain to review. Preferably no more
than 10-12 patches per set, please. If the patches bigger then the limit
should be even lower.

--
Kalle Valo

2017-08-30 16:22:42

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 00/27] qtnfmac: allow to configure channel, BW, HT/VHT caps

Kalle Valo <[email protected]> writes:

> [email protected] writes:
>
>> This patchset has a goal to make operational parameters (channel, BW,
>> HT/VHT capabilities) configuration possible for qtnfmac driver.
>> Basically the idea is to make driver level as thin as possible, and let
>> everything to be handled by userspace/nl80211 and wireless device itself.
>
> This patchset is just too big and pain to review. Preferably no more
> than 10-12 patches per set, please. If the patches bigger then the limit
> should be even lower.

And I noticed that patch 25 didn't make it to patchwork:

https://patchwork.kernel.org/project/linux-wireless/list/?state=*&q=qtnfmac

--
Kalle Valo

2017-08-25 02:31:10

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 24/27] qtnfmac: configure and start AP interface with a single command

From: Igor Mitsyanko <[email protected]>

Current logic artificially divides "start AP" procedure into three
stages:
- generic interface configuration (security, channel etc)
- IE's processing
- enable AP mode on interface

This separation would not allow to do a proper device configuration as
first stage needs to use information from IEs that are processed on
a second stage. Which means first and second stages have to be meged.
In that case there is no point anymore to keep third stage either, so
merge all three into a single command.

This new command carries all the same info as contained in
"struct cfg80211_ap_settings".

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 17 +-----
drivers/net/wireless/quantenna/qtnfmac/commands.c | 72 +++++++++++++----------
drivers/net/wireless/quantenna/qtnfmac/commands.h | 5 +-
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 5 +-
4 files changed, 47 insertions(+), 52 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 2497493..d6ddb4d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -266,26 +266,11 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev,
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
int ret;

- ret = qtnf_cmd_send_config_ap(vif, settings);
- if (ret) {
- pr_err("VIF%u.%u: failed to push config to FW\n",
- vif->mac->macid, vif->vifid);
- goto out;
- }
-
- ret = qtnf_mgmt_set_appie(vif, &settings->beacon);
- if (ret) {
- pr_err("VIF%u.%u: failed to add IEs to beacon\n",
- vif->mac->macid, vif->vifid);
- goto out;
- }
-
- ret = qtnf_cmd_send_start_ap(vif);
+ ret = qtnf_cmd_send_start_ap(vif, settings);
if (ret)
pr_err("VIF%u.%u: failed to start AP\n", vif->mac->macid,
vif->vifid);

-out:
return ret;
}

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 2e30c26..1965061 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -162,56 +162,51 @@ static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type,
memcpy(tlv->ie_data, buf, len);
}

-int qtnf_cmd_send_start_ap(struct qtnf_vif *vif)
+static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif,
+ const struct cfg80211_ap_settings *s)
{
- struct sk_buff *cmd_skb;
- u16 res_code = QLINK_CMD_RESULT_OK;
- int ret;
+ unsigned int len = sizeof(struct qlink_cmd_start_ap);

- cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
- QLINK_CMD_START_AP,
- sizeof(struct qlink_cmd));
- if (unlikely(!cmd_skb))
- return -ENOMEM;
+ len += s->ssid_len;
+ len += s->beacon.head_len;
+ len += s->beacon.tail_len;
+ len += s->beacon.beacon_ies_len;
+ len += s->beacon.proberesp_ies_len;
+ len += s->beacon.assocresp_ies_len;
+ len += s->beacon.probe_resp_len;

- qtnf_bus_lock(vif->mac->bus);
-
- ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+ if (cfg80211_chandef_valid(&s->chandef))
+ len += sizeof(struct qlink_tlv_chandef);

- if (unlikely(ret))
- goto out;
-
- if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
- pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
- vif->vifid, res_code);
- ret = -EFAULT;
- goto out;
+ if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) {
+ pr_err("VIF%u.%u: can not fit AP settings: %u\n",
+ vif->mac->macid, vif->vifid, len);
+ return false;
}

- netif_carrier_on(vif->netdev);
-
-out:
- qtnf_bus_unlock(vif->mac->bus);
- return ret;
+ return true;
}

-int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
- const struct cfg80211_ap_settings *s)
+int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
+ const struct cfg80211_ap_settings *s)
{
struct sk_buff *cmd_skb;
- struct qlink_cmd_config_ap *cmd;
+ struct qlink_cmd_start_ap *cmd;
struct qlink_auth_encr *aen;
u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
int i;

+ if (!qtnf_cmd_start_ap_can_fit(vif, s))
+ return -E2BIG;
+
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
- QLINK_CMD_CONFIG_AP,
+ QLINK_CMD_START_AP,
sizeof(*cmd));
if (unlikely(!cmd_skb))
return -ENOMEM;

- cmd = (struct qlink_cmd_config_ap *)cmd_skb->data;
+ cmd = (struct qlink_cmd_start_ap *)cmd_skb->data;
cmd->dtim_period = s->dtim_period;
cmd->beacon_interval = cpu_to_le16(s->beacon_interval);
cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid);
@@ -255,6 +250,21 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
qlink_chandef_cfg2q(&s->chandef, &chtlv->chan);
}

+ qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_HEAD,
+ s->beacon.head, s->beacon.head_len);
+ qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_TAIL,
+ s->beacon.tail, s->beacon.tail_len);
+ qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_IES,
+ s->beacon.beacon_ies, s->beacon.beacon_ies_len);
+ qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP,
+ s->beacon.probe_resp, s->beacon.probe_resp_len);
+ qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP_IES,
+ s->beacon.proberesp_ies,
+ s->beacon.proberesp_ies_len);
+ qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_RESP,
+ s->beacon.assocresp_ies,
+ s->beacon.assocresp_ies_len);
+
qtnf_bus_lock(vif->mac->bus);

ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
@@ -269,6 +279,8 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
goto out;
}

+ netif_carrier_on(vif->netdev);
+
out:
qtnf_bus_unlock(vif->mac->bus);
return ret;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index d6fe3cc..d981a76 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -33,9 +33,8 @@ int qtnf_cmd_send_del_intf(struct qtnf_vif *vif);
int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
struct ieee80211_supported_band *band);
int qtnf_cmd_send_regulatory_config(struct qtnf_wmac *mac, const char *alpha2);
-int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
- const struct cfg80211_ap_settings *s);
-int qtnf_cmd_send_start_ap(struct qtnf_vif *vif);
+int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
+ const struct cfg80211_ap_settings *s);
int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif);
int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg);
int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index eba73fd..9a913b6 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -183,7 +183,6 @@ enum qlink_cmd_type {
QLINK_CMD_BAND_INFO_GET = 0x001A,
QLINK_CMD_CHAN_SWITCH = 0x001B,
QLINK_CMD_CHAN_GET = 0x001C,
- QLINK_CMD_CONFIG_AP = 0x0020,
QLINK_CMD_START_AP = 0x0021,
QLINK_CMD_STOP_AP = 0x0022,
QLINK_CMD_GET_STA_INFO = 0x0030,
@@ -533,7 +532,7 @@ enum qlink_hidden_ssid {
};

/**
- * struct qlink_cmd_config_ap - data for QLINK_CMD_CONFIG_AP command
+ * struct qlink_cmd_start_ap - data for QLINK_CMD_START_AP command
*
* @beacon_interval: beacon interval
* @inactivity_timeout: station's inactivity period in seconds
@@ -545,7 +544,7 @@ enum qlink_hidden_ssid {
* @aen: encryption info
* @info: variable configurations
*/
-struct qlink_cmd_config_ap {
+struct qlink_cmd_start_ap {
struct qlink_cmd chdr;
__le16 beacon_interval;
__le16 inactivity_timeout;
--
2.9.5

2017-08-29 14:42:17

by Sergey Matyukevich

[permalink] [raw]
Subject: Re: [PATCH 03/27] qtnfmac: retreive current channel info from EP


Typo in commit title: retrieve

...

> - if (!cfg80211_chandef_valid(&mac->chandef)) {
> - pr_err("invalid channel settings on %s\n", ndev->name);
> - return -ENODATA;
> + if (!cfg80211_chandef_valid(chandef)) {
> + pr_err("%s: bad chan freq1=%u bw=%u\n", ndev->name,
> + chandef->center_freq1, chandef->width);
> + ret = -ENODATA;
> }

Lets keep both center_freq1 and center_freq2 in error message.

Regards,
Sergey

2017-08-25 02:30:58

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 13/27] qtnfmac: pass VIF info to SendChannel command

From: Igor Mitsyanko <[email protected]>

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 2 +-
drivers/net/wireless/quantenna/qtnfmac/commands.c | 5 +++--
drivers/net/wireless/quantenna/qtnfmac/commands.h | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 062189b..b33c4fc 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -760,7 +760,7 @@ static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev,
return -EINVAL;
}

- ret = qtnf_cmd_send_chan_switch(mac, params);
+ ret = qtnf_cmd_send_chan_switch(vif, params);
if (ret)
pr_warn("%s: failed to switch to channel (%u)\n",
dev->name, params->chandef.chan->hw_value);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 195b777..cfbb636 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2316,15 +2316,16 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
return ret;
}

-int qtnf_cmd_send_chan_switch(struct qtnf_wmac *mac,
+int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
struct cfg80211_csa_settings *params)
{
+ struct qtnf_wmac *mac = vif->mac;
struct qlink_cmd_chan_switch *cmd;
struct sk_buff *cmd_skb;
u16 res_code = QLINK_CMD_RESULT_OK;
int ret;

- cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0x0,
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid,
QLINK_CMD_CHAN_SWITCH,
sizeof(*cmd));

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index 634b057..e87c4a4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -74,7 +74,7 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif,
int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req);
int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
struct qtnf_chan_stats *stats);
-int qtnf_cmd_send_chan_switch(struct qtnf_wmac *mac,
+int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
struct cfg80211_csa_settings *params);
int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef);

--
2.9.5

2017-08-30 14:02:23

by Sergey Matyukevich

[permalink] [raw]
Subject: Re: [PATCH 06/27] qtnfmac: pass full channel definition to device on start_ap command

> + if (s->ssid && s->ssid_len > 0 && s->ssid_len <= IEEE80211_MAX_SSID_LEN)
> + qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, s->ssid,
> + s->ssid_len);
> +
> + if (cfg80211_chandef_valid(&s->chandef)) {
> + struct qlink_tlv_chandef *chtlv =
> + (struct qlink_tlv_chandef *)skb_put(cmd_skb,
> + sizeof(*chtlv));
> +
> + chtlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANDEF);
> + chtlv->hdr.len = sizeof(*chtlv) - sizeof(chtlv->hdr);

It looks like cpu_to_le16 is needed here as well.

> + qlink_chandef_cfg2q(&s->chandef, &chtlv->chan);
> + }
> +

2017-08-25 02:30:53

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 07/27] qtnfmac: get rid of QTNF_STATE_AP_CONFIG

From: Igor Mitsyanko <[email protected]>

QTNF_STATE_AP_CONFIG is redundant and has no real meaning.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 8 --------
drivers/net/wireless/quantenna/qtnfmac/commands.c | 3 ---
drivers/net/wireless/quantenna/qtnfmac/core.h | 1 -
3 files changed, 12 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 858c24f..26caaf6 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -275,13 +275,6 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev,
goto out;
}

- if (!(vif->bss_status & QTNF_STATE_AP_CONFIG)) {
- pr_err("VIF%u.%u: AP config failed in FW\n", vif->mac->macid,
- vif->vifid);
- ret = -EFAULT;
- goto out;
- }
-
ret = qtnf_mgmt_set_appie(vif, &settings->beacon);
if (ret) {
pr_err("VIF%u.%u: failed to add IEs to beacon\n",
@@ -316,7 +309,6 @@ static int qtnf_stop_ap(struct wiphy *wiphy, struct net_device *dev)
pr_err("VIF%u.%u: failed to stop AP operation in FW\n",
vif->mac->macid, vif->vifid);
vif->bss_status &= ~QTNF_STATE_AP_START;
- vif->bss_status &= ~QTNF_STATE_AP_CONFIG;

netif_carrier_off(vif->netdev);
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 7b24d37..6b4ccf7 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -255,8 +255,6 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
goto out;
}

- vif->bss_status |= QTNF_STATE_AP_CONFIG;
-
out:
qtnf_bus_unlock(vif->mac->bus);
return ret;
@@ -289,7 +287,6 @@ int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif)
}

vif->bss_status &= ~QTNF_STATE_AP_START;
- vif->bss_status &= ~QTNF_STATE_AP_CONFIG;

netif_carrier_off(vif->netdev);

diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 066fcd1..4d3e036 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -52,7 +52,6 @@
#define QTNF_DEF_WDOG_TIMEOUT 5
#define QTNF_TX_TIMEOUT_TRSHLD 100

-#define QTNF_STATE_AP_CONFIG BIT(2)
#define QTNF_STATE_AP_START BIT(1)

extern const struct net_device_ops qtnf_netdev_ops;
--
2.9.5

2017-08-25 02:30:46

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 01/27] qtnfmac: qlink: convert channel width from bitfiled to simple enum

From: Igor Mitsyanko <[email protected]>

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 16 ++++++++--------
drivers/net/wireless/quantenna/qtnfmac/qlink_util.c | 16 ++++++++--------
2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index a8242f6..a69fd470 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -108,14 +108,14 @@ enum qlink_sta_flags {
};

enum qlink_channel_width {
- QLINK_CHAN_WIDTH_5 = BIT(0),
- QLINK_CHAN_WIDTH_10 = BIT(1),
- QLINK_CHAN_WIDTH_20_NOHT = BIT(2),
- QLINK_CHAN_WIDTH_20 = BIT(3),
- QLINK_CHAN_WIDTH_40 = BIT(4),
- QLINK_CHAN_WIDTH_80 = BIT(5),
- QLINK_CHAN_WIDTH_80P80 = BIT(6),
- QLINK_CHAN_WIDTH_160 = BIT(7),
+ QLINK_CHAN_WIDTH_5 = 0,
+ QLINK_CHAN_WIDTH_10,
+ QLINK_CHAN_WIDTH_20_NOHT,
+ QLINK_CHAN_WIDTH_20,
+ QLINK_CHAN_WIDTH_40,
+ QLINK_CHAN_WIDTH_80,
+ QLINK_CHAN_WIDTH_80P80,
+ QLINK_CHAN_WIDTH_160,
};

/* QLINK Command messages related definitions
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
index cf024c9..369b77d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
@@ -49,28 +49,28 @@ u8 qlink_chan_width_mask_to_nl(u16 qlink_mask)
{
u8 result = 0;

- if (qlink_mask & QLINK_CHAN_WIDTH_5)
+ if (qlink_mask & BIT(QLINK_CHAN_WIDTH_5))
result |= BIT(NL80211_CHAN_WIDTH_5);

- if (qlink_mask & QLINK_CHAN_WIDTH_10)
+ if (qlink_mask & BIT(QLINK_CHAN_WIDTH_10))
result |= BIT(NL80211_CHAN_WIDTH_10);

- if (qlink_mask & QLINK_CHAN_WIDTH_20_NOHT)
+ if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20_NOHT))
result |= BIT(NL80211_CHAN_WIDTH_20_NOHT);

- if (qlink_mask & QLINK_CHAN_WIDTH_20)
+ if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20))
result |= BIT(NL80211_CHAN_WIDTH_20);

- if (qlink_mask & QLINK_CHAN_WIDTH_40)
+ if (qlink_mask & BIT(QLINK_CHAN_WIDTH_40))
result |= BIT(NL80211_CHAN_WIDTH_40);

- if (qlink_mask & QLINK_CHAN_WIDTH_80)
+ if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80))
result |= BIT(NL80211_CHAN_WIDTH_80);

- if (qlink_mask & QLINK_CHAN_WIDTH_80P80)
+ if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80P80))
result |= BIT(NL80211_CHAN_WIDTH_80P80);

- if (qlink_mask & QLINK_CHAN_WIDTH_160)
+ if (qlink_mask & BIT(QLINK_CHAN_WIDTH_160))
result |= BIT(NL80211_CHAN_WIDTH_160);

return result;
--
2.9.5

2017-08-30 01:39:16

by Igor Mitsyanko

[permalink] [raw]
Subject: Re: [PATCH 03/27] qtnfmac: retreive current channel info from EP

On 08/29/2017 07:42 AM, Sergey Matyukevich wrote:
>
> Typo in commit title: retrieve

will fix

>
> ...
>
>> - if (!cfg80211_chandef_valid(&mac->chandef)) {
>> - pr_err("invalid channel settings on %s\n", ndev->name);
>> - return -ENODATA;
>> + if (!cfg80211_chandef_valid(chandef)) {
>> + pr_err("%s: bad chan freq1=%u bw=%u\n", ndev->name,
>> + chandef->center_freq1, chandef->width);
>> + ret = -ENODATA;
>> }
>
> Lets keep both center_freq1 and center_freq2 in error message.

Ok


>
> Regards,
> Sergey
>

2017-08-29 15:47:33

by Sergey Matyukevich

[permalink] [raw]
Subject: Re: [PATCH 15/27] qtnfmac: remove unused mac::status field

On Thu, Aug 24, 2017 at 07:30:12PM -0700, [email protected] wrote:
> From: Igor Mitsyanko <[email protected]>
>
> It is no longer used.

If we come to the agreement on the previous patch,
then this field should be kept.

Regards,
Sergey

2017-08-25 02:31:08

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 22/27] qtnfmac: SCAN results: retreive frame type information from "IE set" TLV

From: Igor Mitsyanko <[email protected]>

"IE set" TLV carries the same information as
qlink_event_scan_result::frame_type. Convert the event to make use of
TLV and drop frame_type member.
While at it, make qlink_event_scan_result structure alignement-safe.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/event.c | 25 ++++++++++++-------------
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 11 ++---------
2 files changed, 14 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index c2452dc..5fb0ead 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -252,13 +252,12 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif,
struct cfg80211_bss *bss;
struct ieee80211_channel *channel;
struct wiphy *wiphy = priv_to_wiphy(vif->mac);
- enum cfg80211_bss_frame_type frame_type;
+ enum cfg80211_bss_frame_type frame_type = CFG80211_BSS_FTYPE_UNKNOWN;
size_t payload_len;
u16 tlv_type;
u16 tlv_value_len;
size_t tlv_full_len;
const struct qlink_tlv_hdr *tlv;
-
const u8 *ies = NULL;
size_t ies_len = 0;

@@ -275,17 +274,6 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif,
return -EINVAL;
}

- switch (sr->frame_type) {
- case QLINK_BSS_FTYPE_BEACON:
- frame_type = CFG80211_BSS_FTYPE_BEACON;
- break;
- case QLINK_BSS_FTYPE_PRESP:
- frame_type = CFG80211_BSS_FTYPE_PRESP;
- break;
- default:
- frame_type = CFG80211_BSS_FTYPE_UNKNOWN;
- }
-
payload_len = len - sizeof(*sr);
tlv = (struct qlink_tlv_hdr *)sr->payload;

@@ -308,6 +296,17 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif,
ie_len = tlv_value_len -
(sizeof(*ie_set) - sizeof(ie_set->hdr));

+ switch (ie_set->type) {
+ case QLINK_IE_SET_BEACON_IES:
+ frame_type = CFG80211_BSS_FTYPE_BEACON;
+ break;
+ case QLINK_IE_SET_PROBE_RESP_IES:
+ frame_type = CFG80211_BSS_FTYPE_PRESP;
+ break;
+ default:
+ frame_type = CFG80211_BSS_FTYPE_UNKNOWN;
+ }
+
if (ie_len) {
ies = ie_set->ie_data;
ies_len = ie_len;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index ecf493d..e584d2e 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -872,12 +872,6 @@ struct qlink_event_rxmgmt {
u8 frame_data[0];
} __packed;

-enum qlink_frame_type {
- QLINK_BSS_FTYPE_UNKNOWN,
- QLINK_BSS_FTYPE_BEACON,
- QLINK_BSS_FTYPE_PRESP,
-};
-
/**
* struct qlink_event_scan_result - data for QLINK_EVENT_SCAN_RESULTS event
*
@@ -887,7 +881,6 @@ enum qlink_frame_type {
* @capab: capabilities field.
* @bintval: beacon interval announced by discovered BSS.
* @signal: signal strength.
- * @frame_type: frame type used to get scan result, see &enum qlink_frame_type.
* @bssid: BSSID announced by discovered BSS.
* @ssid_len: length of SSID announced by BSS.
* @ssid: SSID announced by discovered BSS.
@@ -900,10 +893,10 @@ struct qlink_event_scan_result {
__le16 capab;
__le16 bintval;
s8 signal;
- u8 frame_type;
- u8 bssid[ETH_ALEN];
u8 ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u8 bssid[ETH_ALEN];
+ u8 rsvd[2];
u8 payload[0];
} __packed;

--
2.9.5

2017-08-30 18:20:15

by Igor Mitsyanko

[permalink] [raw]
Subject: Re: [PATCH 00/27] qtnfmac: allow to configure channel, BW, HT/VHT caps

On 08/30/2017 09:16 AM, Kalle Valo wrote:
>
> [email protected] writes:
>
>> This patchset has a goal to make operational parameters (channel, BW,
>> HT/VHT capabilities) configuration possible for qtnfmac driver.
>> Basically the idea is to make driver level as thin as possible, and let
>> everything to be handled by userspace/nl80211 and wireless device itself.
>
> This patchset is just too big and pain to review. Preferably no more
> than 10-12 patches per set, please. If the patches bigger then the limit
> should be even lower.

Sure, will split in 3 patchsets then.

>
> --
> Kalle Valo
>

2017-08-25 02:31:03

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 17/27] qtnfmac: do not report channel changes until wiphy is registered

From: Igor Mitsyanko <[email protected]>

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/event.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 9befc9f..b2f6410 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -356,6 +356,9 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
return -EINVAL;
}

+ if (!wiphy->registered)
+ return 0;
+
qlink_chandef_q2cfg(wiphy, &data->chan, &chdef);

if (!cfg80211_chandef_valid(&chdef)) {
--
2.9.5

2017-08-29 15:45:16

by Sergey Matyukevich

[permalink] [raw]
Subject: Re: [PATCH 14/27] qtnfmac: do not cache CSA chandef info

I am ok with removal of CSA chandef info. It was kept mainly to warn
about channel switch to the frequency that differs from original
CSA request.

> - if (vif->vifid != 0) {
> - if (!(mac->status & QTNF_MAC_CSA_ACTIVE))
> - return -EOPNOTSUPP;
> -
> - if (!cfg80211_chandef_identical(&params->chandef,
> - &mac->csa_chandef))
> - return -EINVAL;
> -
> - return 0;
> - }


This particular CSA_ACTIVE status check was introduced for compatibility with
hostapd behaviour. Currently hostapd goes through all the virtual interfaces
and sends CSA for each of them. So the idea was to send CSA for primary
interface and confirm success for the others. If this snipped is dropped
then we end up in multiple identical CSA requests queued in firmware.

I suggest to remove chandef_identical check, but to keep the logic for
secondary virtual interface handling.

Regards,
Sergey

2017-08-30 18:22:24

by Igor Mitsyanko

[permalink] [raw]
Subject: Re: [PATCH 00/27] qtnfmac: allow to configure channel, BW, HT/VHT caps

On 08/30/2017 09:28 AM, Kalle Valo wrote:
>
> External Email
>
>
> Kalle Valo <[email protected]> writes:
>
>> Kalle Valo <[email protected]> writes:
>>
>>> [email protected] writes:
>>>
>>>> This patchset has a goal to make operational parameters (channel, BW,
>>>> HT/VHT capabilities) configuration possible for qtnfmac driver.
>>>> Basically the idea is to make driver level as thin as possible, and let
>>>> everything to be handled by userspace/nl80211 and wireless device itself.
>>>
>>> This patchset is just too big and pain to review. Preferably no more
>>> than 10-12 patches per set, please. If the patches bigger then the limit
>>> should be even lower.
>>
>> And I noticed that patch 25 didn't make it to patchwork:
>>
>> https://patchwork.kernel.org/project/linux-wireless/list/?state=*&q=qtnfmac
>
> Actually it did but it was an nl80211 patch:
>
> https://patchwork.kernel.org/patch/9921179/
>
> Never ever hide mac80211 or cfg80211 patches within driver patches like
> this. They need to be submitted separately so that everyone sees them.
>
> In some cases it makes sense to submit the driver patches using the new
> cfg80211/mac80211 feature at the same, but then do it so that you have
> the cfg80211/mac80211 patches and the corresponding driver patches as
> last. In that case I assign the whole patchset first to Johannes and
> once he has applied the cfg80211/mac80211 patches he assigns the driver
> patches to me.

Ok, understood.

>
> --
> Kalle Valo
>

2017-08-25 02:30:48

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 03/27] qtnfmac: retreive current channel info from EP

From: Igor Mitsyanko <[email protected]>

Do not try to cache current operational channel info in driver, this
is a potential source of synchronization issues + driver does not
really need that info.

Introduce GET_CHANNEL command and process it appropriately.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 34 ++++++++------------
drivers/net/wireless/quantenna/qtnfmac/commands.c | 38 +++++++++++++++++++++++
drivers/net/wireless/quantenna/qtnfmac/commands.h | 1 +
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 11 +++++++
4 files changed, 63 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 856fa6e..8bfe61d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -793,37 +793,29 @@ qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
struct qtnf_wmac *mac = wiphy_priv(wiphy);
struct net_device *ndev = wdev->netdev;
struct qtnf_vif *vif;
+ int ret;

if (!ndev)
return -ENODEV;

vif = qtnf_netdev_get_priv(wdev->netdev);

- switch (vif->wdev.iftype) {
- case NL80211_IFTYPE_STATION:
- if (vif->sta_state == QTNF_STA_DISCONNECTED) {
- pr_warn("%s: STA disconnected\n", ndev->name);
- return -ENODATA;
- }
- break;
- case NL80211_IFTYPE_AP:
- if (!(vif->bss_status & QTNF_STATE_AP_START)) {
- pr_warn("%s: AP not started\n", ndev->name);
- return -ENODATA;
- }
- break;
- default:
- pr_err("unsupported vif type (%d)\n", vif->wdev.iftype);
- return -ENODATA;
+ ret = qtnf_cmd_get_channel(vif, chandef);
+ if (ret) {
+ pr_err("%s: failed to get channel: %d\n", ndev->name, ret);
+ goto out;
}

- if (!cfg80211_chandef_valid(&mac->chandef)) {
- pr_err("invalid channel settings on %s\n", ndev->name);
- return -ENODATA;
+ if (!cfg80211_chandef_valid(chandef)) {
+ pr_err("%s: bad chan freq1=%u bw=%u\n", ndev->name,
+ chandef->center_freq1, chandef->width);
+ ret = -ENODATA;
}

- memcpy(chandef, &mac->chandef, sizeof(*chandef));
- return 0;
+ memcpy(&mac->chandef, chandef, sizeof(mac->chandef));
+
+out:
+ return ret;
}

static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 4206886..806b88b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2358,3 +2358,41 @@ int qtnf_cmd_send_chan_switch(struct qtnf_wmac *mac,
qtnf_bus_unlock(mac->bus);
return ret;
}
+
+int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef)
+{
+ struct qtnf_bus *bus = vif->mac->bus;
+ const struct qlink_resp_channel_get *resp;
+ struct sk_buff *cmd_skb;
+ struct sk_buff *resp_skb = NULL;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_CHAN_GET,
+ sizeof(struct qlink_cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(bus);
+
+ ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, &res_code,
+ sizeof(*resp), NULL);
+
+ qtnf_bus_unlock(bus);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ ret = -ENODATA;
+ goto out;
+ }
+
+ resp = (const struct qlink_resp_channel_get *)resp_skb->data;
+ qlink_chandef_q2cfg(priv_to_wiphy(vif->mac), &resp->chan, chdef);
+
+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 783b203..e1bcb83 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -75,5 +75,6 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
struct qtnf_chan_stats *stats);
int qtnf_cmd_send_chan_switch(struct qtnf_wmac *mac,
struct cfg80211_csa_settings *params);
+int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef);

#endif /* QLINK_COMMANDS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 5936854..fb88f3e 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -169,6 +169,7 @@ enum qlink_cmd_type {
QLINK_CMD_REG_NOTIFY = 0x0019,
QLINK_CMD_CHANS_INFO_GET = 0x001A,
QLINK_CMD_CHAN_SWITCH = 0x001B,
+ QLINK_CMD_CHAN_GET = 0x001C,
QLINK_CMD_CONFIG_AP = 0x0020,
QLINK_CMD_START_AP = 0x0021,
QLINK_CMD_STOP_AP = 0x0022,
@@ -694,6 +695,16 @@ struct qlink_resp_get_chan_stats {
u8 info[0];
} __packed;

+/**
+ * struct qlink_resp_channel_get - response for QLINK_CMD_CHAN_GET command
+ *
+ * @chan: definition of current operating channel.
+ */
+struct qlink_resp_channel_get {
+ struct qlink_resp rhdr;
+ struct qlink_chandef chan;
+} __packed;
+
/* QLINK Events messages related definitions
*/

--
2.9.5

2017-08-25 02:31:07

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 21/27] qtnfmac: extend "IE set" TLV to include frame type info

From: Igor Mitsyanko <[email protected]>

Specifying frame type for "IE set" TLV will allow to use several
TLVs in a single message.
Modify users accordingly.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/commands.c | 25 +++++++---
drivers/net/wireless/quantenna/qtnfmac/event.c | 58 +++++++++++++----------
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 27 +++++++++++
3 files changed, 80 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 79a3e75..cc37114 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -147,6 +147,21 @@ static struct sk_buff *qtnf_cmd_alloc_new_cmdskb(u8 macid, u8 vifid, u16 cmd_no,
return cmd_skb;
}

+static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type,
+ const u8 *buf, size_t len)
+{
+ struct qlink_tlv_ie_set *tlv;
+
+ tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + len);
+ tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_IE_SET);
+ tlv->hdr.len = cpu_to_le16(len + sizeof(*tlv) - sizeof(tlv->hdr));
+ tlv->type = frame_type;
+ tlv->flags = 0;
+
+ if (len && buf)
+ memcpy(tlv->ie_data, buf, len);
+}
+
int qtnf_cmd_send_start_ap(struct qtnf_vif *vif)
{
struct sk_buff *cmd_skb;
@@ -2026,9 +2041,8 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
}

if (scan_req->ie_len != 0)
- qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET,
- scan_req->ie,
- scan_req->ie_len);
+ qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ,
+ scan_req->ie, scan_req->ie_len);

if (scan_req->n_channels) {
n_channels = scan_req->n_channels;
@@ -2152,9 +2166,8 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
sme->ssid_len);

if (sme->ie_len != 0)
- qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET,
- sme->ie,
- sme->ie_len);
+ qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_REQ,
+ sme->ie, sme->ie_len);

qtnf_bus_lock(vif->mac->bus);

diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index b2f6410..c2452dc 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -65,34 +65,39 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
sinfo.assoc_req_ies_len = 0;

payload_len = len - sizeof(*sta_assoc);
- tlv = (struct qlink_tlv_hdr *)sta_assoc->ies;
+ tlv = (const struct qlink_tlv_hdr *)sta_assoc->ies;

- while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
+ while (payload_len >= sizeof(*tlv)) {
tlv_type = le16_to_cpu(tlv->type);
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) {
- pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n",
- mac->macid, vif->vifid, tlv_type,
- tlv_value_len);
+ if (tlv_full_len > payload_len)
return -EINVAL;
- }

if (tlv_type == QTN_TLV_ID_IE_SET) {
- sinfo.assoc_req_ies = tlv->val;
- sinfo.assoc_req_ies_len = tlv_value_len;
+ const struct qlink_tlv_ie_set *ie_set;
+ unsigned int ie_len;
+
+ if (payload_len < sizeof(*ie_set))
+ return -EINVAL;
+
+ ie_set = (const struct qlink_tlv_ie_set *)tlv;
+ ie_len = tlv_value_len -
+ (sizeof(*ie_set) - sizeof(ie_set->hdr));
+
+ if (ie_set->type == QLINK_IE_SET_ASSOC_REQ && ie_len) {
+ sinfo.assoc_req_ies = ie_set->ie_data;
+ sinfo.assoc_req_ies_len = ie_len;
+ }
}

payload_len -= tlv_full_len;
tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
}

- if (payload_len) {
- pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n",
- mac->macid, vif->vifid, payload_len);
+ if (payload_len)
return -EINVAL;
- }

cfg80211_new_sta(vif->netdev, sta_assoc->sta_addr, &sinfo,
GFP_KERNEL);
@@ -289,27 +294,32 @@ qtnf_event_handle_scan_results(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) {
- pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n",
- vif->mac->macid, vif->vifid, tlv_type,
- tlv_value_len);
+ if (tlv_full_len > payload_len)
return -EINVAL;
- }

if (tlv_type == QTN_TLV_ID_IE_SET) {
- ies = tlv->val;
- ies_len = tlv_value_len;
+ const struct qlink_tlv_ie_set *ie_set;
+ unsigned int ie_len;
+
+ if (payload_len < sizeof(*ie_set))
+ return -EINVAL;
+
+ ie_set = (const struct qlink_tlv_ie_set *)tlv;
+ ie_len = tlv_value_len -
+ (sizeof(*ie_set) - sizeof(ie_set->hdr));
+
+ if (ie_len) {
+ ies = ie_set->ie_data;
+ ies_len = ie_len;
+ }
}

payload_len -= tlv_full_len;
tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
}

- if (payload_len) {
- pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n",
- vif->mac->macid, vif->vifid, payload_len);
+ if (payload_len)
return -EINVAL;
- }

bss = cfg80211_inform_bss(wiphy, channel, frame_type,
sr->bssid, get_unaligned_le64(&sr->tsf),
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index e4d3e7f..ecf493d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -1138,6 +1138,33 @@ struct qlink_tlv_chandef {
struct qlink_chandef chan;
} __packed;

+enum qlink_ie_set_type {
+ QLINK_IE_SET_UNKNOWN,
+ QLINK_IE_SET_ASSOC_REQ,
+ QLINK_IE_SET_ASSOC_RESP,
+ QLINK_IE_SET_PROBE_REQ,
+ QLINK_IE_SET_SCAN,
+ QLINK_IE_SET_BEACON_HEAD,
+ QLINK_IE_SET_BEACON_TAIL,
+ QLINK_IE_SET_BEACON_IES,
+ QLINK_IE_SET_PROBE_RESP,
+ QLINK_IE_SET_PROBE_RESP_IES,
+};
+
+/**
+ * struct qlink_tlv_ie_set - data for QTN_TLV_ID_IE_SET
+ *
+ * @type: type of MGMT frame IEs belong to, one of &enum qlink_ie_set_type.
+ * @flags: for future use.
+ * @ie_data: IEs data.
+ */
+struct qlink_tlv_ie_set {
+ struct qlink_tlv_hdr hdr;
+ u8 type;
+ u8 flags;
+ u8 ie_data[0];
+} __packed;
+
struct qlink_chan_stats {
__le32 chan_num;
__le32 cca_tx;
--
2.9.5

2017-08-25 02:30:52

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 06/27] qtnfmac: pass full channel definition to device on start_ap command

From: Igor Mitsyanko <[email protected]>

Introduce chandef TLV and pass it to wireless card on start_ap
command processing.
No need to cache chandef in driver private structure as it is
not used anywhere.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 9 ------
drivers/net/wireless/quantenna/qtnfmac/commands.c | 27 +++++++++---------
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 13 +++++++++
.../net/wireless/quantenna/qtnfmac/qlink_util.c | 32 ++++++++++++++++++++++
.../net/wireless/quantenna/qtnfmac/qlink_util.h | 2 ++
5 files changed, 61 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index f6eb681..858c24f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -266,17 +266,8 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ap_settings *settings)
{
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
- struct qtnf_wmac *mac = wiphy_priv(wiphy);
int ret;

- if (!cfg80211_chandef_identical(&mac->chandef, &settings->chandef)) {
- memcpy(&mac->chandef, &settings->chandef, sizeof(mac->chandef));
- if (vif->vifid != 0)
- pr_warn("%s: unexpected chan %u (%u MHz)\n", dev->name,
- settings->chandef.chan->hw_value,
- settings->chandef.chan->center_freq);
- }
-
ret = qtnf_cmd_send_config_ap(vif, settings);
if (ret) {
pr_err("VIF%u.%u: failed to push config to FW\n",
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index cddbb5d..7b24d37 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -185,8 +185,6 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
const struct cfg80211_ap_settings *s)
{
struct sk_buff *cmd_skb;
- struct cfg80211_chan_def *chandef = &vif->mac->chandef;
- struct qlink_tlv_channel *qchan;
struct qlink_cmd_config_ap *cmd;
struct qlink_auth_encr *aen;
u16 res_code = QLINK_CMD_RESULT_OK;
@@ -211,17 +209,6 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
cmd->ht_required = s->ht_required;
cmd->vht_required = s->vht_required;

- if (s->ssid && s->ssid_len > 0 && s->ssid_len <= IEEE80211_MAX_SSID_LEN)
- qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, s->ssid,
- s->ssid_len);
-
- qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
- qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
- qchan->hdr.len = cpu_to_le16(sizeof(*qchan) -
- sizeof(struct qlink_tlv_hdr));
- qchan->hw_value = cpu_to_le16(
- ieee80211_frequency_to_channel(chandef->chan->center_freq));
-
aen = &cmd->aen;
aen->auth_type = s->auth_type;
aen->privacy = !!s->privacy;
@@ -240,6 +227,20 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
aen->control_port_ethertype =
cpu_to_le16(be16_to_cpu(s->crypto.control_port_ethertype));

+ if (s->ssid && s->ssid_len > 0 && s->ssid_len <= IEEE80211_MAX_SSID_LEN)
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, s->ssid,
+ s->ssid_len);
+
+ if (cfg80211_chandef_valid(&s->chandef)) {
+ struct qlink_tlv_chandef *chtlv =
+ (struct qlink_tlv_chandef *)skb_put(cmd_skb,
+ sizeof(*chtlv));
+
+ chtlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANDEF);
+ chtlv->hdr.len = sizeof(*chtlv) - sizeof(chtlv->hdr);
+ qlink_chandef_cfg2q(&s->chandef, &chtlv->chan);
+ }
+
qtnf_bus_lock(vif->mac->bus);

ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 6814254..641d252 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -941,6 +941,7 @@ enum qlink_tlv_id {
QTN_TLV_ID_LRETRY_LIMIT = 0x0204,
QTN_TLV_ID_REG_RULE = 0x0207,
QTN_TLV_ID_CHANNEL = 0x020F,
+ QTN_TLV_ID_CHANDEF = 0x0210,
QTN_TLV_ID_COVERAGE_CLASS = 0x0213,
QTN_TLV_ID_IFACE_LIMIT = 0x0214,
QTN_TLV_ID_NUM_IFACE_COMB = 0x0215,
@@ -1128,6 +1129,18 @@ struct qlink_tlv_channel {
u8 rsvd[2];
} __packed;

+/**
+ * struct qlink_tlv_chandef - data for QTN_TLV_ID_CHANDEF TLV
+ *
+ * Channel definition.
+ *
+ * @chan: channel definition data.
+ */
+struct qlink_tlv_chandef {
+ struct qlink_tlv_hdr hdr;
+ struct qlink_chandef chan;
+} __packed;
+
struct qlink_chan_stats {
__le32 chan_num;
__le32 cca_tx;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
index 63a74b2..61d999a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
@@ -128,6 +128,38 @@ void qlink_chandef_q2cfg(struct wiphy *wiphy,
}
}

+static u8 qlink_chanwidth_nl_to_qlink(enum nl80211_chan_width nlwidth)
+{
+ switch (nlwidth) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ return QLINK_CHAN_WIDTH_20_NOHT;
+ case NL80211_CHAN_WIDTH_20:
+ return QLINK_CHAN_WIDTH_20;
+ case NL80211_CHAN_WIDTH_40:
+ return QLINK_CHAN_WIDTH_40;
+ case NL80211_CHAN_WIDTH_80:
+ return QLINK_CHAN_WIDTH_80;
+ case NL80211_CHAN_WIDTH_80P80:
+ return QLINK_CHAN_WIDTH_80P80;
+ case NL80211_CHAN_WIDTH_160:
+ return QLINK_CHAN_WIDTH_160;
+ case NL80211_CHAN_WIDTH_5:
+ return QLINK_CHAN_WIDTH_5;
+ case NL80211_CHAN_WIDTH_10:
+ return QLINK_CHAN_WIDTH_10;
+ default:
+ return -1;
+ }
+}
+
+void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef,
+ struct qlink_chandef *qch)
+{
+ qch->center_freq1 = cpu_to_le16(chdef->center_freq1);
+ qch->center_freq2 = cpu_to_le16(chdef->center_freq2);
+ qch->width = qlink_chanwidth_nl_to_qlink(chdef->width);
+}
+
enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val)
{
switch (nl_val) {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
index 416f11d..260383d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -66,6 +66,8 @@ u8 qlink_chan_width_mask_to_nl(u16 qlink_mask);
void qlink_chandef_q2cfg(struct wiphy *wiphy,
const struct qlink_chandef *qch,
struct cfg80211_chan_def *chdef);
+void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef,
+ struct qlink_chandef *qch);
enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val);

#endif /* _QTN_FMAC_QLINK_UTIL_H_ */
--
2.9.5

2017-08-25 02:30:54

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 09/27] qtnfmac: do not cache BSS state in per-VIF structure

From: Igor Mitsyanko <[email protected]>

This cached state is unused, except for BSSID that we will keep.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 39 ++++--------------
drivers/net/wireless/quantenna/qtnfmac/commands.c | 49 +++++++++++++++--------
drivers/net/wireless/quantenna/qtnfmac/core.h | 19 ++-------
3 files changed, 42 insertions(+), 65 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 999f1bd..9eb0c08 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -131,6 +131,7 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
vif->netdev = NULL;
vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
eth_zero_addr(vif->mac_addr);
+ eth_zero_addr(vif->bssid);

return 0;
}
@@ -199,6 +200,8 @@ 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);
}
@@ -569,7 +572,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
struct qtnf_wmac *mac = wiphy_priv(wiphy);
struct cfg80211_chan_def chandef;
- struct qtnf_bss_config *bss_cfg;
int ret;

if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
@@ -578,9 +580,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
if (vif->sta_state != QTNF_STA_DISCONNECTED)
return -EBUSY;

- bss_cfg = &vif->bss_cfg;
- memset(bss_cfg, 0, sizeof(*bss_cfg));
-
if (sme->channel) {
/* FIXME: need to set proper nl80211_channel_type value */
cfg80211_chandef_create(&chandef, sme->channel,
@@ -593,34 +592,10 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
memcpy(&mac->chandef, &chandef, sizeof(mac->chandef));
}

- bss_cfg->ssid_len = sme->ssid_len;
- memcpy(&bss_cfg->ssid, sme->ssid, bss_cfg->ssid_len);
- bss_cfg->auth_type = sme->auth_type;
- bss_cfg->privacy = sme->privacy;
- bss_cfg->mfp = sme->mfp;
-
- if ((sme->bg_scan_period > 0) &&
- (sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD))
- bss_cfg->bg_scan_period = sme->bg_scan_period;
- else if (sme->bg_scan_period == -1)
- bss_cfg->bg_scan_period = QTNF_DEFAULT_BG_SCAN_PERIOD;
- else
- bss_cfg->bg_scan_period = 0; /* disabled */
-
- bss_cfg->connect_flags = 0;
-
- if (sme->flags & ASSOC_REQ_DISABLE_HT)
- bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_HT;
- if (sme->flags & ASSOC_REQ_DISABLE_VHT)
- bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT;
- if (sme->flags & ASSOC_REQ_USE_RRM)
- bss_cfg->connect_flags |= QLINK_STA_CONNECT_USE_RRM;
-
- memcpy(&bss_cfg->crypto, &sme->crypto, sizeof(bss_cfg->crypto));
if (sme->bssid)
- ether_addr_copy(bss_cfg->bssid, sme->bssid);
+ ether_addr_copy(vif->bssid, sme->bssid);
else
- eth_zero_addr(bss_cfg->bssid);
+ eth_zero_addr(vif->bssid);

ret = qtnf_cmd_send_connect(vif, sme);
if (ret) {
@@ -1050,7 +1025,7 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev)
break;
case QTNF_STA_CONNECTING:
cfg80211_connect_result(vif->netdev,
- vif->bss_cfg.bssid, NULL, 0,
+ vif->bssid, NULL, 0,
NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
@@ -1077,7 +1052,7 @@ void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif)
switch (vif->sta_state) {
case QTNF_STA_CONNECTING:
cfg80211_connect_result(vif->netdev,
- vif->bss_cfg.bssid, NULL, 0,
+ vif->bssid, NULL, 0,
NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index cb9632b..7dbee42 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2036,11 +2036,11 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
{
struct sk_buff *cmd_skb;
struct qlink_cmd_connect *cmd;
- struct qtnf_bss_config *bss_cfg = &vif->bss_cfg;
struct qlink_auth_encr aen;
u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
int i;
+ u32 connect_flags = 0;

cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_CONNECT,
@@ -2052,40 +2052,55 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,

cmd = (struct qlink_cmd_connect *)cmd_skb->data;

- ether_addr_copy(cmd->bssid, bss_cfg->bssid);
+ ether_addr_copy(cmd->bssid, vif->bssid);

if (vif->mac->chandef.chan)
cmd->channel = cpu_to_le16(vif->mac->chandef.chan->hw_value);

- cmd->bg_scan_period = cpu_to_le16(bss_cfg->bg_scan_period);
+ if ((sme->bg_scan_period > 0) &&
+ (sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD))
+ 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 */
+
+ if (sme->flags & ASSOC_REQ_DISABLE_HT)
+ connect_flags |= QLINK_STA_CONNECT_DISABLE_HT;
+ if (sme->flags & ASSOC_REQ_DISABLE_VHT)
+ connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT;
+ if (sme->flags & ASSOC_REQ_USE_RRM)
+ connect_flags |= QLINK_STA_CONNECT_USE_RRM;
+
+ cmd->flags = cpu_to_le32(connect_flags);

memset(&aen, 0, sizeof(aen));
- aen.auth_type = bss_cfg->auth_type;
- aen.privacy = !!bss_cfg->privacy;
- aen.mfp = bss_cfg->mfp;
- aen.wpa_versions = cpu_to_le32(bss_cfg->crypto.wpa_versions);
- aen.cipher_group = cpu_to_le32(bss_cfg->crypto.cipher_group);
+ aen.auth_type = sme->auth_type;
+ aen.privacy = !!sme->privacy;
+ aen.mfp = sme->mfp;
+ aen.wpa_versions = cpu_to_le32(sme->crypto.wpa_versions);
+ aen.cipher_group = cpu_to_le32(sme->crypto.cipher_group);
aen.n_ciphers_pairwise = cpu_to_le32(
- bss_cfg->crypto.n_ciphers_pairwise);
+ sme->crypto.n_ciphers_pairwise);

for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
aen.ciphers_pairwise[i] = cpu_to_le32(
- bss_cfg->crypto.ciphers_pairwise[i]);
+ sme->crypto.ciphers_pairwise[i]);

- aen.n_akm_suites = cpu_to_le32(bss_cfg->crypto.n_akm_suites);
+ aen.n_akm_suites = cpu_to_le32(sme->crypto.n_akm_suites);

for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
aen.akm_suites[i] = cpu_to_le32(
- bss_cfg->crypto.akm_suites[i]);
+ sme->crypto.akm_suites[i]);

- aen.control_port = bss_cfg->crypto.control_port;
+ aen.control_port = sme->crypto.control_port;
aen.control_port_no_encrypt =
- bss_cfg->crypto.control_port_no_encrypt;
+ sme->crypto.control_port_no_encrypt;
aen.control_port_ethertype = cpu_to_le16(be16_to_cpu(
- bss_cfg->crypto.control_port_ethertype));
+ sme->crypto.control_port_ethertype));

- qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, bss_cfg->ssid,
- bss_cfg->ssid_len);
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, sme->ssid,
+ sme->ssid_len);
qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen,
sizeof(aen));

diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index a40295e..aa1a92f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -57,20 +57,6 @@ extern const struct net_device_ops qtnf_netdev_ops;
struct qtnf_bus;
struct qtnf_vif;

-struct qtnf_bss_config {
- u8 ssid[IEEE80211_MAX_SSID_LEN];
- u8 bssid[ETH_ALEN];
- size_t ssid_len;
- u8 dtim;
- u16 bcn_period;
- u16 auth_type;
- bool privacy;
- enum nl80211_mfp mfp;
- struct cfg80211_crypto_settings crypto;
- u16 bg_scan_period;
- u32 connect_flags;
-};
-
struct qtnf_sta_node {
struct list_head list;
u8 mac_addr[ETH_ALEN];
@@ -93,6 +79,8 @@ enum qtnf_mac_status {

struct qtnf_vif {
struct wireless_dev wdev;
+ u8 bssid[ETH_ALEN];
+ u8 mac_addr[ETH_ALEN];
u8 vifid;
u8 bss_priority;
u8 bss_status;
@@ -100,9 +88,8 @@ struct qtnf_vif {
u16 mgmt_frames_bitmask;
struct net_device *netdev;
struct qtnf_wmac *mac;
- u8 mac_addr[ETH_ALEN];
+
struct work_struct reset_work;
- struct qtnf_bss_config bss_cfg;
struct qtnf_sta_list sta_list;
unsigned long cons_tx_timeout_cnt;
};
--
2.9.5

2017-08-30 12:21:14

by Sergey Matyukevich

[permalink] [raw]
Subject: Re: [PATCH 21/27] qtnfmac: extend "IE set" TLV to include frame type info

> Two points here. First, it looks like there is a problem here inherited
> from the existing implementation. We go through payload, but in fact we
> pass to cfg80211_inform_bss only the last QTN_TLV_ID_IE_SET element.
> Second, it looks like QTN_TLV_ID_IE_SET here should be treated in
> the same way as in qtnf_event_handle_sta_assoc, to avoid confusion.
> In other words, either we use only QTN_TLV_ID_IE_SET in both cases,
> or switch to specific qlink_tlv_ie_set elements.

Ignore the second point: it is addressed by the next patch.

Regards,
Sergey

2017-08-25 02:30:56

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 10/27] qtnfmac: do not cache channel info from "connect" command

From: Igor Mitsyanko <[email protected]>

This makes no sense because real operational channel is choosen based
on AP operation, not on what STA is configured to.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 14 --------------
drivers/net/wireless/quantenna/qtnfmac/commands.c | 6 ++++--
2 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 9eb0c08..501ece3 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -570,8 +570,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_connect_params *sme)
{
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
- struct qtnf_wmac *mac = wiphy_priv(wiphy);
- struct cfg80211_chan_def chandef;
int ret;

if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
@@ -580,18 +578,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
if (vif->sta_state != QTNF_STA_DISCONNECTED)
return -EBUSY;

- if (sme->channel) {
- /* FIXME: need to set proper nl80211_channel_type value */
- cfg80211_chandef_create(&chandef, sme->channel,
- NL80211_CHAN_HT20);
- /* fall-back to minimal safe chandef description */
- if (!cfg80211_chandef_valid(&chandef))
- cfg80211_chandef_create(&chandef, sme->channel,
- NL80211_CHAN_HT20);
-
- memcpy(&mac->chandef, &chandef, sizeof(mac->chandef));
- }
-
if (sme->bssid)
ether_addr_copy(vif->bssid, sme->bssid);
else
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 7dbee42..65eee2b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2054,8 +2054,10 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,

ether_addr_copy(cmd->bssid, vif->bssid);

- if (vif->mac->chandef.chan)
- cmd->channel = cpu_to_le16(vif->mac->chandef.chan->hw_value);
+ if (sme->channel)
+ cmd->channel = cpu_to_le16(sme->channel->hw_value);
+ else
+ cmd->channel = 0;

if ((sme->bg_scan_period > 0) &&
(sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD))
--
2.9.5

2017-08-25 02:31:06

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 20/27] qtnfmac: get rid of PHYMODE capabilities flags

From: Igor Mitsyanko <[email protected]>

Supported WiFi operation modes are now identified per-band based on
HT/VHT capabilities of each band.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 3 ---
drivers/net/wireless/quantenna/qtnfmac/commands.c | 1 -
drivers/net/wireless/quantenna/qtnfmac/core.h | 1 -
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 11 ++---------
4 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index d6780f42..3faac7a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -879,9 +879,6 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
if (ret)
goto out;

- pr_info("MAC%u: phymode=%#x radar=%#x\n", mac->macid,
- mac->macinfo.phymode_cap, mac->macinfo.radar_detect_widths);
-
wiphy->frag_threshold = mac->macinfo.frag_thr;
wiphy->rts_threshold = mac->macinfo.rts_thr;
wiphy->retry_short = mac->macinfo.sretry_limit;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index b26cd01..79a3e75 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1088,7 +1088,6 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac,
mac_info = &mac->macinfo;

mac_info->bands_cap = resp_info->bands_cap;
- mac_info->phymode_cap = resp_info->phymode_cap;
memcpy(&mac_info->dev_mac, &resp_info->dev_mac,
sizeof(mac_info->dev_mac));

diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 3e74736..72d4298 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -92,7 +92,6 @@ struct qtnf_vif {

struct qtnf_mac_info {
u8 bands_cap;
- u8 phymode_cap;
u8 dev_mac[ETH_ALEN];
u8 num_tx_chain;
u8 num_rx_chain;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index a9f410b..e4d3e7f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -65,12 +65,6 @@ enum qlink_hw_capab {
QLINK_HW_SUPPORTS_REG_UPDATE = BIT(0),
};

-enum qlink_phy_mode {
- QLINK_PHYMODE_BGN = BIT(0),
- QLINK_PHYMODE_AN = BIT(1),
- QLINK_PHYMODE_AC = BIT(2),
-};
-
enum qlink_iface_type {
QLINK_IFTYPE_AP = 1,
QLINK_IFTYPE_STATION = 2,
@@ -630,7 +624,6 @@ struct qlink_resp {
* @vht_cap_mod_mask: mask specifying which VHT capabilities can be altered.
* @ht_cap_mod_mask: mask specifying which HT capabilities can be altered.
* @bands_cap: wireless bands WMAC can operate in, bitmap of &enum qlink_band.
- * @phymode_cap: PHY modes WMAC can operate in, bitmap of &enum qlink_phy_mode.
* @max_ap_assoc_sta: Maximum number of associations supported by WMAC.
* @radar_detect_widths: bitmask of channels BW for which WMAC can detect radar.
* @var_info: variable-length WMAC info data.
@@ -642,10 +635,10 @@ struct qlink_resp_get_mac_info {
u8 num_rx_chain;
struct ieee80211_vht_cap vht_cap_mod_mask;
struct ieee80211_ht_cap ht_cap_mod_mask;
- u8 bands_cap;
- u8 phymode_cap;
__le16 max_ap_assoc_sta;
__le16 radar_detect_widths;
+ u8 bands_cap;
+ u8 rsvd[1];
u8 var_info[0];
} __packed;

--
2.9.5

2017-08-25 02:31:01

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 16/27] qtnfmac: stop using private driver info about current channel

From: Igor Mitsyanko <[email protected]>

Linux Wireless device structure already has required info.
Since driver's info is not used anymore, remove it.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 7 ++-----
drivers/net/wireless/quantenna/qtnfmac/core.h | 1 -
drivers/net/wireless/quantenna/qtnfmac/event.c | 2 --
3 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 8542c16..5ee3345 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -630,15 +630,15 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev,
int idx, struct survey_info *survey)
{
struct qtnf_wmac *mac = wiphy_priv(wiphy);
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
struct ieee80211_supported_band *sband;
- struct cfg80211_chan_def *chandef;
+ const struct cfg80211_chan_def *chandef = &wdev->chandef;
struct ieee80211_channel *chan;
struct qtnf_chan_stats stats;
struct qtnf_vif *vif;
int ret;

vif = qtnf_netdev_get_priv(dev);
- chandef = &mac->chandef;

sband = wiphy->bands[NL80211_BAND_2GHZ];
if (sband && idx >= sband->n_channels) {
@@ -705,7 +705,6 @@ static int
qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_chan_def *chandef)
{
- struct qtnf_wmac *mac = wiphy_priv(wiphy);
struct net_device *ndev = wdev->netdev;
struct qtnf_vif *vif;
int ret;
@@ -727,8 +726,6 @@ qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
ret = -ENODATA;
}

- memcpy(&mac->chandef, chandef, sizeof(mac->chandef));
-
out:
return ret;
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 5234a9e..44a2cbb 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -126,7 +126,6 @@ struct qtnf_wmac {
struct qtnf_mac_info macinfo;
struct qtnf_vif iflist[QTNF_MAX_INTF];
struct cfg80211_scan_request *scan_req;
- struct cfg80211_chan_def chandef;
struct mutex mac_lock; /* lock during wmac speicific ops */
struct timer_list scan_timeout;
};
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index db7e475..9befc9f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -368,8 +368,6 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
mac->macid, chdef.chan->hw_value, chdef.center_freq1,
chdef.center_freq2, chdef.width);

- memcpy(&mac->chandef, &chdef, sizeof(mac->chandef));
-
for (i = 0; i < QTNF_MAX_INTF; i++) {
vif = &mac->iflist[i];
if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)
--
2.9.5

2017-08-25 02:30:56

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 11/27] qtnfmac: make encryption info a part of "connect" command.

From: Igor Mitsyanko <[email protected]>

Encryption info is a constant part of STA settings, no point
to pass it as an optional TLV.
Remove QTN_TLV_ID_CRYPTO type as it's not used anymore.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/commands.c | 42 ++++++++++-------------
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 5 +--
2 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 65eee2b..195b777 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2036,7 +2036,7 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
{
struct sk_buff *cmd_skb;
struct qlink_cmd_connect *cmd;
- struct qlink_auth_encr aen;
+ struct qlink_auth_encr *aen;
u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
int i;
@@ -2048,8 +2048,6 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
if (unlikely(!cmd_skb))
return -ENOMEM;

- qtnf_bus_lock(vif->mac->bus);
-
cmd = (struct qlink_cmd_connect *)cmd_skb->data;

ether_addr_copy(cmd->bssid, vif->bssid);
@@ -2076,41 +2074,39 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,

cmd->flags = cpu_to_le32(connect_flags);

- memset(&aen, 0, sizeof(aen));
- aen.auth_type = sme->auth_type;
- aen.privacy = !!sme->privacy;
- aen.mfp = sme->mfp;
- aen.wpa_versions = cpu_to_le32(sme->crypto.wpa_versions);
- aen.cipher_group = cpu_to_le32(sme->crypto.cipher_group);
- aen.n_ciphers_pairwise = cpu_to_le32(
- sme->crypto.n_ciphers_pairwise);
+ aen = &cmd->aen;
+ aen->auth_type = sme->auth_type;
+ aen->privacy = !!sme->privacy;
+ aen->mfp = sme->mfp;
+ aen->wpa_versions = cpu_to_le32(sme->crypto.wpa_versions);
+ aen->cipher_group = cpu_to_le32(sme->crypto.cipher_group);
+ aen->n_ciphers_pairwise = cpu_to_le32(sme->crypto.n_ciphers_pairwise);

for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
- aen.ciphers_pairwise[i] = cpu_to_le32(
- sme->crypto.ciphers_pairwise[i]);
+ aen->ciphers_pairwise[i] =
+ cpu_to_le32(sme->crypto.ciphers_pairwise[i]);

- aen.n_akm_suites = cpu_to_le32(sme->crypto.n_akm_suites);
+ aen->n_akm_suites = cpu_to_le32(sme->crypto.n_akm_suites);

for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
- aen.akm_suites[i] = cpu_to_le32(
- sme->crypto.akm_suites[i]);
+ aen->akm_suites[i] = cpu_to_le32(sme->crypto.akm_suites[i]);

- aen.control_port = sme->crypto.control_port;
- aen.control_port_no_encrypt =
+ aen->control_port = sme->crypto.control_port;
+ aen->control_port_no_encrypt =
sme->crypto.control_port_no_encrypt;
- aen.control_port_ethertype = cpu_to_le16(be16_to_cpu(
- sme->crypto.control_port_ethertype));
+ aen->control_port_ethertype =
+ cpu_to_le16(be16_to_cpu(sme->crypto.control_port_ethertype));

qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, sme->ssid,
- sme->ssid_len);
- qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen,
- sizeof(aen));
+ sme->ssid_len);

if (sme->ie_len != 0)
qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET,
sme->ie,
sme->ie_len);

+ qtnf_bus_lock(vif->mac->bus);
+
ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);

if (unlikely(ret))
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 641d252..7b313d3 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -417,8 +417,9 @@ enum qlink_sta_connect_flags {
* struct qlink_cmd_connect - data for QLINK_CMD_CONNECT command
*
* @flags: for future use.
- * @freq: center frequence of a channel which should be used to connect.
+ * @channel: channel which should be used to connect.
* @bg_scan_period: period of background scan.
+ * @aen: authentication information.
* @bssid: BSSID of the BSS to connect to.
* @payload: variable portion of connection request.
*/
@@ -427,6 +428,7 @@ struct qlink_cmd_connect {
__le32 flags;
__le16 channel;
__le16 bg_scan_period;
+ struct qlink_auth_encr aen;
u8 bssid[ETH_ALEN];
u8 payload[0];
} __packed;
@@ -950,7 +952,6 @@ enum qlink_tlv_id {
QTN_TLV_ID_STA_GENERIC_INFO = 0x0301,
QTN_TLV_ID_KEY = 0x0302,
QTN_TLV_ID_SEQ = 0x0303,
- QTN_TLV_ID_CRYPTO = 0x0304,
QTN_TLV_ID_IE_SET = 0x0305,
};

--
2.9.5

2017-08-30 01:45:44

by Igor Mitsyanko

[permalink] [raw]
Subject: Re: [PATCH 02/27] qtnfmac: make "Channel change" event report full channel info

On 08/29/2017 07:31 AM, Sergey Matyukevich wrote:
>> static int
>> qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
>> @@ -358,41 +359,36 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
>> u16 len)
>> {
>> struct wiphy *wiphy = priv_to_wiphy(mac);
>> - struct cfg80211_chan_def chandef;
>> - struct ieee80211_channel *chan;
>> + struct cfg80211_chan_def chdef;
>> struct qtnf_vif *vif;
>> - int freq;
>> int i;
>
> Original variable name 'chandef' was easier to spell on the phone :)

Will return)

>
> ...
>
>> + qlink_chandef_q2cfg(wiphy, &data->chan, &chdef);
>> +
>> + if (!cfg80211_chandef_valid(&chdef)) {
>> + pr_err("MAC%u: bad channel freq1=%u bw=%u\n", mac->macid,
>> + chdef.center_freq1, chdef.width);
>> return -EINVAL;
>> }
>
> Lets keep both freq1 and freq2 in error message.

Ok

>
> ...
>
>> +void qlink_chandef_q2cfg(struct wiphy *wiphy,
>> + const struct qlink_chandef *qch,
>> + struct cfg80211_chan_def *chdef)
>> +{
>> + chdef->center_freq1 = le16_to_cpu(qch->center_freq1);
>> + chdef->center_freq2 = le16_to_cpu(qch->center_freq2);
>> + chdef->width = qlink_chanwidth_to_nl(qch->width);
>> +
>> + switch (chdef->width) {
>> + case NL80211_CHAN_WIDTH_20_NOHT:
>> + case NL80211_CHAN_WIDTH_20:
>> + case NL80211_CHAN_WIDTH_5:
>> + case NL80211_CHAN_WIDTH_10:
>> + chdef->chan = ieee80211_get_channel(wiphy, chdef->center_freq1);
>> + break;
>> + case NL80211_CHAN_WIDTH_40:
>> + case NL80211_CHAN_WIDTH_80:
>> + case NL80211_CHAN_WIDTH_80P80:
>> + case NL80211_CHAN_WIDTH_160:
>> + chdef->chan = ieee80211_get_channel(wiphy,
>> + chdef->center_freq1 - 10);
>
> Do we have the same formula for 40MHz and 80MHz center frequency ?
> I thought we should be using the channel number for the left-most 20MHz band.

Here it should be no difference which channel number we're using as long
as it falls within specified bandwidth. I mean, we can take (freq - 10),
(freq + 10) for 40MHz, or (freq - 30) (freq + 30) for 80 MHz etc.

I don't see how we can identify which 20MHz channel is primary, with a
chandef structure.

>
>> + break;
>> + default:
>> + chdef->chan = NULL;
>> + break;
>> + }
>> +}
>
> Regards,
> Sergey
>

2017-08-25 02:31:12

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 26/27] qtnfmac: include HTCAP and VHTCAP into config AP command

From: Igor Mitsyanko <[email protected]>

Include HT/VHT caps directly into command so that they won't have
to be searched for in IEs.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/commands.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 1965061..dde2013 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -265,6 +265,24 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
s->beacon.assocresp_ies,
s->beacon.assocresp_ies_len);

+ if (s->ht_cap) {
+ struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *)
+ skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->ht_cap));
+
+ tlv->type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
+ tlv->len = cpu_to_le16(sizeof(*s->ht_cap));
+ memcpy(tlv->val, s->ht_cap, sizeof(*s->ht_cap));
+ }
+
+ if (s->vht_cap) {
+ struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *)
+ skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->vht_cap));
+
+ tlv->type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
+ tlv->len = cpu_to_le16(sizeof(*s->vht_cap));
+ memcpy(tlv->val, s->ht_cap, sizeof(*s->vht_cap));
+ }
+
qtnf_bus_lock(vif->mac->bus);

ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
--
2.9.5

2017-08-30 16:29:02

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 00/27] qtnfmac: allow to configure channel, BW, HT/VHT caps

Kalle Valo <[email protected]> writes:

> Kalle Valo <[email protected]> writes:
>
>> [email protected] writes:
>>
>>> This patchset has a goal to make operational parameters (channel, BW,
>>> HT/VHT capabilities) configuration possible for qtnfmac driver.
>>> Basically the idea is to make driver level as thin as possible, and let
>>> everything to be handled by userspace/nl80211 and wireless device itself.
>>
>> This patchset is just too big and pain to review. Preferably no more
>> than 10-12 patches per set, please. If the patches bigger then the limit
>> should be even lower.
>
> And I noticed that patch 25 didn't make it to patchwork:
>
> https://patchwork.kernel.org/project/linux-wireless/list/?state=*&q=qtnfmac

Actually it did but it was an nl80211 patch:

https://patchwork.kernel.org/patch/9921179/

Never ever hide mac80211 or cfg80211 patches within driver patches like
this. They need to be submitted separately so that everyone sees them.

In some cases it makes sense to submit the driver patches using the new
cfg80211/mac80211 feature at the same, but then do it so that you have
the cfg80211/mac80211 patches and the corresponding driver patches as
last. In that case I assign the whole patchset first to Johannes and
once he has applied the cfg80211/mac80211 patches he assigns the driver
patches to me.

--
Kalle Valo

2017-08-25 02:31:11

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 25/27] nl80211: look for HT/VHT capabilities in beacon's tail

From: Igor Mitsyanko <[email protected]>

There are no HT/VHT capabilities in cfg80211_ap_settings::beacon_ies,
these should be looked for in beacon's tail instead.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
net/wireless/nl80211.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8ce8542..0df8023 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3791,8 +3791,8 @@ static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
{
const struct cfg80211_beacon_data *bcn = &params->beacon;
- size_t ies_len = bcn->beacon_ies_len;
- const u8 *ies = bcn->beacon_ies;
+ size_t ies_len = bcn->tail_len;
+ const u8 *ies = bcn->tail;
const u8 *rates;
const u8 *cap;

--
2.9.5

2017-08-25 02:30:48

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 02/27] qtnfmac: make "Channel change" event report full channel info

From: Igor Mitsyanko <[email protected]>

Specifically, it has to report center frequency, secondary center
frequency (for 80+80) and BW.
Introduce channel definition structure to qlink and modify channel
change event processing function accordingly.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/event.c | 34 +++++++-------
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 18 +++++++-
.../net/wireless/quantenna/qtnfmac/qlink_util.c | 52 ++++++++++++++++++++++
.../net/wireless/quantenna/qtnfmac/qlink_util.h | 4 ++
4 files changed, 87 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 0fc2814..52e2652 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -25,6 +25,7 @@
#include "trans.h"
#include "util.h"
#include "event.h"
+#include "qlink_util.h"

static int
qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
@@ -358,41 +359,36 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
u16 len)
{
struct wiphy *wiphy = priv_to_wiphy(mac);
- struct cfg80211_chan_def chandef;
- struct ieee80211_channel *chan;
+ struct cfg80211_chan_def chdef;
struct qtnf_vif *vif;
- int freq;
int i;

if (len < sizeof(*data)) {
- pr_err("payload is too short\n");
+ pr_err("MAC%u: payload is too short\n", mac->macid);
return -EINVAL;
}

- freq = le32_to_cpu(data->freq);
- chan = ieee80211_get_channel(wiphy, freq);
- if (!chan) {
- pr_err("channel at %d MHz not found\n", freq);
+ qlink_chandef_q2cfg(wiphy, &data->chan, &chdef);
+
+ if (!cfg80211_chandef_valid(&chdef)) {
+ pr_err("MAC%u: bad channel freq1=%u bw=%u\n", mac->macid,
+ chdef.center_freq1, chdef.width);
return -EINVAL;
}

- pr_debug("MAC%d switch to new channel %u MHz\n", mac->macid, freq);
+ pr_debug("MAC%d: new channel ieee=%u freq1=%u freq2=%u bw=%u\n",
+ mac->macid, chdef.chan->hw_value, chdef.center_freq1,
+ chdef.center_freq2, chdef.width);

if (mac->status & QTNF_MAC_CSA_ACTIVE) {
mac->status &= ~QTNF_MAC_CSA_ACTIVE;
- if (chan->hw_value != mac->csa_chandef.chan->hw_value)
+ if (chdef.chan->hw_value != mac->csa_chandef.chan->hw_value)
pr_warn("unexpected switch to %u during CSA to %u\n",
- chan->hw_value,
+ chdef.chan->hw_value,
mac->csa_chandef.chan->hw_value);
}

- /* FIXME: need to figure out proper nl80211_channel_type value */
- cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);
- /* fall-back to minimal safe chandef description */
- if (!cfg80211_chandef_valid(&chandef))
- cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);
-
- memcpy(&mac->chandef, &chandef, sizeof(mac->chandef));
+ memcpy(&mac->chandef, &chdef, sizeof(mac->chandef));

for (i = 0; i < QTNF_MAX_INTF; i++) {
vif = &mac->iflist[i];
@@ -401,7 +397,7 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,

if (vif->netdev) {
mutex_lock(&vif->wdev.mtx);
- cfg80211_ch_switch_notify(vif->netdev, &chandef);
+ cfg80211_ch_switch_notify(vif->netdev, &chdef);
mutex_unlock(&vif->wdev.mtx);
}
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index a69fd470..5936854 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -118,6 +118,20 @@ enum qlink_channel_width {
QLINK_CHAN_WIDTH_160,
};

+/**
+ * struct qlink_chandef - qlink channel definition
+ *
+ * @center_freq1: center frequency of first segment
+ * @center_freq2: center frequency of second segment (80+80 only)
+ * @width: channel width, one of @enum qlink_channel_width
+ */
+struct qlink_chandef {
+ __le16 center_freq1;
+ __le16 center_freq2;
+ u8 width;
+ u8 rsvd[3];
+} __packed;
+
/* QLINK Command messages related definitions
*/

@@ -764,11 +778,11 @@ struct qlink_event_bss_leave {
/**
* struct qlink_event_freq_change - data for QLINK_EVENT_FREQ_CHANGE event
*
- * @freq: new operating frequency in MHz
+ * @chan: new operating channel definition
*/
struct qlink_event_freq_change {
struct qlink_event ehdr;
- __le32 freq;
+ struct qlink_chandef chan;
} __packed;

enum qlink_rxmgmt_flags {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
index 369b77d..3c1db5b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
@@ -75,3 +75,55 @@ u8 qlink_chan_width_mask_to_nl(u16 qlink_mask)

return result;
}
+
+static enum nl80211_chan_width qlink_chanwidth_to_nl(u8 qlw)
+{
+ switch (qlw) {
+ case QLINK_CHAN_WIDTH_20_NOHT:
+ return NL80211_CHAN_WIDTH_20_NOHT;
+ case QLINK_CHAN_WIDTH_20:
+ return NL80211_CHAN_WIDTH_20;
+ case QLINK_CHAN_WIDTH_40:
+ return NL80211_CHAN_WIDTH_40;
+ case QLINK_CHAN_WIDTH_80:
+ return NL80211_CHAN_WIDTH_80;
+ case QLINK_CHAN_WIDTH_80P80:
+ return NL80211_CHAN_WIDTH_80P80;
+ case QLINK_CHAN_WIDTH_160:
+ return NL80211_CHAN_WIDTH_160;
+ case QLINK_CHAN_WIDTH_5:
+ return NL80211_CHAN_WIDTH_5;
+ case QLINK_CHAN_WIDTH_10:
+ return NL80211_CHAN_WIDTH_10;
+ default:
+ return -1;
+ }
+}
+
+void qlink_chandef_q2cfg(struct wiphy *wiphy,
+ const struct qlink_chandef *qch,
+ struct cfg80211_chan_def *chdef)
+{
+ chdef->center_freq1 = le16_to_cpu(qch->center_freq1);
+ chdef->center_freq2 = le16_to_cpu(qch->center_freq2);
+ chdef->width = qlink_chanwidth_to_nl(qch->width);
+
+ switch (chdef->width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_5:
+ case NL80211_CHAN_WIDTH_10:
+ chdef->chan = ieee80211_get_channel(wiphy, chdef->center_freq1);
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ case NL80211_CHAN_WIDTH_80:
+ case NL80211_CHAN_WIDTH_80P80:
+ case NL80211_CHAN_WIDTH_160:
+ chdef->chan = ieee80211_get_channel(wiphy,
+ chdef->center_freq1 - 10);
+ break;
+ default:
+ chdef->chan = NULL;
+ break;
+ }
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
index de06c1e..5e49a8a 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -19,6 +19,7 @@

#include <linux/types.h>
#include <linux/skbuff.h>
+#include <net/cfg80211.h>

#include "qlink.h"

@@ -62,5 +63,8 @@ static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff *skb,

u16 qlink_iface_type_to_nl_mask(u16 qlink_type);
u8 qlink_chan_width_mask_to_nl(u16 qlink_mask);
+void qlink_chandef_q2cfg(struct wiphy *wiphy,
+ const struct qlink_chandef *qch,
+ struct cfg80211_chan_def *chdef);

#endif /* _QTN_FMAC_QLINK_UTIL_H_ */
--
2.9.5

2017-08-29 14:32:00

by Sergey Matyukevich

[permalink] [raw]
Subject: Re: [PATCH 02/27] qtnfmac: make "Channel change" event report full channel info

> static int
> qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
> @@ -358,41 +359,36 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
> u16 len)
> {
> struct wiphy *wiphy = priv_to_wiphy(mac);
> - struct cfg80211_chan_def chandef;
> - struct ieee80211_channel *chan;
> + struct cfg80211_chan_def chdef;
> struct qtnf_vif *vif;
> - int freq;
> int i;

Original variable name 'chandef' was easier to spell on the phone :)

...

> + qlink_chandef_q2cfg(wiphy, &data->chan, &chdef);
> +
> + if (!cfg80211_chandef_valid(&chdef)) {
> + pr_err("MAC%u: bad channel freq1=%u bw=%u\n", mac->macid,
> + chdef.center_freq1, chdef.width);
> return -EINVAL;
> }

Lets keep both freq1 and freq2 in error message.

...

> +void qlink_chandef_q2cfg(struct wiphy *wiphy,
> + const struct qlink_chandef *qch,
> + struct cfg80211_chan_def *chdef)
> +{
> + chdef->center_freq1 = le16_to_cpu(qch->center_freq1);
> + chdef->center_freq2 = le16_to_cpu(qch->center_freq2);
> + chdef->width = qlink_chanwidth_to_nl(qch->width);
> +
> + switch (chdef->width) {
> + case NL80211_CHAN_WIDTH_20_NOHT:
> + case NL80211_CHAN_WIDTH_20:
> + case NL80211_CHAN_WIDTH_5:
> + case NL80211_CHAN_WIDTH_10:
> + chdef->chan = ieee80211_get_channel(wiphy, chdef->center_freq1);
> + break;
> + case NL80211_CHAN_WIDTH_40:
> + case NL80211_CHAN_WIDTH_80:
> + case NL80211_CHAN_WIDTH_80P80:
> + case NL80211_CHAN_WIDTH_160:
> + chdef->chan = ieee80211_get_channel(wiphy,
> + chdef->center_freq1 - 10);

Do we have the same formula for 40MHz and 80MHz center frequency ?
I thought we should be using the channel number for the left-most 20MHz band.

> + break;
> + default:
> + chdef->chan = NULL;
> + break;
> + }
> +}

Regards,
Sergey

2017-08-25 02:31:13

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 27/27] qtnfmac: pass all CONNECT cmd params to wireless card for processing

From: Igor Mitsyanko <[email protected]>

Specifically, following parameters are needed for wireless device
configuration but were not available to it before:
- HT/VHT capabilities and capabilities masks.
- full channel info (not just IEEE number)
- BSSID hint
- previous BSSID for reassoc request

Move Management Frame Protection setting from common encr info
structure into STA-specific .connect command parameters.

Make sure that all new qlink structure definitions are alignment-safe.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/commands.c | 63 +++++++++++++++--------
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 32 +++++++++---
2 files changed, 65 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index dde2013..c8de438 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -221,7 +221,6 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
aen = &cmd->aen;
aen->auth_type = s->auth_type;
aen->privacy = !!s->privacy;
- aen->mfp = 0;
aen->wpa_versions = cpu_to_le32(s->crypto.wpa_versions);
aen->cipher_group = cpu_to_le32(s->crypto.cipher_group);
aen->n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise);
@@ -2027,17 +2026,36 @@ int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
return ret;
}

+static void qtnf_cmd_channel_tlv_add(struct sk_buff *cmd_skb,
+ const struct ieee80211_channel *sc)
+{
+ struct qlink_tlv_channel *qchan;
+ u32 flags = 0;
+
+ qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
+ qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
+ qchan->hdr.len = cpu_to_le16(sizeof(*qchan) - sizeof(qchan->hdr));
+ qchan->center_freq = cpu_to_le16(sc->center_freq);
+ qchan->hw_value = cpu_to_le16(sc->hw_value);
+
+ if (sc->flags & IEEE80211_CHAN_NO_IR)
+ flags |= QLINK_CHAN_NO_IR;
+
+ if (sc->flags & IEEE80211_CHAN_RADAR)
+ flags |= QLINK_CHAN_RADAR;
+
+ qchan->flags = cpu_to_le32(flags);
+}
+
int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
{
struct sk_buff *cmd_skb;
u16 res_code = QLINK_CMD_RESULT_OK;
struct ieee80211_channel *sc;
struct cfg80211_scan_request *scan_req = mac->scan_req;
- struct qlink_tlv_channel *qchan;
int n_channels;
int count = 0;
int ret;
- u32 flags;

if (scan_req->n_ssids > QTNF_MAX_SSID_LIST_LENGTH) {
pr_err("MAC%u: too many SSIDs in scan request\n", mac->macid);
@@ -2079,22 +2097,8 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
pr_debug("MAC%u: scan chan=%d, freq=%d, flags=%#x\n",
mac->macid, sc->hw_value, sc->center_freq,
sc->flags);
- qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
- flags = 0;
-
- qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
- qchan->hdr.len = cpu_to_le16(sizeof(*qchan) -
- sizeof(struct qlink_tlv_hdr));
- qchan->center_freq = cpu_to_le16(sc->center_freq);
- qchan->hw_value = cpu_to_le16(sc->hw_value);
-
- if (sc->flags & IEEE80211_CHAN_NO_IR)
- flags |= QLINK_CHAN_NO_IR;

- if (sc->flags & IEEE80211_CHAN_RADAR)
- flags |= QLINK_CHAN_RADAR;
-
- qchan->flags = cpu_to_le32(flags);
+ qtnf_cmd_channel_tlv_add(cmd_skb, sc);
n_channels--;
count++;
}
@@ -2138,10 +2142,15 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,

ether_addr_copy(cmd->bssid, vif->bssid);

- if (sme->channel)
- cmd->channel = cpu_to_le16(sme->channel->hw_value);
+ if (sme->bssid_hint)
+ ether_addr_copy(cmd->bssid_hint, sme->bssid_hint);
else
- cmd->channel = 0;
+ eth_zero_addr(cmd->bssid_hint);
+
+ if (sme->prev_bssid)
+ ether_addr_copy(cmd->prev_bssid, sme->prev_bssid);
+ else
+ eth_zero_addr(cmd->prev_bssid);

if ((sme->bg_scan_period > 0) &&
(sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD))
@@ -2159,11 +2168,18 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
connect_flags |= QLINK_STA_CONNECT_USE_RRM;

cmd->flags = cpu_to_le32(connect_flags);
+ memcpy(&cmd->ht_capa, &sme->ht_capa, sizeof(cmd->ht_capa));
+ memcpy(&cmd->ht_capa_mask, &sme->ht_capa_mask,
+ sizeof(cmd->ht_capa_mask));
+ memcpy(&cmd->vht_capa, &sme->vht_capa, sizeof(cmd->vht_capa));
+ memcpy(&cmd->vht_capa_mask, &sme->vht_capa_mask,
+ sizeof(cmd->vht_capa_mask));
+ cmd->pbss = sme->pbss;

aen = &cmd->aen;
aen->auth_type = sme->auth_type;
aen->privacy = !!sme->privacy;
- aen->mfp = sme->mfp;
+ cmd->mfp = sme->mfp;
aen->wpa_versions = cpu_to_le32(sme->crypto.wpa_versions);
aen->cipher_group = cpu_to_le32(sme->crypto.cipher_group);
aen->n_ciphers_pairwise = cpu_to_le32(sme->crypto.n_ciphers_pairwise);
@@ -2190,6 +2206,9 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_REQ,
sme->ie, sme->ie_len);

+ if (sme->channel)
+ qtnf_cmd_channel_tlv_add(cmd_skb, sme->channel);
+
qtnf_bus_lock(vif->mac->bus);

ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 9a913b6..e45fc87 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -19,7 +19,7 @@

#include <linux/ieee80211.h>

-#define QLINK_PROTO_VER 5
+#define QLINK_PROTO_VER 6

#define QLINK_MACID_RSVD 0xFF
#define QLINK_VIFID_RSVD 0xFF
@@ -139,9 +139,9 @@ struct qlink_auth_encr {
__le16 control_port_ethertype;
u8 auth_type;
u8 privacy;
- u8 mfp;
u8 control_port;
u8 control_port_no_encrypt;
+ u8 rsvd[2];
} __packed;

/* QLINK Command messages related definitions
@@ -395,20 +395,36 @@ enum qlink_sta_connect_flags {
/**
* struct qlink_cmd_connect - data for QLINK_CMD_CONNECT command
*
- * @flags: for future use.
- * @channel: channel which should be used to connect.
+ * @bssid: BSSID of the BSS to connect to.
+ * @bssid_hint: recommended AP BSSID for initial connection to the BSS or
+ * 00:00:00:00:00:00 if not specified.
+ * @prev_bssid: previous BSSID, if specified (not 00:00:00:00:00:00) indicates
+ * a request to reassociate.
* @bg_scan_period: period of background scan.
+ * @flags: one of &enum qlink_sta_connect_flags.
+ * @ht_capa: HT Capabilities overrides.
+ * @ht_capa_mask: The bits of ht_capa which are to be used.
+ * @vht_capa: VHT Capability overrides
+ * @vht_capa_mask: The bits of vht_capa which are to be used.
* @aen: authentication information.
- * @bssid: BSSID of the BSS to connect to.
+ * @mfp: whether to use management frame protection.
* @payload: variable portion of connection request.
*/
struct qlink_cmd_connect {
struct qlink_cmd chdr;
- __le32 flags;
- __le16 channel;
+ u8 bssid[ETH_ALEN];
+ u8 bssid_hint[ETH_ALEN];
+ u8 prev_bssid[ETH_ALEN];
__le16 bg_scan_period;
+ __le32 flags;
+ struct ieee80211_ht_cap ht_capa;
+ struct ieee80211_ht_cap ht_capa_mask;
+ struct ieee80211_vht_cap vht_capa;
+ struct ieee80211_vht_cap vht_capa_mask;
struct qlink_auth_encr aen;
- u8 bssid[ETH_ALEN];
+ u8 mfp;
+ u8 pbss;
+ u8 rsvd[2];
u8 payload[0];
} __packed;

--
2.9.5

2017-08-30 13:08:14

by Sergey Matyukevich

[permalink] [raw]
Subject: Re: [PATCH 24/27] qtnfmac: configure and start AP interface with a single command


> This separation would not allow to do a proper device configuration as
> first stage needs to use information from IEs that are processed on
> a second stage. Which means first and second stages have to be meged.
> In that case there is no point anymore to keep third stage either, so
> merge all three into a single command.

typo in commit message: 'meged'

> + if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) {
> + pr_err("VIF%u.%u: can not fit AP settings: %u\n",
> + vif->mac->macid, vif->vifid, len);
> + return false;
> }

Initial len value is sizeof(struct qlink_cmd_start_ap), qlink_cmd is a part
of qlink_cmd_start_ap. So this check has to be fixed. It looks like the
simplest option is only to check payload: set initial len value to 0
and drop sizeof in comparison.

2017-08-25 02:30:51

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 05/27] qtnfmac: pass all AP settings to wireless card for processing

From: Igor Mitsyanko <[email protected]>

"struct cfg80211_ap_settings" provides more information for AP mode
configuration that is currently being passed on to network card
for processing.
Modify QLINK command to pass all AP settings. Make most of settings
a constant part of "config AP" command instead of passing it as
optional TLVs.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/commands.c | 52 ++++++++-------
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 78 ++++++++++++++++------
.../net/wireless/quantenna/qtnfmac/qlink_util.c | 13 ++++
.../net/wireless/quantenna/qtnfmac/qlink_util.h | 1 +
4 files changed, 101 insertions(+), 43 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index b498019..cddbb5d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -187,27 +187,34 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
struct sk_buff *cmd_skb;
struct cfg80211_chan_def *chandef = &vif->mac->chandef;
struct qlink_tlv_channel *qchan;
- struct qlink_auth_encr aen;
+ struct qlink_cmd_config_ap *cmd;
+ struct qlink_auth_encr *aen;
u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
int i;

cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_CONFIG_AP,
- sizeof(struct qlink_cmd));
+ sizeof(*cmd));
if (unlikely(!cmd_skb))
return -ENOMEM;

- qtnf_bus_lock(vif->mac->bus);
+ cmd = (struct qlink_cmd_config_ap *)cmd_skb->data;
+ cmd->dtim_period = s->dtim_period;
+ cmd->beacon_interval = cpu_to_le16(s->beacon_interval);
+ cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid);
+ cmd->inactivity_timeout = cpu_to_le16(s->inactivity_timeout);
+ cmd->smps_mode = s->smps_mode;
+ cmd->p2p_ctwindow = s->p2p_ctwindow;
+ cmd->p2p_opp_ps = s->p2p_opp_ps;
+ cmd->pbss = s->pbss;
+ cmd->ht_required = s->ht_required;
+ cmd->vht_required = s->vht_required;

if (s->ssid && s->ssid_len > 0 && s->ssid_len <= IEEE80211_MAX_SSID_LEN)
qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, s->ssid,
s->ssid_len);

- qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_BCN_PERIOD,
- s->beacon_interval);
- qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_DTIM, s->dtim_period);
-
qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
qchan->hdr.len = cpu_to_le16(sizeof(*qchan) -
@@ -215,26 +222,25 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
qchan->hw_value = cpu_to_le16(
ieee80211_frequency_to_channel(chandef->chan->center_freq));

- memset(&aen, 0, sizeof(aen));
- aen.auth_type = s->auth_type;
- aen.privacy = !!s->privacy;
- aen.mfp = 0;
- aen.wpa_versions = cpu_to_le32(s->crypto.wpa_versions);
- aen.cipher_group = cpu_to_le32(s->crypto.cipher_group);
- aen.n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise);
+ aen = &cmd->aen;
+ aen->auth_type = s->auth_type;
+ aen->privacy = !!s->privacy;
+ aen->mfp = 0;
+ aen->wpa_versions = cpu_to_le32(s->crypto.wpa_versions);
+ aen->cipher_group = cpu_to_le32(s->crypto.cipher_group);
+ aen->n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise);
for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
- aen.ciphers_pairwise[i] =
- cpu_to_le32(s->crypto.ciphers_pairwise[i]);
- aen.n_akm_suites = cpu_to_le32(s->crypto.n_akm_suites);
+ aen->ciphers_pairwise[i] =
+ cpu_to_le32(s->crypto.ciphers_pairwise[i]);
+ aen->n_akm_suites = cpu_to_le32(s->crypto.n_akm_suites);
for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
- aen.akm_suites[i] = cpu_to_le32(s->crypto.akm_suites[i]);
- aen.control_port = s->crypto.control_port;
- aen.control_port_no_encrypt =s->crypto.control_port_no_encrypt;
- aen.control_port_ethertype =
+ aen->akm_suites[i] = cpu_to_le32(s->crypto.akm_suites[i]);
+ aen->control_port = s->crypto.control_port;
+ aen->control_port_no_encrypt = s->crypto.control_port_no_encrypt;
+ aen->control_port_ethertype =
cpu_to_le16(be16_to_cpu(s->crypto.control_port_ethertype));

- qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen,
- sizeof(aen));
+ qtnf_bus_lock(vif->mac->bus);

ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);

diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index fb88f3e..6814254 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -132,6 +132,24 @@ struct qlink_chandef {
u8 rsvd[3];
} __packed;

+#define QLINK_MAX_NR_CIPHER_SUITES 5
+#define QLINK_MAX_NR_AKM_SUITES 2
+
+struct qlink_auth_encr {
+ __le32 wpa_versions;
+ __le32 cipher_group;
+ __le32 n_ciphers_pairwise;
+ __le32 ciphers_pairwise[QLINK_MAX_NR_CIPHER_SUITES];
+ __le32 n_akm_suites;
+ __le32 akm_suites[QLINK_MAX_NR_AKM_SUITES];
+ __le16 control_port_ethertype;
+ u8 auth_type;
+ u8 privacy;
+ u8 mfp;
+ u8 control_port;
+ u8 control_port_no_encrypt;
+} __packed;
+
/* QLINK Command messages related definitions
*/

@@ -521,6 +539,46 @@ struct qlink_cmd_chan_switch {
u8 beacon_count;
} __packed;

+/**
+ * enum qlink_hidden_ssid - values for %NL80211_ATTR_HIDDEN_SSID
+ *
+ * Refer to &enum nl80211_hidden_ssid
+ */
+enum qlink_hidden_ssid {
+ QLINK_HIDDEN_SSID_NOT_IN_USE,
+ QLINK_HIDDEN_SSID_ZERO_LEN,
+ QLINK_HIDDEN_SSID_ZERO_CONTENTS
+};
+
+/**
+ * struct qlink_cmd_config_ap - data for QLINK_CMD_CONFIG_AP command
+ *
+ * @beacon_interval: beacon interval
+ * @inactivity_timeout: station's inactivity period in seconds
+ * @dtim_period: DTIM period
+ * @hidden_ssid: whether to hide the SSID, one of &enum qlink_hidden_ssid
+ * @smps_mode: SMPS mode
+ * @ht_required: stations must support HT
+ * @vht_required: stations must support VHT
+ * @aen: encryption info
+ * @info: variable configurations
+ */
+struct qlink_cmd_config_ap {
+ struct qlink_cmd chdr;
+ __le16 beacon_interval;
+ __le16 inactivity_timeout;
+ u8 dtim_period;
+ u8 hidden_ssid;
+ u8 smps_mode;
+ u8 p2p_ctwindow;
+ u8 p2p_opp_ps;
+ u8 pbss;
+ u8 ht_required;
+ u8 vht_required;
+ struct qlink_auth_encr aen;
+ u8 info[0];
+} __packed;
+
/* QLINK Command Responses messages related definitions
*/

@@ -881,8 +939,6 @@ enum qlink_tlv_id {
QTN_TLV_ID_RTS_THRESH = 0x0202,
QTN_TLV_ID_SRETRY_LIMIT = 0x0203,
QTN_TLV_ID_LRETRY_LIMIT = 0x0204,
- QTN_TLV_ID_BCN_PERIOD = 0x0205,
- QTN_TLV_ID_DTIM = 0x0206,
QTN_TLV_ID_REG_RULE = 0x0207,
QTN_TLV_ID_CHANNEL = 0x020F,
QTN_TLV_ID_COVERAGE_CLASS = 0x0213,
@@ -1072,24 +1128,6 @@ struct qlink_tlv_channel {
u8 rsvd[2];
} __packed;

-#define QLINK_MAX_NR_CIPHER_SUITES 5
-#define QLINK_MAX_NR_AKM_SUITES 2
-
-struct qlink_auth_encr {
- __le32 wpa_versions;
- __le32 cipher_group;
- __le32 n_ciphers_pairwise;
- __le32 ciphers_pairwise[QLINK_MAX_NR_CIPHER_SUITES];
- __le32 n_akm_suites;
- __le32 akm_suites[QLINK_MAX_NR_AKM_SUITES];
- __le16 control_port_ethertype;
- u8 auth_type;
- u8 privacy;
- u8 mfp;
- u8 control_port;
- u8 control_port_no_encrypt;
-} __packed;
-
struct qlink_chan_stats {
__le32 chan_num;
__le32 cca_tx;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
index 3c1db5b..63a74b2 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
@@ -127,3 +127,16 @@ void qlink_chandef_q2cfg(struct wiphy *wiphy,
break;
}
}
+
+enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val)
+{
+ switch (nl_val) {
+ case NL80211_HIDDEN_SSID_ZERO_LEN:
+ return QLINK_HIDDEN_SSID_ZERO_LEN;
+ case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
+ return QLINK_HIDDEN_SSID_ZERO_CONTENTS;
+ case NL80211_HIDDEN_SSID_NOT_IN_USE:
+ default:
+ return QLINK_HIDDEN_SSID_NOT_IN_USE;
+ }
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
index 5e49a8a..416f11d 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -66,5 +66,6 @@ u8 qlink_chan_width_mask_to_nl(u16 qlink_mask);
void qlink_chandef_q2cfg(struct wiphy *wiphy,
const struct qlink_chandef *qch,
struct cfg80211_chan_def *chdef);
+enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val);

#endif /* _QTN_FMAC_QLINK_UTIL_H_ */
--
2.9.5

2017-08-25 02:31:04

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 18/27] qtnfmac: use per-band HT/VHT info from wireless device

From: Igor Mitsyanko <[email protected]>

HT/VHT capabilities must be reported per each band supported on a radio,
not for all bands on a radio. Furthermore, driver better not assume
any capabilities and just use whetever is reported by device itself.

To support this, convert "get channels" command into "get band info"
command. Difference is that it may also carry HT/VHT capabilities along
with channels information.

While at it, also add "num_bitrates" field to "get band info" command,
for future use.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 30 +--------
drivers/net/wireless/quantenna/qtnfmac/commands.c | 77 +++++++++++++++++++----
drivers/net/wireless/quantenna/qtnfmac/commands.h | 4 +-
drivers/net/wireless/quantenna/qtnfmac/core.c | 3 +-
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 29 +++++----
5 files changed, 84 insertions(+), 59 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 5ee3345..28612da 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -811,8 +811,7 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
if (!wiphy->bands[band])
continue;

- ret = qtnf_cmd_get_mac_chan_info(mac,
- wiphy->bands[band]);
+ ret = qtnf_cmd_band_info_get(mac, wiphy->bands[band]);
if (ret)
pr_err("failed to get chan info for mac %u band %u\n",
mac_idx, band);
@@ -820,33 +819,6 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
}
}

-void qtnf_band_setup_htvht_caps(struct qtnf_mac_info *macinfo,
- struct ieee80211_supported_band *band)
-{
- struct ieee80211_sta_ht_cap *ht_cap;
- struct ieee80211_sta_vht_cap *vht_cap;
-
- ht_cap = &band->ht_cap;
- ht_cap->ht_supported = true;
- memcpy(&ht_cap->cap, &macinfo->ht_cap.cap_info,
- sizeof(u16));
- ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
- ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
- memcpy(&ht_cap->mcs, &macinfo->ht_cap.mcs,
- sizeof(ht_cap->mcs));
-
- if (macinfo->phymode_cap & QLINK_PHYMODE_AC) {
- vht_cap = &band->vht_cap;
- vht_cap->vht_supported = true;
- memcpy(&vht_cap->cap,
- &macinfo->vht_cap.vht_cap_info, sizeof(u32));
- /* Update MCS support for VHT */
- memcpy(&vht_cap->vht_mcs,
- &macinfo->vht_cap.supp_mcs,
- sizeof(struct ieee80211_vht_mcs_info));
- }
-}
-
struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus)
{
struct wiphy *wiphy;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index e1f77e4..065a93f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1113,19 +1113,50 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac,
sizeof(mac_info->vht_cap));
}

+static void qtnf_cmd_resp_band_fill_htcap(const u8 *info,
+ struct ieee80211_sta_ht_cap *bcap)
+{
+ const struct ieee80211_ht_cap *ht_cap =
+ (const struct ieee80211_ht_cap *)info;
+
+ bcap->ht_supported = true;
+ bcap->cap = le16_to_cpu(ht_cap->cap_info);
+ bcap->ampdu_factor =
+ ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR;
+ bcap->ampdu_density =
+ (ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >>
+ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
+ memcpy(&bcap->mcs, &ht_cap->mcs, sizeof(bcap->mcs));
+}
+
+static void qtnf_cmd_resp_band_fill_vhtcap(const u8 *info,
+ struct ieee80211_sta_vht_cap *bcap)
+{
+ const struct ieee80211_vht_cap *vht_cap =
+ (const struct ieee80211_vht_cap *)info;
+
+ bcap->vht_supported = true;
+ bcap->cap = le32_to_cpu(vht_cap->vht_cap_info);
+ memcpy(&bcap->vht_mcs, &vht_cap->supp_mcs, sizeof(bcap->vht_mcs));
+}
+
static int
-qtnf_cmd_resp_fill_channels_info(struct ieee80211_supported_band *band,
- struct qlink_resp_get_chan_info *resp,
- size_t payload_len)
+qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
+ struct qlink_resp_band_info_get *resp,
+ size_t payload_len)
{
u16 tlv_type;
size_t tlv_len;
+ size_t tlv_dlen;
const struct qlink_tlv_hdr *tlv;
const struct qlink_tlv_channel *qchan;
struct ieee80211_channel *chan;
unsigned int chidx = 0;
u32 qflags;

+ memset(&band->ht_cap, 0, sizeof(band->ht_cap));
+ memset(&band->vht_cap, 0, sizeof(band->vht_cap));
+
if (band->channels) {
if (band->n_channels == resp->num_chans) {
memset(band->channels, 0,
@@ -1153,7 +1184,8 @@ qtnf_cmd_resp_fill_channels_info(struct ieee80211_supported_band *band,

while (payload_len >= sizeof(*tlv)) {
tlv_type = le16_to_cpu(tlv->type);
- tlv_len = le16_to_cpu(tlv->len) + sizeof(*tlv);
+ tlv_dlen = le16_to_cpu(tlv->len);
+ tlv_len = tlv_dlen + sizeof(*tlv);

if (tlv_len > payload_len) {
pr_warn("malformed TLV 0x%.2X; LEN: %zu\n",
@@ -1239,13 +1271,32 @@ qtnf_cmd_resp_fill_channels_info(struct ieee80211_supported_band *band,
chan->hw_value, chan->flags, chan->max_power,
chan->max_reg_power);
break;
+ case WLAN_EID_HT_CAPABILITY:
+ if (unlikely(tlv_dlen !=
+ sizeof(struct ieee80211_ht_cap))) {
+ pr_err("bad HTCAP TLV len %zu\n", tlv_dlen);
+ goto error_ret;
+ }
+
+ qtnf_cmd_resp_band_fill_htcap(tlv->val, &band->ht_cap);
+ break;
+ case WLAN_EID_VHT_CAPABILITY:
+ if (unlikely(tlv_dlen !=
+ sizeof(struct ieee80211_vht_cap))) {
+ pr_err("bad VHTCAP TLV len %zu\n", tlv_dlen);
+ goto error_ret;
+ }
+
+ qtnf_cmd_resp_band_fill_vhtcap(tlv->val,
+ &band->vht_cap);
+ break;
default:
pr_warn("unknown TLV type: %#x\n", tlv_type);
break;
}

payload_len -= tlv_len;
- tlv = (struct qlink_tlv_hdr *)((u8 *)tlv + tlv_len);
+ tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_dlen);
}

if (payload_len) {
@@ -1467,13 +1518,13 @@ int qtnf_cmd_get_hw_info(struct qtnf_bus *bus)
return ret;
}

-int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
- struct ieee80211_supported_band *band)
+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_chans_info_get *cmd;
- struct qlink_resp_get_chan_info *resp;
+ struct qlink_cmd_band_info_get *cmd;
+ struct qlink_resp_band_info_get *resp;
u16 res_code = QLINK_CMD_RESULT_OK;
int ret = 0;
u8 qband;
@@ -1493,12 +1544,12 @@ int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
}

cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
- QLINK_CMD_CHANS_INFO_GET,
+ QLINK_CMD_BAND_INFO_GET,
sizeof(*cmd));
if (!cmd_skb)
return -ENOMEM;

- cmd = (struct qlink_cmd_chans_info_get *)cmd_skb->data;
+ cmd = (struct qlink_cmd_band_info_get *)cmd_skb->data;
cmd->band = qband;

qtnf_bus_lock(mac->bus);
@@ -1515,7 +1566,7 @@ int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
goto out;
}

- resp = (struct qlink_resp_get_chan_info *)resp_skb->data;
+ resp = (struct qlink_resp_band_info_get *)resp_skb->data;
if (resp->band != qband) {
pr_err("MAC%u: reply band %u != cmd band %u\n", mac->macid,
resp->band, qband);
@@ -1523,7 +1574,7 @@ int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
goto out;
}

- ret = qtnf_cmd_resp_fill_channels_info(band, resp, info_len);
+ ret = qtnf_cmd_resp_fill_band_info(band, resp, info_len);

out:
qtnf_bus_unlock(mac->bus);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index e87c4a4..d6fe3cc 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -30,8 +30,8 @@ int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype,
int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
enum nl80211_iftype iftype, u8 *mac_addr);
int qtnf_cmd_send_del_intf(struct qtnf_vif *vif);
-int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
- struct ieee80211_supported_band *band);
+int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
+ struct ieee80211_supported_band *band);
int qtnf_cmd_send_regulatory_config(struct qtnf_wmac *mac, const char *alpha2);
int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
const struct cfg80211_ap_settings *s);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c
index 5e60180..b96231e 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -171,7 +171,7 @@ static int qtnf_mac_init_single_band(struct wiphy *wiphy,

wiphy->bands[band]->band = band;

- ret = qtnf_cmd_get_mac_chan_info(mac, wiphy->bands[band]);
+ ret = qtnf_cmd_band_info_get(mac, wiphy->bands[band]);
if (ret) {
pr_err("MAC%u: band %u: failed to get chans info: %d\n",
mac->macid, band, ret);
@@ -179,7 +179,6 @@ static int qtnf_mac_init_single_band(struct wiphy *wiphy,
}

qtnf_band_init_rates(wiphy->bands[band]);
- qtnf_band_setup_htvht_caps(&mac->macinfo, wiphy->bands[band]);

return 0;
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 7b313d3..de0e5b9 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -159,11 +159,12 @@ struct qlink_auth_encr {
* Commands are QLINK messages of type @QLINK_MSG_TYPE_CMD, sent by driver to
* wireless network device for processing. Device is expected to send back a
* reply message of type &QLINK_MSG_TYPE_CMDRSP, containing at least command
- * execution status (one of &enum qlink_cmd_result) at least. Reply message
+ * execution status (one of &enum qlink_cmd_result). Reply message
* may also contain data payload specific to the command type.
*
- * @QLINK_CMD_CHANS_INFO_GET: for the specified MAC and specified band, get
- * number of operational channels and information on each of the channel.
+ * @QLINK_CMD_BAND_INFO_GET: for the specified MAC and specified band, get
+ * the band's description including number of operational channels and
+ * info on each channel, HT/VHT capabilities, supported rates etc.
* This command is generic to a specified MAC, interface index must be set
* to QLINK_VIFID_RSVD in command header.
* @QLINK_CMD_REG_NOTIFY: notify device about regulatory domain change. This
@@ -185,7 +186,7 @@ enum qlink_cmd_type {
QLINK_CMD_CHANGE_INTF = 0x0017,
QLINK_CMD_UPDOWN_INTF = 0x0018,
QLINK_CMD_REG_NOTIFY = 0x0019,
- QLINK_CMD_CHANS_INFO_GET = 0x001A,
+ QLINK_CMD_BAND_INFO_GET = 0x001A,
QLINK_CMD_CHAN_SWITCH = 0x001B,
QLINK_CMD_CHAN_GET = 0x001C,
QLINK_CMD_CONFIG_AP = 0x0020,
@@ -468,11 +469,11 @@ enum qlink_band {
};

/**
- * struct qlink_cmd_chans_info_get - data for QLINK_CMD_CHANS_INFO_GET command
+ * struct qlink_cmd_band_info_get - data for QLINK_CMD_BAND_INFO_GET command
*
- * @band: a PHY band for which channels info is needed, one of @enum qlink_band
+ * @band: a PHY band for which information is queried, one of @enum qlink_band
*/
-struct qlink_cmd_chans_info_get {
+struct qlink_cmd_band_info_get {
struct qlink_cmd chdr;
u8 band;
} __packed;
@@ -721,17 +722,19 @@ struct qlink_resp_get_sta_info {
} __packed;

/**
- * struct qlink_resp_get_chan_info - response for QLINK_CMD_CHANS_INFO_GET cmd
+ * struct qlink_resp_band_info_get - response for QLINK_CMD_BAND_INFO_GET cmd
*
- * @band: frequency band to which channels belong to, one of @enum qlink_band.
- * @num_chans: total number of channels info data contained in reply data.
- * @info: variable-length channels info.
+ * @band: frequency band that the response describes, one of @enum qlink_band.
+ * @num_chans: total number of channels info TLVs contained in reply.
+ * @num_bitrates: total number of bitrate TLVs contained in reply.
+ * @info: variable-length info portion.
*/
-struct qlink_resp_get_chan_info {
+struct qlink_resp_band_info_get {
struct qlink_resp rhdr;
u8 band;
u8 num_chans;
- u8 rsvd[2];
+ u8 num_bitrates;
+ u8 rsvd[1];
u8 info[0];
} __packed;

--
2.9.5

2017-08-30 12:07:32

by Sergey Matyukevich

[permalink] [raw]
Subject: Re: [PATCH 21/27] qtnfmac: extend "IE set" TLV to include frame type info

> - if (tlv_full_len > payload_len) {
> - pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n",
> - mac->macid, vif->vifid, tlv_type,
> - tlv_value_len);
> + if (tlv_full_len > payload_len)
> return -EINVAL;
> - }

Why drop this sanity check ?

> if (tlv_type == QTN_TLV_ID_IE_SET) {
> - sinfo.assoc_req_ies = tlv->val;
> - sinfo.assoc_req_ies_len = tlv_value_len;
> + const struct qlink_tlv_ie_set *ie_set;
> + unsigned int ie_len;
> +
> + if (payload_len < sizeof(*ie_set))
> + return -EINVAL;
> +
> + ie_set = (const struct qlink_tlv_ie_set *)tlv;
> + ie_len = tlv_value_len -
> + (sizeof(*ie_set) - sizeof(ie_set->hdr));
> +
> + if (ie_set->type == QLINK_IE_SET_ASSOC_REQ && ie_len) {
> + sinfo.assoc_req_ies = ie_set->ie_data;
> + sinfo.assoc_req_ies_len = ie_len;
> + }
> }

Does it make sense to keep QTN_TLV_ID_IE_SET here at all ?
Maybe replace it completely by qlink_tlv_ie_set with
QLINK_IE_SET_ASSOC_REQ type ? Also see the comment below
for the similar snippet in qtnf_event_handle_scan_results.

...

> - if (tlv_full_len > payload_len) {
> - pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n",
> - vif->mac->macid, vif->vifid, tlv_type,
> - tlv_value_len);
> + if (tlv_full_len > payload_len)
> return -EINVAL;
> - }

ditto

...

> if (tlv_type == QTN_TLV_ID_IE_SET) {
> - ies = tlv->val;
> - ies_len = tlv_value_len;
> + const struct qlink_tlv_ie_set *ie_set;
> + unsigned int ie_len;
> +
> + if (payload_len < sizeof(*ie_set))
> + return -EINVAL;
> +
> + ie_set = (const struct qlink_tlv_ie_set *)tlv;
> + ie_len = tlv_value_len -
> + (sizeof(*ie_set) - sizeof(ie_set->hdr));
> +
> + if (ie_len) {
> + ies = ie_set->ie_data;
> + ies_len = ie_len;
> + }
> }
> }

Two points here. First, it looks like there is a problem here inherited
from the existing implementation. We go through payload, but in fact we
pass to cfg80211_inform_bss only the last QTN_TLV_ID_IE_SET element.
Second, it looks like QTN_TLV_ID_IE_SET here should be treated in
the same way as in qtnf_event_handle_sta_assoc, to avoid confusion.
In other words, either we use only QTN_TLV_ID_IE_SET in both cases,
or switch to specific qlink_tlv_ie_set elements.

Thoughts ? Comments ?

Regards,
Sergey

2017-08-25 02:31:09

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 23/27] qtnfmac: convert "Append IEs" command to QTN_TLV_ID_IE_SET usage

From: Igor Mitsyanko <[email protected]>

Data contained within "Append IEs" command (QLINK_CMD_MGMT_SET_APPIE)
duplicates QTN_TLV_ID_IE_SET TLV. Conver the command to use that TLV
instead.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 12 ++++++------
drivers/net/wireless/quantenna/qtnfmac/commands.c | 17 ++++-------------
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 15 ---------------
3 files changed, 10 insertions(+), 34 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 3faac7a..2497493 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -212,10 +212,10 @@ static int qtnf_mgmt_set_appie(struct qtnf_vif *vif,
int ret = 0;

if (!info->beacon_ies || !info->beacon_ies_len) {
- ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_MGMT_FRAME_BEACON,
+ ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_IE_SET_BEACON_IES,
NULL, 0);
} else {
- ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_MGMT_FRAME_BEACON,
+ ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_IE_SET_BEACON_IES,
info->beacon_ies,
info->beacon_ies_len);
}
@@ -225,11 +225,11 @@ static int qtnf_mgmt_set_appie(struct qtnf_vif *vif,

if (!info->proberesp_ies || !info->proberesp_ies_len) {
ret = qtnf_cmd_send_mgmt_set_appie(vif,
- QLINK_MGMT_FRAME_PROBE_RESP,
+ QLINK_IE_SET_PROBE_RESP_IES,
NULL, 0);
} else {
ret = qtnf_cmd_send_mgmt_set_appie(vif,
- QLINK_MGMT_FRAME_PROBE_RESP,
+ QLINK_IE_SET_PROBE_RESP_IES,
info->proberesp_ies,
info->proberesp_ies_len);
}
@@ -239,11 +239,11 @@ static int qtnf_mgmt_set_appie(struct qtnf_vif *vif,

if (!info->assocresp_ies || !info->assocresp_ies_len) {
ret = qtnf_cmd_send_mgmt_set_appie(vif,
- QLINK_MGMT_FRAME_ASSOC_RESP,
+ QLINK_IE_SET_ASSOC_RESP,
NULL, 0);
} else {
ret = qtnf_cmd_send_mgmt_set_appie(vif,
- QLINK_MGMT_FRAME_ASSOC_RESP,
+ QLINK_IE_SET_ASSOC_RESP,
info->assocresp_ies,
info->assocresp_ies_len);
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index cc37114..2e30c26 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -394,11 +394,10 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
const u8 *buf, size_t len)
{
struct sk_buff *cmd_skb;
- struct qlink_cmd_mgmt_append_ie *cmd;
u16 res_code = QLINK_CMD_RESULT_OK;
int ret;

- if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
+ if (len > QTNF_MAX_CMD_BUF_SIZE) {
pr_warn("VIF%u.%u: %u frame is too big: %zu\n", vif->mac->macid,
vif->vifid, frame_type, len);
return -E2BIG;
@@ -406,21 +405,13 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,

cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_MGMT_SET_APPIE,
- sizeof(*cmd));
+ sizeof(struct qlink_cmd));
if (unlikely(!cmd_skb))
return -ENOMEM;

- qtnf_bus_lock(vif->mac->bus);
-
- cmd = (struct qlink_cmd_mgmt_append_ie *)cmd_skb->data;
- cmd->type = frame_type;
- cmd->flags = 0;
+ qtnf_cmd_tlv_ie_set_add(cmd_skb, frame_type, buf, len);

- /* If len == 0 then IE buf for specified frame type
- * should be cleared on EP.
- */
- if (len && buf)
- qtnf_cmd_skb_put_buffer(cmd_skb, buf, len);
+ qtnf_bus_lock(vif->mac->bus);

ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);

diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index e584d2e..eba73fd 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -290,21 +290,6 @@ struct qlink_cmd_mgmt_frame_tx {
} __packed;

/**
- * struct qlink_cmd_mgmt_append_ie - data for QLINK_CMD_MGMT_SET_APPIE command
- *
- * @type: type of MGMT frame to appent requested IEs to, one of
- * &enum qlink_mgmt_frame_type.
- * @flags: for future use.
- * @ie_data: IEs data to append.
- */
-struct qlink_cmd_mgmt_append_ie {
- struct qlink_cmd chdr;
- u8 type;
- u8 flags;
- u8 ie_data[0];
-} __packed;
-
-/**
* struct qlink_cmd_get_sta_info - data for QLINK_CMD_GET_STA_INFO command
*
* @sta_addr: MAC address of the STA statistics is requested for.
--
2.9.5

2017-08-25 02:30:57

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 12/27] qtnfmac: let wifi card handle channel switch request to the same chan

From: Igor Mitsyanko <[email protected]>

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 5 -----
1 file changed, 5 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 501ece3..062189b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -760,11 +760,6 @@ static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev,
return -EINVAL;
}

- if (cfg80211_chandef_identical(&params->chandef, &mac->chandef)) {
- pr_err("%s: switch request to the same channel\n", dev->name);
- return -EALREADY;
- }
-
ret = qtnf_cmd_send_chan_switch(mac, params);
if (ret)
pr_warn("%s: failed to switch to channel (%u)\n",
--
2.9.5

2017-08-25 02:30:50

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 04/27] qtnfmac: do not cache AP settings in driver structures

From: Igor Mitsyanko <[email protected]>

Cached AP setings are passed to WiFi card right away and never used.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 17 +--------
drivers/net/wireless/quantenna/qtnfmac/commands.c | 46 +++++++++++------------
drivers/net/wireless/quantenna/qtnfmac/commands.h | 3 +-
3 files changed, 25 insertions(+), 41 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 8bfe61d..f6eb681 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -267,7 +267,6 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev,
{
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
struct qtnf_wmac *mac = wiphy_priv(wiphy);
- struct qtnf_bss_config *bss_cfg;
int ret;

if (!cfg80211_chandef_identical(&mac->chandef, &settings->chandef)) {
@@ -278,21 +277,7 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev,
settings->chandef.chan->center_freq);
}

- bss_cfg = &vif->bss_cfg;
- memset(bss_cfg, 0, sizeof(*bss_cfg));
-
- bss_cfg->bcn_period = settings->beacon_interval;
- bss_cfg->dtim = settings->dtim_period;
- bss_cfg->auth_type = settings->auth_type;
- bss_cfg->privacy = settings->privacy;
-
- bss_cfg->ssid_len = settings->ssid_len;
- memcpy(&bss_cfg->ssid, settings->ssid, bss_cfg->ssid_len);
-
- memcpy(&bss_cfg->crypto, &settings->crypto,
- sizeof(struct cfg80211_crypto_settings));
-
- ret = qtnf_cmd_send_config_ap(vif);
+ ret = qtnf_cmd_send_config_ap(vif, settings);
if (ret) {
pr_err("VIF%u.%u: failed to push config to FW\n",
vif->mac->macid, vif->vifid);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 806b88b..b498019 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -181,10 +181,10 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif)
return ret;
}

-int qtnf_cmd_send_config_ap(struct qtnf_vif *vif)
+int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
+ const struct cfg80211_ap_settings *s)
{
struct sk_buff *cmd_skb;
- struct qtnf_bss_config *bss_cfg = &vif->bss_cfg;
struct cfg80211_chan_def *chandef = &vif->mac->chandef;
struct qlink_tlv_channel *qchan;
struct qlink_auth_encr aen;
@@ -200,11 +200,13 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif)

qtnf_bus_lock(vif->mac->bus);

- qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, bss_cfg->ssid,
- bss_cfg->ssid_len);
+ if (s->ssid && s->ssid_len > 0 && s->ssid_len <= IEEE80211_MAX_SSID_LEN)
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, s->ssid,
+ s->ssid_len);
+
qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_BCN_PERIOD,
- bss_cfg->bcn_period);
- qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_DTIM, bss_cfg->dtim);
+ s->beacon_interval);
+ qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_DTIM, s->dtim_period);

qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
@@ -214,26 +216,22 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif)
ieee80211_frequency_to_channel(chandef->chan->center_freq));

memset(&aen, 0, sizeof(aen));
- aen.auth_type = bss_cfg->auth_type;
- aen.privacy = !!bss_cfg->privacy;
- aen.mfp = bss_cfg->mfp;
- aen.wpa_versions = cpu_to_le32(bss_cfg->crypto.wpa_versions);
- aen.cipher_group = cpu_to_le32(bss_cfg->crypto.cipher_group);
- aen.n_ciphers_pairwise = cpu_to_le32(
- bss_cfg->crypto.n_ciphers_pairwise);
+ aen.auth_type = s->auth_type;
+ aen.privacy = !!s->privacy;
+ aen.mfp = 0;
+ aen.wpa_versions = cpu_to_le32(s->crypto.wpa_versions);
+ aen.cipher_group = cpu_to_le32(s->crypto.cipher_group);
+ aen.n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise);
for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
- aen.ciphers_pairwise[i] = cpu_to_le32(
- bss_cfg->crypto.ciphers_pairwise[i]);
- aen.n_akm_suites = cpu_to_le32(
- bss_cfg->crypto.n_akm_suites);
+ aen.ciphers_pairwise[i] =
+ cpu_to_le32(s->crypto.ciphers_pairwise[i]);
+ aen.n_akm_suites = cpu_to_le32(s->crypto.n_akm_suites);
for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
- aen.akm_suites[i] = cpu_to_le32(
- bss_cfg->crypto.akm_suites[i]);
- aen.control_port = bss_cfg->crypto.control_port;
- aen.control_port_no_encrypt =
- bss_cfg->crypto.control_port_no_encrypt;
- aen.control_port_ethertype = cpu_to_le16(be16_to_cpu(
- bss_cfg->crypto.control_port_ethertype));
+ aen.akm_suites[i] = cpu_to_le32(s->crypto.akm_suites[i]);
+ aen.control_port = s->crypto.control_port;
+ aen.control_port_no_encrypt =s->crypto.control_port_no_encrypt;
+ aen.control_port_ethertype =
+ cpu_to_le16(be16_to_cpu(s->crypto.control_port_ethertype));

qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen,
sizeof(aen));
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h
index e1bcb83..634b057 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -33,7 +33,8 @@ int qtnf_cmd_send_del_intf(struct qtnf_vif *vif);
int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
struct ieee80211_supported_band *band);
int qtnf_cmd_send_regulatory_config(struct qtnf_wmac *mac, const char *alpha2);
-int qtnf_cmd_send_config_ap(struct qtnf_vif *vif);
+int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
+ const struct cfg80211_ap_settings *s);
int qtnf_cmd_send_start_ap(struct qtnf_vif *vif);
int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif);
int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg);
--
2.9.5

2017-08-30 01:48:30

by Igor Mitsyanko

[permalink] [raw]
Subject: Re: [PATCH 14/27] qtnfmac: do not cache CSA chandef info

On 08/29/2017 08:44 AM, Sergey Matyukevich wrote:
> I am ok with removal of CSA chandef info. It was kept mainly to warn
> about channel switch to the frequency that differs from original
> CSA request.
>
>> - if (vif->vifid != 0) {
>> - if (!(mac->status & QTNF_MAC_CSA_ACTIVE))
>> - return -EOPNOTSUPP;
>> -
>> - if (!cfg80211_chandef_identical(&params->chandef,
>> - &mac->csa_chandef))
>> - return -EINVAL;
>> -
>> - return 0;
>> - }
>
>
> This particular CSA_ACTIVE status check was introduced for compatibility with
> hostapd behaviour. Currently hostapd goes through all the virtual interfaces
> and sends CSA for each of them. So the idea was to send CSA for primary
> interface and confirm success for the others. If this snipped is dropped
> then we end up in multiple identical CSA requests queued in firmware.
>
> I suggest to remove chandef_identical check, but to keep the logic for
> secondary virtual interface handling.
>
> Regards,
> Sergey
>

The idea was that driver doesn't have to keep track of this, but instead
it will just forward directly to card, and card will return success for
CSA request to the same channel, because card knows that already.

As a bonus, in case it will ever support virtual concurrent (virtual
interfaces on different physical channels), no changes to driver will be
required.

2017-08-30 08:05:29

by Sergey Matyukevich

[permalink] [raw]
Subject: Re: [PATCH 14/27] qtnfmac: do not cache CSA chandef info

On Tue, Aug 29, 2017 at 06:48:23PM -0700, Igor Mitsyanko wrote:
> On 08/29/2017 08:44 AM, Sergey Matyukevich wrote:
> > I am ok with removal of CSA chandef info. It was kept mainly to warn
> > about channel switch to the frequency that differs from original
> > CSA request.
> >
> > > - if (vif->vifid != 0) {
> > > - if (!(mac->status & QTNF_MAC_CSA_ACTIVE))
> > > - return -EOPNOTSUPP;
> > > -
> > > - if (!cfg80211_chandef_identical(&params->chandef,
> > > - &mac->csa_chandef))
> > > - return -EINVAL;
> > > -
> > > - return 0;
> > > - }
> >
> >
> > This particular CSA_ACTIVE status check was introduced for compatibility with
> > hostapd behaviour. Currently hostapd goes through all the virtual interfaces
> > and sends CSA for each of them. So the idea was to send CSA for primary
> > interface and confirm success for the others. If this snipped is dropped
> > then we end up in multiple identical CSA requests queued in firmware.
> >
> > I suggest to remove chandef_identical check, but to keep the logic for
> > secondary virtual interface handling.
>
> The idea was that driver doesn't have to keep track of this, but instead it
> will just forward directly to card, and card will return success for CSA
> request to the same channel, because card knows that already.
>
> As a bonus, in case it will ever support virtual concurrent (virtual
> interfaces on different physical channels), no changes to driver will be
> required.

If we drop this check from driver, then we have to add similar check into
the firmware for the time being. We should drop subsequent CSA requests
for secondary virtual interfaces.

Regards,
Sergey

2017-08-25 02:31:05

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 19/27] qtnfmac: initialize HT/VHT caps "can override" masks

From: Igor Mitsyanko <[email protected]>

Information on which HT/VHT capabilities can be overridden is reported
per-MAC by wireless device.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 2 ++
drivers/net/wireless/quantenna/qtnfmac/commands.c | 7 ++++---
drivers/net/wireless/quantenna/qtnfmac/core.h | 4 ++--
drivers/net/wireless/quantenna/qtnfmac/qlink.h | 8 ++++----
4 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 28612da..d6780f42 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -913,6 +913,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
wiphy->available_antennas_rx = mac->macinfo.num_rx_chain;

wiphy->max_ap_assoc_sta = mac->macinfo.max_ap_assoc_sta;
+ wiphy->ht_capa_mod_mask = &mac->macinfo.ht_cap_mod_mask;
+ wiphy->vht_capa_mod_mask = &mac->macinfo.vht_cap_mod_mask;

ether_addr_copy(wiphy->perm_addr, mac->macaddr);

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 065a93f..b26cd01 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1108,9 +1108,10 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac,
qlink_chan_width_mask_to_nl(le16_to_cpu(
resp_info->radar_detect_widths));

- memcpy(&mac_info->ht_cap, &resp_info->ht_cap, sizeof(mac_info->ht_cap));
- memcpy(&mac_info->vht_cap, &resp_info->vht_cap,
- sizeof(mac_info->vht_cap));
+ memcpy(&mac_info->ht_cap_mod_mask, &resp_info->ht_cap_mod_mask,
+ sizeof(mac_info->ht_cap_mod_mask));
+ memcpy(&mac_info->vht_cap_mod_mask, &resp_info->vht_cap_mod_mask,
+ sizeof(mac_info->vht_cap_mod_mask));
}

static void qtnf_cmd_resp_band_fill_htcap(const u8 *info,
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 44a2cbb..3e74736 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -103,8 +103,8 @@ struct qtnf_mac_info {
u8 sretry_limit;
u8 coverage_class;
u8 radar_detect_widths;
- struct ieee80211_ht_cap ht_cap;
- struct ieee80211_vht_cap vht_cap;
+ struct ieee80211_ht_cap ht_cap_mod_mask;
+ struct ieee80211_vht_cap vht_cap_mod_mask;
struct ieee80211_iface_limit *limits;
size_t n_limits;
};
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index de0e5b9..a9f410b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -627,8 +627,8 @@ struct qlink_resp {
* specified WMAC).
* @num_tx_chain: Number of transmit chains used by WMAC.
* @num_rx_chain: Number of receive chains used by WMAC.
- * @vht_cap: VHT capabilities.
- * @ht_cap: HT capabilities.
+ * @vht_cap_mod_mask: mask specifying which VHT capabilities can be altered.
+ * @ht_cap_mod_mask: mask specifying which HT capabilities can be altered.
* @bands_cap: wireless bands WMAC can operate in, bitmap of &enum qlink_band.
* @phymode_cap: PHY modes WMAC can operate in, bitmap of &enum qlink_phy_mode.
* @max_ap_assoc_sta: Maximum number of associations supported by WMAC.
@@ -640,8 +640,8 @@ struct qlink_resp_get_mac_info {
u8 dev_mac[ETH_ALEN];
u8 num_tx_chain;
u8 num_rx_chain;
- struct ieee80211_vht_cap vht_cap;
- struct ieee80211_ht_cap ht_cap;
+ struct ieee80211_vht_cap vht_cap_mod_mask;
+ struct ieee80211_ht_cap ht_cap_mod_mask;
u8 bands_cap;
u8 phymode_cap;
__le16 max_ap_assoc_sta;
--
2.9.5

2017-08-25 02:30:59

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 14/27] qtnfmac: do not cache CSA chandef info

From: Igor Mitsyanko <[email protected]>

It is never used for anything useful, and all logic is handled by
either WiFi card or higher layers.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 12 ------------
drivers/net/wireless/quantenna/qtnfmac/commands.c | 2 --
drivers/net/wireless/quantenna/qtnfmac/core.h | 1 -
drivers/net/wireless/quantenna/qtnfmac/event.c | 8 +-------
4 files changed, 1 insertion(+), 22 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index b33c4fc..8542c16 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -736,7 +736,6 @@ qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_csa_settings *params)
{
- struct qtnf_wmac *mac = wiphy_priv(wiphy);
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
int ret;

@@ -744,17 +743,6 @@ static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev,
params->chandef.chan->hw_value, params->count,
params->radar_required, params->block_tx);

- if (vif->vifid != 0) {
- if (!(mac->status & QTNF_MAC_CSA_ACTIVE))
- return -EOPNOTSUPP;
-
- if (!cfg80211_chandef_identical(&params->chandef,
- &mac->csa_chandef))
- return -EINVAL;
-
- return 0;
- }
-
if (!cfg80211_chandef_valid(&params->chandef)) {
pr_err("%s: invalid channel\n", dev->name);
return -EINVAL;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index cfbb636..7a616f9 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2347,8 +2347,6 @@ int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,

switch (res_code) {
case QLINK_CMD_RESULT_OK:
- memcpy(&mac->csa_chandef, &params->chandef,
- sizeof(mac->csa_chandef));
mac->status |= QTNF_MAC_CSA_ACTIVE;
ret = 0;
break;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index aa1a92f..5997915 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -132,7 +132,6 @@ struct qtnf_wmac {
struct qtnf_vif iflist[QTNF_MAX_INTF];
struct cfg80211_scan_request *scan_req;
struct cfg80211_chan_def chandef;
- struct cfg80211_chan_def csa_chandef;
struct mutex mac_lock; /* lock during wmac speicific ops */
struct timer_list scan_timeout;
};
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 7435986..b9ceeed 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -368,13 +368,7 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
mac->macid, chdef.chan->hw_value, chdef.center_freq1,
chdef.center_freq2, chdef.width);

- if (mac->status & QTNF_MAC_CSA_ACTIVE) {
- mac->status &= ~QTNF_MAC_CSA_ACTIVE;
- if (chdef.chan->hw_value != mac->csa_chandef.chan->hw_value)
- pr_warn("unexpected switch to %u during CSA to %u\n",
- chdef.chan->hw_value,
- mac->csa_chandef.chan->hw_value);
- }
+ mac->status &= ~QTNF_MAC_CSA_ACTIVE;

memcpy(&mac->chandef, &chdef, sizeof(mac->chandef));

--
2.9.5

2017-08-25 02:31:00

by Igor Mitsyanko

[permalink] [raw]
Subject: [PATCH 15/27] qtnfmac: remove unused mac::status field

From: Igor Mitsyanko <[email protected]>

It is no longer used.

Signed-off-by: Igor Mitsyanko <[email protected]>
---
drivers/net/wireless/quantenna/qtnfmac/commands.c | 1 -
drivers/net/wireless/quantenna/qtnfmac/core.h | 5 -----
drivers/net/wireless/quantenna/qtnfmac/event.c | 2 --
3 files changed, 8 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 7a616f9..e1f77e4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -2347,7 +2347,6 @@ int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,

switch (res_code) {
case QLINK_CMD_RESULT_OK:
- mac->status |= QTNF_MAC_CSA_ACTIVE;
ret = 0;
break;
case QLINK_CMD_RESULT_ENOTFOUND:
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index 5997915..5234a9e 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -73,10 +73,6 @@ enum qtnf_sta_state {
QTNF_STA_CONNECTED
};

-enum qtnf_mac_status {
- QTNF_MAC_CSA_ACTIVE = BIT(0)
-};
-
struct qtnf_vif {
struct wireless_dev wdev;
u8 bssid[ETH_ALEN];
@@ -126,7 +122,6 @@ struct qtnf_wmac {
u8 macid;
u8 wiphy_registered;
u8 macaddr[ETH_ALEN];
- u32 status;
struct qtnf_bus *bus;
struct qtnf_mac_info macinfo;
struct qtnf_vif iflist[QTNF_MAX_INTF];
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index b9ceeed..db7e475 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -368,8 +368,6 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
mac->macid, chdef.chan->hw_value, chdef.center_freq1,
chdef.center_freq2, chdef.width);

- mac->status &= ~QTNF_MAC_CSA_ACTIVE;
-
memcpy(&mac->chandef, &chdef, sizeof(mac->chandef));

for (i = 0; i < QTNF_MAX_INTF; i++) {
--
2.9.5