提交 2f6d7c1b 编写于 作者: D David S. Miller
...@@ -1293,7 +1293,9 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) ...@@ -1293,7 +1293,9 @@ static void ar9170_op_stop(struct ieee80211_hw *hw)
flush_workqueue(ar->hw->workqueue); flush_workqueue(ar->hw->workqueue);
cancel_delayed_work_sync(&ar->tx_janitor); cancel_delayed_work_sync(&ar->tx_janitor);
#ifdef CONFIG_AR9170_LEDS
cancel_delayed_work_sync(&ar->led_work); cancel_delayed_work_sync(&ar->led_work);
#endif
cancel_work_sync(&ar->filter_config_work); cancel_work_sync(&ar->filter_config_work);
cancel_work_sync(&ar->beacon_work); cancel_work_sync(&ar->beacon_work);
mutex_lock(&ar->mutex); mutex_lock(&ar->mutex);
......
...@@ -18,6 +18,6 @@ config ATH9K_DEBUG ...@@ -18,6 +18,6 @@ config ATH9K_DEBUG
Say Y, if you need ath9k to display debug messages. Say Y, if you need ath9k to display debug messages.
Pass the debug mask as a module parameter: Pass the debug mask as a module parameter:
modprobe ath9k debug=0x00002000 modprobe ath9k debug=0x00000200
Look in ath9k/core.h for possible debug masks Look in ath9k/debug.h for possible debug masks
...@@ -190,12 +190,9 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, ...@@ -190,12 +190,9 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
#define ATH_AGGR_MIN_QDEPTH 2 #define ATH_AGGR_MIN_QDEPTH 2
#define ATH_AMPDU_SUBFRAME_DEFAULT 32 #define ATH_AMPDU_SUBFRAME_DEFAULT 32
#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) #define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1)
#define ATH_AMPDU_LIMIT_DEFAULT ATH_AMPDU_LIMIT_MAX
#define IEEE80211_SEQ_SEQ_SHIFT 4 #define IEEE80211_SEQ_SEQ_SHIFT 4
#define IEEE80211_SEQ_MAX 4096 #define IEEE80211_SEQ_MAX 4096
#define IEEE80211_MIN_AMPDU_BUF 0x8
#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
#define IEEE80211_WEP_IVLEN 3 #define IEEE80211_WEP_IVLEN 3
#define IEEE80211_WEP_KIDLEN 1 #define IEEE80211_WEP_KIDLEN 1
#define IEEE80211_WEP_CRCLEN 4 #define IEEE80211_WEP_CRCLEN 4
...@@ -240,7 +237,6 @@ struct ath_txq { ...@@ -240,7 +237,6 @@ struct ath_txq {
spinlock_t axq_lock; spinlock_t axq_lock;
u32 axq_depth; u32 axq_depth;
u8 axq_aggr_depth; u8 axq_aggr_depth;
u32 axq_totalqueued;
bool stopped; bool stopped;
bool axq_tx_inprogress; bool axq_tx_inprogress;
struct ath_buf *axq_linkbuf; struct ath_buf *axq_linkbuf;
...@@ -365,9 +361,9 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -365,9 +361,9 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
void ath_tx_tasklet(struct ath_softc *sc); void ath_tx_tasklet(struct ath_softc *sc);
void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn); u16 tid, u16 *ssn);
int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
/********/ /********/
...@@ -576,6 +572,7 @@ struct ath_softc { ...@@ -576,6 +572,7 @@ struct ath_softc {
u32 keymax; u32 keymax;
DECLARE_BITMAP(keymap, ATH_KEYMAX); DECLARE_BITMAP(keymap, ATH_KEYMAX);
u8 splitmic; u8 splitmic;
bool ps_enabled;
unsigned long ps_usecount; unsigned long ps_usecount;
enum ath9k_int imask; enum ath9k_int imask;
enum ath9k_ht_extprotspacing ht_extprotspacing; enum ath9k_ht_extprotspacing ht_extprotspacing;
......
...@@ -116,7 +116,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, ...@@ -116,7 +116,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
"NF calibrated [ctl] [chain 1] is %d\n", nf); "NF calibrated [ctl] [chain 1] is %d\n", nf);
nfarray[1] = nf; nfarray[1] = nf;
if (!AR_SREV_9280(ah)) { if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
AR_PHY_CH2_MINCCA_PWR); AR_PHY_CH2_MINCCA_PWR);
if (nf & 0x100) if (nf & 0x100)
...@@ -154,7 +154,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, ...@@ -154,7 +154,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
"NF calibrated [ext] [chain 1] is %d\n", nf); "NF calibrated [ext] [chain 1] is %d\n", nf);
nfarray[4] = nf; nfarray[4] = nf;
if (!AR_SREV_9280(ah)) { if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
AR_PHY_CH2_EXT_MINCCA_PWR); AR_PHY_CH2_EXT_MINCCA_PWR);
if (nf & 0x100) if (nf & 0x100)
...@@ -613,7 +613,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) ...@@ -613,7 +613,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
if (AR_SREV_9285(ah)) if (AR_SREV_9285(ah))
chainmask = 0x9; chainmask = 0x9;
else if (AR_SREV_9280(ah)) else if (AR_SREV_9280(ah) || AR_SREV_9287(ah))
chainmask = 0x1B; chainmask = 0x1B;
else else
chainmask = 0x3F; chainmask = 0x3F;
...@@ -873,7 +873,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -873,7 +873,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
if (AR_SREV_9285_11_OR_LATER(ah)) if (AR_SREV_9285_11_OR_LATER(ah))
ath9k_hw_9285_pa_cal(ah); ath9k_hw_9285_pa_cal(ah);
if (OLC_FOR_AR9280_20_LATER) if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER)
ath9k_olc_temp_compensation(ah); ath9k_olc_temp_compensation(ah);
ath9k_hw_getnf(ah, chan); ath9k_hw_getnf(ah, chan);
ath9k_hw_loadnf(ah, ah->curchan); ath9k_hw_loadnf(ah, ah->curchan);
...@@ -929,8 +929,11 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) ...@@ -929,8 +929,11 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
return false; return false;
} else { } else {
if (AR_SREV_9280_10_OR_LATER(ah)) { if (AR_SREV_9280_10_OR_LATER(ah)) {
REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); if (!AR_SREV_9287_10_OR_LATER(ah))
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
AR_PHY_ADC_CTL_OFF_PWDADC);
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
AR_PHY_AGC_CONTROL_FLTR_CAL);
} }
/* Calibrate the AGC */ /* Calibrate the AGC */
...@@ -948,8 +951,11 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) ...@@ -948,8 +951,11 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
} }
if (AR_SREV_9280_10_OR_LATER(ah)) { if (AR_SREV_9280_10_OR_LATER(ah)) {
REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); if (!AR_SREV_9287_10_OR_LATER(ah))
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); REG_SET_BIT(ah, AR_PHY_ADC_CTL,
AR_PHY_ADC_CTL_OFF_PWDADC);
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
AR_PHY_AGC_CONTROL_FLTR_CAL);
} }
} }
......
...@@ -486,6 +486,83 @@ static const struct file_operations fops_wiphy = { ...@@ -486,6 +486,83 @@ static const struct file_operations fops_wiphy = {
.owner = THIS_MODULE .owner = THIS_MODULE
}; };
#define PR(str, elem) \
do { \
len += snprintf(buf + len, size - len, \
"%s%13u%11u%10u%10u\n", str, \
sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BE]].elem, \
sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BK]].elem, \
sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VI]].elem, \
sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VO]].elem); \
} while(0)
static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char *buf;
unsigned int len = 0, size = 2048;
ssize_t retval = 0;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return 0;
len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO");
PR("MPDUs Queued: ", queued);
PR("MPDUs Completed: ", completed);
PR("Aggregates: ", a_aggr);
PR("AMPDUs Queued: ", a_queued);
PR("AMPDUs Completed:", a_completed);
PR("AMPDUs Retried: ", a_retries);
PR("AMPDUs XRetried: ", a_xretries);
PR("FIFO Underrun: ", fifo_underrun);
PR("TXOP Exceeded: ", xtxop);
PR("TXTIMER Expiry: ", timer_exp);
PR("DESC CFG Error: ", desc_cfg_err);
PR("DATA Underrun: ", data_underrun);
PR("DELIM Underrun: ", delim_underrun);
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf)
{
struct ath_desc *ds = bf->bf_desc;
if (bf_isampdu(bf)) {
if (bf_isxretried(bf))
TX_STAT_INC(txq->axq_qnum, a_xretries);
else
TX_STAT_INC(txq->axq_qnum, a_completed);
} else {
TX_STAT_INC(txq->axq_qnum, completed);
}
if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO)
TX_STAT_INC(txq->axq_qnum, fifo_underrun);
if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP)
TX_STAT_INC(txq->axq_qnum, xtxop);
if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED)
TX_STAT_INC(txq->axq_qnum, timer_exp);
if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR)
TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN)
TX_STAT_INC(txq->axq_qnum, data_underrun);
if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN)
TX_STAT_INC(txq->axq_qnum, delim_underrun);
}
static const struct file_operations fops_xmit = {
.read = read_file_xmit,
.open = ath9k_debugfs_open,
.owner = THIS_MODULE
};
int ath9k_init_debug(struct ath_softc *sc) int ath9k_init_debug(struct ath_softc *sc)
{ {
...@@ -529,6 +606,13 @@ int ath9k_init_debug(struct ath_softc *sc) ...@@ -529,6 +606,13 @@ int ath9k_init_debug(struct ath_softc *sc)
if (!sc->debug.debugfs_wiphy) if (!sc->debug.debugfs_wiphy)
goto err; goto err;
sc->debug.debugfs_xmit = debugfs_create_file("xmit",
S_IRUSR,
sc->debug.debugfs_phy,
sc, &fops_xmit);
if (!sc->debug.debugfs_xmit)
goto err;
return 0; return 0;
err: err:
ath9k_exit_debug(sc); ath9k_exit_debug(sc);
...@@ -537,6 +621,7 @@ int ath9k_init_debug(struct ath_softc *sc) ...@@ -537,6 +621,7 @@ int ath9k_init_debug(struct ath_softc *sc)
void ath9k_exit_debug(struct ath_softc *sc) void ath9k_exit_debug(struct ath_softc *sc)
{ {
debugfs_remove(sc->debug.debugfs_xmit);
debugfs_remove(sc->debug.debugfs_wiphy); debugfs_remove(sc->debug.debugfs_wiphy);
debugfs_remove(sc->debug.debugfs_rcstat); debugfs_remove(sc->debug.debugfs_rcstat);
debugfs_remove(sc->debug.debugfs_interrupt); debugfs_remove(sc->debug.debugfs_interrupt);
......
...@@ -35,6 +35,15 @@ enum ATH_DEBUG { ...@@ -35,6 +35,15 @@ enum ATH_DEBUG {
#define DBG_DEFAULT (ATH_DBG_FATAL) #define DBG_DEFAULT (ATH_DBG_FATAL)
struct ath_txq;
struct ath_buf;
#ifdef CONFIG_ATH9K_DEBUG
#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
#else
#define TX_STAT_INC(q, c) do { } while (0)
#endif
#ifdef CONFIG_ATH9K_DEBUG #ifdef CONFIG_ATH9K_DEBUG
/** /**
...@@ -87,9 +96,45 @@ struct ath_rc_stats { ...@@ -87,9 +96,45 @@ struct ath_rc_stats {
u8 per; u8 per;
}; };
/**
* struct ath_tx_stats - Statistics about TX
* @queued: Total MPDUs (non-aggr) queued
* @completed: Total MPDUs (non-aggr) completed
* @a_aggr: Total no. of aggregates queued
* @a_queued: Total AMPDUs queued
* @a_completed: Total AMPDUs completed
* @a_retries: No. of AMPDUs retried (SW)
* @a_xretries: No. of AMPDUs dropped due to xretries
* @fifo_underrun: FIFO underrun occurrences
Valid only for:
- non-aggregate condition.
- first packet of aggregate.
* @xtxop: No. of frames filtered because of TXOP limit
* @timer_exp: Transmit timer expiry
* @desc_cfg_err: Descriptor configuration errors
* @data_urn: TX data underrun errors
* @delim_urn: TX delimiter underrun errors
*/
struct ath_tx_stats {
u32 queued;
u32 completed;
u32 a_aggr;
u32 a_queued;
u32 a_completed;
u32 a_retries;
u32 a_xretries;
u32 fifo_underrun;
u32 xtxop;
u32 timer_exp;
u32 desc_cfg_err;
u32 data_underrun;
u32 delim_underrun;
};
struct ath_stats { struct ath_stats {
struct ath_interrupt_stats istats; struct ath_interrupt_stats istats;
struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
}; };
struct ath9k_debug { struct ath9k_debug {
...@@ -100,6 +145,7 @@ struct ath9k_debug { ...@@ -100,6 +145,7 @@ struct ath9k_debug {
struct dentry *debugfs_interrupt; struct dentry *debugfs_interrupt;
struct dentry *debugfs_rcstat; struct dentry *debugfs_rcstat;
struct dentry *debugfs_wiphy; struct dentry *debugfs_wiphy;
struct dentry *debugfs_xmit;
struct ath_stats stats; struct ath_stats stats;
}; };
...@@ -110,6 +156,8 @@ int ath9k_debug_create_root(void); ...@@ -110,6 +156,8 @@ int ath9k_debug_create_root(void);
void ath9k_debug_remove_root(void); void ath9k_debug_remove_root(void);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf);
void ath_debug_stat_retries(struct ath_softc *sc, int rix, void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per); int xretries, int retries, u8 per);
...@@ -148,6 +196,12 @@ static inline void ath_debug_stat_rc(struct ath_softc *sc, ...@@ -148,6 +196,12 @@ static inline void ath_debug_stat_rc(struct ath_softc *sc,
{ {
} }
static inline void ath_debug_stat_tx(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_buf *bf)
{
}
static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix, static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per) int xretries, int retries, u8 per)
{ {
......
...@@ -100,6 +100,8 @@ ...@@ -100,6 +100,8 @@
#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) #define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_10_OR_LATER(ah) && \
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 #define AR_EEPROM_RFSILENT_GPIO_SEL_S 2
...@@ -176,6 +178,57 @@ ...@@ -176,6 +178,57 @@
#define AR9280_TX_GAIN_TABLE_SIZE 22 #define AR9280_TX_GAIN_TABLE_SIZE 22
#define AR9287_EEP_VER 0xE
#define AR9287_EEP_VER_MINOR_MASK 0xFFF
#define AR9287_EEP_MINOR_VER_1 0x1
#define AR9287_EEP_MINOR_VER_2 0x2
#define AR9287_EEP_MINOR_VER_3 0x3
#define AR9287_EEP_MINOR_VER AR9287_EEP_MINOR_VER_3
#define AR9287_EEP_MINOR_VER_b AR9287_EEP_MINOR_VER
#define AR9287_EEP_NO_BACK_VER AR9287_EEP_MINOR_VER_1
#define AR9287_EEP_START_LOC 128
#define AR9287_NUM_2G_CAL_PIERS 3
#define AR9287_NUM_2G_CCK_TARGET_POWERS 3
#define AR9287_NUM_2G_20_TARGET_POWERS 3
#define AR9287_NUM_2G_40_TARGET_POWERS 3
#define AR9287_NUM_CTLS 12
#define AR9287_NUM_BAND_EDGES 4
#define AR9287_NUM_PD_GAINS 4
#define AR9287_PD_GAINS_IN_MASK 4
#define AR9287_PD_GAIN_ICEPTS 1
#define AR9287_EEPROM_MODAL_SPURS 5
#define AR9287_MAX_RATE_POWER 63
#define AR9287_NUM_PDADC_VALUES 128
#define AR9287_NUM_RATES 16
#define AR9287_BCHAN_UNUSED 0xFF
#define AR9287_MAX_PWR_RANGE_IN_HALF_DB 64
#define AR9287_OPFLAGS_11A 0x01
#define AR9287_OPFLAGS_11G 0x02
#define AR9287_OPFLAGS_2G_HT40 0x08
#define AR9287_OPFLAGS_2G_HT20 0x20
#define AR9287_OPFLAGS_5G_HT40 0x04
#define AR9287_OPFLAGS_5G_HT20 0x10
#define AR9287_EEPMISC_BIG_ENDIAN 0x01
#define AR9287_EEPMISC_WOW 0x02
#define AR9287_MAX_CHAINS 2
#define AR9287_ANT_16S 32
#define AR9287_custdatasize 20
#define AR9287_NUM_ANT_CHAIN_FIELDS 6
#define AR9287_NUM_ANT_COMMON_FIELDS 4
#define AR9287_SIZE_ANT_CHAIN_FIELD 2
#define AR9287_SIZE_ANT_COMMON_FIELD 4
#define AR9287_ANT_CHAIN_MASK 0x3
#define AR9287_ANT_COMMON_MASK 0xf
#define AR9287_CHAIN_0_IDX 0
#define AR9287_CHAIN_1_IDX 1
#define AR9287_DATA_SZ 32
#define AR9287_PWR_TABLE_OFFSET_DB -5
#define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1)
enum eeprom_param { enum eeprom_param {
EEP_NFTHRESH_5, EEP_NFTHRESH_5,
EEP_NFTHRESH_2, EEP_NFTHRESH_2,
...@@ -199,7 +252,11 @@ enum eeprom_param { ...@@ -199,7 +252,11 @@ enum eeprom_param {
EEP_OL_PWRCTRL, EEP_OL_PWRCTRL,
EEP_RC_CHAIN_MASK, EEP_RC_CHAIN_MASK,
EEP_DAC_HPWR_5G, EEP_DAC_HPWR_5G,
EEP_FRAC_N_5G EEP_FRAC_N_5G,
EEP_DEV_TYPE,
EEP_TEMPSENSE_SLOPE,
EEP_TEMPSENSE_SLOPE_PAL_ON,
EEP_PWR_TABLE_OFFSET
}; };
enum ar5416_rates { enum ar5416_rates {
...@@ -368,6 +425,65 @@ struct modal_eep_4k_header { ...@@ -368,6 +425,65 @@ struct modal_eep_4k_header {
struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
} __packed; } __packed;
struct base_eep_ar9287_header {
u16 length;
u16 checksum;
u16 version;
u8 opCapFlags;
u8 eepMisc;
u16 regDmn[2];
u8 macAddr[6];
u8 rxMask;
u8 txMask;
u16 rfSilent;
u16 blueToothOptions;
u16 deviceCap;
u32 binBuildNumber;
u8 deviceType;
u8 openLoopPwrCntl;
int8_t pwrTableOffset;
int8_t tempSensSlope;
int8_t tempSensSlopePalOn;
u8 futureBase[29];
} __packed;
struct modal_eep_ar9287_header {
u32 antCtrlChain[AR9287_MAX_CHAINS];
u32 antCtrlCommon;
int8_t antennaGainCh[AR9287_MAX_CHAINS];
u8 switchSettling;
u8 txRxAttenCh[AR9287_MAX_CHAINS];
u8 rxTxMarginCh[AR9287_MAX_CHAINS];
int8_t adcDesiredSize;
u8 txEndToXpaOff;
u8 txEndToRxOn;
u8 txFrameToXpaOn;
u8 thresh62;
int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS];
u8 xpdGain;
u8 xpd;
int8_t iqCalICh[AR9287_MAX_CHAINS];
int8_t iqCalQCh[AR9287_MAX_CHAINS];
u8 pdGainOverlap;
u8 xpaBiasLvl;
u8 txFrameToDataStart;
u8 txFrameToPaOn;
u8 ht40PowerIncForPdadc;
u8 bswAtten[AR9287_MAX_CHAINS];
u8 bswMargin[AR9287_MAX_CHAINS];
u8 swSettleHt40;
u8 version;
u8 db1;
u8 db2;
u8 ob_cck;
u8 ob_psk;
u8 ob_qam;
u8 ob_pal_off;
u8 futureModal[30];
struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS];
} __packed;
struct cal_data_per_freq { struct cal_data_per_freq {
u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
...@@ -402,6 +518,29 @@ struct cal_ctl_edges { ...@@ -402,6 +518,29 @@ struct cal_ctl_edges {
} __packed; } __packed;
#endif #endif
struct cal_data_op_loop_ar9287 {
u8 pwrPdg[2][5];
u8 vpdPdg[2][5];
u8 pcdac[2][5];
u8 empty[2][5];
} __packed;
struct cal_data_per_freq_ar9287 {
u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
} __packed;
union cal_data_per_freq_ar9287_u {
struct cal_data_op_loop_ar9287 calDataOpen;
struct cal_data_per_freq_ar9287 calDataClose;
} __packed;
struct cal_ctl_data_ar9287 {
struct cal_ctl_edges
ctlEdges[AR9287_MAX_CHAINS][AR9287_NUM_BAND_EDGES];
} __packed;
struct cal_ctl_data { struct cal_ctl_data {
struct cal_ctl_edges struct cal_ctl_edges
ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
...@@ -461,6 +600,27 @@ struct ar5416_eeprom_4k { ...@@ -461,6 +600,27 @@ struct ar5416_eeprom_4k {
u8 padding; u8 padding;
} __packed; } __packed;
struct ar9287_eeprom_t {
struct base_eep_ar9287_header baseEepHeader;
u8 custData[AR9287_DATA_SZ];
struct modal_eep_ar9287_header modalHeader;
u8 calFreqPier2G[AR9287_NUM_2G_CAL_PIERS];
union cal_data_per_freq_ar9287_u
calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS];
struct cal_target_power_leg
calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS];
struct cal_target_power_leg
calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS];
struct cal_target_power_ht
calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS];
struct cal_target_power_ht
calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS];
u8 ctlIndex[AR9287_NUM_CTLS];
struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS];
u8 padding;
} __packed;
enum reg_ext_bitmap { enum reg_ext_bitmap {
REG_EXT_JAPAN_MIDBAND = 1, REG_EXT_JAPAN_MIDBAND = 1,
REG_EXT_FCC_DFS_HT40 = 2, REG_EXT_FCC_DFS_HT40 = 2,
...@@ -480,6 +640,7 @@ struct ath9k_country_entry { ...@@ -480,6 +640,7 @@ struct ath9k_country_entry {
enum ath9k_eep_map { enum ath9k_eep_map {
EEP_MAP_DEFAULT = 0x0, EEP_MAP_DEFAULT = 0x0,
EEP_MAP_4KBITS, EEP_MAP_4KBITS,
EEP_MAP_AR9287,
EEP_MAP_MAX EEP_MAP_MAX
}; };
......
...@@ -380,6 +380,9 @@ static const char *ath9k_hw_devname(u16 devid) ...@@ -380,6 +380,9 @@ static const char *ath9k_hw_devname(u16 devid)
return "Atheros 9280"; return "Atheros 9280";
case AR9285_DEVID_PCIE: case AR9285_DEVID_PCIE:
return "Atheros 9285"; return "Atheros 9285";
case AR5416_DEVID_AR9287_PCI:
case AR5416_DEVID_AR9287_PCIE:
return "Atheros 9287";
} }
return NULL; return NULL;
...@@ -475,6 +478,8 @@ static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc, ...@@ -475,6 +478,8 @@ static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc,
ah->gbeacon_rate = 0; ah->gbeacon_rate = 0;
ah->power_mode = ATH9K_PM_UNDEFINED;
return ah; return ah;
} }
...@@ -660,7 +665,8 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ...@@ -660,7 +665,8 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) && if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) &&
(ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) && (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) &&
(ah->hw_version.macVersion != AR_SREV_VERSION_9160) && (ah->hw_version.macVersion != AR_SREV_VERSION_9160) &&
(!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) { (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) &&
(!AR_SREV_9285(ah)) && (!AR_SREV_9287(ah))) {
DPRINTF(sc, ATH_DBG_FATAL, DPRINTF(sc, ATH_DBG_FATAL,
"Mac Chip Rev 0x%02x.%x is not supported by " "Mac Chip Rev 0x%02x.%x is not supported by "
"this driver\n", ah->hw_version.macVersion, "this driver\n", ah->hw_version.macVersion,
...@@ -700,8 +706,37 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ...@@ -700,8 +706,37 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
ah->ani_function = ATH9K_ANI_ALL; ah->ani_function = ATH9K_ANI_ALL;
if (AR_SREV_9280_10_OR_LATER(ah)) if (AR_SREV_9280_10_OR_LATER(ah))
ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
ARRAY_SIZE(ar9287Common_9287_1_1), 2);
if (ah->config.pcie_clock_req)
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9287PciePhy_clkreq_off_L1_9287_1_1,
ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2);
else
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9287PciePhy_clkreq_always_on_L1_9287_1_1,
ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1),
2);
} else if (AR_SREV_9287_10_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0,
ARRAY_SIZE(ar9287Modes_9287_1_0), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0,
ARRAY_SIZE(ar9287Common_9287_1_0), 2);
if (ah->config.pcie_clock_req)
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9287PciePhy_clkreq_off_L1_9287_1_0,
ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2);
else
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9287PciePhy_clkreq_always_on_L1_9287_1_0,
ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0),
2);
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
if (AR_SREV_9285_12_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
ARRAY_SIZE(ar9285Modes_9285_1_2), 6); ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
...@@ -842,7 +877,28 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ...@@ -842,7 +877,28 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
if (ecode != 0) if (ecode != 0)
goto bad; goto bad;
if (AR_SREV_9285_12_OR_LATER(ah)) { if (AR_SREV_9287_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9287Modes_rx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
else if (AR_SREV_9287_10(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9287Modes_rx_gain_9287_1_0,
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6);
else if (AR_SREV_9280_20(ah))
ath9k_hw_init_rxgain_ini(ah);
if (AR_SREV_9287_11(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9287Modes_tx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
} else if (AR_SREV_9287_10(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9287Modes_tx_gain_9287_1_0,
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6);
} else if (AR_SREV_9280_20(ah)) {
ath9k_hw_init_txgain_ini(ah);
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
/* txgain table */ /* txgain table */
...@@ -858,14 +914,6 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ...@@ -858,14 +914,6 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
} }
/* rxgain table */
if (AR_SREV_9280_20(ah))
ath9k_hw_init_rxgain_ini(ah);
/* txgain table */
if (AR_SREV_9280_20(ah))
ath9k_hw_init_txgain_ini(ah);
ath9k_hw_fill_cap_info(ah); ath9k_hw_fill_cap_info(ah);
if ((ah->hw_version.devid == AR9280_DEVID_PCI) && if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
...@@ -1165,6 +1213,8 @@ struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error) ...@@ -1165,6 +1213,8 @@ struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error)
case AR9280_DEVID_PCI: case AR9280_DEVID_PCI:
case AR9280_DEVID_PCIE: case AR9280_DEVID_PCIE:
case AR9285_DEVID_PCIE: case AR9285_DEVID_PCIE:
case AR5416_DEVID_AR9287_PCI:
case AR5416_DEVID_AR9287_PCIE:
ah = ath9k_hw_do_attach(devid, sc, error); ah = ath9k_hw_do_attach(devid, sc, error);
break; break;
default: default:
...@@ -1341,10 +1391,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, ...@@ -1341,10 +1391,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
DO_DELAY(regWrites); DO_DELAY(regWrites);
} }
if (AR_SREV_9280(ah)) if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah))
REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah)) if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) ||
AR_SREV_9287_10_OR_LATER(ah))
REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
for (i = 0; i < ah->iniCommon.ia_rows; i++) { for (i = 0; i < ah->iniCommon.ia_rows; i++) {
...@@ -2254,6 +2305,16 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -2254,6 +2305,16 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (AR_SREV_9280_10_OR_LATER(ah)) if (AR_SREV_9280_10_OR_LATER(ah))
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
if (AR_SREV_9287_10_OR_LATER(ah)) {
/* Enable ASYNC FIFO */
REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
}
r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width); r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width);
if (r) if (r)
return r; return r;
...@@ -2330,6 +2391,27 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -2330,6 +2391,27 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_init_user_settings(ah); ath9k_hw_init_user_settings(ah);
if (AR_SREV_9287_10_OR_LATER(ah)) {
REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
}
if (AR_SREV_9287_10_OR_LATER(ah)) {
REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
}
REG_WRITE(ah, AR_STA_ID1, REG_WRITE(ah, AR_STA_ID1,
REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
...@@ -2739,6 +2821,9 @@ static bool ath9k_hw_setpower_nolock(struct ath_hw *ah, ...@@ -2739,6 +2821,9 @@ static bool ath9k_hw_setpower_nolock(struct ath_hw *ah,
"UNDEFINED" "UNDEFINED"
}; };
if (ah->power_mode == mode)
return status;
DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n", DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n",
modes[ah->power_mode], modes[mode]); modes[ah->power_mode], modes[mode]);
...@@ -2783,10 +2868,7 @@ void ath9k_ps_wakeup(struct ath_softc *sc) ...@@ -2783,10 +2868,7 @@ void ath9k_ps_wakeup(struct ath_softc *sc)
if (++sc->ps_usecount != 1) if (++sc->ps_usecount != 1)
goto unlock; goto unlock;
if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_AWAKE);
sc->sc_ah->restore_mode = sc->sc_ah->power_mode;
ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_AWAKE);
}
unlock: unlock:
spin_unlock_irqrestore(&sc->sc_pm_lock, flags); spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
...@@ -2800,13 +2882,12 @@ void ath9k_ps_restore(struct ath_softc *sc) ...@@ -2800,13 +2882,12 @@ void ath9k_ps_restore(struct ath_softc *sc)
if (--sc->ps_usecount != 0) if (--sc->ps_usecount != 0)
goto unlock; goto unlock;
if ((sc->hw->conf.flags & IEEE80211_CONF_PS) && if (sc->ps_enabled &&
!(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
SC_OP_WAIT_FOR_CAB | SC_OP_WAIT_FOR_CAB |
SC_OP_WAIT_FOR_PSPOLL_DATA | SC_OP_WAIT_FOR_PSPOLL_DATA |
SC_OP_WAIT_FOR_TX_ACK))) SC_OP_WAIT_FOR_TX_ACK)))
ath9k_hw_setpower_nolock(sc->sc_ah, ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
sc->sc_ah->restore_mode);
unlock: unlock:
spin_unlock_irqrestore(&sc->sc_pm_lock, flags); spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
...@@ -3644,7 +3725,9 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) ...@@ -3644,7 +3725,9 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
if (gpio >= ah->caps.num_gpio_pins) if (gpio >= ah->caps.num_gpio_pins)
return 0xffffffff; return 0xffffffff;
if (AR_SREV_9285_10_OR_LATER(ah)) if (AR_SREV_9287_10_OR_LATER(ah))
return MS_REG_READ(AR9287, gpio) != 0;
else if (AR_SREV_9285_10_OR_LATER(ah))
return MS_REG_READ(AR9285, gpio) != 0; return MS_REG_READ(AR9285, gpio) != 0;
else if (AR_SREV_9280_10_OR_LATER(ah)) else if (AR_SREV_9280_10_OR_LATER(ah))
return MS_REG_READ(AR928X, gpio) != 0; return MS_REG_READ(AR928X, gpio) != 0;
......
...@@ -42,6 +42,9 @@ ...@@ -42,6 +42,9 @@
#define AR_SUBVENDOR_ID_NEW_A 0x7065 #define AR_SUBVENDOR_ID_NEW_A 0x7065
#define AR5416_MAGIC 0x19641014 #define AR5416_MAGIC 0x19641014
#define AR5416_DEVID_AR9287_PCI 0x002D
#define AR5416_DEVID_AR9287_PCIE 0x002E
/* Register read/write primitives */ /* Register read/write primitives */
#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) #define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val))
#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) #define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg))
...@@ -400,6 +403,7 @@ struct ath_hw { ...@@ -400,6 +403,7 @@ struct ath_hw {
union { union {
struct ar5416_eeprom_def def; struct ar5416_eeprom_def def;
struct ar5416_eeprom_4k map4k; struct ar5416_eeprom_4k map4k;
struct ar9287_eeprom_t map9287;
} eeprom; } eeprom;
const struct eeprom_ops *eep_ops; const struct eeprom_ops *eep_ops;
enum ath9k_eep_map eep_map; enum ath9k_eep_map eep_map;
...@@ -417,7 +421,6 @@ struct ath_hw { ...@@ -417,7 +421,6 @@ struct ath_hw {
enum nl80211_iftype opmode; enum nl80211_iftype opmode;
enum ath9k_power_mode power_mode; enum ath9k_power_mode power_mode;
enum ath9k_power_mode restore_mode;
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
struct ar5416Stats stats; struct ar5416Stats stats;
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
#include <linux/nl80211.h> #include <linux/nl80211.h>
#include "ath9k.h" #include "ath9k.h"
#define ATH_PCI_VERSION "0.1"
static char *dev_info = "ath9k"; static char *dev_info = "ath9k";
MODULE_AUTHOR("Atheros Communications"); MODULE_AUTHOR("Atheros Communications");
...@@ -462,7 +460,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) ...@@ -462,7 +460,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
if (sc->sc_flags & SC_OP_TXAGGR) { if (sc->sc_flags & SC_OP_TXAGGR) {
ath_tx_node_init(sc, an); ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor); sta->ht_cap.ampdu_factor);
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
an->last_rssi = ATH_RSSI_DUMMY_MARKER; an->last_rssi = ATH_RSSI_DUMMY_MARKER;
...@@ -499,8 +497,7 @@ static void ath9k_tasklet(unsigned long data) ...@@ -499,8 +497,7 @@ static void ath9k_tasklet(unsigned long data)
if (status & ATH9K_INT_TX) if (status & ATH9K_INT_TX)
ath_tx_tasklet(sc); ath_tx_tasklet(sc);
if ((status & ATH9K_INT_TSFOOR) && if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) {
(sc->hw->conf.flags & IEEE80211_CONF_PS)) {
/* /*
* TSF sync does not look correct; remain awake to sync with * TSF sync does not look correct; remain awake to sync with
* the next Beacon. * the next Beacon.
...@@ -888,8 +885,6 @@ static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) ...@@ -888,8 +885,6 @@ static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
static void setup_ht_cap(struct ath_softc *sc, static void setup_ht_cap(struct ath_softc *sc,
struct ieee80211_sta_ht_cap *ht_info) struct ieee80211_sta_ht_cap *ht_info)
{ {
#define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
u8 tx_streams, rx_streams; u8 tx_streams, rx_streams;
ht_info->ht_supported = true; ht_info->ht_supported = true;
...@@ -898,8 +893,8 @@ static void setup_ht_cap(struct ath_softc *sc, ...@@ -898,8 +893,8 @@ static void setup_ht_cap(struct ath_softc *sc,
IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_DSSSCCK40; IEEE80211_HT_CAP_DSSSCCK40;
ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536; ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8; ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
/* set up supported mcs set */ /* set up supported mcs set */
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
...@@ -2003,7 +1998,7 @@ static int ath9k_tx(struct ieee80211_hw *hw, ...@@ -2003,7 +1998,7 @@ static int ath9k_tx(struct ieee80211_hw *hw,
goto exit; goto exit;
} }
if (sc->hw->conf.flags & IEEE80211_CONF_PS) { if (sc->ps_enabled) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
/* /*
* mac80211 does not set PM field for normal data frames, so we * mac80211 does not set PM field for normal data frames, so we
...@@ -2291,8 +2286,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ...@@ -2291,8 +2286,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
} }
ath9k_hw_setrxabort(sc->sc_ah, 1); ath9k_hw_setrxabort(sc->sc_ah, 1);
} }
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); sc->ps_enabled = true;
} else { } else {
sc->ps_enabled = false;
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
if (!(ah->caps.hw_caps & if (!(ah->caps.hw_caps &
ATH9K_HW_CAP_AUTOSLEEP)) { ATH9K_HW_CAP_AUTOSLEEP)) {
...@@ -2671,19 +2667,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, ...@@ -2671,19 +2667,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_RX_STOP: case IEEE80211_AMPDU_RX_STOP:
break; break;
case IEEE80211_AMPDU_TX_START: case IEEE80211_AMPDU_TX_START:
ret = ath_tx_aggr_start(sc, sta, tid, ssn); ath_tx_aggr_start(sc, sta, tid, ssn);
if (ret < 0) ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to start TX aggregation\n");
else
ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break; break;
case IEEE80211_AMPDU_TX_STOP: case IEEE80211_AMPDU_TX_STOP:
ret = ath_tx_aggr_stop(sc, sta, tid); ath_tx_aggr_stop(sc, sta, tid);
if (ret < 0)
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to stop TX aggregation\n");
ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break; break;
case IEEE80211_AMPDU_TX_OPERATIONAL: case IEEE80211_AMPDU_TX_OPERATIONAL:
...@@ -2761,7 +2749,8 @@ static struct { ...@@ -2761,7 +2749,8 @@ static struct {
{ AR_SREV_VERSION_9100, "9100" }, { AR_SREV_VERSION_9100, "9100" },
{ AR_SREV_VERSION_9160, "9160" }, { AR_SREV_VERSION_9160, "9160" },
{ AR_SREV_VERSION_9280, "9280" }, { AR_SREV_VERSION_9280, "9280" },
{ AR_SREV_VERSION_9285, "9285" } { AR_SREV_VERSION_9285, "9285" },
{ AR_SREV_VERSION_9287, "9287" }
}; };
static struct { static struct {
......
...@@ -25,6 +25,8 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = { ...@@ -25,6 +25,8 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = {
{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
{ 0 } { 0 }
}; };
......
...@@ -375,6 +375,7 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, ...@@ -375,6 +375,7 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
#define AR_PHY_CHAN_INFO_GAIN 0x9CFC #define AR_PHY_CHAN_INFO_GAIN 0x9CFC
#define AR_PHY_MODE 0xA200 #define AR_PHY_MODE 0xA200
#define AR_PHY_MODE_ASYNCFIFO 0x80
#define AR_PHY_MODE_AR2133 0x08 #define AR_PHY_MODE_AR2133 0x08
#define AR_PHY_MODE_AR5111 0x00 #define AR_PHY_MODE_AR5111 0x00
#define AR_PHY_MODE_AR5112 0x08 #define AR_PHY_MODE_AR5112 0x08
......
...@@ -59,6 +59,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, ...@@ -59,6 +59,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid, struct ath_atx_tid *tid,
struct list_head *bf_head); struct list_head *bf_head);
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq,
struct list_head *bf_q, struct list_head *bf_q,
int txok, int sendbar); int txok, int sendbar);
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
...@@ -212,7 +213,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, ...@@ -212,7 +213,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_update_baw(sc, tid, bf->bf_seqno); ath_tx_update_baw(sc, tid, bf->bf_seqno);
spin_unlock(&txq->axq_lock); spin_unlock(&txq->axq_lock);
ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
spin_lock(&txq->axq_lock); spin_lock(&txq->axq_lock);
} }
...@@ -220,13 +221,15 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, ...@@ -220,13 +221,15 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
tid->baw_tail = tid->baw_head; tid->baw_tail = tid->baw_head;
} }
static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf) static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
bf->bf_state.bf_type |= BUF_RETRY; bf->bf_state.bf_type |= BUF_RETRY;
bf->bf_retries++; bf->bf_retries++;
TX_STAT_INC(txq->axq_qnum, a_retries);
skb = bf->bf_mpdu; skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
...@@ -328,7 +331,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ...@@ -328,7 +331,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (!(tid->state & AGGR_CLEANUP) && if (!(tid->state & AGGR_CLEANUP) &&
ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
if (bf->bf_retries < ATH_MAX_SW_RETRIES) { if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
ath_tx_set_retry(sc, bf); ath_tx_set_retry(sc, txq, bf);
txpending = 1; txpending = 1;
} else { } else {
bf->bf_state.bf_type |= BUF_XRETRY; bf->bf_state.bf_type |= BUF_XRETRY;
...@@ -375,7 +378,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ...@@ -375,7 +378,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_rc_status(bf, ds, nbad, txok, false); ath_tx_rc_status(bf, ds, nbad, txok, false);
} }
ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); ath_tx_complete_buf(sc, bf, txq, &bf_head, !txfail, sendbar);
} else { } else {
/* retry the un-acked ones */ /* retry the un-acked ones */
if (bf->bf_next == NULL && bf_last->bf_stale) { if (bf->bf_next == NULL && bf_last->bf_stale) {
...@@ -395,8 +398,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ...@@ -395,8 +398,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_state.bf_type |= BUF_XRETRY; bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(bf, ds, nbad, ath_tx_rc_status(bf, ds, nbad,
0, false); 0, false);
ath_tx_complete_buf(sc, bf, &bf_head, ath_tx_complete_buf(sc, bf, txq,
0, 0); &bf_head, 0, 0);
break; break;
} }
...@@ -455,7 +458,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, ...@@ -455,7 +458,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ieee80211_tx_rate *rates; struct ieee80211_tx_rate *rates;
struct ath_tx_info_priv *tx_info_priv; struct ath_tx_info_priv *tx_info_priv;
u32 max_4ms_framelen, frmlen; u32 max_4ms_framelen, frmlen;
u16 aggr_limit, legacy = 0, maxampdu; u16 aggr_limit, legacy = 0;
int i; int i;
skb = bf->bf_mpdu; skb = bf->bf_mpdu;
...@@ -490,16 +493,15 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, ...@@ -490,16 +493,15 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
return 0; return 0;
aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_DEFAULT); aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_MAX);
/* /*
* h/w can accept aggregates upto 16 bit lengths (65535). * h/w can accept aggregates upto 16 bit lengths (65535).
* The IE, however can hold upto 65536, which shows up here * The IE, however can hold upto 65536, which shows up here
* as zero. Ignore 65536 since we are constrained by hw. * as zero. Ignore 65536 since we are constrained by hw.
*/ */
maxampdu = tid->an->maxampdu; if (tid->an->maxampdu)
if (maxampdu) aggr_limit = min(aggr_limit, tid->an->maxampdu);
aggr_limit = min(aggr_limit, maxampdu);
return aggr_limit; return aggr_limit;
} }
...@@ -507,7 +509,6 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, ...@@ -507,7 +509,6 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
/* /*
* Returns the number of delimiters to be added to * Returns the number of delimiters to be added to
* meet the minimum required mpdudensity. * meet the minimum required mpdudensity.
* caller should make sure that the rate is HT rate .
*/ */
static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
struct ath_buf *bf, u16 frmlen) struct ath_buf *bf, u16 frmlen)
...@@ -515,7 +516,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, ...@@ -515,7 +516,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
const struct ath_rate_table *rt = sc->cur_rate_table; const struct ath_rate_table *rt = sc->cur_rate_table;
struct sk_buff *skb = bf->bf_mpdu; struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
u32 nsymbits, nsymbols, mpdudensity; u32 nsymbits, nsymbols;
u16 minlen; u16 minlen;
u8 rc, flags, rix; u8 rc, flags, rix;
int width, half_gi, ndelim, mindelim; int width, half_gi, ndelim, mindelim;
...@@ -537,14 +538,12 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, ...@@ -537,14 +538,12 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
* on highest rate in rate series (i.e. first rate) to determine * on highest rate in rate series (i.e. first rate) to determine
* required minimum length for subframe. Take into account * required minimum length for subframe. Take into account
* whether high rate is 20 or 40Mhz and half or full GI. * whether high rate is 20 or 40Mhz and half or full GI.
*/ *
mpdudensity = tid->an->mpdudensity;
/*
* If there is no mpdu density restriction, no further calculation * If there is no mpdu density restriction, no further calculation
* is needed. * is needed.
*/ */
if (mpdudensity == 0)
if (tid->an->mpdudensity == 0)
return ndelim; return ndelim;
rix = tx_info->control.rates[0].idx; rix = tx_info->control.rates[0].idx;
...@@ -554,9 +553,9 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, ...@@ -554,9 +553,9 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0; half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
if (half_gi) if (half_gi)
nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity); nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(tid->an->mpdudensity);
else else
nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity); nsymbols = NUM_SYMBOLS_PER_USEC(tid->an->mpdudensity);
if (nsymbols == 0) if (nsymbols == 0)
nsymbols = 1; nsymbols = 1;
...@@ -573,6 +572,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, ...@@ -573,6 +572,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
} }
static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_atx_tid *tid, struct ath_atx_tid *tid,
struct list_head *bf_q) struct list_head *bf_q)
{ {
...@@ -637,6 +637,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, ...@@ -637,6 +637,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
bf_prev->bf_desc->ds_link = bf->bf_daddr; bf_prev->bf_desc->ds_link = bf->bf_daddr;
} }
bf_prev = bf; bf_prev = bf;
} while (!list_empty(&tid->buf_q)); } while (!list_empty(&tid->buf_q));
bf_first->bf_al = al; bf_first->bf_al = al;
...@@ -659,7 +660,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, ...@@ -659,7 +660,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
INIT_LIST_HEAD(&bf_q); INIT_LIST_HEAD(&bf_q);
status = ath_tx_form_aggr(sc, tid, &bf_q); status = ath_tx_form_aggr(sc, txq, tid, &bf_q);
/* /*
* no frames picked up to be aggregated; * no frames picked up to be aggregated;
...@@ -690,30 +691,26 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, ...@@ -690,30 +691,26 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
txq->axq_aggr_depth++; txq->axq_aggr_depth++;
ath_tx_txqaddbuf(sc, txq, &bf_q); ath_tx_txqaddbuf(sc, txq, &bf_q);
TX_STAT_INC(txq->axq_qnum, a_aggr);
} while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
status != ATH_AGGR_BAW_CLOSED); status != ATH_AGGR_BAW_CLOSED);
} }
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn) u16 tid, u16 *ssn)
{ {
struct ath_atx_tid *txtid; struct ath_atx_tid *txtid;
struct ath_node *an; struct ath_node *an;
an = (struct ath_node *)sta->drv_priv; an = (struct ath_node *)sta->drv_priv;
txtid = ATH_AN_2_TID(an, tid);
if (sc->sc_flags & SC_OP_TXAGGR) { txtid->state |= AGGR_ADDBA_PROGRESS;
txtid = ATH_AN_2_TID(an, tid); ath_tx_pause_tid(sc, txtid);
txtid->state |= AGGR_ADDBA_PROGRESS; *ssn = txtid->seq_start;
ath_tx_pause_tid(sc, txtid);
*ssn = txtid->seq_start;
}
return 0;
} }
int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
{ {
struct ath_node *an = (struct ath_node *)sta->drv_priv; struct ath_node *an = (struct ath_node *)sta->drv_priv;
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
...@@ -723,11 +720,11 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) ...@@ -723,11 +720,11 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
INIT_LIST_HEAD(&bf_head); INIT_LIST_HEAD(&bf_head);
if (txtid->state & AGGR_CLEANUP) if (txtid->state & AGGR_CLEANUP)
return 0; return;
if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
txtid->state &= ~AGGR_ADDBA_PROGRESS; txtid->state &= ~AGGR_ADDBA_PROGRESS;
return 0; return;
} }
ath_tx_pause_tid(sc, txtid); ath_tx_pause_tid(sc, txtid);
...@@ -746,7 +743,7 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) ...@@ -746,7 +743,7 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
} }
list_move_tail(&bf->list, &bf_head); list_move_tail(&bf->list, &bf_head);
ath_tx_update_baw(sc, txtid, bf->bf_seqno); ath_tx_update_baw(sc, txtid, bf->bf_seqno);
ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
} }
spin_unlock_bh(&txq->axq_lock); spin_unlock_bh(&txq->axq_lock);
...@@ -756,8 +753,6 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) ...@@ -756,8 +753,6 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
txtid->state &= ~AGGR_ADDBA_COMPLETE; txtid->state &= ~AGGR_ADDBA_COMPLETE;
ath_tx_flush_tid(sc, txtid); ath_tx_flush_tid(sc, txtid);
} }
return 0;
} }
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
...@@ -870,7 +865,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) ...@@ -870,7 +865,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
spin_lock_init(&txq->axq_lock); spin_lock_init(&txq->axq_lock);
txq->axq_depth = 0; txq->axq_depth = 0;
txq->axq_aggr_depth = 0; txq->axq_aggr_depth = 0;
txq->axq_totalqueued = 0;
txq->axq_linkbuf = NULL; txq->axq_linkbuf = NULL;
txq->axq_tx_inprogress = false; txq->axq_tx_inprogress = false;
sc->tx.txqsetup |= 1<<qnum; sc->tx.txqsetup |= 1<<qnum;
...@@ -1036,7 +1030,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) ...@@ -1036,7 +1030,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
if (bf_isampdu(bf)) if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0); ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0);
else else
ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
} }
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
...@@ -1187,7 +1181,6 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, ...@@ -1187,7 +1181,6 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
list_splice_tail_init(head, &txq->axq_q); list_splice_tail_init(head, &txq->axq_q);
txq->axq_depth++; txq->axq_depth++;
txq->axq_totalqueued++;
txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
DPRINTF(sc, ATH_DBG_QUEUE, DPRINTF(sc, ATH_DBG_QUEUE,
...@@ -1235,6 +1228,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, ...@@ -1235,6 +1228,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
bf = list_first_entry(bf_head, struct ath_buf, list); bf = list_first_entry(bf_head, struct ath_buf, list);
bf->bf_state.bf_type |= BUF_AMPDU; bf->bf_state.bf_type |= BUF_AMPDU;
TX_STAT_INC(txctl->txq->axq_qnum, a_queued);
/* /*
* Do not queue to h/w when any of the following conditions is true: * Do not queue to h/w when any of the following conditions is true:
...@@ -1281,6 +1275,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, ...@@ -1281,6 +1275,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_lastbf = bf; bf->bf_lastbf = bf;
ath_buf_set_rate(sc, bf); ath_buf_set_rate(sc, bf);
ath_tx_txqaddbuf(sc, txq, bf_head); ath_tx_txqaddbuf(sc, txq, bf_head);
TX_STAT_INC(txq->axq_qnum, queued);
} }
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
...@@ -1294,6 +1289,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, ...@@ -1294,6 +1289,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_nframes = 1; bf->bf_nframes = 1;
ath_buf_set_rate(sc, bf); ath_buf_set_rate(sc, bf);
ath_tx_txqaddbuf(sc, txq, bf_head); ath_tx_txqaddbuf(sc, txq, bf_head);
TX_STAT_INC(txq->axq_qnum, queued);
} }
static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
...@@ -1819,6 +1815,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, ...@@ -1819,6 +1815,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
} }
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq,
struct list_head *bf_q, struct list_head *bf_q,
int txok, int sendbar) int txok, int sendbar)
{ {
...@@ -1826,7 +1823,6 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, ...@@ -1826,7 +1823,6 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
unsigned long flags; unsigned long flags;
int tx_flags = 0; int tx_flags = 0;
if (sendbar) if (sendbar)
tx_flags = ATH_TX_BAR; tx_flags = ATH_TX_BAR;
...@@ -1839,6 +1835,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, ...@@ -1839,6 +1835,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
ath_tx_complete(sc, skb, tx_flags); ath_tx_complete(sc, skb, tx_flags);
ath_debug_stat_tx(sc, txq, bf);
/* /*
* Return the list of ath_buf of this mpdu to free queue * Return the list of ath_buf of this mpdu to free queue
...@@ -2026,7 +2023,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) ...@@ -2026,7 +2023,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
if (bf_isampdu(bf)) if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok);
else else
ath_tx_complete_buf(sc, bf, &bf_head, txok, 0); ath_tx_complete_buf(sc, bf, txq, &bf_head, txok, 0);
ath_wake_mac80211_queue(sc, txq); ath_wake_mac80211_queue(sc, txq);
...@@ -2037,7 +2034,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) ...@@ -2037,7 +2034,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
} }
} }
void ath_tx_complete_poll_work(struct work_struct *work) static void ath_tx_complete_poll_work(struct work_struct *work)
{ {
struct ath_softc *sc = container_of(work, struct ath_softc, struct ath_softc *sc = container_of(work, struct ath_softc,
tx_complete_work.work); tx_complete_work.work);
......
...@@ -450,7 +450,7 @@ static struct country_code_to_enum_rd allCountries[] = { ...@@ -450,7 +450,7 @@ static struct country_code_to_enum_rd allCountries[] = {
{CTRY_SWITZERLAND, ETSI1_WORLD, "CH"}, {CTRY_SWITZERLAND, ETSI1_WORLD, "CH"},
{CTRY_SYRIA, NULL1_WORLD, "SY"}, {CTRY_SYRIA, NULL1_WORLD, "SY"},
{CTRY_TAIWAN, APL3_FCCA, "TW"}, {CTRY_TAIWAN, APL3_FCCA, "TW"},
{CTRY_THAILAND, NULL1_WORLD, "TH"}, {CTRY_THAILAND, FCC3_WORLD, "TH"},
{CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"}, {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"},
{CTRY_TUNISIA, ETSI3_WORLD, "TN"}, {CTRY_TUNISIA, ETSI3_WORLD, "TN"},
{CTRY_TURKEY, ETSI3_WORLD, "TR"}, {CTRY_TURKEY, ETSI3_WORLD, "TR"},
......
...@@ -9,6 +9,9 @@ config IWLWIFI ...@@ -9,6 +9,9 @@ config IWLWIFI
config IWLWIFI_LEDS config IWLWIFI_LEDS
bool "Enable LED support in iwlagn and iwl3945 drivers" bool "Enable LED support in iwlagn and iwl3945 drivers"
depends on IWLWIFI depends on IWLWIFI
default y
---help---
Select this if you want LED support.
config IWLWIFI_SPECTRUM_MEASUREMENT config IWLWIFI_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwlagn driver" bool "Enable Spectrum Measurement in iwlagn driver"
......
...@@ -55,13 +55,88 @@ ...@@ -55,13 +55,88 @@
#define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" #define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode"
#define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api) #define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api)
/*
* For 1000, use advance thermal throttling critical temperature threshold,
* but legacy thermal management implementation for now.
* This is for the reason of 1000 uCode using advance thermal throttling API
* but not implement ct_kill_exit based on ct_kill exit temperature
* so the thermal throttling will still based on legacy thermal throttling
* management.
* The code here need to be modified once 1000 uCode has the advanced thermal
* throttling algorithm in place
*/
static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
{
/* want Celsius */
priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
}
static struct iwl_lib_ops iwl1000_lib = {
.set_hw_params = iwl5000_hw_set_hw_params,
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
.txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
.txq_set_sched = iwl5000_txq_set_sched,
.txq_agg_enable = iwl5000_txq_agg_enable,
.txq_agg_disable = iwl5000_txq_agg_disable,
.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
.txq_free_tfd = iwl_hw_txq_free_tfd,
.txq_init = iwl_hw_tx_queue_init,
.rx_handler_setup = iwl5000_rx_handler_setup,
.setup_deferred_work = iwl5000_setup_deferred_work,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
.load_ucode = iwl5000_load_ucode,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
.update_chain_flags = iwl_update_chain_flags,
.apm_ops = {
.init = iwl5000_apm_init,
.reset = iwl5000_apm_reset,
.stop = iwl5000_apm_stop,
.config = iwl5000_nic_config,
.set_pwr_src = iwl_set_pwr_src,
},
.eeprom_ops = {
.regulatory_bands = {
EEPROM_5000_REG_BAND_1_CHANNELS,
EEPROM_5000_REG_BAND_2_CHANNELS,
EEPROM_5000_REG_BAND_3_CHANNELS,
EEPROM_5000_REG_BAND_4_CHANNELS,
EEPROM_5000_REG_BAND_5_CHANNELS,
EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
EEPROM_5000_REG_BAND_52_FAT_CHANNELS
},
.verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
.release_semaphore = iwlcore_eeprom_release_semaphore,
.calib_version = iwl5000_eeprom_calib_version,
.query_addr = iwl5000_eeprom_query_addr,
},
.post_associate = iwl_post_associate,
.isr = iwl_isr_ict,
.config_ap = iwl_config_ap,
.temp_ops = {
.temperature = iwl5000_temperature,
.set_ct_kill = iwl1000_set_ct_threshold,
},
};
static struct iwl_ops iwl1000_ops = {
.ucode = &iwl5000_ucode,
.lib = &iwl1000_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl5000_hcmd_utils,
};
struct iwl_cfg iwl1000_bgn_cfg = { struct iwl_cfg iwl1000_bgn_cfg = {
.name = "1000 Series BGN", .name = "1000 Series BGN",
.fw_name_pre = IWL1000_FW_PRE, .fw_name_pre = IWL1000_FW_PRE,
.ucode_api_max = IWL1000_UCODE_API_MAX, .ucode_api_max = IWL1000_UCODE_API_MAX,
.ucode_api_min = IWL1000_UCODE_API_MIN, .ucode_api_min = IWL1000_UCODE_API_MIN,
.sku = IWL_SKU_G|IWL_SKU_N, .sku = IWL_SKU_G|IWL_SKU_N,
.ops = &iwl5000_ops, .ops = &iwl1000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
......
...@@ -79,11 +79,10 @@ static const struct { ...@@ -79,11 +79,10 @@ static const struct {
#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/ #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/
#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
static int iwl3945_led_cmd_callback(struct iwl_priv *priv, static void iwl3945_led_cmd_callback(struct iwl_priv *priv,
struct iwl_cmd *cmd, struct iwl_device_cmd *cmd,
struct sk_buff *skb) struct sk_buff *skb)
{ {
return 1;
} }
static inline int iwl3945_brightness_to_idx(enum led_brightness brightness) static inline int iwl3945_brightness_to_idx(enum led_brightness brightness)
...@@ -99,8 +98,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, ...@@ -99,8 +98,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv,
.id = REPLY_LEDS_CMD, .id = REPLY_LEDS_CMD,
.len = sizeof(struct iwl_led_cmd), .len = sizeof(struct iwl_led_cmd),
.data = led_cmd, .data = led_cmd,
.meta.flags = CMD_ASYNC, .flags = CMD_ASYNC,
.meta.u.callback = iwl3945_led_cmd_callback, .callback = iwl3945_led_cmd_callback,
}; };
return iwl_send_cmd(priv, &cmd); return iwl_send_cmd(priv, &cmd);
......
...@@ -749,8 +749,8 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) ...@@ -749,8 +749,8 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
/* Unmap tx_cmd */ /* Unmap tx_cmd */
if (counter) if (counter)
pci_unmap_single(dev, pci_unmap_single(dev,
pci_unmap_addr(&txq->cmd[index]->meta, mapping), pci_unmap_addr(&txq->meta[index], mapping),
pci_unmap_len(&txq->cmd[index]->meta, len), pci_unmap_len(&txq->meta[index], len),
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
/* unmap chunks if any */ /* unmap chunks if any */
...@@ -774,9 +774,11 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) ...@@ -774,9 +774,11 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
* iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD: * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
* *
*/ */
void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd, void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
struct ieee80211_tx_info *info, struct iwl_device_cmd *cmd,
struct ieee80211_hdr *hdr, int sta_id, int tx_id) struct ieee80211_tx_info *info,
struct ieee80211_hdr *hdr,
int sta_id, int tx_id)
{ {
u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value; u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value;
u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1); u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1);
...@@ -1858,7 +1860,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) ...@@ -1858,7 +1860,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
.id = REPLY_RXON_ASSOC, .id = REPLY_RXON_ASSOC,
.len = sizeof(rxon_assoc), .len = sizeof(rxon_assoc),
.meta.flags = CMD_WANT_SKB, .flags = CMD_WANT_SKB,
.data = &rxon_assoc, .data = &rxon_assoc,
}; };
const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
...@@ -1882,14 +1884,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) ...@@ -1882,14 +1884,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
if (rc) if (rc)
return rc; return rc;
res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) { if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
rc = -EIO; rc = -EIO;
} }
priv->alloc_rxb_skb--; priv->alloc_rxb_skb--;
dev_kfree_skb_any(cmd.meta.u.skb); dev_kfree_skb_any(cmd.reply_skb);
return rc; return rc;
} }
......
...@@ -254,10 +254,11 @@ extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, ...@@ -254,10 +254,11 @@ extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv,
struct iwl_tx_queue *txq); struct iwl_tx_queue *txq);
extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv, extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl3945_frame *frame, u8 rate); struct iwl3945_frame *frame, u8 rate);
void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd, void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
struct ieee80211_tx_info *info, struct iwl_device_cmd *cmd,
struct ieee80211_hdr *hdr, struct ieee80211_tx_info *info,
int sta_id, int tx_id); struct ieee80211_hdr *hdr,
int sta_id, int tx_id);
extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv); extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power); extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv, extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
......
...@@ -776,7 +776,8 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = { ...@@ -776,7 +776,8 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
static void iwl4965_set_ct_threshold(struct iwl_priv *priv) static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
{ {
/* want Kelvin */ /* want Kelvin */
priv->hw_params.ct_kill_threshold = CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD); priv->hw_params.ct_kill_threshold =
CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY);
} }
/** /**
...@@ -1796,6 +1797,7 @@ static void iwl4965_temperature_calib(struct iwl_priv *priv) ...@@ -1796,6 +1797,7 @@ static void iwl4965_temperature_calib(struct iwl_priv *priv)
} }
priv->temperature = temp; priv->temperature = temp;
iwl_tt_handler(priv);
set_bit(STATUS_TEMPERATURE, &priv->status); set_bit(STATUS_TEMPERATURE, &priv->status);
if (!priv->disable_tx_power_cal && if (!priv->disable_tx_power_cal &&
......
...@@ -91,7 +91,7 @@ static int iwl5000_apm_stop_master(struct iwl_priv *priv) ...@@ -91,7 +91,7 @@ static int iwl5000_apm_stop_master(struct iwl_priv *priv)
} }
static int iwl5000_apm_init(struct iwl_priv *priv) int iwl5000_apm_init(struct iwl_priv *priv)
{ {
int ret = 0; int ret = 0;
...@@ -137,7 +137,7 @@ static int iwl5000_apm_init(struct iwl_priv *priv) ...@@ -137,7 +137,7 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
} }
/* FIXME: this is identical to 4965 */ /* FIXME: this is identical to 4965 */
static void iwl5000_apm_stop(struct iwl_priv *priv) void iwl5000_apm_stop(struct iwl_priv *priv)
{ {
unsigned long flags; unsigned long flags;
...@@ -156,7 +156,7 @@ static void iwl5000_apm_stop(struct iwl_priv *priv) ...@@ -156,7 +156,7 @@ static void iwl5000_apm_stop(struct iwl_priv *priv)
} }
static int iwl5000_apm_reset(struct iwl_priv *priv) int iwl5000_apm_reset(struct iwl_priv *priv)
{ {
int ret = 0; int ret = 0;
...@@ -198,7 +198,7 @@ static int iwl5000_apm_reset(struct iwl_priv *priv) ...@@ -198,7 +198,7 @@ static int iwl5000_apm_reset(struct iwl_priv *priv)
} }
static void iwl5000_nic_config(struct iwl_priv *priv) void iwl5000_nic_config(struct iwl_priv *priv)
{ {
unsigned long flags; unsigned long flags;
u16 radio_cfg; u16 radio_cfg;
...@@ -290,7 +290,7 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) ...@@ -290,7 +290,7 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
return (address & ADDRESS_MSK) + (offset << 1); return (address & ADDRESS_MSK) + (offset << 1);
} }
static u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv) u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv)
{ {
struct iwl_eeprom_calib_hdr { struct iwl_eeprom_calib_hdr {
u8 version; u8 version;
...@@ -436,7 +436,7 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { ...@@ -436,7 +436,7 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
.nrg_th_ofdm = 95, .nrg_th_ofdm = 95,
}; };
static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
size_t offset) size_t offset)
{ {
u32 address = eeprom_indirect_address(priv, offset); u32 address = eeprom_indirect_address(priv, offset);
...@@ -447,7 +447,7 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, ...@@ -447,7 +447,7 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
static void iwl5150_set_ct_threshold(struct iwl_priv *priv) static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
{ {
const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD) - s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) -
iwl_temp_calib_to_offset(priv); iwl_temp_calib_to_offset(priv);
priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef; priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef;
...@@ -456,7 +456,7 @@ static void iwl5150_set_ct_threshold(struct iwl_priv *priv) ...@@ -456,7 +456,7 @@ static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
static void iwl5000_set_ct_threshold(struct iwl_priv *priv) static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
{ {
/* want Celsius */ /* want Celsius */
priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
} }
/* /*
...@@ -631,7 +631,7 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv, ...@@ -631,7 +631,7 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv,
return ret; return ret;
} }
static int iwl5000_load_ucode(struct iwl_priv *priv) int iwl5000_load_ucode(struct iwl_priv *priv)
{ {
int ret = 0; int ret = 0;
...@@ -658,7 +658,7 @@ static int iwl5000_load_ucode(struct iwl_priv *priv) ...@@ -658,7 +658,7 @@ static int iwl5000_load_ucode(struct iwl_priv *priv)
return ret; return ret;
} }
static void iwl5000_init_alive_start(struct iwl_priv *priv) void iwl5000_init_alive_start(struct iwl_priv *priv)
{ {
int ret = 0; int ret = 0;
...@@ -734,7 +734,7 @@ static int iwl5000_send_wimax_coex(struct iwl_priv *priv) ...@@ -734,7 +734,7 @@ static int iwl5000_send_wimax_coex(struct iwl_priv *priv)
sizeof(coex_cmd), &coex_cmd); sizeof(coex_cmd), &coex_cmd);
} }
static int iwl5000_alive_notify(struct iwl_priv *priv) int iwl5000_alive_notify(struct iwl_priv *priv)
{ {
u32 a; u32 a;
unsigned long flags; unsigned long flags;
...@@ -821,7 +821,7 @@ static int iwl5000_alive_notify(struct iwl_priv *priv) ...@@ -821,7 +821,7 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
return 0; return 0;
} }
static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
{ {
if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) || if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) ||
(priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
...@@ -892,7 +892,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) ...@@ -892,7 +892,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
/** /**
* iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/ */
static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq, struct iwl_tx_queue *txq,
u16 byte_cnt) u16 byte_cnt)
{ {
...@@ -932,7 +932,7 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, ...@@ -932,7 +932,7 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
} }
static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq) struct iwl_tx_queue *txq)
{ {
struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
...@@ -987,7 +987,7 @@ static void iwl5000_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) ...@@ -987,7 +987,7 @@ static void iwl5000_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id)
(1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); (1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
} }
static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
int tx_fifo, int sta_id, int tid, u16 ssn_idx) int tx_fifo, int sta_id, int tid, u16 ssn_idx)
{ {
unsigned long flags; unsigned long flags;
...@@ -1048,7 +1048,7 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, ...@@ -1048,7 +1048,7 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
return 0; return 0;
} }
static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
u16 ssn_idx, u8 tx_fifo) u16 ssn_idx, u8 tx_fifo)
{ {
if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
...@@ -1091,7 +1091,7 @@ u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) ...@@ -1091,7 +1091,7 @@ u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
* Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
* must be called under priv->lock and mac access * must be called under priv->lock and mac access
*/ */
static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask) void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
{ {
iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); iwl_write_prph(priv, IWL50_SCD_TXFACT, mask);
} }
...@@ -1312,13 +1312,13 @@ u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len) ...@@ -1312,13 +1312,13 @@ u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len)
return len; return len;
} }
static void iwl5000_setup_deferred_work(struct iwl_priv *priv) void iwl5000_setup_deferred_work(struct iwl_priv *priv)
{ {
/* in 5000 the tx power calibration is done in uCode */ /* in 5000 the tx power calibration is done in uCode */
priv->disable_tx_power_cal = 1; priv->disable_tx_power_cal = 1;
} }
static void iwl5000_rx_handler_setup(struct iwl_priv *priv) void iwl5000_rx_handler_setup(struct iwl_priv *priv)
{ {
/* init calibration handlers */ /* init calibration handlers */
priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
...@@ -1329,7 +1329,7 @@ static void iwl5000_rx_handler_setup(struct iwl_priv *priv) ...@@ -1329,7 +1329,7 @@ static void iwl5000_rx_handler_setup(struct iwl_priv *priv)
} }
static int iwl5000_hw_valid_rtc_data_addr(u32 addr) int iwl5000_hw_valid_rtc_data_addr(u32 addr)
{ {
return (addr >= IWL50_RTC_DATA_LOWER_BOUND) && return (addr >= IWL50_RTC_DATA_LOWER_BOUND) &&
(addr < IWL50_RTC_DATA_UPPER_BOUND); (addr < IWL50_RTC_DATA_UPPER_BOUND);
...@@ -1381,7 +1381,7 @@ static int iwl5000_send_rxon_assoc(struct iwl_priv *priv) ...@@ -1381,7 +1381,7 @@ static int iwl5000_send_rxon_assoc(struct iwl_priv *priv)
return ret; return ret;
} }
static int iwl5000_send_tx_power(struct iwl_priv *priv) int iwl5000_send_tx_power(struct iwl_priv *priv)
{ {
struct iwl5000_tx_power_dbm_cmd tx_power_cmd; struct iwl5000_tx_power_dbm_cmd tx_power_cmd;
u8 tx_ant_cfg_cmd; u8 tx_ant_cfg_cmd;
...@@ -1401,10 +1401,11 @@ static int iwl5000_send_tx_power(struct iwl_priv *priv) ...@@ -1401,10 +1401,11 @@ static int iwl5000_send_tx_power(struct iwl_priv *priv)
NULL); NULL);
} }
static void iwl5000_temperature(struct iwl_priv *priv) void iwl5000_temperature(struct iwl_priv *priv)
{ {
/* store temperature from statistics (in Celsius) */ /* store temperature from statistics (in Celsius) */
priv->temperature = le32_to_cpu(priv->statistics.general.temperature); priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
iwl_tt_handler(priv);
} }
static void iwl5150_temperature(struct iwl_priv *priv) static void iwl5150_temperature(struct iwl_priv *priv)
......
...@@ -61,6 +61,63 @@ ...@@ -61,6 +61,63 @@
#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
{
/* want Celsius */
priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
}
static struct iwl_lib_ops iwl6000_lib = {
.set_hw_params = iwl5000_hw_set_hw_params,
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
.txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
.txq_set_sched = iwl5000_txq_set_sched,
.txq_agg_enable = iwl5000_txq_agg_enable,
.txq_agg_disable = iwl5000_txq_agg_disable,
.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
.txq_free_tfd = iwl_hw_txq_free_tfd,
.txq_init = iwl_hw_tx_queue_init,
.rx_handler_setup = iwl5000_rx_handler_setup,
.setup_deferred_work = iwl5000_setup_deferred_work,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
.load_ucode = iwl5000_load_ucode,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
.update_chain_flags = iwl_update_chain_flags,
.apm_ops = {
.init = iwl5000_apm_init,
.reset = iwl5000_apm_reset,
.stop = iwl5000_apm_stop,
.config = iwl5000_nic_config,
.set_pwr_src = iwl_set_pwr_src,
},
.eeprom_ops = {
.regulatory_bands = {
EEPROM_5000_REG_BAND_1_CHANNELS,
EEPROM_5000_REG_BAND_2_CHANNELS,
EEPROM_5000_REG_BAND_3_CHANNELS,
EEPROM_5000_REG_BAND_4_CHANNELS,
EEPROM_5000_REG_BAND_5_CHANNELS,
EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
EEPROM_5000_REG_BAND_52_FAT_CHANNELS
},
.verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
.release_semaphore = iwlcore_eeprom_release_semaphore,
.calib_version = iwl5000_eeprom_calib_version,
.query_addr = iwl5000_eeprom_query_addr,
},
.post_associate = iwl_post_associate,
.isr = iwl_isr_ict,
.config_ap = iwl_config_ap,
.temp_ops = {
.temperature = iwl5000_temperature,
.set_ct_kill = iwl6000_set_ct_threshold,
},
};
static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = { static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = {
.get_hcmd_size = iwl5000_get_hcmd_size, .get_hcmd_size = iwl5000_get_hcmd_size,
.build_addsta_hcmd = iwl5000_build_addsta_hcmd, .build_addsta_hcmd = iwl5000_build_addsta_hcmd,
...@@ -70,7 +127,7 @@ static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = { ...@@ -70,7 +127,7 @@ static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = {
static struct iwl_ops iwl6000_ops = { static struct iwl_ops iwl6000_ops = {
.ucode = &iwl5000_ucode, .ucode = &iwl5000_ucode,
.lib = &iwl5000_lib, .lib = &iwl6000_lib,
.hcmd = &iwl5000_hcmd, .hcmd = &iwl5000_hcmd,
.utils = &iwl6000_hcmd_utils, .utils = &iwl6000_hcmd_utils,
}; };
......
...@@ -177,7 +177,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -177,7 +177,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
struct sk_buff *skb, struct sk_buff *skb,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta); struct iwl_lq_sta *lq_sta);
static void rs_fill_link_cmd(const struct iwl_priv *priv, static void rs_fill_link_cmd(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta, u32 rate_n_flags); struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
...@@ -1398,6 +1398,12 @@ static int rs_move_legacy_other(struct iwl_priv *priv, ...@@ -1398,6 +1398,12 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
int ret = 0; int ret = 0;
u8 update_search_tbl_counter = 0; u8 update_search_tbl_counter = 0;
if (!iwl_ht_enabled(priv))
/* stay in Legacy */
tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
else if (iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE &&
tbl->action > IWL_LEGACY_SWITCH_SISO)
tbl->action = IWL_LEGACY_SWITCH_SISO;
for (; ;) { for (; ;) {
lq_sta->action_counter++; lq_sta->action_counter++;
switch (tbl->action) { switch (tbl->action) {
...@@ -1529,6 +1535,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, ...@@ -1529,6 +1535,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
u8 update_search_tbl_counter = 0; u8 update_search_tbl_counter = 0;
int ret; int ret;
if (iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE &&
tbl->action > IWL_SISO_SWITCH_ANTENNA2) {
/* stay in SISO */
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
}
for (;;) { for (;;) {
lq_sta->action_counter++; lq_sta->action_counter++;
switch (tbl->action) { switch (tbl->action) {
...@@ -1663,6 +1674,12 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, ...@@ -1663,6 +1674,12 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
u8 update_search_tbl_counter = 0; u8 update_search_tbl_counter = 0;
int ret; int ret;
if ((iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE) &&
(tbl->action < IWL_MIMO2_SWITCH_SISO_A ||
tbl->action > IWL_MIMO2_SWITCH_SISO_C)) {
/* switch in SISO */
tbl->action = IWL_MIMO2_SWITCH_SISO_A;
}
for (;;) { for (;;) {
lq_sta->action_counter++; lq_sta->action_counter++;
switch (tbl->action) { switch (tbl->action) {
...@@ -1799,6 +1816,12 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, ...@@ -1799,6 +1816,12 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
int ret; int ret;
u8 update_search_tbl_counter = 0; u8 update_search_tbl_counter = 0;
if ((iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE) &&
(tbl->action < IWL_MIMO3_SWITCH_SISO_A ||
tbl->action > IWL_MIMO3_SWITCH_SISO_C)) {
/* switch in SISO */
tbl->action = IWL_MIMO3_SWITCH_SISO_A;
}
for (;;) { for (;;) {
lq_sta->action_counter++; lq_sta->action_counter++;
switch (tbl->action) { switch (tbl->action) {
...@@ -2002,6 +2025,25 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) ...@@ -2002,6 +2025,25 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
} }
} }
/*
* setup rate table in uCode
* return rate_n_flags as used in the table
*/
static u32 rs_update_rate_tbl(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl,
int index, u8 is_green)
{
u32 rate;
/* Update uCode's rate table. */
rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
rs_fill_link_cmd(priv, lq_sta, rate);
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
return rate;
}
/* /*
* Do rate scaling and search for new modulation mode. * Do rate scaling and search for new modulation mode.
*/ */
...@@ -2098,6 +2140,16 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -2098,6 +2140,16 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
if (!((1 << index) & rate_scale_index_msk)) { if (!((1 << index) & rate_scale_index_msk)) {
IWL_ERR(priv, "Current Rate is not valid\n"); IWL_ERR(priv, "Current Rate is not valid\n");
if (lq_sta->search_better_tbl) {
/* revert to active table if search table is not valid*/
tbl->lq_type = LQ_NONE;
lq_sta->search_better_tbl = 0;
tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
/* get "active" rate info */
index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
rate = rs_update_rate_tbl(priv, lq_sta,
tbl, index, is_green);
}
return; return;
} }
...@@ -2149,8 +2201,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -2149,8 +2201,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
tbl->expected_tpt[index] + 64) / 128)); tbl->expected_tpt[index] + 64) / 128));
/* If we are searching for better modulation mode, check success. */ /* If we are searching for better modulation mode, check success. */
if (lq_sta->search_better_tbl) { if (lq_sta->search_better_tbl &&
(iwl_tx_ant_restriction(priv) == IWL_TX_MULTI)) {
/* If good success, continue using the "search" mode; /* If good success, continue using the "search" mode;
* no need to send new link quality command, since we're * no need to send new link quality command, since we're
* continuing to use the setup that we've been trying. */ * continuing to use the setup that we've been trying. */
...@@ -2278,7 +2330,11 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -2278,7 +2330,11 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
((sr > IWL_RATE_HIGH_TH) || ((sr > IWL_RATE_HIGH_TH) ||
(current_tpt > (100 * tbl->expected_tpt[low])))) (current_tpt > (100 * tbl->expected_tpt[low]))))
scale_action = 0; scale_action = 0;
if (!iwl_ht_enabled(priv) && !is_legacy(tbl->lq_type))
scale_action = -1;
if (iwl_tx_ant_restriction(priv) != IWL_TX_MULTI &&
(is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type)))
scale_action = -1;
switch (scale_action) { switch (scale_action) {
case -1: case -1:
/* Decrease starting rate, update uCode's rate table */ /* Decrease starting rate, update uCode's rate table */
...@@ -2308,15 +2364,15 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -2308,15 +2364,15 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
lq_update: lq_update:
/* Replace uCode's rate table for the destination station. */ /* Replace uCode's rate table for the destination station. */
if (update_lq) { if (update_lq)
rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); rate = rs_update_rate_tbl(priv, lq_sta,
rs_fill_link_cmd(priv, lq_sta, rate); tbl, index, is_green);
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
}
/* Should we stay with this modulation mode, or search for a new one? */
rs_stay_in_table(lq_sta);
if (iwl_tx_ant_restriction(priv) == IWL_TX_MULTI) {
/* Should we stay with this modulation mode,
* or search for a new one? */
rs_stay_in_table(lq_sta);
}
/* /*
* Search for new modulation mode if we're: * Search for new modulation mode if we're:
* 1) Not changing rates right now * 1) Not changing rates right now
...@@ -2373,7 +2429,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -2373,7 +2429,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
* have been tried and compared, stay in this best modulation * have been tried and compared, stay in this best modulation
* mode for a while before next round of mode comparisons. */ * mode for a while before next round of mode comparisons. */
if (lq_sta->enable_counter && if (lq_sta->enable_counter &&
(lq_sta->action_counter >= tbl1->max_search)) { (lq_sta->action_counter >= tbl1->max_search) &&
iwl_ht_enabled(priv)) {
if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
(lq_sta->tx_agg_tid_en & (1 << tid)) && (lq_sta->tx_agg_tid_en & (1 << tid)) &&
(tid != MAX_TID_COUNT)) { (tid != MAX_TID_COUNT)) {
...@@ -2659,7 +2716,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, ...@@ -2659,7 +2716,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
rs_initialize_lq(priv, conf, sta, lq_sta); rs_initialize_lq(priv, conf, sta, lq_sta);
} }
static void rs_fill_link_cmd(const struct iwl_priv *priv, static void rs_fill_link_cmd(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta, u32 new_rate) struct iwl_lq_sta *lq_sta, u32 new_rate)
{ {
struct iwl_scale_tbl_info tbl_type; struct iwl_scale_tbl_info tbl_type;
......
...@@ -442,8 +442,8 @@ void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) ...@@ -442,8 +442,8 @@ void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
/* Unmap tx_cmd */ /* Unmap tx_cmd */
if (num_tbs) if (num_tbs)
pci_unmap_single(dev, pci_unmap_single(dev,
pci_unmap_addr(&txq->cmd[index]->meta, mapping), pci_unmap_addr(&txq->meta[index], mapping),
pci_unmap_len(&txq->cmd[index]->meta, len), pci_unmap_len(&txq->meta[index], len),
PCI_DMA_BIDIRECTIONAL); PCI_DMA_BIDIRECTIONAL);
/* Unmap chunks, if any. */ /* Unmap chunks, if any. */
...@@ -637,7 +637,6 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, ...@@ -637,7 +637,6 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
unsigned long status = priv->status; unsigned long status = priv->status;
unsigned long reg_flags;
IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n", IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n",
(flags & HW_CARD_DISABLED) ? "Kill" : "On", (flags & HW_CARD_DISABLED) ? "Kill" : "On",
...@@ -657,19 +656,12 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, ...@@ -657,19 +656,12 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
iwl_write_direct32(priv, HBUS_TARG_MBX_C, iwl_write_direct32(priv, HBUS_TARG_MBX_C,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
}
if (flags & RF_CARD_DISABLED) {
iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
iwl_read32(priv, CSR_UCODE_DRV_GP1);
spin_lock_irqsave(&priv->reg_lock, reg_flags);
if (!iwl_grab_nic_access(priv))
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
} }
if (flags & RF_CARD_DISABLED)
iwl_tt_enter_ct_kill(priv);
} }
if (!(flags & RF_CARD_DISABLED))
iwl_tt_exit_ct_kill(priv);
if (flags & HW_CARD_DISABLED) if (flags & HW_CARD_DISABLED)
set_bit(STATUS_RF_KILL_HW, &priv->status); set_bit(STATUS_RF_KILL_HW, &priv->status);
...@@ -3015,6 +3007,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3015,6 +3007,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
test_bit(STATUS_RF_KILL_HW, &priv->status)); test_bit(STATUS_RF_KILL_HW, &priv->status));
iwl_power_initialize(priv); iwl_power_initialize(priv);
iwl_tt_initialize(priv);
return 0; return 0;
out_remove_sysfs: out_remove_sysfs:
...@@ -3067,6 +3060,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) ...@@ -3067,6 +3060,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
iwl_down(priv); iwl_down(priv);
} }
iwl_tt_exit(priv);
/* make sure we flush any pending irq or /* make sure we flush any pending irq or
* tasklet for the driver * tasklet for the driver
*/ */
......
...@@ -86,7 +86,7 @@ int iwl_send_calib_results(struct iwl_priv *priv) ...@@ -86,7 +86,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
struct iwl_host_cmd hcmd = { struct iwl_host_cmd hcmd = {
.id = REPLY_PHY_CALIBRATION_CMD, .id = REPLY_PHY_CALIBRATION_CMD,
.meta.flags = CMD_SIZE_HUGE, .flags = CMD_SIZE_HUGE,
}; };
for (i = 0; i < IWL_CALIB_MAX; i++) { for (i = 0; i < IWL_CALIB_MAX; i++) {
...@@ -419,7 +419,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) ...@@ -419,7 +419,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
struct iwl_host_cmd cmd_out = { struct iwl_host_cmd cmd_out = {
.id = SENSITIVITY_CMD, .id = SENSITIVITY_CMD,
.len = sizeof(struct iwl_sensitivity_cmd), .len = sizeof(struct iwl_sensitivity_cmd),
.meta.flags = CMD_ASYNC, .flags = CMD_ASYNC,
.data = &cmd, .data = &cmd,
}; };
......
...@@ -2413,6 +2413,13 @@ struct iwl_ct_kill_config { ...@@ -2413,6 +2413,13 @@ struct iwl_ct_kill_config {
__le32 critical_temperature_R; __le32 critical_temperature_R;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* 1000, and 6x00 */
struct iwl_ct_kill_throttling_config {
__le32 critical_temperature_exit;
__le32 reserved;
__le32 critical_temperature_enter;
} __attribute__ ((packed));
/****************************************************************************** /******************************************************************************
* (8) * (8)
* Scan Commands, Responses, Notifications: * Scan Commands, Responses, Notifications:
......
...@@ -632,6 +632,10 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, ...@@ -632,6 +632,10 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
if (!sta_ht_inf->ht_supported) if (!sta_ht_inf->ht_supported)
return 0; return 0;
} }
#ifdef CONFIG_IWLWIFI_DEBUG
if (priv->disable_ht40)
return 0;
#endif
return iwl_is_channel_extension(priv, priv->band, return iwl_is_channel_extension(priv, priv->band,
le16_to_cpu(priv->staging_rxon.channel), le16_to_cpu(priv->staging_rxon.channel),
iwl_ht_conf->extension_chan_offset); iwl_ht_conf->extension_chan_offset);
...@@ -1291,7 +1295,6 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv) ...@@ -1291,7 +1295,6 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr); IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
} }
#endif
static const char *desc_lookup_text[] = { static const char *desc_lookup_text[] = {
"OK", "OK",
...@@ -1496,6 +1499,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) ...@@ -1496,6 +1499,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
iwl_print_event_log(priv, 0, next_entry, mode); iwl_print_event_log(priv, 0, next_entry, mode);
} }
#endif
/** /**
* iwl_irq_handle_error - called for HW or SW error interrupt from card * iwl_irq_handle_error - called for HW or SW error interrupt from card
*/ */
...@@ -2089,7 +2093,7 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags) ...@@ -2089,7 +2093,7 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags)
u32 stat_flags = 0; u32 stat_flags = 0;
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
.id = REPLY_STATISTICS_CMD, .id = REPLY_STATISTICS_CMD,
.meta.flags = flags, .flags = flags,
.len = sizeof(stat_flags), .len = sizeof(stat_flags),
.data = (u8 *) &stat_flags, .data = (u8 *) &stat_flags,
}; };
...@@ -2224,6 +2228,7 @@ EXPORT_SYMBOL(iwl_verify_ucode); ...@@ -2224,6 +2228,7 @@ EXPORT_SYMBOL(iwl_verify_ucode);
void iwl_rf_kill_ct_config(struct iwl_priv *priv) void iwl_rf_kill_ct_config(struct iwl_priv *priv)
{ {
struct iwl_ct_kill_config cmd; struct iwl_ct_kill_config cmd;
struct iwl_ct_kill_throttling_config adv_cmd;
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
...@@ -2231,10 +2236,28 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv) ...@@ -2231,10 +2236,28 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
priv->power_data.ct_kill_toggle = false;
switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
case CSR_HW_REV_TYPE_1000:
case CSR_HW_REV_TYPE_6x00:
case CSR_HW_REV_TYPE_6x50:
adv_cmd.critical_temperature_enter =
cpu_to_le32(priv->hw_params.ct_kill_threshold);
adv_cmd.critical_temperature_exit =
cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
sizeof(adv_cmd), &adv_cmd);
break;
default:
cmd.critical_temperature_R =
cpu_to_le32(priv->hw_params.ct_kill_threshold);
cmd.critical_temperature_R = ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
cpu_to_le32(priv->hw_params.ct_kill_threshold); sizeof(cmd), &cmd);
break;
}
ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
sizeof(cmd), &cmd); sizeof(cmd), &cmd);
if (ret) if (ret)
...@@ -2263,7 +2286,7 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) ...@@ -2263,7 +2286,7 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
.id = REPLY_CARD_STATE_CMD, .id = REPLY_CARD_STATE_CMD,
.len = sizeof(u32), .len = sizeof(u32),
.data = &flags, .data = &flags,
.meta.flags = meta_flag, .flags = meta_flag,
}; };
return iwl_send_cmd(priv, &cmd); return iwl_send_cmd(priv, &cmd);
......
...@@ -446,9 +446,9 @@ int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, ...@@ -446,9 +446,9 @@ int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id,
u16 len, const void *data); u16 len, const void *data);
int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
const void *data, const void *data,
int (*callback)(struct iwl_priv *priv, void (*callback)(struct iwl_priv *priv,
struct iwl_cmd *cmd, struct iwl_device_cmd *cmd,
struct sk_buff *skb)); struct sk_buff *skb));
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
......
...@@ -84,9 +84,11 @@ struct iwl_debugfs { ...@@ -84,9 +84,11 @@ struct iwl_debugfs {
struct dentry *file_status; struct dentry *file_status;
struct dentry *file_interrupt; struct dentry *file_interrupt;
struct dentry *file_qos; struct dentry *file_qos;
struct dentry *file_thermal_throttling;
#ifdef CONFIG_IWLWIFI_LEDS #ifdef CONFIG_IWLWIFI_LEDS
struct dentry *file_led; struct dentry *file_led;
#endif #endif
struct dentry *file_disable_ht40;
} dbgfs_data_files; } dbgfs_data_files;
struct dir_rf_files { struct dir_rf_files {
struct dentry *file_disable_sensitivity; struct dentry *file_disable_sensitivity;
......
...@@ -618,6 +618,84 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, ...@@ -618,6 +618,84 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
} }
#endif #endif
static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
struct iwl_tt_mgmt *tt = &priv->power_data.tt;
struct iwl_tt_restriction *restriction;
char buf[100];
int pos = 0;
const size_t bufsz = sizeof(buf);
ssize_t ret;
pos += scnprintf(buf + pos, bufsz - pos,
"Thermal Throttling Mode: %s\n",
(priv->power_data.adv_tt)
? "Advance" : "Legacy");
pos += scnprintf(buf + pos, bufsz - pos,
"Thermal Throttling State: %d\n",
tt->state);
if (priv->power_data.adv_tt) {
restriction = tt->restriction + tt->state;
pos += scnprintf(buf + pos, bufsz - pos,
"Tx mode: %d\n",
restriction->tx_stream);
pos += scnprintf(buf + pos, bufsz - pos,
"Rx mode: %d\n",
restriction->rx_stream);
pos += scnprintf(buf + pos, bufsz - pos,
"HT mode: %d\n",
restriction->is_ht);
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
return ret;
}
static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
char buf[8];
int buf_size;
int ht40;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (sscanf(buf, "%d", &ht40) != 1)
return -EFAULT;
if (!iwl_is_associated(priv))
priv->disable_ht40 = ht40 ? true : false;
else {
IWL_ERR(priv, "Sta associated with AP - "
"Change to 40MHz channel support is not allowed\n");
return -EINVAL;
}
return count;
}
static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
char buf[100];
int pos = 0;
const size_t bufsz = sizeof(buf);
ssize_t ret;
pos += scnprintf(buf + pos, bufsz - pos,
"11n 40MHz Mode: %s\n",
priv->disable_ht40 ? "Disabled" : "Enabled");
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
return ret;
}
DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_READ_WRITE_FILE_OPS(sram);
DEBUGFS_WRITE_FILE_OPS(log_event); DEBUGFS_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(nvm); DEBUGFS_READ_FILE_OPS(nvm);
...@@ -631,6 +709,8 @@ DEBUGFS_READ_FILE_OPS(qos); ...@@ -631,6 +709,8 @@ DEBUGFS_READ_FILE_OPS(qos);
#ifdef CONFIG_IWLWIFI_LEDS #ifdef CONFIG_IWLWIFI_LEDS
DEBUGFS_READ_FILE_OPS(led); DEBUGFS_READ_FILE_OPS(led);
#endif #endif
DEBUGFS_READ_FILE_OPS(thermal_throttling);
DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
/* /*
* Create the debugfs files and directories * Create the debugfs files and directories
...@@ -671,6 +751,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) ...@@ -671,6 +751,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
#ifdef CONFIG_IWLWIFI_LEDS #ifdef CONFIG_IWLWIFI_LEDS
DEBUGFS_ADD_FILE(led, data); DEBUGFS_ADD_FILE(led, data);
#endif #endif
DEBUGFS_ADD_FILE(thermal_throttling, data);
DEBUGFS_ADD_FILE(disable_ht40, data);
DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
DEBUGFS_ADD_BOOL(disable_chain_noise, rf, DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
&priv->disable_chain_noise_cal); &priv->disable_chain_noise_cal);
...@@ -709,6 +791,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) ...@@ -709,6 +791,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
#ifdef CONFIG_IWLWIFI_LEDS #ifdef CONFIG_IWLWIFI_LEDS
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
#endif #endif
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
DEBUGFS_REMOVE(priv->dbgfs->dir_data); DEBUGFS_REMOVE(priv->dbgfs->dir_data);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
......
...@@ -63,6 +63,8 @@ extern struct iwl_cfg iwl6050_2agn_cfg; ...@@ -63,6 +63,8 @@ extern struct iwl_cfg iwl6050_2agn_cfg;
extern struct iwl_cfg iwl6050_3agn_cfg; extern struct iwl_cfg iwl6050_3agn_cfg;
extern struct iwl_cfg iwl1000_bgn_cfg; extern struct iwl_cfg iwl1000_bgn_cfg;
struct iwl_tx_queue;
/* shared structures from iwl-5000.c */ /* shared structures from iwl-5000.c */
extern struct iwl_mod_params iwl50_mod_params; extern struct iwl_mod_params iwl50_mod_params;
extern struct iwl_ops iwl5000_ops; extern struct iwl_ops iwl5000_ops;
...@@ -79,9 +81,37 @@ extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, ...@@ -79,9 +81,37 @@ extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
__le32 *tx_flags); __le32 *tx_flags);
extern int iwl5000_calc_rssi(struct iwl_priv *priv, extern int iwl5000_calc_rssi(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp); struct iwl_rx_phy_res *rx_resp);
extern int iwl5000_apm_init(struct iwl_priv *priv);
extern void iwl5000_apm_stop(struct iwl_priv *priv);
extern int iwl5000_apm_reset(struct iwl_priv *priv);
extern void iwl5000_nic_config(struct iwl_priv *priv);
extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv);
extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
size_t offset);
extern void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
u16 byte_cnt);
extern void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
extern int iwl5000_load_ucode(struct iwl_priv *priv);
extern void iwl5000_init_alive_start(struct iwl_priv *priv);
extern int iwl5000_alive_notify(struct iwl_priv *priv);
extern int iwl5000_hw_set_hw_params(struct iwl_priv *priv);
extern int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
int tx_fifo, int sta_id, int tid, u16 ssn_idx);
extern int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
u16 ssn_idx, u8 tx_fifo);
extern void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask);
extern void iwl5000_setup_deferred_work(struct iwl_priv *priv);
extern void iwl5000_rx_handler_setup(struct iwl_priv *priv);
extern int iwl5000_hw_valid_rtc_data_addr(u32 addr);
extern int iwl5000_send_tx_power(struct iwl_priv *priv);
extern void iwl5000_temperature(struct iwl_priv *priv);
/* CT-KILL constants */ /* CT-KILL constants */
#define CT_KILL_THRESHOLD 110 /* in Celsius */ #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */
#define CT_KILL_THRESHOLD 114 /* in Celsius */
#define CT_KILL_EXIT_THRESHOLD 95 /* in Celsius */
/* Default noise level to report when noise measurement is not available. /* Default noise level to report when noise measurement is not available.
* This may be because we're: * This may be because we're:
...@@ -120,6 +150,31 @@ struct iwl_rx_mem_buffer { ...@@ -120,6 +150,31 @@ struct iwl_rx_mem_buffer {
struct list_head list; struct list_head list;
}; };
/* defined below */
struct iwl_device_cmd;
struct iwl_cmd_meta {
/* only for SYNC commands, iff the reply skb is wanted */
struct iwl_host_cmd *source;
/*
* only for ASYNC commands
* (which is somewhat stupid -- look at iwl-sta.c for instance
* which duplicates a bunch of code because the callback isn't
* invoked for SYNC commands, if it were and its result passed
* through it would be simpler...)
*/
void (*callback)(struct iwl_priv *priv,
struct iwl_device_cmd *cmd,
struct sk_buff *skb);
/* The CMD_SIZE_HUGE flag bit indicates that the command
* structure is stored at the end of the shared queue memory. */
u32 flags;
DECLARE_PCI_UNMAP_ADDR(mapping)
DECLARE_PCI_UNMAP_LEN(len)
};
/* /*
* Generic queue structure * Generic queue structure
* *
...@@ -147,7 +202,8 @@ struct iwl_tx_info { ...@@ -147,7 +202,8 @@ struct iwl_tx_info {
* struct iwl_tx_queue - Tx Queue for DMA * struct iwl_tx_queue - Tx Queue for DMA
* @q: generic Rx/Tx queue descriptor * @q: generic Rx/Tx queue descriptor
* @bd: base of circular buffer of TFDs * @bd: base of circular buffer of TFDs
* @cmd: array of command/Tx buffers * @cmd: array of command/TX buffer pointers
* @meta: array of meta data for each command/tx buffer
* @dma_addr_cmd: physical address of cmd/tx buffer array * @dma_addr_cmd: physical address of cmd/tx buffer array
* @txb: array of per-TFD driver data * @txb: array of per-TFD driver data
* @need_update: indicates need to update read/write index * @need_update: indicates need to update read/write index
...@@ -162,7 +218,8 @@ struct iwl_tx_info { ...@@ -162,7 +218,8 @@ struct iwl_tx_info {
struct iwl_tx_queue { struct iwl_tx_queue {
struct iwl_queue q; struct iwl_queue q;
void *tfds; void *tfds;
struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS]; struct iwl_device_cmd **cmd;
struct iwl_cmd_meta *meta;
struct iwl_tx_info *txb; struct iwl_tx_info *txb;
u8 need_update; u8 need_update;
u8 sched_retry; u8 sched_retry;
...@@ -299,35 +356,16 @@ enum { ...@@ -299,35 +356,16 @@ enum {
CMD_WANT_SKB = (1 << 2), CMD_WANT_SKB = (1 << 2),
}; };
struct iwl_cmd;
struct iwl_priv;
struct iwl_cmd_meta {
struct iwl_cmd_meta *source;
union {
struct sk_buff *skb;
int (*callback)(struct iwl_priv *priv,
struct iwl_cmd *cmd, struct sk_buff *skb);
} __attribute__ ((packed)) u;
/* The CMD_SIZE_HUGE flag bit indicates that the command
* structure is stored at the end of the shared queue memory. */
u32 flags;
DECLARE_PCI_UNMAP_ADDR(mapping)
DECLARE_PCI_UNMAP_LEN(len)
} __attribute__ ((packed));
#define IWL_CMD_MAX_PAYLOAD 320 #define IWL_CMD_MAX_PAYLOAD 320
/** /**
* struct iwl_cmd * struct iwl_device_cmd
* *
* For allocation of the command and tx queues, this establishes the overall * For allocation of the command and tx queues, this establishes the overall
* size of the largest command we send to uCode, except for a scan command * size of the largest command we send to uCode, except for a scan command
* (which is relatively huge; space is allocated separately). * (which is relatively huge; space is allocated separately).
*/ */
struct iwl_cmd { struct iwl_device_cmd {
struct iwl_cmd_meta meta; /* driver data */
struct iwl_cmd_header hdr; /* uCode API */ struct iwl_cmd_header hdr; /* uCode API */
union { union {
u32 flags; u32 flags;
...@@ -339,17 +377,20 @@ struct iwl_cmd { ...@@ -339,17 +377,20 @@ struct iwl_cmd {
} __attribute__ ((packed)) cmd; } __attribute__ ((packed)) cmd;
} __attribute__ ((packed)); } __attribute__ ((packed));
#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
struct iwl_host_cmd { struct iwl_host_cmd {
u8 id;
u16 len;
struct iwl_cmd_meta meta;
const void *data; const void *data;
struct sk_buff *reply_skb;
void (*callback)(struct iwl_priv *priv,
struct iwl_device_cmd *cmd,
struct sk_buff *skb);
u32 flags;
u16 len;
u8 id;
}; };
#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_cmd) - \
sizeof(struct iwl_cmd_meta))
/* /*
* RX related structures and functions * RX related structures and functions
*/ */
...@@ -450,8 +491,16 @@ union iwl_ht_rate_supp { ...@@ -450,8 +491,16 @@ union iwl_ht_rate_supp {
}; };
#define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3) #define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3)
#define CFG_HT_MPDU_DENSITY_2USEC (0x5)
#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_2USEC /*
* Maximal MPDU density for TX aggregation
* 4 - 2us density
* 5 - 4us density
* 6 - 8us density
* 7 - 16us density
*/
#define CFG_HT_MPDU_DENSITY_4USEC (0x5)
#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC
struct iwl_ht_info { struct iwl_ht_info {
/* self configuration data */ /* self configuration data */
...@@ -630,6 +679,8 @@ struct iwl_hw_params { ...@@ -630,6 +679,8 @@ struct iwl_hw_params {
u32 max_data_size; u32 max_data_size;
u32 max_bsm_size; u32 max_bsm_size;
u32 ct_kill_threshold; /* value in hw-dependent units */ u32 ct_kill_threshold; /* value in hw-dependent units */
u32 ct_kill_exit_threshold; /* value in hw-dependent units */
/* for 1000, 6000 series and up */
u32 calib_init_cfg; u32 calib_init_cfg;
const struct iwl_sensitivity_ranges *sens; const struct iwl_sensitivity_ranges *sens;
}; };
...@@ -1113,6 +1164,7 @@ struct iwl_priv { ...@@ -1113,6 +1164,7 @@ struct iwl_priv {
/* debugging info */ /* debugging info */
u32 framecnt_to_us; u32 framecnt_to_us;
atomic_t restrict_refcnt; atomic_t restrict_refcnt;
bool disable_ht40;
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
/* debugfs */ /* debugfs */
struct iwl_debugfs *dbgfs; struct iwl_debugfs *dbgfs;
......
...@@ -91,8 +91,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) ...@@ -91,8 +91,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
.id = REPLY_LEDS_CMD, .id = REPLY_LEDS_CMD,
.len = sizeof(struct iwl_led_cmd), .len = sizeof(struct iwl_led_cmd),
.data = led_cmd, .data = led_cmd,
.meta.flags = CMD_ASYNC, .flags = CMD_ASYNC,
.meta.u.callback = NULL, .callback = NULL,
}; };
u32 reg; u32 reg;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册