summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c92
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c19
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c43
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pri_detector.c49
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pri_detector.h27
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h13
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c19
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c170
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c137
27 files changed, 321 insertions, 373 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index fd69376ecc83..391da5ad6a99 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -18,6 +18,7 @@
#include "hw-ops.h"
#include "../regd.h"
#include "ar9002_phy.h"
+#include "ar5008_initvals.h"
/* All code below is for AR5008, AR9001, AR9002 */
@@ -43,23 +44,16 @@ static const int m2ThreshLowExt_off = 127;
static const int m1ThreshExt_off = 127;
static const int m2ThreshExt_off = 127;
+static const struct ar5416IniArray bank0 = STATIC_INI_ARRAY(ar5416Bank0);
+static const struct ar5416IniArray bank1 = STATIC_INI_ARRAY(ar5416Bank1);
+static const struct ar5416IniArray bank2 = STATIC_INI_ARRAY(ar5416Bank2);
+static const struct ar5416IniArray bank3 = STATIC_INI_ARRAY(ar5416Bank3);
+static const struct ar5416IniArray bank7 = STATIC_INI_ARRAY(ar5416Bank7);
-static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array,
- int col)
-{
- int i;
-
- for (i = 0; i < array->ia_rows; i++)
- bank[i] = INI_RA(array, i, col);
-}
-
-
-#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \
- ar5008_write_rf_array(ah, iniarray, regData, &(regWr))
-
-static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array,
- u32 *data, unsigned int *writecnt)
+static void ar5008_write_bank6(struct ath_hw *ah, unsigned int *writecnt)
{
+ struct ar5416IniArray *array = &ah->iniBank6;
+ u32 *data = ah->analogBank6Data;
int r;
ENABLE_REGWRITE_BUFFER(ah);
@@ -165,7 +159,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3);
/* write Bank 6 with new params */
- REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes);
+ ar5008_write_bank6(ah, &reg_writes);
}
/**
@@ -469,31 +463,16 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
*/
static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
{
-#define ATH_ALLOC_BANK(bank, size) do { \
- bank = devm_kzalloc(ah->dev, sizeof(u32) * size, GFP_KERNEL); \
- if (!bank) \
- goto error; \
- } while (0);
-
- struct ath_common *common = ath9k_hw_common(ah);
+ int size = ah->iniBank6.ia_rows * sizeof(u32);
if (AR_SREV_9280_20_OR_LATER(ah))
return 0;
- ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows);
- 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->bank6Temp, ah->iniBank6.ia_rows);
+ ah->analogBank6Data = devm_kzalloc(ah->dev, size, GFP_KERNEL);
+ if (!ah->analogBank6Data)
+ return -ENOMEM;
return 0;
-#undef ATH_ALLOC_BANK
-error:
- ath_err(common, "Cannot allocate RF banks\n");
- return -ENOMEM;
}
@@ -517,6 +496,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
u32 ob5GHz = 0, db5GHz = 0;
u32 ob2GHz = 0, db2GHz = 0;
int regWrites = 0;
+ int i;
/*
* Software does not need to program bank data
@@ -529,25 +509,8 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
/* Setup rf parameters */
eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
- /* Setup Bank 0 Write */
- ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1);
-
- /* Setup Bank 1 Write */
- ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1);
-
- /* Setup Bank 2 Write */
- ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1);
-
- /* Setup Bank 6 Write */
- ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3,
- modesIndex);
- {
- int i;
- for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) {
- ah->analogBank6Data[i] =
- INI_RA(&ah->iniBank6TPC, i, modesIndex);
- }
- }
+ for (i = 0; i < ah->iniBank6.ia_rows; i++)
+ ah->analogBank6Data[i] = INI_RA(&ah->iniBank6, i, modesIndex);
/* Only the 5 or 2 GHz OB/DB need to be set for a mode */
if (eepMinorRev >= 2) {
@@ -568,22 +531,13 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
}
}
- /* Setup Bank 7 Setup */
- ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1);
-
/* Write Analog registers */
- REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data,
- regWrites);
+ REG_WRITE_ARRAY(&bank0, 1, regWrites);
+ REG_WRITE_ARRAY(&bank1, 1, regWrites);
+ REG_WRITE_ARRAY(&bank2, 1, regWrites);
+ REG_WRITE_ARRAY(&bank3, modesIndex, regWrites);
+ ar5008_write_bank6(ah, &regWrites);
+ REG_WRITE_ARRAY(&bank7, 1, regWrites);
return true;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index f053d978540e..830daa12feb6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -67,12 +67,10 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
} else if (AR_SREV_9100_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100);
- INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100);
} else {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common);
- INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac);
}
@@ -80,20 +78,11 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
/* Common for AR5416, AR913x, AR9160 */
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain);
- INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0);
- INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1);
- INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2);
- INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3);
- INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7);
-
- /* Common for AR5416, AR9160 */
- if (!AR_SREV_9100(ah))
- INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6);
-
/* Common for AR913x, AR9160 */
if (!AR_SREV_5416(ah))
- INIT_INI_ARRAY(&ah->iniBank6TPC,
- ar5416Bank6TPC_9100);
+ INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100);
+ else
+ INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC);
}
/* iniAddac needs to be modified for these chips */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index a56b2416e2f9..8a1888d02070 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -234,6 +234,7 @@ struct ath_buf {
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
bool bf_stale;
+ struct ieee80211_tx_rate rates[4];
struct ath_buf_state bf_state;
};
@@ -311,6 +312,7 @@ struct ath_rx_edma {
struct ath_rx {
u8 defant;
u8 rxotherant;
+ bool discard_next;
u32 *rxlink;
u32 num_pkts;
unsigned int rxfilter;
@@ -657,11 +659,10 @@ enum sc_op_flags {
struct ath_rate_table;
struct ath9k_vif_iter_data {
- const u8 *hw_macaddr; /* phy's hardware address, set
- * before starting iteration for
- * valid bssid mask.
- */
+ u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
u8 mask[ETH_ALEN]; /* bssid mask */
+ bool has_hw_macaddr;
+
int naps; /* number of AP vifs */
int nmeshes; /* number of mesh vifs */
int nstations; /* number of station vifs */
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 5f05c26d1ec4..2ff570f7f8ff 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -79,7 +79,7 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
u8 chainmask = ah->txchainmask;
u8 rate = 0;
- sband = &sc->sbands[common->hw->conf.channel->band];
+ sband = &sc->sbands[common->hw->conf.chandef.chan->band];
rate = sband->bitrates[rateidx].hw_value;
if (vif->bss_conf.use_short_preamble)
rate |= sband->bitrates[rateidx].hw_value_short;
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 7bdd726c7a8f..7304e7585009 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -208,7 +208,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
return true;
ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n",
- currCal->calData->calType, conf->channel->center_freq);
+ currCal->calData->calType, conf->chandef.chan->center_freq);
ah->caldata->CalValid &= ~currCal->calData->calType;
currCal->calState = CAL_WAITING;
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 60dcb6c22db9..3d70b8c2bcdd 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -33,6 +33,12 @@ struct ar5416IniArray {
u32 ia_columns;
};
+#define STATIC_INI_ARRAY(array) { \
+ .ia_array = (u32 *)(array), \
+ .ia_rows = ARRAY_SIZE(array), \
+ .ia_columns = ARRAY_SIZE(array[0]), \
+ }
+
#define INIT_INI_ARRAY(iniarray, array) do { \
(iniarray)->ia_array = (u32 *)(array); \
(iniarray)->ia_rows = ARRAY_SIZE(array); \
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 905f1b313961..344fdde1d7a3 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -27,20 +27,6 @@ MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
MODULE_LICENSE("Dual BSD/GPL");
-int ath9k_cmn_padpos(__le16 frame_control)
-{
- int padpos = 24;
- if (ieee80211_has_a4(frame_control)) {
- padpos += ETH_ALEN;
- }
- if (ieee80211_is_data_qos(frame_control)) {
- padpos += IEEE80211_QOS_CTL_LEN;
- }
-
- return padpos;
-}
-EXPORT_SYMBOL(ath9k_cmn_padpos);
-
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -133,13 +119,14 @@ EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
struct ath_hw *ah)
{
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
struct ath9k_channel *channel;
u8 chan_idx;
chan_idx = curchan->hw_value;
channel = &ah->channels[chan_idx];
- ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type);
+ ath9k_cmn_update_ichannel(channel, curchan,
+ cfg80211_get_chandef_type(&hw->conf.chandef));
return channel;
}
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 6102476a65de..207d06995b15 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -42,7 +42,6 @@
#define ATH_EP_RND(x, mul) \
(((x) + ((mul)/2)) / (mul))
-int ath9k_cmn_padpos(__le16 frame_control);
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
struct ieee80211_channel *chan,
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c
index 508f8b33f0ef..7187d3671512 100644
--- a/drivers/net/wireless/ath/ath9k/dfs.c
+++ b/drivers/net/wireless/ath/ath9k/dfs.c
@@ -55,12 +55,6 @@ ath9k_postprocess_radar_event(struct ath_softc *sc,
u8 rssi;
u16 dur;
- ath_dbg(ath9k_hw_common(sc->sc_ah), DFS,
- "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n",
- ard->pulse_bw_info,
- ard->pulse_length_pri, ard->rssi,
- ard->pulse_length_ext, ard->ext_rssi);
-
/*
* Only the last 2 bits of the BW info are relevant, they indicate
* which channel the radar was detected in.
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
index 73fe8d6db566..491305c81fce 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
@@ -19,6 +19,7 @@
#include "dfs_pattern_detector.h"
#include "dfs_pri_detector.h"
+#include "ath9k.h"
/*
* tolerated deviation of radar time stamp in usecs on both sides
@@ -142,6 +143,7 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
{
u32 sz, i;
struct channel_detector *cd;
+ struct ath_common *common = ath9k_hw_common(dpd->ah);
cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
if (cd == NULL)
@@ -165,7 +167,8 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
return cd;
fail:
- pr_err("failed to allocate channel_detector for freq=%d\n", freq);
+ ath_dbg(common, DFS,
+ "failed to allocate channel_detector for freq=%d\n", freq);
channel_detector_exit(dpd, cd);
return NULL;
}
@@ -216,34 +219,34 @@ static bool
dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event)
{
u32 i;
- bool ts_wraparound;
struct channel_detector *cd;
- if (dpd->region == NL80211_DFS_UNSET) {
- /*
- * pulses received for a non-supported or un-initialized
- * domain are treated as detected radars
- */
+ /*
+ * pulses received for a non-supported or un-initialized
+ * domain are treated as detected radars for fail-safety
+ */
+ if (dpd->region == NL80211_DFS_UNSET)
return true;
- }
cd = channel_detector_get(dpd, event->freq);
if (cd == NULL)
return false;
- ts_wraparound = (event->ts < dpd->last_pulse_ts);
dpd->last_pulse_ts = event->ts;
- if (ts_wraparound) {
- /*
- * reset detector on time stamp wraparound
- * with monotonic time stamps, this should never happen
- */
- pr_warn("DFS: time stamp wraparound detected, resetting\n");
+ /* reset detector on time stamp wraparound, caused by TSF reset */
+ if (event->ts < dpd->last_pulse_ts)
dpd_reset(dpd);
- }
+
/* do type individual pattern matching */
for (i = 0; i < dpd->num_radar_types; i++) {
- if (cd->detectors[i]->add_pulse(cd->detectors[i], event) != 0) {
+ struct pri_detector *pd = cd->detectors[i];
+ struct pri_sequence *ps = pd->add_pulse(pd, event);
+ if (ps != NULL) {
+ ath_dbg(ath9k_hw_common(dpd->ah), DFS,
+ "DFS: radar found on freq=%d: id=%d, pri=%d, "
+ "count=%d, count_false=%d\n",
+ event->freq, pd->rs->type_id,
+ ps->pri, ps->count, ps->count_falses);
channel_detector_reset(dpd, cd);
return true;
}
@@ -285,9 +288,10 @@ static struct dfs_pattern_detector default_dpd = {
};
struct dfs_pattern_detector *
-dfs_pattern_detector_init(enum nl80211_dfs_regions region)
+dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region)
{
struct dfs_pattern_detector *dpd;
+ struct ath_common *common = ath9k_hw_common(ah);
dpd = kmalloc(sizeof(*dpd), GFP_KERNEL);
if (dpd == NULL)
@@ -296,10 +300,11 @@ dfs_pattern_detector_init(enum nl80211_dfs_regions region)
*dpd = default_dpd;
INIT_LIST_HEAD(&dpd->channel_detectors);
+ dpd->ah = ah;
if (dpd->set_dfs_domain(dpd, region))
return dpd;
- pr_err("Could not set DFS domain to %d. ", region);
+ ath_dbg(common, DFS,"Could not set DFS domain to %d", region);
kfree(dpd);
return NULL;
}
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
index cda52f39f28a..90a5abcc4265 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
+++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
@@ -80,6 +80,8 @@ struct dfs_pattern_detector {
enum nl80211_dfs_regions region;
u8 num_radar_types;
u64 last_pulse_ts;
+ /* needed for ath_dbg() */
+ struct ath_hw *ah;
const struct radar_detector_specs *radar_spec;
struct list_head channel_detectors;
@@ -92,10 +94,10 @@ struct dfs_pattern_detector {
*/
#if defined(CONFIG_ATH9K_DFS_CERTIFIED)
extern struct dfs_pattern_detector *
-dfs_pattern_detector_init(enum nl80211_dfs_regions region);
+dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region);
#else
static inline struct dfs_pattern_detector *
-dfs_pattern_detector_init(enum nl80211_dfs_regions region)
+dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region)
{
return NULL;
}
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
index 5e48c5515b8c..5ba4b6fe37c0 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
@@ -23,28 +23,6 @@
#include "dfs_debug.h"
/**
- * struct pri_sequence - sequence of pulses matching one PRI
- * @head: list_head
- * @pri: pulse repetition interval (PRI) in usecs
- * @dur: duration of sequence in usecs
- * @count: number of pulses in this sequence
- * @count_falses: number of not matching pulses in this sequence
- * @first_ts: time stamp of first pulse in usecs
- * @last_ts: time stamp of last pulse in usecs
- * @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur)
- */
-struct pri_sequence {
- struct list_head head;
- u32 pri;
- u32 dur;
- u32 count;
- u32 count_falses;
- u64 first_ts;
- u64 last_ts;
- u64 deadline_ts;
-};
-
-/**
* struct pulse_elem - elements in pulse queue
* @ts: time stamp in usecs
*/
@@ -393,8 +371,8 @@ static void pri_detector_exit(struct pri_detector *de)
kfree(de);
}
-static bool pri_detector_add_pulse(struct pri_detector *de,
- struct pulse_event *event)
+static struct pri_sequence *pri_detector_add_pulse(struct pri_detector *de,
+ struct pulse_event *event)
{
u32 max_updated_seq;
struct pri_sequence *ps;
@@ -403,38 +381,33 @@ static bool pri_detector_add_pulse(struct pri_detector *de,
/* ignore pulses not within width range */
if ((rs->width_min > event->width) || (rs->width_max < event->width))
- return false;
+ return NULL;
if ((ts - de->last_ts) < rs->max_pri_tolerance)
/* if delta to last pulse is too short, don't use this pulse */
- return false;
+ return NULL;
de->last_ts = ts;
max_updated_seq = pseq_handler_add_to_existing_seqs(de, ts);
if (!pseq_handler_create_sequences(de, ts, max_updated_seq)) {
- pr_err("failed to create pulse sequences\n");
pri_detector_reset(de, ts);
return false;
}
ps = pseq_handler_check_detection(de);
- if (ps != NULL) {
- pr_info("DFS: radar found: pri=%d, count=%d, count_false=%d\n",
- ps->pri, ps->count, ps->count_falses);
- pri_detector_reset(de, ts);
- return true;
- }
- pulse_queue_enqueue(de, ts);
- return false;
+ if (ps == NULL)
+ pulse_queue_enqueue(de, ts);
+
+ return ps;
}
-struct pri_detector *
-pri_detector_init(const struct radar_detector_specs *rs)
+struct pri_detector *pri_detector_init(const struct radar_detector_specs *rs)
{
struct pri_detector *de;
- de = kzalloc(sizeof(*de), GFP_KERNEL);
+
+ de = kzalloc(sizeof(*de), GFP_ATOMIC);
if (de == NULL)
return NULL;
de->exit = pri_detector_exit;
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h
index 81cde9f28e44..723962d1abc6 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h
+++ b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h
@@ -20,9 +20,31 @@
#include <linux/list.h>
/**
+ * struct pri_sequence - sequence of pulses matching one PRI
+ * @head: list_head
+ * @pri: pulse repetition interval (PRI) in usecs
+ * @dur: duration of sequence in usecs
+ * @count: number of pulses in this sequence
+ * @count_falses: number of not matching pulses in this sequence
+ * @first_ts: time stamp of first pulse in usecs
+ * @last_ts: time stamp of last pulse in usecs
+ * @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur)
+ */
+struct pri_sequence {
+ struct list_head head;
+ u32 pri;
+ u32 dur;
+ u32 count;
+ u32 count_falses;
+ u64 first_ts;
+ u64 last_ts;
+ u64 deadline_ts;
+};
+
+/**
* struct pri_detector - PRI detector element for a dedicated radar type
* @exit(): destructor
- * @add_pulse(): add pulse event, returns true if pattern was detected
+ * @add_pulse(): add pulse event, returns pri_sequence if pattern was detected
* @reset(): clear states and reset to given time stamp
* @rs: detector specs for this detector element
* @last_ts: last pulse time stamp considered for this element in usecs
@@ -34,7 +56,8 @@
*/
struct pri_detector {
void (*exit) (struct pri_detector *de);
- bool (*add_pulse)(struct pri_detector *de, struct pulse_event *e);
+ struct pri_sequence *
+ (*add_pulse)(struct pri_detector *de, struct pulse_event *e);
void (*reset) (struct pri_detector *de, u64 ts);
/* private: internal use only */
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index d0ce1f5bba10..f13f458dd656 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -308,7 +308,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv,
while(skb) {
hdr = (struct ieee80211_hdr *) skb->data;
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len > padpos) {
if (skb_headroom(skb) < padsize) {
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index a8016d70088a..0743a47cef8f 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -190,7 +190,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
{
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *channel = priv->hw->conf.channel;
+ struct ieee80211_channel *channel = priv->hw->conf.chandef.chan;
struct ath9k_hw_cal_data *caldata = NULL;
enum htc_phymode mode;
__be16 htc_mode;
@@ -250,7 +250,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
bool fastcc;
- struct ieee80211_channel *channel = hw->conf.channel;
+ struct ieee80211_channel *channel = hw->conf.chandef.chan;
struct ath9k_hw_cal_data *caldata = NULL;
enum htc_phymode mode;
__be16 htc_mode;
@@ -602,7 +602,7 @@ static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv,
u32 caps = 0;
int i, j;
- sband = priv->hw->wiphy->bands[priv->hw->conf.channel->band];
+ sband = priv->hw->wiphy->bands[priv->hw->conf.chandef.chan->band];
for (i = 0, j = 0; i < sband->n_bitrates; i++) {
if (sta->supp_rates[sband->band] & BIT(i)) {
@@ -866,7 +866,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw,
hdr = (struct ieee80211_hdr *) skb->data;
/* Add the padding after the header if this is not already done */
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len > padpos) {
if (skb_headroom(skb) < padsize) {
@@ -904,7 +904,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
struct ath9k_channel *init_channel;
int ret = 0;
enum htc_phymode mode;
@@ -1193,15 +1193,17 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
}
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) {
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&hw->conf.chandef);
int pos = curchan->hw_value;
ath_dbg(common, CONFIG, "Set channel: %d MHz\n",
curchan->center_freq);
ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
- hw->conf.channel,
- hw->conf.channel_type);
+ hw->conf.chandef.chan,
+ channel_type);
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
ath_err(common, "Unable to set channel\n");
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index bd8251c1c749..6bd0e92ea2aa 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -490,7 +490,7 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv,
if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI)
rate->flags |= IEEE80211_TX_RC_SHORT_GI;
} else {
- if (cur_conf->channel->band == IEEE80211_BAND_5GHZ)
+ if (cur_conf->chandef.chan->band == IEEE80211_BAND_5GHZ)
rate->idx += 4; /* No CCK rates */
}
@@ -939,7 +939,7 @@ static void ath9k_process_rate(struct ieee80211_hw *hw,
return;
}
- band = hw->conf.channel->band;
+ band = hw->conf.chandef.chan->band;
sband = hw->wiphy->bands[band];
for (i = 0; i < sband->n_bitrates; i++) {
@@ -966,7 +966,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
struct sk_buff *skb = rxbuf->skb;
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath_htc_rx_status *rxstatus;
- int hdrlen, padpos, padsize;
+ int hdrlen, padsize;
int last_rssi = ATH_RSSI_DUMMY_MARKER;
__le16 fc;
@@ -996,11 +996,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
fc = hdr->frame_control;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- padpos = ath9k_cmn_padpos(fc);
-
- padsize = padpos & 3;
- if (padsize && skb->len >= padpos+padsize+FCS_LEN) {
- memmove(skb->data + padsize, skb->data, padpos);
+ padsize = hdrlen & 3;
+ if (padsize && skb->len >= hdrlen+padsize+FCS_LEN) {
+ memmove(skb->data + padsize, skb->data, hdrlen);
skb_pull(skb, padsize);
}
@@ -1082,8 +1080,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
}
rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
- rx_status->band = hw->conf.channel->band;
- rx_status->freq = hw->conf.channel->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
rx_status->antenna = rxbuf->rxstatus.rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_END;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 3473a797651a..7f25da8444fe 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -139,7 +139,7 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
clockrate = 117;
else if (!ah->curchan) /* should really check for CCK instead */
clockrate = ATH9K_CLOCK_RATE_CCK;
- else if (conf->channel->band == IEEE80211_BAND_2GHZ)
+ else if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ)
clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
@@ -1100,7 +1100,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
}
/* As defined by IEEE 802.11-2007 17.3.8.6 */
- acktimeout = slottime + sifstime + 3 * ah->coverage_class + ack_offset;
+ slottime += 3 * ah->coverage_class;
+ acktimeout = slottime + sifstime + ack_offset;
ctstimeout = acktimeout;
/*
@@ -1110,7 +1111,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
* BA frames in some implementations, but it has been found to fix ACK
* timeout issues in other cases as well.
*/
- if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ &&
+ if (conf->chandef.chan &&
+ conf->chandef.chan->band == IEEE80211_BAND_2GHZ &&
!IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) {
acktimeout += 64 - sifstime - ah->slottime;
ctstimeout += 48 - sifstime - ah->slottime;
@@ -1697,12 +1699,11 @@ static void ath9k_hw_reset_opmode(struct ath_hw *ah,
ENABLE_REGWRITE_BUFFER(ah);
- REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
- REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
- | macStaId1
+ REG_RMW(ah, AR_STA_ID1, macStaId1
| AR_STA_ID1_RTS_USE_DEF
| (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
- | ah->sta_id1_defaults);
+ | ah->sta_id1_defaults,
+ ~AR_STA_ID1_SADH_MASK);
ath_hw_setbssidmask(common);
REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
ath9k_hw_write_associd(ah);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 30e62d92d46d..ae3034374bc4 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -847,14 +847,7 @@ struct ath_hw {
struct ath_hw_ops ops;
/* Used to program the radio on non single-chip devices */
- u32 *analogBank0Data;
- u32 *analogBank1Data;
- u32 *analogBank2Data;
- u32 *analogBank3Data;
u32 *analogBank6Data;
- u32 *analogBank6TPCData;
- u32 *analogBank7Data;
- u32 *bank6Temp;
int coverage_class;
u32 slottime;
@@ -885,14 +878,8 @@ struct ath_hw {
struct ar5416IniArray iniModes;
struct ar5416IniArray iniCommon;
- struct ar5416IniArray iniBank0;
struct ar5416IniArray iniBB_RfGain;
- struct ar5416IniArray iniBank1;
- struct ar5416IniArray iniBank2;
- struct ar5416IniArray iniBank3;
struct ar5416IniArray iniBank6;
- struct ar5416IniArray iniBank6TPC;
- struct ar5416IniArray iniBank7;
struct ar5416IniArray iniAddac;
struct ar5416IniArray iniPcieSerdes;
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 3be2eb0da84a..0237b2868961 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -577,7 +577,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
atomic_set(&ah->intr_ref_cnt, -1);
sc->sc_ah = ah;
- sc->dfs_detector = dfs_pattern_detector_init(NL80211_DFS_UNSET);
+ sc->dfs_detector = dfs_pattern_detector_init(ah, NL80211_DFS_UNSET);
if (!pdata) {
ah->ah_flags |= AH_USE_EEPROM;
@@ -766,7 +766,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
IEEE80211_HW_SPECTRUM_MGMT |
- IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+ IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+ IEEE80211_HW_SUPPORTS_RC_TABLE;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 7fdac6c7b3ea..849259b07370 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -214,7 +214,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
memset(tx_info, 0, sizeof(*tx_info));
- tx_info->band = hw->conf.channel->band;
+ tx_info->band = hw->conf.chandef.chan->band;
tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
tx_info->control.rates[0].idx = 0;
tx_info->control.rates[0].count = 1;
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 811007ec07a7..498fee04afa0 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -615,6 +615,14 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
rs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (ads.ds_rxstatus8 & AR_MichaelErr)
rs->rs_status |= ATH9K_RXERR_MIC;
+ } else {
+ if (ads.ds_rxstatus8 &
+ (AR_CRCErr | AR_PHYErr | AR_DecryptCRCErr | AR_MichaelErr))
+ rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;
+
+ /* Only up to MCS16 supported, everything above is invalid */
+ if (rs->rs_rate >= 0x90)
+ rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;
}
if (ads.ds_rxstatus8 & AR_KeyMiss)
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 1ff817061ebc..5865f92998e1 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -183,6 +183,7 @@ struct ath_htc_rx_status {
#define ATH9K_RXERR_DECRYPT 0x08
#define ATH9K_RXERR_MIC 0x10
#define ATH9K_RXERR_KEYMISS 0x20
+#define ATH9K_RXERR_CORRUPT_DESC 0x40
#define ATH9K_RX_MORE 0x01
#define ATH9K_RX_MORE_AGGR 0x02
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 1bf52c88004a..6963862a1872 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -589,7 +589,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
struct ath9k_channel *init_channel;
int r;
@@ -839,10 +839,14 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
struct ath9k_vif_iter_data *iter_data = data;
int i;
- if (iter_data->hw_macaddr)
+ if (iter_data->has_hw_macaddr) {
for (i = 0; i < ETH_ALEN; i++)
iter_data->mask[i] &=
~(iter_data->hw_macaddr[i] ^ mac[i]);
+ } else {
+ memcpy(iter_data->hw_macaddr, mac, ETH_ALEN);
+ iter_data->has_hw_macaddr = true;
+ }
switch (vif->type) {
case NL80211_IFTYPE_AP:
@@ -891,7 +895,6 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
* together with the BSSID mask when matching addresses.
*/
memset(iter_data, 0, sizeof(*iter_data));
- iter_data->hw_macaddr = common->macaddr;
memset(&iter_data->mask, 0xff, ETH_ALEN);
if (vif)
@@ -901,6 +904,8 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
ieee80211_iterate_active_interfaces_atomic(
sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
ath9k_vif_iter, iter_data);
+
+ memcpy(common->macaddr, iter_data->hw_macaddr, ETH_ALEN);
}
/* Called with sc->mutex held. */
@@ -1188,7 +1193,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
}
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&conf->chandef);
int pos = curchan->hw_value;
int old_pos = -1;
unsigned long flags;
@@ -1197,7 +1204,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
old_pos = ah->curchan - &ah->channels[0];
ath_dbg(common, CONFIG, "Set channel: %d MHz type: %d\n",
- curchan->center_freq, conf->channel_type);
+ curchan->center_freq, channel_type);
/* update survey stats for the old channel before switching */
spin_lock_irqsave(&common->cc_lock, flags);
@@ -1212,7 +1219,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
ath9k_hw_getnf(ah, ah->curchan);
ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
- curchan, conf->channel_type);
+ curchan, channel_type);
/*
* If the operating channel changes, change the survey in-use flags
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 96ac433ba7f6..aa4d368d8d3d 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -814,7 +814,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
* So, set fourth rate in series to be same as third one for
* above conditions.
*/
- if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
+ if ((sc->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) &&
(conf_is_ht(&sc->hw->conf))) {
u8 dot11rate = rate_table->info[rix].dot11rate;
u8 phy = rate_table->info[rix].phy;
@@ -1328,7 +1328,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG,
"Operating HT Bandwidth changed to: %d\n",
- sc->hw->conf.channel_type);
+ cfg80211_get_chandef_type(&sc->hw->conf.chandef));
}
}
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index ee7ca5aecdb0..8be2b5d8c155 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -124,13 +124,13 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc,
SKB_CB_ATHBUF(skb) = bf;
ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype);
- skb_queue_tail(&rx_edma->rx_fifo, skb);
+ __skb_queue_tail(&rx_edma->rx_fifo, skb);
return true;
}
static void ath_rx_addbuffer_edma(struct ath_softc *sc,
- enum ath9k_rx_qtype qtype, int size)
+ enum ath9k_rx_qtype qtype)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_buf *bf, *tbf;
@@ -155,7 +155,7 @@ static void ath_rx_remove_buffer(struct ath_softc *sc,
rx_edma = &sc->rx.rx_edma[qtype];
- while ((skb = skb_dequeue(&rx_edma->rx_fifo)) != NULL) {
+ while ((skb = __skb_dequeue(&rx_edma->rx_fifo)) != NULL) {
bf = SKB_CB_ATHBUF(skb);
BUG_ON(!bf);
list_add_tail(&bf->list, &sc->rx.rxbuf);
@@ -250,15 +250,9 @@ rx_init_fail:
static void ath_edma_start_recv(struct ath_softc *sc)
{
ath9k_hw_rxena(sc->sc_ah);
-
- ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP,
- sc->rx.rx_edma[ATH9K_RX_QUEUE_HP].rx_fifo_hwsize);
-
- ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
- sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
-
+ ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP);
+ ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP);
ath_opmode_init(sc);
-
ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
}
@@ -280,49 +274,47 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
sc->sc_ah->caps.rx_status_len;
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
return ath_rx_edma_init(sc, nbufs);
- } else {
- ath_dbg(common, CONFIG, "cachelsz %u rxbufsize %u\n",
- common->cachelsz, common->rx_bufsize);
- /* Initialize rx descriptors */
+ ath_dbg(common, CONFIG, "cachelsz %u rxbufsize %u\n",
+ common->cachelsz, common->rx_bufsize);
- error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
- "rx", nbufs, 1, 0);
- if (error != 0) {
- ath_err(common,
- "failed to allocate rx descriptors: %d\n",
- error);
+ /* Initialize rx descriptors */
+
+ error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
+ "rx", nbufs, 1, 0);
+ if (error != 0) {
+ ath_err(common,
+ "failed to allocate rx descriptors: %d\n",
+ error);
+ goto err;
+ }
+
+ list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+ skb = ath_rxbuf_alloc(common, common->rx_bufsize,
+ GFP_KERNEL);
+ if (skb == NULL) {
+ error = -ENOMEM;
goto err;
}
- list_for_each_entry(bf, &sc->rx.rxbuf, list) {
- skb = ath_rxbuf_alloc(common, common->rx_bufsize,
- GFP_KERNEL);
- if (skb == NULL) {
- error = -ENOMEM;
- goto err;
- }
-
- bf->bf_mpdu = skb;
- bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
- common->rx_bufsize,
- DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(sc->dev,
- bf->bf_buf_addr))) {
- dev_kfree_skb_any(skb);
- bf->bf_mpdu = NULL;
- bf->bf_buf_addr = 0;
- ath_err(common,
- "dma_mapping_error() on RX init\n");
- error = -ENOMEM;
- goto err;
- }
+ bf->bf_mpdu = skb;
+ bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+ common->rx_bufsize,
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(sc->dev,
+ bf->bf_buf_addr))) {
+ dev_kfree_skb_any(skb);
+ bf->bf_mpdu = NULL;
+ bf->bf_buf_addr = 0;
+ ath_err(common,
+ "dma_mapping_error() on RX init\n");
+ error = -ENOMEM;
+ goto err;
}
- sc->rx.rxlink = NULL;
}
-
+ sc->rx.rxlink = NULL;
err:
if (error)
ath_rx_cleanup(sc);
@@ -340,17 +332,17 @@ void ath_rx_cleanup(struct ath_softc *sc)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
ath_rx_edma_cleanup(sc);
return;
- } else {
- list_for_each_entry(bf, &sc->rx.rxbuf, list) {
- skb = bf->bf_mpdu;
- if (skb) {
- dma_unmap_single(sc->dev, bf->bf_buf_addr,
- common->rx_bufsize,
- DMA_FROM_DEVICE);
- dev_kfree_skb(skb);
- bf->bf_buf_addr = 0;
- bf->bf_mpdu = NULL;
- }
+ }
+
+ list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+ skb = bf->bf_mpdu;
+ if (skb) {
+ dma_unmap_single(sc->dev, bf->bf_buf_addr,
+ common->rx_bufsize,
+ DMA_FROM_DEVICE);
+ dev_kfree_skb(skb);
+ bf->bf_buf_addr = 0;
+ bf->bf_mpdu = NULL;
}
}
}
@@ -727,6 +719,13 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
ret = ath9k_hw_rxprocdesc(ah, tds, &trs);
if (ret == -EINPROGRESS)
return NULL;
+
+ /*
+ * mark descriptor as zero-length and set the 'more'
+ * flag to ensure that both buffers get discarded
+ */
+ rs->rs_datalen = 0;
+ rs->rs_more = true;
}
list_del(&bf->list);
@@ -863,7 +862,7 @@ static int ath9k_process_rate(struct ath_common *common,
unsigned int i = 0;
struct ath_softc __maybe_unused *sc = common->priv;
- band = hw->conf.channel->band;
+ band = hw->conf.chandef.chan->band;
sband = hw->wiphy->bands[band];
if (rx_stats->rs_rate & 0x80) {
@@ -933,14 +932,20 @@ static void ath9k_process_rssi(struct ath_common *common,
* up the frame up to let mac80211 handle the actual error case, be it no
* decryption key or real decryption error. This let us keep statistics there.
*/
-static int ath9k_rx_skb_preprocess(struct ath_common *common,
- struct ieee80211_hw *hw,
+static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
struct ieee80211_hdr *hdr,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rx_status,
bool *decrypt_error)
{
- struct ath_hw *ah = common->ah;
+ struct ieee80211_hw *hw = sc->hw;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ bool discard_current = sc->rx.discard_next;
+
+ sc->rx.discard_next = rx_stats->rs_more;
+ if (discard_current)
+ return -EINVAL;
/*
* everything but the rate is checked here, the rate check is done
@@ -958,14 +963,15 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
if (ath9k_process_rate(common, hw, rx_stats, rx_status))
return -EINVAL;
- rx_status->band = hw->conf.channel->band;
- rx_status->freq = hw->conf.channel->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->signal = ah->noise + rx_stats->rs_rssi;
rx_status->antenna = rx_stats->rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_END;
if (rx_stats->rs_moreaggr)
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+ sc->rx.discard_next = false;
return 0;
}
@@ -985,7 +991,7 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
fc = hdr->frame_control;
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(fc);
/* The MAC header is padded to have 32-bit boundary if the
* packet payload is non-zero. The general calculation for
@@ -1166,6 +1172,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
u64 tsf = 0;
u32 tsf_lower = 0;
unsigned long flags;
+ dma_addr_t new_buf_addr;
if (edma)
dma_type = DMA_BIDIRECTIONAL;
@@ -1242,8 +1249,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
}
}
- retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
- rxs, &decrypt_error);
+ retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs,
+ &decrypt_error);
if (retval)
goto requeue_drop_frag;
@@ -1264,10 +1271,20 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
goto requeue_drop_frag;
}
+ /* We will now give hardware our shiny new allocated skb */
+ new_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
+ common->rx_bufsize, dma_type);
+ if (unlikely(dma_mapping_error(sc->dev, new_buf_addr))) {
+ dev_kfree_skb_any(requeue_skb);
+ goto requeue_drop_frag;
+ }
+
/* Unmap the frame */
dma_unmap_single(sc->dev, bf->bf_buf_addr,
- common->rx_bufsize,
- dma_type);
+ common->rx_bufsize, dma_type);
+
+ bf->bf_mpdu = requeue_skb;
+ bf->bf_buf_addr = new_buf_addr;
skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len);
if (ah->caps.rx_status_len)
@@ -1277,21 +1294,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
rxs, decrypt_error);
- /* We will now give hardware our shiny new allocated skb */
- bf->bf_mpdu = requeue_skb;
- bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
- common->rx_bufsize,
- dma_type);
- if (unlikely(dma_mapping_error(sc->dev,
- bf->bf_buf_addr))) {
- dev_kfree_skb_any(requeue_skb);
- bf->bf_mpdu = NULL;
- bf->bf_buf_addr = 0;
- ath_err(common, "dma_mapping_error() on RX\n");
- ieee80211_rx(hw, skb);
- break;
- }
-
if (rs.rs_more) {
RX_STAT_INC(rx_frags);
/*
@@ -1309,6 +1311,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
sc->rx.frag = skb;
goto requeue;
}
+ if (rs.rs_status & ATH9K_RXERR_CORRUPT_DESC)
+ goto requeue_drop_frag;
if (sc->rx.frag) {
int space = skb->len - skb_tailroom(hdr_skb);
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 5929850649f0..5c4ab5026dca 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -1493,9 +1493,6 @@ enum {
#define AR9271_RADIO_RF_RST 0x20
#define AR9271_GATE_MAC_CTL 0x4000
-#define AR_STA_ID0 0x8000
-#define AR_STA_ID1 0x8004
-#define AR_STA_ID1_SADH_MASK 0x0000FFFF
#define AR_STA_ID1_STA_AP 0x00010000
#define AR_STA_ID1_ADHOC 0x00020000
#define AR_STA_ID1_PWR_SAV 0x00040000
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 89a64411b82e..eab0fcb7ded6 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -157,6 +157,13 @@ static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
seqno << IEEE80211_SEQ_SEQ_SHIFT);
}
+static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ath_buf *bf)
+{
+ ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
+ ARRAY_SIZE(bf->rates));
+}
+
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
struct ath_txq *txq = tid->ac->txq;
@@ -189,6 +196,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
sendbar = true;
} else {
+ ath_set_rates(tid->an->vif, tid->an->sta, bf);
ath_tx_send_normal(sc, txq, NULL, skb);
}
}
@@ -407,7 +415,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
tx_info = IEEE80211_SKB_CB(skb);
- memcpy(rates, tx_info->control.rates, sizeof(rates));
+ memcpy(rates, bf->rates, sizeof(rates));
retries = ts->ts_longretry + 1;
for (i = 0; i < ts->ts_rateindex; i++)
@@ -516,8 +524,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* not a holding desc.
*/
INIT_LIST_HEAD(&bf_head);
- if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
- bf_next != NULL || !bf_last->bf_stale)
+ if (bf_next != NULL || !bf_last->bf_stale)
list_move_tail(&bf->list, &bf_head);
if (!txpending || (tid->state & AGGR_CLEANUP)) {
@@ -537,8 +544,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
!txfail);
} else {
/* retry the un-acked ones */
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
- bf->bf_next == NULL && bf_last->bf_stale) {
+ if (bf->bf_next == NULL && bf_last->bf_stale) {
struct ath_buf *tbf;
tbf = ath_clone_txbuf(sc, bf_last);
@@ -738,8 +744,6 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
bool first_subfrm)
{
#define FIRST_DESC_NDELIMS 60
- struct sk_buff *skb = bf->bf_mpdu;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
u32 nsymbits, nsymbols;
u16 minlen;
u8 flags, rix;
@@ -780,8 +784,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
if (tid->an->mpdudensity == 0)
return ndelim;
- rix = tx_info->control.rates[0].idx;
- flags = tx_info->control.rates[0].flags;
+ rix = bf->rates[0].idx;
+ flags = bf->rates[0].flags;
width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
@@ -860,6 +864,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
bf_first = bf;
if (!rl) {
+ ath_set_rates(tid->an->vif, tid->an->sta, bf);
aggr_limit = ath_lookup_rate(sc, bf, tid);
rl = 1;
}
@@ -1000,14 +1005,14 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
skb = bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
- rates = tx_info->control.rates;
+ rates = bf->rates;
hdr = (struct ieee80211_hdr *)skb->data;
/* set dur_update_en for l-sig computation except for PS-Poll frames */
info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
info->rtscts_rate = fi->rtscts_rate;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < ARRAY_SIZE(bf->rates); i++) {
bool is_40, is_sgi, is_sp;
int phy;
@@ -1745,6 +1750,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
return;
}
+ ath_set_rates(tid->an->vif, tid->an->sta, bf);
bf->bf_state.bf_type = BUF_AMPDU;
INIT_LIST_HEAD(&bf_head);
list_add(&bf->list, &bf_head);
@@ -1894,49 +1900,6 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
return bf;
}
-/* FIXME: tx power */
-static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
- struct ath_tx_control *txctl)
-{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ath_atx_tid *tid = NULL;
- struct ath_buf *bf;
- u8 tidno;
-
- if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) {
- tidno = ieee80211_get_qos_ctl(hdr)[0] &
- IEEE80211_QOS_CTL_TID_MASK;
- tid = ATH_AN_2_TID(txctl->an, tidno);
-
- WARN_ON(tid->ac->txq != txctl->txq);
- }
-
- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
- /*
- * Try aggregation if it's a unicast data frame
- * and the destination is HT capable.
- */
- ath_tx_send_ampdu(sc, tid, skb, txctl);
- } else {
- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
- if (!bf) {
- if (txctl->paprd)
- dev_kfree_skb_any(skb);
- else
- ieee80211_free_txskb(sc->hw, skb);
- return;
- }
-
- bf->bf_state.bfs_paprd = txctl->paprd;
-
- if (txctl->paprd)
- bf->bf_state.bfs_paprd_timestamp = jiffies;
-
- ath_tx_send_normal(sc, txctl->txq, tid, skb);
- }
-}
-
/* Upon failure caller should free skb */
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_tx_control *txctl)
@@ -1947,8 +1910,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_vif *vif = info->control.vif;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
+ struct ath_atx_tid *tid = NULL;
+ struct ath_buf *bf;
int padpos, padsize;
int frmlen = skb->len + FCS_LEN;
+ u8 tidno;
int q;
/* NOTE: sta can be NULL according to net/mac80211.h */
@@ -1971,7 +1937,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
}
/* Add the padding after the header if this is not already done */
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len > padpos) {
if (skb_headroom(skb) < padsize)
@@ -2004,8 +1970,41 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
txq->stopped = true;
}
- ath_tx_start_dma(sc, skb, txctl);
+ if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) {
+ tidno = ieee80211_get_qos_ctl(hdr)[0] &
+ IEEE80211_QOS_CTL_TID_MASK;
+ tid = ATH_AN_2_TID(txctl->an, tidno);
+
+ WARN_ON(tid->ac->txq != txctl->txq);
+ }
+
+ if ((info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
+ /*
+ * Try aggregation if it's a unicast data frame
+ * and the destination is HT capable.
+ */
+ ath_tx_send_ampdu(sc, tid, skb, txctl);
+ goto out;
+ }
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+ if (!bf) {
+ if (txctl->paprd)
+ dev_kfree_skb_any(skb);
+ else
+ ieee80211_free_txskb(sc->hw, skb);
+ goto out;
+ }
+
+ bf->bf_state.bfs_paprd = txctl->paprd;
+
+ if (txctl->paprd)
+ bf->bf_state.bfs_paprd_timestamp = jiffies;
+
+ ath_set_rates(vif, sta, bf);
+ ath_tx_send_normal(sc, txctl->txq, tid, skb);
+
+out:
ath_txq_unlock(sc, txq);
return 0;
@@ -2033,7 +2032,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
/* Frame was ACKed */
tx_info->flags |= IEEE80211_TX_STAT_ACK;
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len>padpos+padsize) {
/*
@@ -2264,6 +2263,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
struct ath_txq *txq;
struct ath_buf *bf, *lastbf;
struct list_head bf_head;
+ struct list_head *fifo_list;
int status;
for (;;) {
@@ -2291,20 +2291,24 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
TX_STAT_INC(txq->axq_qnum, txprocdesc);
- if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+ fifo_list = &txq->txq_fifo[txq->txq_tailidx];
+ if (list_empty(fifo_list)) {
ath_txq_unlock(sc, txq);
return;
}
- bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
- struct ath_buf, list);
+ bf = list_first_entry(fifo_list, struct ath_buf, list);
+ if (bf->bf_stale) {
+ list_del(&bf->list);
+ ath_tx_return_buffer(sc, bf);
+ bf = list_first_entry(fifo_list, struct ath_buf, list);
+ }
+
lastbf = bf->bf_lastbf;
INIT_LIST_HEAD(&bf_head);
- list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
- &lastbf->list);
-
- if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+ if (list_is_last(&lastbf->list, fifo_list)) {
+ list_splice_tail_init(fifo_list, &bf_head);
INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
if (!list_empty(&txq->axq_q)) {
@@ -2315,6 +2319,11 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
list_splice_tail_init(&txq->axq_q, &bf_q);
ath_tx_txqaddbuf(sc, txq, &bf_q, true);
}
+ } else {
+ lastbf->bf_stale = true;
+ if (bf != lastbf)
+ list_cut_position(&bf_head, fifo_list,
+ lastbf->list.prev);
}
ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
OpenPOWER on IntegriCloud