wireless-drivers fixes for v5.5

First set of fixes for v5.5. Fixing security issues, some regressions
 and few major bugs.
 
 mwifiex
 
 * security fix for handling country Information Elements (CVE-2019-14895)
 
 * security fix for handling TDLS Information Elements
 
 ath9k
 
 * fix endian issue with ath9k_pci_owl_loader
 
 mt76
 
 * fix default mac address handling
 
 iwlwifi
 
 * fix merge damage which lead to firmware crashing during boot on some devices
 
 * fix device initialisation regression on some devices
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJd+P4eAAoJEG4XJFUm622bnOQH/RHSFFQNjxfPboZoozKb0/mT
 6YtrG+0K1z8E21Os2bd+s4aRJgq1oGKDocMie5y53M38qQ5N3FchzcGopNRCRy/a
 gF1PzEqceOysbEtPOx4yI+c0Gfi7rS0SjEyf2XKGowXsoIZh4j+1xlWbF/JtHt6n
 J901W1GW0ZUCHaP8KuZcbsS2nfdV8tFW2NQW3Xuhy+nOdBhNRL/lKSvlhZLCCAfY
 f1eJrB0rAzQpCqw8Wuz2JzWsxBiTt+6Ucuzv4EkFVrt7Xnj00feghTKJkVDqa+fL
 B9hTiiYh8sLGJkYHsZLDZIzAdOW8jmun1I+XFsjdl7ucLRYz6U8NL9jc6oIGK00=
 =KJmM
 -----END PGP SIGNATURE-----

Merge tag 'wireless-drivers-2019-12-17' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers

Kalle Valo says:

====================
wireless-drivers fixes for v5.5

First set of fixes for v5.5. Fixing security issues, some regressions
and few major bugs.

mwifiex

* security fix for handling country Information Elements (CVE-2019-14895)

* security fix for handling TDLS Information Elements

ath9k

* fix endian issue with ath9k_pci_owl_loader

mt76

* fix default mac address handling

iwlwifi

* fix merge damage which lead to firmware crashing during boot on some devices

* fix device initialisation regression on some devices
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2019-12-17 14:27:35 -08:00
commit 040cda8a15
7 changed files with 122 additions and 47 deletions

View File

@ -83,7 +83,7 @@ static int ath9k_pci_fixup(struct pci_dev *pdev, const u16 *cal_data,
val = swahb32(val);
}
__raw_writel(val, mem + reg);
iowrite32(val, mem + reg);
usleep_range(100, 120);
}

View File

@ -1111,18 +1111,18 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* same thing for QuZ... */
if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) {
if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr)
iwl_trans->cfg = &iwl_ax101_cfg_quz_hr;
else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr)
iwl_trans->cfg = &iwl_ax201_cfg_quz_hr;
else if (iwl_trans->cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
iwl_trans->cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc;
else if (iwl_trans->cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
iwl_trans->cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc;
else if (iwl_trans->cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
iwl_trans->cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc;
else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
iwl_trans->cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc;
if (cfg == &iwl_ax101_cfg_qu_hr)
cfg = &iwl_ax101_cfg_quz_hr;
else if (cfg == &iwl_ax201_cfg_qu_hr)
cfg = &iwl_ax201_cfg_quz_hr;
else if (cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc;
else if (cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc;
else if (cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc;
else if (cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc;
}
#endif

View File

@ -57,24 +57,6 @@
#include "internal.h"
#include "fw/dbg.h"
static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
{
iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
udelay(20);
iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
HPM_HIPM_GEN_CFG_CR_PG_EN |
HPM_HIPM_GEN_CFG_CR_SLP_EN);
udelay(20);
iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
iwl_trans_sw_reset(trans);
iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
return 0;
}
/*
* Start up NIC's basic functionality after it has been reset
* (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop())
@ -110,13 +92,6 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
iwl_pcie_apm_config(trans);
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
trans->cfg->integrated) {
ret = iwl_pcie_gen2_force_power_gating(trans);
if (ret)
return ret;
}
ret = iwl_finish_nic_init(trans, trans->trans_cfg);
if (ret)
return ret;

View File

@ -1783,6 +1783,29 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
return 0;
}
static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
{
int ret;
ret = iwl_finish_nic_init(trans, trans->trans_cfg);
if (ret < 0)
return ret;
iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
udelay(20);
iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
HPM_HIPM_GEN_CFG_CR_PG_EN |
HPM_HIPM_GEN_CFG_CR_SLP_EN);
udelay(20);
iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
iwl_trans_pcie_sw_reset(trans);
return 0;
}
static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@ -1802,6 +1825,13 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
iwl_trans_pcie_sw_reset(trans);
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
trans->cfg->integrated) {
err = iwl_pcie_gen2_force_power_gating(trans);
if (err)
return err;
}
err = iwl_pcie_apm_init(trans);
if (err)
return err;

View File

@ -229,6 +229,14 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,
"11D: skip setting domain info in FW\n");
return 0;
}
if (country_ie_len >
(IEEE80211_COUNTRY_STRING_LEN + MWIFIEX_MAX_TRIPLET_802_11D)) {
mwifiex_dbg(priv->adapter, ERROR,
"11D: country_ie_len overflow!, deauth AP\n");
return -EINVAL;
}
memcpy(priv->adapter->country_code, &country_ie[2], 2);
domain_info->country_code[0] = country_ie[2];
@ -272,8 +280,9 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
priv->scan_block = false;
if (bss) {
if (adapter->region_code == 0x00)
mwifiex_process_country_ie(priv, bss);
if (adapter->region_code == 0x00 &&
mwifiex_process_country_ie(priv, bss))
return -EINVAL;
/* Allocate and fill new bss descriptor */
bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),

View File

@ -953,59 +953,117 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
switch (*pos) {
case WLAN_EID_SUPP_RATES:
if (pos[1] > 32)
return;
sta_ptr->tdls_cap.rates_len = pos[1];
for (i = 0; i < pos[1]; i++)
sta_ptr->tdls_cap.rates[i] = pos[i + 2];
break;
case WLAN_EID_EXT_SUPP_RATES:
if (pos[1] > 32)
return;
basic = sta_ptr->tdls_cap.rates_len;
if (pos[1] > 32 - basic)
return;
for (i = 0; i < pos[1]; i++)
sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
sta_ptr->tdls_cap.rates_len += pos[1];
break;
case WLAN_EID_HT_CAPABILITY:
memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
if (pos > end - sizeof(struct ieee80211_ht_cap) - 2)
return;
if (pos[1] != sizeof(struct ieee80211_ht_cap))
return;
/* copy the ie's value into ht_capb*/
memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2,
sizeof(struct ieee80211_ht_cap));
sta_ptr->is_11n_enabled = 1;
break;
case WLAN_EID_HT_OPERATION:
memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
if (pos > end -
sizeof(struct ieee80211_ht_operation) - 2)
return;
if (pos[1] != sizeof(struct ieee80211_ht_operation))
return;
/* copy the ie's value into ht_oper*/
memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2,
sizeof(struct ieee80211_ht_operation));
break;
case WLAN_EID_BSS_COEX_2040:
if (pos > end - 3)
return;
if (pos[1] != 1)
return;
sta_ptr->tdls_cap.coex_2040 = pos[2];
break;
case WLAN_EID_EXT_CAPABILITY:
if (pos > end - sizeof(struct ieee_types_header))
return;
if (pos[1] < sizeof(struct ieee_types_header))
return;
if (pos[1] > 8)
return;
memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
sizeof(struct ieee_types_header) +
min_t(u8, pos[1], 8));
break;
case WLAN_EID_RSN:
if (pos > end - sizeof(struct ieee_types_header))
return;
if (pos[1] < sizeof(struct ieee_types_header))
return;
if (pos[1] > IEEE_MAX_IE_SIZE -
sizeof(struct ieee_types_header))
return;
memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
sizeof(struct ieee_types_header) +
min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
sizeof(struct ieee_types_header)));
break;
case WLAN_EID_QOS_CAPA:
if (pos > end - 3)
return;
if (pos[1] != 1)
return;
sta_ptr->tdls_cap.qos_info = pos[2];
break;
case WLAN_EID_VHT_OPERATION:
if (priv->adapter->is_hw_11ac_capable)
memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
if (priv->adapter->is_hw_11ac_capable) {
if (pos > end -
sizeof(struct ieee80211_vht_operation) - 2)
return;
if (pos[1] !=
sizeof(struct ieee80211_vht_operation))
return;
/* copy the ie's value into vhtoper*/
memcpy(&sta_ptr->tdls_cap.vhtoper, pos + 2,
sizeof(struct ieee80211_vht_operation));
}
break;
case WLAN_EID_VHT_CAPABILITY:
if (priv->adapter->is_hw_11ac_capable) {
memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
if (pos > end -
sizeof(struct ieee80211_vht_cap) - 2)
return;
if (pos[1] != sizeof(struct ieee80211_vht_cap))
return;
/* copy the ie's value into vhtcap*/
memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2,
sizeof(struct ieee80211_vht_cap));
sta_ptr->is_11ac_enabled = 1;
}
break;
case WLAN_EID_AID:
if (priv->adapter->is_hw_11ac_capable)
if (priv->adapter->is_hw_11ac_capable) {
if (pos > end - 4)
return;
if (pos[1] != 2)
return;
sta_ptr->tdls_cap.aid =
get_unaligned_le16((pos + 2));
}
break;
default:
break;
}

View File

@ -342,8 +342,11 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev)
dev_info(dev->mt76.dev, "EEPROM ver:%02hhx fae:%02hhx\n",
version, fae);
mt76x02_mac_setaddr(dev, dev->mt76.eeprom.data + MT_EE_MAC_ADDR);
memcpy(dev->mt76.macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
ETH_ALEN);
mt76_eeprom_override(&dev->mt76);
mt76x02_mac_setaddr(dev, dev->mt76.macaddr);
mt76x0_set_chip_cap(dev);
mt76x0_set_freq_offset(dev);
mt76x0_set_temp_offset(dev);