diff options
35 files changed, 191 insertions, 199 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 4a953a5fd666..cf44acd87be0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3323,7 +3323,6 @@ F: drivers/net/wimax/i2400m/ F: include/linux/wimax/i2400m.h INTEL WIRELESS WIFI LINK (iwlwifi) -M: Reinette Chatre <reinette.chatre@intel.com> M: Wey-Yi Guy <wey-yi.w.guy@intel.com> M: Intel Linux Wireless <ilw@linux.intel.com> L: linux-wireless@vger.kernel.org diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 949ed09c6361..a126e614601f 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -47,46 +47,40 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); #define USB_REQ_DFU_DNLOAD 1 #define BULK_SIZE 4096 -struct ath3k_data { - struct usb_device *udev; - u8 *fw_data; - u32 fw_size; - u32 fw_sent; -}; - -static int ath3k_load_firmware(struct ath3k_data *data, - unsigned char *firmware, - int count) +static int ath3k_load_firmware(struct usb_device *udev, + const struct firmware *firmware) { u8 *send_buf; int err, pipe, len, size, sent = 0; + int count = firmware->size; - BT_DBG("ath3k %p udev %p", data, data->udev); + BT_DBG("udev %p", udev); - pipe = usb_sndctrlpipe(data->udev, 0); + pipe = usb_sndctrlpipe(udev, 0); - if ((usb_control_msg(data->udev, pipe, + send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); + if (!send_buf) { + BT_ERR("Can't allocate memory chunk for firmware"); + return -ENOMEM; + } + + memcpy(send_buf, firmware->data, 20); + if ((err = usb_control_msg(udev, pipe, USB_REQ_DFU_DNLOAD, USB_TYPE_VENDOR, 0, 0, - firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) { + send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) { BT_ERR("Can't change to loading configuration err"); - return -EBUSY; + goto error; } sent += 20; count -= 20; - send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); - if (!send_buf) { - BT_ERR("Can't allocate memory chunk for firmware"); - return -ENOMEM; - } - while (count) { size = min_t(uint, count, BULK_SIZE); - pipe = usb_sndbulkpipe(data->udev, 0x02); - memcpy(send_buf, firmware + sent, size); + pipe = usb_sndbulkpipe(udev, 0x02); + memcpy(send_buf, firmware->data + sent, size); - err = usb_bulk_msg(data->udev, pipe, send_buf, size, + err = usb_bulk_msg(udev, pipe, send_buf, size, &len, 3000); if (err || (len != size)) { @@ -112,57 +106,28 @@ static int ath3k_probe(struct usb_interface *intf, { const struct firmware *firmware; struct usb_device *udev = interface_to_usbdev(intf); - struct ath3k_data *data; - int size; BT_DBG("intf %p id %p", intf, id); if (intf->cur_altsetting->desc.bInterfaceNumber != 0) return -ENODEV; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->udev = udev; - if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) { - kfree(data); return -EIO; } - size = max_t(uint, firmware->size, 4096); - data->fw_data = kmalloc(size, GFP_KERNEL); - if (!data->fw_data) { + if (ath3k_load_firmware(udev, firmware)) { release_firmware(firmware); - kfree(data); - return -ENOMEM; - } - - memcpy(data->fw_data, firmware->data, firmware->size); - data->fw_size = firmware->size; - data->fw_sent = 0; - release_firmware(firmware); - - usb_set_intfdata(intf, data); - if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) { - usb_set_intfdata(intf, NULL); - kfree(data->fw_data); - kfree(data); return -EIO; } + release_firmware(firmware); return 0; } static void ath3k_disconnect(struct usb_interface *intf) { - struct ath3k_data *data = usb_get_intfdata(intf); - BT_DBG("ath3k_disconnect intf %p", intf); - - kfree(data->fw_data); - kfree(data); } static struct usb_driver ath3k_driver = { diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index e9e7af6e4b62..dbc45e085434 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2280,6 +2280,8 @@ ath5k_tx_complete_poll_work(struct work_struct *work) int i; bool needreset = false; + mutex_lock(&sc->lock); + for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { if (sc->txqs[i].setup) { txq = &sc->txqs[i]; @@ -2307,6 +2309,8 @@ ath5k_tx_complete_poll_work(struct work_struct *work) ath5k_reset(sc, NULL, true); } + mutex_unlock(&sc->lock); + ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT)); } diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 0064be7ce5c9..21091c26a9a5 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -838,9 +838,9 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah) for (i = 0; i < qmax; i++) { err = ath5k_hw_stop_tx_dma(ah, i); /* -EINVAL -> queue inactive */ - if (err != -EINVAL) + if (err && err != -EINVAL) return err; } - return err; + return 0; } diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index e5f2b96a4c63..a702817daf72 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -86,7 +86,7 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, if (!ah->ah_bwmode) { dur = ieee80211_generic_frame_duration(sc->hw, NULL, len, rate); - return dur; + return le16_to_cpu(dur); } bitrate = rate->bitrate; @@ -265,8 +265,6 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) * what rate we should choose to TX ACKs. */ tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); - tx_time = le16_to_cpu(tx_time); - ath5k_hw_reg_write(ah, tx_time, reg); if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 14d7d2a68ec5..76388c6d6692 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -679,10 +679,6 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, /* Do NF cal only at longer intervals */ if (longcal || nfcal_pending) { - /* Do periodic PAOffset Cal */ - ar9002_hw_pa_cal(ah, false); - ar9002_hw_olc_temp_compensation(ah); - /* * Get the value from the previous NF cal and update * history buffer. @@ -697,8 +693,12 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, ath9k_hw_loadnf(ah, ah->curchan); } - if (longcal) + if (longcal) { ath9k_hw_start_nfcal(ah, false); + /* Do periodic PAOffset Cal */ + ar9002_hw_pa_cal(ah, false); + ar9002_hw_olc_temp_compensation(ah); + } } return iscaldone; diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index f8a7771faee2..f44c84ab5dce 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -426,9 +426,8 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, } /* WAR for ASPM system hang */ - if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { + if (AR_SREV_9285(ah) || AR_SREV_9287(ah)) val |= (AR_WA_BIT6 | AR_WA_BIT7); - } if (AR_SREV_9285E_20(ah)) val |= AR_WA_BIT23; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 81f9cf294dec..9ecca93392e8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -1842,7 +1842,7 @@ static const u32 ar9300_2p2_soc_preamble[][2] = { static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = { /* Addr allmodes */ - {0x00004040, 0x08212e5e}, + {0x00004040, 0x0821265e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 6137634e46ca..06fb2c850535 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -146,8 +146,8 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) /* Sleep Setting */ INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, - ar9300PciePhy_clkreq_enable_L1_2p2, - ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2), + ar9300PciePhy_pll_on_clkreq_disable_L1_2p2, + ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2), 2); /* Fast clock modal settings */ diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index c976600ba255..63549868e686 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -78,7 +78,7 @@ struct tx_frame_hdr { u8 node_idx; u8 vif_idx; u8 tidno; - u32 flags; /* ATH9K_HTC_TX_* */ + __be32 flags; /* ATH9K_HTC_TX_* */ u8 key_type; u8 keyix; u8 reserved[26]; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 8e04586c5256..a7bc26d1bd66 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -142,9 +142,6 @@ static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) { ath9k_htc_exit_debug(priv->ah); ath9k_hw_deinit(priv->ah); - tasklet_kill(&priv->swba_tasklet); - tasklet_kill(&priv->rx_tasklet); - tasklet_kill(&priv->tx_tasklet); kfree(priv->ah); priv->ah = NULL; } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index f14f37d29f45..a702089f18d0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1026,12 +1026,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) int ret = 0; u8 cmd_rsp; - /* Cancel all the running timers/work .. */ - cancel_work_sync(&priv->fatal_work); - cancel_work_sync(&priv->ps_work); - cancel_delayed_work_sync(&priv->ath9k_led_blink_work); - ath9k_led_stop_brightness(priv); - mutex_lock(&priv->mutex); if (priv->op_flags & OP_INVALID) { @@ -1045,8 +1039,23 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); + + tasklet_kill(&priv->swba_tasklet); + tasklet_kill(&priv->rx_tasklet); + tasklet_kill(&priv->tx_tasklet); + skb_queue_purge(&priv->tx_queue); + mutex_unlock(&priv->mutex); + + /* Cancel all the running timers/work .. */ + cancel_work_sync(&priv->fatal_work); + cancel_work_sync(&priv->ps_work); + cancel_delayed_work_sync(&priv->ath9k_led_blink_work); + ath9k_led_stop_brightness(priv); + + mutex_lock(&priv->mutex); + /* Remove monitor interface here */ if (ah->opmode == NL80211_IFTYPE_MONITOR) { if (ath9k_htc_remove_monitor_interface(priv)) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 33f36029fa4f..7a5ffca21958 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -113,6 +113,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) if (ieee80211_is_data(fc)) { struct tx_frame_hdr tx_hdr; + u32 flags = 0; u8 *qc; memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); @@ -136,13 +137,14 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) /* Check for RTS protection */ if (priv->hw->wiphy->rts_threshold != (u32) -1) if (skb->len > priv->hw->wiphy->rts_threshold) - tx_hdr.flags |= ATH9K_HTC_TX_RTSCTS; + flags |= ATH9K_HTC_TX_RTSCTS; /* CTS-to-self */ - if (!(tx_hdr.flags & ATH9K_HTC_TX_RTSCTS) && + if (!(flags & ATH9K_HTC_TX_RTSCTS) && (priv->op_flags & OP_PROTECT_ENABLE)) - tx_hdr.flags |= ATH9K_HTC_TX_CTSONLY; + flags |= ATH9K_HTC_TX_CTSONLY; + tx_hdr.flags = cpu_to_be32(flags); tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ca6f10b8947a..f9cf81551817 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -369,6 +369,9 @@ static void ath9k_hw_init_config(struct ath_hw *ah) else ah->config.ht_enable = 0; + /* PAPRD needs some more work to be enabled */ + ah->config.paprd_disable = 1; + ah->config.rx_intr_mitigation = true; ah->config.pcieSerDesWrite = true; @@ -1971,7 +1974,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->rx_status_len = sizeof(struct ar9003_rxs); pCap->tx_desc_len = sizeof(struct ar9003_txc); pCap->txs_len = sizeof(struct ar9003_txs); - if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) + if (!ah->config.paprd_disable && + ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; } else { pCap->tx_desc_len = sizeof(struct ath_desc); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 8c688a12cba8..ef79f4c876ca 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -228,6 +228,7 @@ struct ath9k_ops_config { u32 pcie_waen; u8 analog_shiftreg; u8 ht_enable; + u8 paprd_disable; u32 ofdm_trig_low; u32 ofdm_trig_high; u32 cck_trig_high; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index c1e159219065..e5c1eead98a2 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -600,8 +600,6 @@ err_btcoex: err_queues: ath9k_hw_deinit(ah); err_hw: - tasklet_kill(&sc->intr_tq); - tasklet_kill(&sc->bcon_tasklet); kfree(ah); sc->sc_ah = NULL; @@ -805,9 +803,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc) ath9k_hw_deinit(sc->sc_ah); - tasklet_kill(&sc->intr_tq); - tasklet_kill(&sc->bcon_tasklet); - kfree(sc->sc_ah); sc->sc_ah = NULL; } @@ -821,6 +816,8 @@ void ath9k_deinit_device(struct ath_softc *sc) wiphy_rfkill_stop_polling(sc->hw->wiphy); ath_deinit_leds(sc); + ath9k_ps_restore(sc); + ieee80211_unregister_hw(hw); pm_qos_remove_request(&sc->pm_qos_req); ath_rx_cleanup(sc); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 91af57c48581..20c70ba45753 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -611,14 +611,12 @@ void ath9k_tasklet(unsigned long data) u32 status = sc->intrstatus; u32 rxmask; - ath9k_ps_wakeup(sc); - if (status & ATH9K_INT_FATAL) { ath_reset(sc, true); - ath9k_ps_restore(sc); return; } + ath9k_ps_wakeup(sc); spin_lock(&sc->sc_pcu_lock); /* @@ -939,8 +937,6 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) spin_unlock_bh(&sc->sc_pcu_lock); ath9k_ps_restore(sc); - - ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); } int ath_reset(struct ath_softc *sc, bool retry_tx) @@ -953,6 +949,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) /* Stop ANI */ del_timer_sync(&common->ani.timer); + ath9k_ps_wakeup(sc); spin_lock_bh(&sc->sc_pcu_lock); ieee80211_stop_queues(hw); @@ -999,6 +996,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) /* Start ANI */ ath_start_ani(common); + ath9k_ps_restore(sc); return r; } @@ -1220,6 +1218,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) spin_lock_bh(&sc->sc_pcu_lock); + /* prevent tasklets to enable interrupts once we disable them */ + ah->imask &= ~ATH9K_INT_GLOBAL; + /* make sure h/w will not generate any interrupt * before setting the invalid flag. */ ath9k_hw_disable_interrupts(ah); @@ -1242,6 +1243,12 @@ static void ath9k_stop(struct ieee80211_hw *hw) spin_unlock_bh(&sc->sc_pcu_lock); + /* we can now sync irq and kill any running tasklets, since we already + * disabled interrupts and not holding a spin lock */ + synchronize_irq(sc->irq); + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); + ath9k_ps_restore(sc); sc->ps_idle = true; @@ -1706,7 +1713,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_POWER) { sc->config.txpowlimit = 2 * conf->power_level; + ath9k_ps_wakeup(sc); ath_update_txpow(sc); + ath9k_ps_restore(sc); } if (disable_radio) { diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index d211aa7f1a3b..68a1c7612e9b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2173,9 +2173,7 @@ static void ath_tx_complete_poll_work(struct work_struct *work) if (needreset) { ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, "tx hung, resetting the chip\n"); - ath9k_ps_wakeup(sc); ath_reset(sc, true); - ath9k_ps_restore(sc); } ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 053240642b50..7c14eb31d954 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2629,6 +2629,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .fw_name_pre = IWL4965_FW_PRE, .ucode_api_max = IWL4965_UCODE_API_MAX, .ucode_api_min = IWL4965_UCODE_API_MIN, + .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_ABC, .eeprom_ver = EEPROM_4965_EEPROM_VERSION, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index 97906dd442e6..27b5a3eec9dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -152,11 +152,14 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv) eeprom_sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); - priv->cfg->sku = ((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >> + if (!priv->cfg->sku) { + /* not using sku overwrite */ + priv->cfg->sku = + ((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >> EEPROM_SKU_CAP_BAND_POS); - if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE) - priv->cfg->sku |= IWL_SKU_N; - + if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE) + priv->cfg->sku |= IWL_SKU_N; + } if (!priv->cfg->sku) { IWL_ERR(priv, "Invalid device sku\n"); return -EINVAL; @@ -168,7 +171,7 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv) /* not using .cfg overwrite */ radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); - priv->cfg->valid_rx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); + priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) { IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n", priv->cfg->valid_tx_ant, diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c index 13a69ebf2a94..5091d77e02ce 100644 --- a/drivers/net/wireless/iwmc3200wifi/netdev.c +++ b/drivers/net/wireless/iwmc3200wifi/netdev.c @@ -126,6 +126,7 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES); if (!ndev) { dev_err(dev, "no memory for network device instance\n"); + ret = -ENOMEM; goto out_priv; } @@ -138,6 +139,7 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, GFP_KERNEL); if (!iwm->umac_profile) { dev_err(dev, "Couldn't alloc memory for profile\n"); + ret = -ENOMEM; goto out_profile; } diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index f0e1eb72befc..be0ff78c1b16 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -58,6 +58,7 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) if (!fw || !fw->size || !fw->data) { ERROR(rt2x00dev, "Failed to read Firmware.\n"); + release_firmware(fw); return -ENOENT; } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 0b4e8590cbb7..029be3c6c030 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2446,6 +2446,7 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) }, /* Qcom */ { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) }, diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index b8433f3a9bc2..62876cd5c41a 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c @@ -726,9 +726,9 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) } static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, - u8 efuse_data, u8 offset, int *bcontinual, - u8 *write_state, struct pgpkt_struct target_pkt, - int *repeat_times, int *bresult, u8 word_en) + u8 efuse_data, u8 offset, int *bcontinual, + u8 *write_state, struct pgpkt_struct *target_pkt, + int *repeat_times, int *bresult, u8 word_en) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct pgpkt_struct tmp_pkt; @@ -744,8 +744,8 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, tmp_pkt.word_en = tmp_header & 0x0F; tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en); - if (tmp_pkt.offset != target_pkt.offset) { - efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; + if (tmp_pkt.offset != target_pkt->offset) { + *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; *write_state = PG_STATE_HEADER; } else { for (tmpindex = 0; tmpindex < (tmp_word_cnts * 2); tmpindex++) { @@ -756,23 +756,23 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, } if (bdataempty == false) { - efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; + *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; *write_state = PG_STATE_HEADER; } else { match_word_en = 0x0F; - if (!((target_pkt.word_en & BIT(0)) | + if (!((target_pkt->word_en & BIT(0)) | (tmp_pkt.word_en & BIT(0)))) match_word_en &= (~BIT(0)); - if (!((target_pkt.word_en & BIT(1)) | + if (!((target_pkt->word_en & BIT(1)) | (tmp_pkt.word_en & BIT(1)))) match_word_en &= (~BIT(1)); - if (!((target_pkt.word_en & BIT(2)) | + if (!((target_pkt->word_en & BIT(2)) | (tmp_pkt.word_en & BIT(2)))) match_word_en &= (~BIT(2)); - if (!((target_pkt.word_en & BIT(3)) | + if (!((target_pkt->word_en & BIT(3)) | (tmp_pkt.word_en & BIT(3)))) match_word_en &= (~BIT(3)); @@ -780,7 +780,7 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, badworden = efuse_word_enable_data_write( hw, *efuse_addr + 1, tmp_pkt.word_en, - target_pkt.data); + target_pkt->data); if (0x0F != (badworden & 0x0F)) { u8 reorg_offset = offset; @@ -791,26 +791,26 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, } tmp_word_en = 0x0F; - if ((target_pkt.word_en & BIT(0)) ^ + if ((target_pkt->word_en & BIT(0)) ^ (match_word_en & BIT(0))) tmp_word_en &= (~BIT(0)); - if ((target_pkt.word_en & BIT(1)) ^ + if ((target_pkt->word_en & BIT(1)) ^ (match_word_en & BIT(1))) tmp_word_en &= (~BIT(1)); - if ((target_pkt.word_en & BIT(2)) ^ + if ((target_pkt->word_en & BIT(2)) ^ (match_word_en & BIT(2))) tmp_word_en &= (~BIT(2)); - if ((target_pkt.word_en & BIT(3)) ^ + if ((target_pkt->word_en & BIT(3)) ^ (match_word_en & BIT(3))) tmp_word_en &= (~BIT(3)); if ((tmp_word_en & 0x0F) != 0x0F) { *efuse_addr = efuse_get_current_size(hw); - target_pkt.offset = offset; - target_pkt.word_en = tmp_word_en; + target_pkt->offset = offset; + target_pkt->word_en = tmp_word_en; } else *bcontinual = false; *write_state = PG_STATE_HEADER; @@ -821,8 +821,8 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, } } else { *efuse_addr += (2 * tmp_word_cnts) + 1; - target_pkt.offset = offset; - target_pkt.word_en = word_en; + target_pkt->offset = offset; + target_pkt->word_en = word_en; *write_state = PG_STATE_HEADER; } } @@ -938,7 +938,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, efuse_write_data_case1(hw, &efuse_addr, efuse_data, offset, &bcontinual, - &write_state, target_pkt, + &write_state, &target_pkt, &repeat_times, &bresult, word_en); else diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 0fa36aa6701a..1758d4463247 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -619,6 +619,13 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) struct sk_buff *uskb = NULL; u8 *pdata; uskb = dev_alloc_skb(skb->len + 128); + if (!uskb) { + RT_TRACE(rtlpriv, + (COMP_INTR | COMP_RECV), + DBG_EMERG, + ("can't alloc rx skb\n")); + goto done; + } memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status)); @@ -641,7 +648,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) new_skb = dev_alloc_skb(rtlpci->rxbuffersize); if (unlikely(!new_skb)) { RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), - DBG_DMESG, + DBG_EMERG, ("can't alloc skb for rx\n")); goto done; } @@ -1066,9 +1073,9 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) struct sk_buff *skb = dev_alloc_skb(rtlpci->rxbuffersize); u32 bufferaddress; - entry = &rtlpci->rx_ring[rx_queue_idx].desc[i]; if (!skb) return 0; + entry = &rtlpci->rx_ring[rx_queue_idx].desc[i]; /*skb->dev = dev; */ diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 6042228954a7..294169e31364 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -959,7 +959,7 @@ struct ieee80211_ht_info { /* block-ack parameters */ #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C -#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 +#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFC0 #define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index a29feb01854e..d2cf88407690 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -184,6 +184,7 @@ struct hci_conn { __u32 link_mode; __u8 auth_type; __u8 sec_level; + __u8 pending_sec_level; __u8 power_save; __u16 disc_timeout; unsigned long pend; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 6b90a4191734..99cd8d9d891b 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -379,14 +379,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 hci_conn_hold(acl); if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { - acl->sec_level = sec_level; + acl->sec_level = BT_SECURITY_LOW; + acl->pending_sec_level = sec_level; acl->auth_type = auth_type; hci_acl_connect(acl); - } else { - if (acl->sec_level < sec_level) - acl->sec_level = sec_level; - if (acl->auth_type < auth_type) - acl->auth_type = auth_type; } if (type == ACL_LINK) @@ -442,11 +438,17 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) { BT_DBG("conn %p", conn); + if (conn->pending_sec_level > sec_level) + sec_level = conn->pending_sec_level; + if (sec_level > conn->sec_level) - conn->sec_level = sec_level; + conn->pending_sec_level = sec_level; else if (conn->link_mode & HCI_LM_AUTH) return 1; + /* Make sure we preserve an existing MITM requirement*/ + auth_type |= (conn->auth_type & 0x01); + conn->auth_type = auth_type; if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 8b602d881fd7..9c4541bc488a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1011,6 +1011,10 @@ int hci_unregister_dev(struct hci_dev *hdev) destroy_workqueue(hdev->workqueue); + hci_dev_lock_bh(hdev); + hci_blacklist_clear(hdev); + hci_dev_unlock_bh(hdev); + __hci_dev_put(hdev); return 0; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 38100170d380..a290854fdaa6 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -692,13 +692,13 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev, if (conn->state != BT_CONFIG || !conn->out) return 0; - if (conn->sec_level == BT_SECURITY_SDP) + if (conn->pending_sec_level == BT_SECURITY_SDP) return 0; /* Only request authentication for SSP connections or non-SSP * devices with sec_level HIGH */ if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && - conn->sec_level != BT_SECURITY_HIGH) + conn->pending_sec_level != BT_SECURITY_HIGH) return 0; return 1; @@ -1095,9 +1095,10 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (conn) { - if (!ev->status) + if (!ev->status) { conn->link_mode |= HCI_LM_AUTH; - else + conn->sec_level = conn->pending_sec_level; + } else conn->sec_level = BT_SECURITY_LOW; clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index c791fcda7b2d..7550abb0c96a 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -305,33 +305,44 @@ static void l2cap_chan_del(struct sock *sk, int err) } } -/* Service level security */ -static inline int l2cap_check_security(struct sock *sk) +static inline u8 l2cap_get_auth_type(struct sock *sk) { - struct l2cap_conn *conn = l2cap_pi(sk)->conn; - __u8 auth_type; + if (sk->sk_type == SOCK_RAW) { + switch (l2cap_pi(sk)->sec_level) { + case BT_SECURITY_HIGH: + return HCI_AT_DEDICATED_BONDING_MITM; + case BT_SECURITY_MEDIUM: + return HCI_AT_DEDICATED_BONDING; + default: + return HCI_AT_NO_BONDING; + } + } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) { + if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW) + l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; - if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) { if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) - auth_type = HCI_AT_NO_BONDING_MITM; + return HCI_AT_NO_BONDING_MITM; else - auth_type = HCI_AT_NO_BONDING; - - if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW) - l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; + return HCI_AT_NO_BONDING; } else { switch (l2cap_pi(sk)->sec_level) { case BT_SECURITY_HIGH: - auth_type = HCI_AT_GENERAL_BONDING_MITM; - break; + return HCI_AT_GENERAL_BONDING_MITM; case BT_SECURITY_MEDIUM: - auth_type = HCI_AT_GENERAL_BONDING; - break; + return HCI_AT_GENERAL_BONDING; default: - auth_type = HCI_AT_NO_BONDING; - break; + return HCI_AT_NO_BONDING; } } +} + +/* Service level security */ +static inline int l2cap_check_security(struct sock *sk) +{ + struct l2cap_conn *conn = l2cap_pi(sk)->conn; + __u8 auth_type; + + auth_type = l2cap_get_auth_type(sk); return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level, auth_type); @@ -1068,39 +1079,7 @@ static int l2cap_do_connect(struct sock *sk) err = -ENOMEM; - if (sk->sk_type == SOCK_RAW) { - switch (l2cap_pi(sk)->sec_level) { - case BT_SECURITY_HIGH: - auth_type = HCI_AT_DEDICATED_BONDING_MITM; - break; - case BT_SECURITY_MEDIUM: - auth_type = HCI_AT_DEDICATED_BONDING; - break; - default: - auth_type = HCI_AT_NO_BONDING; - break; - } - } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) { - if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) - auth_type = HCI_AT_NO_BONDING_MITM; - else - auth_type = HCI_AT_NO_BONDING; - - if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW) - l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; - } else { - switch (l2cap_pi(sk)->sec_level) { - case BT_SECURITY_HIGH: - auth_type = HCI_AT_GENERAL_BONDING_MITM; - break; - case BT_SECURITY_MEDIUM: - auth_type = HCI_AT_GENERAL_BONDING; - break; - default: - auth_type = HCI_AT_NO_BONDING; - break; - } - } + auth_type = l2cap_get_auth_type(sk); hcon = hci_connect(hdev, ACL_LINK, dst, l2cap_pi(sk)->sec_level, auth_type); @@ -1127,7 +1106,8 @@ static int l2cap_do_connect(struct sock *sk) if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM) { l2cap_sock_clear_timer(sk); - sk->sk_state = BT_CONNECTED; + if (l2cap_check_security(sk)) + sk->sk_state = BT_CONNECTED; } else l2cap_do_start(sk); } @@ -1893,8 +1873,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms if (pi->mode == L2CAP_MODE_STREAMING) { l2cap_streaming_send(sk); } else { - if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && - pi->conn_state && L2CAP_CONN_WAIT_F) { + if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && + (pi->conn_state & L2CAP_CONN_WAIT_F)) { err = len; break; } diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index ff8aaa736650..6b83776534fb 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1164,7 +1164,8 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) * initiator rfcomm_process_rx already calls * rfcomm_session_put() */ if (s->sock->sk->sk_state != BT_CLOSED) - rfcomm_session_put(s); + if (list_empty(&s->dlcs)) + rfcomm_session_put(s); break; } } diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 1f51f4162426..0c9d0c07eae6 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -185,8 +185,6 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_hw *hw = &local->hw; - struct ieee80211_conf *conf = &hw->conf; struct tid_ampdu_rx *tid_agg_rx; u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; u8 dialog_token; @@ -231,13 +229,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, goto end_no_lock; } /* determine default buffer size */ - if (buf_size == 0) { - struct ieee80211_supported_band *sband; - - sband = local->hw.wiphy->bands[conf->channel->band]; - buf_size = IEEE80211_MIN_AMPDU_BUF; - buf_size = buf_size << sband->ht_cap.ampdu_factor; - } + if (buf_size == 0) + buf_size = IEEE80211_MAX_AMPDU_BUF; /* make sure the size doesn't exceed the maximum supported by the hw */ if (buf_size > local->hw.max_rx_aggregation_subframes) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 1c507c6972e6..09a27449f3fd 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -39,6 +39,8 @@ module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, "Disable 40MHz support in the 2.4GHz band"); +static struct lock_class_key ieee80211_rx_skb_queue_class; + void ieee80211_configure_filter(struct ieee80211_local *local) { u64 mc; @@ -570,7 +572,15 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, spin_lock_init(&local->filter_lock); spin_lock_init(&local->queue_stop_reason_lock); - skb_queue_head_init(&local->rx_skb_queue); + /* + * The rx_skb_queue is only accessed from tasklets, + * but other SKB queues are used from within IRQ + * context. Therefore, this one needs a different + * locking class so our direct, non-irq-safe use of + * the queue's lock doesn't throw lockdep warnings. + */ + skb_queue_head_init_class(&local->rx_skb_queue, + &ieee80211_rx_skb_queue_class); INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e46c801320e1..ffc67491c38f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2230,6 +2230,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, sdata = vif_to_sdata(vif); + if (!ieee80211_sdata_running(sdata)) + goto out; + if (tim_offset) *tim_offset = 0; if (tim_length) |