[PATCH v2] brcmfmac: Fix a memory leak in error handling path in 'brcmf_cfg80211_attach'
If 'wiphy_new()' fails, we leak 'ops'. Add a new label in the error handling path to free it in such a case. Cc: sta...@vger.kernel.org Fixes: 5c22fb85102a7 ("brcmfmac: add wowl gtk rekeying offload support") Signed-off-by: Christophe JAILLET--- v2: Add CC tag Change prefix --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 2443c71a202f..032d823c53c2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6861,7 +6861,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info)); if (!wiphy) { brcmf_err("Could not allocate wiphy device\n"); - return NULL; + goto ops_out; } memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN); set_wiphy_dev(wiphy, busdev); @@ -7012,6 +7012,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, ifp->vif = NULL; wiphy_out: brcmf_free_wiphy(wiphy); +ops_out: kfree(ops); return NULL; } -- 2.11.0
Re: [RFC] mac80211: support non-data TXQs
On 06/20/2017 02:03 PM, Johannes Berg wrote: From: Johannes BergSome drivers may want to also use the TXQ abstraction with non-data packets, so add a hardware flag to allow this. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 9 +++-- net/mac80211/debugfs.c | 1 + net/mac80211/debugfs_sta.c | 4 +++- net/mac80211/sta_info.c| 15 --- net/mac80211/tx.c | 20 ++-- 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 13c59e6f88d4..b64148c49db0 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1908,7 +1908,7 @@ struct ieee80211_sta { bool support_p2p_ps; u16 max_rc_amsdu_len; - struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; + struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1]; Isn't that a little confusing? Wouldn't it be better to have a separate member for non-data txq and name it accordingly (something like txq_nodata). You have to handle it specially in most cases anyway I guess. With this approach you won't have to replace ARRAY_SIZE(sta->txq) by IEEE80211_NUM_TIDS anywhere. /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); @@ -1942,7 +1942,8 @@ struct ieee80211_tx_control { * * @vif: ieee80211_vif pointer from the add_interface callback. * @sta: station table entry, %NULL for per-vif queue - * @tid: the TID for this queue (unused for per-vif queue) + * @tid: the TID for this queue (unused for per-vif queue), + * %IEEE80211_NUM_TIDS for non-data (if enabled) * @ac: the AC for this queue * @drv_priv: driver private area, sized by hw->txq_data_size * @@ -2141,6 +2142,9 @@ struct ieee80211_txq { *The stack will not do fragmentation. *The callback for @set_frag_threshold should be set as well. * + * @IEEE80211_HW_WANT_NONDATA_TXQ: The driver/hardware wants to have a TXQ + * ( ieee80211_txq) for non-data frames + * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { @@ -2183,6 +2187,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_TX_FRAG_LIST, IEEE80211_HW_REPORTS_LOW_ACK, IEEE80211_HW_SUPPORTS_TX_FRAG, + IEEE80211_HW_WANT_NONDATA_TXQ, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index d40ec17829a9..d754dc9ff56f 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -791,6 +791,7 @@ static const char *hw_flag_names[] = { FLAG(TX_FRAG_LIST), FLAG(REPORTS_LOW_ACK), FLAG(SUPPORTS_TX_FRAG), + FLAG(WANT_NONDATA_TXQ), #undef FLAG }; diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 0f122a554d2e..48984f6cabd9 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -171,7 +171,9 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf, bufsz+buf-p, "tid ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets\n"); - for (i = 0; i < IEEE80211_NUM_TIDS; i++) { + for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { + if (!sta->sta.txq[i]) + continue; txqi = to_txq_info(sta->sta.txq[i]); p += scnprintf(p, bufsz+buf-p, "%d %d %u %u %u %u %u %u %u %u %u\n", diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 0297f544e0cc..8b71960eb2a0 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -112,7 +112,12 @@ static void __cleanup_single_sta(struct sta_info *sta) if (sta->sta.txq[0]) { for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { - struct txq_info *txqi = to_txq_info(sta->sta.txq[i]); + struct txq_info *txqi; + + if (!sta->sta.txq[i]) + continue; + + txqi = to_txq_info(sta->sta.txq[i]); spin_lock_bh(>lock); ieee80211_txq_purge(local, txqi); @@ -384,15 +389,19 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, ewma_signal_init(>rx_stats_avg.chain_signal[i]); if (local->ops->wake_tx_queue) { + int num_queues = IEEE80211_NUM_TIDS; void *txq_data; int size = sizeof(struct txq_info) + ALIGN(hw->txq_data_size, sizeof(void *)); - txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp); + if (ieee80211_hw_check(>hw, WANT_NONDATA_TXQ)) + num_queues++; + + txq_data = kcalloc(num_queues, size, gfp); if (!txq_data)
Re: [PATCH] mac80211: don't look at the PM bit of BAR frames
On 06/08/2017 04:00 AM, Emmanuel Grumbach wrote: When a peer sends a BAR frame with PM bit clear, we should not modify its PM state as madated by the spec in 802.11-20012 10.2.1.2. Signed-off-by: Emmanuel Grumbach--- net/mac80211/rx.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index e48724a6725e..bb1e4bbf55e2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1558,12 +1558,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) */ if (!ieee80211_hw_check(>local->hw, AP_LINK_PS) && !ieee80211_has_morefrags(hdr->frame_control) && + !ieee80211_is_back_req(hdr->frame_control) && BTW latest spec also notes that PSPOLL frame has PM bit reserved too, because it may not result in ACK frame from AP. !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && (rx->sdata->vif.type == NL80211_IFTYPE_AP || rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && - /* PM bit is only checked in frames where it isn't reserved, + /* +* PM bit is only checked in frames where it isn't reserved, * in AP mode it's reserved in non-bufferable management frames * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) +* BAR frames should be ignored as specified in +* IEEE 802.11-2012 10.2.1.2. Comment placement is a little confusing IMO. Maybe move ieee80211_is_back_req() check to this position? */ (!ieee80211_is_mgmt(hdr->frame_control) || ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
Re: [RFC] mac80211: support non-data TXQs
On Tue, 2017-06-20 at 23:03 +0200, Johannes Berg wrote: > From: Johannes Berg> > Some drivers may want to also use the TXQ abstraction with > non-data packets, so add a hardware flag to allow this. Need to replace various ARRAY_SIZE(sta->txq) in ath9k/ath10k by IEEE80211_NUM_TIDS. johannes
[RFC] mac80211: don't put null-data frames on the normal TXQ
From: Johannes BergSince (QoS) NDP frames shouldn't be put into aggregation nor are assigned real sequence numbers, etc. it's better to treat them as non-data packets and not put them on the normal TXQs. Signed-off-by: Johannes Berg --- net/mac80211/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d1cef5ad91ee..726fb3b02a23 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1256,7 +1256,7 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local, return NULL; } else if (!sta) { txq = vif->txq; - } else if (!ieee80211_is_data(hdr->frame_control)) { + } else if (!ieee80211_is_data_present(hdr->frame_control)) { if (!sta->uploaded) return NULL; -- 2.11.0
[RFC] mac80211: support non-data TXQs
From: Johannes BergSome drivers may want to also use the TXQ abstraction with non-data packets, so add a hardware flag to allow this. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 9 +++-- net/mac80211/debugfs.c | 1 + net/mac80211/debugfs_sta.c | 4 +++- net/mac80211/sta_info.c| 15 --- net/mac80211/tx.c | 20 ++-- 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 13c59e6f88d4..b64148c49db0 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1908,7 +1908,7 @@ struct ieee80211_sta { bool support_p2p_ps; u16 max_rc_amsdu_len; - struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; + struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1]; /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); @@ -1942,7 +1942,8 @@ struct ieee80211_tx_control { * * @vif: ieee80211_vif pointer from the add_interface callback. * @sta: station table entry, %NULL for per-vif queue - * @tid: the TID for this queue (unused for per-vif queue) + * @tid: the TID for this queue (unused for per-vif queue), + * %IEEE80211_NUM_TIDS for non-data (if enabled) * @ac: the AC for this queue * @drv_priv: driver private area, sized by hw->txq_data_size * @@ -2141,6 +2142,9 @@ struct ieee80211_txq { * The stack will not do fragmentation. * The callback for @set_frag_threshold should be set as well. * + * @IEEE80211_HW_WANT_NONDATA_TXQ: The driver/hardware wants to have a TXQ + * ( ieee80211_txq) for non-data frames + * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { @@ -2183,6 +2187,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_TX_FRAG_LIST, IEEE80211_HW_REPORTS_LOW_ACK, IEEE80211_HW_SUPPORTS_TX_FRAG, + IEEE80211_HW_WANT_NONDATA_TXQ, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index d40ec17829a9..d754dc9ff56f 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -791,6 +791,7 @@ static const char *hw_flag_names[] = { FLAG(TX_FRAG_LIST), FLAG(REPORTS_LOW_ACK), FLAG(SUPPORTS_TX_FRAG), + FLAG(WANT_NONDATA_TXQ), #undef FLAG }; diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 0f122a554d2e..48984f6cabd9 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -171,7 +171,9 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf, bufsz+buf-p, "tid ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets\n"); - for (i = 0; i < IEEE80211_NUM_TIDS; i++) { + for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { + if (!sta->sta.txq[i]) + continue; txqi = to_txq_info(sta->sta.txq[i]); p += scnprintf(p, bufsz+buf-p, "%d %d %u %u %u %u %u %u %u %u %u\n", diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 0297f544e0cc..8b71960eb2a0 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -112,7 +112,12 @@ static void __cleanup_single_sta(struct sta_info *sta) if (sta->sta.txq[0]) { for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { - struct txq_info *txqi = to_txq_info(sta->sta.txq[i]); + struct txq_info *txqi; + + if (!sta->sta.txq[i]) + continue; + + txqi = to_txq_info(sta->sta.txq[i]); spin_lock_bh(>lock); ieee80211_txq_purge(local, txqi); @@ -384,15 +389,19 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, ewma_signal_init(>rx_stats_avg.chain_signal[i]); if (local->ops->wake_tx_queue) { + int num_queues = IEEE80211_NUM_TIDS; void *txq_data; int size = sizeof(struct txq_info) + ALIGN(hw->txq_data_size, sizeof(void *)); - txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp); + if (ieee80211_hw_check(>hw, WANT_NONDATA_TXQ)) + num_queues++; + + txq_data = kcalloc(num_queues, size, gfp); if (!txq_data) goto free; - for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { + for (i = 0; i < num_queues; i++) { struct txq_info *txq = txq_data + i * size; ieee80211_txq_init(sdata, sta, txq, i); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 3d3e37f29bcb..d1cef5ad91ee 100644 ---
Re: [PATCH 5/8] qtnfmac: enable reporting the current operating channel
On Tue, 2017-06-20 at 23:09 +0300, Sergey Matyukevich wrote: > > > > > + if (sme->channel) { > > > + /* FIXME: need to set proper nl80211_channel_type > > > value */ > > > + cfg80211_chandef_create(, sme->channel, > > > + NL80211_CHAN_HT20); > > > + /* fall-back to minimal safe chandef description */ > > > + if (!cfg80211_chandef_valid()) > > > + cfg80211_chandef_create(, sme- > > > > channel, > > > > > > + NL80211_CHAN_HT20); > > > > > > > This seems odd since you just do the same thing over again? Not > > that I > > could see how it would be invalid anyway. > > The first call of cfg80211_chandef_create will be replaced by proper > chandef calculation based on current h/w channel settings. This piece > is still in work. NL80211_CHAN_HT20 is going to be used as a safe > fallback when channel info turns out to be inconsistent. Yeah, ok. I guess I'd advocate doing that when the code is actually there, but I suppose it doesn't really matter much. johannes
Re: [PATCH 5/8] qtnfmac: enable reporting the current operating channel
> > > + if (sme->channel) { > > + /* FIXME: need to set proper nl80211_channel_type > > value */ > > + cfg80211_chandef_create(, sme->channel, > > + NL80211_CHAN_HT20); > > + /* fall-back to minimal safe chandef description */ > > + if (!cfg80211_chandef_valid()) > > + cfg80211_chandef_create(, sme- > > >channel, > > + NL80211_CHAN_HT20); > > > This seems odd since you just do the same thing over again? Not that I > could see how it would be invalid anyway. The first call of cfg80211_chandef_create will be replaced by proper chandef calculation based on current h/w channel settings. This piece is still in work. NL80211_CHAN_HT20 is going to be used as a safe fallback when channel info turns out to be inconsistent. Regards, Sergey
Re: [PATCH 5/8] qtnfmac: enable reporting the current operating channel
On Tue, 2017-06-20 at 22:55 +0300, Sergey Matyukevich wrote: > + if (sme->channel) { > + /* FIXME: need to set proper nl80211_channel_type > value */ > + cfg80211_chandef_create(, sme->channel, > + NL80211_CHAN_HT20); > + /* fall-back to minimal safe chandef description */ > + if (!cfg80211_chandef_valid()) > + cfg80211_chandef_create(, sme- > >channel, > + NL80211_CHAN_HT20); > This seems odd since you just do the same thing over again? Not that I could see how it would be invalid anyway. johannes
[PATCH 7/8] qtnfmac: implement cfg80211 channel_switch handler
This patch implements cfg80211 channel_switch handler enabling CSA channel-switch procedure. At the moment qtnfmac host driver performs only basic validation of the requested new channel and then sends command to firmware. Beacon IEs are not sent since beacon update is handled by firmware. Signed-off-by: Sergey Matyukevich--- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 60 ++- drivers/net/wireless/quantenna/qtnfmac/commands.c | 55 + drivers/net/wireless/quantenna/qtnfmac/commands.h | 2 + drivers/net/wireless/quantenna/qtnfmac/core.h | 6 +++ drivers/net/wireless/quantenna/qtnfmac/event.c| 8 +++ drivers/net/wireless/quantenna/qtnfmac/qlink.h| 17 +++ 6 files changed, 146 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 3f90f57ed595..097f29189339 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -977,6 +977,59 @@ qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, return 0; } +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; + + pr_info("%s: chan(%u) count(%u) radar(%u) block_tx(%u)\n", dev->name, + 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; + + if (!cfg80211_chandef_identical(>chandef, + >csa_chandef)) + return -EINVAL; + + return 0; + } + + if (!cfg80211_chandef_valid(>chandef)) { + pr_err("%s: invalid channel\n", dev->name); + return -EINVAL; + } + + if (cfg80211_chandef_identical(>chandef, >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", + dev->name, params->chandef.chan->hw_value); + + return ret; +} + static struct cfg80211_ops qtn_cfg80211_ops = { .add_virtual_intf = qtnf_add_virtual_intf, .change_virtual_intf= qtnf_change_virtual_intf, @@ -999,7 +1052,8 @@ static struct cfg80211_ops qtn_cfg80211_ops = { .connect= qtnf_connect, .disconnect = qtnf_disconnect, .dump_survey= qtnf_dump_survey, - .get_channel= qtnf_get_channel + .get_channel= qtnf_get_channel, + .channel_switch = qtnf_channel_switch }; static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in, @@ -1149,6 +1203,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) wiphy->iface_combinations = iface_comb; wiphy->n_iface_combinations = 1; + wiphy->max_num_csa_counters = 2; /* Initialize cipher suits */ wiphy->cipher_suites = qtnf_cipher_suites; @@ -1156,7 +1211,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | - WIPHY_FLAG_AP_UAPSD; + WIPHY_FLAG_AP_UAPSD | + WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2; diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index f44ae71047c3..900159e82bc8 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -2334,3 +2334,58 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, consume_skb(resp_skb); return ret; } + +int
[PATCH 8/8] qtnfmac: implement scan timeout
Userspace tools may hang on scan in the case when scan completion event is not returned by firmware. This patch implements the scan timeout to avoid such situation. Signed-off-by: Sergey Matyukevich--- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 22 ++ drivers/net/wireless/quantenna/qtnfmac/cfg80211.h | 4 drivers/net/wireless/quantenna/qtnfmac/core.c | 2 ++ drivers/net/wireless/quantenna/qtnfmac/core.h | 13 + drivers/net/wireless/quantenna/qtnfmac/event.c| 2 ++ 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 097f29189339..a0ab7d289684 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -741,19 +741,33 @@ qtnf_del_station(struct wiphy *wiphy, struct net_device *dev, return ret; } +static void qtnf_scan_timeout(unsigned long data) +{ + struct qtnf_wmac *mac = (struct qtnf_wmac *)data; + + pr_warn("mac%d scan timed out\n", mac->macid); + qtnf_scan_done(mac, true); +} + static int qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { struct qtnf_wmac *mac = wiphy_priv(wiphy); - int ret; mac->scan_req = request; - ret = qtnf_cmd_send_scan(mac); - if (ret) + if (qtnf_cmd_send_scan(mac)) { pr_err("MAC%u: failed to start scan\n", mac->macid); + mac->scan_req = NULL; + return -EFAULT; + } - return ret; + mac->scan_timeout.data = (unsigned long)mac; + mac->scan_timeout.function = qtnf_scan_timeout; + mod_timer(>scan_timeout, + jiffies + QTNF_SCAN_TIMEOUT_SEC * HZ); + + return 0; } static int diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h index 5bd33124a7c8..eddd040b8869 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h @@ -34,10 +34,14 @@ static inline void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted) .aborted = aborted, }; + qtnf_wmac_lock(mac); + if (mac->scan_req) { cfg80211_scan_done(mac->scan_req, ); mac->scan_req = NULL; } + + qtnf_wmac_unlock(mac); } #endif /* _QTN_FMAC_CFG80211_H_ */ diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index 3d9b217790ed..8ce9c370dc94 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -336,6 +336,8 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus, mac->iflist[i].vifid = i; qtnf_list_init(>iflist[i].sta_list); qtnf_list_init(>iflist[i].vlan_list); + mutex_init(>mac_lock); + init_timer(>scan_timeout); } qtnf_mac_init_primary_intf(mac); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index efe078a6d1d3..883b052ccb01 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -46,6 +46,7 @@ #define QTNF_MAX_EVENT_QUEUE_LEN 255 #define QTNF_DEFAULT_BG_SCAN_PERIOD300 #define QTNF_MAX_BG_SCAN_PERIOD0x +#define QTNF_SCAN_TIMEOUT_SEC 15 #define QTNF_DEF_BSS_PRIORITY 0 #define QTNF_DEF_WDOG_TIMEOUT 5 @@ -161,6 +162,8 @@ struct qtnf_wmac { 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; }; struct qtnf_hw_info { @@ -197,4 +200,14 @@ static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev) return *((void **)netdev_priv(dev)); } +static __always_inline void qtnf_wmac_lock(struct qtnf_wmac *mac) +{ + mutex_lock(>mac_lock); +} + +static __always_inline void qtnf_wmac_unlock(struct qtnf_wmac *mac) +{ + mutex_unlock(>mac_lock); +} + #endif /* _QTN_FMAC_CORE_H_ */ diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index b48d9e8b6935..2c0d6095544f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -345,6 +345,8 @@ qtnf_event_handle_scan_complete(struct qtnf_wmac *mac, return -EINVAL; } + if (timer_pending(>scan_timeout)) + del_timer_sync(>scan_timeout); qtnf_scan_done(mac, le32_to_cpu(status->flags) & QLINK_SCAN_ABORTED); return 0; -- 2.11.0
[PATCH 5/8] qtnfmac: enable reporting the current operating channel
This patch implements all the necessary features needed to keep operating channel information in sync between firmware and driver: - implement cfg80211 qtnf_get_channel handler - implement QLINK_EVENT_FREQ_CHANGE event handling using this event firmware notifies host when operating channel is changed - update qtnf_dump_survey specify current channel in use in survey report - update qtnf_connect pass to firmware channel number rather than frequency Signed-off-by: Sergey Matyukevich--- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 66 ++- drivers/net/wireless/quantenna/qtnfmac/commands.c | 2 +- drivers/net/wireless/quantenna/qtnfmac/event.c| 60 - drivers/net/wireless/quantenna/qtnfmac/qlink.h| 15 +- 4 files changed, 136 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index eb648f02aa40..77afc0fc8c03 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -755,6 +755,7 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) { struct qtnf_vif *vif = qtnf_netdev_get_priv(dev); + struct cfg80211_chan_def chandef; struct qtnf_bss_config *bss_cfg; int ret; @@ -767,9 +768,20 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev, bss_cfg = >bss_cfg; memset(bss_cfg, 0, sizeof(*bss_cfg)); + if (sme->channel) { + /* FIXME: need to set proper nl80211_channel_type value */ + cfg80211_chandef_create(, sme->channel, + NL80211_CHAN_HT20); + /* fall-back to minimal safe chandef description */ + if (!cfg80211_chandef_valid()) + cfg80211_chandef_create(, sme->channel, + NL80211_CHAN_HT20); + + memcpy(_cfg->chandef, , sizeof(bss_cfg->chandef)); + } + bss_cfg->ssid_len = sme->ssid_len; memcpy(_cfg->ssid, sme->ssid, bss_cfg->ssid_len); - bss_cfg->chandef.chan = sme->channel; bss_cfg->auth_type = sme->auth_type; bss_cfg->privacy = sme->privacy; bss_cfg->mfp = sme->mfp; @@ -845,10 +857,15 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, { struct qtnf_wmac *mac = wiphy_priv(wiphy); struct ieee80211_supported_band *sband; + struct cfg80211_chan_def *bss_chandef; struct ieee80211_channel *chan; struct qtnf_chan_stats stats; + struct qtnf_vif *vif; int ret; + vif = qtnf_netdev_get_priv(dev); + bss_chandef = >bss_cfg.chandef; + sband = wiphy->bands[NL80211_BAND_2GHZ]; if (sband && idx >= sband->n_channels) { idx -= sband->n_channels; @@ -867,6 +884,10 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, survey->channel = chan; survey->filled = 0x0; + if (bss_chandef->chan) + if (chan->hw_value == bss_chandef->chan->hw_value) + survey->filled |= SURVEY_INFO_IN_USE; + ret = qtnf_cmd_get_chan_stats(mac, chan->hw_value, ); switch (ret) { case 0: @@ -905,6 +926,46 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, return ret; } +static int +qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, +struct cfg80211_chan_def *chandef) +{ + struct net_device *ndev = wdev->netdev; + struct qtnf_bss_config *bss_cfg; + struct qtnf_vif *vif; + + if (!ndev) + return -ENODEV; + + vif = qtnf_netdev_get_priv(wdev->netdev); + bss_cfg = >bss_cfg; + + 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_VLAN: + /* AP_VLAN: get primary vif and pass through to AP */ + vif = vif->u.vlan.parent; + bss_cfg = >bss_cfg; + 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; + } + + memcpy(chandef, _cfg->chandef, sizeof(*chandef)); + return 0; +} + static struct cfg80211_ops qtn_cfg80211_ops = { .add_virtual_intf = qtnf_add_virtual_intf, .change_virtual_intf= qtnf_change_virtual_intf, @@
[PATCH 6/8] qtnfmac: move current channel info from vif to mac
Wireless cfg80211 core supplies channel settings in cfg80211_ap_settings structure for each BSS in multiple BSS configuration. On the other hand all the virtual interfaces on one radio are using the same PHY settings including channel. Move chandef structure from vif to mac structure in order to mantain the only instance of cfg80211_chan_def structure in qtnf_wmac rather than its multiple copies in qtnf_vif. Signed-off-by: Sergey Matyukevich--- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 39 +++ drivers/net/wireless/quantenna/qtnfmac/commands.c | 6 ++-- drivers/net/wireless/quantenna/qtnfmac/core.h | 2 +- drivers/net/wireless/quantenna/qtnfmac/event.c| 7 ++-- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 77afc0fc8c03..3f90f57ed595 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -408,11 +408,19 @@ 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); struct qtnf_bss_config *bss_cfg; int ret; - bss_cfg = >bss_cfg; + if (!cfg80211_chandef_identical(>chandef, >chandef)) { + memcpy(>chandef, >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); + } + bss_cfg = >bss_cfg; memset(bss_cfg, 0, sizeof(*bss_cfg)); bss_cfg->bcn_period = settings->beacon_interval; @@ -423,8 +431,6 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev, bss_cfg->ssid_len = settings->ssid_len; memcpy(_cfg->ssid, settings->ssid, bss_cfg->ssid_len); - memcpy(_cfg->chandef, >chandef, - sizeof(struct cfg80211_chan_def)); memcpy(_cfg->crypto, >crypto, sizeof(struct cfg80211_crypto_settings)); @@ -755,6 +761,7 @@ 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; struct qtnf_bss_config *bss_cfg; int ret; @@ -777,7 +784,7 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev, cfg80211_chandef_create(, sme->channel, NL80211_CHAN_HT20); - memcpy(_cfg->chandef, , sizeof(bss_cfg->chandef)); + memcpy(>chandef, , sizeof(mac->chandef)); } bss_cfg->ssid_len = sme->ssid_len; @@ -857,14 +864,14 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, { struct qtnf_wmac *mac = wiphy_priv(wiphy); struct ieee80211_supported_band *sband; - struct cfg80211_chan_def *bss_chandef; + struct cfg80211_chan_def *chandef; struct ieee80211_channel *chan; struct qtnf_chan_stats stats; struct qtnf_vif *vif; int ret; vif = qtnf_netdev_get_priv(dev); - bss_chandef = >bss_cfg.chandef; + chandef = >chandef; sband = wiphy->bands[NL80211_BAND_2GHZ]; if (sband && idx >= sband->n_channels) { @@ -884,9 +891,10 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, survey->channel = chan; survey->filled = 0x0; - if (bss_chandef->chan) - if (chan->hw_value == bss_chandef->chan->hw_value) - survey->filled |= SURVEY_INFO_IN_USE; + if (chandef->chan) { + if (chan->hw_value == chandef->chan->hw_value) + survey->filled = SURVEY_INFO_IN_USE; + } ret = qtnf_cmd_get_chan_stats(mac, chan->hw_value, ); switch (ret) { @@ -898,7 +906,7 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, break; } - survey->filled = SURVEY_INFO_TIME | + survey->filled |= SURVEY_INFO_TIME | SURVEY_INFO_TIME_SCAN | SURVEY_INFO_TIME_BUSY | SURVEY_INFO_TIME_RX | @@ -930,15 +938,14 @@ 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_bss_config *bss_cfg; struct qtnf_vif *vif; if
[PATCH 3/8] qtnfmac: implement AP_VLAN iftype support
This patch implements AP_VLAN interface type support enabling the use of dynamic VLAN mode in hostapd. Implementation notes. 1. Passing dynamic VLAN tag to firmware Currently there is no established way to pass VLAN tag assigned to STA by Radius server to wireless driver. It is assumed that hostapd is able to setup all the bridging and tagging on its own. However qtnf firmware needs to know the assigned dynamic VLAN tags in order to perform various internal tasks including group key management, filtering, acceleration, and more. Current implementation makes use of the following workaround. Driver obtains dynamic VLAN tags assigned by Radius server from AP/VLAN interface names: - for primary interfaces: wlanX.Z where X and Z are macid and vlan tag respectively - for MBSS virtual interfaces: wlanX_Y.Z where X, Y, Z are macid, vifid, and vlan tag respectively Such a naming convention can be configured using hostapd vlan_file configuration file. 2. Packet routing to/from AP/VLAN interfaces Firmware operates with tagged packets after dynamic VLAN mode is configured. In particular, packets destined to STAs should be properly tagged before they can be passed to firmware. Packets received from STAs are properly tagged by firmware and then passed to wireless driver. As a result, packet routing to AP/VLAN interfaces is straightforward: it is enough to check VLAN tags. Normally hostapd expects untagged packets from AP/VLAN interfaces. Meanwhile firmware performs tagging using h/w acceleration. That is why it makes sense to avoid untagging packets in driver if they are supposed to by tagged again on host. To enable this behavior a new module parameter 'dyn_vlan_tagged' has been introduced: - dyn_vlan_tagged = 0 (default) In this case untagged packets are sent to and expected from AP/VLAN interfaces. Driver tags/untags packets going to/from firmware. This behaviour is expected by hostapd which is able to create bridges and VLAN interfaces automatically when hostapd is built with CONFIG_FULL_DYNAMIC_VLAN option enabled. - dyn_vlan_tagged = 1 In this case tagged packets are sent to and expected from AP/VLAN interfaces. Hostapd build option CONFIG_FULL_DYNAMIC_VLAN should be disabled. Setup of networking topology on host is left up to the implementers. Signed-off-by: Sergey Matyukevich--- drivers/net/wireless/quantenna/qtnfmac/bus.h | 1 + drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 247 ++--- drivers/net/wireless/quantenna/qtnfmac/commands.c | 28 ++- drivers/net/wireless/quantenna/qtnfmac/core.c | 78 ++- drivers/net/wireless/quantenna/qtnfmac/core.h | 25 ++- .../net/wireless/quantenna/qtnfmac/pearl/pcie.c| 5 + drivers/net/wireless/quantenna/qtnfmac/qlink.h | 10 +- .../net/wireless/quantenna/qtnfmac/qlink_util.c| 3 + drivers/net/wireless/quantenna/qtnfmac/util.c | 74 -- drivers/net/wireless/quantenna/qtnfmac/util.h | 34 ++- 10 files changed, 428 insertions(+), 77 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h b/drivers/net/wireless/quantenna/qtnfmac/bus.h index dda05003d522..819ba3ba0f05 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/bus.h +++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h @@ -52,6 +52,7 @@ struct qtnf_bus { enum qtnf_fw_state fw_state; u32 chip; u32 chiprev; + u8 dyn_vlan_tagged; const struct qtnf_bus_ops *bus_ops; struct qtnf_wmac *mac[QTNF_MAX_MAC]; struct qtnf_qlink_transport trans; diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 825a6334fbfe..e222e8d038d3 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -77,6 +77,35 @@ qtnf_mgmt_stypes[NUM_NL80211_IFTYPES] = { }, }; +static int qtnf_vlan_vif_exists(struct qtnf_vif *vif, u16 vlanid) +{ + struct qtnf_vif *vlan_vif; + + vlan_vif = qtnf_vlan_list_lookup(>vlan_list, vlanid); + if (vlan_vif) + return 1; + + return 0; +} + +static struct qtnf_vif *qtnf_add_vlan_vif(struct qtnf_vif *vif, u16 vlanid) +{ + struct qtnf_vif *vlan_vif; + + vlan_vif = qtnf_vlan_list_add(>vlan_list, vlanid); + if (vlan_vif) { + vlan_vif->u.vlan.parent = vif; + vlan_vif->u.vlan.vlanid = vlanid; + } + + return vlan_vif; +} + +static int qtnf_del_vlan_vif(struct qtnf_vif *vif, u16 vlanid) +{ + return qtnf_vlan_list_del(>vlan_list, vlanid); +} + static int qtnf_change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, @@ -92,7 +121,15 @@ qtnf_change_virtual_intf(struct wiphy *wiphy, else mac_addr = NULL; - qtnf_scan_done(vif->mac, true); + switch (type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_AP: +
[PATCH 4/8] qtnfmac: implement cfg80211 dump_survey handler
This patch implements cfg80211 dump_survey handler enabling per-channel survey data reports. Signed-off-by: Avinash PatilSigned-off-by: Sergey Matyukevich --- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 69 +- drivers/net/wireless/quantenna/qtnfmac/commands.c | 107 ++ drivers/net/wireless/quantenna/qtnfmac/commands.h | 2 + drivers/net/wireless/quantenna/qtnfmac/core.h | 9 ++ drivers/net/wireless/quantenna/qtnfmac/qlink.h| 31 +++ 5 files changed, 217 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index e222e8d038d3..eb648f02aa40 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -839,6 +839,72 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev, return 0; } +static int +qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, +int idx, struct survey_info *survey) +{ + struct qtnf_wmac *mac = wiphy_priv(wiphy); + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + struct qtnf_chan_stats stats; + int ret; + + sband = wiphy->bands[NL80211_BAND_2GHZ]; + if (sband && idx >= sband->n_channels) { + idx -= sband->n_channels; + sband = NULL; + } + + if (!sband) + sband = wiphy->bands[NL80211_BAND_5GHZ]; + + if (!sband || idx >= sband->n_channels) + return -ENOENT; + + chan = >channels[idx]; + memset(, 0, sizeof(stats)); + + survey->channel = chan; + survey->filled = 0x0; + + ret = qtnf_cmd_get_chan_stats(mac, chan->hw_value, ); + switch (ret) { + case 0: + if (unlikely(stats.chan_num != chan->hw_value)) { + pr_err("received stats for channel %d instead of %d\n", + stats.chan_num, chan->hw_value); + ret = -EINVAL; + break; + } + + survey->filled = SURVEY_INFO_TIME | +SURVEY_INFO_TIME_SCAN | +SURVEY_INFO_TIME_BUSY | +SURVEY_INFO_TIME_RX | +SURVEY_INFO_TIME_TX | +SURVEY_INFO_NOISE_DBM; + + survey->time_scan = stats.cca_try; + survey->time = stats.cca_try; + survey->time_tx = stats.cca_tx; + survey->time_rx = stats.cca_rx; + survey->time_busy = stats.cca_busy; + survey->noise = stats.chan_noise; + break; + case -ENOENT: + pr_debug("no stats for channel %u\n", chan->hw_value); + ret = 0; + break; + default: + pr_debug("failed to get chan(%d) stats from card\n", +chan->hw_value); + ret = -EINVAL; + break; + } + + return ret; +} + static struct cfg80211_ops qtn_cfg80211_ops = { .add_virtual_intf = qtnf_add_virtual_intf, .change_virtual_intf= qtnf_change_virtual_intf, @@ -859,7 +925,8 @@ static struct cfg80211_ops qtn_cfg80211_ops = { .set_default_mgmt_key = qtnf_set_default_mgmt_key, .scan = qtnf_scan, .connect= qtnf_connect, - .disconnect = qtnf_disconnect + .disconnect = qtnf_disconnect, + .dump_survey= qtnf_dump_survey }; static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in, diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 221804f8c43a..22741bf6f4ac 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -1358,6 +1358,62 @@ static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac *mac, return 0; } +static int +qtnf_cmd_resp_proc_chan_stat_info(struct qtnf_chan_stats *stats, + const u8 *payload, size_t payload_len) +{ + struct qlink_chan_stats *qlink_stats; + const struct qlink_tlv_hdr *tlv; + size_t tlv_full_len; + u16 tlv_value_len; + u16 tlv_type; + + tlv = (struct qlink_tlv_hdr *)payload; + while (payload_len >= sizeof(struct qlink_tlv_hdr)) { + 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("malformed TLV 0x%.2X; LEN: %u\n", + tlv_type, tlv_value_len); +
[PATCH 2/8] qtnfmac: cleanup and fixes preparing AP_VLAN support
This patch implements various cleanups and fixes aimed to simplify adding AP_VLAN support to qtnfmac driver: - Remove unused flag field from qlink_intf_info - Add interface type to qlink_cmd_change_sta - Modify qtnf_cmd_send_change_sta: add interface type to command - Fix handling of iftype mask reported by firmware: Firmware sends supported interface type rather than mask. As a result, types field of ieee80211_iface_limit structure may end up having multiple iftype bits set. This leads to WARN_ON from wiphy_verify_combinations. Signed-off-by: Sergey Matyukevich--- drivers/net/wireless/quantenna/qtnfmac/commands.c | 35 +- drivers/net/wireless/quantenna/qtnfmac/qlink.h | 4 +-- .../net/wireless/quantenna/qtnfmac/qlink_util.c| 23 +++--- .../net/wireless/quantenna/qtnfmac/qlink_util.h| 2 +- 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 2ee007ecb236..5a6caf5b685b 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -995,7 +995,7 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, struct ieee80211_iface_limit *limits = NULL; const struct qlink_iface_limit *limit_record; size_t record_count = 0, rec = 0; - u16 tlv_type, tlv_value_len, mask; + u16 tlv_type, tlv_value_len; struct qlink_iface_comb_num *comb; size_t tlv_full_len; const struct qlink_tlv_hdr *tlv; @@ -1048,9 +1048,10 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, limit_record = (void *)tlv->val; limits[rec].max = le16_to_cpu(limit_record->max_num); - mask = le16_to_cpu(limit_record->type_mask); - limits[rec].types = qlink_iface_type_mask_to_nl(mask); - /* only AP and STA modes are supported */ + limits[rec].types = qlink_iface_type_to_nl_mask( + le16_to_cpu(limit_record->type)); + + /* supported modes: STA, AP */ limits[rec].types &= BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION); @@ -1063,6 +1064,7 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, default: break; } + tlv_buf_size -= tlv_full_len; tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } @@ -1808,10 +1810,27 @@ int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac, cmd = (struct qlink_cmd_change_sta *)cmd_skb->data; ether_addr_copy(cmd->sta_addr, mac); - cmd->sta_flags_mask = cpu_to_le32(qtnf_encode_sta_flags( - params->sta_flags_mask)); - cmd->sta_flags_set = cpu_to_le32(qtnf_encode_sta_flags( -params->sta_flags_set)); + + switch (vif->wdev.iftype) { + case NL80211_IFTYPE_AP: + cmd->if_type = cpu_to_le16(QLINK_IFTYPE_AP); + cmd->sta_flags_mask = cpu_to_le32(qtnf_encode_sta_flags( + params->sta_flags_mask)); + cmd->sta_flags_set = cpu_to_le32(qtnf_encode_sta_flags( +params->sta_flags_set)); + break; + case NL80211_IFTYPE_STATION: + cmd->if_type = cpu_to_le16(QLINK_IFTYPE_STATION); + cmd->sta_flags_mask = cpu_to_le32(qtnf_encode_sta_flags( + params->sta_flags_mask)); + cmd->sta_flags_set = cpu_to_le32(qtnf_encode_sta_flags( +params->sta_flags_set)); + break; + default: + pr_err("unsupported iftype %d\n", vif->wdev.iftype); + ret = -EINVAL; + goto out; + } ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, _code); if (unlikely(ret)) diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index e27833b78940..8bcd8a55ad11 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -90,7 +90,6 @@ enum qlink_iface_type { */ struct qlink_intf_info { __le16 if_type; - __le16 flags; u8 mac_addr[ETH_ALEN]; u8 rsvd[2]; } __packed; @@ -350,6 +349,7 @@ struct qlink_cmd_change_sta { struct qlink_cmd chdr; __le32 sta_flags_mask; __le32 sta_flags_set; + __le16 if_type; u8 sta_addr[ETH_ALEN]; } __packed; @@ -823,7 +823,7 @@ struct qlink_tlv_hdr { struct
[PATCH 1/8] qtnfmac: updates and fixes for regulatory support
This patch introduces several changes for regulatory support in qtnfmac driver: * Introduce support for setting regdomain from host New command is implemented to notify firmware about regdomain changes performed by host. Firmware is supposed to check requested regdomain changes. On success firmware enables updated hardware channel configuration and then host driver updates channel info for each band. * Introduce support of custom regulatory rules Obtain custom regulatory rules from the firmware and enable them during wiphy registration * Regulatory for self-managed setup Regdomain information needs to be registered with cfg80211 for devices with REGULATORY_WIPHY_SELF_MANAGED flag set. * Misc fixes in regulatory code paths - add missing lock in qtnf_cmd_get_mac_chan_info - do not free band channel structure if channel count is the same - free allocated regdomain hw_info.rd structure on detach Signed-off-by: Igor MitsyankoSigned-off-by: Sergey Matyukevich --- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 83 +++ drivers/net/wireless/quantenna/qtnfmac/commands.c | 286 ++ drivers/net/wireless/quantenna/qtnfmac/commands.h | 1 + drivers/net/wireless/quantenna/qtnfmac/core.c | 3 + drivers/net/wireless/quantenna/qtnfmac/core.h | 7 +- drivers/net/wireless/quantenna/qtnfmac/qlink.h| 126 +- 6 files changed, 403 insertions(+), 103 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index e3c090008125..825a6334fbfe 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -700,67 +700,45 @@ static struct cfg80211_ops qtn_cfg80211_ops = { .disconnect = qtnf_disconnect }; -static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy, +static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in, struct regulatory_request *req) { - struct qtnf_wmac *mac = wiphy_priv(wiphy); - struct qtnf_bus *bus; - struct qtnf_vif *vif; - struct qtnf_wmac *chan_mac; - int i; + struct qtnf_wmac *mac = wiphy_priv(wiphy_in); + struct wiphy *wiphy; + struct qtnf_bus *bus = mac->bus; + unsigned int mac_idx; enum nl80211_band band; - - bus = mac->bus; + int ret; pr_debug("MAC%u: initiator=%d alpha=%c%c\n", mac->macid, req->initiator, req->alpha2[0], req->alpha2[1]); - vif = qtnf_mac_get_base_vif(mac); - if (!vif) { - pr_err("MAC%u: primary VIF is not configured\n", mac->macid); - return; - } - - /* ignore non-ISO3166 country codes */ - for (i = 0; i < sizeof(req->alpha2); i++) { - if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { - pr_err("MAC%u: not an ISO3166 code\n", mac->macid); - return; - } - } - if (!strncasecmp(req->alpha2, bus->hw_info.alpha2_code, -sizeof(req->alpha2))) { - pr_warn("MAC%u: unchanged country code\n", mac->macid); - return; - } - - if (qtnf_cmd_send_regulatory_config(mac, req->alpha2)) { - pr_err("MAC%u: failed to configure regulatory\n", mac->macid); + ret = qtnf_cmd_reg_notify(bus, req); + if (ret) { + if (ret != -EOPNOTSUPP && ret != -EALREADY) + pr_err("failed to update reg domain to %c%c\n", + req->alpha2[0], req->alpha2[1]); return; } - for (i = 0; i < bus->hw_info.num_mac; i++) { - chan_mac = bus->mac[i]; - - if (!chan_mac) + for (mac_idx = 0; mac_idx < QTNF_MAX_MAC; ++mac_idx) { + if (!(bus->hw_info.mac_bitmap & (1 << mac_idx))) continue; - if (!(bus->hw_info.mac_bitmap & BIT(i))) - continue; + mac = bus->mac[mac_idx]; + wiphy = priv_to_wiphy(mac); for (band = 0; band < NUM_NL80211_BANDS; ++band) { if (!wiphy->bands[band]) continue; - if (qtnf_cmd_get_mac_chan_info(chan_mac, - wiphy->bands[band])) { - pr_err("MAC%u: can't get channel info\n", - chan_mac->macid); - qtnf_core_detach(bus); - - return; - } + ret = qtnf_cmd_get_mac_chan_info(mac, +wiphy->bands[band]); + if (ret) +
[PATCH 0/8] qtnfmac: add more features to driver
This patch series adds more features to qtnfmac driver including the following major pieces: - updates for regulatory support - AP/VLAN support - dump_survey handler - channel_switch handler bus.h|1 cfg80211.c | 560 +-- cfg80211.h |4 commands.c | 515 -- commands.h |5 core.c | 83 core.h | 62 +- event.c | 67 ++- pearl/pcie.c |5 qlink.h | 201 +++-- qlink_util.c | 26 +- qlink_util.h |2 util.c | 74 +-- util.h | 34 ++- 14 files changed, 1422 insertions(+), 217 deletions(-)
Re: [PATCH] cfg80211: Fix a memory leak in error handling path in 'brcmf_cfg80211_attach'
On 20-06-17 08:22, Christophe JAILLET wrote: > If 'wiphy_new()' fails, we leak 'ops'. Add a new label in the error > handling path to free it in such a case. Thanks. Please add the following tags: Cc: sta...@vger.kernel.org > Fixes: 5c22fb85102a7 ("brcmfmac: add wowl gtk rekeying offload support") Acked-by: Arend van Spriel> Signed-off-by: Christophe JAILLET > --- > drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-)
Re: pull-request: wireless-drivers 2017-06-20
From: Kalle ValoDate: Tue, 20 Jun 2017 16:39:59 +0300 > here's a pull request to net tree, few important fixes still I would > like to have in 4.12. Please let me know if there are any problems. Pulled, thanks Kalle.
pull-request: wireless-drivers 2017-06-20
Hi Dave, here's a pull request to net tree, few important fixes still I would like to have in 4.12. Please let me know if there are any problems. Kalle The following changes since commit dc89481bb4c9af0700423e21c8371379d3d943b1: Merge tag 'iwlwifi-for-kalle-2017-06-05' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes (2017-06-05 22:21:25 +0300) are available in the git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers.git tags/wireless-drivers-for-davem-2017-06-20 for you to fetch changes up to 35abcd4f9f303ac4f10f99b3f7e993e5f2e6fa37: brcmfmac: fix uninitialized warning in brcmf_usb_probe_phase2() (2017-06-16 11:52:36 +0300) wireless-drivers fixes for 4.12 Two important fixes for brcmfmac. The rest of the brcmfmac patches are either code preparation and fixing a new build warning. brcmfmac * fix a NULL pointer dereference during resume * fix a NULL pointer dereference with USB devices, a regression from v4.12-rc1 Arend Van Spriel (5): brcmfmac: add parameter to pass error code in firmware callback brcmfmac: use firmware callback upon failure to load brcmfmac: unbind all devices upon failure in firmware callback brcmfmac: fix brcmf_fws_add_interface() for USB devices brcmfmac: fix uninitialized warning in brcmf_usb_probe_phase2() .../broadcom/brcm80211/brcmfmac/firmware.c | 35 +++--- .../broadcom/brcm80211/brcmfmac/firmware.h | 4 +-- .../broadcom/brcm80211/brcmfmac/fwsignal.c | 2 +- .../wireless/broadcom/brcm80211/brcmfmac/pcie.c| 17 +++ .../wireless/broadcom/brcm80211/brcmfmac/sdio.c| 18 +++ .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 9 +++--- 6 files changed, 49 insertions(+), 36 deletions(-)
Re: [PATCH 2/6] rsi: use enum for FSM states
On Mon, Jun 19, 2017 at 8:49 PM, Kalle Valowrote: > Amitkumar Karwar writes: > >> On Thu, Jun 15, 2017 at 8:14 PM, Kalle Valo wrote: >>> Amitkumar Karwar writes: >>> On Wed, Jun 14, 2017 at 2:43 PM, Kalle Valo wrote: > amit karwar writes: > >> On Tue, Jun 13, 2017 at 12:17 PM, Kalle Valo >> wrote: >> >>> Also your name in patchwork is not capitalised (patchwork is idiotic and >>> takes the name from patchwork user data and not from the patch): >>> >>> [1/6] rsi: add usb RS9113 chipset support 2017-06-02 amit >>> karwar New >>> [2/6] rsi: use enum for FSM states 2017-06-02 amit karwar New >>> [3/6] rsi: Register interrupt handler before firmware load >>> 2017-06-02 amit karwar New >>> [4/6] rsi: receive path enhancement for RS9113 2017-06-02 amit >>> karwar New >>> [5/6] rsi: configure new boot parameters to device 2017-06-02 >>> amit karwar New >>> [6/6] rsi: add tx frame for common device configuration >>> 2017-06-02 amit karwar New >>> >>> To fix that could you please register to patchwork and capitalise your >>> name correctly? You have only one chance, patchwork doesn't allow users >>> edit the name afterwards, so don't do any typos :) >> >> Thanks. I have registered with patchwork and corrected my name. > > What address did you use? Patchwork still shows your name all lower: > > https://patchwork.kernel.org/project/linux-wireless/list/?submitter=173645 > > I suspect you didn't register with gmail.com, but with some other > address. I recommend that you link all your email addresses, including > gmail.com, to the same patchwork account and hopefully that fixes it. > You should be able to do that from the profile page in patchwork. I had registered with my gmail id. Also, other email id has also been linked to patchwork. But still patchwork took previous user name. I could not find a way to check my name in patchwork database after login. I have now corrected my display name in gmail's setting. >>> >>> Good, thanks. This name format bug in patchwork is really annoying, I'm >>> suffering from frequently. Let's see how your next submission goes and >>> hopefully we can sort it out. >> >> I just submitted a patch series. But patchwork is still showing older name. > > I think the best is that you now report this to kernel.org admins: > > https://korg.wiki.kernel.org/userdoc/support > > Hopefully they can easily fix it directly in the database. > Thanks for the pointers. I have dropped an email to helpdesk for this issue.
Re: [PATCH] cfg80211: Fix a memory leak in error handling path in 'brcmf_cfg80211_attach'
Christophe JAILLETwrites: > If 'wiphy_new()' fails, we leak 'ops'. Add a new label in the error > handling path to free it in such a case. > > Fixes: 5c22fb85102a7 ("brcmfmac: add wowl gtk rekeying offload support") > Signed-off-by: Christophe JAILLET The prefix should be "brcmfmac:", like in the commit you are fixing. "cfg80211:" is very misleading. -- Kalle Valo