提交 ad86c55b 编写于 作者: J John W. Linville

Merge branch 'master' of...

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
无相关合并请求
......@@ -1430,7 +1430,7 @@ F: Documentation/aoe/
F: drivers/block/aoe/
ATHEROS ATH GENERIC UTILITIES
M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
L: linux-wireless@vger.kernel.org
S: Supported
F: drivers/net/wireless/ath/*
......@@ -1438,7 +1438,7 @@ F: drivers/net/wireless/ath/*
ATHEROS ATH5K WIRELESS DRIVER
M: Jiri Slaby <jirislaby@gmail.com>
M: Nick Kossifidis <mickflemm@gmail.com>
M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
L: linux-wireless@vger.kernel.org
L: ath5k-devel@lists.ath5k.org
W: http://wireless.kernel.org/en/users/Drivers/ath5k
......
......@@ -176,6 +176,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
bcma_err(bus,
"Could not register dev for core 0x%03X\n",
core->id.id);
put_device(&core->dev);
continue;
}
core->dev_registered = true;
......
......@@ -2754,9 +2754,9 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
mask->control[band].legacy << 4;
/* copy mcs rate mask */
mcsrate = mask->control[band].mcs[1];
mcsrate = mask->control[band].ht_mcs[1];
mcsrate <<= 8;
mcsrate |= mask->control[band].mcs[0];
mcsrate |= mask->control[band].ht_mcs[0];
ratemask[band] |= mcsrate << 12;
ratemask[band] |= mcsrate << 28;
}
......@@ -2806,7 +2806,7 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
mask->control[band].legacy << 4;
/* copy mcs rate mask */
mcsrate = mask->control[band].mcs[0];
mcsrate = mask->control[band].ht_mcs[0];
ratemask[band] |= mcsrate << 12;
ratemask[band] |= mcsrate << 20;
}
......
......@@ -11,12 +11,14 @@ ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o
ath9k-$(CONFIG_ATH9K_PCI) += pci.o
ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o
ath9k-$(CONFIG_ATH9K_TX99) += tx99.o
ath9k-$(CONFIG_ATH9K_WOW) += wow.o
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o \
spectral.o
obj-$(CONFIG_ATH9K) += ath9k.o
ath9k_hw-y:= \
......
......@@ -724,14 +724,14 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
struct ath_ant_comb *antcomb = &sc->ant_comb;
int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
int curr_main_set;
int main_rssi = rs->rs_rssi_ctl0;
int alt_rssi = rs->rs_rssi_ctl1;
int main_rssi = rs->rs_rssi_ctl[0];
int alt_rssi = rs->rs_rssi_ctl[1];
int rx_ant_conf, main_ant_conf;
bool short_scan = false, ret;
rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) &
ATH_ANT_RX_MASK;
main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) &
ATH_ANT_RX_MASK;
if (alt_rssi >= antcomb->low_rssi_thresh) {
......
......@@ -32,12 +32,8 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
return 0;
}
if (ah->config.pcie_clock_req)
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9280PciePhy_clkreq_off_L1_9280);
else
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9280PciePhy_clkreq_always_on_L1_9280);
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9280PciePhy_clkreq_always_on_L1_9280);
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1);
......
......@@ -29,7 +29,8 @@ static void ar9002_hw_set_desc_link(void *ds, u32 ds_link)
((struct ath_desc*) ds)->ds_link = ds_link;
}
static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked,
u32 *sync_cause_p)
{
u32 isr = 0;
u32 mask2 = 0;
......@@ -136,7 +137,8 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
}
if (sync_cause) {
ath9k_debug_sync_cause(common, sync_cause);
if (sync_cause_p)
*sync_cause_p = sync_cause;
fatal_int =
(sync_cause &
(AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
......
......@@ -201,7 +201,6 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
ath9k_hw_get_channel_centers(ah, chan, &centers);
freq = centers.synth_center;
ah->config.spurmode = SPUR_ENABLE_EEPROM;
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
......
......@@ -131,6 +131,7 @@ static const struct ar9300_eeprom ar9300_default = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.switchcomspdt = 0,
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0,
......@@ -138,7 +139,7 @@ static const struct ar9300_eeprom ar9300_default = {
},
.base_ext1 = {
.ant_div_control = 0,
.future = {0, 0, 0},
.future = {0, 0},
.tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
},
.calFreqPier2G = {
......@@ -333,6 +334,7 @@ static const struct ar9300_eeprom ar9300_default = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.switchcomspdt = 0,
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0,
......@@ -707,6 +709,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.switchcomspdt = 0,
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0,
......@@ -714,7 +717,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
},
.base_ext1 = {
.ant_div_control = 0,
.future = {0, 0, 0},
.future = {0, 0},
.tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
},
.calFreqPier2G = {
......@@ -909,6 +912,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.switchcomspdt = 0,
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0,
......@@ -1284,6 +1288,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.switchcomspdt = 0,
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0,
......@@ -1291,7 +1296,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
},
.base_ext1 = {
.ant_div_control = 0,
.future = {0, 0, 0},
.future = {0, 0},
.tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
},
.calFreqPier2G = {
......@@ -1486,6 +1491,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.switchcomspdt = 0,
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0,
......@@ -1861,6 +1867,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.switchcomspdt = 0,
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0,
......@@ -1868,7 +1875,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
},
.base_ext1 = {
.ant_div_control = 0,
.future = {0, 0, 0},
.future = {0, 0},
.tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
},
.calFreqPier2G = {
......@@ -2063,6 +2070,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.switchcomspdt = 0,
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0,
......@@ -2437,6 +2445,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0c80C080),
.papdRateMaskHt40 = LE32(0x0080C080),
.switchcomspdt = 0,
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0,
......@@ -2444,7 +2453,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
},
.base_ext1 = {
.ant_div_control = 0,
.future = {0, 0, 0},
.future = {0, 0},
.tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
},
.calFreqPier2G = {
......@@ -2639,6 +2648,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.switchcomspdt = 0,
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0,
......@@ -4111,6 +4121,37 @@ static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah)
}
}
static void ar9003_hw_apply_minccapwr_thresh(struct ath_hw *ah,
bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
const u_int32_t cca_ctrl[AR9300_MAX_CHAINS] = {
AR_PHY_CCA_CTRL_0,
AR_PHY_CCA_CTRL_1,
AR_PHY_CCA_CTRL_2,
};
int chain;
u32 val;
if (is2ghz) {
if (!(eep->base_ext1.misc_enable & BIT(2)))
return;
} else {
if (!(eep->base_ext1.misc_enable & BIT(3)))
return;
}
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
if (!(ah->caps.tx_chainmask & BIT(chain)))
continue;
val = ar9003_modal_header(ah, is2ghz)->noiseFloorThreshCh[chain];
REG_RMW_FIELD(ah, cca_ctrl[chain],
AR_PHY_EXT_CCA0_THRESH62_1, val);
}
}
static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
struct ath9k_channel *chan)
{
......@@ -4125,6 +4166,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
ar9003_hw_internal_regulator_apply(ah);
ar9003_hw_apply_tuning_caps(ah);
ar9003_hw_apply_minccapwr_thresh(ah, chan);
ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
ar9003_hw_thermometer_apply(ah);
ar9003_hw_thermo_cal_apply(ah);
......
......@@ -270,10 +270,20 @@ struct cal_ctl_data_5g {
u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G];
} __packed;
#define MAX_BASE_EXTENSION_FUTURE 2
struct ar9300_BaseExtension_1 {
u8 ant_div_control;
u8 future[3];
u8 tempslopextension[8];
u8 future[MAX_BASE_EXTENSION_FUTURE];
/*
* misc_enable:
*
* BIT 0 - TX Gain Cap enable.
* BIT 1 - Uncompressed Checksum enable.
* BIT 2/3 - MinCCApwr enable 2g/5g.
*/
u8 misc_enable;
int8_t tempslopextension[8];
int8_t quick_drop_low;
int8_t quick_drop_high;
} __packed;
......
......@@ -175,7 +175,8 @@ static void ar9003_hw_set_desc_link(void *ds, u32 ds_link)
ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
}
static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked,
u32 *sync_cause_p)
{
u32 isr = 0;
u32 mask2 = 0;
......@@ -310,7 +311,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
ar9003_mci_get_isr(ah, masked);
if (sync_cause) {
ath9k_debug_sync_cause(common, sync_cause);
if (sync_cause_p)
*sync_cause_p = sync_cause;
fatal_int =
(sync_cause &
(AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
......@@ -476,12 +478,12 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
/* XXX: Keycache */
rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00);
rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01);
rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02);
rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10);
rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11);
rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12);
if (rxsp->status11 & AR_RxKeyIdxValid)
rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
......
......@@ -270,7 +270,7 @@
#define AR_PHY_AGC (AR_AGC_BASE + 0x14)
#define AR_PHY_EXT_ATTEN_CTL_0 (AR_AGC_BASE + 0x18)
#define AR_PHY_CCA_0 (AR_AGC_BASE + 0x1c)
#define AR_PHY_EXT_CCA0 (AR_AGC_BASE + 0x20)
#define AR_PHY_CCA_CTRL_0 (AR_AGC_BASE + 0x20)
#define AR_PHY_RESTART (AR_AGC_BASE + 0x24)
/*
......@@ -398,6 +398,8 @@
#define AR9280_PHY_CCA_THRESH62_S 12
#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF
#define AR_PHY_EXT_CCA0_THRESH62_S 0
#define AR_PHY_EXT_CCA0_THRESH62_1 0x000001FF
#define AR_PHY_EXT_CCA0_THRESH62_1_S 0
#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0
......
......@@ -27,40 +27,15 @@
#include "common.h"
#include "mci.h"
#include "dfs.h"
/*
* Header for the ath9k.ko driver core *only* -- hw code nor any other driver
* should rely on this file or its contents.
*/
#include "spectral.h"
struct ath_node;
struct ath_rate_table;
/* Macro to expand scalars to 64-bit objects */
#define ito64(x) (sizeof(x) == 1) ? \
(((unsigned long long int)(x)) & (0xff)) : \
(sizeof(x) == 2) ? \
(((unsigned long long int)(x)) & 0xffff) : \
((sizeof(x) == 4) ? \
(((unsigned long long int)(x)) & 0xffffffff) : \
(unsigned long long int)(x))
/* increment with wrap-around */
#define INCR(_l, _sz) do { \
(_l)++; \
(_l) &= ((_sz) - 1); \
} while (0)
/* decrement with wrap-around */
#define DECR(_l, _sz) do { \
(_l)--; \
(_l) &= ((_sz) - 1); \
} while (0)
#define TSF_TO_TU(_h,_l) \
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
#define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i))
extern struct ieee80211_ops ath9k_ops;
extern int ath9k_modparam_nohwcrypt;
extern int led_blink;
extern bool is_ath9k_unloaded;
struct ath_config {
u16 txpowlimit;
......@@ -70,6 +45,17 @@ struct ath_config {
/* Descriptor Management */
/*************************/
#define ATH_TXSTATUS_RING_SIZE 512
/* Macro to expand scalars to 64-bit objects */
#define ito64(x) (sizeof(x) == 1) ? \
(((unsigned long long int)(x)) & (0xff)) : \
(sizeof(x) == 2) ? \
(((unsigned long long int)(x)) & 0xffff) : \
((sizeof(x) == 4) ? \
(((unsigned long long int)(x)) & 0xffffffff) : \
(unsigned long long int)(x))
#define ATH_TXBUF_RESET(_bf) do { \
(_bf)->bf_lastbf = NULL; \
(_bf)->bf_next = NULL; \
......@@ -77,23 +63,6 @@ struct ath_config {
sizeof(struct ath_buf_state)); \
} while (0)
/**
* enum buffer_type - Buffer type flags
*
* @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
* @BUF_AGGR: Indicates whether the buffer can be aggregated
* (used in aggregation scheduling)
*/
enum buffer_type {
BUF_AMPDU = BIT(0),
BUF_AGGR = BIT(1),
};
#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
#define ATH_TXSTATUS_RING_SIZE 512
#define DS2PHYS(_dd, _ds) \
((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
......@@ -113,11 +82,20 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
/* RX / TX */
/***********/
#define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i))
/* increment with wrap-around */
#define INCR(_l, _sz) do { \
(_l)++; \
(_l) &= ((_sz) - 1); \
} while (0)
#define ATH_RXBUF 512
#define ATH_TXBUF 512
#define ATH_TXBUF_RESERVE 5
#define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
#define ATH_TXMAXTRY 13
#define ATH_MAX_SW_RETRIES 30
#define TID_TO_WME_AC(_tid) \
((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE : \
......@@ -133,6 +111,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
#define ATH_AGGR_MIN_QDEPTH 2
/* minimum h/w qdepth for non-aggregated traffic */
#define ATH_NON_AGGR_MIN_QDEPTH 8
#define ATH_TX_COMPLETE_POLL_INT 1000
#define ATH_TXFIFO_DEPTH 8
#define ATH_TX_ERROR 0x01
#define IEEE80211_SEQ_SEQ_SHIFT 4
#define IEEE80211_SEQ_MAX 4096
......@@ -167,9 +148,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
#define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e))
#define ATH_TX_COMPLETE_POLL_INT 1000
#define ATH_TXFIFO_DEPTH 8
struct ath_txq {
int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
u32 axq_qnum; /* ath9k hardware queue number */
......@@ -214,6 +192,21 @@ struct ath_rxbuf {
dma_addr_t bf_buf_addr;
};
/**
* enum buffer_type - Buffer type flags
*
* @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
* @BUF_AGGR: Indicates whether the buffer can be aggregated
* (used in aggregation scheduling)
*/
enum buffer_type {
BUF_AMPDU = BIT(0),
BUF_AGGR = BIT(1),
};
#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
struct ath_buf_state {
u8 bf_type;
u8 bfs_paprd;
......@@ -278,7 +271,6 @@ struct ath_tx_control {
struct ieee80211_sta *sta;
};
#define ATH_TX_ERROR 0x01
/**
* @txq_map: Index is mac80211 queue number. This is
......@@ -372,6 +364,22 @@ struct ath_vif {
struct ath_buf *av_bcbuf;
};
struct ath9k_vif_iter_data {
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 */
int nwds; /* number of WDS vifs */
int nadhocs; /* number of adhoc vifs */
};
void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ath9k_vif_iter_data *iter_data);
/*******************/
/* Beacon Handling */
/*******************/
......@@ -387,6 +395,9 @@ struct ath_vif {
#define ATH_DEFAULT_BMISS_LIMIT 10
#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
#define TSF_TO_TU(_h,_l) \
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
struct ath_beacon_config {
int beacon_interval;
u16 listen_interval;
......@@ -420,12 +431,10 @@ struct ath_beacon {
};
void ath9k_beacon_tasklet(unsigned long data);
bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
u32 changed);
void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_set_beacon(struct ath_softc *sc);
bool ath9k_csa_is_finished(struct ath_softc *sc);
......@@ -440,10 +449,9 @@ bool ath9k_csa_is_finished(struct ath_softc *sc);
#define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
#define ATH_ANI_MAX_SKIP_COUNT 10
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
#define ATH_PLL_WORK_INTERVAL 100
#define ATH_ANI_MAX_SKIP_COUNT 10
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
#define ATH_PLL_WORK_INTERVAL 100
void ath_tx_complete_poll_work(struct work_struct *work);
void ath_reset_work(struct work_struct *work);
......@@ -477,20 +485,19 @@ enum bt_op_flags {
};
struct ath_btcoex {
bool hw_timer_enabled;
spinlock_t btcoex_lock;
struct timer_list period_timer; /* Timer for BT period */
struct timer_list no_stomp_timer;
u32 bt_priority_cnt;
unsigned long bt_priority_time;
unsigned long op_flags;
int bt_stomp_type; /* Types of BT stomping */
u32 btcoex_no_stomp; /* in usec */
u32 btcoex_no_stomp; /* in msec */
u32 btcoex_period; /* in msec */
u32 btscan_no_stomp; /* in usec */
u32 btscan_no_stomp; /* in msec */
u32 duty_cycle;
u32 bt_wait_time;
int rssi_count;
struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
struct ath_mci_profile mci;
u8 stomp_audio;
};
......@@ -538,12 +545,6 @@ static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
}
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
struct ath9k_wow_pattern {
u8 pattern_bytes[MAX_PATTERN_SIZE];
u8 mask_bytes[MAX_PATTERN_SIZE];
u32 pattern_len;
};
/********************/
/* LED Control */
/********************/
......@@ -575,6 +576,12 @@ static inline void ath_fill_led_pin(struct ath_softc *sc)
/* Wake on Wireless LAN */
/************************/
struct ath9k_wow_pattern {
u8 pattern_bytes[MAX_PATTERN_SIZE];
u8 mask_bytes[MAX_PATTERN_SIZE];
u32 pattern_len;
};
#ifdef CONFIG_ATH9K_WOW
void ath9k_init_wow(struct ieee80211_hw *hw);
int ath9k_suspend(struct ieee80211_hw *hw,
......@@ -678,13 +685,8 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
* Used when PCI device not fully initialized by bootrom/BIOS
*/
#define DEFAULT_CACHELINE 32
#define ATH_REGCLASSIDS_MAX 10
#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
#define ATH_MAX_SW_RETRIES 30
#define ATH_CHAN_MAX 255
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
#define ATH_RATE_DUMMY_MARKER 0
enum sc_op_flags {
SC_OP_INVALID,
......@@ -703,37 +705,6 @@ enum sc_op_flags {
#define PS_BEACON_SYNC BIT(4)
#define PS_WAIT_FOR_ANI BIT(5)
struct ath_rate_table;
struct ath9k_vif_iter_data {
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 */
int nwds; /* number of WDS vifs */
int nadhocs; /* number of adhoc vifs */
};
/* enum spectral_mode:
*
* @SPECTRAL_DISABLED: spectral mode is disabled
* @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
* something else.
* @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
* is performed manually.
* @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels
* during a channel scan.
*/
enum spectral_mode {
SPECTRAL_DISABLED = 0,
SPECTRAL_BACKGROUND,
SPECTRAL_MANUAL,
SPECTRAL_CHANSCAN,
};
struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
......@@ -823,162 +794,6 @@ struct ath_softc {
#endif
};
#define SPECTRAL_SCAN_BITMASK 0x10
/* Radar info packet format, used for DFS and spectral formats. */
struct ath_radar_info {
u8 pulse_length_pri;
u8 pulse_length_ext;
u8 pulse_bw_info;
} __packed;
/* The HT20 spectral data has 4 bytes of additional information at it's end.
*
* [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]}
* [7:0]: all bins max_magnitude[9:2]
* [7:0]: all bins {max_index[5:0], max_magnitude[11:10]}
* [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
*/
struct ath_ht20_mag_info {
u8 all_bins[3];
u8 max_exp;
} __packed;
#define SPECTRAL_HT20_NUM_BINS 56
/* WARNING: don't actually use this struct! MAC may vary the amount of
* data by -1/+2. This struct is for reference only.
*/
struct ath_ht20_fft_packet {
u8 data[SPECTRAL_HT20_NUM_BINS];
struct ath_ht20_mag_info mag_info;
struct ath_radar_info radar_info;
} __packed;
#define SPECTRAL_HT20_TOTAL_DATA_LEN (sizeof(struct ath_ht20_fft_packet))
/* Dynamic 20/40 mode:
*
* [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]}
* [7:0]: lower bins max_magnitude[9:2]
* [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]}
* [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]}
* [7:0]: upper bins max_magnitude[9:2]
* [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]}
* [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
*/
struct ath_ht20_40_mag_info {
u8 lower_bins[3];
u8 upper_bins[3];
u8 max_exp;
} __packed;
#define SPECTRAL_HT20_40_NUM_BINS 128
/* WARNING: don't actually use this struct! MAC may vary the amount of
* data. This struct is for reference only.
*/
struct ath_ht20_40_fft_packet {
u8 data[SPECTRAL_HT20_40_NUM_BINS];
struct ath_ht20_40_mag_info mag_info;
struct ath_radar_info radar_info;
} __packed;
#define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet))
/* grabs the max magnitude from the all/upper/lower bins */
static inline u16 spectral_max_magnitude(u8 *bins)
{
return (bins[0] & 0xc0) >> 6 |
(bins[1] & 0xff) << 2 |
(bins[2] & 0x03) << 10;
}
/* return the max magnitude from the all/upper/lower bins */
static inline u8 spectral_max_index(u8 *bins)
{
s8 m = (bins[2] & 0xfc) >> 2;
/* TODO: this still doesn't always report the right values ... */
if (m > 32)
m |= 0xe0;
else
m &= ~0xe0;
return m + 29;
}
/* return the bitmap weight from the all/upper/lower bins */
static inline u8 spectral_bitmap_weight(u8 *bins)
{
return bins[0] & 0x3f;
}
/* FFT sample format given to userspace via debugfs.
*
* Please keep the type/length at the front position and change
* other fields after adding another sample type
*
* TODO: this might need rework when switching to nl80211-based
* interface.
*/
enum ath_fft_sample_type {
ATH_FFT_SAMPLE_HT20 = 1,
ATH_FFT_SAMPLE_HT20_40,
};
struct fft_sample_tlv {
u8 type; /* see ath_fft_sample */
__be16 length;
/* type dependent data follows */
} __packed;
struct fft_sample_ht20 {
struct fft_sample_tlv tlv;
u8 max_exp;
__be16 freq;
s8 rssi;
s8 noise;
__be16 max_magnitude;
u8 max_index;
u8 bitmap_weight;
__be64 tsf;
u8 data[SPECTRAL_HT20_NUM_BINS];
} __packed;
struct fft_sample_ht20_40 {
struct fft_sample_tlv tlv;
u8 channel_type;
__be16 freq;
s8 lower_rssi;
s8 upper_rssi;
__be64 tsf;
s8 lower_noise;
s8 upper_noise;
__be16 lower_max_magnitude;
__be16 upper_max_magnitude;
u8 lower_max_index;
u8 upper_max_index;
u8 lower_bitmap_weight;
u8 upper_bitmap_weight;
u8 max_exp;
u8 data[SPECTRAL_HT20_40_NUM_BINS];
} __packed;
/********/
/* TX99 */
/********/
......@@ -999,19 +814,13 @@ static inline int ath9k_tx99_send(struct ath_softc *sc,
}
#endif /* CONFIG_ATH9K_TX99 */
void ath9k_tasklet(unsigned long data);
int ath_cabq_update(struct ath_softc *);
static inline void ath_read_cachesize(struct ath_common *common, int *csz)
{
common->bus_ops->read_cachesize(common, csz);
}
extern struct ieee80211_ops ath9k_ops;
extern int ath9k_modparam_nohwcrypt;
extern int led_blink;
extern bool is_ath9k_unloaded;
void ath9k_tasklet(unsigned long data);
int ath_cabq_update(struct ath_softc *);
u8 ath9k_parse_mpdudensity(u8 mpdudensity);
irqreturn_t ath_isr(int irq, void *dev);
int ath_reset(struct ath_softc *sc);
......@@ -1020,13 +829,12 @@ void ath_restart_work(struct ath_softc *sc);
int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops);
void ath9k_deinit_device(struct ath_softc *sc);
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath9k_reload_chainmask_settings(struct ath_softc *sc);
void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw);
int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
enum spectral_mode spectral_mode);
u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
void ath_start_rfkill_poll(struct ath_softc *sc);
void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
void ath9k_ps_wakeup(struct ath_softc *sc);
void ath9k_ps_restore(struct ath_softc *sc);
#ifdef CONFIG_ATH9K_PCI
int ath_pci_init(void);
......@@ -1044,15 +852,4 @@ static inline int ath_ahb_init(void) { return 0; };
static inline void ath_ahb_exit(void) {};
#endif
void ath9k_ps_wakeup(struct ath_softc *sc);
void ath9k_ps_restore(struct ath_softc *sc);
u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
void ath_start_rfkill_poll(struct ath_softc *sc);
void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ath9k_vif_iter_data *iter_data);
#endif /* ATH9K_H */
......@@ -274,18 +274,19 @@ static int ath9k_beacon_choose_slot(struct ath_softc *sc)
return slot;
}
void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
u64 tsfadjust;
u32 tsfadjust;
if (avp->av_bslot == 0)
return;
tsfadjust = cur_conf->beacon_interval * avp->av_bslot / ATH_BCBUF;
avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
tsfadjust = TU_TO_USEC(tsfadjust) / ATH_BCBUF;
avp->tsf_adjust = cpu_to_le64(tsfadjust);
ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n",
(unsigned long long)tsfadjust, avp->av_bslot);
......@@ -431,6 +432,33 @@ static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt,
ath9k_hw_enable_interrupts(ah);
}
/* Calculate the modulo of a 64 bit TSF snapshot with a TU divisor */
static u32 ath9k_mod_tsf64_tu(u64 tsf, u32 div_tu)
{
u32 tsf_mod, tsf_hi, tsf_lo, mod_hi, mod_lo;
tsf_mod = tsf & (BIT(10) - 1);
tsf_hi = tsf >> 32;
tsf_lo = ((u32) tsf) >> 10;
mod_hi = tsf_hi % div_tu;
mod_lo = ((mod_hi << 22) + tsf_lo) % div_tu;
return (mod_lo << 10) | tsf_mod;
}
static u32 ath9k_get_next_tbtt(struct ath_softc *sc, u64 tsf,
unsigned int interval)
{
struct ath_hw *ah = sc->sc_ah;
unsigned int offset;
tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time);
offset = ath9k_mod_tsf64_tu(tsf, interval);
return (u32) tsf + TU_TO_USEC(interval) - offset;
}
/*
* For multi-bss ap support beacons are either staggered evenly over N slots or
* burst together. For the former arrange for the SWBA to be delivered for each
......@@ -446,7 +474,8 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc,
/* NB: the beacon interval is kept internally in TU's */
intval = TU_TO_USEC(conf->beacon_interval);
intval /= ATH_BCBUF;
nexttbtt = intval;
nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah),
conf->beacon_interval);
if (conf->enable_beacon)
ah->imask |= ATH9K_INT_SWBA;
......@@ -458,7 +487,7 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc,
(conf->enable_beacon) ? "Enable" : "Disable",
nexttbtt, intval, conf->beacon_interval);
ath9k_beacon_init(sc, nexttbtt, intval, true);
ath9k_beacon_init(sc, nexttbtt, intval, false);
}
/*
......@@ -475,11 +504,9 @@ static void ath9k_beacon_config_sta(struct ath_softc *sc,
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_beacon_state bs;
int dtimperiod, dtimcount, sleepduration;
int cfpperiod, cfpcount;
u32 nexttbtt = 0, intval, tsftu;
int dtim_intval, sleepduration;
u32 nexttbtt = 0, intval;
u64 tsf;
int num_beacons, offset, dtim_dec_count, cfp_dec_count;
/* No need to configure beacon if we are not associated */
if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
......@@ -492,53 +519,25 @@ static void ath9k_beacon_config_sta(struct ath_softc *sc,
intval = conf->beacon_interval;
/*
* Setup dtim and cfp parameters according to
* Setup dtim parameters according to
* last beacon we received (which may be none).
*/
dtimperiod = conf->dtim_period;
dtimcount = conf->dtim_count;
if (dtimcount >= dtimperiod) /* NB: sanity check */
dtimcount = 0;
cfpperiod = 1; /* NB: no PCF support yet */
cfpcount = 0;
dtim_intval = intval * conf->dtim_period;
sleepduration = conf->listen_interval * intval;
/*
* Pull nexttbtt forward to reflect the current
* TSF and calculate dtim+cfp state for the result.
* TSF and calculate dtim state for the result.
*/
tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
num_beacons = tsftu / intval + 1;
offset = tsftu % intval;
nexttbtt = tsftu - offset;
if (offset)
nexttbtt += intval;
/* DTIM Beacon every dtimperiod Beacon */
dtim_dec_count = num_beacons % dtimperiod;
/* CFP every cfpperiod DTIM Beacon */
cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
if (dtim_dec_count)
cfp_dec_count++;
dtimcount -= dtim_dec_count;
if (dtimcount < 0)
dtimcount += dtimperiod;
cfpcount -= cfp_dec_count;
if (cfpcount < 0)
cfpcount += cfpperiod;
bs.bs_intval = intval;
nexttbtt = ath9k_get_next_tbtt(sc, tsf, intval);
bs.bs_intval = TU_TO_USEC(intval);
bs.bs_dtimperiod = conf->dtim_period * bs.bs_intval;
bs.bs_nexttbtt = nexttbtt;
bs.bs_dtimperiod = dtimperiod*intval;
bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
bs.bs_cfpmaxduration = 0;
bs.bs_nextdtim = nexttbtt;
if (conf->dtim_period > 1)
bs.bs_nextdtim = ath9k_get_next_tbtt(sc, tsf, dtim_intval);
/*
* Calculate the number of consecutive beacons to miss* before taking
......@@ -566,18 +565,16 @@ static void ath9k_beacon_config_sta(struct ath_softc *sc,
* XXX fixed at 100ms
*/
bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100),
sleepduration));
if (bs.bs_sleepduration > bs.bs_dtimperiod)
bs.bs_sleepduration = bs.bs_dtimperiod;
/* TSF out of range threshold fixed at 1 second */
bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
ath_dbg(common, BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
ath_dbg(common, BEACON,
"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
bs.bs_bmissthreshold, bs.bs_sleepduration,
bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
ath_dbg(common, BEACON, "bmiss: %u sleep: %u\n",
bs.bs_bmissthreshold, bs.bs_sleepduration);
/* Set the computed STA beacon timers */
......@@ -600,25 +597,11 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
intval = TU_TO_USEC(conf->beacon_interval);
if (conf->ibss_creator) {
if (conf->ibss_creator)
nexttbtt = intval;
} else {
u32 tbtt, offset, tsftu;
u64 tsf;
/*
* Pull nexttbtt forward to reflect the current
* sync'd TSF.
*/
tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE;
offset = tsftu % conf->beacon_interval;
tbtt = tsftu - offset;
if (offset)
tbtt += conf->beacon_interval;
nexttbtt = TU_TO_USEC(tbtt);
}
else
nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah),
conf->beacon_interval);
if (conf->enable_beacon)
ah->imask |= ATH9K_INT_SWBA;
......@@ -640,7 +623,8 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
set_bit(SC_OP_BEACONS, &sc->sc_flags);
}
bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
static bool ath9k_allow_beacon_config(struct ath_softc *sc,
struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_vif *avp = (void *)vif->drv_priv;
......@@ -711,12 +695,17 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
unsigned long flags;
bool skip_beacon = false;
if (vif->type == NL80211_IFTYPE_AP)
ath9k_set_tsfadjust(sc, vif);
if (!ath9k_allow_beacon_config(sc, vif))
return;
if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
ath9k_cache_beacon_config(sc, bss_conf);
ath9k_set_beacon(sc);
set_bit(SC_OP_BEACONS, &sc->sc_flags);
return;
}
/*
......
......@@ -66,7 +66,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
.bt_first_slot_time = 5,
.bt_hold_rx_clear = true,
};
u32 i, idx;
bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
if (AR_SREV_9300_20_OR_LATER(ah))
......@@ -88,11 +87,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) |
SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
AR_BT_DISABLE_BT_ANT;
for (i = 0; i < 32; i++) {
idx = (debruijn32 << i) >> 27;
ah->hw_gen_timers.gen_timer_index[idx] = i;
}
}
EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
......
......@@ -98,10 +98,8 @@ struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw,
{
struct ieee80211_channel *curchan = chandef->chan;
struct ath9k_channel *channel;
u8 chan_idx;
chan_idx = curchan->hw_value;
channel = &ah->channels[chan_idx];
channel = &ah->channels[curchan->hw_value];
ath9k_cmn_update_ichannel(channel, chandef);
return channel;
......
......@@ -17,7 +17,6 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/export.h>
#include <linux/relay.h>
#include <asm/unaligned.h>
#include "ath9k.h"
......@@ -27,6 +26,47 @@
#define REG_READ_D(_ah, _reg) \
ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
void ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause)
{
if (sync_cause)
sc->debug.stats.istats.sync_cause_all++;
if (sync_cause & AR_INTR_SYNC_RTC_IRQ)
sc->debug.stats.istats.sync_rtc_irq++;
if (sync_cause & AR_INTR_SYNC_MAC_IRQ)
sc->debug.stats.istats.sync_mac_irq++;
if (sync_cause & AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS)
sc->debug.stats.istats.eeprom_illegal_access++;
if (sync_cause & AR_INTR_SYNC_APB_TIMEOUT)
sc->debug.stats.istats.apb_timeout++;
if (sync_cause & AR_INTR_SYNC_PCI_MODE_CONFLICT)
sc->debug.stats.istats.pci_mode_conflict++;
if (sync_cause & AR_INTR_SYNC_HOST1_FATAL)
sc->debug.stats.istats.host1_fatal++;
if (sync_cause & AR_INTR_SYNC_HOST1_PERR)
sc->debug.stats.istats.host1_perr++;
if (sync_cause & AR_INTR_SYNC_TRCV_FIFO_PERR)
sc->debug.stats.istats.trcv_fifo_perr++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_EP)
sc->debug.stats.istats.radm_cpl_ep++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_DLLP_ABORT)
sc->debug.stats.istats.radm_cpl_dllp_abort++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TLP_ABORT)
sc->debug.stats.istats.radm_cpl_tlp_abort++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_ECRC_ERR)
sc->debug.stats.istats.radm_cpl_ecrc_err++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT)
sc->debug.stats.istats.radm_cpl_timeout++;
if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
sc->debug.stats.istats.local_timeout++;
if (sync_cause & AR_INTR_SYNC_PM_ACCESS)
sc->debug.stats.istats.pm_access++;
if (sync_cause & AR_INTR_SYNC_MAC_AWAKE)
sc->debug.stats.istats.mac_awake++;
if (sync_cause & AR_INTR_SYNC_MAC_ASLEEP)
sc->debug.stats.istats.mac_asleep++;
if (sync_cause & AR_INTR_SYNC_MAC_SLEEP_ACCESS)
sc->debug.stats.istats.mac_sleep_access++;
}
static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
......@@ -1016,293 +1056,6 @@ static const struct file_operations fops_recv = {
.llseek = default_llseek,
};
static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char *mode = "";
unsigned int len;
switch (sc->spectral_mode) {
case SPECTRAL_DISABLED:
mode = "disable";
break;
case SPECTRAL_BACKGROUND:
mode = "background";
break;
case SPECTRAL_CHANSCAN:
mode = "chanscan";
break;
case SPECTRAL_MANUAL:
mode = "manual";
break;
}
len = strlen(mode);
return simple_read_from_buffer(user_buf, count, ppos, mode, len);
}
static ssize_t write_file_spec_scan_ctl(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
char buf[32];
ssize_t len;
if (config_enabled(CONFIG_ATH9K_TX99))
return -EOPNOTSUPP;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (strncmp("trigger", buf, 7) == 0) {
ath9k_spectral_scan_trigger(sc->hw);
} else if (strncmp("background", buf, 9) == 0) {
ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND);
ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n");
} else if (strncmp("chanscan", buf, 8) == 0) {
ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN);
ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n");
} else if (strncmp("manual", buf, 6) == 0) {
ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL);
ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n");
} else if (strncmp("disable", buf, 7) == 0) {
ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED);
ath_dbg(common, CONFIG, "spectral scan: disabled\n");
} else {
return -EINVAL;
}
return count;
}
static const struct file_operations fops_spec_scan_ctl = {
.read = read_file_spec_scan_ctl,
.write = write_file_spec_scan_ctl,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t read_file_spectral_short_repeat(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
len = sprintf(buf, "%d\n", sc->spec_config.short_repeat);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_spectral_short_repeat(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 1)
return -EINVAL;
sc->spec_config.short_repeat = val;
return count;
}
static const struct file_operations fops_spectral_short_repeat = {
.read = read_file_spectral_short_repeat,
.write = write_file_spectral_short_repeat,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t read_file_spectral_count(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
len = sprintf(buf, "%d\n", sc->spec_config.count);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_spectral_count(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 255)
return -EINVAL;
sc->spec_config.count = val;
return count;
}
static const struct file_operations fops_spectral_count = {
.read = read_file_spectral_count,
.write = write_file_spectral_count,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t read_file_spectral_period(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
len = sprintf(buf, "%d\n", sc->spec_config.period);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_spectral_period(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 255)
return -EINVAL;
sc->spec_config.period = val;
return count;
}
static const struct file_operations fops_spectral_period = {
.read = read_file_spectral_period,
.write = write_file_spectral_period,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t read_file_spectral_fft_period(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
len = sprintf(buf, "%d\n", sc->spec_config.fft_period);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_spectral_fft_period(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 15)
return -EINVAL;
sc->spec_config.fft_period = val;
return count;
}
static const struct file_operations fops_spectral_fft_period = {
.read = read_file_spectral_fft_period,
.write = write_file_spectral_fft_period,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static struct dentry *create_buf_file_handler(const char *filename,
struct dentry *parent,
umode_t mode,
struct rchan_buf *buf,
int *is_global)
{
struct dentry *buf_file;
buf_file = debugfs_create_file(filename, mode, parent, buf,
&relay_file_operations);
*is_global = 1;
return buf_file;
}
static int remove_buf_file_handler(struct dentry *dentry)
{
debugfs_remove(dentry);
return 0;
}
void ath_debug_send_fft_sample(struct ath_softc *sc,
struct fft_sample_tlv *fft_sample_tlv)
{
int length;
if (!sc->rfs_chan_spec_scan)
return;
length = __be16_to_cpu(fft_sample_tlv->length) +
sizeof(*fft_sample_tlv);
relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length);
}
static struct rchan_callbacks rfs_spec_scan_cb = {
.create_buf_file = create_buf_file_handler,
.remove_buf_file = remove_buf_file_handler,
};
static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
......@@ -1772,10 +1525,7 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw,
void ath9k_deinit_debug(struct ath_softc *sc)
{
if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
relay_close(sc->rfs_chan_spec_scan);
sc->rfs_chan_spec_scan = NULL;
}
ath9k_spectral_deinit_debug(sc);
}
int ath9k_init_debug(struct ath_hw *ah)
......@@ -1795,6 +1545,7 @@ int ath9k_init_debug(struct ath_hw *ah)
ath9k_dfs_init_debug(sc);
ath9k_tx99_init_debug(sc);
ath9k_spectral_init_debug(sc);
debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_dma);
......@@ -1841,23 +1592,6 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_base_eeprom);
debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_modal_eeprom);
sc->rfs_chan_spec_scan = relay_open("spectral_scan",
sc->debug.debugfs_phy,
1024, 256, &rfs_spec_scan_cb,
NULL);
debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc,
&fops_spec_scan_ctl);
debugfs_create_file("spectral_short_repeat", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc,
&fops_spectral_short_repeat);
debugfs_create_file("spectral_count", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_spectral_count);
debugfs_create_file("spectral_period", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_spectral_period);
debugfs_create_file("spectral_fft_period", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc,
&fops_spectral_fft_period);
debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
......
......@@ -292,11 +292,11 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct dentry *dir);
void ath_debug_send_fft_sample(struct ath_softc *sc,
struct fft_sample_tlv *fft_sample);
void ath9k_debug_stat_ant(struct ath_softc *sc,
struct ath_hw_antcomb_conf *div_ant_conf,
int main_rssi_avg, int alt_rssi_avg);
void ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause);
#else
#define RX_STAT_INC(c) /* NOP */
......@@ -331,6 +331,11 @@ static inline void ath9k_debug_stat_ant(struct ath_softc *sc,
}
static inline void
ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause)
{
}
#endif /* CONFIG_ATH9K_DEBUGFS */
#endif /* DEBUG_H */
......@@ -158,8 +158,8 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
return;
}
ard.rssi = rs->rs_rssi_ctl0;
ard.ext_rssi = rs->rs_rssi_ext0;
ard.rssi = rs->rs_rssi_ctl[0];
ard.ext_rssi = rs->rs_rssi_ext[0];
/*
* hardware stores this as 8 bit signed value.
......
......@@ -1085,31 +1085,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
{
#define EEP_MAP4K_SPURCHAN \
(ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
struct ath_common *common = ath9k_hw_common(ah);
u16 spur_val = AR_NO_SPUR;
ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
i, is2GHz, ah->config.spurchans[i][is2GHz]);
switch (ah->config.spurmode) {
case SPUR_DISABLE:
break;
case SPUR_ENABLE_IOCTL:
spur_val = ah->config.spurchans[i][is2GHz];
ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
spur_val);
break;
case SPUR_ENABLE_EEPROM:
spur_val = EEP_MAP4K_SPURCHAN;
break;
}
return spur_val;
#undef EEP_MAP4K_SPURCHAN
return ah->eeprom.map4k.modalHeader.spurChans[i].spurChan;
}
const struct eeprom_ops eep_4k_ops = {
......
......@@ -1004,31 +1004,7 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
u16 i, bool is2GHz)
{
#define EEP_MAP9287_SPURCHAN \
(ah->eeprom.map9287.modalHeader.spurChans[i].spurChan)
struct ath_common *common = ath9k_hw_common(ah);
u16 spur_val = AR_NO_SPUR;
ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
i, is2GHz, ah->config.spurchans[i][is2GHz]);
switch (ah->config.spurmode) {
case SPUR_DISABLE:
break;
case SPUR_ENABLE_IOCTL:
spur_val = ah->config.spurchans[i][is2GHz];
ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
spur_val);
break;
case SPUR_ENABLE_EEPROM:
spur_val = EEP_MAP9287_SPURCHAN;
break;
}
return spur_val;
#undef EEP_MAP9287_SPURCHAN
return ah->eeprom.map9287.modalHeader.spurChans[i].spurChan;
}
const struct eeprom_ops eep_ar9287_ops = {
......
......@@ -1348,31 +1348,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
{
#define EEP_DEF_SPURCHAN \
(ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
struct ath_common *common = ath9k_hw_common(ah);
u16 spur_val = AR_NO_SPUR;
ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
i, is2GHz, ah->config.spurchans[i][is2GHz]);
switch (ah->config.spurmode) {
case SPUR_DISABLE:
break;
case SPUR_ENABLE_IOCTL:
spur_val = ah->config.spurchans[i][is2GHz];
ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
spur_val);
break;
case SPUR_ENABLE_EEPROM:
spur_val = EEP_DEF_SPURCHAN;
break;
}
return spur_val;
#undef EEP_DEF_SPURCHAN
return ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan;
}
const struct eeprom_ops eep_def_ops = {
......
......@@ -157,36 +157,6 @@ static void ath_detect_bt_priority(struct ath_softc *sc)
}
}
static void ath9k_gen_timer_start(struct ath_hw *ah,
struct ath_gen_timer *timer,
u32 trig_timeout,
u32 timer_period)
{
ath9k_hw_gen_timer_start(ah, timer, trig_timeout, timer_period);
if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
ath9k_hw_disable_interrupts(ah);
ah->imask |= ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah);
ath9k_hw_enable_interrupts(ah);
}
}
static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
{
struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
ath9k_hw_gen_timer_stop(ah, timer);
/* if no timer is enabled, turn off interrupt mask */
if (timer_table->timer_mask.val == 0) {
ath9k_hw_disable_interrupts(ah);
ah->imask &= ~ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah);
ath9k_hw_enable_interrupts(ah);
}
}
static void ath_mci_ftp_adjust(struct ath_softc *sc)
{
struct ath_btcoex *btcoex = &sc->btcoex;
......@@ -257,19 +227,9 @@ static void ath_btcoex_period_timer(unsigned long data)
spin_unlock_bh(&btcoex->btcoex_lock);
/*
* btcoex_period is in msec while (btocex/btscan_)no_stomp are in usec,
* ensure that we properly convert btcoex_period to usec
* for any comparision with (btcoex/btscan_)no_stomp.
*/
if (btcoex->btcoex_period * 1000 != btcoex->btcoex_no_stomp) {
if (btcoex->hw_timer_enabled)
ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period,
timer_period * 10);
btcoex->hw_timer_enabled = true;
}
if (btcoex->btcoex_period != btcoex->btcoex_no_stomp)
mod_timer(&btcoex->no_stomp_timer,
jiffies + msecs_to_jiffies(timer_period));
ath9k_ps_restore(sc);
......@@ -282,7 +242,7 @@ static void ath_btcoex_period_timer(unsigned long data)
* Generic tsf based hw timer which configures weight
* registers to time slice between wlan and bt traffic
*/
static void ath_btcoex_no_stomp_timer(void *arg)
static void ath_btcoex_no_stomp_timer(unsigned long arg)
{
struct ath_softc *sc = (struct ath_softc *)arg;
struct ath_hw *ah = sc->sc_ah;
......@@ -311,24 +271,18 @@ static int ath_init_btcoex_timer(struct ath_softc *sc)
struct ath_btcoex *btcoex = &sc->btcoex;
btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 1000 *
btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
btcoex->btcoex_period / 100;
btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * 1000 *
btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
btcoex->btcoex_period / 100;
setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
(unsigned long) sc);
setup_timer(&btcoex->no_stomp_timer, ath_btcoex_no_stomp_timer,
(unsigned long) sc);
spin_lock_init(&btcoex->btcoex_lock);
btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah,
ath_btcoex_no_stomp_timer,
ath_btcoex_no_stomp_timer,
(void *) sc, AR_FIRST_NDP_TIMER);
if (!btcoex->no_stomp_timer)
return -ENOMEM;
return 0;
}
......@@ -343,10 +297,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)
ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n");
/* make sure duty cycle timer is also stopped when resuming */
if (btcoex->hw_timer_enabled) {
ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
btcoex->hw_timer_enabled = false;
}
del_timer_sync(&btcoex->no_stomp_timer);
btcoex->bt_priority_cnt = 0;
btcoex->bt_priority_time = jiffies;
......@@ -363,24 +314,16 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)
void ath9k_btcoex_timer_pause(struct ath_softc *sc)
{
struct ath_btcoex *btcoex = &sc->btcoex;
struct ath_hw *ah = sc->sc_ah;
del_timer_sync(&btcoex->period_timer);
if (btcoex->hw_timer_enabled) {
ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
btcoex->hw_timer_enabled = false;
}
del_timer_sync(&btcoex->no_stomp_timer);
}
void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
{
struct ath_btcoex *btcoex = &sc->btcoex;
if (btcoex->hw_timer_enabled) {
ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
btcoex->hw_timer_enabled = false;
}
del_timer_sync(&btcoex->no_stomp_timer);
}
u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
......@@ -400,12 +343,6 @@ u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status)
{
struct ath_hw *ah = sc->sc_ah;
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
if (status & ATH9K_INT_GENTIMER)
ath_gen_timer_isr(sc->sc_ah);
if (status & ATH9K_INT_MCI)
ath_mci_intr(sc);
}
......@@ -447,10 +384,6 @@ void ath9k_deinit_btcoex(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
if ((sc->btcoex.no_stomp_timer) &&
ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE)
ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
if (ath9k_hw_mci_is_enabled(ah))
ath_mci_cleanup(sc);
}
......
......@@ -600,10 +600,15 @@ void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
struct base_eep_header *ath9k_htc_get_eeprom_base(struct ath9k_htc_priv *priv);
#ifdef CONFIG_MAC80211_LEDS
void ath9k_configure_leds(struct ath9k_htc_priv *priv);
void ath9k_init_leds(struct ath9k_htc_priv *priv);
void ath9k_deinit_leds(struct ath9k_htc_priv *priv);
void ath9k_led_work(struct work_struct *work);
#else
static inline void ath9k_configure_leds(struct ath9k_htc_priv *priv)
{
}
static inline void ath9k_init_leds(struct ath9k_htc_priv *priv)
{
}
......
......@@ -70,11 +70,11 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
struct ath9k_beacon_state bs;
enum ath9k_int imask = 0;
int dtimperiod, dtimcount, sleepduration;
int cfpperiod, cfpcount, bmiss_timeout;
int bmiss_timeout;
u32 nexttbtt = 0, intval, tsftu;
__be32 htc_imask = 0;
u64 tsf;
int num_beacons, offset, dtim_dec_count, cfp_dec_count;
int num_beacons, offset, dtim_dec_count;
int ret __attribute__ ((unused));
u8 cmd_rsp;
......@@ -84,7 +84,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval);
/*
* Setup dtim and cfp parameters according to
* Setup dtim parameters according to
* last beacon we received (which may be none).
*/
dtimperiod = bss_conf->dtim_period;
......@@ -93,8 +93,6 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
dtimcount = 1;
if (dtimcount >= dtimperiod) /* NB: sanity check */
dtimcount = 0;
cfpperiod = 1; /* NB: no PCF support yet */
cfpcount = 0;
sleepduration = intval;
if (sleepduration <= 0)
......@@ -102,7 +100,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
/*
* Pull nexttbtt forward to reflect the current
* TSF and calculate dtim+cfp state for the result.
* TSF and calculate dtim state for the result.
*/
tsf = ath9k_hw_gettsf64(priv->ah);
tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
......@@ -115,26 +113,14 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
/* DTIM Beacon every dtimperiod Beacon */
dtim_dec_count = num_beacons % dtimperiod;
/* CFP every cfpperiod DTIM Beacon */
cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
if (dtim_dec_count)
cfp_dec_count++;
dtimcount -= dtim_dec_count;
if (dtimcount < 0)
dtimcount += dtimperiod;
cfpcount -= cfp_dec_count;
if (cfpcount < 0)
cfpcount += cfpperiod;
bs.bs_intval = intval;
bs.bs_nexttbtt = nexttbtt;
bs.bs_dtimperiod = dtimperiod*intval;
bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
bs.bs_cfpmaxduration = 0;
bs.bs_intval = TU_TO_USEC(intval);
bs.bs_nexttbtt = TU_TO_USEC(nexttbtt);
bs.bs_dtimperiod = dtimperiod * bs.bs_intval;
bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount * bs.bs_intval;
/*
* Calculate the number of consecutive beacons to miss* before taking
......@@ -161,7 +147,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
* XXX fixed at 100ms
*/
bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100),
sleepduration));
if (bs.bs_sleepduration > bs.bs_dtimperiod)
bs.bs_sleepduration = bs.bs_dtimperiod;
......@@ -170,10 +157,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
ath_dbg(common, CONFIG, "intval: %u tsf: %llu tsftu: %u\n",
intval, tsf, tsftu);
ath_dbg(common, CONFIG,
"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
bs.bs_bmissthreshold, bs.bs_sleepduration,
bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
ath_dbg(common, CONFIG, "bmiss: %u sleep: %u\n",
bs.bs_bmissthreshold, bs.bs_sleepduration);
/* Set the computed STA beacon timers */
......
......@@ -255,6 +255,17 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
cancel_work_sync(&priv->led_work);
}
void ath9k_configure_leds(struct ath9k_htc_priv *priv)
{
/* Configure gpio 1 for output */
ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
/* LED off, active low */
ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
}
void ath9k_init_leds(struct ath9k_htc_priv *priv)
{
int ret;
......@@ -268,11 +279,7 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv)
else
priv->ah->led_pin = ATH_LED_PIN_DEF;
/* Configure gpio 1 for output */
ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
/* LED off, active low */
ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
ath9k_configure_leds(priv);
snprintf(priv->led_name, sizeof(priv->led_name),
"ath9k_htc-%s", wiphy_name(priv->hw->wiphy));
......
......@@ -1000,6 +1000,8 @@ int ath9k_htc_resume(struct htc_target *htc_handle)
ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
priv->ah->hw_version.usbdev);
ath9k_configure_leds(priv);
return ret;
}
#endif
......
......@@ -49,9 +49,10 @@ static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
}
static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked,
u32 *sync_cause_p)
{
return ath9k_hw_ops(ah)->get_isr(ah, masked);
return ath9k_hw_ops(ah)->get_isr(ah, masked, sync_cause_p);
}
static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds,
......
......@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/time.h>
#include <linux/bitops.h>
#include <asm/unaligned.h>
#include "hw.h"
......@@ -84,48 +85,6 @@ static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah)
#ifdef CONFIG_ATH9K_DEBUGFS
void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause)
{
struct ath_softc *sc = common->priv;
if (sync_cause)
sc->debug.stats.istats.sync_cause_all++;
if (sync_cause & AR_INTR_SYNC_RTC_IRQ)
sc->debug.stats.istats.sync_rtc_irq++;
if (sync_cause & AR_INTR_SYNC_MAC_IRQ)
sc->debug.stats.istats.sync_mac_irq++;
if (sync_cause & AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS)
sc->debug.stats.istats.eeprom_illegal_access++;
if (sync_cause & AR_INTR_SYNC_APB_TIMEOUT)
sc->debug.stats.istats.apb_timeout++;
if (sync_cause & AR_INTR_SYNC_PCI_MODE_CONFLICT)
sc->debug.stats.istats.pci_mode_conflict++;
if (sync_cause & AR_INTR_SYNC_HOST1_FATAL)
sc->debug.stats.istats.host1_fatal++;
if (sync_cause & AR_INTR_SYNC_HOST1_PERR)
sc->debug.stats.istats.host1_perr++;
if (sync_cause & AR_INTR_SYNC_TRCV_FIFO_PERR)
sc->debug.stats.istats.trcv_fifo_perr++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_EP)
sc->debug.stats.istats.radm_cpl_ep++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_DLLP_ABORT)
sc->debug.stats.istats.radm_cpl_dllp_abort++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TLP_ABORT)
sc->debug.stats.istats.radm_cpl_tlp_abort++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_ECRC_ERR)
sc->debug.stats.istats.radm_cpl_ecrc_err++;
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT)
sc->debug.stats.istats.radm_cpl_timeout++;
if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
sc->debug.stats.istats.local_timeout++;
if (sync_cause & AR_INTR_SYNC_PM_ACCESS)
sc->debug.stats.istats.pm_access++;
if (sync_cause & AR_INTR_SYNC_MAC_AWAKE)
sc->debug.stats.istats.mac_awake++;
if (sync_cause & AR_INTR_SYNC_MAC_ASLEEP)
sc->debug.stats.istats.mac_asleep++;
if (sync_cause & AR_INTR_SYNC_MAC_SLEEP_ACCESS)
sc->debug.stats.istats.mac_sleep_access++;
}
#endif
......@@ -438,21 +397,12 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah)
static void ath9k_hw_init_config(struct ath_hw *ah)
{
int i;
ah->config.dma_beacon_response_time = 1;
ah->config.sw_beacon_response_time = 6;
ah->config.additional_swba_backoff = 0;
ah->config.ack_6mb = 0x0;
ah->config.cwm_ignore_extcca = 0;
ah->config.pcie_clock_req = 0;
ah->config.analog_shiftreg = 1;
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
ah->config.spurchans[i][0] = AR_NO_SPUR;
ah->config.spurchans[i][1] = AR_NO_SPUR;
}
ah->config.rx_intr_mitigation = true;
/*
......@@ -485,7 +435,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah->hw_version.magic = AR5416_MAGIC;
ah->hw_version.subvendorid = 0;
ah->atim_window = 0;
ah->sta_id1_defaults =
AR_STA_ID1_CRPT_MIC_ENABLE |
AR_STA_ID1_MCAST_KSRCH;
......@@ -1281,6 +1230,42 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
*coef_exponent = coef_exp - 16;
}
/* AR9330 WAR:
* call external reset function to reset WMAC if:
* - doing a cold reset
* - we have pending frames in the TX queues.
*/
static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type)
{
int i, npend = 0;
for (i = 0; i < AR_NUM_QCU; i++) {
npend = ath9k_hw_numtxpending(ah, i);
if (npend)
break;
}
if (ah->external_reset &&
(npend || type == ATH9K_RESET_COLD)) {
int reset_err = 0;
ath_dbg(ath9k_hw_common(ah), RESET,
"reset MAC via external reset\n");
reset_err = ah->external_reset();
if (reset_err) {
ath_err(ath9k_hw_common(ah),
"External reset failed, err=%d\n",
reset_err);
return false;
}
REG_WRITE(ah, AR_RTC_RESET, 1);
}
return true;
}
static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
{
u32 rst_flags;
......@@ -1331,38 +1316,8 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
}
if (AR_SREV_9330(ah)) {
int npend = 0;
int i;
/* AR9330 WAR:
* call external reset function to reset WMAC if:
* - doing a cold reset
* - we have pending frames in the TX queues
*/
for (i = 0; i < AR_NUM_QCU; i++) {
npend = ath9k_hw_numtxpending(ah, i);
if (npend)
break;
}
if (ah->external_reset &&
(npend || type == ATH9K_RESET_COLD)) {
int reset_err = 0;
ath_dbg(ath9k_hw_common(ah), RESET,
"reset MAC via external reset\n");
reset_err = ah->external_reset();
if (reset_err) {
ath_err(ath9k_hw_common(ah),
"External reset failed, err=%d\n",
reset_err);
return false;
}
REG_WRITE(ah, AR_RTC_RESET, 1);
}
if (!ath9k_hw_ar9330_reset_war(ah, type))
return false;
}
if (ath9k_hw_mci_is_enabled(ah))
......@@ -1372,7 +1327,12 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
REGWRITE_BUFFER_FLUSH(ah);
udelay(50);
if (AR_SREV_9300_20_OR_LATER(ah))
udelay(50);
else if (AR_SREV_9100(ah))
udelay(10000);
else
udelay(100);
REG_WRITE(ah, AR_RTC_RC, 0);
if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
......@@ -1408,8 +1368,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
REGWRITE_BUFFER_FLUSH(ah);
if (!AR_SREV_9300_20_OR_LATER(ah))
udelay(2);
udelay(2);
if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_RC, 0);
......@@ -1485,7 +1444,6 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
if (AR_SREV_9330(ah))
ar9003_hw_internal_regulator_apply(ah);
ath9k_hw_init_pll(ah, chan);
ath9k_hw_set_rfmode(ah, chan);
return true;
}
......@@ -1954,6 +1912,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (r)
return r;
ath9k_hw_set_rfmode(ah, chan);
if (ath9k_hw_mci_is_enabled(ah))
ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep);
......@@ -2264,9 +2224,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
case NL80211_IFTYPE_ADHOC:
REG_SET_BIT(ah, AR_TXCFG,
AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon +
TU_TO_USEC(ah->atim_window ? ah->atim_window : 1));
flags |= AR_NDP_TIMER_EN;
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon);
......@@ -2287,7 +2244,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period);
REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period);
REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period);
REG_WRITE(ah, AR_NDP_PERIOD, beacon_period);
REGWRITE_BUFFER_FLUSH(ah);
......@@ -2304,12 +2260,9 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
REG_WRITE(ah, AR_BEACON_PERIOD,
TU_TO_USEC(bs->bs_intval));
REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
TU_TO_USEC(bs->bs_intval));
REG_WRITE(ah, AR_NEXT_TBTT_TIMER, bs->bs_nexttbtt);
REG_WRITE(ah, AR_BEACON_PERIOD, bs->bs_intval);
REG_WRITE(ah, AR_DMA_BEACON_PERIOD, bs->bs_intval);
REGWRITE_BUFFER_FLUSH(ah);
......@@ -2337,9 +2290,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_NEXT_DTIM,
TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
REG_WRITE(ah, AR_NEXT_DTIM, bs->bs_nextdtim - SLEEP_SLOP);
REG_WRITE(ah, AR_NEXT_TIM, nextTbtt - SLEEP_SLOP);
REG_WRITE(ah, AR_SLEEP1,
SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
......@@ -2353,8 +2305,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
REG_WRITE(ah, AR_SLEEP2,
SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
REG_WRITE(ah, AR_TIM_PERIOD, beaconintval);
REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod);
REGWRITE_BUFFER_FLUSH(ah);
......@@ -2990,20 +2942,6 @@ static const struct ath_gen_timer_configuration gen_tmr_configuration[] =
/* HW generic timer primitives */
/* compute and clear index of rightmost 1 */
static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask)
{
u32 b;
b = *mask;
b &= (0-b);
*mask &= ~b;
b *= debruijn32;
b >>= 27;
return timer_table->gen_timer_index[b];
}
u32 ath9k_hw_gettsf32(struct ath_hw *ah)
{
return REG_READ(ah, AR_TSF_L32);
......@@ -3019,6 +2957,10 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
struct ath_gen_timer *timer;
if ((timer_index < AR_FIRST_NDP_TIMER) ||
(timer_index >= ATH_MAX_GEN_TIMER))
return NULL;
timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL);
if (timer == NULL)
return NULL;
......@@ -3036,23 +2978,13 @@ EXPORT_SYMBOL(ath_gen_timer_alloc);
void ath9k_hw_gen_timer_start(struct ath_hw *ah,
struct ath_gen_timer *timer,
u32 trig_timeout,
u32 timer_next,
u32 timer_period)
{
struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
u32 tsf, timer_next;
BUG_ON(!timer_period);
set_bit(timer->index, &timer_table->timer_mask.timer_bits);
tsf = ath9k_hw_gettsf32(ah);
u32 mask = 0;
timer_next = tsf + trig_timeout;
ath_dbg(ath9k_hw_common(ah), BTCOEX,
"current tsf %x period %x timer_next %x\n",
tsf, timer_period, timer_next);
timer_table->timer_mask |= BIT(timer->index);
/*
* Program generic timer registers
......@@ -3078,10 +3010,19 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah,
(1 << timer->index));
}
/* Enable both trigger and thresh interrupt masks */
REG_SET_BIT(ah, AR_IMR_S5,
(SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
if (timer->trigger)
mask |= SM(AR_GENTMR_BIT(timer->index),
AR_IMR_S5_GENTIMER_TRIG);
if (timer->overflow)
mask |= SM(AR_GENTMR_BIT(timer->index),
AR_IMR_S5_GENTIMER_THRESH);
REG_SET_BIT(ah, AR_IMR_S5, mask);
if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
ah->imask |= ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah);
}
}
EXPORT_SYMBOL(ath9k_hw_gen_timer_start);
......@@ -3089,11 +3030,6 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
{
struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
if ((timer->index < AR_FIRST_NDP_TIMER) ||
(timer->index >= ATH_MAX_GEN_TIMER)) {
return;
}
/* Clear generic timer enable bits. */
REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
gen_tmr_configuration[timer->index].mode_mask);
......@@ -3113,7 +3049,12 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
(SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
clear_bit(timer->index, &timer_table->timer_mask.timer_bits);
timer_table->timer_mask &= ~BIT(timer->index);
if (timer_table->timer_mask == 0) {
ah->imask &= ~ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah);
}
}
EXPORT_SYMBOL(ath9k_hw_gen_timer_stop);
......@@ -3134,32 +3075,32 @@ void ath_gen_timer_isr(struct ath_hw *ah)
{
struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
struct ath_gen_timer *timer;
struct ath_common *common = ath9k_hw_common(ah);
u32 trigger_mask, thresh_mask, index;
unsigned long trigger_mask, thresh_mask;
unsigned int index;
/* get hardware generic timer interrupt status */
trigger_mask = ah->intr_gen_timer_trigger;
thresh_mask = ah->intr_gen_timer_thresh;
trigger_mask &= timer_table->timer_mask.val;
thresh_mask &= timer_table->timer_mask.val;
trigger_mask &= timer_table->timer_mask;
thresh_mask &= timer_table->timer_mask;
trigger_mask &= ~thresh_mask;
while (thresh_mask) {
index = rightmost_index(timer_table, &thresh_mask);
for_each_set_bit(index, &thresh_mask, ARRAY_SIZE(timer_table->timers)) {
timer = timer_table->timers[index];
BUG_ON(!timer);
ath_dbg(common, BTCOEX, "TSF overflow for Gen timer %d\n",
index);
if (!timer)
continue;
if (!timer->overflow)
continue;
timer->overflow(timer->arg);
}
while (trigger_mask) {
index = rightmost_index(timer_table, &trigger_mask);
for_each_set_bit(index, &trigger_mask, ARRAY_SIZE(timer_table->timers)) {
timer = timer_table->timers[index];
BUG_ON(!timer);
ath_dbg(common, BTCOEX,
"Gen timer[%d] trigger\n", index);
if (!timer)
continue;
if (!timer->trigger)
continue;
timer->trigger(timer->arg);
}
}
......
......@@ -168,7 +168,7 @@
#define CAB_TIMEOUT_VAL 10
#define BEACON_TIMEOUT_VAL 10
#define MIN_BEACON_TIMEOUT_VAL 1
#define SLEEP_SLOP 3
#define SLEEP_SLOP TU_TO_USEC(3)
#define INIT_CONFIG_STATUS 0x00000000
#define INIT_RSSI_THR 0x00000700
......@@ -280,10 +280,8 @@ struct ath9k_hw_capabilities {
struct ath9k_ops_config {
int dma_beacon_response_time;
int sw_beacon_response_time;
int additional_swba_backoff;
int ack_6mb;
u32 cwm_ignore_extcca;
u8 pcie_clock_req;
u32 pcie_waen;
u8 analog_shiftreg;
u32 ofdm_trig_low;
......@@ -294,18 +292,11 @@ struct ath9k_ops_config {
int serialize_regmode;
bool rx_intr_mitigation;
bool tx_intr_mitigation;
#define SPUR_DISABLE 0
#define SPUR_ENABLE_IOCTL 1
#define SPUR_ENABLE_EEPROM 2
#define AR_SPUR_5413_1 1640
#define AR_SPUR_5413_2 1200
#define AR_NO_SPUR 0x8000
#define AR_BASE_FREQ_2GHZ 2300
#define AR_BASE_FREQ_5GHZ 4900
#define AR_SPUR_FEEQ_BOUND_HT40 19
#define AR_SPUR_FEEQ_BOUND_HT20 10
int spurmode;
u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
u8 max_txtrig_level;
u16 ani_poll_interval; /* ANI poll interval in ms */
......@@ -460,10 +451,6 @@ struct ath9k_beacon_state {
u32 bs_intval;
#define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */
u32 bs_dtimperiod;
u16 bs_cfpperiod;
u16 bs_cfpmaxduration;
u32 bs_cfpnext;
u16 bs_timoffset;
u16 bs_bmissthreshold;
u32 bs_sleepduration;
u32 bs_tsfoor_threshold;
......@@ -499,12 +486,6 @@ struct ath9k_hw_version {
#define AR_GENTMR_BIT(_index) (1 << (_index))
/*
* Using de Bruijin sequence to look up 1's index in a 32 bit number
* debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
*/
#define debruijn32 0x077CB531U
struct ath_gen_timer_configuration {
u32 next_addr;
u32 period_addr;
......@@ -520,12 +501,8 @@ struct ath_gen_timer {
};
struct ath_gen_timer_table {
u32 gen_timer_index[32];
struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER];
union {
unsigned long timer_bits;
u16 val;
} timer_mask;
u16 timer_mask;
};
struct ath_hw_antcomb_conf {
......@@ -690,7 +667,8 @@ struct ath_hw_ops {
struct ath9k_channel *chan,
u8 rxchainmask,
bool longcal);
bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked,
u32 *sync_cause_p);
void (*set_txdesc)(struct ath_hw *ah, void *ds,
struct ath_tx_info *i);
int (*proc_txdesc)(struct ath_hw *ah, void *ds,
......@@ -786,7 +764,6 @@ struct ath_hw {
u32 txurn_interrupt_mask;
atomic_t intr_ref_cnt;
bool chip_fullsleep;
u32 atim_window;
u32 modes_index;
/* Calibration */
......@@ -1018,13 +995,6 @@ bool ath9k_hw_check_alive(struct ath_hw *ah);
bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
#ifdef CONFIG_ATH9K_DEBUGFS
void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause);
#else
static inline void ath9k_debug_sync_cause(struct ath_common *common,
u32 sync_cause) {}
#endif
/* Generic hw timer primitives */
struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
void (*trigger)(void *),
......
......@@ -470,7 +470,6 @@ static int ath9k_init_queues(struct ath_softc *sc)
sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
ath_cabq_update(sc);
sc->tx.uapsdq = ath_txq_setup(sc, ATH9K_TX_QUEUE_UAPSD, 0);
......@@ -705,7 +704,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
ah->reg_ops.read = ath9k_ioread32;
ah->reg_ops.write = ath9k_iowrite32;
ah->reg_ops.rmw = ath9k_reg_rmw;
atomic_set(&ah->intr_ref_cnt, -1);
sc->sc_ah = ah;
pCap = &ah->caps;
......@@ -899,7 +897,7 @@ static const struct ieee80211_iface_combination if_comb[] = {
}
};
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
......
......@@ -481,8 +481,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
| AR_Q_MISC_CBR_INCR_DIS0);
value = (qi->tqi_readyTime -
(ah->config.sw_beacon_response_time -
ah->config.dma_beacon_response_time) -
ah->config.additional_swba_backoff) * 1024;
ah->config.dma_beacon_response_time)) * 1024;
REG_WRITE(ah, AR_QRDYTIMECFG(q),
value | AR_Q_RDYTIMECFG_EN);
REG_SET_BIT(ah, AR_DMISC(q),
......@@ -550,25 +549,25 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
rs->rs_rssi = ATH9K_RSSI_BAD;
rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD;
rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD;
rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD;
rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD;
rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD;
rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD;
} else {
rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0,
AR_RxRSSIAnt00);
rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0,
AR_RxRSSIAnt01);
rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0,
AR_RxRSSIAnt02);
rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4,
AR_RxRSSIAnt10);
rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4,
AR_RxRSSIAnt11);
rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4,
AR_RxRSSIAnt12);
}
if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
......
......@@ -133,12 +133,8 @@ struct ath_rx_status {
u8 rs_rate;
u8 rs_antenna;
u8 rs_more;
int8_t rs_rssi_ctl0;
int8_t rs_rssi_ctl1;
int8_t rs_rssi_ctl2;
int8_t rs_rssi_ext0;
int8_t rs_rssi_ext1;
int8_t rs_rssi_ext2;
int8_t rs_rssi_ctl[3];
int8_t rs_rssi_ext[3];
u8 rs_isaggr;
u8 rs_firstaggr;
u8 rs_moreaggr;
......
......@@ -508,6 +508,9 @@ void ath9k_tasklet(unsigned long data)
wake_up(&sc->tx_wait);
}
if (status & ATH9K_INT_GENTIMER)
ath_gen_timer_isr(sc->sc_ah);
ath9k_btcoex_handle_interrupt(sc, status);
/* re-enable hardware interrupt */
......@@ -538,6 +541,7 @@ irqreturn_t ath_isr(int irq, void *dev)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
enum ath9k_int status;
u32 sync_cause;
bool sched = false;
/*
......@@ -564,7 +568,8 @@ irqreturn_t ath_isr(int irq, void *dev)
* bits we haven't explicitly enabled so we mask the
* value to insure we only process bits we requested.
*/
ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
ath9k_hw_getisr(ah, &status, &sync_cause); /* NB: clears ISR too */
ath9k_debug_sync_cause(sc, sync_cause);
status &= ah->imask; /* discard unasked-for bits */
/*
......@@ -757,6 +762,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
*/
ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_hw_reset_tsf(ah);
spin_unlock_bh(&sc->sc_pcu_lock);
mutex_unlock(&sc->mutex);
......@@ -1657,13 +1664,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
}
if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
(changed & BSS_CHANGED_BEACON_INT)) {
if (ah->opmode == NL80211_IFTYPE_AP &&
bss_conf->enable_beacon)
ath9k_set_tsfadjust(sc, vif);
if (ath9k_allow_beacon_config(sc, vif))
ath9k_beacon_config(sc, vif, changed);
}
(changed & BSS_CHANGED_BEACON_INT))
ath9k_beacon_config(sc, vif, changed);
if (changed & BSS_CHANGED_ERP_SLOT) {
if (bss_conf->use_short_slot)
......
......@@ -200,7 +200,7 @@ static void ath_mci_update_scheme(struct ath_softc *sc)
if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE)
btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE;
btcoex->btcoex_no_stomp = btcoex->btcoex_period * 1000 *
btcoex->btcoex_no_stomp = btcoex->btcoex_period *
(100 - btcoex->duty_cycle) / 100;
ath9k_hw_btcoex_enable(sc->sc_ah);
......
......@@ -15,7 +15,6 @@
*/
#include <linux/dma-mapping.h>
#include <linux/relay.h>
#include "ath9k.h"
#include "ar9003_mac.h"
......@@ -906,6 +905,7 @@ static void ath9k_process_rssi(struct ath_common *common,
struct ath_hw *ah = common->ah;
int last_rssi;
int rssi = rx_stats->rs_rssi;
int i, j;
/*
* RSSI is not available for subframes in an A-MPDU.
......@@ -924,6 +924,20 @@ static void ath9k_process_rssi(struct ath_common *common,
return;
}
for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
s8 rssi;
if (!(ah->rxchainmask & BIT(i)))
continue;
rssi = rx_stats->rs_rssi_ctl[i];
if (rssi != ATH9K_RSSI_BAD) {
rxs->chains |= BIT(j);
rxs->chain_signal[j] = ah->noise + rssi;
}
j++;
}
/*
* Update Beacon RSSI, this is used by ANI.
*/
......@@ -960,186 +974,6 @@ static void ath9k_process_tsf(struct ath_rx_status *rs,
rxs->mactime += 0x100000000ULL;
}
#ifdef CONFIG_ATH9K_DEBUGFS
static s8 fix_rssi_inv_only(u8 rssi_val)
{
if (rssi_val == 128)
rssi_val = 0;
return (s8) rssi_val;
}
#endif
/* returns 1 if this was a spectral frame, even if not handled. */
static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
struct ath_rx_status *rs, u64 tsf)
{
#ifdef CONFIG_ATH9K_DEBUGFS
struct ath_hw *ah = sc->sc_ah;
u8 num_bins, *bins, *vdata = (u8 *)hdr;
struct fft_sample_ht20 fft_sample_20;
struct fft_sample_ht20_40 fft_sample_40;
struct fft_sample_tlv *tlv;
struct ath_radar_info *radar_info;
int len = rs->rs_datalen;
int dc_pos;
u16 fft_len, length, freq = ah->curchan->chan->center_freq;
enum nl80211_channel_type chan_type;
/* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
* via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
* yet, but this is supposed to be possible as well.
*/
if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL)
return 0;
/* check if spectral scan bit is set. This does not have to be checked
* if received through a SPECTRAL phy error, but shouldn't hurt.
*/
radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
return 0;
chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef);
if ((chan_type == NL80211_CHAN_HT40MINUS) ||
(chan_type == NL80211_CHAN_HT40PLUS)) {
fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN;
num_bins = SPECTRAL_HT20_40_NUM_BINS;
bins = (u8 *)fft_sample_40.data;
} else {
fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN;
num_bins = SPECTRAL_HT20_NUM_BINS;
bins = (u8 *)fft_sample_20.data;
}
/* Variation in the data length is possible and will be fixed later */
if ((len > fft_len + 2) || (len < fft_len - 1))
return 1;
switch (len - fft_len) {
case 0:
/* length correct, nothing to do. */
memcpy(bins, vdata, num_bins);
break;
case -1:
/* first byte missing, duplicate it. */
memcpy(&bins[1], vdata, num_bins - 1);
bins[0] = vdata[0];
break;
case 2:
/* MAC added 2 extra bytes at bin 30 and 32, remove them. */
memcpy(bins, vdata, 30);
bins[30] = vdata[31];
memcpy(&bins[31], &vdata[33], num_bins - 31);
break;
case 1:
/* MAC added 2 extra bytes AND first byte is missing. */
bins[0] = vdata[0];
memcpy(&bins[1], vdata, 30);
bins[31] = vdata[31];
memcpy(&bins[32], &vdata[33], num_bins - 32);
break;
default:
return 1;
}
/* DC value (value in the middle) is the blind spot of the spectral
* sample and invalid, interpolate it.
*/
dc_pos = num_bins / 2;
bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2;
if ((chan_type == NL80211_CHAN_HT40MINUS) ||
(chan_type == NL80211_CHAN_HT40PLUS)) {
s8 lower_rssi, upper_rssi;
s16 ext_nf;
u8 lower_max_index, upper_max_index;
u8 lower_bitmap_w, upper_bitmap_w;
u16 lower_mag, upper_mag;
struct ath9k_hw_cal_data *caldata = ah->caldata;
struct ath_ht20_40_mag_info *mag_info;
if (caldata)
ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan,
caldata->nfCalHist[3].privNF);
else
ext_nf = ATH_DEFAULT_NOISE_FLOOR;
length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv);
fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40;
fft_sample_40.tlv.length = __cpu_to_be16(length);
fft_sample_40.freq = __cpu_to_be16(freq);
fft_sample_40.channel_type = chan_type;
if (chan_type == NL80211_CHAN_HT40PLUS) {
lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
fft_sample_40.lower_noise = ah->noise;
fft_sample_40.upper_noise = ext_nf;
} else {
lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
fft_sample_40.lower_noise = ext_nf;
fft_sample_40.upper_noise = ah->noise;
}
fft_sample_40.lower_rssi = lower_rssi;
fft_sample_40.upper_rssi = upper_rssi;
mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1;
lower_mag = spectral_max_magnitude(mag_info->lower_bins);
upper_mag = spectral_max_magnitude(mag_info->upper_bins);
fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag);
fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag);
lower_max_index = spectral_max_index(mag_info->lower_bins);
upper_max_index = spectral_max_index(mag_info->upper_bins);
fft_sample_40.lower_max_index = lower_max_index;
fft_sample_40.upper_max_index = upper_max_index;
lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins);
upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins);
fft_sample_40.lower_bitmap_weight = lower_bitmap_w;
fft_sample_40.upper_bitmap_weight = upper_bitmap_w;
fft_sample_40.max_exp = mag_info->max_exp & 0xf;
fft_sample_40.tsf = __cpu_to_be64(tsf);
tlv = (struct fft_sample_tlv *)&fft_sample_40;
} else {
u8 max_index, bitmap_w;
u16 magnitude;
struct ath_ht20_mag_info *mag_info;
length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv);
fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20;
fft_sample_20.tlv.length = __cpu_to_be16(length);
fft_sample_20.freq = __cpu_to_be16(freq);
fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
fft_sample_20.noise = ah->noise;
mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
magnitude = spectral_max_magnitude(mag_info->all_bins);
fft_sample_20.max_magnitude = __cpu_to_be16(magnitude);
max_index = spectral_max_index(mag_info->all_bins);
fft_sample_20.max_index = max_index;
bitmap_w = spectral_bitmap_weight(mag_info->all_bins);
fft_sample_20.bitmap_weight = bitmap_w;
fft_sample_20.max_exp = mag_info->max_exp & 0xf;
fft_sample_20.tsf = __cpu_to_be64(tsf);
tlv = (struct fft_sample_tlv *)&fft_sample_20;
}
ath_debug_send_fft_sample(sc, tlv);
return 1;
#else
return 0;
#endif
}
static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr)
{
struct ath_hw *ah = sc->sc_ah;
......
/*
* Copyright (c) 2013 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/relay.h>
#include "ath9k.h"
static s8 fix_rssi_inv_only(u8 rssi_val)
{
if (rssi_val == 128)
rssi_val = 0;
return (s8) rssi_val;
}
static void ath_debug_send_fft_sample(struct ath_softc *sc,
struct fft_sample_tlv *fft_sample_tlv)
{
int length;
if (!sc->rfs_chan_spec_scan)
return;
length = __be16_to_cpu(fft_sample_tlv->length) +
sizeof(*fft_sample_tlv);
relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length);
}
/* returns 1 if this was a spectral frame, even if not handled. */
int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
struct ath_rx_status *rs, u64 tsf)
{
struct ath_hw *ah = sc->sc_ah;
u8 num_bins, *bins, *vdata = (u8 *)hdr;
struct fft_sample_ht20 fft_sample_20;
struct fft_sample_ht20_40 fft_sample_40;
struct fft_sample_tlv *tlv;
struct ath_radar_info *radar_info;
int len = rs->rs_datalen;
int dc_pos;
u16 fft_len, length, freq = ah->curchan->chan->center_freq;
enum nl80211_channel_type chan_type;
/* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
* via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
* yet, but this is supposed to be possible as well.
*/
if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL)
return 0;
/* check if spectral scan bit is set. This does not have to be checked
* if received through a SPECTRAL phy error, but shouldn't hurt.
*/
radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
return 0;
chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef);
if ((chan_type == NL80211_CHAN_HT40MINUS) ||
(chan_type == NL80211_CHAN_HT40PLUS)) {
fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN;
num_bins = SPECTRAL_HT20_40_NUM_BINS;
bins = (u8 *)fft_sample_40.data;
} else {
fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN;
num_bins = SPECTRAL_HT20_NUM_BINS;
bins = (u8 *)fft_sample_20.data;
}
/* Variation in the data length is possible and will be fixed later */
if ((len > fft_len + 2) || (len < fft_len - 1))
return 1;
switch (len - fft_len) {
case 0:
/* length correct, nothing to do. */
memcpy(bins, vdata, num_bins);
break;
case -1:
/* first byte missing, duplicate it. */
memcpy(&bins[1], vdata, num_bins - 1);
bins[0] = vdata[0];
break;
case 2:
/* MAC added 2 extra bytes at bin 30 and 32, remove them. */
memcpy(bins, vdata, 30);
bins[30] = vdata[31];
memcpy(&bins[31], &vdata[33], num_bins - 31);
break;
case 1:
/* MAC added 2 extra bytes AND first byte is missing. */
bins[0] = vdata[0];
memcpy(&bins[1], vdata, 30);
bins[31] = vdata[31];
memcpy(&bins[32], &vdata[33], num_bins - 32);
break;
default:
return 1;
}
/* DC value (value in the middle) is the blind spot of the spectral
* sample and invalid, interpolate it.
*/
dc_pos = num_bins / 2;
bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2;
if ((chan_type == NL80211_CHAN_HT40MINUS) ||
(chan_type == NL80211_CHAN_HT40PLUS)) {
s8 lower_rssi, upper_rssi;
s16 ext_nf;
u8 lower_max_index, upper_max_index;
u8 lower_bitmap_w, upper_bitmap_w;
u16 lower_mag, upper_mag;
struct ath9k_hw_cal_data *caldata = ah->caldata;
struct ath_ht20_40_mag_info *mag_info;
if (caldata)
ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan,
caldata->nfCalHist[3].privNF);
else
ext_nf = ATH_DEFAULT_NOISE_FLOOR;
length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv);
fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40;
fft_sample_40.tlv.length = __cpu_to_be16(length);
fft_sample_40.freq = __cpu_to_be16(freq);
fft_sample_40.channel_type = chan_type;
if (chan_type == NL80211_CHAN_HT40PLUS) {
lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
fft_sample_40.lower_noise = ah->noise;
fft_sample_40.upper_noise = ext_nf;
} else {
lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
fft_sample_40.lower_noise = ext_nf;
fft_sample_40.upper_noise = ah->noise;
}
fft_sample_40.lower_rssi = lower_rssi;
fft_sample_40.upper_rssi = upper_rssi;
mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1;
lower_mag = spectral_max_magnitude(mag_info->lower_bins);
upper_mag = spectral_max_magnitude(mag_info->upper_bins);
fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag);
fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag);
lower_max_index = spectral_max_index(mag_info->lower_bins);
upper_max_index = spectral_max_index(mag_info->upper_bins);
fft_sample_40.lower_max_index = lower_max_index;
fft_sample_40.upper_max_index = upper_max_index;
lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins);
upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins);
fft_sample_40.lower_bitmap_weight = lower_bitmap_w;
fft_sample_40.upper_bitmap_weight = upper_bitmap_w;
fft_sample_40.max_exp = mag_info->max_exp & 0xf;
fft_sample_40.tsf = __cpu_to_be64(tsf);
tlv = (struct fft_sample_tlv *)&fft_sample_40;
} else {
u8 max_index, bitmap_w;
u16 magnitude;
struct ath_ht20_mag_info *mag_info;
length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv);
fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20;
fft_sample_20.tlv.length = __cpu_to_be16(length);
fft_sample_20.freq = __cpu_to_be16(freq);
fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
fft_sample_20.noise = ah->noise;
mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
magnitude = spectral_max_magnitude(mag_info->all_bins);
fft_sample_20.max_magnitude = __cpu_to_be16(magnitude);
max_index = spectral_max_index(mag_info->all_bins);
fft_sample_20.max_index = max_index;
bitmap_w = spectral_bitmap_weight(mag_info->all_bins);
fft_sample_20.bitmap_weight = bitmap_w;
fft_sample_20.max_exp = mag_info->max_exp & 0xf;
fft_sample_20.tsf = __cpu_to_be64(tsf);
tlv = (struct fft_sample_tlv *)&fft_sample_20;
}
ath_debug_send_fft_sample(sc, tlv);
return 1;
}
/*********************/
/* spectral_scan_ctl */
/*********************/
static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char *mode = "";
unsigned int len;
switch (sc->spectral_mode) {
case SPECTRAL_DISABLED:
mode = "disable";
break;
case SPECTRAL_BACKGROUND:
mode = "background";
break;
case SPECTRAL_CHANSCAN:
mode = "chanscan";
break;
case SPECTRAL_MANUAL:
mode = "manual";
break;
}
len = strlen(mode);
return simple_read_from_buffer(user_buf, count, ppos, mode, len);
}
static ssize_t write_file_spec_scan_ctl(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
char buf[32];
ssize_t len;
if (config_enabled(CONFIG_ATH9K_TX99))
return -EOPNOTSUPP;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (strncmp("trigger", buf, 7) == 0) {
ath9k_spectral_scan_trigger(sc->hw);
} else if (strncmp("background", buf, 9) == 0) {
ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND);
ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n");
} else if (strncmp("chanscan", buf, 8) == 0) {
ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN);
ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n");
} else if (strncmp("manual", buf, 6) == 0) {
ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL);
ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n");
} else if (strncmp("disable", buf, 7) == 0) {
ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED);
ath_dbg(common, CONFIG, "spectral scan: disabled\n");
} else {
return -EINVAL;
}
return count;
}
static const struct file_operations fops_spec_scan_ctl = {
.read = read_file_spec_scan_ctl,
.write = write_file_spec_scan_ctl,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
/*************************/
/* spectral_short_repeat */
/*************************/
static ssize_t read_file_spectral_short_repeat(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
len = sprintf(buf, "%d\n", sc->spec_config.short_repeat);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_spectral_short_repeat(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 1)
return -EINVAL;
sc->spec_config.short_repeat = val;
return count;
}
static const struct file_operations fops_spectral_short_repeat = {
.read = read_file_spectral_short_repeat,
.write = write_file_spectral_short_repeat,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
/******************/
/* spectral_count */
/******************/
static ssize_t read_file_spectral_count(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
len = sprintf(buf, "%d\n", sc->spec_config.count);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_spectral_count(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 255)
return -EINVAL;
sc->spec_config.count = val;
return count;
}
static const struct file_operations fops_spectral_count = {
.read = read_file_spectral_count,
.write = write_file_spectral_count,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
/*******************/
/* spectral_period */
/*******************/
static ssize_t read_file_spectral_period(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
len = sprintf(buf, "%d\n", sc->spec_config.period);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_spectral_period(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 255)
return -EINVAL;
sc->spec_config.period = val;
return count;
}
static const struct file_operations fops_spectral_period = {
.read = read_file_spectral_period,
.write = write_file_spectral_period,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
/***********************/
/* spectral_fft_period */
/***********************/
static ssize_t read_file_spectral_fft_period(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
len = sprintf(buf, "%d\n", sc->spec_config.fft_period);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_spectral_fft_period(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 15)
return -EINVAL;
sc->spec_config.fft_period = val;
return count;
}
static const struct file_operations fops_spectral_fft_period = {
.read = read_file_spectral_fft_period,
.write = write_file_spectral_fft_period,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
/*******************/
/* Relay interface */
/*******************/
static struct dentry *create_buf_file_handler(const char *filename,
struct dentry *parent,
umode_t mode,
struct rchan_buf *buf,
int *is_global)
{
struct dentry *buf_file;
buf_file = debugfs_create_file(filename, mode, parent, buf,
&relay_file_operations);
*is_global = 1;
return buf_file;
}
static int remove_buf_file_handler(struct dentry *dentry)
{
debugfs_remove(dentry);
return 0;
}
struct rchan_callbacks rfs_spec_scan_cb = {
.create_buf_file = create_buf_file_handler,
.remove_buf_file = remove_buf_file_handler,
};
/*********************/
/* Debug Init/Deinit */
/*********************/
void ath9k_spectral_deinit_debug(struct ath_softc *sc)
{
if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
relay_close(sc->rfs_chan_spec_scan);
sc->rfs_chan_spec_scan = NULL;
}
}
void ath9k_spectral_init_debug(struct ath_softc *sc)
{
sc->rfs_chan_spec_scan = relay_open("spectral_scan",
sc->debug.debugfs_phy,
1024, 256, &rfs_spec_scan_cb,
NULL);
debugfs_create_file("spectral_scan_ctl",
S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc,
&fops_spec_scan_ctl);
debugfs_create_file("spectral_short_repeat",
S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc,
&fops_spectral_short_repeat);
debugfs_create_file("spectral_count",
S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc,
&fops_spectral_count);
debugfs_create_file("spectral_period",
S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc,
&fops_spectral_period);
debugfs_create_file("spectral_fft_period",
S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc,
&fops_spectral_fft_period);
}
/*
* Copyright (c) 2013 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef SPECTRAL_H
#define SPECTRAL_H
/* enum spectral_mode:
*
* @SPECTRAL_DISABLED: spectral mode is disabled
* @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
* something else.
* @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
* is performed manually.
* @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels
* during a channel scan.
*/
enum spectral_mode {
SPECTRAL_DISABLED = 0,
SPECTRAL_BACKGROUND,
SPECTRAL_MANUAL,
SPECTRAL_CHANSCAN,
};
#define SPECTRAL_SCAN_BITMASK 0x10
/* Radar info packet format, used for DFS and spectral formats. */
struct ath_radar_info {
u8 pulse_length_pri;
u8 pulse_length_ext;
u8 pulse_bw_info;
} __packed;
/* The HT20 spectral data has 4 bytes of additional information at it's end.
*
* [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]}
* [7:0]: all bins max_magnitude[9:2]
* [7:0]: all bins {max_index[5:0], max_magnitude[11:10]}
* [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
*/
struct ath_ht20_mag_info {
u8 all_bins[3];
u8 max_exp;
} __packed;
#define SPECTRAL_HT20_NUM_BINS 56
/* WARNING: don't actually use this struct! MAC may vary the amount of
* data by -1/+2. This struct is for reference only.
*/
struct ath_ht20_fft_packet {
u8 data[SPECTRAL_HT20_NUM_BINS];
struct ath_ht20_mag_info mag_info;
struct ath_radar_info radar_info;
} __packed;
#define SPECTRAL_HT20_TOTAL_DATA_LEN (sizeof(struct ath_ht20_fft_packet))
/* Dynamic 20/40 mode:
*
* [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]}
* [7:0]: lower bins max_magnitude[9:2]
* [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]}
* [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]}
* [7:0]: upper bins max_magnitude[9:2]
* [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]}
* [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
*/
struct ath_ht20_40_mag_info {
u8 lower_bins[3];
u8 upper_bins[3];
u8 max_exp;
} __packed;
#define SPECTRAL_HT20_40_NUM_BINS 128
/* WARNING: don't actually use this struct! MAC may vary the amount of
* data. This struct is for reference only.
*/
struct ath_ht20_40_fft_packet {
u8 data[SPECTRAL_HT20_40_NUM_BINS];
struct ath_ht20_40_mag_info mag_info;
struct ath_radar_info radar_info;
} __packed;
#define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet))
/* grabs the max magnitude from the all/upper/lower bins */
static inline u16 spectral_max_magnitude(u8 *bins)
{
return (bins[0] & 0xc0) >> 6 |
(bins[1] & 0xff) << 2 |
(bins[2] & 0x03) << 10;
}
/* return the max magnitude from the all/upper/lower bins */
static inline u8 spectral_max_index(u8 *bins)
{
s8 m = (bins[2] & 0xfc) >> 2;
/* TODO: this still doesn't always report the right values ... */
if (m > 32)
m |= 0xe0;
else
m &= ~0xe0;
return m + 29;
}
/* return the bitmap weight from the all/upper/lower bins */
static inline u8 spectral_bitmap_weight(u8 *bins)
{
return bins[0] & 0x3f;
}
/* FFT sample format given to userspace via debugfs.
*
* Please keep the type/length at the front position and change
* other fields after adding another sample type
*
* TODO: this might need rework when switching to nl80211-based
* interface.
*/
enum ath_fft_sample_type {
ATH_FFT_SAMPLE_HT20 = 1,
ATH_FFT_SAMPLE_HT20_40,
};
struct fft_sample_tlv {
u8 type; /* see ath_fft_sample */
__be16 length;
/* type dependent data follows */
} __packed;
struct fft_sample_ht20 {
struct fft_sample_tlv tlv;
u8 max_exp;
__be16 freq;
s8 rssi;
s8 noise;
__be16 max_magnitude;
u8 max_index;
u8 bitmap_weight;
__be64 tsf;
u8 data[SPECTRAL_HT20_NUM_BINS];
} __packed;
struct fft_sample_ht20_40 {
struct fft_sample_tlv tlv;
u8 channel_type;
__be16 freq;
s8 lower_rssi;
s8 upper_rssi;
__be64 tsf;
s8 lower_noise;
s8 upper_noise;
__be16 lower_max_magnitude;
__be16 upper_max_magnitude;
u8 lower_max_index;
u8 upper_max_index;
u8 lower_bitmap_weight;
u8 upper_bitmap_weight;
u8 max_exp;
u8 data[SPECTRAL_HT20_40_NUM_BINS];
} __packed;
void ath9k_spectral_init_debug(struct ath_softc *sc);
void ath9k_spectral_deinit_debug(struct ath_softc *sc);
void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw);
int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
enum spectral_mode spectral_mode);
#ifdef CONFIG_ATH9K_DEBUGFS
int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
struct ath_rx_status *rs, u64 tsf);
#else
static inline int ath_process_fft(struct ath_softc *sc,
struct ieee80211_hdr *hdr,
struct ath_rx_status *rs, u64 tsf)
{
return 0;
}
#endif /* CONFIG_ATH9K_DEBUGFS */
#endif /* SPECTRAL_H */
......@@ -174,14 +174,7 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
static struct ath_atx_tid *
ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
u8 tidno = 0;
hdr = (struct ieee80211_hdr *) skb->data;
if (ieee80211_is_data_qos(hdr->frame_control))
tidno = ieee80211_get_qos_ctl(hdr)[0];
tidno &= IEEE80211_QOS_CTL_TID_MASK;
u8 tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
return ATH_AN_2_TID(an, tidno);
}
......
......@@ -2060,22 +2060,28 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
case WCN36XX_HAL_OTA_TX_COMPL_IND:
case WCN36XX_HAL_MISSED_BEACON_IND:
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
mutex_lock(&wcn->hal_ind_mutex);
msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
if (msg_ind) {
msg_ind->msg_len = len;
msg_ind->msg = kmalloc(len, GFP_KERNEL);
memcpy(msg_ind->msg, buf, len);
list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
if (!msg_ind)
goto nomem;
msg_ind->msg_len = len;
msg_ind->msg = kmalloc(len, GFP_KERNEL);
if (!msg_ind->msg) {
kfree(msg_ind);
nomem:
/*
* FIXME: Do something smarter then just
* printing an error.
*/
wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
msg_header->msg_type);
break;
}
memcpy(msg_ind->msg, buf, len);
mutex_lock(&wcn->hal_ind_mutex);
list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
mutex_unlock(&wcn->hal_ind_mutex);
if (msg_ind)
break;
/* FIXME: Do something smarter then just printing an error. */
wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
msg_header->msg_type);
wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
break;
default:
wcn36xx_err("SMD_EVENT (%d) not supported\n",
......
......@@ -36,7 +36,6 @@ brcmfmac-objs += \
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
dhd_sdio.o \
bcmsdh.o \
bcmsdh_sdmmc.o \
sdio_chip.o
brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
usb.o
......
......@@ -101,35 +101,41 @@ struct brcmf_proto_bcdc_header {
* plus any space that might be needed
* for bus alignment padding.
*/
#define ROUND_UP_MARGIN 2048 /* Biggest bus block size possible for
* round off at the end of buffer
* Currently is SDIO
*/
struct brcmf_bcdc {
u16 reqid;
u8 bus_header[BUS_HEADER_LEN];
struct brcmf_proto_bcdc_dcmd msg;
unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN];
unsigned char buf[BRCMF_DCMD_MAXLEN];
};
static int brcmf_proto_bcdc_msg(struct brcmf_pub *drvr)
static int
brcmf_proto_bcdc_msg(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
uint len, bool set)
{
struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
int len = le32_to_cpu(bcdc->msg.len) +
sizeof(struct brcmf_proto_bcdc_dcmd);
struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
u32 flags;
brcmf_dbg(BCDC, "Enter\n");
/* NOTE : bcdc->msg.len holds the desired length of the buffer to be
* returned. Only up to BCDC_MAX_MSG_SIZE of this buffer area
* is actually sent to the dongle
*/
if (len > BCDC_MAX_MSG_SIZE)
len = BCDC_MAX_MSG_SIZE;
memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd));
msg->cmd = cpu_to_le32(cmd);
msg->len = cpu_to_le32(len);
flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT);
if (set)
flags |= BCDC_DCMD_SET;
flags = (flags & ~BCDC_DCMD_IF_MASK) |
(ifidx << BCDC_DCMD_IF_SHIFT);
msg->flags = cpu_to_le32(flags);
if (buf)
memcpy(bcdc->buf, buf, len);
/* Send request */
return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len);
return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg,
len + sizeof(struct brcmf_proto_bcdc_dcmd));
}
static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
......@@ -161,19 +167,7 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd));
msg->cmd = cpu_to_le32(cmd);
msg->len = cpu_to_le32(len);
flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT);
flags = (flags & ~BCDC_DCMD_IF_MASK) |
(ifidx << BCDC_DCMD_IF_SHIFT);
msg->flags = cpu_to_le32(flags);
if (buf)
memcpy(bcdc->buf, buf, len);
ret = brcmf_proto_bcdc_msg(drvr);
ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false);
if (ret < 0) {
brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n",
ret);
......@@ -227,19 +221,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd));
msg->cmd = cpu_to_le32(cmd);
msg->len = cpu_to_le32(len);
flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT) | BCDC_DCMD_SET;
flags = (flags & ~BCDC_DCMD_IF_MASK) |
(ifidx << BCDC_DCMD_IF_SHIFT);
msg->flags = cpu_to_le32(flags);
if (buf)
memcpy(bcdc->buf, buf, len);
ret = brcmf_proto_bcdc_msg(drvr);
ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true);
if (ret < 0)
goto done;
......@@ -347,6 +329,15 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
return 0;
}
static int
brcmf_proto_bcdc_txdata(struct brcmf_pub *drvr, int ifidx, u8 offset,
struct sk_buff *pktbuf)
{
brcmf_proto_bcdc_hdrpush(drvr, ifidx, offset, pktbuf);
return brcmf_bus_txdata(drvr->bus_if, pktbuf);
}
int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
{
struct brcmf_bcdc *bcdc;
......@@ -361,15 +352,15 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
goto fail;
}
drvr->proto->hdrpush = brcmf_proto_bcdc_hdrpush;
drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull;
drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
drvr->proto->txdata = brcmf_proto_bcdc_txdata;
drvr->proto->pd = bcdc;
drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN +
sizeof(struct brcmf_proto_bcdc_dcmd) + ROUND_UP_MARGIN;
sizeof(struct brcmf_proto_bcdc_dcmd);
return 0;
fail:
......
......@@ -24,6 +24,12 @@ enum brcmf_bus_state {
BRCMF_BUS_DATA /* Ready for frame transfers */
};
/* The level of bus communication with the dongle */
enum brcmf_bus_protocol_type {
BRCMF_PROTO_BCDC,
BRCMF_PROTO_MSGBUF
};
struct brcmf_bus_dcmd {
char *name;
char *param;
......@@ -65,6 +71,7 @@ struct brcmf_bus_ops {
* struct brcmf_bus - interface structure between common and bus layer
*
* @bus_priv: pointer to private bus device.
* @proto_type: protocol type, bcdc or msgbuf
* @dev: device pointer of bus device.
* @drvr: public driver information.
* @state: operational state of the bus interface.
......@@ -80,6 +87,7 @@ struct brcmf_bus {
struct brcmf_sdio_dev *sdio;
struct brcmf_usbdev *usb;
} bus_priv;
enum brcmf_bus_protocol_type proto_type;
struct device *dev;
struct brcmf_pub *drvr;
enum brcmf_bus_state state;
......
......@@ -68,7 +68,7 @@ brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
mutex_unlock(&ifp->drvr->proto_block);
......@@ -86,7 +86,7 @@ brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
mutex_unlock(&ifp->drvr->proto_block);
......@@ -155,7 +155,7 @@ brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
sizeof(drvr->proto_buf));
......@@ -195,7 +195,7 @@ brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
mutex_unlock(&drvr->proto_block);
return err;
......@@ -278,7 +278,7 @@ brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
drvr->proto_buf, sizeof(drvr->proto_buf));
......@@ -317,7 +317,7 @@ brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
}
brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
mutex_unlock(&drvr->proto_block);
return err;
......
......@@ -838,7 +838,7 @@ static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx)
brcmf_fws_hanger_cleanup(fws, matchfn, ifidx);
}
static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
static u8 brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
{
struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
u8 *wlh;
......@@ -887,9 +887,7 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
if (fillers)
memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers);
brcmf_proto_hdrpush(fws->drvr, brcmf_skb_if_flags_get_field(skb, INDEX),
data_offset >> 2, skb);
return 0;
return (u8)(data_offset >> 2);
}
static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
......@@ -897,10 +895,11 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
int fifo, bool send_immediately)
{
struct sk_buff *skb;
struct brcmf_bus *bus;
struct brcmf_skbuff_cb *skcb;
s32 err;
u32 len;
u8 data_offset;
int ifidx;
/* check delayedQ and suppressQ in one call using bitmap */
if (brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0)
......@@ -928,13 +927,11 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
skcb->state = BRCMF_FWS_SKBSTATE_TIM;
skcb->htod = 0;
skcb->htod_seq = 0;
bus = fws->drvr->bus_if;
err = brcmf_fws_hdrpush(fws, skb);
if (err == 0) {
brcmf_fws_unlock(fws);
err = brcmf_bus_txdata(bus, skb);
brcmf_fws_lock(fws);
}
data_offset = brcmf_fws_hdrpush(fws, skb);
ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
brcmf_fws_unlock(fws);
err = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb);
brcmf_fws_lock(fws);
if (err)
brcmu_pkt_buf_free_skb(skb);
return true;
......@@ -1393,7 +1390,7 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
entry->generation = genbit;
ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
if (ret == 0)
if (ret == 0) {
brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
brcmf_skbcb(skb)->htod_seq = seq;
if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
......@@ -1404,6 +1401,8 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
}
ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo,
skb);
}
if (ret != 0) {
/* suppress q is full or hdrpull failed, drop this packet */
brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
......@@ -1717,7 +1716,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
return 0;
}
static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
struct sk_buff *p)
{
struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
......@@ -1735,7 +1734,7 @@ static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
}
brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
brcmf_fws_hdrpush(fws, p);
return brcmf_fws_hdrpush(fws, p);
}
static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
......@@ -1803,20 +1802,21 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
{
struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
struct brcmf_fws_mac_descriptor *entry;
struct brcmf_bus *bus = fws->drvr->bus_if;
int rc;
u8 ifidx;
u8 data_offset;
entry = skcb->mac;
if (IS_ERR(entry))
return PTR_ERR(entry);
brcmf_fws_precommit_skb(fws, fifo, skb);
data_offset = brcmf_fws_precommit_skb(fws, fifo, skb);
entry->transit_count++;
if (entry->suppressed)
entry->suppr_transit_count++;
ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
brcmf_fws_unlock(fws);
rc = brcmf_bus_txdata(bus, skb);
rc = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb);
brcmf_fws_lock(fws);
brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name,
skcb->if_flags, skcb->htod, rc);
......@@ -1977,10 +1977,9 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
&skb, true);
ifidx = brcmf_skb_if_flags_get_field(skb,
INDEX);
brcmf_proto_hdrpush(drvr, ifidx, 0, skb);
/* Use bus module to send data frame */
/* Use proto layer to send data frame */
brcmf_fws_unlock(fws);
ret = brcmf_bus_txdata(drvr->bus_if, skb);
ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
brcmf_fws_lock(fws);
if (ret < 0)
brcmf_txfinalize(drvr, skb, false);
......
......@@ -39,7 +39,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
if (brcmf_proto_bcdc_attach(drvr))
goto fail;
if ((proto->hdrpush == NULL) || (proto->hdrpull == NULL) ||
if ((proto->txdata == NULL) || (proto->hdrpull == NULL) ||
(proto->query_dcmd == NULL) || (proto->set_dcmd == NULL)) {
brcmf_err("Not all proto handlers have been installed\n");
goto fail;
......
......@@ -17,14 +17,14 @@
#define BRCMFMAC_PROTO_H
struct brcmf_proto {
void (*hdrpush)(struct brcmf_pub *drvr, int ifidx, u8 offset,
struct sk_buff *skb);
int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
struct sk_buff *skb);
int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
void *buf, uint len);
int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
uint len);
int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
struct sk_buff *skb);
void *pd;
};
......@@ -32,11 +32,6 @@ struct brcmf_proto {
int brcmf_proto_attach(struct brcmf_pub *drvr);
void brcmf_proto_detach(struct brcmf_pub *drvr);
static inline void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
u8 offset, struct sk_buff *skb)
{
drvr->proto->hdrpush(drvr, ifidx, offset, skb);
}
static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
u8 *ifidx, struct sk_buff *skb)
{
......@@ -52,6 +47,11 @@ static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx,
{
return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
}
static inline int brcmf_proto_txdata(struct brcmf_pub *drvr, int ifidx,
u8 offset, struct sk_buff *skb)
{
return drvr->proto->txdata(drvr, ifidx, offset, skb);
}
#endif /* BRCMFMAC_PROTO_H */
......@@ -224,7 +224,7 @@ struct sdpcmd_regs {
};
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
struct chip_info **ci_ptr, u32 regs);
struct chip_info **ci_ptr);
void brcmf_sdio_chip_detach(struct chip_info **ci_ptr);
void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u32 drivestrength);
......
......@@ -1253,6 +1253,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
bus->ops = &brcmf_usb_bus_ops;
bus->chip = bus_pub->devid;
bus->chiprev = bus_pub->chiprev;
bus->proto_type = BRCMF_PROTO_BCDC;
/* Attach to the common driver interface */
ret = brcmf_attach(dev);
......
......@@ -322,12 +322,6 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
flush_workqueue(priv->workqueue);
/* User space software may expect getting rfkill changes
* even if interface is down, trans->down will leave the RF
* kill interrupt enabled
*/
iwl_trans_stop_hw(priv->trans, false);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
......
......@@ -1313,7 +1313,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
}
/* Reset chip to save power until we load uCode during "up". */
iwl_trans_stop_hw(priv->trans, false);
iwl_trans_stop_device(priv->trans);
priv->nvm_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg,
priv->eeprom_blob,
......@@ -1458,7 +1458,7 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
dev_kfree_skb(priv->beacon_skb);
iwl_trans_stop_hw(priv->trans, true);
iwl_trans_op_mode_leave(priv->trans);
ieee80211_free_hw(priv->hw);
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部