Commit c87308b1 authored by David S. Miller's avatar David S. Miller

Merge tag 'wireless-drivers-for-davem-2018-03-24' of...

Merge tag 'wireless-drivers-for-davem-2018-03-24' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers

Kalle Valo says:

====================
wireless-drivers fixes for 4.16

Some fixes for 4.16, only for iwlwifi and brcmfmac this time. All
pretty small.

iwlwifi

* fix an issue with the multicast queue

* fix IGTK handling

* fix some missing return value checks

* add support for a HW workaround for issues on some platforms

* a couple of fixes for channel-switch

* a few fixes for the aggregation handling code

brcmfmac

* drop Inter-Access Point Protocol packets by default

* fix check for ISO3166 regulatory code
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 10b8a3de 9b9322db
...@@ -6802,7 +6802,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, ...@@ -6802,7 +6802,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
return; return;
/* ignore non-ISO3166 country codes */ /* ignore non-ISO3166 country codes */
for (i = 0; i < sizeof(req->alpha2); i++) for (i = 0; i < 2; i++)
if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n", brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n",
req->alpha2[0], req->alpha2[1]); req->alpha2[0], req->alpha2[1]);
......
...@@ -75,6 +75,10 @@ static int brcmf_roamoff; ...@@ -75,6 +75,10 @@ static int brcmf_roamoff;
module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
static int brcmf_iapp_enable;
module_param_named(iapp, brcmf_iapp_enable, int, 0);
MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol");
#ifdef DEBUG #ifdef DEBUG
/* always succeed brcmf_bus_started() */ /* always succeed brcmf_bus_started() */
static int brcmf_ignore_probe_fail; static int brcmf_ignore_probe_fail;
...@@ -441,6 +445,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, ...@@ -441,6 +445,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
settings->feature_disable = brcmf_feature_disable; settings->feature_disable = brcmf_feature_disable;
settings->fcmode = brcmf_fcmode; settings->fcmode = brcmf_fcmode;
settings->roamoff = !!brcmf_roamoff; settings->roamoff = !!brcmf_roamoff;
settings->iapp = !!brcmf_iapp_enable;
#ifdef DEBUG #ifdef DEBUG
settings->ignore_probe_fail = !!brcmf_ignore_probe_fail; settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
#endif #endif
......
...@@ -58,6 +58,7 @@ struct brcmf_mp_device { ...@@ -58,6 +58,7 @@ struct brcmf_mp_device {
unsigned int feature_disable; unsigned int feature_disable;
int fcmode; int fcmode;
bool roamoff; bool roamoff;
bool iapp;
bool ignore_probe_fail; bool ignore_probe_fail;
struct brcmfmac_pd_cc *country_codes; struct brcmfmac_pd_cc *country_codes;
union { union {
......
...@@ -230,6 +230,37 @@ static void brcmf_netdev_set_multicast_list(struct net_device *ndev) ...@@ -230,6 +230,37 @@ static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
schedule_work(&ifp->multicast_work); schedule_work(&ifp->multicast_work);
} }
/**
* brcmf_skb_is_iapp - checks if skb is an IAPP packet
*
* @skb: skb to check
*/
static bool brcmf_skb_is_iapp(struct sk_buff *skb)
{
static const u8 iapp_l2_update_packet[6] __aligned(2) = {
0x00, 0x01, 0xaf, 0x81, 0x01, 0x00,
};
unsigned char *eth_data;
#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
const u16 *a, *b;
#endif
if (skb->len - skb->mac_len != 6 ||
!is_multicast_ether_addr(eth_hdr(skb)->h_dest))
return false;
eth_data = skb_mac_header(skb) + ETH_HLEN;
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
return !(((*(const u32 *)eth_data) ^ (*(const u32 *)iapp_l2_update_packet)) |
((*(const u16 *)(eth_data + 4)) ^ (*(const u16 *)(iapp_l2_update_packet + 4))));
#else
a = (const u16 *)eth_data;
b = (const u16 *)iapp_l2_update_packet;
return !((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]));
#endif
}
static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
struct net_device *ndev) struct net_device *ndev)
{ {
...@@ -250,6 +281,23 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, ...@@ -250,6 +281,23 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
goto done; goto done;
} }
/* Some recent Broadcom's firmwares disassociate STA when they receive
* an 802.11f ADD frame. This behavior can lead to a local DoS security
* issue. Attacker may trigger disassociation of any STA by sending a
* proper Ethernet frame to the wireless interface.
*
* Moreover this feature may break AP interfaces in some specific
* setups. This applies e.g. to the bridge with hairpin mode enabled and
* IFLA_BRPORT_MCAST_TO_UCAST set. IAPP packet generated by a firmware
* will get passed back to the wireless interface and cause immediate
* disassociation of a just-connected STA.
*/
if (!drvr->settings->iapp && brcmf_skb_is_iapp(skb)) {
dev_kfree_skb(skb);
ret = -EINVAL;
goto done;
}
/* Make sure there's enough writeable headroom */ /* Make sure there's enough writeable headroom */
if (skb_headroom(skb) < drvr->hdrlen || skb_header_cloned(skb)) { if (skb_headroom(skb) < drvr->hdrlen || skb_header_cloned(skb)) {
head_delta = max_t(int, drvr->hdrlen - skb_headroom(skb), 0); head_delta = max_t(int, drvr->hdrlen - skb_headroom(skb), 0);
...@@ -325,6 +373,15 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, ...@@ -325,6 +373,15 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp,
void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
{ {
/* Most of Broadcom's firmwares send 802.11f ADD frame every time a new
* STA connects to the AP interface. This is an obsoleted standard most
* users don't use, so don't pass these frames up unless requested.
*/
if (!ifp->drvr->settings->iapp && brcmf_skb_is_iapp(skb)) {
brcmu_pkt_buf_free_skb(skb);
return;
}
if (skb->pkt_type == PACKET_MULTICAST) if (skb->pkt_type == PACKET_MULTICAST)
ifp->ndev->stats.multicast++; ifp->ndev->stats.multicast++;
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include <linux/stringify.h> #include <linux/stringify.h>
#include "iwl-config.h" #include "iwl-config.h"
#include "iwl-agn-hw.h" #include "iwl-agn-hw.h"
#include "fw/file.h"
/* Highest firmware API version supported */ /* Highest firmware API version supported */
#define IWL9000_UCODE_API_MAX 36 #define IWL9000_UCODE_API_MAX 36
...@@ -265,6 +266,67 @@ const struct iwl_cfg iwl9560_2ac_cfg_soc = { ...@@ -265,6 +266,67 @@ const struct iwl_cfg iwl9560_2ac_cfg_soc = {
.integrated = true, .integrated = true,
.soc_latency = 5000, .soc_latency = 5000,
}; };
const struct iwl_cfg iwl9460_2ac_cfg_shared_clk = {
.name = "Intel(R) Dual Band Wireless AC 9460",
.fw_name_pre = IWL9000A_FW_PRE,
.fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
.fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
IWL_DEVICE_9000,
.ht_params = &iwl9000_ht_params,
.nvm_ver = IWL9000_NVM_VERSION,
.nvm_calib_ver = IWL9000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.integrated = true,
.soc_latency = 5000,
.extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK
};
const struct iwl_cfg iwl9461_2ac_cfg_shared_clk = {
.name = "Intel(R) Dual Band Wireless AC 9461",
.fw_name_pre = IWL9000A_FW_PRE,
.fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
.fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
IWL_DEVICE_9000,
.ht_params = &iwl9000_ht_params,
.nvm_ver = IWL9000_NVM_VERSION,
.nvm_calib_ver = IWL9000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.integrated = true,
.soc_latency = 5000,
.extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK
};
const struct iwl_cfg iwl9462_2ac_cfg_shared_clk = {
.name = "Intel(R) Dual Band Wireless AC 9462",
.fw_name_pre = IWL9000A_FW_PRE,
.fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
.fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
IWL_DEVICE_9000,
.ht_params = &iwl9000_ht_params,
.nvm_ver = IWL9000_NVM_VERSION,
.nvm_calib_ver = IWL9000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.integrated = true,
.soc_latency = 5000,
.extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK
};
const struct iwl_cfg iwl9560_2ac_cfg_shared_clk = {
.name = "Intel(R) Dual Band Wireless AC 9560",
.fw_name_pre = IWL9000A_FW_PRE,
.fw_name_pre_b_or_c_step = IWL9000B_FW_PRE,
.fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
IWL_DEVICE_9000,
.ht_params = &iwl9000_ht_params,
.nvm_ver = IWL9000_NVM_VERSION,
.nvm_calib_ver = IWL9000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.integrated = true,
.soc_latency = 5000,
.extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK
};
MODULE_FIRMWARE(IWL9000A_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL9000A_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL9000B_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL9000B_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL9000RFB_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL9000RFB_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
......
...@@ -441,6 +441,7 @@ enum iwl_fw_phy_cfg { ...@@ -441,6 +441,7 @@ enum iwl_fw_phy_cfg {
FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS, FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS,
FW_PHY_CFG_RX_CHAIN_POS = 20, FW_PHY_CFG_RX_CHAIN_POS = 20,
FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS, FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
FW_PHY_CFG_SHARED_CLK = BIT(31),
}; };
#define IWL_UCODE_MAX_CS 1 #define IWL_UCODE_MAX_CS 1
......
...@@ -398,6 +398,7 @@ struct iwl_cfg { ...@@ -398,6 +398,7 @@ struct iwl_cfg {
u8 ucode_api_max; u8 ucode_api_max;
u8 ucode_api_min; u8 ucode_api_min;
u32 min_umac_error_event_table; u32 min_umac_error_event_table;
u32 extra_phy_cfg_flags;
}; };
/* /*
...@@ -477,6 +478,10 @@ extern const struct iwl_cfg iwl9460_2ac_cfg_soc; ...@@ -477,6 +478,10 @@ extern const struct iwl_cfg iwl9460_2ac_cfg_soc;
extern const struct iwl_cfg iwl9461_2ac_cfg_soc; extern const struct iwl_cfg iwl9461_2ac_cfg_soc;
extern const struct iwl_cfg iwl9462_2ac_cfg_soc; extern const struct iwl_cfg iwl9462_2ac_cfg_soc;
extern const struct iwl_cfg iwl9560_2ac_cfg_soc; extern const struct iwl_cfg iwl9560_2ac_cfg_soc;
extern const struct iwl_cfg iwl9460_2ac_cfg_shared_clk;
extern const struct iwl_cfg iwl9461_2ac_cfg_shared_clk;
extern const struct iwl_cfg iwl9462_2ac_cfg_shared_clk;
extern const struct iwl_cfg iwl9560_2ac_cfg_shared_clk;
extern const struct iwl_cfg iwl22000_2ac_cfg_hr; extern const struct iwl_cfg iwl22000_2ac_cfg_hr;
extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb; extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb;
extern const struct iwl_cfg iwl22000_2ac_cfg_jf; extern const struct iwl_cfg iwl22000_2ac_cfg_jf;
......
...@@ -433,6 +433,10 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) ...@@ -433,6 +433,10 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
/* Set parameters */ /* Set parameters */
phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_get_phy_config(mvm)); phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_get_phy_config(mvm));
/* set flags extra PHY configuration flags from the device's cfg */
phy_cfg_cmd.phy_cfg |= cpu_to_le32(mvm->cfg->extra_phy_cfg_flags);
phy_cfg_cmd.calib_control.event_trigger = phy_cfg_cmd.calib_control.event_trigger =
mvm->fw->default_calib[ucode_type].event_trigger; mvm->fw->default_calib[ucode_type].event_trigger;
phy_cfg_cmd.calib_control.flow_trigger = phy_cfg_cmd.calib_control.flow_trigger =
......
...@@ -2132,10 +2132,10 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, ...@@ -2132,10 +2132,10 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
* Send the bcast station. At this stage the TBTT and DTIM time * Send the bcast station. At this stage the TBTT and DTIM time
* events are added and applied to the scheduler * events are added and applied to the scheduler
*/ */
iwl_mvm_send_add_bcast_sta(mvm, vif); ret = iwl_mvm_send_add_bcast_sta(mvm, vif);
if (ret) if (ret)
goto out_unbind; goto out_unbind;
iwl_mvm_add_mcast_sta(mvm, vif); ret = iwl_mvm_add_mcast_sta(mvm, vif);
if (ret) { if (ret) {
iwl_mvm_send_rm_bcast_sta(mvm, vif); iwl_mvm_send_rm_bcast_sta(mvm, vif);
goto out_unbind; goto out_unbind;
...@@ -3494,6 +3494,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, ...@@ -3494,6 +3494,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
ret = 0; ret = 0;
goto out; goto out;
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
mvmvif->csa_bcn_pending = false;
break; break;
case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MONITOR:
/* always disable PS when a monitor interface is active */ /* always disable PS when a monitor interface is active */
...@@ -3537,7 +3538,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, ...@@ -3537,7 +3538,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
} }
if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) { if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) {
u32 duration = 2 * vif->bss_conf.beacon_int; u32 duration = 3 * vif->bss_conf.beacon_int;
/* iwl_mvm_protect_session() reads directly from the /* iwl_mvm_protect_session() reads directly from the
* device (the system time), so make sure it is * device (the system time), so make sure it is
...@@ -3550,6 +3551,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, ...@@ -3550,6 +3551,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
/* Protect the session to make sure we hear the first /* Protect the session to make sure we hear the first
* beacon on the new channel. * beacon on the new channel.
*/ */
mvmvif->csa_bcn_pending = true;
iwl_mvm_protect_session(mvm, vif, duration, duration, iwl_mvm_protect_session(mvm, vif, duration, duration,
vif->bss_conf.beacon_int / 2, vif->bss_conf.beacon_int / 2,
true); true);
...@@ -3988,6 +3990,7 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw, ...@@ -3988,6 +3990,7 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_STATION) { if (vif->type == NL80211_IFTYPE_STATION) {
struct iwl_mvm_sta *mvmsta; struct iwl_mvm_sta *mvmsta;
mvmvif->csa_bcn_pending = false;
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
mvmvif->ap_sta_id); mvmvif->ap_sta_id);
......
...@@ -438,6 +438,9 @@ struct iwl_mvm_vif { ...@@ -438,6 +438,9 @@ struct iwl_mvm_vif {
bool csa_failed; bool csa_failed;
u16 csa_target_freq; u16 csa_target_freq;
/* Indicates that we are waiting for a beacon on a new channel */
bool csa_bcn_pending;
/* TCP Checksum Offload */ /* TCP Checksum Offload */
netdev_features_t features; netdev_features_t features;
}; };
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -18,11 +19,6 @@ ...@@ -18,11 +19,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution * The full GNU General Public License is included in this distribution
* in the file called COPYING. * in the file called COPYING.
* *
...@@ -34,6 +30,7 @@ ...@@ -34,6 +30,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2018 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -286,6 +283,20 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) ...@@ -286,6 +283,20 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
return; return;
ctxt->ref--; ctxt->ref--;
/*
* Move unused phy's to a default channel. When the phy is moved the,
* fw will cleanup immediate quiet bit if it was previously set,
* otherwise we might not be able to reuse this phy.
*/
if (ctxt->ref == 0) {
struct ieee80211_channel *chan;
struct cfg80211_chan_def chandef;
chan = &mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[0];
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
iwl_mvm_phy_ctxt_changed(mvm, ctxt, &chandef, 1, 1);
}
} }
static void iwl_mvm_binding_iterator(void *_data, u8 *mac, static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
......
...@@ -1695,7 +1695,8 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, ...@@ -1695,7 +1695,8 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
u32 qmask, enum nl80211_iftype iftype, u32 qmask, enum nl80211_iftype iftype,
enum iwl_sta_type type) enum iwl_sta_type type)
{ {
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
sta->sta_id == IWL_MVM_INVALID_STA) {
sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype); sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype);
if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_INVALID_STA)) if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_INVALID_STA))
return -ENOSPC; return -ENOSPC;
...@@ -2478,28 +2479,12 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -2478,28 +2479,12 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
/* /*
* Note the possible cases: * Note the possible cases:
* 1. In DQA mode with an enabled TXQ - TXQ needs to become agg'ed * 1. An enabled TXQ - TXQ needs to become agg'ed
* 2. Non-DQA mode: the TXQ hasn't yet been enabled, so find a free * 2. The TXQ hasn't yet been enabled, so find a free one and mark
* one and mark it as reserved * it as reserved
* 3. In DQA mode, but no traffic yet on this TID: same treatment as in
* non-DQA mode, since the TXQ hasn't yet been allocated
* Don't support case 3 for new TX path as it is not expected to happen
* and aggregation will be offloaded soon anyway
*/ */
txq_id = mvmsta->tid_data[tid].txq_id; txq_id = mvmsta->tid_data[tid].txq_id;
if (iwl_mvm_has_new_tx_api(mvm)) { if (txq_id == IWL_MVM_INVALID_QUEUE) {
if (txq_id == IWL_MVM_INVALID_QUEUE) {
ret = -ENXIO;
goto release_locks;
}
} else if (unlikely(mvm->queue_info[txq_id].status ==
IWL_MVM_QUEUE_SHARED)) {
ret = -ENXIO;
IWL_DEBUG_TX_QUEUES(mvm,
"Can't start tid %d agg on shared queue!\n",
tid);
goto release_locks;
} else if (mvm->queue_info[txq_id].status != IWL_MVM_QUEUE_READY) {
txq_id = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id, txq_id = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id,
IWL_MVM_DQA_MIN_DATA_QUEUE, IWL_MVM_DQA_MIN_DATA_QUEUE,
IWL_MVM_DQA_MAX_DATA_QUEUE); IWL_MVM_DQA_MAX_DATA_QUEUE);
...@@ -2508,16 +2493,16 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -2508,16 +2493,16 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
IWL_ERR(mvm, "Failed to allocate agg queue\n"); IWL_ERR(mvm, "Failed to allocate agg queue\n");
goto release_locks; goto release_locks;
} }
/*
* TXQ shouldn't be in inactive mode for non-DQA, so getting
* an inactive queue from iwl_mvm_find_free_queue() is
* certainly a bug
*/
WARN_ON(mvm->queue_info[txq_id].status ==
IWL_MVM_QUEUE_INACTIVE);
/* TXQ hasn't yet been enabled, so mark it only as reserved */ /* TXQ hasn't yet been enabled, so mark it only as reserved */
mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_RESERVED; mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_RESERVED;
} else if (unlikely(mvm->queue_info[txq_id].status ==
IWL_MVM_QUEUE_SHARED)) {
ret = -ENXIO;
IWL_DEBUG_TX_QUEUES(mvm,
"Can't start tid %d agg on shared queue!\n",
tid);
goto release_locks;
} }
spin_unlock(&mvm->queue_info_lock); spin_unlock(&mvm->queue_info_lock);
...@@ -2696,8 +2681,10 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -2696,8 +2681,10 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm, static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta, struct iwl_mvm_sta *mvmsta,
u16 txq_id) struct iwl_mvm_tid_data *tid_data)
{ {
u16 txq_id = tid_data->txq_id;
if (iwl_mvm_has_new_tx_api(mvm)) if (iwl_mvm_has_new_tx_api(mvm))
return; return;
...@@ -2709,8 +2696,10 @@ static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm, ...@@ -2709,8 +2696,10 @@ static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm,
* allocated through iwl_mvm_enable_txq, so we can just mark it back as * allocated through iwl_mvm_enable_txq, so we can just mark it back as
* free. * free.
*/ */
if (mvm->queue_info[txq_id].status == IWL_MVM_QUEUE_RESERVED) if (mvm->queue_info[txq_id].status == IWL_MVM_QUEUE_RESERVED) {
mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_FREE; mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_FREE;
tid_data->txq_id = IWL_MVM_INVALID_QUEUE;
}
spin_unlock_bh(&mvm->queue_info_lock); spin_unlock_bh(&mvm->queue_info_lock);
} }
...@@ -2741,7 +2730,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -2741,7 +2730,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvmsta->agg_tids &= ~BIT(tid); mvmsta->agg_tids &= ~BIT(tid);
iwl_mvm_unreserve_agg_queue(mvm, mvmsta, txq_id); iwl_mvm_unreserve_agg_queue(mvm, mvmsta, tid_data);
switch (tid_data->state) { switch (tid_data->state) {
case IWL_AGG_ON: case IWL_AGG_ON:
...@@ -2808,7 +2797,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -2808,7 +2797,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvmsta->agg_tids &= ~BIT(tid); mvmsta->agg_tids &= ~BIT(tid);
spin_unlock_bh(&mvmsta->lock); spin_unlock_bh(&mvmsta->lock);
iwl_mvm_unreserve_agg_queue(mvm, mvmsta, txq_id); iwl_mvm_unreserve_agg_queue(mvm, mvmsta, tid_data);
if (old_state >= IWL_AGG_ON) { if (old_state >= IWL_AGG_ON) {
iwl_mvm_drain_sta(mvm, mvmsta, true); iwl_mvm_drain_sta(mvm, mvmsta, true);
...@@ -3233,17 +3222,9 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, ...@@ -3233,17 +3222,9 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
} }
sta_id = mvm_sta->sta_id; sta_id = mvm_sta->sta_id;
if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) {
ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id,
false);
goto end;
}
/* /*
* It is possible that the 'sta' parameter is NULL, and thus * It is possible that the 'sta' parameter is NULL, and thus
* there is a need to retrieve the sta from the local station * there is a need to retrieve the sta from the local station
* table. * table.
*/ */
if (!sta) { if (!sta) {
...@@ -3258,6 +3239,17 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, ...@@ -3258,6 +3239,17 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif)) if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
return -EINVAL; return -EINVAL;
} else {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
sta_id = mvmvif->mcast_sta.sta_id;
}
if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) {
ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, false);
goto end;
} }
/* If the key_offset is not pre-assigned, we need to find a /* If the key_offset is not pre-assigned, we need to find a
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -18,11 +19,6 @@ ...@@ -18,11 +19,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution * The full GNU General Public License is included in this distribution
* in the file called COPYING. * in the file called COPYING.
* *
...@@ -35,6 +31,7 @@ ...@@ -35,6 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -198,9 +195,13 @@ static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm, ...@@ -198,9 +195,13 @@ static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
const char *errmsg) const char *errmsg)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (vif->type != NL80211_IFTYPE_STATION) if (vif->type != NL80211_IFTYPE_STATION)
return false; return false;
if (vif->bss_conf.assoc && vif->bss_conf.dtim_period)
if (!mvmvif->csa_bcn_pending && vif->bss_conf.assoc &&
vif->bss_conf.dtim_period)
return false; return false;
if (errmsg) if (errmsg)
IWL_ERR(mvm, "%s\n", errmsg); IWL_ERR(mvm, "%s\n", errmsg);
...@@ -344,7 +345,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, ...@@ -344,7 +345,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
* and know the dtim period. * and know the dtim period.
*/ */
iwl_mvm_te_check_disconnect(mvm, te_data->vif, iwl_mvm_te_check_disconnect(mvm, te_data->vif,
"No association and the time event is over already..."); "No beacon heard and the time event is over already...");
break; break;
default: default:
break; break;
......
...@@ -1894,14 +1894,12 @@ int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal, u32 flags) ...@@ -1894,14 +1894,12 @@ int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal, u32 flags)
struct iwl_mvm_int_sta *int_sta = sta; struct iwl_mvm_int_sta *int_sta = sta;
struct iwl_mvm_sta *mvm_sta = sta; struct iwl_mvm_sta *mvm_sta = sta;
if (iwl_mvm_has_new_tx_api(mvm)) { BUILD_BUG_ON(offsetof(struct iwl_mvm_int_sta, sta_id) !=
if (internal) offsetof(struct iwl_mvm_sta, sta_id));
return iwl_mvm_flush_sta_tids(mvm, int_sta->sta_id,
BIT(IWL_MGMT_TID), flags);
if (iwl_mvm_has_new_tx_api(mvm))
return iwl_mvm_flush_sta_tids(mvm, mvm_sta->sta_id, return iwl_mvm_flush_sta_tids(mvm, mvm_sta->sta_id,
0xFF, flags); 0xff | BIT(IWL_MGMT_TID), flags);
}
if (internal) if (internal)
return iwl_mvm_flush_tx_path(mvm, int_sta->tfd_queue_msk, return iwl_mvm_flush_tx_path(mvm, int_sta->tfd_queue_msk,
......
...@@ -579,25 +579,25 @@ static const struct pci_device_id iwl_hw_card_ids[] = { ...@@ -579,25 +579,25 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x30DC, 0x0264, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x0264, iwl9461_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x30DC, 0x02A0, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x02A0, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x30DC, 0x02A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x02A4, iwl9462_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x0034, iwl9560_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0038, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x0038, iwl9560_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x003C, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x003C, iwl9560_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0060, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x0060, iwl9460_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x0064, iwl9461_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x00A0, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x00A0, iwl9462_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x00A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x00A4, iwl9462_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0230, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x0230, iwl9560_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x0234, iwl9560_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0238, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x0238, iwl9560_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x023C, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x023C, iwl9560_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0260, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x0260, iwl9461_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x0264, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x0264, iwl9461_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x02A0, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x02A0, iwl9462_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x02A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x02A4, iwl9462_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x4030, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x4030, iwl9560_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x4034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x4034, iwl9560_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x31DC, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x31DC, 0x40A4, iwl9462_2ac_cfg_shared_clk)},
{IWL_PCI_DEVICE(0x34F0, 0x0030, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x34F0, 0x0030, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x34F0, 0x0034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x34F0, 0x0034, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x34F0, 0x02A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x34F0, 0x02A4, iwl9462_2ac_cfg_soc)},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment