aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c25
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c19
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.h12
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9485_initvals.h10
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c5
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c1
-rw-r--r--drivers/net/wireless/b43/main.c7
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945.c7
-rw-r--r--drivers/net/wireless/iwlegacy/iwl3945-base.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c39
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c20
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c2
-rw-r--r--drivers/net/wireless/libertas/if_spi.c1
-rw-r--r--drivers/net/wireless/p54/p54spi.c19
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c28
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c28
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c9
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c3
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c16
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c15
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/fw.c4
-rw-r--r--drivers/net/wireless/wl12xx/boot.c14
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c22
-rw-r--r--drivers/net/wireless/wl12xx/scan.c19
42 files changed, 248 insertions, 151 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index bfb6481..4e4e7c3 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -502,9 +502,6 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
ATH9K_ANI_CCK_WEAK_SIG_THR);
- ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
- ATH9K_RX_FILTER_PHYERR);
-
ath9k_ani_restart(ah);
return;
}
@@ -525,8 +522,6 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel);
- ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
- ~ATH9K_RX_FILTER_PHYERR);
ath9k_ani_restart(ah);
ENABLE_REGWRITE_BUFFER(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 441bb33..0f23b1a 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -489,8 +489,6 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows);
ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows);
ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows);
- ATH_ALLOC_BANK(ah->addac5416_21,
- ah->iniAddac.ia_rows * ah->iniAddac.ia_columns);
ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows);
return 0;
@@ -519,7 +517,6 @@ static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah)
ATH_FREE_BANK(ah->analogBank6Data);
ATH_FREE_BANK(ah->analogBank6TPCData);
ATH_FREE_BANK(ah->analogBank7Data);
- ATH_FREE_BANK(ah->addac5416_21);
ATH_FREE_BANK(ah->bank6Temp);
#undef ATH_FREE_BANK
@@ -799,27 +796,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
ah->eep_ops->set_addac(ah, chan);
- if (AR_SREV_5416_22_OR_LATER(ah)) {
- REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
- } else {
- struct ar5416IniArray temp;
- u32 addacSize =
- sizeof(u32) * ah->iniAddac.ia_rows *
- ah->iniAddac.ia_columns;
-
- /* For AR5416 2.0/2.1 */
- memcpy(ah->addac5416_21,
- ah->iniAddac.ia_array, addacSize);
-
- /* override CLKDRV value at [row, column] = [31, 1] */
- (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0;
-
- temp.ia_array = ah->addac5416_21;
- temp.ia_columns = ah->iniAddac.ia_columns;
- temp.ia_rows = ah->iniAddac.ia_rows;
- REG_WRITE_ARRAY(&temp, 1, regWrites);
- }
-
+ REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
ENABLE_REGWRITE_BUFFER(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index c32f9d1..30bf703 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -179,6 +179,25 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
ARRAY_SIZE(ar5416Addac), 2);
}
+
+ /* iniAddac needs to be modified for these chips */
+ if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) {
+ struct ar5416IniArray *addac = &ah->iniAddac;
+ u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns;
+ u32 *data;
+
+ data = kmalloc(size, GFP_KERNEL);
+ if (!data)
+ return;
+
+ memcpy(data, addac->ia_array, size);
+ addac->ia_array = data;
+
+ if (!AR_SREV_5416_22_OR_LATER(ah)) {
+ /* override CLKDRV value */
+ INI_RA(addac, 31,1) = 0;
+ }
+ }
}
/* Support for Japan ch.14 (2484) spread */
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index f48051c..7c2aaad 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -643,8 +643,9 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
outlier_idx = max_idx;
else
outlier_idx = min_idx;
+
+ mp_coeff[outlier_idx] = mp_avg;
}
- mp_coeff[outlier_idx] = mp_avg;
}
static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 1f99249..7880dca 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -255,8 +255,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
return -EIO;
}
- if (status & AR_TxOpExceeded)
- ts->ts_status |= ATH9K_TXERR_XTXOP;
ts->ts_rateindex = MS(status, AR_FinalTxIdx);
ts->ts_seqnum = MS(status, AR_SeqNum);
ts->tid = MS(status, AR_TxTid);
@@ -267,6 +265,8 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
ts->ts_status = 0;
ts->ts_flags = 0;
+ if (status & AR_TxOpExceeded)
+ ts->ts_status |= ATH9K_TXERR_XTXOP;
status = ACCESS_ONCE(ads->status2);
ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index efdbe98..2364b5f 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -570,12 +570,12 @@
#define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300)
-#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \
- 0x3c8 : 0x448)
-#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \
- 0x3c4 : 0x440)
-#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + AR_SREV_9485(ah) ? \
- 0x3f0 : 0x48c)
+#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+ 0x3c8 : 0x448))
+#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+ 0x3c4 : 0x440))
+#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+ 0x3f0 : 0x48c))
#define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \
(AR_SREV_9485(ah) ? \
0x3d0 : 0x450) + ((_i) << 2))
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
index 611ea6c..d16d029 100644
--- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
@@ -521,7 +521,7 @@ static const u32 ar9485_1_1_radio_postamble[][2] = {
{0x000160ac, 0x24611800},
{0x000160b0, 0x03284f3e},
{0x0001610c, 0x00170000},
- {0x00016140, 0x10804008},
+ {0x00016140, 0x50804008},
};
static const u32 ar9485_1_1_mac_postamble[][5] = {
@@ -603,7 +603,7 @@ static const u32 ar9485_1_1_radio_core[][2] = {
static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = {
/* Addr allmodes */
- {0x00018c00, 0x10052e5e},
+ {0x00018c00, 0x18052e5e},
{0x00018c04, 0x000801d8},
{0x00018c08, 0x0000080c},
};
@@ -776,7 +776,7 @@ static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = {
static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = {
/* Addr allmodes */
- {0x00018c00, 0x10013e5e},
+ {0x00018c00, 0x18013e5e},
{0x00018c04, 0x000801d8},
{0x00018c08, 0x0000080c},
};
@@ -882,7 +882,7 @@ static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = {
static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
/* Addr allmodes */
- {0x00018c00, 0x10012e5e},
+ {0x00018c00, 0x18012e5e},
{0x00018c04, 0x000801d8},
{0x00018c08, 0x0000080c},
};
@@ -1021,7 +1021,7 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = {
static const u32 ar9485_1_1_pcie_phy_clkreq_enable_L1[][2] = {
/* Addr allmodes */
- {0x00018c00, 0x10053e5e},
+ {0x00018c00, 0x18053e5e},
{0x00018c04, 0x000801d8},
{0x00018c08, 0x0000080c},
};
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 260f1f3..5513c0a 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -37,6 +37,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
{ USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
{ USB_DEVICE(0x040D, 0x3801) }, /* VIA */
{ USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */
+ { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */
{ USB_DEVICE(0x0cf3, 0x7015),
.driver_info = AR9287_USB }, /* Atheros */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 03900ca..7c2f06e 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1931,6 +1931,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->num_gpio_pins = AR9271_NUM_GPIO;
else if (AR_DEVID_7010(ah))
pCap->num_gpio_pins = AR7010_NUM_GPIO;
+ else if (AR_SREV_9300_20_OR_LATER(ah))
+ pCap->num_gpio_pins = AR9300_NUM_GPIO;
+ else if (AR_SREV_9287_11_OR_LATER(ah))
+ pCap->num_gpio_pins = AR9287_NUM_GPIO;
else if (AR_SREV_9285_12_OR_LATER(ah))
pCap->num_gpio_pins = AR9285_NUM_GPIO;
else if (AR_SREV_9280_20_OR_LATER(ah))
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 939cc9d..9dc2666 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -763,7 +763,6 @@ struct ath_hw {
u32 *analogBank6Data;
u32 *analogBank6TPCData;
u32 *analogBank7Data;
- u32 *addac5416_21;
u32 *bank6Temp;
u8 txpower_limit;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 5362306..a126a3e 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1828,6 +1828,9 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
struct ath_softc *sc = hw->priv;
struct ath_node *an = (struct ath_node *) sta->drv_priv;
+ if (!(sc->sc_flags & SC_OP_TXAGGR))
+ return;
+
switch (cmd) {
case STA_NOTIFY_SLEEP:
an->sleeping = true;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index ba7f36a..9d965e3 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1252,7 +1252,9 @@ static void ath_rc_init(struct ath_softc *sc,
ath_rc_priv->max_valid_rate = k;
ath_rc_sort_validrates(rate_table, ath_rc_priv);
- ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
+ ath_rc_priv->rate_max_phy = (k > 4) ?
+ ath_rc_priv->valid_rate_index[k-4] :
+ ath_rc_priv->valid_rate_index[k-1];
ath_rc_priv->rate_table = rate_table;
ath_dbg(common, ATH_DBG_CONFIG,
@@ -1326,7 +1328,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
fc = hdr->frame_control;
for (i = 0; i < sc->hw->max_rates; i++) {
struct ieee80211_tx_rate *rate = &tx_info->status.rates[i];
- if (!rate->count)
+ if (rate->idx < 0 || !rate->count)
break;
final_ts_idx = i;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 07e35e5..3b5f9d6 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -423,12 +423,9 @@ void ath_rx_cleanup(struct ath_softc *sc)
u32 ath_calcrxfilter(struct ath_softc *sc)
{
-#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
-
u32 rfilt;
- rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
- | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
+ rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
| ATH9K_RX_FILTER_MCAST;
if (sc->rx.rxfilter & FIF_PROBE_REQ)
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index e94084f..f190f32 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -1245,6 +1245,7 @@ static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb)
atomic_dec(&ar->tx_ampdu_upload);
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+ carl9170_release_dev_space(ar, skb);
carl9170_tx_status(ar, skb, false);
return true;
}
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index b1fe4fe..7c2e09a 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2401,6 +2401,13 @@ static int b43_upload_microcode(struct b43_wldev *dev)
b43_print_fw_helptext(dev->wl, 1);
err = -EOPNOTSUPP;
goto error;
+ } else if (fwrev >= 598) {
+ b43err(dev->wl, "YOUR FIRMWARE IS TOO NEW. Support for "
+ "firmware 598 and up requires kernel 3.2 or newer. You "
+ "have to install older firmware or upgrade kernel.\n");
+ b43_print_fw_helptext(dev->wl, 1);
+ err = -EOPNOTSUPP;
+ goto error;
}
dev->fw.rev = fwrev;
dev->fw.patch = fwpatch;
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c
index dcc1552..effeabb 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945.c
@@ -1872,11 +1872,12 @@ static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv,
_3945.thermal_periodic.work);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
mutex_lock(&priv->mutex);
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) || priv->txq == NULL)
+ goto out;
+
iwl3945_reg_txpower_periodic(priv);
+out:
mutex_unlock(&priv->mutex);
}
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c
index 421d5c8..101a2c2 100644
--- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
@@ -2763,7 +2763,7 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
container_of(data, struct iwl_priv, alive_start.work);
mutex_lock(&priv->mutex);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) || priv->txq == NULL)
goto out;
iwl3945_alive_start(priv);
@@ -2910,14 +2910,13 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
IWL_WARN(priv, "Invalid scan band\n");
return -EIO;
}
-
/*
- * If active scaning is requested but a certain channel
- * is marked passive, we can do active scanning if we
- * detect transmissions.
+ * If active scaning is requested but a certain channel is marked
+ * passive, we can do active scanning if we detect transmissions. For
+ * passive only scanning disable switching to active on any channel.
*/
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
- IWL_GOOD_CRC_TH_DISABLED;
+ IWL_GOOD_CRC_TH_NEVER;
if (!priv->is_internal_short_scan) {
scan->tx_cmd.len = cpu_to_le16(
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index f803fb6..857cf61 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -2023,6 +2023,7 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
case IEEE80211_SMPS_STATIC:
case IEEE80211_SMPS_DYNAMIC:
return IWL_NUM_IDLE_CHAINS_SINGLE;
+ case IEEE80211_SMPS_AUTOMATIC:
case IEEE80211_SMPS_OFF:
return active_cnt;
default:
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 09f679d..272bcdf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -411,6 +411,24 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
return 0;
}
+void iwlagn_config_ht40(struct ieee80211_conf *conf,
+ struct iwl_rxon_context *ctx)
+{
+ if (conf_is_ht40_minus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ ctx->ht.is_40mhz = true;
+ } else if (conf_is_ht40_plus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ ctx->ht.is_40mhz = true;
+ } else {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ ctx->ht.is_40mhz = false;
+ }
+}
+
int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
{
struct iwl_priv *priv = hw->priv;
@@ -424,6 +442,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&priv->mutex);
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ goto out;
+
if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
goto out;
@@ -470,19 +491,11 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
ctx->ht.enabled = conf_is_ht(conf);
if (ctx->ht.enabled) {
- if (conf_is_ht40_minus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- ctx->ht.is_40mhz = true;
- } else if (conf_is_ht40_plus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- ctx->ht.is_40mhz = true;
- } else {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_NONE;
- ctx->ht.is_40mhz = false;
- }
+ /* if HT40 is used, it should not change
+ * after associated except channel switch */
+ if (!ctx->ht.is_40mhz ||
+ !iwl_is_associated_ctx(ctx))
+ iwlagn_config_ht40(conf, ctx);
} else
ctx->ht.is_40mhz = false;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 4974cd7..67cd2e3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -385,7 +385,10 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
tx_cmd->tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
} else {
- tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+ tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+ else
+ tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
}
priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags);
@@ -775,10 +778,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
- /* Set up entry for this TFD in Tx byte-count array */
- if (info->flags & IEEE80211_TX_CTL_AMPDU)
- iwlagn_txq_update_byte_cnt_tbl(priv, txq,
- le16_to_cpu(tx_cmd->len));
+ iwlagn_txq_update_byte_cnt_tbl(priv, txq, le16_to_cpu(tx_cmd->len));
pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
firstlen, PCI_DMA_BIDIRECTIONAL);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 97de5d9..a03dbcc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -144,13 +144,8 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name);
- ret = wait_event_interruptible_timeout(priv->wait_command_queue,
- priv->ucode_write_complete, 5 * HZ);
- if (ret == -ERESTARTSYS) {
- IWL_ERR(priv, "Could not load the %s uCode section due "
- "to interrupt\n", name);
- return ret;
- }
+ ret = wait_event_timeout(priv->wait_command_queue,
+ priv->ucode_write_complete, 5 * HZ);
if (!ret) {
IWL_ERR(priv, "Could not load the %s uCode section\n",
name);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index f24165d..67d4c2d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -797,7 +797,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
handled |= CSR_INT_BIT_FH_TX;
/* Wake up uCode load routine, now that load is complete */
priv->ucode_write_complete = 1;
- wake_up_interruptible(&priv->wait_command_queue);
+ wake_up(&priv->wait_command_queue);
}
if (inta & ~handled) {
@@ -2872,21 +2872,9 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
/* Configure HT40 channels */
ctx->ht.enabled = conf_is_ht(conf);
- if (ctx->ht.enabled) {
- if (conf_is_ht40_minus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- ctx->ht.is_40mhz = true;
- } else if (conf_is_ht40_plus(conf)) {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- ctx->ht.is_40mhz = true;
- } else {
- ctx->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_NONE;
- ctx->ht.is_40mhz = false;
- }
- } else
+ if (ctx->ht.enabled)
+ iwlagn_config_ht40(conf, ctx);
+ else
ctx->ht.is_40mhz = false;
if ((le16_to_cpu(ctx->staging.channel) != ch))
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index d171684..5a0acab 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -152,6 +152,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u32 changes);
+void iwlagn_config_ht40(struct ieee80211_conf *conf,
+ struct iwl_rxon_context *ctx);
/* uCode */
void iwlagn_rx_calib_result(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 45cc51c..5638407 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -899,7 +899,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
* commands by clearing the ready bit */
clear_bit(STATUS_READY, &priv->status);
- wake_up_interruptible(&priv->wait_command_queue);
+ wake_up(&priv->wait_command_queue);
if (!ondemand) {
/*
@@ -950,7 +950,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
*/
clear_bit(STATUS_READY, &priv->status);
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
- wake_up_interruptible(&priv->wait_command_queue);
+ wake_up(&priv->wait_command_queue);
IWL_ERR(priv, "RF is used by WiMAX\n");
return;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 76f9966..fc11277 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -194,7 +194,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
return ret;
}
- ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+ ret = wait_event_timeout(priv->wait_command_queue,
!test_bit(STATUS_HCMD_ACTIVE, &priv->status),
HOST_COMPLETE_TIMEOUT);
if (!ret) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index b774517..865ac1a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -738,7 +738,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
test_bit(STATUS_RF_KILL_HW, &priv->status));
else
- wake_up_interruptible(&priv->wait_command_queue);
+ wake_up(&priv->wait_command_queue);
}
static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index c368c50..93152c3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -821,7 +821,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n",
get_cmd_string(cmd->hdr.cmd));
- wake_up_interruptible(&priv->wait_command_queue);
+ wake_up(&priv->wait_command_queue);
}
/* Mark as unmapped */
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 463352c..db39742 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -997,6 +997,7 @@ static int if_spi_host_to_card(struct lbs_private *priv,
spin_unlock_irqrestore(&card->buffer_lock, flags);
break;
default:
+ kfree(packet);
netdev_err(priv->dev, "can't transfer buffer of type %d\n",
type);
err = -EINVAL;
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index 6d9204fe..d895ff9 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -589,8 +589,6 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
WARN_ON(priv->fw_state != FW_STATE_READY);
- cancel_work_sync(&priv->work);
-
p54spi_power_off(priv);
spin_lock_irqsave(&priv->tx_lock, flags);
INIT_LIST_HEAD(&priv->tx_pending);
@@ -598,6 +596,8 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
priv->fw_state = FW_STATE_OFF;
mutex_unlock(&priv->mutex);
+
+ cancel_work_sync(&priv->work);
}
static int __devinit p54spi_probe(struct spi_device *spi)
@@ -623,19 +623,19 @@ static int __devinit p54spi_probe(struct spi_device *spi)
ret = spi_setup(spi);
if (ret < 0) {
dev_err(&priv->spi->dev, "spi_setup failed");
- goto err_free_common;
+ goto err_free;
}
ret = gpio_request(p54spi_gpio_power, "p54spi power");
if (ret < 0) {
dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret);
- goto err_free_common;
+ goto err_free;
}
ret = gpio_request(p54spi_gpio_irq, "p54spi irq");
if (ret < 0) {
dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret);
- goto err_free_common;
+ goto err_free_gpio_power;
}
gpio_direction_output(p54spi_gpio_power, 0);
@@ -646,7 +646,7 @@ static int __devinit p54spi_probe(struct spi_device *spi)
priv->spi);
if (ret < 0) {
dev_err(&priv->spi->dev, "request_irq() failed");
- goto err_free_common;
+ goto err_free_gpio_irq;
}
irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
@@ -657,6 +657,7 @@ static int __devinit p54spi_probe(struct spi_device *spi)
init_completion(&priv->fw_comp);
INIT_LIST_HEAD(&priv->tx_pending);
mutex_init(&priv->mutex);
+ spin_lock_init(&priv->tx_lock);
SET_IEEE80211_DEV(hw, &spi->dev);
priv->common.open = p54spi_op_start;
priv->common.stop = p54spi_op_stop;
@@ -677,6 +678,12 @@ static int __devinit p54spi_probe(struct spi_device *spi)
return 0;
err_free_common:
+ free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
+err_free_gpio_irq:
+ gpio_free(p54spi_gpio_irq);
+err_free_gpio_power:
+ gpio_free(p54spi_gpio_power);
+err_free:
p54_free_common(priv->hw);
return ret;
}
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 3f7ea1c..e6e174c 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -3514,7 +3514,7 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
/* Apparently the data is read from end to start */
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
/* The returned value is in CPU order, but eeprom is le */
- rt2x00dev->eeprom[i] = cpu_to_le32(reg);
+ *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 55cd3e1..dab7dc1 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -426,7 +426,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
- int mask = (state == STATE_RADIO_IRQ_ON);
u32 reg;
unsigned long flags;
@@ -448,25 +447,14 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
}
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC0_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC1_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC2_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC3_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_HCCA_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_MGMT_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_MCU_COMMAND, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RXTX_COHERENT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
+ reg = 0;
+ if (state == STATE_RADIO_IRQ_ON) {
+ rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
+ }
rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 6e7fe94..97edee2 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -839,6 +839,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x07d1, 0x3c0f) },
{ USB_DEVICE(0x07d1, 0x3c11) },
{ USB_DEVICE(0x07d1, 0x3c16) },
+ { USB_DEVICE(0x2001, 0x3c1b) },
/* Draytek */
{ USB_DEVICE(0x07fa, 0x7712) },
/* Edimax */
@@ -878,6 +879,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x13b1, 0x0031) },
{ USB_DEVICE(0x1737, 0x0070) },
{ USB_DEVICE(0x1737, 0x0071) },
+ { USB_DEVICE(0x1737, 0x0077) },
/* Logitec */
{ USB_DEVICE(0x0789, 0x0162) },
{ USB_DEVICE(0x0789, 0x0163) },
@@ -1069,7 +1071,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x1740, 0x0605) },
{ USB_DEVICE(0x1740, 0x0615) },
/* Linksys */
- { USB_DEVICE(0x1737, 0x0077) },
{ USB_DEVICE(0x1737, 0x0078) },
/* Logitec */
{ USB_DEVICE(0x0789, 0x0168) },
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index c446db6..8c82211 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -922,6 +922,7 @@ struct rt2x00_dev {
* Powersaving work
*/
struct delayed_work autowakeup_work;
+ struct work_struct sleep_work;
/*
* Data queue arrays for RX, TX, Beacon and ATIM.
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 939821b..5bd2c55 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -410,10 +410,14 @@ void rt2x00lib_txdone(struct queue_entry *entry,
/*
* If the data queue was below the threshold before the txdone
* handler we must make sure the packet queue in the mac80211 stack
- * is reenabled when the txdone handler has finished.
+ * is reenabled when the txdone handler has finished. This has to be
+ * serialized with rt2x00mac_tx(), otherwise we can wake up queue
+ * before it was stopped.
*/
+ spin_lock_bh(&entry->queue->tx_lock);
if (!rt2x00queue_threshold(entry->queue))
rt2x00queue_unpause_queue(entry->queue);
+ spin_unlock_bh(&entry->queue->tx_lock);
}
EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
@@ -449,6 +453,23 @@ static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie)
return NULL;
}
+static void rt2x00lib_sleep(struct work_struct *work)
+{
+ struct rt2x00_dev *rt2x00dev =
+ container_of(work, struct rt2x00_dev, sleep_work);
+
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+ return;
+
+ /*
+ * Check again is powersaving is enabled, to prevent races from delayed
+ * work execution.
+ */
+ if (!test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
+ rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
+ IEEE80211_CONF_CHANGE_PS);
+}
+
static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb,
struct rxdone_entry_desc *rxdesc)
@@ -496,8 +517,7 @@ static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
cam |= (tim_ie->bitmap_ctrl & 0x01);
if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
- rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
- IEEE80211_CONF_CHANGE_PS);
+ queue_work(rt2x00dev->workqueue, &rt2x00dev->sleep_work);
}
static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
@@ -1108,6 +1128,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
+ INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
/*
* Let the driver probe the device to detect the capabilities.
@@ -1164,6 +1185,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
*/
cancel_work_sync(&rt2x00dev->intf_work);
cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
+ cancel_work_sync(&rt2x00dev->sleep_work);
if (rt2x00_is_usb(rt2x00dev)) {
del_timer_sync(&rt2x00dev->txstatus_timer);
cancel_work_sync(&rt2x00dev->rxdone_work);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index a76fdbe..bc159be 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -152,13 +152,22 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false)))
goto exit_fail;
+ /*
+ * Pausing queue has to be serialized with rt2x00lib_txdone(). Note
+ * we should not use spin_lock_bh variant as bottom halve was already
+ * disabled before ieee80211_xmit() call.
+ */
+ spin_lock(&queue->tx_lock);
if (rt2x00queue_threshold(queue))
rt2x00queue_pause_queue(queue);
+ spin_unlock(&queue->tx_lock);
return;
exit_fail:
+ spin_lock(&queue->tx_lock);
rt2x00queue_pause_queue(queue);
+ spin_unlock(&queue->tx_lock);
exit_free_skb:
dev_kfree_skb_any(skb);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 2886d25..76f26ad 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -562,6 +562,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
u8 rate_idx, rate_flags;
int ret = 0;
+ /*
+ * That function must be called with bh disabled.
+ */
spin_lock(&queue->tx_lock);
entry = rt2x00queue_get_entry(queue, Q_INDEX);
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index c872a23..6c56198 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -1180,10 +1180,12 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
ring->idx = (ring->idx + 1) % ring->entries;
}
- pci_free_consistent(rtlpci->pdev,
- sizeof(*ring->desc) * ring->entries,
- ring->desc, ring->dma);
- ring->desc = NULL;
+ if (ring->desc) {
+ pci_free_consistent(rtlpci->pdev,
+ sizeof(*ring->desc) * ring->entries,
+ ring->desc, ring->dma);
+ ring->desc = NULL;
+ }
}
static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci)
@@ -1207,12 +1209,14 @@ static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci)
kfree_skb(skb);
}
- pci_free_consistent(rtlpci->pdev,
+ if (rtlpci->rx_ring[rx_queue_idx].desc) {
+ pci_free_consistent(rtlpci->pdev,
sizeof(*rtlpci->rx_ring[rx_queue_idx].
desc) * rtlpci->rxringcount,
rtlpci->rx_ring[rx_queue_idx].desc,
rtlpci->rx_ring[rx_queue_idx].dma);
- rtlpci->rx_ring[rx_queue_idx].desc = NULL;
+ rtlpci->rx_ring[rx_queue_idx].desc = NULL;
+ }
}
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index 9718382..2d33d7d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -523,6 +523,10 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
dm_digtable.cur_igvalue, dm_digtable.pre_igvalue,
dm_digtable.backoff_val));
+ dm_digtable.cur_igvalue += 2;
+ if (dm_digtable.cur_igvalue > 0x3f)
+ dm_digtable.cur_igvalue = 0x3f;
+
if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) {
rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
dm_digtable.cur_igvalue);
@@ -1218,13 +1222,18 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
("PreState = %d, CurState = %d\n",
p_ra->pre_ratr_state, p_ra->ratr_state));
- rcu_read_lock();
- sta = ieee80211_find_sta(mac->vif, mac->bssid);
+ /* Only the PCI card uses sta in the update rate table
+ * callback routine */
+ if (rtlhal->interface == INTF_PCI) {
+ rcu_read_lock();
+ sta = ieee80211_find_sta(mac->vif, mac->bssid);
+ }
rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
p_ra->ratr_state);
p_ra->pre_ratr_state = p_ra->ratr_state;
- rcu_read_unlock();
+ if (rtlhal->interface == INTF_PCI)
+ rcu_read_unlock();
}
}
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
index 3b5af01..0c77a14 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
@@ -196,6 +196,8 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw,
/* Allocate skb buffer to contain firmware */
/* info and tx descriptor info. */
skb = dev_alloc_skb(frag_length);
+ if (!skb)
+ return false;
skb_reserve(skb, extra_descoffset);
seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length -
extra_descoffset));
@@ -575,6 +577,8 @@ static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd,
len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len);
skb = dev_alloc_skb(len);
+ if (!skb)
+ return false;
cb_desc = (struct rtl_tcb_desc *)(skb->cb);
cb_desc->queue_index = TXCMD_QUEUE;
cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL;
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index b07f8b7..e0e1688 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -328,6 +328,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_ptr += 3;
for (i = 0; i < burst_len; i++) {
+ if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len)
+ goto out_badnvs;
+
val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
| (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
@@ -339,6 +342,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_ptr += 4;
dest_addr += 4;
}
+
+ if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
+ goto out_badnvs;
}
/*
@@ -350,6 +356,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
*/
nvs_ptr = (u8 *)wl->nvs +
ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4);
+
+ if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
+ goto out_badnvs;
+
nvs_len -= nvs_ptr - (u8 *)wl->nvs;
/* Now we must set the partition correctly */
@@ -365,6 +375,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
kfree(nvs_aligned);
return 0;
+
+out_badnvs:
+ wl1271_error("nvs data is malformed");
+ return -EILSEQ;
}
static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 42935ac..b8ec8cd 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -121,6 +121,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
if (!wl->nvs)
return -ENODEV;
+ if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+ wl1271_warning("FEM index from INI out of bounds");
+ return -EINVAL;
+ }
+
gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
if (!gen_parms)
return -ENOMEM;
@@ -144,6 +149,12 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
gp->tx_bip_fem_manufacturer =
gen_parms->general_params.tx_bip_fem_manufacturer;
+ if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+ wl1271_warning("FEM index from FW out of bounds");
+ ret = -EINVAL;
+ goto out;
+ }
+
wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);
@@ -163,6 +174,11 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
if (!wl->nvs)
return -ENODEV;
+ if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+ wl1271_warning("FEM index from ini out of bounds");
+ return -EINVAL;
+ }
+
gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
if (!gen_parms)
return -ENOMEM;
@@ -187,6 +203,12 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
gp->tx_bip_fem_manufacturer =
gen_parms->general_params.tx_bip_fem_manufacturer;
+ if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+ wl1271_warning("FEM index from FW out of bounds");
+ ret = -EINVAL;
+ goto out;
+ }
+
wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 56f76ab..9542e46 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -83,14 +83,18 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
for (i = 0, j = 0;
i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS;
i++) {
-
flags = req->channels[i]->flags;
if (!test_bit(i, wl->scan.scanned_ch) &&
!(flags & IEEE80211_CHAN_DISABLED) &&
- ((!!(flags & IEEE80211_CHAN_PASSIVE_SCAN)) == passive) &&
- (req->channels[i]->band == band)) {
-
+ (req->channels[i]->band == band) &&
+ /*
+ * In passive scans, we scan all remaining
+ * channels, even if not marked as such.
+ * In active scans, we only scan channels not
+ * marked as passive.
+ */
+ (passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) {
wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",
req->channels[i]->band,
req->channels[i]->center_freq);
@@ -142,6 +146,10 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
int ret;
u16 scan_options = 0;
+ /* skip active scans if we don't have SSIDs */
+ if (!passive && wl->scan.req->n_ssids == 0)
+ return WL1271_NOTHING_TO_SCAN;
+
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
if (!cmd || !trigger) {
@@ -152,8 +160,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
/* We always use high priority scans */
scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH;
- /* No SSIDs means that we have a forced passive scan */
- if (passive || wl->scan.req->n_ssids == 0)
+ if (passive)
scan_options |= WL1271_SCAN_OPT_PASSIVE;
cmd->params.scan_options = cpu_to_le16(scan_options);