diff options
33 files changed, 322 insertions, 316 deletions
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index d1214696a35..d716b748e57 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile @@ -11,3 +11,4 @@ ath-objs := main.o \ key.o ath-$(CONFIG_ATH_DEBUG) += debug.o +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c index e4e84a9e627..f4f56aff1e9 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.c +++ b/drivers/net/wireless/ath/ath9k/dfs.c @@ -66,7 +66,7 @@ ath9k_postprocess_radar_event(struct ath_softc *sc, u8 rssi; u16 dur; - ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_DFS, + ath_dbg(ath9k_hw_common(sc->sc_ah), DFS, "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n", are->pulse_bw_info, are->pulse_length_pri, are->rssi, @@ -161,7 +161,7 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, if ((!(rs->rs_phyerr != ATH9K_PHYERR_RADAR)) && (!(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT))) { - ath_dbg(common, ATH_DBG_DFS, + ath_dbg(common, DFS, "Error: rs_phyer=0x%x not a radar error\n", rs->rs_phyerr); return; @@ -190,7 +190,7 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, ard.pulse_length_ext = vdata_end[-2]; ard.pulse_length_pri = vdata_end[-3]; - ath_dbg(common, ATH_DBG_DFS, + ath_dbg(common, DFS, "bw_info=%d, length_pri=%d, length_ext=%d, " "rssi_pri=%d, rssi_ext=%d\n", ard.pulse_bw_info, ard.pulse_length_pri, ard.pulse_length_ext, @@ -200,7 +200,7 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, drp.ts = mactime; if (ath9k_postprocess_radar_event(sc, &ard, &drp)) { static u64 last_ts; - ath_dbg(common, ATH_DBG_DFS, + ath_dbg(common, DFS, "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, " "width=%d, rssi=%d, delta_ts=%llu\n", drp.freq, drp.ts, drp.width, drp.rssi, drp.ts-last_ts); diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.h b/drivers/net/wireless/ath/ath9k/dfs_debug.h index 6e1e2a71659..4911724cb44 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.h +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.h @@ -16,8 +16,8 @@ */ -#ifndef DFS_DEBUG_H -#define DFS_DEBUG_H +#ifndef ATH9K_DFS_DEBUG_H +#define ATH9K_DFS_DEBUG_H #include "hw.h" @@ -54,4 +54,4 @@ static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { } #endif /* CONFIG_ATH9K_DFS_DEBUGFS */ -#endif /* DFS_DEBUG_H */ +#endif /* ATH9K_DFS_DEBUG_H */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b2d95e86713..b5c7c5f0a75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1253,9 +1253,10 @@ int iwl_alive_start(struct iwl_priv *priv) iwl_send_bt_config(priv); } - if (hw_params(priv).calib_rt_cfg) - iwlagn_send_calib_cfg_rt(priv, - hw_params(priv).calib_rt_cfg); + /* + * Perform runtime calibrations, including DC calibration. + */ + iwlagn_send_calib_cfg_rt(priv, IWL_CALIB_CFG_DC_IDX); ieee80211_wake_queues(priv->hw); @@ -1668,7 +1669,7 @@ static int iwl_set_hw_params(struct iwl_priv *priv) hw_params(priv).rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); - if (iwlagn_mod_params.disable_11n) + if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL) cfg(priv)->sku &= ~EEPROM_SKU_CAP_11N_ENABLE; hw_params(priv).num_ampdu_queues = @@ -1995,8 +1996,9 @@ module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO); MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO); MODULE_PARM_DESC(queues_num, "number of hw queues."); -module_param_named(11n_disable, iwlagn_mod_params.disable_11n, int, S_IRUGO); -MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); +module_param_named(11n_disable, iwlagn_mod_params.disable_11n, uint, S_IRUGO); +MODULE_PARM_DESC(11n_disable, + "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX"); module_param_named(amsdu_size_8K, iwlagn_mod_params.amsdu_size_8K, int, S_IRUGO); MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 08b97594e30..940d5038b39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -122,7 +122,8 @@ struct iwl_bus; * struct iwl_bus_ops - bus specific operations * @get_pm_support: must returns true if the bus can go to sleep * @apm_config: will be called during the config of the APM - * @get_hw_id: prints the hw_id in the provided buffer + * @get_hw_id_string: prints the hw_id in the provided buffer + * @get_hw_id: get hw_id in u32 * @write8: write a byte to register at offset ofs * @write32: write a dword to register at offset ofs * @wread32: read a dword at register at offset ofs @@ -130,7 +131,8 @@ struct iwl_bus; struct iwl_bus_ops { bool (*get_pm_support)(struct iwl_bus *bus); void (*apm_config)(struct iwl_bus *bus); - void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); + void (*get_hw_id_string)(struct iwl_bus *bus, char buf[], int buf_len); + u32 (*get_hw_id)(struct iwl_bus *bus); void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); u32 (*read32)(struct iwl_bus *bus, u32 ofs); @@ -172,9 +174,15 @@ static inline void bus_apm_config(struct iwl_bus *bus) bus->ops->apm_config(bus); } -static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len) +static inline void bus_get_hw_id_string(struct iwl_bus *bus, char buf[], + int buf_len) { - bus->ops->get_hw_id(bus, buf, buf_len); + bus->ops->get_hw_id_string(bus, buf, buf_len); +} + +static inline u32 bus_get_hw_id(struct iwl_bus *bus) +{ + return bus->ops->get_hw_id(bus); } static inline void bus_write8(struct iwl_bus *bus, u32 ofs, u8 val) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e513a80a377..7bcfa781e0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -204,7 +204,7 @@ int iwl_init_geos(struct iwl_priv *priv) if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && cfg(priv)->sku & EEPROM_SKU_CAP_BAND_52GHZ) { char buf[32]; - bus_get_hw_id(bus(priv), buf, sizeof(buf)); + bus_get_hw_id_string(bus(priv), buf, sizeof(buf)); IWL_INFO(priv, "Incorrectly detected BG card as ABG. " "Please send your %s to maintainer.\n", buf); cfg(priv)->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index f9d3319ecad..9b212a8f30b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -90,6 +90,35 @@ TRACE_EVENT(iwlwifi_dev_iowrite32, TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val) ); +TRACE_EVENT(iwlwifi_dev_irq, + TP_PROTO(void *priv), + TP_ARGS(priv), + TP_STRUCT__entry( + PRIV_ENTRY + ), + TP_fast_assign( + PRIV_ASSIGN; + ), + /* TP_printk("") doesn't compile */ + TP_printk("%d", 0) +); + +TRACE_EVENT(iwlwifi_dev_ict_read, + TP_PROTO(void *priv, u32 index, u32 value), + TP_ARGS(priv, index, value), + TP_STRUCT__entry( + PRIV_ENTRY + __field(u32, index) + __field(u32, value) + ), + TP_fast_assign( + PRIV_ASSIGN; + __entry->index = index; + __entry->value = value; + ), + TP_printk("read ict[%d] = %#.8x", __entry->index, __entry->value) +); + #undef TRACE_SYSTEM #define TRACE_SYSTEM iwlwifi_ucode diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index da689582af6..f980e574e1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -234,6 +234,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ]; + hw->wiphy->hw_version = bus_get_hw_id(bus(priv)); + iwl_leds_init(priv); ret = ieee80211_register_hw(priv->hw); @@ -633,6 +635,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: + if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) + break; IWL_DEBUG_HT(priv, "start Rx\n"); ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn); break; @@ -643,6 +647,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, ret = 0; break; case IEEE80211_AMPDU_TX_START: + if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) + break; IWL_DEBUG_HT(priv, "start Tx\n"); ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); break; diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 850ec8e51b1..fb30ea7ca96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -135,7 +135,7 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) } } -static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], +static void iwl_pci_get_hw_id_string(struct iwl_bus *bus, char buf[], int buf_len) { struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); @@ -144,6 +144,13 @@ static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], pci_dev->subsystem_device); } +static u32 iwl_pci_get_hw_id(struct iwl_bus *bus) +{ + struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); + + return (pci_dev->device << 16) + pci_dev->subsystem_device; +} + static void iwl_pci_write8(struct iwl_bus *bus, u32 ofs, u8 val) { iowrite8(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); @@ -163,6 +170,7 @@ static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs) static const struct iwl_bus_ops bus_ops_pci = { .get_pm_support = iwl_pci_is_pm_supported, .apm_config = iwl_pci_apm_config, + .get_hw_id_string = iwl_pci_get_hw_id_string, .get_hw_id = iwl_pci_get_hw_id, .write8 = iwl_pci_write8, .write32 = iwl_pci_write32, diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 8cf877e4352..dc55cc4a810 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -107,6 +107,10 @@ struct iwl_trans_ops; extern struct iwl_mod_params iwlagn_mod_params; +#define IWL_DISABLE_HT_ALL BIT(0) +#define IWL_DISABLE_HT_TXAGG BIT(1) +#define IWL_DISABLE_HT_RXAGG BIT(2) + /** * struct iwl_mod_params * @@ -114,7 +118,8 @@ extern struct iwl_mod_params iwlagn_mod_params; * * @sw_crypto: using hardware encryption, default = 0 * @num_of_queues: number of tx queue, HW dependent - * @disable_11n: 11n capabilities enabled, default = 0 + * @disable_11n: disable 11n capabilities, default = 0, + * use IWL_DISABLE_HT_* constants * @amsdu_size_8K: enable 8K amsdu size, default = 1 * @antenna: both antennas (use diversity), default = 0 * @restart_fw: restart firmware, default = 1 @@ -135,7 +140,7 @@ extern struct iwl_mod_params iwlagn_mod_params; struct iwl_mod_params { int sw_crypto; int num_of_queues; - int disable_11n; + unsigned int disable_11n; int amsdu_size_8K; int antenna; int restart_fw; @@ -174,7 +179,6 @@ struct iwl_mod_params { * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit * relevant for 1000, 6000 and up * @wd_timeout: TX queues watchdog timeout - * @calib_rt_cfg: setup runtime calibrations for the hw * @struct iwl_sensitivity_ranges: range of sensitivity values */ struct iwl_hw_params { @@ -194,7 +198,6 @@ struct iwl_hw_params { u32 ct_kill_exit_threshold; unsigned int wd_timeout; - u32 calib_rt_cfg; const struct iwl_sensitivity_ranges *sens; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index db8a0d662dc..4a5cddd2d56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -422,8 +422,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) struct sk_buff *skb; unsigned char *rsp_data_ptr = NULL; int status = 0, rsp_data_len = 0; - char buf[32], *ptr = NULL; - unsigned int num, devid; + u32 devid; switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: @@ -534,14 +533,8 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) break; case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: - bus_get_hw_id(bus(priv), buf, sizeof(buf)); - ptr = buf; - strsep(&ptr, ":"); - sscanf(strsep(&ptr, ":"), "%x", &num); - sscanf(strsep(&ptr, ":"), "%x", &devid); - IWL_INFO(priv, "Device ID = 0x%04x, SubDevice ID= 0x%04x\n", - num, devid); - devid |= (num << 16); + devid = bus_get_hw_id(bus(priv)); + IWL_INFO(priv, "hw version: 0x%x\n", devid); skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); if (!skb) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 63a2eb1a71f..f6debf91d7b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -219,9 +219,7 @@ struct iwl_trans_pcie { /* INT ICT Table */ __le32 *ict_tbl; - void *ict_tbl_vir; dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; int ict_index; u32 inta; bool use_ict; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 791005d4783..752493f0040 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1151,7 +1151,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * ICT functions * ******************************************************************************/ -#define ICT_COUNT (PAGE_SIZE/sizeof(u32)) + +/* a device (PCI-E) page is 4096 bytes long */ +#define ICT_SHIFT 12 +#define ICT_SIZE (1 << ICT_SHIFT) +#define ICT_COUNT (ICT_SIZE / sizeof(u32)) /* Free dram table */ void iwl_free_isr_ict(struct iwl_trans *trans) @@ -1159,21 +1163,19 @@ void iwl_free_isr_ict(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - if (trans_pcie->ict_tbl_vir) { - dma_free_coherent(bus(trans)->dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - trans_pcie->ict_tbl_vir, + if (trans_pcie->ict_tbl) { + dma_free_coherent(bus(trans)->dev, ICT_SIZE, + trans_pcie->ict_tbl, trans_pcie->ict_tbl_dma); - trans_pcie->ict_tbl_vir = NULL; - memset(&trans_pcie->ict_tbl_dma, 0, - sizeof(trans_pcie->ict_tbl_dma)); - memset(&trans_pcie->aligned_ict_tbl_dma, 0, - sizeof(trans_pcie->aligned_ict_tbl_dma)); + trans_pcie->ict_tbl = NULL; + trans_pcie->ict_tbl_dma = 0; } } -/* allocate dram shared table it is a PAGE_SIZE aligned +/* + * allocate dram shared table, it is an aligned memory + * block of ICT_SIZE. * also reset all data related to ICT table interrupt. */ int iwl_alloc_isr_ict(struct iwl_trans *trans) @@ -1181,36 +1183,26 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - /* allocate shrared data table */ - trans_pcie->ict_tbl_vir = - dma_alloc_coherent(bus(trans)->dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - &trans_pcie->ict_tbl_dma, GFP_KERNEL); - if (!trans_pcie->ict_tbl_vir) + trans_pcie->ict_tbl = + dma_alloc_coherent(bus(trans)->dev, ICT_SIZE, + &trans_pcie->ict_tbl_dma, + GFP_KERNEL); + if (!trans_pcie->ict_tbl) return -ENOMEM; - /* align table to PAGE_SIZE boundary */ - trans_pcie->aligned_ict_tbl_dma = - ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE); - - IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n", - (unsigned long long)trans_pcie->ict_tbl_dma, - (unsigned long long)trans_pcie->aligned_ict_tbl_dma, - (int)(trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma)); + /* just an API sanity check ... it is guaranteed to be aligned */ + if (WARN_ON(trans_pcie->ict_tbl_dma & (ICT_SIZE - 1))) { + iwl_free_isr_ict(trans); + return -EINVAL; + } - trans_pcie->ict_tbl = trans_pcie->ict_tbl_vir + - (trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma); + IWL_DEBUG_ISR(trans, "ict dma addr %Lx\n", + (unsigned long long)trans_pcie->ict_tbl_dma); - IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n", - trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir, - (int)(trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma)); + IWL_DEBUG_ISR(trans, "ict vir addr %p\n", trans_pcie->ict_tbl); /* reset table and index to all 0 */ - memset(trans_pcie->ict_tbl_vir, 0, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); + memset(trans_pcie->ict_tbl, 0, ICT_SIZE); trans_pcie->ict_index = 0; /* add periodic RX interrupt */ @@ -1228,23 +1220,20 @@ int iwl_reset_ict(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - if (!trans_pcie->ict_tbl_vir) + if (!trans_pcie->ict_tbl) return 0; spin_lock_irqsave(&trans->shrd->lock, flags); iwl_disable_interrupts(trans); - memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); + memset(trans_pcie->ict_tbl, 0, ICT_SIZE); - val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT; + val = trans_pcie->ict_tbl_dma >> ICT_SHIFT; val |= CSR_DRAM_INT_TBL_ENABLE; val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; - IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X " - "aligned dma address %Lx\n", - val, - (unsigned long long)trans_pcie->aligned_ict_tbl_dma); + IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%x\n", val); iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val); trans_pcie->use_ict = true; @@ -1281,6 +1270,8 @@ static irqreturn_t iwl_isr(int irq, void *data) if (!trans) return IRQ_NONE; + trace_iwlwifi_dev_irq(priv(trans)); + trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); spin_lock_irqsave(&trans->shrd->lock, flags); @@ -1355,6 +1346,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) struct iwl_trans_pcie *trans_pcie; u32 inta, inta_mask; u32 val = 0; + u32 read; unsigned long flags; if (!trans) @@ -1368,6 +1360,8 @@ irqreturn_t iwl_isr_ict(int irq, void *data) if (!trans_pcie->use_ict) return iwl_isr(irq, data); + trace_iwlwifi_dev_irq(priv(trans)); + spin_lock_irqsave(&trans->shrd->lock, flags); /* Disable (but don't clear!) interrupts here to avoid @@ -1382,24 +1376,29 @@ irqreturn_t iwl_isr_ict(int irq, void *data) /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ - if (!trans_pcie->ict_tbl[trans_pcie->ict_index]) { + read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); + trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index, read); + if (!read) { IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); goto none; } - /* read all entries that not 0 start with ict_index */ - while (trans_pcie->ict_tbl[trans_pcie->ict_index]) { - - val |= le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); + /* + * Collect all entries up to the first 0, starting from ict_index; + * note we already read at ict_index. + */ + do { + val |= read; IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n", - trans_pcie->ict_index, - le32_to_cpu( - trans_pcie->ict_tbl[trans_pcie->ict_index])); + trans_pcie->ict_index, read); trans_pcie->ict_tbl[trans_pcie->ict_index] = 0; trans_pcie->ict_index = iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT); - } + read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); + trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index, + read); + } while (read); /* We should not get this value, just ignore it. */ if (val == 0xffffffff) @@ -1426,7 +1425,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) if (likely(inta)) tasklet_schedule(&trans_pcie->irq_tasklet); else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && - !trans_pcie->inta) { + !trans_pcie->inta) { /* Allow interrupt if was disabled by this handler and * no tasklet was schedules, We should not enable interrupt, * tasklet will enable it. @@ -1442,7 +1441,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) * only Re-enable if disabled by irq. */ if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && - !trans_pcie->inta) + !trans_pcie->inta) iwl_enable_interrupts(trans); spin_unlock_irqrestore(&trans->shrd->lock, flags); diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index d1d84e0e30f..a7cd311cb1b 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -731,9 +731,11 @@ static void lbs_scan_worker(struct work_struct *work) le16_to_cpu(scan_cmd->hdr.size), lbs_ret_scan, 0); - if (priv->scan_channel >= priv->scan_req->n_channels) + if (priv->scan_channel >= priv->scan_req->n_channels) { /* Mark scan done */ + cancel_delayed_work(&priv->scan_work); lbs_scan_done(priv); + } /* Restart network */ if (carrier) @@ -762,12 +764,12 @@ static void _internal_start_scan(struct lbs_private *priv, bool internal, request->n_ssids, request->n_channels, request->ie_len); priv->scan_channel = 0; - queue_delayed_work(priv->work_thread, &priv->scan_work, - msecs_to_jiffies(50)); - priv->scan_req = request; priv->internal_scan = internal; + queue_delayed_work(priv->work_thread, &priv->scan_work, + msecs_to_jiffies(50)); + lbs_deb_leave(LBS_DEB_CFG80211); } diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 787dbe2aa40..c3b6c4652cd 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -24,50 +24,26 @@ * This function maps the nl802.11 channel type into driver channel type. * * The mapping is as follows - - * NL80211_CHAN_NO_HT -> NO_SEC_CHANNEL - * NL80211_CHAN_HT20 -> NO_SEC_CHANNEL - * NL80211_CHAN_HT40PLUS -> SEC_CHANNEL_ABOVE - * NL80211_CHAN_HT40MINUS -> SEC_CHANNEL_BELOW - * Others -> NO_SEC_CHANNEL + * NL80211_CHAN_NO_HT -> IEEE80211_HT_PARAM_CHA_SEC_NONE + * NL80211_CHAN_HT20 -> IEEE80211_HT_PARAM_CHA_SEC_NONE + * NL80211_CHAN_HT40PLUS -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE + * NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW + * Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE */ -static int -mwifiex_cfg80211_channel_type_to_mwifiex_channels(enum nl80211_channel_type - channel_type) +static u8 +mwifiex_cfg80211_channel_type_to_sec_chan_offset(enum nl80211_channel_type + channel_type) { switch (channel_type) { case NL80211_CHAN_NO_HT: case NL80211_CHAN_HT20: - return NO_SEC_CHANNEL; + return IEEE80211_HT_PARAM_CHA_SEC_NONE; case NL80211_CHAN_HT40PLUS: - return SEC_CHANNEL_ABOVE; + return IEEE80211_HT_PARAM_CHA_SEC_ABOVE; case NL80211_CHAN_HT40MINUS: - return SEC_CHANNEL_BELOW; + return IEEE80211_HT_PARAM_CHA_SEC_BELOW; default: - return NO_SEC_CHANNEL; - } -} - -/* - * This function maps the driver channel type into nl802.11 channel type. - * - * The mapping is as follows - - * NO_SEC_CHANNEL -> NL80211_CHAN_HT20 - * SEC_CHANNEL_ABOVE -> NL80211_CHAN_HT40PLUS - * SEC_CHANNEL_BELOW -> NL80211_CHAN_HT40MINUS - * Others -> NL80211_CHAN_HT20 - */ -static enum nl80211_channel_type -mwifiex_channels_to_cfg80211_channel_type(int channel_type) -{ - switch (channel_type) { - case NO_SEC_CHANNEL: - return NL80211_CHAN_HT20; - case SEC_CHANNEL_ABOVE: - return NL80211_CHAN_HT40PLUS; - case SEC_CHANNEL_BELOW: - return NL80211_CHAN_HT40MINUS; - default: - return NL80211_CHAN_HT20; + return IEEE80211_HT_PARAM_CHA_SEC_NONE; } } @@ -331,37 +307,51 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, enum nl80211_channel_type channel_type) { struct mwifiex_chan_freq_power cfp; - struct mwifiex_ds_band_cfg band_cfg; u32 config_bands = 0; struct wiphy *wiphy = priv->wdev->wiphy; + struct mwifiex_adapter *adapter = priv->adapter; if (chan) { - memset(&band_cfg, 0, sizeof(band_cfg)); /* Set appropriate bands */ - if (chan->band == IEEE80211_BAND_2GHZ) - config_bands = BAND_B | BAND_G | BAND_GN; - else - config_bands = BAND_AN | BAND_A; - if (priv->bss_mode == NL80211_IFTYPE_STATION - || priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED) { - band_cfg.config_bands = config_bands; - } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - band_cfg.config_bands = config_bands; - band_cfg.adhoc_start_band = config_bands; + if (chan->band == IEEE80211_BAND_2GHZ) { + if (channel_type == NL80211_CHAN_NO_HT) + if (priv->adapter->config_bands == BAND_B || + priv->adapter->config_bands == BAND_G) + config_bands = + priv->adapter->config_bands; + else + config_bands = BAND_B | BAND_G; + else + config_bands = BAND_B | BAND_G | BAND_GN; + } else { + if (channel_type == NL80211_CHAN_NO_HT) + config_bands = BAND_A; + else + config_bands = BAND_AN | BAND_A; } - band_cfg.sec_chan_offset = - mwifiex_cfg80211_channel_type_to_mwifiex_channels + if (!((config_bands | adapter->fw_bands) & + ~adapter->fw_bands)) { + adapter->config_bands = config_bands; + if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { + adapter->adhoc_start_band = config_bands; + if ((config_bands & BAND_GN) || + (config_bands & BAND_AN)) + adapter->adhoc_11n_enabled = true; + else + adapter->adhoc_11n_enabled = false; + } + } + adapter->sec_chan_offset = + mwifiex_cfg80211_channel_type_to_sec_chan_offset (channel_type); - - if (mwifiex_set_radio_band_cfg(priv, &band_cfg)) - return -EFAULT; + adapter->channel_type = channel_type; mwifiex_send_domain_info_cmd_fw(wiphy); } wiphy_dbg(wiphy, "info: setting band %d, channel offset %d and " - "mode %d\n", config_bands, band_cfg.sec_chan_offset, + "mode %d\n", config_bands, adapter->sec_chan_offset, priv->bss_mode); if (!chan) return 0; @@ -697,9 +687,9 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, const u8 *peer, const struct cfg80211_bitrate_mask *mask) { - struct mwifiex_ds_band_cfg band_cfg; struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); int index = 0, mode = 0, i; + struct mwifiex_adapter *adapter = priv->adapter; /* Currently only 2.4GHz is supported */ for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) { @@ -721,16 +711,15 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, mode |= BAND_B; } - memset(&band_cfg, 0, sizeof(band_cfg)); - band_cfg.config_bands = mode; - - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) - band_cfg.adhoc_start_band = mode; - - band_cfg.sec_chan_offset = NO_SEC_CHANNEL; - - if (mwifiex_set_radio_band_cfg(priv, &band_cfg)) - return -EFAULT; + if (!((mode | adapter->fw_bands) & ~adapter->fw_bands)) { + adapter->config_bands = mode; + if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { + adapter->adhoc_start_band = mode; + adapter->adhoc_11n_enabled = false; + } + } + adapter->sec_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; + adapter->channel_type = NL80211_CHAN_NO_HT; wiphy_debug(wiphy, "info: device configured in 802.11%s%s mode\n", (mode & BAND_B) ? "b" : "", @@ -850,8 +839,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, if (channel) ret = mwifiex_set_rf_channel(priv, channel, - mwifiex_channels_to_cfg80211_channel_type - (priv->adapter->chan_offset)); + priv->adapter->channel_type); ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); /* Disable keys */ diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 62b86390769..51c5417c569 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -376,8 +376,6 @@ enum mwifiex_chan_scan_mode_bitmasks { MWIFIEX_DISABLE_CHAN_FILT = BIT(1), }; -#define SECOND_CHANNEL_BELOW 0x30 -#define SECOND_CHANNEL_ABOVE 0x10 struct mwifiex_chan_scan_param_set { u8 radio_type; u8 chan_number; diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 244c728ef9d..e05b417a3fa 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -246,7 +246,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) memset(adapter->event_body, 0, sizeof(adapter->event_body)); adapter->hw_dot_11n_dev_cap = 0; adapter->hw_dev_mcs_support = 0; - adapter->chan_offset = 0; + adapter->sec_chan_offset = 0; adapter->adhoc_11n_enabled = false; mwifiex_wmm_init(adapter); diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index e0b68e7c8ca..d5d81f1fe41 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -62,17 +62,6 @@ enum { BAND_AN = 16, }; -#define NO_SEC_CHANNEL 0 -#define SEC_CHANNEL_ABOVE 1 -#define SEC_CHANNEL_BELOW 3 - -struct mwifiex_ds_band_cfg { - u32 config_bands; - u32 adhoc_start_band; - u32 adhoc_channel; - u32 sec_chan_offset; -}; - enum { ADHOC_IDLE, ADHOC_STARTED, diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 1c4981367e5..0b0eb5efba9 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -885,12 +885,14 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, = mwifiex_band_to_radio_type(priv->curr_bss_params.band); if (adapter->adhoc_start_band & BAND_GN || adapter->adhoc_start_band & BAND_AN) { - if (adapter->chan_offset == SEC_CHANNEL_ABOVE) + if (adapter->sec_chan_offset == + IEEE80211_HT_PARAM_CHA_SEC_ABOVE) chan_tlv->chan_scan_param[0].radio_type |= - SECOND_CHANNEL_ABOVE; - else if (adapter->chan_offset == SEC_CHANNEL_BELOW) + (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4); + else if (adapter->sec_chan_offset == + IEEE80211_HT_PARAM_CHA_SEC_ABOVE) chan_tlv->chan_scan_param[0].radio_type |= - SECOND_CHANNEL_BELOW; + (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4); } dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Band = %d\n", chan_tlv->chan_scan_param[0].radio_type); @@ -936,8 +938,8 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, ht_info->ht_info.control_chan = (u8) priv->curr_bss_params.bss_descriptor.channel; - if (adapter->chan_offset) { - ht_info->ht_info.ht_param = adapter->chan_offset; + if (adapter->sec_chan_offset) { + ht_info->ht_info.ht_param = adapter->sec_chan_offset; ht_info->ht_info.ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; } diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 9207fc64641..3186aa437f4 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -640,7 +640,8 @@ struct mwifiex_adapter { u32 hw_dot_11n_dev_cap; u8 hw_dev_mcs_support; u8 adhoc_11n_enabled; - u8 chan_offset; + u8 sec_chan_offset; + enum nl80211_channel_type channel_type; struct mwifiex_dbg dbg; u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE]; u32 arp_filter_size; @@ -954,8 +955,6 @@ int mwifiex_main_process(struct mwifiex_adapter *); int mwifiex_bss_set_channel(struct mwifiex_private *, struct mwifiex_chan_freq_power *cfp); -int mwifiex_set_radio_band_cfg(struct mwifiex_private *, - struct mwifiex_ds_band_cfg *); int mwifiex_get_bss_info(struct mwifiex_private *, struct mwifiex_bss_info *); int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index ea6518d1c9e..6e443ffa046 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -748,7 +748,7 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv, cpu_to_le16(HostCmd_SCAN_RADIO_TYPE_A); rf_type = le16_to_cpu(rf_chan->rf_type); - SET_SECONDARYCHAN(rf_type, priv->adapter->chan_offset); + SET_SECONDARYCHAN(rf_type, priv->adapter->sec_chan_offset); rf_chan->current_channel = cpu_to_le16(*channel); } rf_chan->action = cpu_to_le16(cmd_action); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 6d990c798a2..e40196dfdea 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -472,67 +472,6 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv, } /* - * The function sets band configurations. - * - * it performs extra checks to make sure the Ad-Hoc - * band and channel are compatible. Otherwise it returns an error. - * - */ -int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv, - struct mwifiex_ds_band_cfg *radio_cfg) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u8 infra_band, adhoc_band; - u32 adhoc_channel; - - infra_band = (u8) radio_cfg->config_bands; - adhoc_band = (u8) radio_cfg->adhoc_start_band; - adhoc_channel = radio_cfg->adhoc_channel; - - /* SET Infra band */ - if ((infra_band | adapter->fw_bands) & ~adapter->fw_bands) - return -1; - - adapter->config_bands = infra_band; - - /* SET Ad-hoc Band */ - if ((adhoc_band | adapter->fw_bands) & ~adapter->fw_bands) - return -1; - - if (adhoc_band) - adapter->adhoc_start_band = adhoc_band; - adapter->chan_offset = (u8) radio_cfg->sec_chan_offset; - /* - * If no adhoc_channel is supplied verify if the existing adhoc - * channel compiles with new adhoc_band - */ - if (!adhoc_channel) { - if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211 - (priv, adapter->adhoc_start_band, - priv->adhoc_channel)) { - /* Pass back the default channel */ - radio_cfg->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; - if ((adapter->adhoc_start_band & BAND_A) - || (adapter->adhoc_start_band & BAND_AN)) - radio_cfg->adhoc_channel = - DEFAULT_AD_HOC_CHANNEL_A; - } - } else { /* Retrurn error if adhoc_band and - adhoc_channel combination is invalid */ - if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211 - (priv, adapter->adhoc_start_band, (u16) adhoc_channel)) - return -1; - priv->adhoc_channel = (u8) adhoc_channel; - } - if ((adhoc_band & BAND_GN) || (adhoc_band & BAND_AN)) - adapter->adhoc_11n_enabled = true; - else - adapter->adhoc_11n_enabled = false; - - return 0; -} - -/* * The function disables auto deep sleep mode. */ int mwifiex_disable_auto_ds(struct mwifiex_private *priv) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 995695c28d5..901cd79a061 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -5044,14 +5044,14 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); break; case IEEE80211_AMPDU_TX_STOP: - if (stream == NULL) - break; - if (stream->state == AMPDU_STREAM_ACTIVE) { - spin_unlock(&priv->stream_lock); - mwl8k_destroy_ba(hw, stream); - spin_lock(&priv->stream_lock); + if (stream) { + if (stream->state == AMPDU_STREAM_ACTIVE) { + spin_unlock(&priv->stream_lock); + mwl8k_destroy_ba(hw, stream); + spin_lock(&priv->stream_lock); + } + mwl8k_remove_stream(hw, stream); } - mwl8k_remove_stream(hw, stream); ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); break; case IEEE80211_AMPDU_TX_OPERATIONAL: diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 377876315b8..7d1b6e4ef07 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1159,6 +1159,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x7392, 0x7722) }, /* Encore */ { USB_DEVICE(0x203d, 0x14a1) }, + /* Fujitsu Stylistic 550 */ + { USB_DEVICE(0x1690, 0x0761) }, /* Gemtek */ { USB_DEVICE(0x15a9, 0x0010) }, /* Gigabyte */ diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index e0d21797948..25990bd38be 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1835,6 +1835,9 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) wlvif->bss_type == BSS_TYPE_IBSS))) return -EINVAL; + /* flush all pending packets */ + wl1271_tx_work_locked(wl); + if (test_bit(wlvif->dev_role_id, wl->roc_map)) { ret = wl12xx_croc(wl, wlvif->dev_role_id); if (ret < 0) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 00ce794eeba..d3280df68f5 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -267,8 +267,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT " "(status 0x%0x)", mbox->scheduled_scan_status); if (wl->sched_scanning) { - wl1271_scan_sched_scan_stop(wl); ieee80211_sched_scan_stopped(wl->hw); + wl->sched_scanning = false; } } diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index c3058419e22..d5f55a149de 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -450,7 +450,16 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, if (wl->state == WL1271_STATE_OFF) goto out; + if (dev->operstate != IF_OPER_UP) + goto out; + /* + * The correct behavior should be just getting the appropriate wlvif + * from the given dev, but currently we don't have a mac80211 + * interface for it. + */ wl12xx_for_each_wlvif_sta(wl, wlvif) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) continue; @@ -458,7 +467,8 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, if (ret < 0) goto out; - wl1271_check_operstate(wl, wlvif, dev->operstate); + wl1271_check_operstate(wl, wlvif, + ieee80211_get_operstate(vif)); wl1271_ps_elp_sleep(wl); } @@ -2036,6 +2046,11 @@ out: return booted; } +static bool wl12xx_dev_role_started(struct wl12xx_vif *wlvif) +{ + return wlvif->dev_hlid != WL12XX_INVALID_LINK_ID; +} + static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -2184,7 +2199,11 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, if (ret < 0) goto deinit; - if (wlvif->bss_type == BSS_TYPE_STA_BSS) { + if (wlvif->bss_type == BSS_TYPE_STA_BSS || + wlvif->bss_type == BSS_TYPE_IBSS) { + if (wl12xx_dev_role_started(wlvif)) + wl12xx_stop_dev(wl, wlvif); + ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); if (ret < 0) goto deinit; @@ -2269,6 +2288,17 @@ out: cancel_work_sync(&wl->recovery_work); } +static int wl12xx_op_change_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum nl80211_iftype new_type, bool p2p) +{ + wl1271_op_remove_interface(hw, vif); + + vif->type = ieee80211_iftype_p2p(new_type, p2p); + vif->p2p = p2p; + return wl1271_op_add_interface(hw, vif); +} + static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, bool set_assoc) { @@ -2358,25 +2388,18 @@ static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif) wlvif->rate_set = wlvif->basic_rate_set; } -static bool wl12xx_is_roc(struct wl1271 *wl) -{ - u8 role_id; - - role_id = find_first_bit(wl->roc_map, WL12XX_MAX_ROLES); - if (role_id >= WL12XX_MAX_ROLES) - return false; - - return true; -} - static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, bool idle) { int ret; + bool cur_idle = !test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags); + + if (idle == cur_idle) + return 0; if (idle) { /* no need to croc if we weren't busy (e.g. during boot) */ - if (wl12xx_is_roc(wl)) { + if (wl12xx_dev_role_started(wlvif)) { ret = wl12xx_stop_dev(wl, wlvif); if (ret < 0) goto out; @@ -2391,7 +2414,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, ACX_KEEP_ALIVE_TPL_INVALID); if (ret < 0) goto out; - set_bit(WL1271_FLAG_IDLE, &wl->flags); + clear_bit(WLVIF_FLAG_IN_USE, &wlvif->flags); } else { /* The current firmware only supports sched_scan in idle */ if (wl->sched_scanning) { @@ -2402,7 +2425,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, ret = wl12xx_start_dev(wl, wlvif); if (ret < 0) goto out; - clear_bit(WL1271_FLAG_IDLE, &wl->flags); + set_bit(WLVIF_FLAG_IN_USE, &wlvif->flags); } out: @@ -2446,7 +2469,7 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { - if (wl12xx_is_roc(wl)) { + if (wl12xx_dev_role_started(wlvif)) { /* roaming */ ret = wl12xx_croc(wl, wlvif->dev_role_id); @@ -2463,7 +2486,7 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, * not idle. otherwise, CROC will be called * anyway. */ - if (wl12xx_is_roc(wl) && + if (wl12xx_dev_role_started(wlvif) && !(conf->flags & IEEE80211_CONF_IDLE)) { ret = wl12xx_stop_dev(wl, wlvif); if (ret < 0) @@ -3010,15 +3033,16 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, if (ret < 0) goto out; + if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) && + test_bit(wlvif->role_id, wl->roc_map)) { + /* don't allow scanning right now */ + ret = -EBUSY; + goto out_sleep; + } + /* cancel ROC before scanning */ - if (wl12xx_is_roc(wl)) { - if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { - /* don't allow scanning right now */ - ret = -EBUSY; - goto out_sleep; - } + if (wl12xx_dev_role_started(wlvif)) wl12xx_stop_dev(wl, wlvif); - } ret = wl1271_scan(hw->priv, vif, ssid, len, req); out_sleep: @@ -3829,9 +3853,9 @@ sta_not_found: } /* * stop device role if started (we might already be in - * STA role). TODO: make it better. + * STA/IBSS role). */ - if (wlvif->dev_role_id != WL12XX_INVALID_ROLE_ID) { + if (wl12xx_dev_role_started(wlvif)) { ret = wl12xx_stop_dev(wl, wlvif); if (ret < 0) goto out; @@ -3948,31 +3972,8 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, else ps_scheme = CONF_PS_SCHEME_LEGACY; - if (wl->state == WL1271_STATE_OFF) { - /* - * If the state is off, the parameters will be recorded and - * configured on init. This happens in AP-mode. - */ - struct conf_tx_ac_category *conf_ac = - &wl->conf.tx.ac_conf[wl1271_tx_get_queue(queue)]; - struct conf_tx_tid *conf_tid = - &wl->conf.tx.tid_conf[wl1271_tx_get_queue(queue)]; - - conf_ac->ac = wl1271_tx_get_queue(queue); - conf_ac->cw_min = (u8)params->cw_min; - conf_ac->cw_max = params->cw_max; - conf_ac->aifsn = params->aifs; - conf_ac->tx_op_limit = params->txop << 5; - - conf_tid->queue_id = wl1271_tx_get_queue(queue); - conf_tid->channel_type = CONF_CHANNEL_TYPE_EDCF; - conf_tid->tsid = wl1271_tx_get_queue(queue); - conf_tid->ps_scheme = ps_scheme; - conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY; - conf_tid->apsd_conf[0] = 0; - conf_tid->apsd_conf[1] = 0; + if (!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) goto out; - } ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) @@ -4629,6 +4630,7 @@ static const struct ieee80211_ops wl1271_ops = { .stop = wl1271_op_stop, .add_interface = wl1271_op_add_interface, .remove_interface = wl1271_op_remove_interface, + .change_interface = wl12xx_op_change_interface, #ifdef CONFIG_PM .suspend = wl1271_op_suspend, .resume = wl1271_op_resume, diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index a7a11088dd3..a2bdacdd7e1 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -53,8 +53,11 @@ void wl1271_elp_work(struct work_struct *work) goto out; wl12xx_for_each_wlvif(wl, wlvif) { + if (wlvif->bss_type == BSS_TYPE_AP_BSS) + goto out; + if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && - !test_bit(WL1271_FLAG_IDLE, &wl->flags)) + test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) goto out; } @@ -78,8 +81,11 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) return; wl12xx_for_each_wlvif(wl, wlvif) { + if (wlvif->bss_type == BSS_TYPE_AP_BSS) + return; + if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && - !test_bit(WL1271_FLAG_IDLE, &wl->flags)) + test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) return; } diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 8599dab1fe2..e24111ececc 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -437,18 +437,19 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, if (flags & IEEE80211_CHAN_RADAR) { channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS; + channels[j].passive_duration = cpu_to_le16(c->dwell_time_dfs); - } - else if (flags & IEEE80211_CHAN_PASSIVE_SCAN) { + } else { channels[j].passive_duration = cpu_to_le16(c->dwell_time_passive); - } else { - channels[j].min_duration = - cpu_to_le16(c->min_dwell_time_active); - channels[j].max_duration = - cpu_to_le16(c->max_dwell_time_active); } + + channels[j].min_duration = + cpu_to_le16(c->min_dwell_time_active); + channels[j].max_duration = + cpu_to_le16(c->max_dwell_time_active); + channels[j].tx_power_att = req->channels[i]->max_power; channels[j].channel = req->channels[i]->hw_value; @@ -703,7 +704,7 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (wlvif->bss_type != BSS_TYPE_STA_BSS) return -EOPNOTSUPP; - if (!test_bit(WL1271_FLAG_IDLE, &wl->flags)) + if (test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) return -EBUSY; start = kzalloc(sizeof(*start), GFP_KERNEL); @@ -753,7 +754,6 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl) wl1271_error("failed to send sched scan stop command"); goto out_free; } - wl->sched_scanning = false; out_free: kfree(stop); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index d21f71ff6f6..b2b09cd0202 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -241,7 +241,6 @@ enum wl12xx_flags { WL1271_FLAG_IN_ELP, WL1271_FLAG_ELP_REQUESTED, WL1271_FLAG_IRQ_RUNNING, - WL1271_FLAG_IDLE, WL1271_FLAG_FW_TX_BUSY, WL1271_FLAG_DUMMY_PACKET_PENDING, WL1271_FLAG_SUSPENDED, @@ -262,6 +261,7 @@ enum wl12xx_vif_flags { WLVIF_FLAG_PSPOLL_FAILURE, WLVIF_FLAG_CS_PROGRESS, WLVIF_FLAG_AP_PROBE_RESP_SET, + WLVIF_FLAG_IN_USE, }; struct wl1271_link { diff --git a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c index 3c96b332184..998e95895f9 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c +++ b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c @@ -1,3 +1,24 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2010-2011 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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 St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + #include <linux/module.h> #include <linux/err.h> #include <linux/wl12xx.h> diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 57832eb44f3..59f124c5833 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1827,7 +1827,12 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) } if (xmit_skb) { - /* send to wireless media */ + /* + * Send to wireless media and increase priority by 256 to + * keep the received priority instead of reclassifying + * the frame (see cfg80211_classify8021d). + */ + xmit_skb->priority += 256; xmit_skb->protocol = htons(ETH_P_802_3); skb_reset_network_header(xmit_skb); skb_reset_mac_header(xmit_skb); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 3d01abb2b81..f0d3b483dab 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -946,6 +946,9 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, mutex_lock(&local->sta_mtx); list_for_each_entry_safe(sta, tmp, &local->sta_list, list) + if (sdata != sta->sdata) + continue; + if (time_after(jiffies, sta->last_rx + exp_time)) { #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", |