Merge branch 'for-davem' of git://git.infradead.org/users/linville/wireless-next

This commit is contained in:
David S. Miller 2011-09-16 15:14:19 -04:00
commit 9c223f9bba
100 changed files with 7763 additions and 6471 deletions

View file

@ -178,23 +178,29 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry);
void ath_hw_cycle_counters_update(struct ath_common *common); void ath_hw_cycle_counters_update(struct ath_common *common);
int32_t ath_hw_get_listen_time(struct ath_common *common); int32_t ath_hw_get_listen_time(struct ath_common *common);
extern __attribute__ ((format (printf, 3, 4))) int extern __attribute__((format (printf, 2, 3)))
ath_printk(const char *level, struct ath_common *common, const char *fmt, ...); void ath_printk(const char *level, const char *fmt, ...);
#define _ath_printk(level, common, fmt, ...) \
do { \
__always_unused struct ath_common *unused = common; \
ath_printk(level, fmt, ##__VA_ARGS__); \
} while (0)
#define ath_emerg(common, fmt, ...) \ #define ath_emerg(common, fmt, ...) \
ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__) _ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__)
#define ath_alert(common, fmt, ...) \ #define ath_alert(common, fmt, ...) \
ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__) _ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__)
#define ath_crit(common, fmt, ...) \ #define ath_crit(common, fmt, ...) \
ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__) _ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__)
#define ath_err(common, fmt, ...) \ #define ath_err(common, fmt, ...) \
ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__) _ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__)
#define ath_warn(common, fmt, ...) \ #define ath_warn(common, fmt, ...) \
ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__) _ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__)
#define ath_notice(common, fmt, ...) \ #define ath_notice(common, fmt, ...) \
ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__) _ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__)
#define ath_info(common, fmt, ...) \ #define ath_info(common, fmt, ...) \
ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__) _ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__)
/** /**
* enum ath_debug_level - atheros wireless debug level * enum ath_debug_level - atheros wireless debug level
@ -247,26 +253,20 @@ enum ATH_DEBUG {
#ifdef CONFIG_ATH_DEBUG #ifdef CONFIG_ATH_DEBUG
#define ath_dbg(common, dbg_mask, fmt, ...) \ #define ath_dbg(common, dbg_mask, fmt, ...) \
({ \ do { \
int rtn; \
if ((common)->debug_mask & dbg_mask) \ if ((common)->debug_mask & dbg_mask) \
rtn = ath_printk(KERN_DEBUG, common, fmt, \ _ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \
##__VA_ARGS__); \ } while (0)
else \
rtn = 0; \
\
rtn; \
})
#define ATH_DBG_WARN(foo, arg...) WARN(foo, arg) #define ATH_DBG_WARN(foo, arg...) WARN(foo, arg)
#define ATH_DBG_WARN_ON_ONCE(foo) WARN_ON_ONCE(foo) #define ATH_DBG_WARN_ON_ONCE(foo) WARN_ON_ONCE(foo)
#else #else
static inline __attribute__ ((format (printf, 3, 4))) int static inline __attribute__((format (printf, 3, 4)))
ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask, void ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask,
const char *fmt, ...) const char *fmt, ...)
{ {
return 0;
} }
#define ATH_DBG_WARN(foo, arg...) do {} while (0) #define ATH_DBG_WARN(foo, arg...) do {} while (0)
#define ATH_DBG_WARN_ON_ONCE(foo) ({ \ #define ATH_DBG_WARN_ON_ONCE(foo) ({ \

View file

@ -643,7 +643,7 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
listenTime = ath_hw_get_listen_time(common); listenTime = ath_hw_get_listen_time(common);
if (listenTime <= 0) { if (listenTime <= 0) {
ah->stats.ast_ani_lneg++; ah->stats.ast_ani_lneg_or_lzero++;
ath9k_ani_restart(ah); ath9k_ani_restart(ah);
return false; return false;
} }

View file

@ -148,8 +148,7 @@ struct ar5416Stats {
u32 ast_ani_ofdmerrs; u32 ast_ani_ofdmerrs;
u32 ast_ani_cckerrs; u32 ast_ani_cckerrs;
u32 ast_ani_reset; u32 ast_ani_reset;
u32 ast_ani_lzero; u32 ast_ani_lneg_or_lzero;
u32 ast_ani_lneg;
u32 avgbrssi; u32 avgbrssi;
struct ath9k_mib_stats ast_mibstats; struct ath9k_mib_stats ast_mibstats;
}; };
@ -159,7 +158,5 @@ void ath9k_enable_mib_counters(struct ath_hw *ah);
void ath9k_hw_disable_mib_counters(struct ath_hw *ah); void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
void ath9k_hw_ani_setup(struct ath_hw *ah); void ath9k_hw_ani_setup(struct ath_hw *ah);
void ath9k_hw_ani_init(struct ath_hw *ah); void ath9k_hw_ani_init(struct ath_hw *ah);
int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
struct ath9k_channel *chan);
#endif /* ANI_H */ #endif /* ANI_H */

View file

@ -273,7 +273,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
u32 pktLen, enum ath9k_pkt_type type, u32 pktLen, enum ath9k_pkt_type type,
u32 txPower, u32 keyIx, u32 txPower, u8 keyIx,
enum ath9k_key_type keyType, u32 flags) enum ath9k_key_type keyType, u32 flags)
{ {
struct ar5416_desc *ads = AR5416DESC(ds); struct ar5416_desc *ads = AR5416DESC(ds);

View file

@ -3318,7 +3318,7 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
word = kzalloc(2048, GFP_KERNEL); word = kzalloc(2048, GFP_KERNEL);
if (!word) if (!word)
return -1; return -ENOMEM;
memcpy(mptr, &ar9300_default, mdata_size); memcpy(mptr, &ar9300_default, mdata_size);

View file

@ -312,7 +312,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
u32 pktlen, enum ath9k_pkt_type type, u32 txpower, u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
u32 keyIx, enum ath9k_key_type keyType, u32 flags) u8 keyIx, enum ath9k_key_type keyType, u32 flags)
{ {
struct ar9003_txc *ads = (struct ar9003_txc *) ds; struct ar9003_txc *ads = (struct ar9003_txc *) ds;

View file

@ -206,16 +206,17 @@ struct ath_atx_ac {
}; };
struct ath_frame_info { struct ath_frame_info {
struct ath_buf *bf;
int framelen; int framelen;
u32 keyix;
enum ath9k_key_type keytype; enum ath9k_key_type keytype;
u8 keyix;
u8 retries; u8 retries;
u16 seqno;
}; };
struct ath_buf_state { struct ath_buf_state {
u8 bf_type; u8 bf_type;
u8 bfs_paprd; u8 bfs_paprd;
u16 seqno;
unsigned long bfs_paprd_timestamp; unsigned long bfs_paprd_timestamp;
}; };
@ -235,7 +236,7 @@ struct ath_buf {
struct ath_atx_tid { struct ath_atx_tid {
struct list_head list; struct list_head list;
struct list_head buf_q; struct sk_buff_head buf_q;
struct ath_node *an; struct ath_node *an;
struct ath_atx_ac *ac; struct ath_atx_ac *ac;
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];

View file

@ -711,7 +711,7 @@ static ssize_t read_file_stations(struct file *file, char __user *user_buf,
" tid: %p %s %s %i %p %p\n", " tid: %p %s %s %i %p %p\n",
tid, tid->sched ? "sched" : "idle", tid, tid->sched ? "sched" : "idle",
tid->paused ? "paused" : "running", tid->paused ? "paused" : "running",
list_empty(&tid->buf_q), skb_queue_empty(&tid->buf_q),
tid->an, tid->ac); tid->an, tid->ac);
if (len >= size) if (len >= size)
goto done; goto done;
@ -828,6 +828,8 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, struct ath_txq *txq) struct ath_tx_status *ts, struct ath_txq *txq)
{ {
#define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\
[sc->debug.tsidx].c)
int qnum = txq->axq_qnum; int qnum = txq->axq_qnum;
TX_STAT_INC(qnum, tx_pkts_all); TX_STAT_INC(qnum, tx_pkts_all);
@ -857,6 +859,26 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
TX_STAT_INC(qnum, data_underrun); TX_STAT_INC(qnum, data_underrun);
if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
TX_STAT_INC(qnum, delim_underrun); TX_STAT_INC(qnum, delim_underrun);
spin_lock(&sc->debug.samp_lock);
TX_SAMP_DBG(jiffies) = jiffies;
TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0;
TX_SAMP_DBG(rssi_ctl1) = ts->ts_rssi_ctl1;
TX_SAMP_DBG(rssi_ctl2) = ts->ts_rssi_ctl2;
TX_SAMP_DBG(rssi_ext0) = ts->ts_rssi_ext0;
TX_SAMP_DBG(rssi_ext1) = ts->ts_rssi_ext1;
TX_SAMP_DBG(rssi_ext2) = ts->ts_rssi_ext2;
TX_SAMP_DBG(rateindex) = ts->ts_rateindex;
TX_SAMP_DBG(isok) = !!(ts->ts_status & ATH9K_TXERR_MASK);
TX_SAMP_DBG(rts_fail_cnt) = ts->ts_shortretry;
TX_SAMP_DBG(data_fail_cnt) = ts->ts_longretry;
TX_SAMP_DBG(rssi) = ts->ts_rssi;
TX_SAMP_DBG(tid) = ts->tid;
TX_SAMP_DBG(qid) = ts->qid;
sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES;
spin_unlock(&sc->debug.samp_lock);
#undef TX_SAMP_DBG
} }
static const struct file_operations fops_xmit = { static const struct file_operations fops_xmit = {
@ -995,6 +1017,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
{ {
#define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++
#define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++
#define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\
[sc->debug.rsidx].c)
u32 phyerr; u32 phyerr;
@ -1030,8 +1054,25 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna; sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna;
spin_lock(&sc->debug.samp_lock);
RX_SAMP_DBG(jiffies) = jiffies;
RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1;
RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2;
RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0;
RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1;
RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2;
RX_SAMP_DBG(antenna) = rs->rs_antenna;
RX_SAMP_DBG(rssi) = rs->rs_rssi;
RX_SAMP_DBG(rate) = rs->rs_rate;
RX_SAMP_DBG(is_mybeacon) = rs->is_mybeacon;
sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES;
spin_unlock(&sc->debug.samp_lock);
#undef RX_STAT_INC #undef RX_STAT_INC
#undef RX_PHY_ERR_INC #undef RX_PHY_ERR_INC
#undef RX_SAMP_DBG
} }
static const struct file_operations fops_recv = { static const struct file_operations fops_recv = {
@ -1272,6 +1313,269 @@ static const struct file_operations fops_modal_eeprom = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
{
#define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
unsigned long flags;
int i;
ath9k_ps_wakeup(sc);
spin_lock_irqsave(&common->cc_lock, flags);
ath_hw_cycle_counters_update(common);
spin_unlock_irqrestore(&common->cc_lock, flags);
spin_lock_bh(&sc->debug.samp_lock);
ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles;
ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy;
ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame;
ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame;
ATH_SAMP_DBG(noise) = ah->noise;
REG_WRITE_D(ah, AR_MACMISC,
((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
(AR_MACMISC_MISC_OBS_BUS_1 <<
AR_MACMISC_MISC_OBS_BUS_MSB_S)));
for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
ATH_SAMP_DBG(dma_dbg_reg_vals[i]) = REG_READ_D(ah,
AR_DMADBG_0 + (i * sizeof(u32)));
ATH_SAMP_DBG(pcu_obs) = REG_READ_D(ah, AR_OBS_BUS_1);
ATH_SAMP_DBG(pcu_cr) = REG_READ_D(ah, AR_CR);
memcpy(ATH_SAMP_DBG(nfCalHist), sc->caldata.nfCalHist,
sizeof(ATH_SAMP_DBG(nfCalHist)));
sc->debug.sampidx = (sc->debug.sampidx + 1) % ATH_DBG_MAX_SAMPLES;
spin_unlock_bh(&sc->debug.samp_lock);
ath9k_ps_restore(sc);
#undef ATH_SAMP_DBG
}
static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
{
#define ATH_SAMP_DBG(c) bb_mac_samp[sampidx].c
struct ath_softc *sc = inode->i_private;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
struct ath_dbg_bb_mac_samp *bb_mac_samp;
struct ath9k_nfcal_hist *h;
int i, j, qcuOffset = 0, dcuOffset = 0;
u32 *qcuBase, *dcuBase, size = 30000, len = 0;
u32 sampidx = 0;
u8 *buf;
u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
u8 nread;
buf = vmalloc(size);
if (!buf)
return -ENOMEM;
bb_mac_samp = vmalloc(sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
if (!bb_mac_samp) {
vfree(buf);
return -ENOMEM;
}
spin_lock_bh(&sc->debug.samp_lock);
memcpy(bb_mac_samp, sc->debug.bb_mac_samp,
sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
spin_unlock_bh(&sc->debug.samp_lock);
len += snprintf(buf + len, size - len,
"Raw DMA Debug Dump:\n");
len += snprintf(buf + len, size - len, "Sample |\t");
for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
len += snprintf(buf + len, size - len, " DMA Reg%d |\t", i);
len += snprintf(buf + len, size - len, "\n");
for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
len += snprintf(buf + len, size - len, "%d\t", sampidx);
for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
len += snprintf(buf + len, size - len, " %08x\t",
ATH_SAMP_DBG(dma_dbg_reg_vals[i]));
len += snprintf(buf + len, size - len, "\n");
}
len += snprintf(buf + len, size - len, "\n");
len += snprintf(buf + len, size - len,
"Sample Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]);
dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]);
for (i = 0; i < ATH9K_NUM_QUEUES; i++,
qcuOffset += 4, dcuOffset += 5) {
if (i == 8) {
qcuOffset = 0;
qcuBase++;
}
if (i == 6) {
dcuOffset = 0;
dcuBase++;
}
if (!sc->debug.stats.txstats[i].queued)
continue;
len += snprintf(buf + len, size - len,
"%4d %7d %2x %1x %2x %2x\n",
sampidx, i,
(*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
(*qcuBase & (0x8 << qcuOffset)) >>
(qcuOffset + 3),
ATH_SAMP_DBG(dma_dbg_reg_vals[2]) &
(0x7 << (i * 3)) >> (i * 3),
(*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
}
len += snprintf(buf + len, size - len, "\n");
}
len += snprintf(buf + len, size - len,
"samp qcu_sh qcu_fh qcu_comp dcu_comp dcu_arb dcu_fp "
"ch_idle_dur ch_idle_dur_val txfifo_val0 txfifo_val1 "
"txfifo_dcu0 txfifo_dcu1 pcu_obs AR_CR\n");
for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]);
dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]);
len += snprintf(buf + len, size - len, "%4d %5x %5x ", sampidx,
(ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x003c0000) >> 18,
(ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x03c00000) >> 22);
len += snprintf(buf + len, size - len, "%7x %8x ",
(ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x1c000000) >> 26,
(ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x3));
len += snprintf(buf + len, size - len, "%7x %7x ",
(ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x06000000) >> 25,
(ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x38000000) >> 27);
len += snprintf(buf + len, size - len, "%7d %12d ",
(ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x000003fc) >> 2,
(ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000400) >> 10);
len += snprintf(buf + len, size - len, "%12d %12d ",
(ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000800) >> 11,
(ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00001000) >> 12);
len += snprintf(buf + len, size - len, "%12d %12d ",
(ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x0001e000) >> 13,
(ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x001e0000) >> 17);
len += snprintf(buf + len, size - len, "0x%07x 0x%07x\n",
ATH_SAMP_DBG(pcu_obs), ATH_SAMP_DBG(pcu_cr));
}
len += snprintf(buf + len, size - len,
"Sample ChNoise Chain privNF #Reading Readings\n");
for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
h = ATH_SAMP_DBG(nfCalHist);
if (!ATH_SAMP_DBG(noise))
continue;
for (i = 0; i < NUM_NF_READINGS; i++) {
if (!(chainmask & (1 << i)) ||
((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
continue;
nread = AR_PHY_CCA_FILTERWINDOW_LENGTH -
h[i].invalidNFcount;
len += snprintf(buf + len, size - len,
"%4d %5d %4d\t %d\t %d\t",
sampidx, ATH_SAMP_DBG(noise),
i, h[i].privNF, nread);
for (j = 0; j < nread; j++)
len += snprintf(buf + len, size - len,
" %d", h[i].nfCalBuffer[j]);
len += snprintf(buf + len, size - len, "\n");
}
}
len += snprintf(buf + len, size - len, "\nCycle counters:\n"
"Sample Total Rxbusy Rxframes Txframes\n");
for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
if (!ATH_SAMP_DBG(cc.cycles))
continue;
len += snprintf(buf + len, size - len,
"%4d %08x %08x %08x %08x\n",
sampidx, ATH_SAMP_DBG(cc.cycles),
ATH_SAMP_DBG(cc.rx_busy),
ATH_SAMP_DBG(cc.rx_frame),
ATH_SAMP_DBG(cc.tx_frame));
}
len += snprintf(buf + len, size - len, "Tx status Dump :\n");
len += snprintf(buf + len, size - len,
"Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb "
"isok rts_fail data_fail rate tid qid tx_before(ms)\n");
for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
if (!ATH_SAMP_DBG(ts[i].jiffies))
continue;
len += snprintf(buf + len, size - len, "%4d \t"
"%8d %4d %4d %4d %4d %4d %4d %4d %4d "
"%4d %4d %2d %2d %d\n",
sampidx,
ATH_SAMP_DBG(ts[i].rssi_ctl0),
ATH_SAMP_DBG(ts[i].rssi_ctl1),
ATH_SAMP_DBG(ts[i].rssi_ctl2),
ATH_SAMP_DBG(ts[i].rssi_ext0),
ATH_SAMP_DBG(ts[i].rssi_ext1),
ATH_SAMP_DBG(ts[i].rssi_ext2),
ATH_SAMP_DBG(ts[i].rssi),
ATH_SAMP_DBG(ts[i].isok),
ATH_SAMP_DBG(ts[i].rts_fail_cnt),
ATH_SAMP_DBG(ts[i].data_fail_cnt),
ATH_SAMP_DBG(ts[i].rateindex),
ATH_SAMP_DBG(ts[i].tid),
ATH_SAMP_DBG(ts[i].qid),
jiffies_to_msecs(jiffies -
ATH_SAMP_DBG(ts[i].jiffies)));
}
}
len += snprintf(buf + len, size - len, "Rx status Dump :\n");
len += snprintf(buf + len, size - len, "Sample rssi:- ctl0 ctl1 ctl2 "
"ext0 ext1 ext2 comb beacon ant rate rx_before(ms)\n");
for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
if (!ATH_SAMP_DBG(rs[i].jiffies))
continue;
len += snprintf(buf + len, size - len, "%4d \t"
"%8d %4d %4d %4d %4d %4d %4d %s %4d %02x %d\n",
sampidx,
ATH_SAMP_DBG(rs[i].rssi_ctl0),
ATH_SAMP_DBG(rs[i].rssi_ctl1),
ATH_SAMP_DBG(rs[i].rssi_ctl2),
ATH_SAMP_DBG(rs[i].rssi_ext0),
ATH_SAMP_DBG(rs[i].rssi_ext1),
ATH_SAMP_DBG(rs[i].rssi_ext2),
ATH_SAMP_DBG(rs[i].rssi),
ATH_SAMP_DBG(rs[i].is_mybeacon) ?
"True" : "False",
ATH_SAMP_DBG(rs[i].antenna),
ATH_SAMP_DBG(rs[i].rate),
jiffies_to_msecs(jiffies -
ATH_SAMP_DBG(rs[i].jiffies)));
}
}
vfree(bb_mac_samp);
file->private_data = buf;
return 0;
#undef ATH_SAMP_DBG
}
static const struct file_operations fops_samps = {
.open = open_file_bb_mac_samps,
.read = ath9k_debugfs_read_buf,
.release = ath9k_debugfs_release_buf,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
int ath9k_init_debug(struct ath_hw *ah) int ath9k_init_debug(struct ath_hw *ah)
{ {
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
@ -1321,6 +1625,8 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_base_eeprom); &fops_base_eeprom);
debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_modal_eeprom); &fops_modal_eeprom);
debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_samps);
debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
@ -1329,5 +1635,9 @@ int ath9k_init_debug(struct ath_hw *ah)
sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
sc->debug.regidx = 0; sc->debug.regidx = 0;
memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp));
sc->debug.sampidx = 0;
sc->debug.tsidx = 0;
sc->debug.rsidx = 0;
return 0; return 0;
} }

View file

@ -177,14 +177,57 @@ struct ath_stats {
struct ath_rx_stats rxstats; struct ath_rx_stats rxstats;
}; };
#define ATH_DBG_MAX_SAMPLES 10
struct ath_dbg_bb_mac_samp {
u32 dma_dbg_reg_vals[ATH9K_NUM_DMA_DEBUG_REGS];
u32 pcu_obs, pcu_cr, noise;
struct {
u64 jiffies;
int8_t rssi_ctl0;
int8_t rssi_ctl1;
int8_t rssi_ctl2;
int8_t rssi_ext0;
int8_t rssi_ext1;
int8_t rssi_ext2;
int8_t rssi;
bool isok;
u8 rts_fail_cnt;
u8 data_fail_cnt;
u8 rateindex;
u8 qid;
u8 tid;
} ts[ATH_DBG_MAX_SAMPLES];
struct {
u64 jiffies;
int8_t rssi_ctl0;
int8_t rssi_ctl1;
int8_t rssi_ctl2;
int8_t rssi_ext0;
int8_t rssi_ext1;
int8_t rssi_ext2;
int8_t rssi;
bool is_mybeacon;
u8 antenna;
u8 rate;
} rs[ATH_DBG_MAX_SAMPLES];
struct ath_cycle_counters cc;
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
};
struct ath9k_debug { struct ath9k_debug {
struct dentry *debugfs_phy; struct dentry *debugfs_phy;
u32 regidx; u32 regidx;
struct ath_stats stats; struct ath_stats stats;
spinlock_t samp_lock;
struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES];
u8 sampidx;
u8 tsidx;
u8 rsidx;
}; };
int ath9k_init_debug(struct ath_hw *ah); int ath9k_init_debug(struct ath_hw *ah);
void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
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_tx(struct ath_softc *sc, struct ath_buf *bf, void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, struct ath_txq *txq); struct ath_tx_status *ts, struct ath_txq *txq);
@ -197,6 +240,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
return 0; return 0;
} }
static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
{
}
static inline void ath_debug_stat_interrupt(struct ath_softc *sc, static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
enum ath9k_int status) enum ath9k_int status)
{ {

View file

@ -1300,6 +1300,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
if (priv->op_flags & OP_INVALID) { if (priv->op_flags & OP_INVALID) {
ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY, ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY,
"Unable to configure filter on invalid state\n"); "Unable to configure filter on invalid state\n");
mutex_unlock(&priv->mutex);
return; return;
} }
ath9k_htc_ps_wakeup(priv); ath9k_htc_ps_wakeup(priv);

View file

@ -440,7 +440,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
if (AR_SREV_9100(ah)) if (AR_SREV_9100(ah))
ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX;
ah->enable_32kHz_clock = DONT_USE_32KHZ; ah->enable_32kHz_clock = DONT_USE_32KHZ;
ah->slottime = 20; ah->slottime = ATH9K_SLOT_TIME_9;
ah->globaltxtimeout = (u32) -1; ah->globaltxtimeout = (u32) -1;
ah->power_mode = ATH9K_PM_UNDEFINED; ah->power_mode = ATH9K_PM_UNDEFINED;
} }
@ -997,8 +997,14 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
slottime = 21; slottime = 21;
sifstime = 64; sifstime = 64;
} else { } else {
eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/common->clockrate; if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO;
reg = AR_USEC_ASYNC_FIFO;
} else {
eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/
common->clockrate;
reg = REG_READ(ah, AR_USEC); reg = REG_READ(ah, AR_USEC);
}
rx_lat = MS(reg, AR_USEC_RX_LAT); rx_lat = MS(reg, AR_USEC_RX_LAT);
tx_lat = MS(reg, AR_USEC_TX_LAT); tx_lat = MS(reg, AR_USEC_TX_LAT);
@ -2754,6 +2760,7 @@ static struct {
{ AR_SREV_VERSION_9271, "9271" }, { AR_SREV_VERSION_9271, "9271" },
{ AR_SREV_VERSION_9300, "9300" }, { AR_SREV_VERSION_9300, "9300" },
{ AR_SREV_VERSION_9330, "9330" }, { AR_SREV_VERSION_9330, "9330" },
{ AR_SREV_VERSION_9340, "9340" },
{ AR_SREV_VERSION_9485, "9485" }, { AR_SREV_VERSION_9485, "9485" },
}; };

View file

@ -623,7 +623,7 @@ struct ath_hw_ops {
struct ath_tx_status *ts); struct ath_tx_status *ts);
void (*set11n_txdesc)(struct ath_hw *ah, void *ds, void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
u32 pktLen, enum ath9k_pkt_type type, u32 pktLen, enum ath9k_pkt_type type,
u32 txPower, u32 keyIx, u32 txPower, u8 keyIx,
enum ath9k_key_type keyType, enum ath9k_key_type keyType,
u32 flags); u32 flags);
void (*set11n_ratescenario)(struct ath_hw *ah, void *ds, void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,

View file

@ -572,6 +572,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
mutex_init(&sc->mutex); mutex_init(&sc->mutex);
#ifdef CONFIG_ATH9K_DEBUGFS #ifdef CONFIG_ATH9K_DEBUGFS
spin_lock_init(&sc->nodes_lock); spin_lock_init(&sc->nodes_lock);
spin_lock_init(&sc->debug.samp_lock);
INIT_LIST_HEAD(&sc->nodes); INIT_LIST_HEAD(&sc->nodes);
#endif #endif
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);

View file

@ -146,6 +146,7 @@ struct ath_rx_status {
u8 rs_moreaggr; u8 rs_moreaggr;
u8 rs_num_delims; u8 rs_num_delims;
u8 rs_flags; u8 rs_flags;
bool is_mybeacon;
u32 evm0; u32 evm0;
u32 evm1; u32 evm1;
u32 evm2; u32 evm2;
@ -194,7 +195,7 @@ struct ath_htc_rx_status {
#define ATH9K_RX_DECRYPT_BUSY 0x40 #define ATH9K_RX_DECRYPT_BUSY 0x40
#define ATH9K_RXKEYIX_INVALID ((u8)-1) #define ATH9K_RXKEYIX_INVALID ((u8)-1)
#define ATH9K_TXKEYIX_INVALID ((u32)-1) #define ATH9K_TXKEYIX_INVALID ((u8)-1)
enum ath9k_phyerr { enum ath9k_phyerr {
ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */ ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */

View file

@ -546,6 +546,7 @@ set_timer:
* The interval must be the shortest necessary to satisfy ANI, * The interval must be the shortest necessary to satisfy ANI,
* short calibration and long calibration. * short calibration and long calibration.
*/ */
ath9k_debug_samp_bb_mac(sc);
cal_interval = ATH_LONG_CALINTERVAL; cal_interval = ATH_LONG_CALINTERVAL;
if (sc->sc_ah->config.enable_ani) if (sc->sc_ah->config.enable_ani)
cal_interval = min(cal_interval, cal_interval = min(cal_interval,
@ -978,6 +979,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
sc->hw_busy_count = 0; sc->hw_busy_count = 0;
ath9k_debug_samp_bb_mac(sc);
/* Stop ANI */ /* Stop ANI */
del_timer_sync(&common->ani.timer); del_timer_sync(&common->ani.timer);

View file

@ -937,7 +937,7 @@ static int ath9k_process_rate(struct ath_common *common,
* No valid hardware bitrate found -- we should not get here * No valid hardware bitrate found -- we should not get here
* because hardware has already validated this frame as OK. * because hardware has already validated this frame as OK.
*/ */
ath_dbg(common, ATH_DBG_XMIT, ath_dbg(common, ATH_DBG_ANY,
"unsupported hw bitrate detected 0x%02x using 1 Mbit\n", "unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
rx_stats->rs_rate); rx_stats->rs_rate);
@ -952,23 +952,12 @@ static void ath9k_process_rssi(struct ath_common *common,
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_hw *ah = common->ah; struct ath_hw *ah = common->ah;
int last_rssi; int last_rssi;
__le16 fc;
if ((ah->opmode != NL80211_IFTYPE_STATION) && if (!rx_stats->is_mybeacon ||
(ah->opmode != NL80211_IFTYPE_ADHOC)) ((ah->opmode != NL80211_IFTYPE_STATION) &&
(ah->opmode != NL80211_IFTYPE_ADHOC)))
return; return;
fc = hdr->frame_control;
if (!ieee80211_is_beacon(fc) ||
compare_ether_addr(hdr->addr3, common->curbssid)) {
/* TODO: This doesn't work well if you have stations
* associated to two different APs because curbssid
* is just the last AP that any of the stations associated
* with.
*/
return;
}
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi); ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi);
@ -1838,6 +1827,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
rxs = IEEE80211_SKB_RXCB(hdr_skb); rxs = IEEE80211_SKB_RXCB(hdr_skb);
if (ieee80211_is_beacon(hdr->frame_control) &&
!compare_ether_addr(hdr->addr3, common->curbssid))
rs.is_mybeacon = true;
else
rs.is_mybeacon = false;
ath_debug_stat_rx(sc, &rs); ath_debug_stat_rx(sc, &rs);

View file

@ -619,6 +619,7 @@
#define AR_D_GBL_IFS_EIFS 0x10b0 #define AR_D_GBL_IFS_EIFS 0x10b0
#define AR_D_GBL_IFS_EIFS_M 0x0000FFFF #define AR_D_GBL_IFS_EIFS_M 0x0000FFFF
#define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 #define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000
#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO 363
#define AR_D_GBL_IFS_MISC 0x10f0 #define AR_D_GBL_IFS_MISC 0x10f0
#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007
@ -1503,6 +1504,7 @@ enum {
#define AR_USEC_TX_LAT_S 14 #define AR_USEC_TX_LAT_S 14
#define AR_USEC_RX_LAT 0x1F800000 #define AR_USEC_RX_LAT 0x1F800000
#define AR_USEC_RX_LAT_S 23 #define AR_USEC_RX_LAT_S 23
#define AR_USEC_ASYNC_FIFO 0x12E00074
#define AR_RESET_TSF 0x8020 #define AR_RESET_TSF 0x8020
#define AR_RESET_TSF_ONCE 0x01000000 #define AR_RESET_TSF_ONCE 0x01000000

View file

@ -48,8 +48,9 @@ static u16 bits_per_symbol[][2] = {
#define IS_HT_RATE(_rate) ((_rate) & 0x80) #define IS_HT_RATE(_rate) ((_rate) & 0x80)
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,
struct ath_atx_tid *tid, struct ath_atx_tid *tid, struct sk_buff *skb);
struct list_head *bf_head); static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
int tx_flags, struct ath_txq *txq);
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 ath_txq *txq, struct list_head *bf_q,
struct ath_tx_status *ts, int txok, int sendbar); struct ath_tx_status *ts, int txok, int sendbar);
@ -61,6 +62,10 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
int txok, bool update_rc); int txok, bool update_rc);
static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
int seqno); int seqno);
static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_atx_tid *tid,
struct sk_buff *skb);
enum { enum {
MCS_HT20, MCS_HT20,
@ -129,7 +134,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
tid->paused = false; tid->paused = false;
if (list_empty(&tid->buf_q)) if (skb_queue_empty(&tid->buf_q))
goto unlock; goto unlock;
ath_tx_queue_tid(txq, tid); ath_tx_queue_tid(txq, tid);
@ -149,6 +154,7 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{ {
struct ath_txq *txq = tid->ac->txq; struct ath_txq *txq = tid->ac->txq;
struct sk_buff *skb;
struct ath_buf *bf; struct ath_buf *bf;
struct list_head bf_head; struct list_head bf_head;
struct ath_tx_status ts; struct ath_tx_status ts;
@ -159,17 +165,17 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
memset(&ts, 0, sizeof(ts)); memset(&ts, 0, sizeof(ts));
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
while (!list_empty(&tid->buf_q)) { while ((skb = __skb_dequeue(&tid->buf_q))) {
bf = list_first_entry(&tid->buf_q, struct ath_buf, list); fi = get_frame_info(skb);
list_move_tail(&bf->list, &bf_head); bf = fi->bf;
spin_unlock_bh(&txq->axq_lock); spin_unlock_bh(&txq->axq_lock);
fi = get_frame_info(bf->bf_mpdu); if (bf && fi->retries) {
if (fi->retries) { list_add_tail(&bf->list, &bf_head);
ath_tx_update_baw(sc, tid, fi->seqno); ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
} else { } else {
ath_tx_send_normal(sc, txq, NULL, &bf_head); ath_tx_send_normal(sc, txq, NULL, skb);
} }
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
} }
@ -219,6 +225,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid) struct ath_atx_tid *tid)
{ {
struct sk_buff *skb;
struct ath_buf *bf; struct ath_buf *bf;
struct list_head bf_head; struct list_head bf_head;
struct ath_tx_status ts; struct ath_tx_status ts;
@ -227,16 +234,21 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
memset(&ts, 0, sizeof(ts)); memset(&ts, 0, sizeof(ts));
INIT_LIST_HEAD(&bf_head); INIT_LIST_HEAD(&bf_head);
for (;;) { while ((skb = __skb_dequeue(&tid->buf_q))) {
if (list_empty(&tid->buf_q)) fi = get_frame_info(skb);
break; bf = fi->bf;
bf = list_first_entry(&tid->buf_q, struct ath_buf, list); if (!bf) {
list_move_tail(&bf->list, &bf_head); spin_unlock(&txq->axq_lock);
ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
spin_lock(&txq->axq_lock);
continue;
}
list_add_tail(&bf->list, &bf_head);
fi = get_frame_info(bf->bf_mpdu);
if (fi->retries) if (fi->retries)
ath_tx_update_baw(sc, tid, fi->seqno); ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
spin_unlock(&txq->axq_lock); spin_unlock(&txq->axq_lock);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
@ -326,7 +338,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
while (bf) { while (bf) {
fi = get_frame_info(bf->bf_mpdu); fi = get_frame_info(bf->bf_mpdu);
ba_index = ATH_BA_INDEX(seq_st, fi->seqno); ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno);
(*nframes)++; (*nframes)++;
if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
@ -349,7 +361,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ieee80211_tx_info *tx_info; struct ieee80211_tx_info *tx_info;
struct ath_atx_tid *tid = NULL; struct ath_atx_tid *tid = NULL;
struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
struct list_head bf_head, bf_pending; struct list_head bf_head;
struct sk_buff_head bf_pending;
u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
u32 ba[WME_BA_BMP_SIZE >> 5]; u32 ba[WME_BA_BMP_SIZE >> 5];
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
@ -422,11 +435,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
} }
} }
INIT_LIST_HEAD(&bf_pending); __skb_queue_head_init(&bf_pending);
INIT_LIST_HEAD(&bf_head);
ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
while (bf) { while (bf) {
u16 seqno = bf->bf_state.seqno;
txfail = txpending = sendbar = 0; txfail = txpending = sendbar = 0;
bf_next = bf->bf_next; bf_next = bf->bf_next;
@ -434,7 +448,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
tx_info = IEEE80211_SKB_CB(skb); tx_info = IEEE80211_SKB_CB(skb);
fi = get_frame_info(skb); fi = get_frame_info(skb);
if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) { if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
/* transmit completion, subframe is /* transmit completion, subframe is
* acked by block ack */ * acked by block ack */
acked_cnt++; acked_cnt++;
@ -467,10 +481,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* Make sure the last desc is reclaimed if it * Make sure the last desc is reclaimed if it
* not a holding desc. * not a holding desc.
*/ */
if (!bf_last->bf_stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head);
else
INIT_LIST_HEAD(&bf_head); INIT_LIST_HEAD(&bf_head);
if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
bf_next != NULL || !bf_last->bf_stale)
list_move_tail(&bf->list, &bf_head);
if (!txpending || (tid->state & AGGR_CLEANUP)) { if (!txpending || (tid->state & AGGR_CLEANUP)) {
/* /*
@ -478,7 +492,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* block-ack window * block-ack window
*/ */
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
ath_tx_update_baw(sc, tid, fi->seqno); ath_tx_update_baw(sc, tid, seqno);
spin_unlock_bh(&txq->axq_lock); spin_unlock_bh(&txq->axq_lock);
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
@ -506,7 +520,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
*/ */
if (!tbf) { if (!tbf) {
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
ath_tx_update_baw(sc, tid, fi->seqno); ath_tx_update_baw(sc, tid, seqno);
spin_unlock_bh(&txq->axq_lock); spin_unlock_bh(&txq->axq_lock);
bf->bf_state.bf_type |= bf->bf_state.bf_type |=
@ -521,7 +535,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath9k_hw_cleartxdesc(sc->sc_ah, ath9k_hw_cleartxdesc(sc->sc_ah,
tbf->bf_desc); tbf->bf_desc);
list_add_tail(&tbf->list, &bf_head); fi->bf = tbf;
} else { } else {
/* /*
* Clear descriptor status words for * Clear descriptor status words for
@ -536,21 +550,21 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* Put this buffer to the temporary pending * Put this buffer to the temporary pending
* queue to retain ordering * queue to retain ordering
*/ */
list_splice_tail_init(&bf_head, &bf_pending); __skb_queue_tail(&bf_pending, skb);
} }
bf = bf_next; bf = bf_next;
} }
/* prepend un-acked frames to the beginning of the pending frame queue */ /* prepend un-acked frames to the beginning of the pending frame queue */
if (!list_empty(&bf_pending)) { if (!skb_queue_empty(&bf_pending)) {
if (an->sleeping) if (an->sleeping)
ieee80211_sta_set_tim(sta); ieee80211_sta_set_tim(sta);
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
if (clear_filter) if (clear_filter)
tid->ac->clear_ps_filter = true; tid->ac->clear_ps_filter = true;
list_splice(&bf_pending, &tid->buf_q); skb_queue_splice(&bf_pending, &tid->buf_q);
if (!an->sleeping) if (!an->sleeping)
ath_tx_queue_tid(txq, tid); ath_tx_queue_tid(txq, tid);
spin_unlock_bh(&txq->axq_lock); spin_unlock_bh(&txq->axq_lock);
@ -582,7 +596,10 @@ static bool ath_lookup_legacy(struct ath_buf *bf)
tx_info = IEEE80211_SKB_CB(skb); tx_info = IEEE80211_SKB_CB(skb);
rates = tx_info->control.rates; rates = tx_info->control.rates;
for (i = 3; i >= 0; i--) { for (i = 0; i < 4; i++) {
if (!rates[i].count || rates[i].idx < 0)
break;
if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) if (!(rates[i].flags & IEEE80211_TX_RC_MCS))
return true; return true;
} }
@ -740,22 +757,33 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
int *aggr_len) int *aggr_len)
{ {
#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
struct ath_buf *bf, *bf_first, *bf_prev = NULL; struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
int rl = 0, nframes = 0, ndelim, prev_al = 0; int rl = 0, nframes = 0, ndelim, prev_al = 0;
u16 aggr_limit = 0, al = 0, bpad = 0, u16 aggr_limit = 0, al = 0, bpad = 0,
al_delta, h_baw = tid->baw_size / 2; al_delta, h_baw = tid->baw_size / 2;
enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
struct ieee80211_tx_info *tx_info; struct ieee80211_tx_info *tx_info;
struct ath_frame_info *fi; struct ath_frame_info *fi;
struct sk_buff *skb;
bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); u16 seqno;
do { do {
bf = list_first_entry(&tid->buf_q, struct ath_buf, list); skb = skb_peek(&tid->buf_q);
fi = get_frame_info(bf->bf_mpdu); fi = get_frame_info(skb);
bf = fi->bf;
if (!fi->bf)
bf = ath_tx_setup_buffer(sc, txq, tid, skb);
if (!bf)
continue;
bf->bf_state.bf_type |= BUF_AMPDU;
seqno = bf->bf_state.seqno;
if (!bf_first)
bf_first = bf;
/* do not step over block-ack window */ /* do not step over block-ack window */
if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) { if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
status = ATH_AGGR_BAW_CLOSED; status = ATH_AGGR_BAW_CLOSED;
break; break;
} }
@ -803,9 +831,11 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
/* link buffers of this frame to the aggregate */ /* link buffers of this frame to the aggregate */
if (!fi->retries) if (!fi->retries)
ath_tx_addto_baw(sc, tid, fi->seqno); ath_tx_addto_baw(sc, tid, seqno);
ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
list_move_tail(&bf->list, bf_q);
__skb_unlink(skb, &tid->buf_q);
list_add_tail(&bf->list, bf_q);
if (bf_prev) { if (bf_prev) {
bf_prev->bf_next = bf; bf_prev->bf_next = bf;
ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc, ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
@ -813,7 +843,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
} }
bf_prev = bf; bf_prev = bf;
} while (!list_empty(&tid->buf_q)); } while (!skb_queue_empty(&tid->buf_q));
*aggr_len = al; *aggr_len = al;
@ -831,7 +861,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
int aggr_len; int aggr_len;
do { do {
if (list_empty(&tid->buf_q)) if (skb_queue_empty(&tid->buf_q))
return; return;
INIT_LIST_HEAD(&bf_q); INIT_LIST_HEAD(&bf_q);
@ -952,7 +982,7 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
if (!list_empty(&tid->buf_q)) if (!skb_queue_empty(&tid->buf_q))
buffered = true; buffered = true;
tid->sched = false; tid->sched = false;
@ -985,7 +1015,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
ac->clear_ps_filter = true; ac->clear_ps_filter = true;
if (!list_empty(&tid->buf_q) && !tid->paused) { if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
ath_tx_queue_tid(txq, tid); ath_tx_queue_tid(txq, tid);
ath_txq_schedule(sc, txq); ath_txq_schedule(sc, txq);
} }
@ -1329,7 +1359,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
* add tid to round-robin queue if more frames * add tid to round-robin queue if more frames
* are pending for the tid * are pending for the tid
*/ */
if (!list_empty(&tid->buf_q)) if (!skb_queue_empty(&tid->buf_q))
ath_tx_queue_tid(txq, tid); ath_tx_queue_tid(txq, tid);
if (tid == last_tid || if (tid == last_tid ||
@ -1421,12 +1451,11 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
} }
static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
struct ath_buf *bf, struct ath_tx_control *txctl) struct sk_buff *skb, struct ath_tx_control *txctl)
{ {
struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); struct ath_frame_info *fi = get_frame_info(skb);
struct list_head bf_head; struct list_head bf_head;
struct ath_buf *bf;
bf->bf_state.bf_type |= BUF_AMPDU;
/* /*
* 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:
@ -1435,26 +1464,30 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
* - seqno is not within block-ack window * - seqno is not within block-ack window
* - h/w queue depth exceeds low water mark * - h/w queue depth exceeds low water mark
*/ */
if (!list_empty(&tid->buf_q) || tid->paused || if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) ||
txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) { txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
/* /*
* Add this frame to software queue for scheduling later * Add this frame to software queue for scheduling later
* for aggregation. * for aggregation.
*/ */
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw); TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
list_add_tail(&bf->list, &tid->buf_q); __skb_queue_tail(&tid->buf_q, skb);
if (!txctl->an || !txctl->an->sleeping) if (!txctl->an || !txctl->an->sleeping)
ath_tx_queue_tid(txctl->txq, tid); ath_tx_queue_tid(txctl->txq, tid);
return; return;
} }
bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
if (!bf)
return;
bf->bf_state.bf_type |= BUF_AMPDU;
INIT_LIST_HEAD(&bf_head); INIT_LIST_HEAD(&bf_head);
list_add(&bf->list, &bf_head); list_add(&bf->list, &bf_head);
/* Add sub-frame to BAW */ /* Add sub-frame to BAW */
if (!fi->retries) ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
ath_tx_addto_baw(sc, tid, fi->seqno);
/* Queue to h/w without aggregation */ /* Queue to h/w without aggregation */
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw); TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
@ -1464,13 +1497,21 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
} }
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,
struct ath_atx_tid *tid, struct ath_atx_tid *tid, struct sk_buff *skb)
struct list_head *bf_head)
{ {
struct ath_frame_info *fi; struct ath_frame_info *fi = get_frame_info(skb);
struct list_head bf_head;
struct ath_buf *bf; struct ath_buf *bf;
bf = list_first_entry(bf_head, struct ath_buf, list); bf = fi->bf;
if (!bf)
bf = ath_tx_setup_buffer(sc, txq, tid, skb);
if (!bf)
return;
INIT_LIST_HEAD(&bf_head);
list_add_tail(&bf->list, &bf_head);
bf->bf_state.bf_type &= ~BUF_AMPDU; bf->bf_state.bf_type &= ~BUF_AMPDU;
/* update starting sequence number for subsequent ADDBA request */ /* update starting sequence number for subsequent ADDBA request */
@ -1478,9 +1519,8 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
INCR(tid->seq_start, IEEE80211_SEQ_MAX); INCR(tid->seq_start, IEEE80211_SEQ_MAX);
bf->bf_lastbf = bf; bf->bf_lastbf = bf;
fi = get_frame_info(bf->bf_mpdu);
ath_buf_set_rate(sc, bf, fi->framelen); ath_buf_set_rate(sc, bf, fi->framelen);
ath_tx_txqaddbuf(sc, txq, bf_head, false); ath_tx_txqaddbuf(sc, txq, &bf_head, false);
TX_STAT_INC(txq->axq_qnum, queued); TX_STAT_INC(txq->axq_qnum, queued);
} }
@ -1510,39 +1550,19 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
int framelen) int framelen)
{ {
struct ath_softc *sc = hw->priv;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = tx_info->control.sta; struct ieee80211_sta *sta = tx_info->control.sta;
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_frame_info *fi = get_frame_info(skb); struct ath_frame_info *fi = get_frame_info(skb);
struct ath_node *an = NULL; struct ath_node *an = NULL;
struct ath_atx_tid *tid;
enum ath9k_key_type keytype; enum ath9k_key_type keytype;
u16 seqno = 0;
u8 tidno;
keytype = ath9k_cmn_get_hw_crypto_keytype(skb); keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
if (sta) if (sta)
an = (struct ath_node *) sta->drv_priv; an = (struct ath_node *) sta->drv_priv;
hdr = (struct ieee80211_hdr *)skb->data;
if (an && ieee80211_is_data_qos(hdr->frame_control) &&
conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
/*
* Override seqno set by upper layer with the one
* in tx aggregation state.
*/
tid = ATH_AN_2_TID(an, tidno);
seqno = tid->seq_next;
hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
INCR(tid->seq_next, IEEE80211_SEQ_MAX);
}
memset(fi, 0, sizeof(*fi)); memset(fi, 0, sizeof(*fi));
if (hw_key) if (hw_key)
fi->keyix = hw_key->hw_key_idx; fi->keyix = hw_key->hw_key_idx;
@ -1552,7 +1572,6 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
fi->keyix = ATH9K_TXKEYIX_INVALID; fi->keyix = ATH9K_TXKEYIX_INVALID;
fi->keytype = keytype; fi->keytype = keytype;
fi->framelen = framelen; fi->framelen = framelen;
fi->seqno = seqno;
} }
static int setup_tx_flags(struct sk_buff *skb) static int setup_tx_flags(struct sk_buff *skb)
@ -1724,26 +1743,39 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
} }
static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, /*
* Assign a descriptor (and sequence number if necessary,
* and map buffer for DMA. Frees skb on error
*/
static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
struct ath_txq *txq, struct ath_txq *txq,
struct ath_atx_tid *tid,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_frame_info *fi = get_frame_info(skb); struct ath_frame_info *fi = get_frame_info(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_buf *bf; struct ath_buf *bf;
struct ath_desc *ds; struct ath_desc *ds;
int frm_type; int frm_type;
u16 seqno;
bf = ath_tx_get_buffer(sc); bf = ath_tx_get_buffer(sc);
if (!bf) { if (!bf) {
ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n"); ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n");
return NULL; goto error;
} }
ATH_TXBUF_RESET(bf); ATH_TXBUF_RESET(bf);
if (tid) {
seqno = tid->seq_next;
hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
INCR(tid->seq_next, IEEE80211_SEQ_MAX);
bf->bf_state.seqno = seqno;
}
bf->bf_flags = setup_tx_flags(skb); bf->bf_flags = setup_tx_flags(skb);
bf->bf_mpdu = skb; bf->bf_mpdu = skb;
@ -1755,7 +1787,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
ath_err(ath9k_hw_common(sc->sc_ah), ath_err(ath9k_hw_common(sc->sc_ah),
"dma_mapping_error() on TX\n"); "dma_mapping_error() on TX\n");
ath_tx_return_buffer(sc, bf); ath_tx_return_buffer(sc, bf);
return NULL; goto error;
} }
frm_type = get_hw_packet_type(skb); frm_type = get_hw_packet_type(skb);
@ -1774,19 +1806,23 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
bf->bf_buf_addr, bf->bf_buf_addr,
txq->axq_qnum); txq->axq_qnum);
fi->bf = bf;
return bf; return bf;
error:
dev_kfree_skb_any(skb);
return NULL;
} }
/* FIXME: tx power */ /* FIXME: tx power */
static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
struct ath_tx_control *txctl) struct ath_tx_control *txctl)
{ {
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);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct list_head bf_head;
struct ath_atx_tid *tid = NULL; struct ath_atx_tid *tid = NULL;
struct ath_buf *bf;
u8 tidno; u8 tidno;
spin_lock_bh(&txctl->txq->axq_lock); spin_lock_bh(&txctl->txq->axq_lock);
@ -1804,10 +1840,11 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
* Try aggregation if it's a unicast data frame * Try aggregation if it's a unicast data frame
* and the destination is HT capable. * and the destination is HT capable.
*/ */
ath_tx_send_ampdu(sc, tid, bf, txctl); ath_tx_send_ampdu(sc, tid, skb, txctl);
} else { } else {
INIT_LIST_HEAD(&bf_head); bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
list_add_tail(&bf->list, &bf_head); if (!bf)
goto out;
bf->bf_state.bfs_paprd = txctl->paprd; bf->bf_state.bfs_paprd = txctl->paprd;
@ -1821,9 +1858,10 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); ath_tx_send_normal(sc, txctl->txq, tid, skb);
} }
out:
spin_unlock_bh(&txctl->txq->axq_lock); spin_unlock_bh(&txctl->txq->axq_lock);
} }
@ -1837,7 +1875,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_vif *vif = info->control.vif; struct ieee80211_vif *vif = info->control.vif;
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq; struct ath_txq *txq = txctl->txq;
struct ath_buf *bf;
int padpos, padsize; int padpos, padsize;
int frmlen = skb->len + FCS_LEN; int frmlen = skb->len + FCS_LEN;
int q; int q;
@ -1884,10 +1921,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
* info are no longer valid (overwritten by the ath_frame_info data. * info are no longer valid (overwritten by the ath_frame_info data.
*/ */
bf = ath_tx_setup_buffer(hw, txctl->txq, skb);
if (unlikely(!bf))
return -ENOMEM;
q = skb_get_queue_mapping(skb); q = skb_get_queue_mapping(skb);
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
if (txq == sc->tx.txq_map[q] && if (txq == sc->tx.txq_map[q] &&
@ -1897,8 +1930,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
} }
spin_unlock_bh(&txq->axq_lock); spin_unlock_bh(&txq->axq_lock);
ath_tx_start_dma(sc, bf, txctl); ath_tx_start_dma(sc, skb, txctl);
return 0; return 0;
} }
@ -2391,7 +2423,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
tid->sched = false; tid->sched = false;
tid->paused = false; tid->paused = false;
tid->state &= ~AGGR_CLEANUP; tid->state &= ~AGGR_CLEANUP;
INIT_LIST_HEAD(&tid->buf_q); __skb_queue_head_init(&tid->buf_q);
acno = TID_TO_WME_AC(tidno); acno = TID_TO_WME_AC(tidno);
tid->ac = &an->ac[acno]; tid->ac = &an->ac[acno];
tid->state &= ~AGGR_ADDBA_COMPLETE; tid->state &= ~AGGR_ADDBA_COMPLETE;

View file

@ -57,22 +57,18 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
} }
EXPORT_SYMBOL(ath_rxbuf_alloc); EXPORT_SYMBOL(ath_rxbuf_alloc);
int ath_printk(const char *level, struct ath_common *common, void ath_printk(const char *level, const char *fmt, ...)
const char *fmt, ...)
{ {
struct va_format vaf; struct va_format vaf;
va_list args; va_list args;
int rtn;
va_start(args, fmt); va_start(args, fmt);
vaf.fmt = fmt; vaf.fmt = fmt;
vaf.va = &args; vaf.va = &args;
rtn = printk("%sath: %pV", level, &vaf); printk("%sath: %pV", level, &vaf);
va_end(args); va_end(args);
return rtn;
} }
EXPORT_SYMBOL(ath_printk); EXPORT_SYMBOL(ath_printk);

View file

@ -124,12 +124,12 @@ config B43_PHY_LP
(802.11a support is optional, and currently disabled). (802.11a support is optional, and currently disabled).
config B43_PHY_HT config B43_PHY_HT
bool "Support for HT-PHY devices (BROKEN)" bool "Support for HT-PHY (high throughput) devices (EXPERIMENTAL)"
depends on B43 && BROKEN depends on B43 && EXPERIMENTAL
---help--- ---help---
Support for the HT-PHY. Support for the HT-PHY.
Say N, this is BROKEN and crashes driver. Enables support for BCM4331 and possibly other chipsets with that PHY.
config B43_PHY_LCN config B43_PHY_LCN
bool "Support for LCN-PHY devices (BROKEN)" bool "Support for LCN-PHY devices (BROKEN)"

View file

@ -419,33 +419,34 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
gfp_t flags = GFP_KERNEL; gfp_t flags = GFP_KERNEL;
/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
* alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing * alignment and 8K buffers for 64-bit DMA with 8K alignment.
* has shown that 4K is sufficient for the latter as long as the buffer * In practice we could use smaller buffers for the latter, but the
* does not cross an 8K boundary. * alignment is really important because of the hardware bug. If bit
* * 0x00001000 is used in DMA address, some hardware (like BCM4331)
* For unknown reasons - possibly a hardware error - the BCM4311 rev * copies that bit into B43_DMA64_RXSTATUS and we get false values from
* 02, which uses 64-bit DMA, needs the ring buffer in very low memory, * B43_DMA64_RXSTATDPTR. Let's just use 8K buffers even if we don't use
* which accounts for the GFP_DMA flag below. * more than 256 slots for ring.
*
* The flags here must match the flags in free_ringmemory below!
*/ */
if (ring->type == B43_DMA_64BIT) u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
flags |= GFP_DMA; B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
B43_DMA_RINGMEMSIZE, ring_mem_size, &(ring->dmabase),
&(ring->dmabase), flags); flags);
if (!ring->descbase) { if (!ring->descbase) {
b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
return -ENOMEM; return -ENOMEM;
} }
memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE); memset(ring->descbase, 0, ring_mem_size);
return 0; return 0;
} }
static void free_ringmemory(struct b43_dmaring *ring) static void free_ringmemory(struct b43_dmaring *ring)
{ {
dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
dma_free_coherent(ring->dev->dev->dma_dev, ring_mem_size,
ring->descbase, ring->dmabase); ring->descbase, ring->dmabase);
} }

View file

@ -161,7 +161,8 @@ struct b43_dmadesc_generic {
} __packed; } __packed;
/* Misc DMA constants */ /* Misc DMA constants */
#define B43_DMA_RINGMEMSIZE PAGE_SIZE #define B43_DMA32_RINGMEMSIZE 4096
#define B43_DMA64_RINGMEMSIZE 8192
/* Offset of frame with actual data */ /* Offset of frame with actual data */
#define B43_DMA0_RX_FW598_FO 38 #define B43_DMA0_RX_FW598_FO 38
#define B43_DMA0_RX_FW351_FO 30 #define B43_DMA0_RX_FW351_FO 30

View file

@ -4131,10 +4131,13 @@ out_unlock:
* because the core might be gone away while we unlocked the mutex. */ * because the core might be gone away while we unlocked the mutex. */
static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
{ {
struct b43_wl *wl = dev->wl; struct b43_wl *wl;
struct b43_wldev *orig_dev; struct b43_wldev *orig_dev;
u32 mask; u32 mask;
if (!dev)
return NULL;
wl = dev->wl;
redo: redo:
if (!dev || b43_status(dev) < B43_STAT_STARTED) if (!dev || b43_status(dev) < B43_STAT_STARTED)
return dev; return dev;

View file

@ -43,6 +43,8 @@
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-helpers.h" #include "iwl-helpers.h"
#include "iwl-agn-hw.h" #include "iwl-agn-hw.h"
#include "iwl-shared.h"
#include "iwl-pci.h"
/* Highest firmware API version supported */ /* Highest firmware API version supported */
#define IWL1000_UCODE_API_MAX 6 #define IWL1000_UCODE_API_MAX 6
@ -76,21 +78,21 @@
static void iwl1000_set_ct_threshold(struct iwl_priv *priv) static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
{ {
/* want Celsius */ /* want Celsius */
priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
} }
/* NIC configuration for 1000 series */ /* NIC configuration for 1000 series */
static void iwl1000_nic_config(struct iwl_priv *priv) static void iwl1000_nic_config(struct iwl_priv *priv)
{ {
/* set CSR_HW_CONFIG_REG for uCode use */ /* set CSR_HW_CONFIG_REG for uCode use */
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
/* Setting digital SVR for 1000 card to 1.32V */ /* Setting digital SVR for 1000 card to 1.32V */
/* locking is acquired in iwl_set_bits_mask_prph() function */ /* locking is acquired in iwl_set_bits_mask_prph() function */
iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG, iwl_set_bits_mask_prph(bus(priv), APMG_DIGITAL_SVR_REG,
APMG_SVR_DIGITAL_VOLTAGE_1_32, APMG_SVR_DIGITAL_VOLTAGE_1_32,
~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
} }
@ -127,43 +129,39 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->base_params->num_of_queues = priv->cfg->base_params->num_of_queues =
iwlagn_mod_params.num_of_queues; iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
priv->hw_params.scd_bc_tbls_size = hw_params(priv).max_stations = IWLAGN_STATION_COUNT;
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE;
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
if (priv->cfg->rx_with_siso_diversity) if (priv->cfg->rx_with_siso_diversity)
priv->hw_params.rx_chains_num = 1; hw_params(priv).rx_chains_num = 1;
else else
priv->hw_params.rx_chains_num = hw_params(priv).rx_chains_num =
num_of_ant(priv->cfg->valid_rx_ant); num_of_ant(priv->cfg->valid_rx_ant);
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
iwl1000_set_ct_threshold(priv); iwl1000_set_ct_threshold(priv);
/* Set initial sensitivity parameters */ /* Set initial sensitivity parameters */
/* Set initial calibration set */ /* Set initial calibration set */
priv->hw_params.sens = &iwl1000_sensitivity; hw_params(priv).sens = &iwl1000_sensitivity;
priv->hw_params.calib_init_cfg = hw_params(priv).calib_init_cfg =
BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_XTAL) |
BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_TX_IQ_PERD) |
BIT(IWL_CALIB_BASE_BAND); BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib) if (priv->cfg->need_dc_calib)
priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC); hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC);
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
return 0; return 0;
} }

View file

@ -44,6 +44,8 @@
#include "iwl-helpers.h" #include "iwl-helpers.h"
#include "iwl-agn-hw.h" #include "iwl-agn-hw.h"
#include "iwl-6000-hw.h" #include "iwl-6000-hw.h"
#include "iwl-shared.h"
#include "iwl-pci.h"
/* Highest firmware API version supported */ /* Highest firmware API version supported */
#define IWL2030_UCODE_API_MAX 6 #define IWL2030_UCODE_API_MAX 6
@ -78,8 +80,8 @@
static void iwl2000_set_ct_threshold(struct iwl_priv *priv) static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
{ {
/* want Celsius */ /* want Celsius */
priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD;
priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
} }
/* NIC configuration for 2000 series */ /* NIC configuration for 2000 series */
@ -88,7 +90,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
iwl_rf_config(priv); iwl_rf_config(priv);
if (priv->cfg->iq_invert) if (priv->cfg->iq_invert)
iwl_set_bit(priv, CSR_GP_DRIVER_REG, iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
} }
@ -124,44 +126,40 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->base_params->num_of_queues = priv->cfg->base_params->num_of_queues =
iwlagn_mod_params.num_of_queues; iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
priv->hw_params.scd_bc_tbls_size = hw_params(priv).max_stations = IWLAGN_STATION_COUNT;
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE;
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
if (priv->cfg->rx_with_siso_diversity) if (priv->cfg->rx_with_siso_diversity)
priv->hw_params.rx_chains_num = 1; hw_params(priv).rx_chains_num = 1;
else else
priv->hw_params.rx_chains_num = hw_params(priv).rx_chains_num =
num_of_ant(priv->cfg->valid_rx_ant); num_of_ant(priv->cfg->valid_rx_ant);
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
iwl2000_set_ct_threshold(priv); iwl2000_set_ct_threshold(priv);
/* Set initial sensitivity parameters */ /* Set initial sensitivity parameters */
/* Set initial calibration set */ /* Set initial calibration set */
priv->hw_params.sens = &iwl2000_sensitivity; hw_params(priv).sens = &iwl2000_sensitivity;
priv->hw_params.calib_init_cfg = hw_params(priv).calib_init_cfg =
BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_XTAL) |
BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND); BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib) if (priv->cfg->need_dc_calib)
priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX;
if (priv->cfg->need_temp_offset_calib) if (priv->cfg->need_temp_offset_calib)
priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
return 0; return 0;
} }
@ -179,7 +177,7 @@ static struct iwl_lib_ops iwl2000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40, EEPROM_REGULATORY_BAND_NO_HT40,
}, },
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
}, },
.temperature = iwlagn_temperature, .temperature = iwlagn_temperature,
}; };
@ -200,7 +198,7 @@ static struct iwl_lib_ops iwl2030_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40, EEPROM_REGULATORY_BAND_NO_HT40,
}, },
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
}, },
.temperature = iwlagn_temperature, .temperature = iwlagn_temperature,
}; };
@ -284,6 +282,11 @@ struct iwl_cfg iwl2000_2bg_cfg = {
IWL_DEVICE_2000, IWL_DEVICE_2000,
}; };
struct iwl_cfg iwl2000_2bgn_d_cfg = {
.name = "2000D Series 2x2 BGN",
IWL_DEVICE_2000,
};
#define IWL_DEVICE_2030 \ #define IWL_DEVICE_2030 \
.fw_name_pre = IWL2030_FW_PRE, \ .fw_name_pre = IWL2030_FW_PRE, \
.ucode_api_max = IWL2030_UCODE_API_MAX, \ .ucode_api_max = IWL2030_UCODE_API_MAX, \

View file

@ -46,6 +46,8 @@
#include "iwl-agn-hw.h" #include "iwl-agn-hw.h"
#include "iwl-5000-hw.h" #include "iwl-5000-hw.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-shared.h"
#include "iwl-pci.h"
/* Highest firmware API version supported */ /* Highest firmware API version supported */
#define IWL5000_UCODE_API_MAX 5 #define IWL5000_UCODE_API_MAX 5
@ -68,18 +70,18 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
iwl_rf_config(priv); iwl_rf_config(priv);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->shrd->lock, flags);
/* W/A : NIC is stuck in a reset state after Early PCIe power off /* W/A : NIC is stuck in a reset state after Early PCIe power off
* (PCIe power is lost before PERST# is asserted), * (PCIe power is lost before PERST# is asserted),
* causing ME FW to lose ownership and not being able to obtain it back. * causing ME FW to lose ownership and not being able to obtain it back.
*/ */
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, iwl_set_bits_mask_prph(bus(priv), APMG_PS_CTRL_REG,
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->shrd->lock, flags);
} }
static struct iwl_sensitivity_ranges iwl5000_sensitivity = { static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
@ -139,13 +141,13 @@ static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) - 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; hw_params(priv).ct_kill_threshold = threshold * volt2temp_coef;
} }
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_LEGACY; hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
} }
static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
@ -155,38 +157,34 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->base_params->num_of_queues = priv->cfg->base_params->num_of_queues =
iwlagn_mod_params.num_of_queues; iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
priv->hw_params.scd_bc_tbls_size = hw_params(priv).max_stations = IWLAGN_STATION_COUNT;
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE;
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ); BIT(IEEE80211_BAND_5GHZ);
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
iwl5000_set_ct_threshold(priv); iwl5000_set_ct_threshold(priv);
/* Set initial sensitivity parameters */ /* Set initial sensitivity parameters */
/* Set initial calibration set */ /* Set initial calibration set */
priv->hw_params.sens = &iwl5000_sensitivity; hw_params(priv).sens = &iwl5000_sensitivity;
priv->hw_params.calib_init_cfg = hw_params(priv).calib_init_cfg =
BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_XTAL) |
BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_TX_IQ_PERD) |
BIT(IWL_CALIB_BASE_BAND); BIT(IWL_CALIB_BASE_BAND);
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
return 0; return 0;
} }
@ -198,38 +196,34 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->base_params->num_of_queues = priv->cfg->base_params->num_of_queues =
iwlagn_mod_params.num_of_queues; iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
priv->hw_params.scd_bc_tbls_size = hw_params(priv).max_stations = IWLAGN_STATION_COUNT;
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE;
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ); BIT(IEEE80211_BAND_5GHZ);
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
iwl5150_set_ct_threshold(priv); iwl5150_set_ct_threshold(priv);
/* Set initial sensitivity parameters */ /* Set initial sensitivity parameters */
/* Set initial calibration set */ /* Set initial calibration set */
priv->hw_params.sens = &iwl5150_sensitivity; hw_params(priv).sens = &iwl5150_sensitivity;
priv->hw_params.calib_init_cfg = hw_params(priv).calib_init_cfg =
BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND); BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib) if (priv->cfg->need_dc_calib)
priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC); hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC);
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
return 0; return 0;
} }
@ -314,7 +308,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT; return -EFAULT;
} }
return trans_send_cmd(&priv->trans, &hcmd); return iwl_trans_send_cmd(trans(priv), &hcmd);
} }
static struct iwl_lib_ops iwl5000_lib = { static struct iwl_lib_ops iwl5000_lib = {

View file

@ -45,6 +45,8 @@
#include "iwl-agn-hw.h" #include "iwl-agn-hw.h"
#include "iwl-6000-hw.h" #include "iwl-6000-hw.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-shared.h"
#include "iwl-pci.h"
/* Highest firmware API version supported */ /* Highest firmware API version supported */
#define IWL6000_UCODE_API_MAX 4 #define IWL6000_UCODE_API_MAX 4
@ -74,15 +76,15 @@
static void iwl6000_set_ct_threshold(struct iwl_priv *priv) static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
{ {
/* want Celsius */ /* want Celsius */
priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD;
priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
} }
static void iwl6050_additional_nic_config(struct iwl_priv *priv) static void iwl6050_additional_nic_config(struct iwl_priv *priv)
{ {
/* Indicate calibration version to uCode. */ /* Indicate calibration version to uCode. */
if (iwlagn_eeprom_calib_version(priv) >= 6) if (iwlagn_eeprom_calib_version(priv) >= 6)
iwl_set_bit(priv, CSR_GP_DRIVER_REG, iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
} }
@ -90,9 +92,9 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)
{ {
/* Indicate calibration version to uCode. */ /* Indicate calibration version to uCode. */
if (iwlagn_eeprom_calib_version(priv) >= 6) if (iwlagn_eeprom_calib_version(priv) >= 6)
iwl_set_bit(priv, CSR_GP_DRIVER_REG, iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
iwl_set_bit(priv, CSR_GP_DRIVER_REG, iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_6050_1x2); CSR_GP_DRIVER_REG_BIT_6050_1x2);
} }
@ -104,7 +106,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
/* no locking required for register write */ /* no locking required for register write */
if (priv->cfg->pa_type == IWL_PA_INTERNAL) { if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
/* 2x2 IPA phy type */ /* 2x2 IPA phy type */
iwl_write32(priv, CSR_GP_DRIVER_REG, iwl_write32(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
} }
/* do additional nic configuration if needed */ /* do additional nic configuration if needed */
@ -144,45 +146,41 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->base_params->num_of_queues = priv->cfg->base_params->num_of_queues =
iwlagn_mod_params.num_of_queues; iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
priv->hw_params.scd_bc_tbls_size = hw_params(priv).max_stations = IWLAGN_STATION_COUNT;
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE;
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ); BIT(IEEE80211_BAND_5GHZ);
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
if (priv->cfg->rx_with_siso_diversity) if (priv->cfg->rx_with_siso_diversity)
priv->hw_params.rx_chains_num = 1; hw_params(priv).rx_chains_num = 1;
else else
priv->hw_params.rx_chains_num = hw_params(priv).rx_chains_num =
num_of_ant(priv->cfg->valid_rx_ant); num_of_ant(priv->cfg->valid_rx_ant);
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
iwl6000_set_ct_threshold(priv); iwl6000_set_ct_threshold(priv);
/* Set initial sensitivity parameters */ /* Set initial sensitivity parameters */
/* Set initial calibration set */ /* Set initial calibration set */
priv->hw_params.sens = &iwl6000_sensitivity; hw_params(priv).sens = &iwl6000_sensitivity;
priv->hw_params.calib_init_cfg = hw_params(priv).calib_init_cfg =
BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_XTAL) |
BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND); BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib) if (priv->cfg->need_dc_calib)
priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX;
if (priv->cfg->need_temp_offset_calib) if (priv->cfg->need_temp_offset_calib)
priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
return 0; return 0;
} }
@ -255,7 +253,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT; return -EFAULT;
} }
return trans_send_cmd(&priv->trans, &hcmd); return iwl_trans_send_cmd(trans(priv), &hcmd);
} }
static struct iwl_lib_ops iwl6000_lib = { static struct iwl_lib_ops iwl6000_lib = {
@ -272,7 +270,7 @@ static struct iwl_lib_ops iwl6000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS EEPROM_REG_BAND_52_HT40_CHANNELS
}, },
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
}, },
.temperature = iwlagn_temperature, .temperature = iwlagn_temperature,
}; };
@ -294,7 +292,7 @@ static struct iwl_lib_ops iwl6030_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS EEPROM_REG_BAND_52_HT40_CHANNELS
}, },
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
}, },
.temperature = iwlagn_temperature, .temperature = iwlagn_temperature,
}; };
@ -395,6 +393,12 @@ struct iwl_cfg iwl6005_2bg_cfg = {
IWL_DEVICE_6005, IWL_DEVICE_6005,
}; };
struct iwl_cfg iwl6005_2agn_sff_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205S AGN",
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
};
#define IWL_DEVICE_6030 \ #define IWL_DEVICE_6030 \
.fw_name_pre = IWL6030_FW_PRE, \ .fw_name_pre = IWL6030_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \ .ucode_api_max = IWL6000G2_UCODE_API_MAX, \

View file

@ -93,12 +93,12 @@ int iwl_send_calib_results(struct iwl_priv *priv)
}; };
for (i = 0; i < IWL_CALIB_MAX; i++) { for (i = 0; i < IWL_CALIB_MAX; i++) {
if ((BIT(i) & priv->hw_params.calib_init_cfg) && if ((BIT(i) & hw_params(priv).calib_init_cfg) &&
priv->calib_results[i].buf) { priv->calib_results[i].buf) {
hcmd.len[0] = priv->calib_results[i].buf_len; hcmd.len[0] = priv->calib_results[i].buf_len;
hcmd.data[0] = priv->calib_results[i].buf; hcmd.data[0] = priv->calib_results[i].buf;
hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
ret = trans_send_cmd(&priv->trans, &hcmd); ret = iwl_trans_send_cmd(trans(priv), &hcmd);
if (ret) { if (ret) {
IWL_ERR(priv, "Error %d iteration %d\n", IWL_ERR(priv, "Error %d iteration %d\n",
ret, i); ret, i);
@ -174,7 +174,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv,
u32 max_false_alarms = MAX_FA_CCK * rx_enable_time; u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
u32 min_false_alarms = MIN_FA_CCK * rx_enable_time; u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
struct iwl_sensitivity_data *data = NULL; struct iwl_sensitivity_data *data = NULL;
const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens;
data = &(priv->sensitivity_data); data = &(priv->sensitivity_data);
@ -357,7 +357,7 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv,
u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time; u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time; u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
struct iwl_sensitivity_data *data = NULL; struct iwl_sensitivity_data *data = NULL;
const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens;
data = &(priv->sensitivity_data); data = &(priv->sensitivity_data);
@ -484,7 +484,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
sizeof(u16)*HD_TABLE_SIZE); sizeof(u16)*HD_TABLE_SIZE);
return trans_send_cmd(&priv->trans, &cmd_out); return iwl_trans_send_cmd(trans(priv), &cmd_out);
} }
/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
@ -573,7 +573,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
&(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]), &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]),
sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES); sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES);
return trans_send_cmd(&priv->trans, &cmd_out); return iwl_trans_send_cmd(trans(priv), &cmd_out);
} }
void iwl_init_sensitivity(struct iwl_priv *priv) void iwl_init_sensitivity(struct iwl_priv *priv)
@ -581,7 +581,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
int ret = 0; int ret = 0;
int i; int i;
struct iwl_sensitivity_data *data = NULL; struct iwl_sensitivity_data *data = NULL;
const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens;
if (priv->disable_sens_cal) if (priv->disable_sens_cal)
return; return;
@ -658,13 +658,13 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
return; return;
} }
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->shrd->lock, flags);
rx_info = &priv->statistics.rx_non_phy; rx_info = &priv->statistics.rx_non_phy;
ofdm = &priv->statistics.rx_ofdm; ofdm = &priv->statistics.rx_ofdm;
cck = &priv->statistics.rx_cck; cck = &priv->statistics.rx_cck;
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->shrd->lock, flags);
return; return;
} }
@ -688,7 +688,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
statis.beacon_energy_c = statis.beacon_energy_c =
le32_to_cpu(rx_info->beacon_energy_c); le32_to_cpu(rx_info->beacon_energy_c);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->shrd->lock, flags);
IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time);
@ -821,21 +821,21 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
* To be safe, simply mask out any chains that we know * To be safe, simply mask out any chains that we know
* are not on the device. * are not on the device.
*/ */
active_chains &= priv->hw_params.valid_rx_ant; active_chains &= hw_params(priv).valid_rx_ant;
num_tx_chains = 0; num_tx_chains = 0;
for (i = 0; i < NUM_RX_CHAINS; i++) { for (i = 0; i < NUM_RX_CHAINS; i++) {
/* loops on all the bits of /* loops on all the bits of
* priv->hw_setting.valid_tx_ant */ * priv->hw_setting.valid_tx_ant */
u8 ant_msk = (1 << i); u8 ant_msk = (1 << i);
if (!(priv->hw_params.valid_tx_ant & ant_msk)) if (!(hw_params(priv).valid_tx_ant & ant_msk))
continue; continue;
num_tx_chains++; num_tx_chains++;
if (data->disconn_array[i] == 0) if (data->disconn_array[i] == 0)
/* there is a Tx antenna connected */ /* there is a Tx antenna connected */
break; break;
if (num_tx_chains == priv->hw_params.tx_chains_num && if (num_tx_chains == hw_params(priv).tx_chains_num &&
data->disconn_array[i]) { data->disconn_array[i]) {
/* /*
* If all chains are disconnected * If all chains are disconnected
@ -852,12 +852,13 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
} }
} }
if (active_chains != priv->hw_params.valid_rx_ant && if (active_chains != hw_params(priv).valid_rx_ant &&
active_chains != priv->chain_noise_data.active_chains) active_chains != priv->chain_noise_data.active_chains)
IWL_DEBUG_CALIB(priv, IWL_DEBUG_CALIB(priv,
"Detected that not all antennas are connected! " "Detected that not all antennas are connected! "
"Connected: %#x, valid: %#x.\n", "Connected: %#x, valid: %#x.\n",
active_chains, priv->hw_params.valid_rx_ant); active_chains,
hw_params(priv).valid_rx_ant);
/* Save for use within RXON, TX, SCAN commands, etc. */ /* Save for use within RXON, TX, SCAN commands, etc. */
data->active_chains = active_chains; data->active_chains = active_chains;
@ -917,7 +918,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
priv->phy_calib_chain_noise_gain_cmd); priv->phy_calib_chain_noise_gain_cmd);
cmd.delta_gain_1 = data->delta_gain_code[1]; cmd.delta_gain_1 = data->delta_gain_code[1];
cmd.delta_gain_2 = data->delta_gain_code[2]; cmd.delta_gain_2 = data->delta_gain_code[2];
trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, iwl_trans_send_cmd_pdu(trans(priv), REPLY_PHY_CALIBRATION_CMD,
CMD_ASYNC, sizeof(cmd), &cmd); CMD_ASYNC, sizeof(cmd), &cmd);
data->radio_write = 1; data->radio_write = 1;
@ -975,13 +976,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
return; return;
} }
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->shrd->lock, flags);
rx_info = &priv->statistics.rx_non_phy; rx_info = &priv->statistics.rx_non_phy;
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->shrd->lock, flags);
return; return;
} }
@ -996,7 +997,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) { if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n", IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
rxon_chnum, rxon_band24); rxon_chnum, rxon_band24);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->shrd->lock, flags);
return; return;
} }
@ -1015,7 +1016,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER; chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER; chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->shrd->lock, flags);
data->beacon_count++; data->beacon_count++;
@ -1046,7 +1047,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
priv->cfg->bt_params->advanced_bt_coexist) { priv->cfg->bt_params->advanced_bt_coexist) {
/* Disable disconnected antenna algorithm for advanced /* Disable disconnected antenna algorithm for advanced
bt coex, assuming valid antennas are connected */ bt coex, assuming valid antennas are connected */
data->active_chains = priv->hw_params.valid_rx_ant; data->active_chains = hw_params(priv).valid_rx_ant;
for (i = 0; i < NUM_RX_CHAINS; i++) for (i = 0; i < NUM_RX_CHAINS; i++)
if (!(data->active_chains & (1<<i))) if (!(data->active_chains & (1<<i)))
data->disconn_array[i] = 1; data->disconn_array[i] = 1;

View file

@ -195,7 +195,7 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
} }
static void static void
iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv, iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv,
struct iwl_eeprom_enhanced_txpwr *txp, struct iwl_eeprom_enhanced_txpwr *txp,
s8 max_txpower_avg) s8 max_txpower_avg)
{ {
@ -235,7 +235,7 @@ iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv,
#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \ #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
? # x " " : "") ? # x " " : "")
void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
{ {
struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
int idx, entries; int idx, entries;
@ -294,6 +294,6 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm) if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm)
priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm; priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm;
iwlcore_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg);
} }
} }

View file

@ -95,17 +95,4 @@
#define IWLAGN_NUM_AMPDU_QUEUES 9 #define IWLAGN_NUM_AMPDU_QUEUES 9
#define IWLAGN_FIRST_AMPDU_QUEUE 11 #define IWLAGN_FIRST_AMPDU_QUEUE 11
/* Fixed (non-configurable) rx data from phy */
/**
* struct iwlagn_schedq_bc_tbl scheduler byte count table
* base physical address provided by SCD_DRAM_BASE_ADDR
* @tfd_offset 0-12 - tx command byte count
* 12-16 - station index
*/
struct iwlagn_scd_bc_tbl {
__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
} __packed;
#endif /* __iwl_agn_hw_h__ */ #endif /* __iwl_agn_hw_h__ */

View file

@ -40,449 +40,7 @@
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-sta.h" #include "iwl-sta.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-shared.h"
static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)
{
return le32_to_cpup((__le32 *)&tx_resp->status +
tx_resp->frame_count) & MAX_SN;
}
static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
{
status &= TX_STATUS_MSK;
switch (status) {
case TX_STATUS_POSTPONE_DELAY:
priv->reply_tx_stats.pp_delay++;
break;
case TX_STATUS_POSTPONE_FEW_BYTES:
priv->reply_tx_stats.pp_few_bytes++;
break;
case TX_STATUS_POSTPONE_BT_PRIO:
priv->reply_tx_stats.pp_bt_prio++;
break;
case TX_STATUS_POSTPONE_QUIET_PERIOD:
priv->reply_tx_stats.pp_quiet_period++;
break;
case TX_STATUS_POSTPONE_CALC_TTAK:
priv->reply_tx_stats.pp_calc_ttak++;
break;
case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY:
priv->reply_tx_stats.int_crossed_retry++;
break;
case TX_STATUS_FAIL_SHORT_LIMIT:
priv->reply_tx_stats.short_limit++;
break;
case TX_STATUS_FAIL_LONG_LIMIT:
priv->reply_tx_stats.long_limit++;
break;
case TX_STATUS_FAIL_FIFO_UNDERRUN:
priv->reply_tx_stats.fifo_underrun++;
break;
case TX_STATUS_FAIL_DRAIN_FLOW:
priv->reply_tx_stats.drain_flow++;
break;
case TX_STATUS_FAIL_RFKILL_FLUSH:
priv->reply_tx_stats.rfkill_flush++;
break;
case TX_STATUS_FAIL_LIFE_EXPIRE:
priv->reply_tx_stats.life_expire++;
break;
case TX_STATUS_FAIL_DEST_PS:
priv->reply_tx_stats.dest_ps++;
break;
case TX_STATUS_FAIL_HOST_ABORTED:
priv->reply_tx_stats.host_abort++;
break;
case TX_STATUS_FAIL_BT_RETRY:
priv->reply_tx_stats.bt_retry++;
break;
case TX_STATUS_FAIL_STA_INVALID:
priv->reply_tx_stats.sta_invalid++;
break;
case TX_STATUS_FAIL_FRAG_DROPPED:
priv->reply_tx_stats.frag_drop++;
break;
case TX_STATUS_FAIL_TID_DISABLE:
priv->reply_tx_stats.tid_disable++;
break;
case TX_STATUS_FAIL_FIFO_FLUSHED:
priv->reply_tx_stats.fifo_flush++;
break;
case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL:
priv->reply_tx_stats.insuff_cf_poll++;
break;
case TX_STATUS_FAIL_PASSIVE_NO_RX:
priv->reply_tx_stats.fail_hw_drop++;
break;
case TX_STATUS_FAIL_NO_BEACON_ON_RADAR:
priv->reply_tx_stats.sta_color_mismatch++;
break;
default:
priv->reply_tx_stats.unknown++;
break;
}
}
static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)
{
status &= AGG_TX_STATUS_MSK;
switch (status) {
case AGG_TX_STATE_UNDERRUN_MSK:
priv->reply_agg_tx_stats.underrun++;
break;
case AGG_TX_STATE_BT_PRIO_MSK:
priv->reply_agg_tx_stats.bt_prio++;
break;
case AGG_TX_STATE_FEW_BYTES_MSK:
priv->reply_agg_tx_stats.few_bytes++;
break;
case AGG_TX_STATE_ABORT_MSK:
priv->reply_agg_tx_stats.abort++;
break;
case AGG_TX_STATE_LAST_SENT_TTL_MSK:
priv->reply_agg_tx_stats.last_sent_ttl++;
break;
case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK:
priv->reply_agg_tx_stats.last_sent_try++;
break;
case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK:
priv->reply_agg_tx_stats.last_sent_bt_kill++;
break;
case AGG_TX_STATE_SCD_QUERY_MSK:
priv->reply_agg_tx_stats.scd_query++;
break;
case AGG_TX_STATE_TEST_BAD_CRC32_MSK:
priv->reply_agg_tx_stats.bad_crc32++;
break;
case AGG_TX_STATE_RESPONSE_MSK:
priv->reply_agg_tx_stats.response++;
break;
case AGG_TX_STATE_DUMP_TX_MSK:
priv->reply_agg_tx_stats.dump_tx++;
break;
case AGG_TX_STATE_DELAY_TX_MSK:
priv->reply_agg_tx_stats.delay_tx++;
break;
default:
priv->reply_agg_tx_stats.unknown++;
break;
}
}
static void iwlagn_set_tx_status(struct iwl_priv *priv,
struct ieee80211_tx_info *info,
struct iwl_rxon_context *ctx,
struct iwlagn_tx_resp *tx_resp,
int txq_id, bool is_agg)
{
u16 status = le16_to_cpu(tx_resp->status.status);
info->status.rates[0].count = tx_resp->failure_frame + 1;
if (is_agg)
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
info->flags |= iwl_tx_status_to_mac80211(status);
iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
info);
if (!iwl_is_tx_success(status))
iwlagn_count_tx_err_status(priv, status);
if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
iwl_is_associated_ctx(ctx) && ctx->vif &&
ctx->vif->type == NL80211_IFTYPE_STATION) {
ctx->last_tx_rejected = true;
iwl_stop_queue(priv, &priv->txq[txq_id]);
}
IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags "
"0x%x retries %d\n",
txq_id,
iwl_get_tx_fail_reason(status), status,
le32_to_cpu(tx_resp->rate_n_flags),
tx_resp->failure_frame);
}
#ifdef CONFIG_IWLWIFI_DEBUG
#define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x
const char *iwl_get_agg_tx_fail_reason(u16 status)
{
status &= AGG_TX_STATUS_MSK;
switch (status) {
case AGG_TX_STATE_TRANSMITTED:
return "SUCCESS";
AGG_TX_STATE_FAIL(UNDERRUN_MSK);
AGG_TX_STATE_FAIL(BT_PRIO_MSK);
AGG_TX_STATE_FAIL(FEW_BYTES_MSK);
AGG_TX_STATE_FAIL(ABORT_MSK);
AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK);
AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK);
AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK);
AGG_TX_STATE_FAIL(SCD_QUERY_MSK);
AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK);
AGG_TX_STATE_FAIL(RESPONSE_MSK);
AGG_TX_STATE_FAIL(DUMP_TX_MSK);
AGG_TX_STATE_FAIL(DELAY_TX_MSK);
}
return "UNKNOWN";
}
#endif /* CONFIG_IWLWIFI_DEBUG */
static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
struct iwl_ht_agg *agg,
struct iwlagn_tx_resp *tx_resp,
int txq_id, u16 start_idx)
{
u16 status;
struct agg_tx_status *frame_status = &tx_resp->status;
struct ieee80211_hdr *hdr = NULL;
int i, sh, idx;
u16 seq;
if (agg->wait_for_ba)
IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n");
agg->frame_count = tx_resp->frame_count;
agg->start_idx = start_idx;
agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
agg->bitmap = 0;
/* # frames attempted by Tx command */
if (agg->frame_count == 1) {
struct iwl_tx_info *txb;
/* Only one frame was attempted; no block-ack will arrive */
idx = start_idx;
IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
agg->frame_count, agg->start_idx, idx);
txb = &priv->txq[txq_id].txb[idx];
iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(txb->skb),
txb->ctx, tx_resp, txq_id, true);
agg->wait_for_ba = 0;
} else {
/* Two or more frames were attempted; expect block-ack */
u64 bitmap = 0;
/*
* Start is the lowest frame sent. It may not be the first
* frame in the batch; we figure this out dynamically during
* the following loop.
*/
int start = agg->start_idx;
/* Construct bit-map of pending frames within Tx window */
for (i = 0; i < agg->frame_count; i++) {
u16 sc;
status = le16_to_cpu(frame_status[i].status);
seq = le16_to_cpu(frame_status[i].sequence);
idx = SEQ_TO_INDEX(seq);
txq_id = SEQ_TO_QUEUE(seq);
if (status & AGG_TX_STATUS_MSK)
iwlagn_count_agg_tx_err_status(priv, status);
if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
AGG_TX_STATE_ABORT_MSK))
continue;
IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
agg->frame_count, txq_id, idx);
IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), "
"try-count (0x%08x)\n",
iwl_get_agg_tx_fail_reason(status),
status & AGG_TX_STATUS_MSK,
status & AGG_TX_TRY_MSK);
hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
if (!hdr) {
IWL_ERR(priv,
"BUG_ON idx doesn't point to valid skb"
" idx=%d, txq_id=%d\n", idx, txq_id);
return -1;
}
sc = le16_to_cpu(hdr->seq_ctrl);
if (idx != (SEQ_TO_SN(sc) & 0xff)) {
IWL_ERR(priv,
"BUG_ON idx doesn't match seq control"
" idx=%d, seq_idx=%d, seq=%d\n",
idx, SEQ_TO_SN(sc),
hdr->seq_ctrl);
return -1;
}
IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
i, idx, SEQ_TO_SN(sc));
/*
* sh -> how many frames ahead of the starting frame is
* the current one?
*
* Note that all frames sent in the batch must be in a
* 64-frame window, so this number should be in [0,63].
* If outside of this window, then we've found a new
* "first" frame in the batch and need to change start.
*/
sh = idx - start;
/*
* If >= 64, out of window. start must be at the front
* of the circular buffer, idx must be near the end of
* the buffer, and idx is the new "first" frame. Shift
* the indices around.
*/
if (sh >= 64) {
/* Shift bitmap by start - idx, wrapped */
sh = 0x100 - idx + start;
bitmap = bitmap << sh;
/* Now idx is the new start so sh = 0 */
sh = 0;
start = idx;
/*
* If <= -64 then wraps the 256-pkt circular buffer
* (e.g., start = 255 and idx = 0, sh should be 1)
*/
} else if (sh <= -64) {
sh = 0x100 - start + idx;
/*
* If < 0 but > -64, out of window. idx is before start
* but not wrapped. Shift the indices around.
*/
} else if (sh < 0) {
/* Shift by how far start is ahead of idx */
sh = start - idx;
bitmap = bitmap << sh;
/* Now idx is the new start so sh = 0 */
start = idx;
sh = 0;
}
/* Sequence number start + sh was sent in this batch */
bitmap |= 1ULL << sh;
IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
start, (unsigned long long)bitmap);
}
/*
* Store the bitmap and possibly the new start, if we wrapped
* the buffer above
*/
agg->bitmap = bitmap;
agg->start_idx = start;
IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
agg->frame_count, agg->start_idx,
(unsigned long long)agg->bitmap);
if (bitmap)
agg->wait_for_ba = 1;
}
return 0;
}
void iwl_check_abort_status(struct iwl_priv *priv,
u8 frame_count, u32 status)
{
if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
IWL_ERR(priv, "Tx flush command to flush out all frames\n");
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
queue_work(priv->workqueue, &priv->tx_flush);
}
}
void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
struct iwl_tx_queue *txq = &priv->txq[txq_id];
struct ieee80211_tx_info *info;
struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
struct ieee80211_hdr *hdr;
struct iwl_tx_info *txb;
u32 status = le16_to_cpu(tx_resp->status.status);
int tid;
int sta_id;
int freed;
unsigned long flags;
if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
IWL_ERR(priv, "%s: Read index for DMA queue txq_id (%d) "
"index %d is out of range [0-%d] %d %d\n", __func__,
txq_id, index, txq->q.n_bd, txq->q.write_ptr,
txq->q.read_ptr);
return;
}
txq->time_stamp = jiffies;
txb = &txq->txb[txq->q.read_ptr];
info = IEEE80211_SKB_CB(txb->skb);
memset(&info->status, 0, sizeof(info->status));
tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
IWLAGN_TX_RES_TID_POS;
sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
IWLAGN_TX_RES_RA_POS;
spin_lock_irqsave(&priv->sta_lock, flags);
hdr = (void *)txb->skb->data;
if (!ieee80211_is_data_qos(hdr->frame_control))
priv->last_seq_ctl = tx_resp->seq_ctl;
if (txq->sched_retry) {
const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp);
struct iwl_ht_agg *agg;
agg = &priv->stations[sta_id].tid[tid].agg;
/*
* If the BT kill count is non-zero, we'll get this
* notification again.
*/
if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
priv->cfg->bt_params &&
priv->cfg->bt_params->advanced_bt_coexist) {
IWL_DEBUG_COEX(priv, "receive reply tx with bt_kill\n");
}
iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
/* check if BAR is needed */
if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status))
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
if (txq->q.read_ptr != (scd_ssn & 0xff)) {
index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim "
"scd_ssn=%d idx=%d txq=%d swq=%d\n",
scd_ssn , index, txq_id, txq->swq_id);
freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
if (priv->mac80211_registered &&
(iwl_queue_space(&txq->q) > txq->q.low_mark) &&
(agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
iwl_wake_queue(priv, txq);
}
} else {
iwlagn_set_tx_status(priv, info, txb->ctx, tx_resp,
txq_id, false);
freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
if (priv->mac80211_registered &&
iwl_queue_space(&txq->q) > txq->q.low_mark &&
status != TX_STATUS_FAIL_PASSIVE_NO_RX)
iwl_wake_queue(priv, txq);
}
iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
iwl_check_abort_status(priv, tx_resp->frame_count, status);
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
int iwlagn_hw_valid_rtc_data_addr(u32 addr) int iwlagn_hw_valid_rtc_data_addr(u32 addr)
{ {
@ -495,7 +53,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
struct iwlagn_tx_power_dbm_cmd tx_power_cmd; struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
u8 tx_ant_cfg_cmd; u8 tx_ant_cfg_cmd;
if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->shrd->status),
"TX Power requested while scanning!\n")) "TX Power requested while scanning!\n"))
return -EAGAIN; return -EAGAIN;
@ -525,7 +83,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
else else
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
return trans_send_cmd_pdu(&priv->trans, tx_ant_cfg_cmd, CMD_SYNC, return iwl_trans_send_cmd_pdu(trans(priv), tx_ant_cfg_cmd, CMD_SYNC,
sizeof(tx_power_cmd), &tx_power_cmd); sizeof(tx_power_cmd), &tx_power_cmd);
} }
@ -609,6 +167,9 @@ struct iwl_mod_params iwlagn_mod_params = {
.bt_coex_active = true, .bt_coex_active = true,
.no_sleep_autoadjust = true, .no_sleep_autoadjust = true,
.power_level = IWL_POWER_INDEX_1, .power_level = IWL_POWER_INDEX_1,
.bt_ch_announce = true,
.wanted_ucode_alternative = 1,
.auto_agg = true,
/* the rest are 0 by default */ /* the rest are 0 by default */
}; };
@ -767,15 +328,15 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
u16 rx_chain = 0; u16 rx_chain = 0;
enum ieee80211_band band; enum ieee80211_band band;
u8 n_probes = 0; u8 n_probes = 0;
u8 rx_ant = priv->hw_params.valid_rx_ant; u8 rx_ant = hw_params(priv).valid_rx_ant;
u8 rate; u8 rate;
bool is_active = false; bool is_active = false;
int chan_mod; int chan_mod;
u8 active_chains; u8 active_chains;
u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; u8 scan_tx_antennas = hw_params(priv).valid_tx_ant;
int ret; int ret;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
if (vif) if (vif)
ctx = iwl_rxon_ctx_from_vif(vif); ctx = iwl_rxon_ctx_from_vif(vif);
@ -942,7 +503,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
/* In power save mode use one chain, otherwise use all chains */ /* In power save mode use one chain, otherwise use all chains */
if (test_bit(STATUS_POWER_PMI, &priv->status)) { if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) {
/* rx_ant has been set to all valid chains previously */ /* rx_ant has been set to all valid chains previously */
active_chains = rx_ant & active_chains = rx_ant &
((u8)(priv->chain_noise_data.active_chains)); ((u8)(priv->chain_noise_data.active_chains));
@ -962,7 +523,8 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
} }
/* MIMO is not used here, but value is required */ /* MIMO is not used here, but value is required */
rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; rx_chain |=
hw_params(priv).valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
@ -1044,15 +606,15 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->len = cpu_to_le16(cmd.len[0]); scan->len = cpu_to_le16(cmd.len[0]);
/* set scan bit here for PAN params */ /* set scan bit here for PAN params */
set_bit(STATUS_SCAN_HW, &priv->status); set_bit(STATUS_SCAN_HW, &priv->shrd->status);
ret = iwlagn_set_pan_params(priv); ret = iwlagn_set_pan_params(priv);
if (ret) if (ret)
return ret; return ret;
ret = trans_send_cmd(&priv->trans, &cmd); ret = iwl_trans_send_cmd(trans(priv), &cmd);
if (ret) { if (ret) {
clear_bit(STATUS_SCAN_HW, &priv->status); clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
iwlagn_set_pan_params(priv); iwlagn_set_pan_params(priv);
} }
@ -1072,52 +634,6 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
vif->bss_conf.bssid); vif->bss_conf.bssid);
} }
void iwl_free_tfds_in_queue(struct iwl_priv *priv,
int sta_id, int tid, int freed)
{
lockdep_assert_held(&priv->sta_lock);
if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed)
priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
else {
IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
priv->stations[sta_id].tid[tid].tfds_in_queue,
freed);
priv->stations[sta_id].tid[tid].tfds_in_queue = 0;
}
}
#define IWL_FLUSH_WAIT_MS 2000
int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv)
{
struct iwl_tx_queue *txq;
struct iwl_queue *q;
int cnt;
unsigned long now = jiffies;
int ret = 0;
/* waiting for all the tx frames complete might take a while */
for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
if (cnt == priv->cmd_queue)
continue;
txq = &priv->txq[cnt];
q = &txq->q;
while (q->read_ptr != q->write_ptr && !time_after(jiffies,
now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS)))
msleep(1);
if (q->read_ptr != q->write_ptr) {
IWL_ERR(priv, "fail to flush all tx fifo queues\n");
ret = -ETIMEDOUT;
break;
}
}
return ret;
}
#define IWL_TX_QUEUE_MSK 0xfffff
/** /**
* iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode * iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode
* *
@ -1156,22 +672,22 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
flush_cmd.fifo_control); flush_cmd.fifo_control);
flush_cmd.flush_control = cpu_to_le16(flush_control); flush_cmd.flush_control = cpu_to_le16(flush_control);
return trans_send_cmd(&priv->trans, &cmd); return iwl_trans_send_cmd(trans(priv), &cmd);
} }
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
{ {
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
ieee80211_stop_queues(priv->hw); ieee80211_stop_queues(priv->hw);
if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) { if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
IWL_ERR(priv, "flush request fail\n"); IWL_ERR(priv, "flush request fail\n");
goto done; goto done;
} }
IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n"); IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n");
iwlagn_wait_tx_queue_empty(priv); iwl_trans_wait_tx_queue_empty(trans(priv));
done: done:
ieee80211_wake_queues(priv->hw); ieee80211_wake_queues(priv->hw);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
} }
/* /*
@ -1350,12 +866,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
if (priv->cfg->bt_params->bt_session_2) { if (priv->cfg->bt_params->bt_session_2) {
memcpy(&bt_cmd_2000.basic, &basic, memcpy(&bt_cmd_2000.basic, &basic,
sizeof(basic)); sizeof(basic));
ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000); CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);
} else { } else {
memcpy(&bt_cmd_6000.basic, &basic, memcpy(&bt_cmd_6000.basic, &basic,
sizeof(basic)); sizeof(basic));
ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000); CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);
} }
if (ret) if (ret)
@ -1368,7 +884,7 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena)
struct iwl_rxon_context *ctx, *found_ctx = NULL; struct iwl_rxon_context *ctx, *found_ctx = NULL;
bool found_ap = false; bool found_ap = false;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
/* Check whether AP or GO mode is active. */ /* Check whether AP or GO mode is active. */
if (rssi_ena) { if (rssi_ena) {
@ -1481,7 +997,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
break; break;
} }
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
/* /*
* We can not send command to firmware while scanning. When the scan * We can not send command to firmware while scanning. When the scan
@ -1490,7 +1006,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
* STATUS_SCANNING to avoid race when queue_work two times from * STATUS_SCANNING to avoid race when queue_work two times from
* different notifications, but quit and not perform any work at all. * different notifications, but quit and not perform any work at all.
*/ */
if (test_bit(STATUS_SCAN_HW, &priv->status)) if (test_bit(STATUS_SCAN_HW, &priv->shrd->status))
goto out; goto out;
iwl_update_chain_flags(priv); iwl_update_chain_flags(priv);
@ -1509,7 +1025,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
*/ */
iwlagn_bt_coex_rssi_monitor(priv); iwlagn_bt_coex_rssi_monitor(priv);
out: out:
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
} }
/* /*
@ -1616,7 +1132,7 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv,
priv->kill_cts_mask = bt_kill_cts_msg[kill_msk]; priv->kill_cts_mask = bt_kill_cts_msg[kill_msk];
/* schedule to send runtime bt_config */ /* schedule to send runtime bt_config */
queue_work(priv->workqueue, &priv->bt_runtime_config); queue_work(priv->shrd->workqueue, &priv->bt_runtime_config);
} }
} }
@ -1660,7 +1176,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
IWL_BT_COEX_TRAFFIC_LOAD_NONE; IWL_BT_COEX_TRAFFIC_LOAD_NONE;
} }
priv->bt_status = coex->bt_status; priv->bt_status = coex->bt_status;
queue_work(priv->workqueue, queue_work(priv->shrd->workqueue,
&priv->bt_traffic_change_work); &priv->bt_traffic_change_work);
} }
} }
@ -1669,9 +1185,9 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
/* FIXME: based on notification, adjust the prio_boost */ /* FIXME: based on notification, adjust the prio_boost */
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->shrd->lock, flags);
priv->bt_ci_compliance = coex->bt_ci_compliance; priv->bt_ci_compliance = coex->bt_ci_compliance;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->shrd->lock, flags);
} }
void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv) void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv)
@ -1771,7 +1287,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{ {
bool is_single = is_single_rx_stream(priv); bool is_single = is_single_rx_stream(priv);
bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->shrd->status);
u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt; u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
u32 active_chains; u32 active_chains;
u16 rx_chain; u16 rx_chain;
@ -1783,7 +1299,7 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
if (priv->chain_noise_data.active_chains) if (priv->chain_noise_data.active_chains)
active_chains = priv->chain_noise_data.active_chains; active_chains = priv->chain_noise_data.active_chains;
else else
active_chains = priv->hw_params.valid_rx_ant; active_chains = hw_params(priv).valid_rx_ant;
if (priv->cfg->bt_params && if (priv->cfg->bt_params &&
priv->cfg->bt_params->advanced_bt_coexist && priv->cfg->bt_params->advanced_bt_coexist &&
@ -1848,136 +1364,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
return ant; return ant;
} }
static const char *get_csr_string(int cmd)
{
switch (cmd) {
IWL_CMD(CSR_HW_IF_CONFIG_REG);
IWL_CMD(CSR_INT_COALESCING);
IWL_CMD(CSR_INT);
IWL_CMD(CSR_INT_MASK);
IWL_CMD(CSR_FH_INT_STATUS);
IWL_CMD(CSR_GPIO_IN);
IWL_CMD(CSR_RESET);
IWL_CMD(CSR_GP_CNTRL);
IWL_CMD(CSR_HW_REV);
IWL_CMD(CSR_EEPROM_REG);
IWL_CMD(CSR_EEPROM_GP);
IWL_CMD(CSR_OTP_GP_REG);
IWL_CMD(CSR_GIO_REG);
IWL_CMD(CSR_GP_UCODE_REG);
IWL_CMD(CSR_GP_DRIVER_REG);
IWL_CMD(CSR_UCODE_DRV_GP1);
IWL_CMD(CSR_UCODE_DRV_GP2);
IWL_CMD(CSR_LED_REG);
IWL_CMD(CSR_DRAM_INT_TBL_REG);
IWL_CMD(CSR_GIO_CHICKEN_BITS);
IWL_CMD(CSR_ANA_PLL_CFG);
IWL_CMD(CSR_HW_REV_WA_REG);
IWL_CMD(CSR_DBG_HPET_MEM_REG);
default:
return "UNKNOWN";
}
}
void iwl_dump_csr(struct iwl_priv *priv)
{
int i;
static const u32 csr_tbl[] = {
CSR_HW_IF_CONFIG_REG,
CSR_INT_COALESCING,
CSR_INT,
CSR_INT_MASK,
CSR_FH_INT_STATUS,
CSR_GPIO_IN,
CSR_RESET,
CSR_GP_CNTRL,
CSR_HW_REV,
CSR_EEPROM_REG,
CSR_EEPROM_GP,
CSR_OTP_GP_REG,
CSR_GIO_REG,
CSR_GP_UCODE_REG,
CSR_GP_DRIVER_REG,
CSR_UCODE_DRV_GP1,
CSR_UCODE_DRV_GP2,
CSR_LED_REG,
CSR_DRAM_INT_TBL_REG,
CSR_GIO_CHICKEN_BITS,
CSR_ANA_PLL_CFG,
CSR_HW_REV_WA_REG,
CSR_DBG_HPET_MEM_REG
};
IWL_ERR(priv, "CSR values:\n");
IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is "
"CSR_INT_PERIODIC_REG)\n");
for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) {
IWL_ERR(priv, " %25s: 0X%08x\n",
get_csr_string(csr_tbl[i]),
iwl_read32(priv, csr_tbl[i]));
}
}
static const char *get_fh_string(int cmd)
{
switch (cmd) {
IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
IWL_CMD(FH_RSCSR_CHNL0_WPTR);
IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
IWL_CMD(FH_TSSR_TX_STATUS_REG);
IWL_CMD(FH_TSSR_TX_ERROR_REG);
default:
return "UNKNOWN";
}
}
int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
{
int i;
#ifdef CONFIG_IWLWIFI_DEBUG
int pos = 0;
size_t bufsz = 0;
#endif
static const u32 fh_tbl[] = {
FH_RSCSR_CHNL0_STTS_WPTR_REG,
FH_RSCSR_CHNL0_RBDCB_BASE_REG,
FH_RSCSR_CHNL0_WPTR,
FH_MEM_RCSR_CHNL0_CONFIG_REG,
FH_MEM_RSSR_SHARED_CTRL_REG,
FH_MEM_RSSR_RX_STATUS_REG,
FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
FH_TSSR_TX_STATUS_REG,
FH_TSSR_TX_ERROR_REG
};
#ifdef CONFIG_IWLWIFI_DEBUG
if (display) {
bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
*buf = kmalloc(bufsz, GFP_KERNEL);
if (!*buf)
return -ENOMEM;
pos += scnprintf(*buf + pos, bufsz - pos,
"FH register values:\n");
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
pos += scnprintf(*buf + pos, bufsz - pos,
" %34s: 0X%08x\n",
get_fh_string(fh_tbl[i]),
iwl_read_direct32(priv, fh_tbl[i]));
}
return pos;
}
#endif
IWL_ERR(priv, "FH register values:\n");
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
IWL_ERR(priv, " %34s: 0X%08x\n",
get_fh_string(fh_tbl[i]),
iwl_read_direct32(priv, fh_tbl[i]));
}
return 0;
}
/* notification wait support */ /* notification wait support */
void iwlagn_init_notification_wait(struct iwl_priv *priv, void iwlagn_init_notification_wait(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry, struct iwl_notification_wait *wait_entry,

View file

@ -297,10 +297,10 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
u8 *qc = ieee80211_get_qos_ctl(hdr); u8 *qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & 0xf; tid = qc[0] & 0xf;
} else } else
return MAX_TID_COUNT; return IWL_MAX_TID_COUNT;
if (unlikely(tid >= TID_MAX_LOAD_COUNT)) if (unlikely(tid >= TID_MAX_LOAD_COUNT))
return MAX_TID_COUNT; return IWL_MAX_TID_COUNT;
tl = &lq_data->load[tid]; tl = &lq_data->load[tid];
@ -313,7 +313,7 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
tl->queue_count = 1; tl->queue_count = 1;
tl->head = 0; tl->head = 0;
tl->packet_count[0] = 1; tl->packet_count[0] = 1;
return MAX_TID_COUNT; return IWL_MAX_TID_COUNT;
} }
time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
@ -420,7 +420,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
load = rs_tl_get_load(lq_data, tid); load = rs_tl_get_load(lq_data, tid);
if (load > IWL_AGG_LOAD_THRESHOLD) { if ((iwlagn_mod_params.auto_agg) || (load > IWL_AGG_LOAD_THRESHOLD)) {
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
sta->addr, tid); sta->addr, tid);
ret = ieee80211_start_tx_ba_session(sta, tid, 5000); ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
@ -819,7 +819,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
if (num_of_ant(tbl->ant_type) > 1) if (num_of_ant(tbl->ant_type) > 1)
tbl->ant_type = tbl->ant_type =
first_antenna(priv->hw_params.valid_tx_ant); first_antenna(hw_params(priv).valid_tx_ant);
tbl->is_ht40 = 0; tbl->is_ht40 = 0;
tbl->is_SGI = 0; tbl->is_SGI = 0;
@ -877,12 +877,12 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
* Is there a need to switch between * Is there a need to switch between
* full concurrency and 3-wire? * full concurrency and 3-wire?
*/ */
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->shrd->lock, flags);
if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) if (priv->bt_ci_compliance && priv->bt_ant_couple_ok)
full_concurrent = true; full_concurrent = true;
else else
full_concurrent = false; full_concurrent = false;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->shrd->lock, flags);
} }
if ((priv->bt_traffic_load != priv->last_bt_traffic_load) || if ((priv->bt_traffic_load != priv->last_bt_traffic_load) ||
(priv->bt_full_concurrent != full_concurrent)) { (priv->bt_full_concurrent != full_concurrent)) {
@ -893,7 +893,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
queue_work(priv->workqueue, &priv->bt_full_concurrency); queue_work(priv->shrd->workqueue, &priv->bt_full_concurrency);
} }
} }
@ -1293,7 +1293,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
return -1; return -1;
/* Need both Tx chains/antennas to support MIMO */ /* Need both Tx chains/antennas to support MIMO */
if (priv->hw_params.tx_chains_num < 2) if (hw_params(priv).tx_chains_num < 2)
return -1; return -1;
IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n"); IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n");
@ -1349,7 +1349,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
return -1; return -1;
/* Need both Tx chains/antennas to support MIMO */ /* Need both Tx chains/antennas to support MIMO */
if (priv->hw_params.tx_chains_num < 3) if (hw_params(priv).tx_chains_num < 3)
return -1; return -1;
IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n"); IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n");
@ -1448,8 +1448,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
u32 sz = (sizeof(struct iwl_scale_tbl_info) - u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action; u8 start_action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant; u8 valid_tx_ant = hw_params(priv).valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num; u8 tx_chains_num = hw_params(priv).tx_chains_num;
int ret = 0; int ret = 0;
u8 update_search_tbl_counter = 0; u8 update_search_tbl_counter = 0;
@ -1459,14 +1459,16 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
break; break;
case IWL_BT_COEX_TRAFFIC_LOAD_LOW: case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
/* avoid antenna B unless MIMO */ /* avoid antenna B unless MIMO */
valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); valid_tx_ant =
first_antenna(hw_params(priv).valid_tx_ant);
if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2) if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2)
tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
break; break;
case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
/* avoid antenna B and MIMO */ /* avoid antenna B and MIMO */
valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); valid_tx_ant =
first_antenna(hw_params(priv).valid_tx_ant);
if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 &&
tbl->action != IWL_LEGACY_SWITCH_SISO) tbl->action != IWL_LEGACY_SWITCH_SISO)
tbl->action = IWL_LEGACY_SWITCH_SISO; tbl->action = IWL_LEGACY_SWITCH_SISO;
@ -1489,7 +1491,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
tbl->action = IWL_LEGACY_SWITCH_SISO; tbl->action = IWL_LEGACY_SWITCH_SISO;
valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); valid_tx_ant =
first_antenna(hw_params(priv).valid_tx_ant);
} }
start_action = tbl->action; start_action = tbl->action;
@ -1623,8 +1626,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
u32 sz = (sizeof(struct iwl_scale_tbl_info) - u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action; u8 start_action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant; u8 valid_tx_ant = hw_params(priv).valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num; u8 tx_chains_num = hw_params(priv).tx_chains_num;
u8 update_search_tbl_counter = 0; u8 update_search_tbl_counter = 0;
int ret; int ret;
@ -1634,14 +1637,16 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
break; break;
case IWL_BT_COEX_TRAFFIC_LOAD_LOW: case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
/* avoid antenna B unless MIMO */ /* avoid antenna B unless MIMO */
valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); valid_tx_ant =
first_antenna(hw_params(priv).valid_tx_ant);
if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) if (tbl->action == IWL_SISO_SWITCH_ANTENNA2)
tbl->action = IWL_SISO_SWITCH_ANTENNA1; tbl->action = IWL_SISO_SWITCH_ANTENNA1;
break; break;
case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
/* avoid antenna B and MIMO */ /* avoid antenna B and MIMO */
valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); valid_tx_ant =
first_antenna(hw_params(priv).valid_tx_ant);
if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) if (tbl->action != IWL_SISO_SWITCH_ANTENNA1)
tbl->action = IWL_SISO_SWITCH_ANTENNA1; tbl->action = IWL_SISO_SWITCH_ANTENNA1;
break; break;
@ -1658,7 +1663,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
/* configure as 1x1 if bt full concurrency */ /* configure as 1x1 if bt full concurrency */
if (priv->bt_full_concurrent) { if (priv->bt_full_concurrent) {
valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); valid_tx_ant =
first_antenna(hw_params(priv).valid_tx_ant);
if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
tbl->action = IWL_SISO_SWITCH_ANTENNA1; tbl->action = IWL_SISO_SWITCH_ANTENNA1;
} }
@ -1794,8 +1800,8 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
u32 sz = (sizeof(struct iwl_scale_tbl_info) - u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action; u8 start_action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant; u8 valid_tx_ant = hw_params(priv).valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num; u8 tx_chains_num = hw_params(priv).tx_chains_num;
u8 update_search_tbl_counter = 0; u8 update_search_tbl_counter = 0;
int ret; int ret;
@ -1964,8 +1970,8 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
u32 sz = (sizeof(struct iwl_scale_tbl_info) - u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action; u8 start_action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant; u8 valid_tx_ant = hw_params(priv).valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num; u8 tx_chains_num = hw_params(priv).tx_chains_num;
int ret; int ret;
u8 update_search_tbl_counter = 0; u8 update_search_tbl_counter = 0;
@ -2208,7 +2214,6 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
/* /*
* setup rate table in uCode * setup rate table in uCode
* return rate_n_flags as used in the table
*/ */
static void rs_update_rate_tbl(struct iwl_priv *priv, static void rs_update_rate_tbl(struct iwl_priv *priv,
struct iwl_rxon_context *ctx, struct iwl_rxon_context *ctx,
@ -2255,7 +2260,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
u8 done_search = 0; u8 done_search = 0;
u16 high_low; u16 high_low;
s32 sr; s32 sr;
u8 tid = MAX_TID_COUNT; u8 tid = IWL_MAX_TID_COUNT;
struct iwl_tid_data *tid_data; struct iwl_tid_data *tid_data;
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
struct iwl_rxon_context *ctx = sta_priv->common.ctx; struct iwl_rxon_context *ctx = sta_priv->common.ctx;
@ -2274,8 +2279,9 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
tid = rs_tl_add_packet(lq_sta, hdr); tid = rs_tl_add_packet(lq_sta, hdr);
if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) { if ((tid != IWL_MAX_TID_COUNT) &&
tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid]; (lq_sta->tx_agg_tid_en & (1 << tid))) {
tid_data = &priv->shrd->tid_data[lq_sta->lq.sta_id][tid];
if (tid_data->agg.state == IWL_AGG_OFF) if (tid_data->agg.state == IWL_AGG_OFF)
lq_sta->is_agg = 0; lq_sta->is_agg = 0;
else else
@ -2645,9 +2651,10 @@ lq_update:
iwl_ht_enabled(priv)) { 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 != IWL_MAX_TID_COUNT)) {
u8 sta_id = lq_sta->lq.sta_id;
tid_data = tid_data =
&priv->stations[lq_sta->lq.sta_id].tid[tid]; &priv->shrd->tid_data[sta_id][tid];
if (tid_data->agg.state == IWL_AGG_OFF) { if (tid_data->agg.state == IWL_AGG_OFF) {
IWL_DEBUG_RATE(priv, IWL_DEBUG_RATE(priv,
"try to aggregate tid %d\n", "try to aggregate tid %d\n",
@ -2703,7 +2710,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
i = lq_sta->last_txrate_idx; i = lq_sta->last_txrate_idx;
valid_tx_ant = priv->hw_params.valid_tx_ant; valid_tx_ant = hw_params(priv).valid_tx_ant;
if (!lq_sta->search_better_tbl) if (!lq_sta->search_better_tbl)
active_tbl = lq_sta->active_tbl; active_tbl = lq_sta->active_tbl;
@ -2886,15 +2893,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
/* These values will be overridden later */ /* These values will be overridden later */
lq_sta->lq.general_params.single_stream_ant_msk = lq_sta->lq.general_params.single_stream_ant_msk =
first_antenna(priv->hw_params.valid_tx_ant); first_antenna(hw_params(priv).valid_tx_ant);
lq_sta->lq.general_params.dual_stream_ant_msk = lq_sta->lq.general_params.dual_stream_ant_msk =
priv->hw_params.valid_tx_ant & hw_params(priv).valid_tx_ant &
~first_antenna(priv->hw_params.valid_tx_ant); ~first_antenna(hw_params(priv).valid_tx_ant);
if (!lq_sta->lq.general_params.dual_stream_ant_msk) { if (!lq_sta->lq.general_params.dual_stream_ant_msk) {
lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) {
lq_sta->lq.general_params.dual_stream_ant_msk = lq_sta->lq.general_params.dual_stream_ant_msk =
priv->hw_params.valid_tx_ant; hw_params(priv).valid_tx_ant;
} }
/* as default allow aggregation for all tids */ /* as default allow aggregation for all tids */
@ -2940,7 +2947,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
if (priv && priv->bt_full_concurrent) { if (priv && priv->bt_full_concurrent) {
/* 1x1 only */ /* 1x1 only */
tbl_type.ant_type = tbl_type.ant_type =
first_antenna(priv->hw_params.valid_tx_ant); first_antenna(hw_params(priv).valid_tx_ant);
} }
/* How many times should we repeat the initial rate? */ /* How many times should we repeat the initial rate? */
@ -2972,7 +2979,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
if (priv->bt_full_concurrent) if (priv->bt_full_concurrent)
valid_tx_ant = ANT_A; valid_tx_ant = ANT_A;
else else
valid_tx_ant = priv->hw_params.valid_tx_ant; valid_tx_ant = hw_params(priv).valid_tx_ant;
} }
/* Fill rest of rate table */ /* Fill rest of rate table */
@ -3006,7 +3013,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
if (priv && priv->bt_full_concurrent) { if (priv && priv->bt_full_concurrent) {
/* 1x1 only */ /* 1x1 only */
tbl_type.ant_type = tbl_type.ant_type =
first_antenna(priv->hw_params.valid_tx_ant); first_antenna(hw_params(priv).valid_tx_ant);
} }
/* Indicate to uCode which entries might be MIMO. /* Indicate to uCode which entries might be MIMO.
@ -3097,7 +3104,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
u8 ant_sel_tx; u8 ant_sel_tx;
priv = lq_sta->drv; priv = lq_sta->drv;
valid_tx_ant = priv->hw_params.valid_tx_ant; valid_tx_ant = hw_params(priv).valid_tx_ant;
if (lq_sta->dbg_fixed_rate) { if (lq_sta->dbg_fixed_rate) {
ant_sel_tx = ant_sel_tx =
((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK)
@ -3168,9 +3175,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
desc += sprintf(buff+desc, "fixed rate 0x%X\n", desc += sprintf(buff+desc, "fixed rate 0x%X\n",
lq_sta->dbg_fixed_rate); lq_sta->dbg_fixed_rate);
desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
(priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", (hw_params(priv).valid_tx_ant & ANT_A) ? "ANT_A," : "",
(priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", (hw_params(priv).valid_tx_ant & ANT_B) ? "ANT_B," : "",
(priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); (hw_params(priv).valid_tx_ant & ANT_C) ? "ANT_C" : "");
desc += sprintf(buff+desc, "lq type %s\n", desc += sprintf(buff+desc, "lq type %s\n",
(is_legacy(tbl->lq_type)) ? "legacy" : "HT"); (is_legacy(tbl->lq_type)) ? "legacy" : "HT");
if (is_Ht(tbl->lq_type)) { if (is_Ht(tbl->lq_type)) {

View file

@ -31,6 +31,7 @@
#include "iwl-agn-calib.h" #include "iwl-agn-calib.h"
#include "iwl-helpers.h" #include "iwl-helpers.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-shared.h"
static int iwlagn_disable_bss(struct iwl_priv *priv, static int iwlagn_disable_bss(struct iwl_priv *priv,
struct iwl_rxon_context *ctx, struct iwl_rxon_context *ctx,
@ -40,7 +41,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv,
int ret; int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd,
CMD_SYNC, sizeof(*send), send); CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter; send->filter_flags = old_filter;
@ -66,7 +67,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
send->dev_type = RXON_DEV_TYPE_P2P; send->dev_type = RXON_DEV_TYPE_P2P;
ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd,
CMD_SYNC, sizeof(*send), send); CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter; send->filter_flags = old_filter;
@ -92,7 +93,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv,
int ret; int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC,
sizeof(*send), send); sizeof(*send), send);
send->filter_flags = old_filter; send->filter_flags = old_filter;
@ -121,7 +122,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
ctx->qos_data.qos_active, ctx->qos_data.qos_active,
ctx->qos_data.def_qos_parm.qos_flags); ctx->qos_data.def_qos_parm.qos_flags);
ret = trans_send_cmd_pdu(&priv->trans, ctx->qos_cmd, CMD_SYNC, ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->qos_cmd, CMD_SYNC,
sizeof(struct iwl_qosparam_cmd), sizeof(struct iwl_qosparam_cmd),
&ctx->qos_data.def_qos_parm); &ctx->qos_data.def_qos_parm);
if (ret) if (ret)
@ -131,7 +132,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
static int iwlagn_update_beacon(struct iwl_priv *priv, static int iwlagn_update_beacon(struct iwl_priv *priv,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
dev_kfree_skb(priv->beacon_skb); dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif); priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif);
@ -180,7 +181,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
ctx->staging.ofdm_ht_triple_stream_basic_rates; ctx->staging.ofdm_ht_triple_stream_basic_rates;
rxon_assoc.acquisition_data = ctx->staging.acquisition_data; rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_assoc_cmd, ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_assoc_cmd,
CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc); CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc);
return ret; return ret;
} }
@ -266,7 +267,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
* Associated RXON doesn't clear the station table in uCode, * Associated RXON doesn't clear the station table in uCode,
* so we don't need to restore stations etc. after this. * so we don't need to restore stations etc. after this.
*/ */
ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC,
sizeof(struct iwl_rxon_cmd), &ctx->staging); sizeof(struct iwl_rxon_cmd), &ctx->staging);
if (ret) { if (ret) {
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
@ -315,7 +316,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
@ -362,7 +363,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
slot0 = bcnint / 2; slot0 = bcnint / 2;
slot1 = bcnint - slot0; slot1 = bcnint - slot0;
if (test_bit(STATUS_SCAN_HW, &priv->status) || if (test_bit(STATUS_SCAN_HW, &priv->shrd->status) ||
(!ctx_bss->vif->bss_conf.idle && (!ctx_bss->vif->bss_conf.idle &&
!ctx_bss->vif->bss_conf.assoc)) { !ctx_bss->vif->bss_conf.assoc)) {
slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME;
@ -378,7 +379,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
ctx_pan->beacon_int; ctx_pan->beacon_int;
slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
if (test_bit(STATUS_SCAN_HW, &priv->status)) { if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME; slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
slot1 = IWL_MIN_SLOT_TIME; slot1 = IWL_MIN_SLOT_TIME;
} }
@ -387,7 +388,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
cmd.slots[0].width = cpu_to_le16(slot0); cmd.slots[0].width = cpu_to_le16(slot0);
cmd.slots[1].width = cpu_to_le16(slot1); cmd.slots[1].width = cpu_to_le16(slot1);
ret = trans_send_cmd_pdu(&priv->trans, REPLY_WIPAN_PARAMS, CMD_SYNC, ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WIPAN_PARAMS, CMD_SYNC,
sizeof(cmd), &cmd); sizeof(cmd), &cmd);
if (ret) if (ret)
IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
@ -420,12 +421,12 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
int ret; int ret;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return -EINVAL; return -EINVAL;
if (!iwl_is_alive(priv)) if (!iwl_is_alive(priv->shrd))
return -EBUSY; return -EBUSY;
/* This function hardcodes a bunch of dual-mode assumptions */ /* This function hardcodes a bunch of dual-mode assumptions */
@ -434,6 +435,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
if (!ctx->is_active) if (!ctx->is_active)
return 0; return 0;
/* override BSSID if necessary due to preauth */
if (ctx->preauth_bssid)
memcpy(ctx->staging.bssid_addr, ctx->bssid, ETH_ALEN);
/* always get timestamp with Rx frame */ /* always get timestamp with Rx frame */
ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
@ -462,7 +467,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
* receive commit_rxon request * receive commit_rxon request
* abort any previous channel switch if still in process * abort any previous channel switch if still in process
*/ */
if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) && if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status) &&
(priv->switch_channel != ctx->staging.channel)) { (priv->switch_channel != ctx->staging.channel)) {
IWL_DEBUG_11H(priv, "abort channel switch on %d\n", IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
le16_to_cpu(priv->switch_channel)); le16_to_cpu(priv->switch_channel));
@ -536,14 +541,14 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
IWL_DEBUG_MAC80211(priv, "changed %#x", changed); IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) {
IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
goto out; goto out;
} }
if (!iwl_is_ready(priv)) { if (!iwl_is_ready(priv->shrd)) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
goto out; goto out;
} }
@ -575,7 +580,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
goto out; goto out;
} }
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->shrd->lock, flags);
for_each_context(priv, ctx) { for_each_context(priv, ctx) {
/* Configure HT40 channels */ /* Configure HT40 channels */
@ -619,7 +624,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
ctx->vif); ctx->vif);
} }
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->shrd->lock, flags);
iwl_update_bcast_stations(priv); iwl_update_bcast_stations(priv);
@ -651,7 +656,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
iwlagn_commit_rxon(priv, ctx); iwlagn_commit_rxon(priv, ctx);
} }
out: out:
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
return ret; return ret;
} }
@ -666,7 +671,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *ht_cap; struct ieee80211_sta_ht_cap *ht_cap;
bool need_multiple; bool need_multiple;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
@ -770,7 +775,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
iwl_set_calib_hdr(&cmd.hdr, iwl_set_calib_hdr(&cmd.hdr,
priv->phy_calib_chain_noise_reset_cmd); priv->phy_calib_chain_noise_reset_cmd);
ret = trans_send_cmd_pdu(&priv->trans, ret = iwl_trans_send_cmd_pdu(trans(priv),
REPLY_PHY_CALIBRATION_CMD, REPLY_PHY_CALIBRATION_CMD,
CMD_SYNC, sizeof(cmd), &cmd); CMD_SYNC, sizeof(cmd), &cmd);
if (ret) if (ret)
@ -791,17 +796,17 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
int ret; int ret;
bool force = false; bool force = false;
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
if (unlikely(!iwl_is_ready(priv))) { if (unlikely(!iwl_is_ready(priv->shrd))) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
return; return;
} }
if (unlikely(!ctx->vif)) { if (unlikely(!ctx->vif)) {
IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n"); IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n");
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
return; return;
} }
@ -834,7 +839,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
*/ */
if (ctx->last_tx_rejected) { if (ctx->last_tx_rejected) {
ctx->last_tx_rejected = false; ctx->last_tx_rejected = false;
iwl_wake_any_queue(priv, ctx); iwl_trans_wake_any_queue(trans(priv),
ctx->ctxid);
} }
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
@ -895,6 +901,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
if (!priv->disable_chain_noise_cal) if (!priv->disable_chain_noise_cal)
iwlagn_chain_noise_reset(priv); iwlagn_chain_noise_reset(priv);
priv->start_calib = 1; priv->start_calib = 1;
WARN_ON(ctx->preauth_bssid);
} }
if (changes & BSS_CHANGED_IBSS) { if (changes & BSS_CHANGED_IBSS) {
@ -912,7 +919,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
IWL_ERR(priv, "Error sending IBSS beacon\n"); IWL_ERR(priv, "Error sending IBSS beacon\n");
} }
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
} }
void iwlagn_post_scan(struct iwl_priv *priv) void iwlagn_post_scan(struct iwl_priv *priv)

View file

@ -49,7 +49,7 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id)
return NULL; return NULL;
} }
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
/* Set up the rate scaling to start at selected rate, fall back /* Set up the rate scaling to start at selected rate, fall back
* all the way down to 1M in IEEE order, and then spin on 1M */ * all the way down to 1M in IEEE order, and then spin on 1M */
@ -63,23 +63,23 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id)
if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
rate_flags |= RATE_MCS_CCK_MSK; rate_flags |= RATE_MCS_CCK_MSK;
rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << rate_flags |= first_antenna(hw_params(priv).valid_tx_ant) <<
RATE_MCS_ANT_POS; RATE_MCS_ANT_POS;
rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
link_cmd->rs_table[i].rate_n_flags = rate_n_flags; link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
link_cmd->general_params.single_stream_ant_msk = link_cmd->general_params.single_stream_ant_msk =
first_antenna(priv->hw_params.valid_tx_ant); first_antenna(hw_params(priv).valid_tx_ant);
link_cmd->general_params.dual_stream_ant_msk = link_cmd->general_params.dual_stream_ant_msk =
priv->hw_params.valid_tx_ant & hw_params(priv).valid_tx_ant &
~first_antenna(priv->hw_params.valid_tx_ant); ~first_antenna(hw_params(priv).valid_tx_ant);
if (!link_cmd->general_params.dual_stream_ant_msk) { if (!link_cmd->general_params.dual_stream_ant_msk) {
link_cmd->general_params.dual_stream_ant_msk = ANT_AB; link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) {
link_cmd->general_params.dual_stream_ant_msk = link_cmd->general_params.dual_stream_ant_msk =
priv->hw_params.valid_tx_ant; hw_params(priv).valid_tx_ant;
} }
link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
@ -116,9 +116,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx
if (sta_id_r) if (sta_id_r)
*sta_id_r = sta_id; *sta_id_r = sta_id;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].used |= IWL_STA_LOCAL; priv->stations[sta_id].used |= IWL_STA_LOCAL;
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
/* Set up default rate scaling table in device's station table */ /* Set up default rate scaling table in device's station table */
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id); link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
@ -132,9 +132,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx
if (ret) if (ret)
IWL_ERR(priv, "Link quality command failed (%d)\n", ret); IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].lq = link_cmd; priv->stations[sta_id].lq = link_cmd;
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return 0; return 0;
} }
@ -189,7 +189,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
cmd.len[0] = cmd_size; cmd.len[0] = cmd_size;
if (not_empty || send_if_empty) if (not_empty || send_if_empty)
return trans_send_cmd(&priv->trans, &cmd); return iwl_trans_send_cmd(trans(priv), &cmd);
else else
return 0; return 0;
} }
@ -197,7 +197,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
int iwl_restore_default_wep_keys(struct iwl_priv *priv, int iwl_restore_default_wep_keys(struct iwl_priv *priv,
struct iwl_rxon_context *ctx) struct iwl_rxon_context *ctx)
{ {
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
return iwl_send_static_wepkey_cmd(priv, ctx, false); return iwl_send_static_wepkey_cmd(priv, ctx, false);
} }
@ -208,13 +208,13 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
{ {
int ret; int ret;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
keyconf->keyidx); keyconf->keyidx);
memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
if (iwl_is_rfkill(priv)) { if (iwl_is_rfkill(priv->shrd)) {
IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
/* but keys in device are clear anyway so return success */ /* but keys in device are clear anyway so return success */
return 0; return 0;
@ -232,7 +232,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
{ {
int ret; int ret;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
if (keyconf->keylen != WEP_KEY_LEN_128 && if (keyconf->keylen != WEP_KEY_LEN_128 &&
keyconf->keylen != WEP_KEY_LEN_64) { keyconf->keylen != WEP_KEY_LEN_64) {
@ -311,9 +311,9 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv,
struct iwl_addsta_cmd sta_cmd; struct iwl_addsta_cmd sta_cmd;
int i; int i;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
key_flags |= STA_KEY_FLG_MAP_KEY_MSK; key_flags |= STA_KEY_FLG_MAP_KEY_MSK;
@ -388,16 +388,16 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
if (sta_id == IWL_INVALID_STATION) if (sta_id == IWL_INVALID_STATION)
return -ENOENT; return -ENOENT;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE))
sta_id = IWL_INVALID_STATION; sta_id = IWL_INVALID_STATION;
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
if (sta_id == IWL_INVALID_STATION) if (sta_id == IWL_INVALID_STATION)
return 0; return 0;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
ctx->key_mapping_keys--; ctx->key_mapping_keys--;
@ -430,7 +430,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
if (sta_id == IWL_INVALID_STATION) if (sta_id == IWL_INVALID_STATION)
return -EINVAL; return -EINVAL;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv); keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv);
if (keyconf->hw_key_idx == WEP_INVALID_OFFSET) if (keyconf->hw_key_idx == WEP_INVALID_OFFSET)
@ -493,18 +493,18 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
unsigned long flags; unsigned long flags;
u8 sta_id; u8 sta_id;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL); sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
if (sta_id == IWL_INVALID_STATION) { if (sta_id == IWL_INVALID_STATION) {
IWL_ERR(priv, "Unable to prepare broadcast station\n"); IWL_ERR(priv, "Unable to prepare broadcast station\n");
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return -EINVAL; return -EINVAL;
} }
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
priv->stations[sta_id].used |= IWL_STA_BCAST; priv->stations[sta_id].used |= IWL_STA_BCAST;
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id); link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
if (!link_cmd) { if (!link_cmd) {
@ -513,9 +513,9 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
return -ENOMEM; return -ENOMEM;
} }
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].lq = link_cmd; priv->stations[sta_id].lq = link_cmd;
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return 0; return 0;
} }
@ -539,13 +539,13 @@ int iwl_update_bcast_station(struct iwl_priv *priv,
return -ENOMEM; return -ENOMEM;
} }
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
if (priv->stations[sta_id].lq) if (priv->stations[sta_id].lq)
kfree(priv->stations[sta_id].lq); kfree(priv->stations[sta_id].lq);
else else
IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n"); IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
priv->stations[sta_id].lq = link_cmd; priv->stations[sta_id].lq = link_cmd;
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return 0; return 0;
} }
@ -572,15 +572,15 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
unsigned long flags; unsigned long flags;
struct iwl_addsta_cmd sta_cmd; struct iwl_addsta_cmd sta_cmd;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
/* Remove "disable" flag, to enable Tx for this TID */ /* Remove "disable" flag, to enable Tx for this TID */
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
} }
@ -592,20 +592,20 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
int sta_id; int sta_id;
struct iwl_addsta_cmd sta_cmd; struct iwl_addsta_cmd sta_cmd;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
sta_id = iwl_sta_id(sta); sta_id = iwl_sta_id(sta);
if (sta_id == IWL_INVALID_STATION) if (sta_id == IWL_INVALID_STATION)
return -ENXIO; return -ENXIO;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].sta.station_flags_msk = 0; priv->stations[sta_id].sta.station_flags_msk = 0;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
} }
@ -617,7 +617,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
int sta_id; int sta_id;
struct iwl_addsta_cmd sta_cmd; struct iwl_addsta_cmd sta_cmd;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
sta_id = iwl_sta_id(sta); sta_id = iwl_sta_id(sta);
if (sta_id == IWL_INVALID_STATION) { if (sta_id == IWL_INVALID_STATION) {
@ -625,13 +625,13 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
return -ENXIO; return -ENXIO;
} }
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].sta.station_flags_msk = 0; priv->stations[sta_id].sta.station_flags_msk = 0;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
} }
@ -640,14 +640,14 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
priv->stations[sta_id].sta.sta.modify_mask = 0; priv->stations[sta_id].sta.sta.modify_mask = 0;
priv->stations[sta_id].sta.sleep_tx_count = 0; priv->stations[sta_id].sta.sleep_tx_count = 0;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
} }
@ -655,7 +655,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
priv->stations[sta_id].sta.sta.modify_mask = priv->stations[sta_id].sta.sta.modify_mask =
@ -663,7 +663,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
} }

View file

@ -176,24 +176,24 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
struct iwl_tt_mgmt *tt = &priv->thermal_throttle; struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
unsigned long flags; unsigned long flags;
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
if (tt->state == IWL_TI_CT_KILL) { if (tt->state == IWL_TI_CT_KILL) {
if (priv->thermal_throttle.ct_kill_toggle) { if (priv->thermal_throttle.ct_kill_toggle) {
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
priv->thermal_throttle.ct_kill_toggle = false; priv->thermal_throttle.ct_kill_toggle = false;
} else { } else {
iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
priv->thermal_throttle.ct_kill_toggle = true; priv->thermal_throttle.ct_kill_toggle = true;
} }
iwl_read32(priv, CSR_UCODE_DRV_GP1); iwl_read32(bus(priv), CSR_UCODE_DRV_GP1);
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus(priv)->reg_lock, flags);
if (!iwl_grab_nic_access(priv)) if (!iwl_grab_nic_access(bus(priv)))
iwl_release_nic_access(priv); iwl_release_nic_access(bus(priv));
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus(priv)->reg_lock, flags);
/* Reschedule the ct_kill timer to occur in /* Reschedule the ct_kill timer to occur in
* CT_KILL_EXIT_DURATION seconds to ensure we get a * CT_KILL_EXIT_DURATION seconds to ensure we get a
@ -209,7 +209,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
{ {
if (stop) { if (stop) {
IWL_DEBUG_TEMP(priv, "Stop all queues\n"); IWL_DEBUG_TEMP(priv, "Stop all queues\n");
if (priv->mac80211_registered) if (priv->shrd->mac80211_registered)
ieee80211_stop_queues(priv->hw); ieee80211_stop_queues(priv->hw);
IWL_DEBUG_TEMP(priv, IWL_DEBUG_TEMP(priv,
"Schedule 5 seconds CT_KILL Timer\n"); "Schedule 5 seconds CT_KILL Timer\n");
@ -217,7 +217,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
jiffies + CT_KILL_EXIT_DURATION * HZ); jiffies + CT_KILL_EXIT_DURATION * HZ);
} else { } else {
IWL_DEBUG_TEMP(priv, "Wake all queues\n"); IWL_DEBUG_TEMP(priv, "Wake all queues\n");
if (priv->mac80211_registered) if (priv->shrd->mac80211_registered)
ieee80211_wake_queues(priv->hw); ieee80211_wake_queues(priv->hw);
} }
} }
@ -227,7 +227,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
struct iwl_priv *priv = (struct iwl_priv *)data; struct iwl_priv *priv = (struct iwl_priv *)data;
struct iwl_tt_mgmt *tt = &priv->thermal_throttle; struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
/* temperature timer expired, ready to go into CT_KILL state */ /* temperature timer expired, ready to go into CT_KILL state */
@ -235,7 +235,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
IWL_DEBUG_TEMP(priv, "entering CT_KILL state when " IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "
"temperature timer expired\n"); "temperature timer expired\n");
tt->state = IWL_TI_CT_KILL; tt->state = IWL_TI_CT_KILL;
set_bit(STATUS_CT_KILL, &priv->status); set_bit(STATUS_CT_KILL, &priv->shrd->status);
iwl_perform_ct_kill_task(priv, true); iwl_perform_ct_kill_task(priv, true);
} }
} }
@ -313,23 +313,24 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
tt->tt_power_mode = IWL_POWER_INDEX_5; tt->tt_power_mode = IWL_POWER_INDEX_5;
break; break;
} }
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
if (old_state == IWL_TI_CT_KILL) if (old_state == IWL_TI_CT_KILL)
clear_bit(STATUS_CT_KILL, &priv->status); clear_bit(STATUS_CT_KILL, &priv->shrd->status);
if (tt->state != IWL_TI_CT_KILL && if (tt->state != IWL_TI_CT_KILL &&
iwl_power_update_mode(priv, true)) { iwl_power_update_mode(priv, true)) {
/* TT state not updated /* TT state not updated
* try again during next temperature read * try again during next temperature read
*/ */
if (old_state == IWL_TI_CT_KILL) if (old_state == IWL_TI_CT_KILL)
set_bit(STATUS_CT_KILL, &priv->status); set_bit(STATUS_CT_KILL, &priv->shrd->status);
tt->state = old_state; tt->state = old_state;
IWL_ERR(priv, "Cannot update power mode, " IWL_ERR(priv, "Cannot update power mode, "
"TT state not updated\n"); "TT state not updated\n");
} else { } else {
if (tt->state == IWL_TI_CT_KILL) { if (tt->state == IWL_TI_CT_KILL) {
if (force) { if (force) {
set_bit(STATUS_CT_KILL, &priv->status); set_bit(STATUS_CT_KILL,
&priv->shrd->status);
iwl_perform_ct_kill_task(priv, true); iwl_perform_ct_kill_task(priv, true);
} else { } else {
iwl_prepare_ct_kill_task(priv); iwl_prepare_ct_kill_task(priv);
@ -343,7 +344,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
IWL_DEBUG_TEMP(priv, "Power Index change to %u\n", IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
tt->tt_power_mode); tt->tt_power_mode);
} }
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
} }
} }
@ -453,9 +454,9 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
* in case get disabled before */ * in case get disabled before */
iwl_set_rxon_ht(priv, &priv->current_ht_config); iwl_set_rxon_ht(priv, &priv->current_ht_config);
} }
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
if (old_state == IWL_TI_CT_KILL) if (old_state == IWL_TI_CT_KILL)
clear_bit(STATUS_CT_KILL, &priv->status); clear_bit(STATUS_CT_KILL, &priv->shrd->status);
if (tt->state != IWL_TI_CT_KILL && if (tt->state != IWL_TI_CT_KILL &&
iwl_power_update_mode(priv, true)) { iwl_power_update_mode(priv, true)) {
/* TT state not updated /* TT state not updated
@ -464,7 +465,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
IWL_ERR(priv, "Cannot update power mode, " IWL_ERR(priv, "Cannot update power mode, "
"TT state not updated\n"); "TT state not updated\n");
if (old_state == IWL_TI_CT_KILL) if (old_state == IWL_TI_CT_KILL)
set_bit(STATUS_CT_KILL, &priv->status); set_bit(STATUS_CT_KILL, &priv->shrd->status);
tt->state = old_state; tt->state = old_state;
} else { } else {
IWL_DEBUG_TEMP(priv, IWL_DEBUG_TEMP(priv,
@ -475,7 +476,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
if (force) { if (force) {
IWL_DEBUG_TEMP(priv, IWL_DEBUG_TEMP(priv,
"Enter IWL_TI_CT_KILL\n"); "Enter IWL_TI_CT_KILL\n");
set_bit(STATUS_CT_KILL, &priv->status); set_bit(STATUS_CT_KILL,
&priv->shrd->status);
iwl_perform_ct_kill_task(priv, true); iwl_perform_ct_kill_task(priv, true);
} else { } else {
iwl_prepare_ct_kill_task(priv); iwl_prepare_ct_kill_task(priv);
@ -487,7 +489,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
iwl_perform_ct_kill_task(priv, false); iwl_perform_ct_kill_task(priv, false);
} }
} }
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
} }
} }
@ -506,10 +508,10 @@ static void iwl_bg_ct_enter(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
struct iwl_tt_mgmt *tt = &priv->thermal_throttle; struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
if (!iwl_is_ready(priv)) if (!iwl_is_ready(priv->shrd))
return; return;
if (tt->state != IWL_TI_CT_KILL) { if (tt->state != IWL_TI_CT_KILL) {
@ -535,10 +537,10 @@ static void iwl_bg_ct_exit(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
struct iwl_tt_mgmt *tt = &priv->thermal_throttle; struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
if (!iwl_is_ready(priv)) if (!iwl_is_ready(priv->shrd))
return; return;
/* stop ct_kill_exit_tm timer */ /* stop ct_kill_exit_tm timer */
@ -565,20 +567,20 @@ static void iwl_bg_ct_exit(struct work_struct *work)
void iwl_tt_enter_ct_kill(struct iwl_priv *priv) void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
{ {
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n"); IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");
queue_work(priv->workqueue, &priv->ct_enter); queue_work(priv->shrd->workqueue, &priv->ct_enter);
} }
void iwl_tt_exit_ct_kill(struct iwl_priv *priv) void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
{ {
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n"); IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");
queue_work(priv->workqueue, &priv->ct_exit); queue_work(priv->shrd->workqueue, &priv->ct_exit);
} }
static void iwl_bg_tt_work(struct work_struct *work) static void iwl_bg_tt_work(struct work_struct *work)
@ -586,7 +588,7 @@ static void iwl_bg_tt_work(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
s32 temp = priv->temperature; /* degrees CELSIUS except specified */ s32 temp = priv->temperature; /* degrees CELSIUS except specified */
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
if (priv->cfg->base_params->temperature_kelvin) if (priv->cfg->base_params->temperature_kelvin)
@ -600,11 +602,11 @@ static void iwl_bg_tt_work(struct work_struct *work)
void iwl_tt_handler(struct iwl_priv *priv) void iwl_tt_handler(struct iwl_priv *priv)
{ {
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n"); IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");
queue_work(priv->workqueue, &priv->tt_work); queue_work(priv->shrd->workqueue, &priv->tt_work);
} }
/* Thermal throttling initialization /* Thermal throttling initialization

File diff suppressed because it is too large Load diff

View file

@ -40,6 +40,7 @@
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-agn-calib.h" #include "iwl-agn-calib.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-fh.h"
static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
@ -84,29 +85,29 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
priv->ucode_write_complete = 0; priv->ucode_write_complete = 0;
iwl_write_direct32(priv, iwl_write_direct32(bus(priv),
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);
iwl_write_direct32(priv, iwl_write_direct32(bus(priv),
FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr);
iwl_write_direct32(priv, iwl_write_direct32(bus(priv),
FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);
iwl_write_direct32(priv, iwl_write_direct32(bus(priv),
FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
(iwl_get_dma_hi_addr(phy_addr) (iwl_get_dma_hi_addr(phy_addr)
<< FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);
iwl_write_direct32(priv, iwl_write_direct32(bus(priv),
FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL),
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX |
FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID);
iwl_write_direct32(priv, iwl_write_direct32(bus(priv),
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
@ -193,7 +194,7 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
calib_cfg_cmd.ucd_calib_cfg.flags = calib_cfg_cmd.ucd_calib_cfg.flags =
IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK;
return trans_send_cmd(&priv->trans, &cmd); return iwl_trans_send_cmd(trans(priv), &cmd);
} }
void iwlagn_rx_calib_result(struct iwl_priv *priv, void iwlagn_rx_calib_result(struct iwl_priv *priv,
@ -291,7 +292,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
/* coexistence is disabled */ /* coexistence is disabled */
memset(&coex_cmd, 0, sizeof(coex_cmd)); memset(&coex_cmd, 0, sizeof(coex_cmd));
} }
return trans_send_cmd_pdu(&priv->trans, return iwl_trans_send_cmd_pdu(trans(priv),
COEX_PRIORITY_TABLE_CMD, CMD_SYNC, COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
sizeof(coex_cmd), &coex_cmd); sizeof(coex_cmd), &coex_cmd);
} }
@ -324,7 +325,7 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv)
memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl,
sizeof(iwlagn_bt_prio_tbl)); sizeof(iwlagn_bt_prio_tbl));
if (trans_send_cmd_pdu(&priv->trans, if (iwl_trans_send_cmd_pdu(trans(priv),
REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC,
sizeof(prio_tbl_cmd), &prio_tbl_cmd)) sizeof(prio_tbl_cmd), &prio_tbl_cmd))
IWL_ERR(priv, "failed to send BT prio tbl command\n"); IWL_ERR(priv, "failed to send BT prio tbl command\n");
@ -337,7 +338,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
env_cmd.action = action; env_cmd.action = action;
env_cmd.type = type; env_cmd.type = type;
ret = trans_send_cmd_pdu(&priv->trans, ret = iwl_trans_send_cmd_pdu(trans(priv),
REPLY_BT_COEX_PROT_ENV, CMD_SYNC, REPLY_BT_COEX_PROT_ENV, CMD_SYNC,
sizeof(env_cmd), &env_cmd); sizeof(env_cmd), &env_cmd);
if (ret) if (ret)
@ -350,7 +351,16 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)
{ {
int ret; int ret;
trans_tx_start(&priv->trans); if (!priv->tx_cmd_pool)
priv->tx_cmd_pool =
kmem_cache_create("iwlagn_dev_cmd",
sizeof(struct iwl_device_cmd),
sizeof(void *), 0, NULL);
if (!priv->tx_cmd_pool)
return -ENOMEM;
iwl_trans_tx_start(trans(priv));
ret = iwlagn_send_wimax_coex(priv); ret = iwlagn_send_wimax_coex(priv);
if (ret) if (ret)
@ -369,7 +379,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)
* using sample data 100 bytes apart. If these sample points are good, * using sample data 100 bytes apart. If these sample points are good,
* it's a pretty good bet that everything between them is good, too. * it's a pretty good bet that everything between them is good, too.
*/ */
static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, static int iwl_verify_inst_sparse(struct iwl_priv *priv,
struct fw_desc *fw_desc) struct fw_desc *fw_desc)
{ {
__le32 *image = (__le32 *)fw_desc->v_addr; __le32 *image = (__le32 *)fw_desc->v_addr;
@ -383,9 +393,9 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv,
/* read data comes through single port, auto-incr addr */ /* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log /* NOTE: Use the debugless read so we don't flood kernel log
* if IWL_DL_IO is set */ * if IWL_DL_IO is set */
iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, iwl_write_direct32(bus(priv), HBUS_TARG_MEM_RADDR,
i + IWLAGN_RTC_INST_LOWER_BOUND); i + IWLAGN_RTC_INST_LOWER_BOUND);
val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image)) if (val != le32_to_cpu(*image))
return -EIO; return -EIO;
} }
@ -404,14 +414,14 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len); IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, iwl_write_direct32(bus(priv), HBUS_TARG_MEM_RADDR,
IWLAGN_RTC_INST_LOWER_BOUND); IWLAGN_RTC_INST_LOWER_BOUND);
for (offs = 0; for (offs = 0;
offs < len && errors < 20; offs < len && errors < 20;
offs += sizeof(u32), image++) { offs += sizeof(u32), image++) {
/* read data comes through single port, auto-incr addr */ /* read data comes through single port, auto-incr addr */
val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image)) { if (val != le32_to_cpu(*image)) {
IWL_ERR(priv, "uCode INST section at " IWL_ERR(priv, "uCode INST section at "
"offset 0x%x, is 0x%x, s/b 0x%x\n", "offset 0x%x, is 0x%x, s/b 0x%x\n",
@ -427,7 +437,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
*/ */
static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img) static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img)
{ {
if (!iwlcore_verify_inst_sparse(priv, &img->code)) { if (!iwl_verify_inst_sparse(priv, &img->code)) {
IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n"); IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
return 0; return 0;
} }
@ -478,7 +488,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
int ret; int ret;
enum iwlagn_ucode_type old_type; enum iwlagn_ucode_type old_type;
ret = trans_start_device(&priv->trans); ret = iwl_trans_start_device(trans(priv));
if (ret) if (ret)
return ret; return ret;
@ -495,7 +505,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
return ret; return ret;
} }
trans_kick_nic(&priv->trans); iwl_trans_kick_nic(trans(priv));
/* /*
* Some things may run in the background now, but we * Some things may run in the background now, but we
@ -545,7 +555,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
struct iwl_notification_wait calib_wait; struct iwl_notification_wait calib_wait;
int ret; int ret;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
/* No init ucode required? Curious, but maybe ok */ /* No init ucode required? Curious, but maybe ok */
if (!priv->ucode_init.code.len) if (!priv->ucode_init.code.len)
@ -580,6 +590,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
iwlagn_remove_notification(priv, &calib_wait); iwlagn_remove_notification(priv, &calib_wait);
out: out:
/* Whatever happened, stop the device */ /* Whatever happened, stop the device */
trans_stop_device(&priv->trans); iwl_trans_stop_device(trans(priv));
return ret; return ret;
} }

File diff suppressed because it is too large Load diff

View file

@ -65,54 +65,9 @@
#include "iwl-dev.h" #include "iwl-dev.h"
/* configuration for the _agn devices */
extern struct iwl_cfg iwl5300_agn_cfg;
extern struct iwl_cfg iwl5100_agn_cfg;
extern struct iwl_cfg iwl5350_agn_cfg;
extern struct iwl_cfg iwl5100_bgn_cfg;
extern struct iwl_cfg iwl5100_abg_cfg;
extern struct iwl_cfg iwl5150_agn_cfg;
extern struct iwl_cfg iwl5150_abg_cfg;
extern struct iwl_cfg iwl6005_2agn_cfg;
extern struct iwl_cfg iwl6005_2abg_cfg;
extern struct iwl_cfg iwl6005_2bg_cfg;
extern struct iwl_cfg iwl1030_bgn_cfg;
extern struct iwl_cfg iwl1030_bg_cfg;
extern struct iwl_cfg iwl6030_2agn_cfg;
extern struct iwl_cfg iwl6030_2abg_cfg;
extern struct iwl_cfg iwl6030_2bgn_cfg;
extern struct iwl_cfg iwl6030_2bg_cfg;
extern struct iwl_cfg iwl6000i_2agn_cfg;
extern struct iwl_cfg iwl6000i_2abg_cfg;
extern struct iwl_cfg iwl6000i_2bg_cfg;
extern struct iwl_cfg iwl6000_3agn_cfg;
extern struct iwl_cfg iwl6050_2agn_cfg;
extern struct iwl_cfg iwl6050_2abg_cfg;
extern struct iwl_cfg iwl6150_bgn_cfg;
extern struct iwl_cfg iwl6150_bg_cfg;
extern struct iwl_cfg iwl1000_bgn_cfg;
extern struct iwl_cfg iwl1000_bg_cfg;
extern struct iwl_cfg iwl100_bgn_cfg;
extern struct iwl_cfg iwl100_bg_cfg;
extern struct iwl_cfg iwl130_bgn_cfg;
extern struct iwl_cfg iwl130_bg_cfg;
extern struct iwl_cfg iwl2000_2bgn_cfg;
extern struct iwl_cfg iwl2000_2bg_cfg;
extern struct iwl_cfg iwl2030_2bgn_cfg;
extern struct iwl_cfg iwl2030_2bg_cfg;
extern struct iwl_cfg iwl6035_2agn_cfg;
extern struct iwl_cfg iwl6035_2abg_cfg;
extern struct iwl_cfg iwl6035_2bg_cfg;
extern struct iwl_cfg iwl105_bg_cfg;
extern struct iwl_cfg iwl105_bgn_cfg;
extern struct iwl_cfg iwl135_bg_cfg;
extern struct iwl_cfg iwl135_bgn_cfg;
extern struct iwl_mod_params iwlagn_mod_params;
extern struct ieee80211_ops iwlagn_hw_ops; extern struct ieee80211_ops iwlagn_hw_ops;
int iwl_reset_ict(struct iwl_priv *priv); int iwl_reset_ict(struct iwl_trans *trans);
static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
{ {
@ -122,10 +77,6 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
hdr->data_valid = 1; hdr->data_valid = 1;
} }
/* tx queue */
void iwl_free_tfds_in_queue(struct iwl_priv *priv,
int sta_id, int tid, int freed);
/* RXON */ /* RXON */
int iwlagn_set_pan_params(struct iwl_priv *priv); int iwlagn_set_pan_params(struct iwl_priv *priv);
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
@ -147,13 +98,10 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
enum iwlagn_ucode_type ucode_type); enum iwlagn_ucode_type ucode_type);
/* lib */ /* lib */
void iwl_check_abort_status(struct iwl_priv *priv,
u8 frame_count, u32 status);
int iwlagn_hw_valid_rtc_data_addr(u32 addr); int iwlagn_hw_valid_rtc_data_addr(u32 addr);
int iwlagn_send_tx_power(struct iwl_priv *priv); int iwlagn_send_tx_power(struct iwl_priv *priv);
void iwlagn_temperature(struct iwl_priv *priv); void iwlagn_temperature(struct iwl_priv *priv);
u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv);
int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
int iwlagn_send_beacon_cmd(struct iwl_priv *priv); int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
@ -165,21 +113,14 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
/* tx */ /* tx */
void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
int index);
void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
struct ieee80211_tx_info *info);
int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u16 *ssn); struct ieee80211_sta *sta, u16 tid, u16 *ssn);
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid); struct ieee80211_sta *sta, u16 tid);
int iwlagn_txq_check_empty(struct iwl_priv *priv,
int sta_id, u8 tid, int txq_id);
void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb); struct iwl_rx_mem_buffer *rxb);
void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
static inline u32 iwl_tx_status_to_mac80211(u32 status) static inline u32 iwl_tx_status_to_mac80211(u32 status)
{ {
@ -287,7 +228,7 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
} }
/* eeprom */ /* eeprom */
void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv); void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
/* notification wait support */ /* notification wait support */

View file

@ -60,16 +60,22 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef __iwl_pci_h__ #ifndef __iwl_bus_h__
#define __iwl_pci_h__ #define __iwl_bus_h__
/*This file includes the declaration that are exported from the bus layer */
#include <linux/types.h>
#include <linux/spinlock.h>
struct iwl_shared;
struct iwl_bus; struct iwl_bus;
/** /**
* struct iwl_bus_ops - bus specific operations * struct iwl_bus_ops - bus specific operations
* @get_pm_support: must returns true if the bus can go to sleep * @get_pm_support: must returns true if the bus can go to sleep
* @apm_config: will be called during the config of the APM configuration * @apm_config: will be called during the config of the APM configuration
* @set_drv_data: set the drv_data pointer to the bus layer * @set_drv_data: set the shared data pointer to the bus layer
* @get_hw_id: prints the hw_id in the provided buffer * @get_hw_id: prints the hw_id in the provided buffer
* @write8: write a byte to register at offset ofs * @write8: write a byte to register at offset ofs
* @write32: write a dword to register at offset ofs * @write32: write a dword to register at offset ofs
@ -78,20 +84,29 @@ struct iwl_bus;
struct iwl_bus_ops { struct iwl_bus_ops {
bool (*get_pm_support)(struct iwl_bus *bus); bool (*get_pm_support)(struct iwl_bus *bus);
void (*apm_config)(struct iwl_bus *bus); void (*apm_config)(struct iwl_bus *bus);
void (*set_drv_data)(struct iwl_bus *bus, void *drv_data); void (*set_drv_data)(struct iwl_bus *bus, struct iwl_shared *shrd);
void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len);
void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val);
void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val);
u32 (*read32)(struct iwl_bus *bus, u32 ofs); u32 (*read32)(struct iwl_bus *bus, u32 ofs);
}; };
/**
* struct iwl_bus - bus common data
* @dev - pointer to struct device * that represent the device
* @ops - pointer to iwl_bus_ops
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
* @irq - the irq number for the device
* @reg_lock - protect hw register access
*/
struct iwl_bus { struct iwl_bus {
/* Common data to all buses */ /* Common data to all buses */
void *drv_data; /* driver's context */
struct device *dev; struct device *dev;
struct iwl_bus_ops *ops; const struct iwl_bus_ops *ops;
struct iwl_shared *shrd;
unsigned int irq; unsigned int irq;
spinlock_t reg_lock;
/* pointer to bus specific struct */ /* pointer to bus specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */ /*Ensure that this pointer will always be aligned to sizeof pointer */
@ -108,9 +123,10 @@ static inline void bus_apm_config(struct iwl_bus *bus)
bus->ops->apm_config(bus); bus->ops->apm_config(bus);
} }
static inline void bus_set_drv_data(struct iwl_bus *bus, void *drv_data) static inline void bus_set_drv_data(struct iwl_bus *bus,
struct iwl_shared *shrd)
{ {
bus->ops->set_drv_data(bus, drv_data); bus->ops->set_drv_data(bus, shrd);
} }
static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len) static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len)
@ -136,4 +152,4 @@ static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs)
int __must_check iwl_pci_register_driver(void); int __must_check iwl_pci_register_driver(void);
void iwl_pci_unregister_driver(void); void iwl_pci_unregister_driver(void);
#endif #endif /* __iwl_bus_h__ */

View file

@ -69,6 +69,9 @@
#ifndef __iwl_commands_h__ #ifndef __iwl_commands_h__
#define __iwl_commands_h__ #define __iwl_commands_h__
#include <linux/etherdevice.h>
#include <linux/ieee80211.h>
struct iwl_priv; struct iwl_priv;
/* uCode version contains 4 values: Major/Minor/API/Serial */ /* uCode version contains 4 values: Major/Minor/API/Serial */
@ -670,7 +673,6 @@ struct iwl_rxon_assoc_cmd {
#define IWL_CONN_MAX_LISTEN_INTERVAL 10 #define IWL_CONN_MAX_LISTEN_INTERVAL 10
#define IWL_MAX_UCODE_BEACON_INTERVAL 4 /* 4096 */ #define IWL_MAX_UCODE_BEACON_INTERVAL 4 /* 4096 */
#define IWL39_MAX_UCODE_BEACON_INTERVAL 1 /* 1024 */
/* /*
* REPLY_RXON_TIMING = 0x14 (command, has simple generic response) * REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
@ -806,6 +808,7 @@ struct iwl_qosparam_cmd {
#define IWLAGN_STATION_COUNT 16 #define IWLAGN_STATION_COUNT 16
#define IWL_INVALID_STATION 255 #define IWL_INVALID_STATION 255
#define IWL_MAX_TID_COUNT 9
#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2)
#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8)
@ -3909,6 +3912,7 @@ struct iwlagn_wowlan_kek_kck_material_cmd {
* Union of all expected notifications/responses: * Union of all expected notifications/responses:
* *
*****************************************************************************/ *****************************************************************************/
#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */
struct iwl_rx_packet { struct iwl_rx_packet {
/* /*

View file

@ -42,22 +42,21 @@
#include "iwl-sta.h" #include "iwl-sta.h"
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-helpers.h" #include "iwl-helpers.h"
#include "iwl-shared.h"
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-trans.h" #include "iwl-trans.h"
u32 iwl_debug_level;
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, static void iwl_init_ht_hw_capab(const struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *ht_info, struct ieee80211_sta_ht_cap *ht_info,
enum ieee80211_band band) enum ieee80211_band band)
{ {
u16 max_bit_rate = 0; u16 max_bit_rate = 0;
u8 rx_chains_num = priv->hw_params.rx_chains_num; u8 rx_chains_num = hw_params(priv).rx_chains_num;
u8 tx_chains_num = priv->hw_params.tx_chains_num; u8 tx_chains_num = hw_params(priv).tx_chains_num;
ht_info->cap = 0; ht_info->cap = 0;
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
@ -69,7 +68,7 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
ht_info->cap |= IEEE80211_HT_CAP_SGI_20; ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
max_bit_rate = MAX_BIT_RATE_20_MHZ; max_bit_rate = MAX_BIT_RATE_20_MHZ;
if (priv->hw_params.ht40_channel & BIT(band)) { if (hw_params(priv).ht40_channel & BIT(band)) {
ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
ht_info->cap |= IEEE80211_HT_CAP_SGI_40; ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
ht_info->mcs.rx_mask[4] = 0x01; ht_info->mcs.rx_mask[4] = 0x01;
@ -107,9 +106,9 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
} }
/** /**
* iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom
*/ */
int iwlcore_init_geos(struct iwl_priv *priv) int iwl_init_geos(struct iwl_priv *priv)
{ {
struct iwl_channel_info *ch; struct iwl_channel_info *ch;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
@ -122,7 +121,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
set_bit(STATUS_GEO_CONFIGURED, &priv->status); set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
return 0; return 0;
} }
@ -146,7 +145,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE) if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, iwl_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_5GHZ); IEEE80211_BAND_5GHZ);
sband = &priv->bands[IEEE80211_BAND_2GHZ]; sband = &priv->bands[IEEE80211_BAND_2GHZ];
@ -156,7 +155,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
sband->n_bitrates = IWL_RATE_COUNT_LEGACY; sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE) if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, iwl_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_2GHZ); IEEE80211_BAND_2GHZ);
priv->ieee_channels = channels; priv->ieee_channels = channels;
@ -222,19 +221,19 @@ int iwlcore_init_geos(struct iwl_priv *priv)
priv->bands[IEEE80211_BAND_2GHZ].n_channels, priv->bands[IEEE80211_BAND_2GHZ].n_channels,
priv->bands[IEEE80211_BAND_5GHZ].n_channels); priv->bands[IEEE80211_BAND_5GHZ].n_channels);
set_bit(STATUS_GEO_CONFIGURED, &priv->status); set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
return 0; return 0;
} }
/* /*
* iwlcore_free_geos - undo allocations in iwlcore_init_geos * iwl_free_geos - undo allocations in iwl_init_geos
*/ */
void iwlcore_free_geos(struct iwl_priv *priv) void iwl_free_geos(struct iwl_priv *priv)
{ {
kfree(priv->ieee_channels); kfree(priv->ieee_channels);
kfree(priv->ieee_rates); kfree(priv->ieee_rates);
clear_bit(STATUS_GEO_CONFIGURED, &priv->status); clear_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
} }
static bool iwl_is_channel_extension(struct iwl_priv *priv, static bool iwl_is_channel_extension(struct iwl_priv *priv,
@ -326,7 +325,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
conf = ieee80211_get_hw_conf(priv->hw); conf = ieee80211_get_hw_conf(priv->hw);
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd)); memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
@ -360,7 +359,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
beacon_int = le16_to_cpu(ctx->timing.beacon_interval); beacon_int = le16_to_cpu(ctx->timing.beacon_interval);
} else { } else {
beacon_int = iwl_adjust_beacon_interval(beacon_int, beacon_int = iwl_adjust_beacon_interval(beacon_int,
priv->hw_params.max_beacon_itrvl * TIME_UNIT); IWL_MAX_UCODE_BEACON_INTERVAL * TIME_UNIT);
ctx->timing.beacon_interval = cpu_to_le16(beacon_int); ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
} }
@ -379,7 +378,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
le32_to_cpu(ctx->timing.beacon_init_val), le32_to_cpu(ctx->timing.beacon_init_val),
le16_to_cpu(ctx->timing.atim_window)); le16_to_cpu(ctx->timing.atim_window));
return trans_send_cmd_pdu(&priv->trans, ctx->rxon_timing_cmd, return iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_timing_cmd,
CMD_SYNC, sizeof(ctx->timing), &ctx->timing); CMD_SYNC, sizeof(ctx->timing), &ctx->timing);
} }
@ -809,10 +808,11 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
*/ */
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
&priv->shrd->status))
ieee80211_chswitch_done(ctx->vif, is_success); ieee80211_chswitch_done(ctx->vif, is_success);
} }
@ -857,16 +857,16 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
unsigned long reload_jiffies; unsigned long reload_jiffies;
/* Set the FW error flag -- cleared on iwl_down */ /* Set the FW error flag -- cleared on iwl_down */
set_bit(STATUS_FW_ERROR, &priv->status); set_bit(STATUS_FW_ERROR, &priv->shrd->status);
/* Cancel currently queued command. */ /* Cancel currently queued command. */
clear_bit(STATUS_HCMD_ACTIVE, &priv->status); clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status);
iwlagn_abort_notification_waits(priv); iwlagn_abort_notification_waits(priv);
/* Keep the restart process from trying to send host /* Keep the restart process from trying to send host
* commands by clearing the ready bit */ * commands by clearing the ready bit */
clear_bit(STATUS_READY, &priv->status); clear_bit(STATUS_READY, &priv->shrd->status);
wake_up_interruptible(&priv->wait_command_queue); wake_up_interruptible(&priv->wait_command_queue);
@ -891,63 +891,26 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
priv->reload_count = 0; priv->reload_count = 0;
} }
if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
if (iwlagn_mod_params.restart_fw) { if (iwlagn_mod_params.restart_fw) {
IWL_DEBUG(priv, IWL_DL_FW_ERRORS, IWL_DEBUG_FW_ERRORS(priv,
"Restarting adapter due to uCode error.\n"); "Restarting adapter due to uCode error.\n");
queue_work(priv->workqueue, &priv->restart); queue_work(priv->shrd->workqueue, &priv->restart);
} else } else
IWL_DEBUG(priv, IWL_DL_FW_ERRORS, IWL_DEBUG_FW_ERRORS(priv,
"Detected FW error, but not restarting\n"); "Detected FW error, but not restarting\n");
} }
} }
/**
* iwl_irq_handle_error - called for HW or SW error interrupt from card
*/
void iwl_irq_handle_error(struct iwl_priv *priv)
{
/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
if (priv->cfg->internal_wimax_coex &&
(!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) &
APMS_CLK_VAL_MRB_FUNC_MODE) ||
(iwl_read_prph(priv, APMG_PS_CTRL_REG) &
APMG_PS_CTRL_VAL_RESET_REQ))) {
/*
* Keep the restart process from trying to send host
* commands by clearing the ready bit.
*/
clear_bit(STATUS_READY, &priv->status);
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
wake_up_interruptible(&priv->wait_command_queue);
IWL_ERR(priv, "RF is used by WiMAX\n");
return;
}
IWL_ERR(priv, "Loaded firmware version: %s\n",
priv->hw->wiphy->fw_version);
iwl_dump_nic_error_log(priv);
iwl_dump_csr(priv);
iwl_dump_fh(priv, NULL, false);
iwl_dump_nic_event_log(priv, false, NULL, false);
#ifdef CONFIG_IWLWIFI_DEBUG
if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
iwl_print_rx_config_cmd(priv,
&priv->contexts[IWL_RXON_CTX_BSS]);
#endif
iwlagn_fw_error(priv, false);
}
static int iwl_apm_stop_master(struct iwl_priv *priv) static int iwl_apm_stop_master(struct iwl_priv *priv)
{ {
int ret = 0; int ret = 0;
/* stop device's busmaster DMA activity */ /* stop device's busmaster DMA activity */
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, ret = iwl_poll_bit(bus(priv), CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
if (ret) if (ret)
IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n"); IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n");
@ -961,13 +924,13 @@ void iwl_apm_stop(struct iwl_priv *priv)
{ {
IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n");
clear_bit(STATUS_DEVICE_ENABLED, &priv->status); clear_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status);
/* Stop device's DMA activity */ /* Stop device's DMA activity */
iwl_apm_stop_master(priv); iwl_apm_stop_master(priv);
/* Reset the entire device */ /* Reset the entire device */
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
udelay(10); udelay(10);
@ -975,7 +938,7 @@ void iwl_apm_stop(struct iwl_priv *priv)
* Clear "initialization complete" bit to move adapter from * Clear "initialization complete" bit to move adapter from
* D0A* (powered-up Active) --> D0U* (Uninitialized) state. * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
*/ */
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); iwl_clear_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
} }
@ -995,45 +958,45 @@ int iwl_apm_init(struct iwl_priv *priv)
*/ */
/* Disable L0S exit timer (platform NMI Work/Around) */ /* Disable L0S exit timer (platform NMI Work/Around) */
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
/* /*
* Disable L0s without affecting L1; * Disable L0s without affecting L1;
* don't wait for ICH L0s (ICH bug W/A) * don't wait for ICH L0s (ICH bug W/A)
*/ */
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
/* Set FH wait threshold to maximum (HW error during stress W/A) */ /* Set FH wait threshold to maximum (HW error during stress W/A) */
iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); iwl_set_bit(bus(priv), CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL);
/* /*
* Enable HAP INTA (interrupt from management bus) to * Enable HAP INTA (interrupt from management bus) to
* wake device's PCI Express link L1a -> L0s * wake device's PCI Express link L1a -> L0s
*/ */
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
bus_apm_config(priv->bus); bus_apm_config(priv->bus);
/* Configure analog phase-lock-loop before activating to D0A */ /* Configure analog phase-lock-loop before activating to D0A */
if (priv->cfg->base_params->pll_cfg_val) if (priv->cfg->base_params->pll_cfg_val)
iwl_set_bit(priv, CSR_ANA_PLL_CFG, iwl_set_bit(bus(priv), CSR_ANA_PLL_CFG,
priv->cfg->base_params->pll_cfg_val); priv->cfg->base_params->pll_cfg_val);
/* /*
* Set "initialization complete" bit to move adapter from * Set "initialization complete" bit to move adapter from
* D0U* --> D0A* (powered-up active) state. * D0U* --> D0A* (powered-up active) state.
*/ */
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); iwl_set_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* /*
* Wait for clock stabilization; once stabilized, access to * Wait for clock stabilization; once stabilized, access to
* device-internal resources is supported, e.g. iwl_write_prph() * device-internal resources is supported, e.g. iwl_write_prph()
* and accesses to uCode SRAM. * and accesses to uCode SRAM.
*/ */
ret = iwl_poll_bit(priv, CSR_GP_CNTRL, ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (ret < 0) { if (ret < 0) {
@ -1048,14 +1011,14 @@ int iwl_apm_init(struct iwl_priv *priv)
* do not disable clocks. This preserves any hardware bits already * do not disable clocks. This preserves any hardware bits already
* set by default in "CLK_CTRL_REG" after reset. * set by default in "CLK_CTRL_REG" after reset.
*/ */
iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); iwl_write_prph(bus(priv), APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
udelay(20); udelay(20);
/* Disable L1-Active */ /* Disable L1-Active */
iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, iwl_set_bits_prph(bus(priv), APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS); APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
set_bit(STATUS_DEVICE_ENABLED, &priv->status); set_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status);
out: out:
return ret; return ret;
@ -1069,7 +1032,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
bool defer; bool defer;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
if (priv->tx_power_user_lmt == tx_power && !force) if (priv->tx_power_user_lmt == tx_power && !force)
return 0; return 0;
@ -1089,7 +1052,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
return -EINVAL; return -EINVAL;
} }
if (!iwl_is_ready_rf(priv)) if (!iwl_is_ready_rf(priv->shrd))
return -EIO; return -EIO;
/* scan complete and commit_rxon use tx_power_next value, /* scan complete and commit_rxon use tx_power_next value,
@ -1097,7 +1060,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
priv->tx_power_next = tx_power; priv->tx_power_next = tx_power;
/* do not set tx power when scanning or channel changing */ /* do not set tx power when scanning or channel changing */
defer = test_bit(STATUS_SCANNING, &priv->status) || defer = test_bit(STATUS_SCANNING, &priv->shrd->status) ||
memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
if (defer && !force) { if (defer && !force) {
IWL_DEBUG_INFO(priv, "Deferring tx power set\n"); IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
@ -1135,7 +1098,7 @@ void iwl_send_bt_config(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, "BT coex %s\n", IWL_DEBUG_INFO(priv, "BT coex %s\n",
(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd)) CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
IWL_ERR(priv, "failed to send BT Coex Config\n"); IWL_ERR(priv, "failed to send BT Coex Config\n");
} }
@ -1148,22 +1111,17 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
}; };
if (flags & CMD_ASYNC) if (flags & CMD_ASYNC)
return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD,
CMD_ASYNC, CMD_ASYNC,
sizeof(struct iwl_statistics_cmd), sizeof(struct iwl_statistics_cmd),
&statistics_cmd); &statistics_cmd);
else else
return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD,
CMD_SYNC, CMD_SYNC,
sizeof(struct iwl_statistics_cmd), sizeof(struct iwl_statistics_cmd),
&statistics_cmd); &statistics_cmd);
} }
void iwl_clear_isr_stats(struct iwl_priv *priv)
{
memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
}
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params) const struct ieee80211_tx_queue_params *params)
{ {
@ -1174,7 +1132,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
IWL_DEBUG_MAC80211(priv, "enter\n"); IWL_DEBUG_MAC80211(priv, "enter\n");
if (!iwl_is_ready_rf(priv)) { if (!iwl_is_ready_rf(priv->shrd)) {
IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
return -EIO; return -EIO;
} }
@ -1186,7 +1144,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
q = AC_NUM - 1 - queue; q = AC_NUM - 1 - queue;
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->shrd->lock, flags);
/* /*
* MULTI-FIXME * MULTI-FIXME
@ -1204,7 +1162,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0; ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
} }
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->shrd->lock, flags);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
return 0; return 0;
@ -1232,7 +1190,7 @@ static int iwl_setup_interface(struct iwl_priv *priv,
struct ieee80211_vif *vif = ctx->vif; struct ieee80211_vif *vif = ctx->vif;
int err; int err;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
/* /*
* This variable will be correct only when there's just * This variable will be correct only when there's just
@ -1276,11 +1234,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
cancel_delayed_work_sync(&priv->hw_roc_disable_work); cancel_delayed_work_sync(&priv->hw_roc_disable_work);
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
iwlagn_disable_roc(priv); iwlagn_disable_roc(priv);
if (!iwl_is_ready_rf(priv)) { if (!iwl_is_ready_rf(priv->shrd)) {
IWL_WARN(priv, "Try to add interface when device not ready\n"); IWL_WARN(priv, "Try to add interface when device not ready\n");
err = -EINVAL; err = -EINVAL;
goto out; goto out;
@ -1323,7 +1281,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
ctx->vif = NULL; ctx->vif = NULL;
priv->iw_mode = NL80211_IFTYPE_STATION; priv->iw_mode = NL80211_IFTYPE_STATION;
out: out:
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
return err; return err;
@ -1335,7 +1293,7 @@ static void iwl_teardown_interface(struct iwl_priv *priv,
{ {
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
if (priv->scan_vif == vif) { if (priv->scan_vif == vif) {
iwl_scan_cancel_timeout(priv, 200); iwl_scan_cancel_timeout(priv, 200);
@ -1367,14 +1325,14 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "enter\n"); IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
WARN_ON(ctx->vif != vif); WARN_ON(ctx->vif != vif);
ctx->vif = NULL; ctx->vif = NULL;
iwl_teardown_interface(priv, vif, false); iwl_teardown_interface(priv, vif, false);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
@ -1398,7 +1356,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
{ {
u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE; u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
if (iwl_debug_level & IWL_DL_TX) { if (iwl_get_debug_level(priv->shrd) & IWL_DL_TX) {
if (!priv->tx_traffic) { if (!priv->tx_traffic) {
priv->tx_traffic = priv->tx_traffic =
kzalloc(traffic_size, GFP_KERNEL); kzalloc(traffic_size, GFP_KERNEL);
@ -1406,7 +1364,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
return -ENOMEM; return -ENOMEM;
} }
} }
if (iwl_debug_level & IWL_DL_RX) { if (iwl_get_debug_level(priv->shrd) & IWL_DL_RX) {
if (!priv->rx_traffic) { if (!priv->rx_traffic) {
priv->rx_traffic = priv->rx_traffic =
kzalloc(traffic_size, GFP_KERNEL); kzalloc(traffic_size, GFP_KERNEL);
@ -1433,7 +1391,7 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
__le16 fc; __le16 fc;
u16 len; u16 len;
if (likely(!(iwl_debug_level & IWL_DL_TX))) if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_TX)))
return; return;
if (!priv->tx_traffic) if (!priv->tx_traffic)
@ -1457,7 +1415,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
__le16 fc; __le16 fc;
u16 len; u16 len;
if (likely(!(iwl_debug_level & IWL_DL_RX))) if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_RX)))
return; return;
if (!priv->rx_traffic) if (!priv->rx_traffic)
@ -1614,7 +1572,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
static void iwl_force_rf_reset(struct iwl_priv *priv) static void iwl_force_rf_reset(struct iwl_priv *priv)
{ {
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
if (!iwl_is_any_associated(priv)) { if (!iwl_is_any_associated(priv)) {
@ -1639,7 +1597,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
{ {
struct iwl_force_reset *force_reset; struct iwl_force_reset *force_reset;
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return -EINVAL; return -EINVAL;
if (mode >= IWL_MAX_FORCE_RESET) { if (mode >= IWL_MAX_FORCE_RESET) {
@ -1698,9 +1656,9 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
newtype = ieee80211_iftype_p2p(newtype, newp2p); newtype = ieee80211_iftype_p2p(newtype, newp2p);
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
if (!ctx->vif || !iwl_is_ready_rf(priv)) { if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) {
/* /*
* Huh? But wait ... this can maybe happen when * Huh? But wait ... this can maybe happen when
* we're in the middle of a firmware restart! * we're in the middle of a firmware restart!
@ -1762,36 +1720,16 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
err = 0; err = 0;
out: out:
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
return err; return err;
} }
/* static inline int iwl_check_stuck_queue(struct iwl_priv *priv, int txq)
* On every watchdog tick we check (latest) time stamp. If it does not
* change during timeout period and queue is not empty we reset firmware.
*/
static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt)
{ {
struct iwl_tx_queue *txq = &priv->txq[cnt]; if (iwl_trans_check_stuck_queue(trans(priv), txq)) {
struct iwl_queue *q = &txq->q; int ret = iwl_force_reset(priv, IWL_FW_RESET, false);
unsigned long timeout;
int ret;
if (q->read_ptr == q->write_ptr) {
txq->time_stamp = jiffies;
return 0;
}
timeout = txq->time_stamp +
msecs_to_jiffies(priv->cfg->base_params->wd_timeout);
if (time_after(jiffies, timeout)) {
IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
q->id, priv->cfg->base_params->wd_timeout);
ret = iwl_force_reset(priv, IWL_FW_RESET, false);
return (ret == -EAGAIN) ? 0 : 1; return (ret == -EAGAIN) ? 0 : 1;
} }
return 0; return 0;
} }
@ -1811,7 +1749,7 @@ void iwl_bg_watchdog(unsigned long data)
int cnt; int cnt;
unsigned long timeout; unsigned long timeout;
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
timeout = priv->cfg->base_params->wd_timeout; timeout = priv->cfg->base_params->wd_timeout;
@ -1819,14 +1757,14 @@ void iwl_bg_watchdog(unsigned long data)
return; return;
/* monitor and check for stuck cmd queue */ /* monitor and check for stuck cmd queue */
if (iwl_check_stuck_queue(priv, priv->cmd_queue)) if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue))
return; return;
/* monitor and check for other stuck queues */ /* monitor and check for other stuck queues */
if (iwl_is_any_associated(priv)) { if (iwl_is_any_associated(priv)) {
for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) {
/* skip as we already checked the command queue */ /* skip as we already checked the command queue */
if (cnt == priv->cmd_queue) if (cnt == priv->shrd->cmd_queue)
continue; continue;
if (iwl_check_stuck_queue(priv, cnt)) if (iwl_check_stuck_queue(priv, cnt))
return; return;
@ -1865,12 +1803,12 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval)
quot = (usec / interval) & quot = (usec / interval) &
(iwl_beacon_time_mask_high(priv, (iwl_beacon_time_mask_high(priv,
priv->hw_params.beacon_time_tsf_bits) >> hw_params(priv).beacon_time_tsf_bits) >>
priv->hw_params.beacon_time_tsf_bits); hw_params(priv).beacon_time_tsf_bits);
rem = (usec % interval) & iwl_beacon_time_mask_low(priv, rem = (usec % interval) & iwl_beacon_time_mask_low(priv,
priv->hw_params.beacon_time_tsf_bits); hw_params(priv).beacon_time_tsf_bits);
return (quot << priv->hw_params.beacon_time_tsf_bits) + rem; return (quot << hw_params(priv).beacon_time_tsf_bits) + rem;
} }
/* base is usually what we get from ucode with each received frame, /* base is usually what we get from ucode with each received frame,
@ -1880,64 +1818,50 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
u32 addon, u32 beacon_interval) u32 addon, u32 beacon_interval)
{ {
u32 base_low = base & iwl_beacon_time_mask_low(priv, u32 base_low = base & iwl_beacon_time_mask_low(priv,
priv->hw_params.beacon_time_tsf_bits); hw_params(priv).beacon_time_tsf_bits);
u32 addon_low = addon & iwl_beacon_time_mask_low(priv, u32 addon_low = addon & iwl_beacon_time_mask_low(priv,
priv->hw_params.beacon_time_tsf_bits); hw_params(priv).beacon_time_tsf_bits);
u32 interval = beacon_interval * TIME_UNIT; u32 interval = beacon_interval * TIME_UNIT;
u32 res = (base & iwl_beacon_time_mask_high(priv, u32 res = (base & iwl_beacon_time_mask_high(priv,
priv->hw_params.beacon_time_tsf_bits)) + hw_params(priv).beacon_time_tsf_bits)) +
(addon & iwl_beacon_time_mask_high(priv, (addon & iwl_beacon_time_mask_high(priv,
priv->hw_params.beacon_time_tsf_bits)); hw_params(priv).beacon_time_tsf_bits));
if (base_low > addon_low) if (base_low > addon_low)
res += base_low - addon_low; res += base_low - addon_low;
else if (base_low < addon_low) { else if (base_low < addon_low) {
res += interval + base_low - addon_low; res += interval + base_low - addon_low;
res += (1 << priv->hw_params.beacon_time_tsf_bits); res += (1 << hw_params(priv).beacon_time_tsf_bits);
} else } else
res += (1 << priv->hw_params.beacon_time_tsf_bits); res += (1 << hw_params(priv).beacon_time_tsf_bits);
return cpu_to_le32(res); return cpu_to_le32(res);
} }
#ifdef CONFIG_PM void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
enum iwl_rxon_context_id ctx,
int iwl_suspend(struct iwl_priv *priv) u8 sta_id, u8 tid)
{ {
/* struct ieee80211_vif *vif = priv->contexts[ctx].vif;
* This function is called when system goes into suspend state u8 *addr = priv->stations[sta_id].sta.sta.addr;
* mac80211 will call iwl_mac_stop() from the mac80211 suspend function
* first but since iwl_mac_stop() has no knowledge of who the caller is,
* it will not call apm_ops.stop() to stop the DMA operation.
* Calling apm_ops.stop here to make sure we stop the DMA.
*
* But of course ... if we have configured WoWLAN then we did other
* things already :-)
*/
if (!priv->wowlan)
iwl_apm_stop(priv);
return 0; if (ctx == NUM_IWL_RXON_CTX)
ctx = priv->stations[sta_id].ctxid;
vif = priv->contexts[ctx].vif;
ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
} }
int iwl_resume(struct iwl_priv *priv) void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid)
{ {
bool hw_rfkill = false; struct ieee80211_vif *vif;
u8 *addr = priv->stations[sta_id].sta.sta.addr;
iwl_enable_interrupts(priv); if (ctx == NUM_IWL_RXON_CTX)
ctx = priv->stations[sta_id].ctxid;
vif = priv->contexts[ctx].vif;
if (!(iwl_read32(priv, CSR_GP_CNTRL) & ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
hw_rfkill = true;
if (hw_rfkill)
set_bit(STATUS_RF_KILL_HW, &priv->status);
else
clear_bit(STATUS_RF_KILL_HW, &priv->status);
wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rfkill);
return 0;
} }
#endif /* CONFIG_PM */

View file

@ -71,11 +71,6 @@
struct iwl_host_cmd; struct iwl_host_cmd;
struct iwl_cmd; struct iwl_cmd;
#define IWLWIFI_VERSION "in-tree:"
#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation"
#define DRV_AUTHOR "<ilw@linux.intel.com>"
#define TIME_UNIT 1024 #define TIME_UNIT 1024
#define IWL_CMD(x) case x: return #x #define IWL_CMD(x) case x: return #x
@ -101,23 +96,6 @@ struct iwl_lib_ops {
void (*temperature)(struct iwl_priv *priv); void (*temperature)(struct iwl_priv *priv);
}; };
struct iwl_mod_params {
int sw_crypto; /* def: 0 = using hardware encryption */
int num_of_queues; /* def: HW dependent */
int disable_11n; /* def: 0 = 11n capabilities enabled */
int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */
int antenna; /* def: 0 = both antennas (use diversity) */
int restart_fw; /* def: 1 = restart firmware */
bool plcp_check; /* def: true = enable plcp health check */
bool ack_check; /* def: false = disable ack health check */
bool wd_disable; /* def: false = enable stuck queue check */
bool bt_coex_active; /* def: true = enable bt coex */
int led_mode; /* def: 0 = system default */
bool no_sleep_autoadjust; /* def: true = disable autoadjust */
bool power_save; /* def: false = disable power save */
int power_level; /* def: 1 = power level */
};
/* /*
* @max_ll_items: max number of OTP blocks * @max_ll_items: max number of OTP blocks
* @shadow_ram_support: shadow support for OTP memory * @shadow_ram_support: shadow support for OTP memory
@ -222,16 +200,7 @@ struct iwl_ht_params {
* We enable the driver to be backward compatible wrt API version. The * We enable the driver to be backward compatible wrt API version. The
* driver specifies which APIs it supports (with @ucode_api_max being the * driver specifies which APIs it supports (with @ucode_api_max being the
* highest and @ucode_api_min the lowest). Firmware will only be loaded if * highest and @ucode_api_min the lowest). Firmware will only be loaded if
* it has a supported API version. The firmware's API version will be * it has a supported API version.
* stored in @iwl_priv, enabling the driver to make runtime changes based
* on firmware version used.
*
* For example,
* if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
* Driver interacts with Firmware API version >= 2.
* } else {
* Driver interacts with Firmware API version 1.
* }
* *
* The ideal usage of this infrastructure is to treat a new ucode API * The ideal usage of this infrastructure is to treat a new ucode API
* release as a new hardware revision. * release as a new hardware revision.
@ -292,7 +261,6 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
void iwl_connection_init_rx_config(struct iwl_priv *priv, void iwl_connection_init_rx_config(struct iwl_priv *priv,
struct iwl_rxon_context *ctx); struct iwl_rxon_context *ctx);
void iwl_set_rate(struct iwl_priv *priv); void iwl_set_rate(struct iwl_priv *priv);
void iwl_irq_handle_error(struct iwl_priv *priv);
int iwl_mac_add_interface(struct ieee80211_hw *hw, int iwl_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
void iwl_mac_remove_interface(struct ieee80211_hw *hw, void iwl_mac_remove_interface(struct ieee80211_hw *hw,
@ -398,22 +366,10 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
__le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
u32 addon, u32 beacon_interval); u32 addon, u32 beacon_interval);
#ifdef CONFIG_PM
int iwl_suspend(struct iwl_priv *priv);
int iwl_resume(struct iwl_priv *priv);
#endif /* !CONFIG_PM */
int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg);
void __devexit iwl_remove(struct iwl_priv * priv);
/***************************************************** /*****************************************************
* Error Handling Debugging * Error Handling Debugging
******************************************************/ ******************************************************/
void iwl_dump_nic_error_log(struct iwl_priv *priv);
int iwl_dump_nic_event_log(struct iwl_priv *priv,
bool full_log, char **buf, bool display);
void iwl_dump_csr(struct iwl_priv *priv);
int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
void iwl_print_rx_config_cmd(struct iwl_priv *priv, void iwl_print_rx_config_cmd(struct iwl_priv *priv,
struct iwl_rxon_context *ctx); struct iwl_rxon_context *ctx);
@ -424,79 +380,11 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
} }
#endif #endif
void iwl_clear_isr_stats(struct iwl_priv *priv);
/***************************************************** /*****************************************************
* GEOS * GEOS
******************************************************/ ******************************************************/
int iwlcore_init_geos(struct iwl_priv *priv); int iwl_init_geos(struct iwl_priv *priv);
void iwlcore_free_geos(struct iwl_priv *priv); void iwl_free_geos(struct iwl_priv *priv);
/*************** DRIVER STATUS FUNCTIONS *****/
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */
#define STATUS_INT_ENABLED 2
#define STATUS_RF_KILL_HW 3
#define STATUS_CT_KILL 4
#define STATUS_INIT 5
#define STATUS_ALIVE 6
#define STATUS_READY 7
#define STATUS_TEMPERATURE 8
#define STATUS_GEO_CONFIGURED 9
#define STATUS_EXIT_PENDING 10
#define STATUS_STATISTICS 12
#define STATUS_SCANNING 13
#define STATUS_SCAN_ABORTING 14
#define STATUS_SCAN_HW 15
#define STATUS_POWER_PMI 16
#define STATUS_FW_ERROR 17
#define STATUS_DEVICE_ENABLED 18
#define STATUS_CHANNEL_SWITCH_PENDING 19
static inline int iwl_is_ready(struct iwl_priv *priv)
{
/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
* set but EXIT_PENDING is not */
return test_bit(STATUS_READY, &priv->status) &&
test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
!test_bit(STATUS_EXIT_PENDING, &priv->status);
}
static inline int iwl_is_alive(struct iwl_priv *priv)
{
return test_bit(STATUS_ALIVE, &priv->status);
}
static inline int iwl_is_init(struct iwl_priv *priv)
{
return test_bit(STATUS_INIT, &priv->status);
}
static inline int iwl_is_rfkill_hw(struct iwl_priv *priv)
{
return test_bit(STATUS_RF_KILL_HW, &priv->status);
}
static inline int iwl_is_rfkill(struct iwl_priv *priv)
{
return iwl_is_rfkill_hw(priv);
}
static inline int iwl_is_ctkill(struct iwl_priv *priv)
{
return test_bit(STATUS_CT_KILL, &priv->status);
}
static inline int iwl_is_ready_rf(struct iwl_priv *priv)
{
if (iwl_is_rfkill(priv))
return 0;
return iwl_is_ready(priv);
}
extern void iwl_send_bt_config(struct iwl_priv *priv); extern void iwl_send_bt_config(struct iwl_priv *priv);
extern int iwl_send_statistics_request(struct iwl_priv *priv, extern int iwl_send_statistics_request(struct iwl_priv *priv,

View file

@ -29,50 +29,51 @@
#ifndef __iwl_debug_h__ #ifndef __iwl_debug_h__
#define __iwl_debug_h__ #define __iwl_debug_h__
#include "iwl-bus.h"
#include "iwl-shared.h"
struct iwl_priv; struct iwl_priv;
extern u32 iwl_debug_level;
#define IWL_ERR(p, f, a...) dev_err(p->bus->dev, f, ## a) /*No matter what is m (priv, bus, trans), this will work */
#define IWL_WARN(p, f, a...) dev_warn(p->bus->dev, f, ## a) #define IWL_ERR(m, f, a...) dev_err(bus(m)->dev, f, ## a)
#define IWL_INFO(p, f, a...) dev_info(p->bus->dev, f, ## a) #define IWL_WARN(m, f, a...) dev_warn(bus(m)->dev, f, ## a)
#define IWL_CRIT(p, f, a...) dev_crit(p->bus->dev, f, ## a) #define IWL_INFO(m, f, a...) dev_info(bus(m)->dev, f, ## a)
#define IWL_CRIT(m, f, a...) dev_crit(bus(m)->dev, f, ## a)
#define iwl_print_hex_error(priv, p, len) \ #define iwl_print_hex_error(m, p, len) \
do { \ do { \
print_hex_dump(KERN_ERR, "iwl data: ", \ print_hex_dump(KERN_ERR, "iwl data: ", \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0) } while (0)
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
#define IWL_DEBUG(__priv, level, fmt, args...) \ #define IWL_DEBUG(m, level, fmt, args...) \
do { \ do { \
if (iwl_get_debug_level(__priv) & (level)) \ if (iwl_get_debug_level((m)->shrd) & (level)) \
dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ dev_printk(KERN_ERR, bus(m)->dev, \
"%c %s " fmt, in_interrupt() ? 'I' : 'U', \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \
__func__ , ## args); \ __func__ , ## args); \
} while (0) } while (0)
#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \ #define IWL_DEBUG_LIMIT(m, level, fmt, args...) \
do { \ do { \
if ((iwl_get_debug_level(__priv) & (level)) && net_ratelimit()) \ if (iwl_get_debug_level((m)->shrd) & (level) && net_ratelimit())\
dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ dev_printk(KERN_ERR, bus(m)->dev, \
"%c %s " fmt, in_interrupt() ? 'I' : 'U', \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \
__func__ , ## args); \ __func__ , ## args); \
} while (0) } while (0)
#define iwl_print_hex_dump(priv, level, p, len) \ #define iwl_print_hex_dump(m, level, p, len) \
do { \ do { \
if (iwl_get_debug_level(priv) & level) \ if (iwl_get_debug_level((m)->shrd) & level) \
print_hex_dump(KERN_DEBUG, "iwl data: ", \ print_hex_dump(KERN_DEBUG, "iwl data: ", \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0) } while (0)
#else #else
#define IWL_DEBUG(__priv, level, fmt, args...) #define IWL_DEBUG(m, level, fmt, args...)
#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) #define IWL_DEBUG_LIMIT(m, level, fmt, args...)
static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, #define iwl_print_hex_dump(m, level, p, len)
const void *p, u32 len)
{}
#endif /* CONFIG_IWLWIFI_DEBUG */ #endif /* CONFIG_IWLWIFI_DEBUG */
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
@ -166,6 +167,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a)
#define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)
#define IWL_DEBUG_FW_ERRORS(p, f, a...) IWL_DEBUG(p, IWL_DL_FW_ERRORS, f, ## a)
#define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a) #define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
#define IWL_DEBUG_DROP_LIMIT(p, f, a...) \ #define IWL_DEBUG_DROP_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)

View file

@ -254,7 +254,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
sram = priv->dbgfs_sram_offset & ~0x3; sram = priv->dbgfs_sram_offset & ~0x3;
/* read the first u32 from sram */ /* read the first u32 from sram */
val = iwl_read_targ_mem(priv, sram); val = iwl_read_targ_mem(bus(priv), sram);
for (; len; len--) { for (; len; len--) {
/* put the address at the start of every line */ /* put the address at the start of every line */
@ -273,7 +273,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
if (++offset == 4) { if (++offset == 4) {
sram += 4; sram += 4;
offset = 0; offset = 0;
val = iwl_read_targ_mem(priv, sram); val = iwl_read_targ_mem(bus(priv), sram);
} }
/* put in extra spaces and split lines for human readability */ /* put in extra spaces and split lines for human readability */
@ -340,7 +340,8 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
{ {
struct iwl_priv *priv = file->private_data; struct iwl_priv *priv = file->private_data;
struct iwl_station_entry *station; struct iwl_station_entry *station;
int max_sta = priv->hw_params.max_stations; struct iwl_tid_data *tid_data;
int max_sta = hw_params(priv).max_stations;
char *buf; char *buf;
int i, j, pos = 0; int i, j, pos = 0;
ssize_t ret; ssize_t ret;
@ -363,22 +364,18 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
i, station->sta.sta.addr, i, station->sta.sta.addr,
station->sta.station_flags_msk); station->sta.station_flags_msk);
pos += scnprintf(buf + pos, bufsz - pos, pos += scnprintf(buf + pos, bufsz - pos,
"TID\tseq_num\ttxq_id\tframes\ttfds\t"); "TID\tseq_num\ttxq_id\ttfds\trate_n_flags\n");
pos += scnprintf(buf + pos, bufsz - pos,
"start_idx\tbitmap\t\t\trate_n_flags\n");
for (j = 0; j < MAX_TID_COUNT; j++) { for (j = 0; j < IWL_MAX_TID_COUNT; j++) {
tid_data = &priv->shrd->tid_data[i][j];
pos += scnprintf(buf + pos, bufsz - pos, pos += scnprintf(buf + pos, bufsz - pos,
"%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", "%d:\t%#x\t%#x\t%u\t%#x",
j, station->tid[j].seq_number, j, tid_data->seq_number,
station->tid[j].agg.txq_id, tid_data->agg.txq_id,
station->tid[j].agg.frame_count, tid_data->tfds_in_queue,
station->tid[j].tfds_in_queue, tid_data->agg.rate_n_flags);
station->tid[j].agg.start_idx,
station->tid[j].agg.bitmap,
station->tid[j].agg.rate_n_flags);
if (station->tid[j].agg.wait_for_ba) if (tid_data->agg.wait_for_ba)
pos += scnprintf(buf + pos, bufsz - pos, pos += scnprintf(buf + pos, bufsz - pos,
" - waitforba"); " - waitforba");
pos += scnprintf(buf + pos, bufsz - pos, "\n"); pos += scnprintf(buf + pos, bufsz - pos, "\n");
@ -442,46 +439,6 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
return ret; return ret;
} }
static ssize_t iwl_dbgfs_log_event_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
char *buf;
int pos = 0;
ssize_t ret = -ENOMEM;
ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true);
if (buf) {
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
}
return ret;
}
static ssize_t iwl_dbgfs_log_event_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
u32 event_log_flag;
char buf[8];
int buf_size;
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", &event_log_flag) != 1)
return -EFAULT;
if (event_log_flag == 1)
iwl_dump_nic_event_log(priv, true, NULL, false);
return count;
}
static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
@ -492,7 +449,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
char *buf; char *buf;
ssize_t ret; ssize_t ret;
if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) if (!test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status))
return -EAGAIN; return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL); buf = kzalloc(bufsz, GFP_KERNEL);
@ -562,45 +519,46 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
const size_t bufsz = sizeof(buf); const size_t bufsz = sizeof(buf);
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
test_bit(STATUS_HCMD_ACTIVE, &priv->status)); test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
test_bit(STATUS_INT_ENABLED, &priv->status)); test_bit(STATUS_INT_ENABLED, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
test_bit(STATUS_RF_KILL_HW, &priv->status)); test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
test_bit(STATUS_CT_KILL, &priv->status)); test_bit(STATUS_CT_KILL, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
test_bit(STATUS_INIT, &priv->status)); test_bit(STATUS_INIT, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
test_bit(STATUS_ALIVE, &priv->status)); test_bit(STATUS_ALIVE, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
test_bit(STATUS_READY, &priv->status)); test_bit(STATUS_READY, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
test_bit(STATUS_TEMPERATURE, &priv->status)); test_bit(STATUS_TEMPERATURE, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
test_bit(STATUS_GEO_CONFIGURED, &priv->status)); test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
test_bit(STATUS_EXIT_PENDING, &priv->status)); test_bit(STATUS_EXIT_PENDING, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
test_bit(STATUS_STATISTICS, &priv->status)); test_bit(STATUS_STATISTICS, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
test_bit(STATUS_SCANNING, &priv->status)); test_bit(STATUS_SCANNING, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
test_bit(STATUS_SCAN_ABORTING, &priv->status)); test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
test_bit(STATUS_SCAN_HW, &priv->status)); test_bit(STATUS_SCAN_HW, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
test_bit(STATUS_POWER_PMI, &priv->status)); test_bit(STATUS_POWER_PMI, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
test_bit(STATUS_FW_ERROR, &priv->status)); test_bit(STATUS_FW_ERROR, &priv->shrd->status));
return simple_read_from_buffer(user_buf, count, ppos, buf, pos); return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
} }
static ssize_t iwl_dbgfs_interrupt_read(struct file *file, static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) { size_t count, loff_t *ppos) {
struct iwl_priv *priv = file->private_data; struct iwl_priv *priv = file->private_data;
int pos = 0; int pos = 0;
int cnt = 0; int cnt = 0;
char *buf; char *buf;
@ -613,61 +571,25 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
return -ENOMEM; return -ENOMEM;
} }
pos += scnprintf(buf + pos, bufsz - pos,
"Interrupt Statistics Report:\n");
pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
priv->isr_stats.hw);
pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
priv->isr_stats.sw);
if (priv->isr_stats.sw || priv->isr_stats.hw) {
pos += scnprintf(buf + pos, bufsz - pos,
"\tLast Restarting Code: 0x%X\n",
priv->isr_stats.err_code);
}
#ifdef CONFIG_IWLWIFI_DEBUG
pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
priv->isr_stats.sch);
pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
priv->isr_stats.alive);
#endif
pos += scnprintf(buf + pos, bufsz - pos,
"HW RF KILL switch toggled:\t %u\n",
priv->isr_stats.rfkill);
pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
priv->isr_stats.ctkill);
pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
priv->isr_stats.wakeup);
pos += scnprintf(buf + pos, bufsz - pos,
"Rx command responses:\t\t %u\n",
priv->isr_stats.rx);
for (cnt = 0; cnt < REPLY_MAX; cnt++) { for (cnt = 0; cnt < REPLY_MAX; cnt++) {
if (priv->isr_stats.rx_handlers[cnt] > 0) if (priv->rx_handlers_stats[cnt] > 0)
pos += scnprintf(buf + pos, bufsz - pos, pos += scnprintf(buf + pos, bufsz - pos,
"\tRx handler[%36s]:\t\t %u\n", "\tRx handler[%36s]:\t\t %u\n",
get_cmd_string(cnt), get_cmd_string(cnt),
priv->isr_stats.rx_handlers[cnt]); priv->rx_handlers_stats[cnt]);
} }
pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
priv->isr_stats.tx);
pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
priv->isr_stats.unhandled);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf); kfree(buf);
return ret; return ret;
} }
static ssize_t iwl_dbgfs_interrupt_write(struct file *file, static ssize_t iwl_dbgfs_rx_handlers_write(struct file *file,
const char __user *user_buf, const char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct iwl_priv *priv = file->private_data; struct iwl_priv *priv = file->private_data;
char buf[8]; char buf[8];
int buf_size; int buf_size;
u32 reset_flag; u32 reset_flag;
@ -679,7 +601,8 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
if (sscanf(buf, "%x", &reset_flag) != 1) if (sscanf(buf, "%x", &reset_flag) != 1)
return -EFAULT; return -EFAULT;
if (reset_flag == 0) if (reset_flag == 0)
iwl_clear_isr_stats(priv); memset(&priv->rx_handlers_stats[0], 0,
sizeof(priv->rx_handlers_stats));
return count; return count;
} }
@ -814,14 +737,14 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
return -EINVAL; return -EINVAL;
if (!iwl_is_ready_rf(priv)) if (!iwl_is_ready_rf(priv->shrd))
return -EAGAIN; return -EAGAIN;
priv->power_data.debug_sleep_level_override = value; priv->power_data.debug_sleep_level_override = value;
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
iwl_power_update_mode(priv, true); iwl_power_update_mode(priv, true);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
return count; return count;
} }
@ -870,188 +793,17 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_READ_WRITE_FILE_OPS(sram);
DEBUGFS_READ_FILE_OPS(wowlan_sram); DEBUGFS_READ_FILE_OPS(wowlan_sram);
DEBUGFS_READ_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(nvm); DEBUGFS_READ_FILE_OPS(nvm);
DEBUGFS_READ_FILE_OPS(stations); DEBUGFS_READ_FILE_OPS(stations);
DEBUGFS_READ_FILE_OPS(channels); DEBUGFS_READ_FILE_OPS(channels);
DEBUGFS_READ_FILE_OPS(status); DEBUGFS_READ_FILE_OPS(status);
DEBUGFS_READ_WRITE_FILE_OPS(interrupt); DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers);
DEBUGFS_READ_FILE_OPS(qos); DEBUGFS_READ_FILE_OPS(qos);
DEBUGFS_READ_FILE_OPS(thermal_throttling); DEBUGFS_READ_FILE_OPS(thermal_throttling);
DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
DEBUGFS_READ_FILE_OPS(current_sleep_command); DEBUGFS_READ_FILE_OPS(current_sleep_command);
static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
int pos = 0, ofs = 0;
int cnt = 0, entry;
struct iwl_tx_queue *txq;
struct iwl_queue *q;
struct iwl_rx_queue *rxq = &priv->rxq;
char *buf;
int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
(priv->cfg->base_params->num_of_queues * 32 * 8) + 400;
const u8 *ptr;
ssize_t ret;
if (!priv->txq) {
IWL_ERR(priv, "txq not ready\n");
return -EAGAIN;
}
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate buffer\n");
return -ENOMEM;
}
pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
txq = &priv->txq[cnt];
q = &txq->q;
pos += scnprintf(buf + pos, bufsz - pos,
"q[%d]: read_ptr: %u, write_ptr: %u\n",
cnt, q->read_ptr, q->write_ptr);
}
if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) {
ptr = priv->tx_traffic;
pos += scnprintf(buf + pos, bufsz - pos,
"Tx Traffic idx: %u\n", priv->tx_traffic_idx);
for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
entry++, ofs += 16) {
pos += scnprintf(buf + pos, bufsz - pos,
"0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
buf + pos, bufsz - pos, 0);
pos += strlen(buf + pos);
if (bufsz - pos > 0)
buf[pos++] = '\n';
}
}
}
pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
pos += scnprintf(buf + pos, bufsz - pos,
"read: %u, write: %u\n",
rxq->read, rxq->write);
if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) {
ptr = priv->rx_traffic;
pos += scnprintf(buf + pos, bufsz - pos,
"Rx Traffic idx: %u\n", priv->rx_traffic_idx);
for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
entry++, ofs += 16) {
pos += scnprintf(buf + pos, bufsz - pos,
"0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
buf + pos, bufsz - pos, 0);
pos += strlen(buf + pos);
if (bufsz - pos > 0)
buf[pos++] = '\n';
}
}
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
}
static ssize_t iwl_dbgfs_traffic_log_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 traffic_log;
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", &traffic_log) != 1)
return -EFAULT;
if (traffic_log == 0)
iwl_reset_traffic_log(priv);
return count;
}
static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
struct iwl_priv *priv = file->private_data;
struct iwl_tx_queue *txq;
struct iwl_queue *q;
char *buf;
int pos = 0;
int cnt;
int ret;
const size_t bufsz = sizeof(char) * 64 *
priv->cfg->base_params->num_of_queues;
if (!priv->txq) {
IWL_ERR(priv, "txq not ready\n");
return -EAGAIN;
}
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf)
return -ENOMEM;
for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
txq = &priv->txq[cnt];
q = &txq->q;
pos += scnprintf(buf + pos, bufsz - pos,
"hwq %.2d: read=%u write=%u stop=%d"
" swq_id=%#.2x (ac %d/hwq %d)\n",
cnt, q->read_ptr, q->write_ptr,
!!test_bit(cnt, priv->queue_stopped),
txq->swq_id, txq->swq_id & 3,
(txq->swq_id >> 2) & 0x1f);
if (cnt >= 4)
continue;
/* for the ACs, display the stop count too */
pos += scnprintf(buf + pos, bufsz - pos,
" stop-count: %d\n",
atomic_read(&priv->queue_stop_count[cnt]));
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
}
static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
struct iwl_priv *priv = file->private_data;
struct iwl_rx_queue *rxq = &priv->rxq;
char buf[256];
int pos = 0;
const size_t bufsz = sizeof(buf);
pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
rxq->read);
pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
rxq->write);
pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
rxq->free_count);
if (rxq->rb_stts) {
pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF);
} else {
pos += scnprintf(buf + pos, bufsz - pos,
"closed_rb_num: Not Allocated\n");
}
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static const char *fmt_value = " %-30s %10u\n"; static const char *fmt_value = " %-30s %10u\n";
static const char *fmt_hex = " %-30s 0x%02X\n"; static const char *fmt_hex = " %-30s 0x%02X\n";
static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; static const char *fmt_table = " %-30s %10u %10u %10u %10u\n";
@ -1096,7 +848,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
struct statistics_rx_non_phy *delta_general, *max_general; struct statistics_rx_non_phy *delta_general, *max_general;
struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
if (!iwl_is_alive(priv)) if (!iwl_is_alive(priv->shrd))
return -EAGAIN; return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL); buf = kzalloc(bufsz, GFP_KERNEL);
@ -1522,7 +1274,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
ssize_t ret; ssize_t ret;
struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
if (!iwl_is_alive(priv)) if (!iwl_is_alive(priv->shrd))
return -EAGAIN; return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL); buf = kzalloc(bufsz, GFP_KERNEL);
@ -1716,7 +1468,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
struct statistics_div *div, *accum_div, *delta_div, *max_div; struct statistics_div *div, *accum_div, *delta_div, *max_div;
if (!iwl_is_alive(priv)) if (!iwl_is_alive(priv->shrd))
return -EAGAIN; return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL); buf = kzalloc(bufsz, GFP_KERNEL);
@ -1829,16 +1581,16 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
ssize_t ret; ssize_t ret;
struct statistics_bt_activity *bt, *accum_bt; struct statistics_bt_activity *bt, *accum_bt;
if (!iwl_is_alive(priv)) if (!iwl_is_alive(priv->shrd))
return -EAGAIN; return -EAGAIN;
if (!priv->bt_enable_flag) if (!priv->bt_enable_flag)
return -EINVAL; return -EINVAL;
/* make request to uCode to retrieve statistics information */ /* make request to uCode to retrieve statistics information */
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
ret = iwl_send_statistics_request(priv, CMD_SYNC, false); ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
if (ret) { if (ret) {
IWL_ERR(priv, IWL_ERR(priv,
@ -1917,7 +1669,7 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
(sizeof(struct reply_agg_tx_error_statistics) * 24) + 200; (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200;
ssize_t ret; ssize_t ret;
if (!iwl_is_alive(priv)) if (!iwl_is_alive(priv->shrd))
return -EAGAIN; return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL); buf = kzalloc(bufsz, GFP_KERNEL);
@ -2199,7 +1951,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
const size_t bufsz = sizeof(buf); const size_t bufsz = sizeof(buf);
u32 pwrsave_status; u32 pwrsave_status;
pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) & pwrsave_status = iwl_read32(bus(priv), CSR_GP_CNTRL) &
CSR_GP_REG_POWER_SAVE_STATUS_MSK; CSR_GP_REG_POWER_SAVE_STATUS_MSK;
pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
@ -2229,30 +1981,9 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,
return -EFAULT; return -EFAULT;
/* make request to uCode to retrieve statistics information */ /* make request to uCode to retrieve statistics information */
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
iwl_send_statistics_request(priv, CMD_SYNC, true); iwl_send_statistics_request(priv, CMD_SYNC, true);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
return count;
}
static ssize_t iwl_dbgfs_csr_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 csr;
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", &csr) != 1)
return -EFAULT;
iwl_dump_csr(priv);
return count; return count;
} }
@ -2333,25 +2064,6 @@ static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, len); return simple_read_from_buffer(user_buf, count, ppos, buf, len);
} }
static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
char *buf;
int pos = 0;
ssize_t ret = -EFAULT;
ret = pos = iwl_dump_fh(priv, &buf, true);
if (buf) {
ret = simple_read_from_buffer(user_buf,
count, ppos, buf, pos);
kfree(buf);
}
return ret;
}
static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) { size_t count, loff_t *ppos) {
@ -2504,7 +2216,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
if (sscanf(buf, "%d", &flush) != 1) if (sscanf(buf, "%d", &flush) != 1)
return -EINVAL; return -EINVAL;
if (iwl_is_rfkill(priv)) if (iwl_is_rfkill(priv->shrd))
return -EFAULT; return -EFAULT;
iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
@ -2628,9 +2340,6 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(rx_statistics);
DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
DEBUGFS_READ_FILE_OPS(rx_queue);
DEBUGFS_READ_FILE_OPS(tx_queue);
DEBUGFS_READ_FILE_OPS(ucode_rx_stats); DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
DEBUGFS_READ_FILE_OPS(ucode_tx_stats); DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
DEBUGFS_READ_FILE_OPS(ucode_general_stats); DEBUGFS_READ_FILE_OPS(ucode_general_stats);
@ -2639,9 +2348,7 @@ DEBUGFS_READ_FILE_OPS(chain_noise);
DEBUGFS_READ_FILE_OPS(power_save_status); DEBUGFS_READ_FILE_OPS(power_save_status);
DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
DEBUGFS_WRITE_FILE_OPS(csr);
DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
DEBUGFS_READ_FILE_OPS(fh_reg);
DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
DEBUGFS_READ_WRITE_FILE_OPS(force_reset); DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
@ -2682,11 +2389,10 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(wowlan_sram, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(wowlan_sram, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_handlers, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
@ -2694,14 +2400,9 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
@ -2725,6 +2426,9 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
&priv->disable_sens_cal); &priv->disable_sens_cal);
DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
&priv->disable_chain_noise_cal); &priv->disable_chain_noise_cal);
if (iwl_trans_dbgfs_register(trans(priv), dir_debug))
goto err;
return 0; return 0;
err: err:

View file

@ -36,12 +36,12 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/slab.h>
#include <net/ieee80211_radiotap.h> #include <net/ieee80211_radiotap.h>
#include "iwl-eeprom.h" #include "iwl-eeprom.h"
#include "iwl-csr.h" #include "iwl-csr.h"
#include "iwl-prph.h" #include "iwl-prph.h"
#include "iwl-fh.h"
#include "iwl-debug.h" #include "iwl-debug.h"
#include "iwl-agn-hw.h" #include "iwl-agn-hw.h"
#include "iwl-led.h" #include "iwl-led.h"
@ -50,8 +50,7 @@
#include "iwl-agn-tt.h" #include "iwl-agn-tt.h"
#include "iwl-bus.h" #include "iwl-bus.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-shared.h"
#define DRV_NAME "iwlagn"
struct iwl_tx_queue; struct iwl_tx_queue;
@ -90,14 +89,6 @@ struct iwl_tx_queue;
#define DEFAULT_SHORT_RETRY_LIMIT 7U #define DEFAULT_SHORT_RETRY_LIMIT 7U
#define DEFAULT_LONG_RETRY_LIMIT 4U #define DEFAULT_LONG_RETRY_LIMIT 4U
struct iwl_rx_mem_buffer {
dma_addr_t page_dma;
struct page *page;
struct list_head list;
};
#define rxb_addr(r) page_address(r->page)
/* defined below */ /* defined below */
struct iwl_device_cmd; struct iwl_device_cmd;
@ -156,12 +147,6 @@ struct iwl_queue {
* space less than this */ * space less than this */
}; };
/* One for each TFD */
struct iwl_tx_info {
struct sk_buff *skb;
struct iwl_rxon_context *ctx;
};
/** /**
* 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
@ -173,6 +158,8 @@ struct iwl_tx_info {
* @time_stamp: time (in jiffies) of last read_ptr change * @time_stamp: time (in jiffies) of last read_ptr change
* @need_update: indicates need to update read/write index * @need_update: indicates need to update read/write index
* @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
* @sta_id: valid if sched_retry is set
* @tid: valid if sched_retry is set
* *
* A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
* descriptors) and required locking structures. * descriptors) and required locking structures.
@ -185,12 +172,15 @@ struct iwl_tx_queue {
struct iwl_tfd *tfds; struct iwl_tfd *tfds;
struct iwl_device_cmd **cmd; struct iwl_device_cmd **cmd;
struct iwl_cmd_meta *meta; struct iwl_cmd_meta *meta;
struct iwl_tx_info *txb; struct sk_buff **skbs;
unsigned long time_stamp; unsigned long time_stamp;
u8 need_update; u8 need_update;
u8 sched_retry; u8 sched_retry;
u8 active; u8 active;
u8 swq_id; u8 swq_id;
u16 sta_id;
u16 tid;
}; };
#define IWL_NUM_SCAN_RATES (2) #define IWL_NUM_SCAN_RATES (2)
@ -254,13 +244,6 @@ struct iwl_channel_info {
#define IWL_DEFAULT_CMD_QUEUE_NUM 4 #define IWL_DEFAULT_CMD_QUEUE_NUM 4
#define IWL_IPAN_CMD_QUEUE_NUM 9 #define IWL_IPAN_CMD_QUEUE_NUM 9
/*
* This queue number is required for proper operation
* because the ucode will stop/start the scheduler as
* required.
*/
#define IWL_IPAN_MCAST_QUEUE 8
#define IEEE80211_DATA_LEN 2304 #define IEEE80211_DATA_LEN 2304
#define IEEE80211_4ADDR_LEN 30 #define IEEE80211_4ADDR_LEN 30
#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
@ -334,81 +317,11 @@ struct iwl_host_cmd {
#define SUP_RATE_11B_MAX_NUM_CHANNELS 4 #define SUP_RATE_11B_MAX_NUM_CHANNELS 4
#define SUP_RATE_11G_MAX_NUM_CHANNELS 12 #define SUP_RATE_11G_MAX_NUM_CHANNELS 12
/**
* struct iwl_rx_queue - Rx queue
* @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
* @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
* @read: Shared index to newest available Rx buffer
* @write: Shared index to oldest written Rx packet
* @free_count: Number of pre-allocated buffers in rx_free
* @rx_free: list of free SKBs for use
* @rx_used: List of Rx buffers with no SKB
* @need_update: flag to indicate we need to update read/write index
* @rb_stts: driver's pointer to receive buffer status
* @rb_stts_dma: bus address of receive buffer status
*
* NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
*/
struct iwl_rx_queue {
__le32 *bd;
dma_addr_t bd_dma;
struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
u32 read;
u32 write;
u32 free_count;
u32 write_actual;
struct list_head rx_free;
struct list_head rx_used;
int need_update;
struct iwl_rb_status *rb_stts;
dma_addr_t rb_stts_dma;
spinlock_t lock;
};
#define IWL_SUPPORTED_RATES_IE_LEN 8 #define IWL_SUPPORTED_RATES_IE_LEN 8
#define MAX_TID_COUNT 9
#define IWL_INVALID_RATE 0xFF #define IWL_INVALID_RATE 0xFF
#define IWL_INVALID_VALUE -1 #define IWL_INVALID_VALUE -1
/**
* struct iwl_ht_agg -- aggregation status while waiting for block-ack
* @txq_id: Tx queue used for Tx attempt
* @frame_count: # frames attempted by Tx command
* @wait_for_ba: Expect block-ack before next Tx reply
* @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx window
* @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx window
* @bitmap1: High order, one bit for each frame pending ACK in Tx window
* @rate_n_flags: Rate at which Tx was attempted
*
* If REPLY_TX indicates that aggregation was attempted, driver must wait
* for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info
* until block ack arrives.
*/
struct iwl_ht_agg {
u16 txq_id;
u16 frame_count;
u16 wait_for_ba;
u16 start_idx;
u64 bitmap;
u32 rate_n_flags;
#define IWL_AGG_OFF 0
#define IWL_AGG_ON 1
#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
#define IWL_EMPTYING_HW_QUEUE_DELBA 3
u8 state;
u8 tx_fifo;
};
struct iwl_tid_data {
u16 seq_number; /* agn only */
u16 tfds_in_queue;
struct iwl_ht_agg agg;
};
union iwl_ht_rate_supp { union iwl_ht_rate_supp {
u16 rates; u16 rates;
struct { struct {
@ -459,7 +372,6 @@ struct iwl_qos_info {
*/ */
struct iwl_station_entry { struct iwl_station_entry {
struct iwl_addsta_cmd sta; struct iwl_addsta_cmd sta;
struct iwl_tid_data tid[MAX_TID_COUNT];
u8 used, ctxid; u8 used, ctxid;
struct iwl_link_quality_cmd *lq; struct iwl_link_quality_cmd *lq;
}; };
@ -647,54 +559,6 @@ struct iwl_sensitivity_ranges {
#define CELSIUS_TO_KELVIN(x) ((x)+273) #define CELSIUS_TO_KELVIN(x) ((x)+273)
/**
* struct iwl_hw_params
* @max_txq_num: Max # Tx queues supported
* @scd_bc_tbls_size: size of scheduler byte count tables
* @tfd_size: TFD size
* @tx/rx_chains_num: Number of TX/RX chains
* @valid_tx/rx_ant: usable antennas
* @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
* @max_rxq_log: Log-base-2 of max_rxq_size
* @rx_page_order: Rx buffer page order
* @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
* @max_stations:
* @ht40_channel: is 40MHz width possible in band 2.4
* BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
* @sw_crypto: 0 for hw, 1 for sw
* @max_xxx_size: for ucode uses
* @ct_kill_threshold: temperature threshold
* @beacon_time_tsf_bits: number of valid tsf bits for beacon time
* @calib_init_cfg: setup initial calibrations for the hw
* @calib_rt_cfg: setup runtime calibrations for the hw
* @struct iwl_sensitivity_ranges: range of sensitivity values
*/
struct iwl_hw_params {
u8 max_txq_num;
u16 scd_bc_tbls_size;
u32 tfd_size;
u8 tx_chains_num;
u8 rx_chains_num;
u8 valid_tx_ant;
u8 valid_rx_ant;
u16 max_rxq_size;
u16 max_rxq_log;
u32 rx_page_order;
u8 max_stations;
u8 ht40_channel;
u8 max_beacon_itrvl; /* in 1024 ms */
u32 max_inst_size;
u32 max_data_size;
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 */
u16 beacon_time_tsf_bits;
u32 calib_init_cfg;
u32 calib_rt_cfg;
const struct iwl_sensitivity_ranges *sens;
};
/****************************************************************************** /******************************************************************************
* *
* Functions implemented in core module which are forward declared here * Functions implemented in core module which are forward declared here
@ -710,26 +574,6 @@ struct iwl_hw_params {
****************************************************************************/ ****************************************************************************/
extern void iwl_update_chain_flags(struct iwl_priv *priv); extern void iwl_update_chain_flags(struct iwl_priv *priv);
extern const u8 iwl_bcast_addr[ETH_ALEN]; extern const u8 iwl_bcast_addr[ETH_ALEN];
extern int iwl_queue_space(const struct iwl_queue *q);
static inline int iwl_queue_used(const struct iwl_queue *q, int i)
{
return q->write_ptr >= q->read_ptr ?
(i >= q->read_ptr && i < q->write_ptr) :
!(i < q->read_ptr && i >= q->write_ptr);
}
static inline u8 get_cmd_index(struct iwl_queue *q, u32 index)
{
return index & (q->n_window - 1);
}
struct iwl_dma_ptr {
dma_addr_t dma;
void *addr;
size_t size;
};
#define IWL_OPERATION_MODE_AUTO 0 #define IWL_OPERATION_MODE_AUTO 0
#define IWL_OPERATION_MODE_HT_ONLY 1 #define IWL_OPERATION_MODE_HT_ONLY 1
@ -897,22 +741,6 @@ enum iwl_pa_type {
IWL_PA_INTERNAL = 1, IWL_PA_INTERNAL = 1,
}; };
/* interrupt statistics */
struct isr_statistics {
u32 hw;
u32 sw;
u32 err_code;
u32 sch;
u32 alive;
u32 rfkill;
u32 ctkill;
u32 wakeup;
u32 rx;
u32 rx_handlers[REPLY_MAX];
u32 tx;
u32 unhandled;
};
/* reply_tx_statistics (for _agn devices) */ /* reply_tx_statistics (for _agn devices) */
struct reply_tx_error_statistics { struct reply_tx_error_statistics {
u32 pp_delay; u32 pp_delay;
@ -1114,20 +942,9 @@ struct iwl_notification_wait {
bool triggered, aborted; bool triggered, aborted;
}; };
enum iwl_rxon_context_id {
IWL_RXON_CTX_BSS,
IWL_RXON_CTX_PAN,
NUM_IWL_RXON_CTX
};
struct iwl_rxon_context { struct iwl_rxon_context {
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
const u8 *ac_to_fifo;
const u8 *ac_to_queue;
u8 mcast_queue;
/* /*
* We could use the vif to indicate active, but we * We could use the vif to indicate active, but we
* also need it to be active during disabling when * also need it to be active during disabling when
@ -1175,6 +992,9 @@ struct iwl_rxon_context {
u8 extension_chan_offset; u8 extension_chan_offset;
} ht; } ht;
u8 bssid[ETH_ALEN];
bool preauth_bssid;
bool last_tx_rejected; bool last_tx_rejected;
}; };
@ -1203,16 +1023,17 @@ struct iwl_testmode_trace {
}; };
#endif #endif
/* uCode ownership */
#define IWL_OWNERSHIP_DRIVER 0
#define IWL_OWNERSHIP_TM 1
struct iwl_priv { struct iwl_priv {
/*data shared among all the driver's layers */
struct iwl_shared _shrd;
struct iwl_shared *shrd;
/* ieee device used by generic ieee processing code */ /* ieee device used by generic ieee processing code */
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct ieee80211_channel *ieee_channels; struct ieee80211_channel *ieee_channels;
struct ieee80211_rate *ieee_rates; struct ieee80211_rate *ieee_rates;
struct kmem_cache *tx_cmd_pool;
struct iwl_cfg *cfg; struct iwl_cfg *cfg;
enum ieee80211_band band; enum ieee80211_band band;
@ -1238,6 +1059,9 @@ struct iwl_priv {
/* jiffies when last recovery from statistics was performed */ /* jiffies when last recovery from statistics was performed */
unsigned long rx_statistics_jiffies; unsigned long rx_statistics_jiffies;
/*counters */
u32 rx_handlers_stats[REPLY_MAX];
/* force reset */ /* force reset */
struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
@ -1268,21 +1092,12 @@ struct iwl_priv {
u8 scan_tx_ant[IEEE80211_NUM_BANDS]; u8 scan_tx_ant[IEEE80211_NUM_BANDS];
u8 mgmt_tx_ant; u8 mgmt_tx_ant;
/* spinlock */ /*TODO: remove these pointers - use bus(priv) instead */
spinlock_t lock; /* protect general shared data */
spinlock_t hcmd_lock; /* protect hcmd */
spinlock_t reg_lock; /* protect hw register access */
struct mutex mutex;
struct iwl_bus *bus; /* bus specific data */ struct iwl_bus *bus; /* bus specific data */
struct iwl_trans trans;
/* microcode/device supports multiple contexts */ /* microcode/device supports multiple contexts */
u8 valid_contexts; u8 valid_contexts;
/* command queue number */
u8 cmd_queue;
/* max number of station keys */ /* max number of station keys */
u8 sta_key_max_num; u8 sta_key_max_num;
@ -1296,9 +1111,6 @@ struct iwl_priv {
u32 ucode_ver; /* version of ucode, copy of u32 ucode_ver; /* version of ucode, copy of
iwl_ucode.ver */ iwl_ucode.ver */
/* uCode owner: default: IWL_OWNERSHIP_DRIVER */
u8 ucode_owner;
struct fw_img ucode_rt; struct fw_img ucode_rt;
struct fw_img ucode_init; struct fw_img ucode_init;
struct fw_img ucode_wowlan; struct fw_img ucode_wowlan;
@ -1334,48 +1146,21 @@ struct iwl_priv {
int activity_timer_active; int activity_timer_active;
/* Rx and Tx DMA processing queues */
struct iwl_rx_queue rxq;
struct iwl_tx_queue *txq;
unsigned long txq_ctx_active_msk;
struct iwl_dma_ptr kw; /* keep warm address */
struct iwl_dma_ptr scd_bc_tbls;
u32 scd_base_addr; /* scheduler sram base address */
unsigned long status;
/* counts mgmt, ctl, and data packets */ /* counts mgmt, ctl, and data packets */
struct traffic_stats tx_stats; struct traffic_stats tx_stats;
struct traffic_stats rx_stats; struct traffic_stats rx_stats;
/* counts interrupts */
struct isr_statistics isr_stats;
struct iwl_power_mgr power_data; struct iwl_power_mgr power_data;
struct iwl_tt_mgmt thermal_throttle; struct iwl_tt_mgmt thermal_throttle;
/* station table variables */ /* station table variables */
/* Note: if lock and sta_lock are needed, lock must be acquired first */
spinlock_t sta_lock;
int num_stations; int num_stations;
struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; struct iwl_station_entry stations[IWLAGN_STATION_COUNT];
unsigned long ucode_key_table; unsigned long ucode_key_table;
/* queue refcounts */
#define IWL_MAX_HW_QUEUES 32
unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
/* for each AC */
atomic_t queue_stop_count[4];
/* Indication if ieee80211_ops->open has been called */ /* Indication if ieee80211_ops->open has been called */
u8 is_open; u8 is_open;
u8 mac80211_registered;
bool wowlan;
/* eeprom -- this is in the card's little endian byte order */ /* eeprom -- this is in the card's little endian byte order */
u8 *eeprom; u8 *eeprom;
int nvm_device_type; int nvm_device_type;
@ -1411,14 +1196,6 @@ struct iwl_priv {
} accum_stats, delta_stats, max_delta_stats; } accum_stats, delta_stats, max_delta_stats;
#endif #endif
/* INT ICT Table */
__le32 *ict_tbl;
void *ict_tbl_vir;
dma_addr_t ict_tbl_dma;
dma_addr_t aligned_ict_tbl_dma;
int ict_index;
u32 inta;
bool use_ict;
/* /*
* reporting the number of tids has AGG on. 0 means * reporting the number of tids has AGG on. 0 means
* no AGGREGATION * no AGGREGATION
@ -1475,15 +1252,8 @@ struct iwl_priv {
struct iwl_rxon_context *cur_rssi_ctx; struct iwl_rxon_context *cur_rssi_ctx;
bool bt_is_sco; bool bt_is_sco;
struct iwl_hw_params hw_params;
u32 inta_mask;
struct workqueue_struct *workqueue;
struct work_struct restart; struct work_struct restart;
struct work_struct scan_completed; struct work_struct scan_completed;
struct work_struct rx_replenish;
struct work_struct abort_scan; struct work_struct abort_scan;
struct work_struct beacon_update; struct work_struct beacon_update;
@ -1499,8 +1269,6 @@ struct iwl_priv {
struct work_struct bt_full_concurrency; struct work_struct bt_full_concurrency;
struct work_struct bt_runtime_config; struct work_struct bt_runtime_config;
struct tasklet_struct irq_tasklet;
struct delayed_work scan_check; struct delayed_work scan_check;
/* TX Power */ /* TX Power */
@ -1509,12 +1277,6 @@ struct iwl_priv {
s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */
s8 tx_power_next; s8 tx_power_next;
#ifdef CONFIG_IWLWIFI_DEBUG
/* debugging info */
u32 debug_level; /* per device debugging will override global
iwl_debug_level if set */
#endif /* CONFIG_IWLWIFI_DEBUG */
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
/* debugfs */ /* debugfs */
u16 tx_traffic_idx; u16 tx_traffic_idx;
@ -1552,47 +1314,7 @@ struct iwl_priv {
bool have_rekey_data; bool have_rekey_data;
}; /*iwl_priv */ }; /*iwl_priv */
static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) extern struct iwl_mod_params iwlagn_mod_params;
{
set_bit(txq_id, &priv->txq_ctx_active_msk);
}
static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
{
clear_bit(txq_id, &priv->txq_ctx_active_msk);
}
#ifdef CONFIG_IWLWIFI_DEBUG
/*
* iwl_get_debug_level: Return active debug level for device
*
* Using sysfs it is possible to set per device debug level. This debug
* level will be used if set, otherwise the global debug level which can be
* set via module parameter is used.
*/
static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
{
if (priv->debug_level)
return priv->debug_level;
else
return iwl_debug_level;
}
#else
static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
{
return iwl_debug_level;
}
#endif
static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv,
int txq_id, int idx)
{
if (priv->txq[txq_id].txb[idx].skb)
return (struct ieee80211_hdr *)priv->txq[txq_id].
txb[idx].skb->data;
return NULL;
}
static inline struct iwl_rxon_context * static inline struct iwl_rxon_context *
iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
@ -1659,13 +1381,4 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch)
return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
} }
static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page)
{
__free_pages(page, priv->hw_params.rx_page_order);
}
static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page)
{
free_pages(page, priv->hw_params.rx_page_order);
}
#endif /* __iwl_dev_h__ */ #endif /* __iwl_dev_h__ */

View file

@ -29,6 +29,8 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
struct iwl_priv;
#if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__)
#undef TRACE_EVENT #undef TRACE_EVENT
#define TRACE_EVENT(name, proto, ...) \ #define TRACE_EVENT(name, proto, ...) \

View file

@ -155,11 +155,11 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv)
for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
/* Request semaphore */ /* Request semaphore */
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
/* See if we got it */ /* See if we got it */
ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, ret = iwl_poll_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
EEPROM_SEM_TIMEOUT); EEPROM_SEM_TIMEOUT);
@ -176,14 +176,14 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv)
static void iwl_eeprom_release_semaphore(struct iwl_priv *priv) static void iwl_eeprom_release_semaphore(struct iwl_priv *priv)
{ {
iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, iwl_clear_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
} }
static int iwl_eeprom_verify_signature(struct iwl_priv *priv) static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
{ {
u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
int ret = 0; int ret = 0;
IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp); IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp);
@ -216,17 +216,17 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
{ {
iwl_read32(priv, CSR_OTP_GP_REG); iwl_read32(bus(priv), CSR_OTP_GP_REG);
if (mode == IWL_OTP_ACCESS_ABSOLUTE) if (mode == IWL_OTP_ACCESS_ABSOLUTE)
iwl_clear_bit(priv, CSR_OTP_GP_REG, iwl_clear_bit(bus(priv), CSR_OTP_GP_REG,
CSR_OTP_GP_REG_OTP_ACCESS_MODE); CSR_OTP_GP_REG_OTP_ACCESS_MODE);
else else
iwl_set_bit(priv, CSR_OTP_GP_REG, iwl_set_bit(bus(priv), CSR_OTP_GP_REG,
CSR_OTP_GP_REG_OTP_ACCESS_MODE); CSR_OTP_GP_REG_OTP_ACCESS_MODE);
} }
static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) static int iwl_get_nvm_type(struct iwl_priv *priv, u32 hw_rev)
{ {
u32 otpgp; u32 otpgp;
int nvm_type; int nvm_type;
@ -243,7 +243,7 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev)
nvm_type = NVM_DEVICE_TYPE_EEPROM; nvm_type = NVM_DEVICE_TYPE_EEPROM;
break; break;
default: default:
otpgp = iwl_read32(priv, CSR_OTP_GP_REG); otpgp = iwl_read32(bus(priv), CSR_OTP_GP_REG);
if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT)
nvm_type = NVM_DEVICE_TYPE_OTP; nvm_type = NVM_DEVICE_TYPE_OTP;
else else
@ -258,22 +258,22 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
int ret; int ret;
/* Enable 40MHz radio clock */ /* Enable 40MHz radio clock */
iwl_write32(priv, CSR_GP_CNTRL, iwl_write32(bus(priv), CSR_GP_CNTRL,
iwl_read32(priv, CSR_GP_CNTRL) | iwl_read32(bus(priv), CSR_GP_CNTRL) |
CSR_GP_CNTRL_REG_FLAG_INIT_DONE); CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* wait for clock to be ready */ /* wait for clock to be ready */
ret = iwl_poll_bit(priv, CSR_GP_CNTRL, ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
25000); 25000);
if (ret < 0) if (ret < 0)
IWL_ERR(priv, "Time out access OTP\n"); IWL_ERR(priv, "Time out access OTP\n");
else { else {
iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, iwl_set_bits_prph(bus(priv), APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ); APMG_PS_CTRL_VAL_RESET_REQ);
udelay(5); udelay(5);
iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, iwl_clear_bits_prph(bus(priv), APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ); APMG_PS_CTRL_VAL_RESET_REQ);
/* /*
@ -281,7 +281,7 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
* this is only applicable for HW with OTP shadow RAM * this is only applicable for HW with OTP shadow RAM
*/ */
if (priv->cfg->base_params->shadow_ram_support) if (priv->cfg->base_params->shadow_ram_support)
iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG, iwl_set_bit(bus(priv), CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED); CSR_RESET_LINK_PWR_MGMT_DISABLED);
} }
return ret; return ret;
@ -293,9 +293,9 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat
u32 r; u32 r;
u32 otpgp; u32 otpgp;
iwl_write32(priv, CSR_EEPROM_REG, iwl_write32(bus(priv), CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
ret = iwl_poll_bit(priv, CSR_EEPROM_REG, ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG,
CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK,
CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK,
IWL_EEPROM_ACCESS_TIMEOUT); IWL_EEPROM_ACCESS_TIMEOUT);
@ -303,13 +303,13 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat
IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
return ret; return ret;
} }
r = iwl_read32(priv, CSR_EEPROM_REG); r = iwl_read32(bus(priv), CSR_EEPROM_REG);
/* check for ECC errors: */ /* check for ECC errors: */
otpgp = iwl_read32(priv, CSR_OTP_GP_REG); otpgp = iwl_read32(bus(priv), CSR_OTP_GP_REG);
if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
/* stop in this case */ /* stop in this case */
/* set the uncorrectable OTP ECC bit for acknowledgement */ /* set the uncorrectable OTP ECC bit for acknowledgement */
iwl_set_bit(priv, CSR_OTP_GP_REG, iwl_set_bit(bus(priv), CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n"); IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n");
return -EINVAL; return -EINVAL;
@ -317,7 +317,7 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat
if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
/* continue in this case */ /* continue in this case */
/* set the correctable OTP ECC bit for acknowledgement */ /* set the correctable OTP ECC bit for acknowledgement */
iwl_set_bit(priv, CSR_OTP_GP_REG, iwl_set_bit(bus(priv), CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
} }
@ -424,14 +424,14 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
{ {
__le16 *e; __le16 *e;
u32 gp = iwl_read32(priv, CSR_EEPROM_GP); u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP);
int sz; int sz;
int ret; int ret;
u16 addr; u16 addr;
u16 validblockaddr = 0; u16 validblockaddr = 0;
u16 cache_addr = 0; u16 cache_addr = 0;
priv->nvm_device_type = iwlcore_get_nvm_type(priv, hw_rev); priv->nvm_device_type = iwl_get_nvm_type(priv, hw_rev);
if (priv->nvm_device_type == -ENOENT) if (priv->nvm_device_type == -ENOENT)
return -ENOENT; return -ENOENT;
/* allocate eeprom */ /* allocate eeprom */
@ -469,11 +469,11 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
ret = -ENOENT; ret = -ENOENT;
goto done; goto done;
} }
iwl_write32(priv, CSR_EEPROM_GP, iwl_write32(bus(priv), CSR_EEPROM_GP,
iwl_read32(priv, CSR_EEPROM_GP) & iwl_read32(bus(priv), CSR_EEPROM_GP) &
~CSR_EEPROM_GP_IF_OWNER_MSK); ~CSR_EEPROM_GP_IF_OWNER_MSK);
iwl_set_bit(priv, CSR_OTP_GP_REG, iwl_set_bit(bus(priv), CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
/* traversing the linked list if no shadow ram supported */ /* traversing the linked list if no shadow ram supported */
@ -498,10 +498,10 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
for (addr = 0; addr < sz; addr += sizeof(u16)) { for (addr = 0; addr < sz; addr += sizeof(u16)) {
u32 r; u32 r;
iwl_write32(priv, CSR_EEPROM_REG, iwl_write32(bus(priv), CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
ret = iwl_poll_bit(priv, CSR_EEPROM_REG, ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG,
CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK,
CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK,
IWL_EEPROM_ACCESS_TIMEOUT); IWL_EEPROM_ACCESS_TIMEOUT);
@ -509,7 +509,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr);
goto done; goto done;
} }
r = iwl_read32(priv, CSR_EEPROM_REG); r = iwl_read32(bus(priv), CSR_EEPROM_REG);
e[addr / 2] = cpu_to_le16(r >> 16); e[addr / 2] = cpu_to_le16(r >> 16);
} }
} }
@ -838,7 +838,7 @@ void iwl_rf_config(struct iwl_priv *priv)
/* write radio config values to register */ /* write radio config values to register */
if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) {
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
EEPROM_RF_CFG_STEP_MSK(radio_cfg) | EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
EEPROM_RF_CFG_DASH_MSK(radio_cfg)); EEPROM_RF_CFG_DASH_MSK(radio_cfg));
@ -850,7 +850,7 @@ void iwl_rf_config(struct iwl_priv *priv)
WARN_ON(1); WARN_ON(1);
/* set CSR_HW_CONFIG_REG for uCode use */ /* set CSR_HW_CONFIG_REG for uCode use */
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
} }

View file

@ -301,7 +301,6 @@ void iwl_eeprom_free(struct iwl_priv *priv);
int iwl_eeprom_check_version(struct iwl_priv *priv); int iwl_eeprom_check_version(struct iwl_priv *priv);
int iwl_eeprom_check_sku(struct iwl_priv *priv); int iwl_eeprom_check_sku(struct iwl_priv *priv);
const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
int iwl_init_channel_map(struct iwl_priv *priv); int iwl_init_channel_map(struct iwl_priv *priv);
void iwl_free_channel_map(struct iwl_priv *priv); void iwl_free_channel_map(struct iwl_priv *priv);

View file

@ -63,6 +63,8 @@
#ifndef __iwl_fh_h__ #ifndef __iwl_fh_h__
#define __iwl_fh_h__ #define __iwl_fh_h__
#include <linux/types.h>
/****************************/ /****************************/
/* Flow Handler Definitions */ /* Flow Handler Definitions */
/****************************/ /****************************/
@ -266,8 +268,6 @@
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000)
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000)
#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */
/** /**
* Rx Shared Status Registers (RSSR) * Rx Shared Status Registers (RSSR)
* *
@ -422,10 +422,6 @@
#define RX_FREE_BUFFERS 64 #define RX_FREE_BUFFERS 64
#define RX_LOW_WATERMARK 8 #define RX_LOW_WATERMARK 8
/* Size of one Rx buffer in host DRAM */
#define IWL_RX_BUF_SIZE_4K (4 * 1024)
#define IWL_RX_BUF_SIZE_8K (8 * 1024)
/** /**
* struct iwl_rb_status - reseve buffer status * struct iwl_rb_status - reseve buffer status
* host memory mapped FH registers * host memory mapped FH registers
@ -508,4 +504,16 @@ struct iwl_tfd {
/* Keep Warm Size */ /* Keep Warm Size */
#define IWL_KW_SIZE 0x1000 /* 4k */ #define IWL_KW_SIZE 0x1000 /* 4k */
/* Fixed (non-configurable) rx data from phy */
/**
* struct iwlagn_schedq_bc_tbl scheduler byte count table
* base physical address provided by SCD_DRAM_BASE_ADDR
* @tfd_offset 0-12 - tx command byte count
* 12-16 - station index
*/
struct iwlagn_scd_bc_tbl {
__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
} __packed;
#endif /* !__iwl_fh_h__ */ #endif /* !__iwl_fh_h__ */

View file

@ -64,99 +64,10 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd)
return --index & (n_bd - 1); return --index & (n_bd - 1);
} }
/*
* we have 8 bits used like this:
*
* 7 6 5 4 3 2 1 0
* | | | | | | | |
* | | | | | | +-+-------- AC queue (0-3)
* | | | | | |
* | +-+-+-+-+------------ HW queue ID
* |
* +---------------------- unused
*/
static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
{
BUG_ON(ac > 3); /* only have 2 bits */
BUG_ON(hwq > 31); /* only use 5 bits */
txq->swq_id = (hwq << 2) | ac;
}
static inline void iwl_wake_queue(struct iwl_priv *priv,
struct iwl_tx_queue *txq)
{
u8 queue = txq->swq_id;
u8 ac = queue & 3;
u8 hwq = (queue >> 2) & 0x1f;
if (test_and_clear_bit(hwq, priv->queue_stopped))
if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0)
ieee80211_wake_queue(priv->hw, ac);
}
static inline void iwl_stop_queue(struct iwl_priv *priv,
struct iwl_tx_queue *txq)
{
u8 queue = txq->swq_id;
u8 ac = queue & 3;
u8 hwq = (queue >> 2) & 0x1f;
if (!test_and_set_bit(hwq, priv->queue_stopped))
if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0)
ieee80211_stop_queue(priv->hw, ac);
}
static inline void iwl_wake_any_queue(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
u8 ac;
for (ac = 0; ac < AC_NUM; ac++) {
IWL_DEBUG_INFO(priv, "Queue Status: Q[%d] %s\n",
ac, (atomic_read(&priv->queue_stop_count[ac]) > 0)
? "stopped" : "awake");
iwl_wake_queue(priv, &priv->txq[ctx->ac_to_queue[ac]]);
}
}
#ifdef ieee80211_stop_queue
#undef ieee80211_stop_queue
#endif
#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
#ifdef ieee80211_wake_queue
#undef ieee80211_wake_queue
#endif
#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
static inline void iwl_disable_interrupts(struct iwl_priv *priv)
{
clear_bit(STATUS_INT_ENABLED, &priv->status);
/* disable interrupts from uCode/NIC to host */
iwl_write32(priv, CSR_INT_MASK, 0x00000000);
/* acknowledge/clear/reset any interrupts still pending
* from uCode or flow handler (Rx/Tx DMA) */
iwl_write32(priv, CSR_INT, 0xffffffff);
iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
}
static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
{ {
IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");
iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); iwl_write32(bus(priv), CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
}
static inline void iwl_enable_interrupts(struct iwl_priv *priv)
{
IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
set_bit(STATUS_INT_ENABLED, &priv->status);
iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
} }
/** /**

View file

@ -25,46 +25,50 @@
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/
#include <linux/delay.h>
#include <linux/device.h>
#include "iwl-io.h" #include "iwl-io.h"
#include"iwl-csr.h"
#include "iwl-debug.h"
#define IWL_POLL_INTERVAL 10 /* microseconds */ #define IWL_POLL_INTERVAL 10 /* microseconds */
static inline void __iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) static inline void __iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask)
{ {
iwl_write32(priv, reg, iwl_read32(priv, reg) | mask); iwl_write32(bus, reg, iwl_read32(bus, reg) | mask);
} }
static inline void __iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) static inline void __iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask)
{ {
iwl_write32(priv, reg, iwl_read32(priv, reg) & ~mask); iwl_write32(bus, reg, iwl_read32(bus, reg) & ~mask);
} }
void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
__iwl_set_bit(priv, reg, mask); __iwl_set_bit(bus, reg, mask);
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
} }
void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
__iwl_clear_bit(priv, reg, mask); __iwl_clear_bit(bus, reg, mask);
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
} }
int iwl_poll_bit(struct iwl_priv *priv, u32 addr, int iwl_poll_bit(struct iwl_bus *bus, u32 addr,
u32 bits, u32 mask, int timeout) u32 bits, u32 mask, int timeout)
{ {
int t = 0; int t = 0;
do { do {
if ((iwl_read32(priv, addr) & mask) == (bits & mask)) if ((iwl_read32(bus, addr) & mask) == (bits & mask))
return t; return t;
udelay(IWL_POLL_INTERVAL); udelay(IWL_POLL_INTERVAL);
t += IWL_POLL_INTERVAL; t += IWL_POLL_INTERVAL;
@ -73,14 +77,14 @@ int iwl_poll_bit(struct iwl_priv *priv, u32 addr,
return -ETIMEDOUT; return -ETIMEDOUT;
} }
int iwl_grab_nic_access_silent(struct iwl_priv *priv) int iwl_grab_nic_access_silent(struct iwl_bus *bus)
{ {
int ret; int ret;
lockdep_assert_held(&priv->reg_lock); lockdep_assert_held(&bus->reg_lock);
/* this bit wakes up the NIC */ /* this bit wakes up the NIC */
__iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); __iwl_set_bit(bus, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/* /*
* These bits say the device is running, and should keep running for * These bits say the device is running, and should keep running for
@ -101,70 +105,70 @@ int iwl_grab_nic_access_silent(struct iwl_priv *priv)
* 5000 series and later (including 1000 series) have non-volatile SRAM, * 5000 series and later (including 1000 series) have non-volatile SRAM,
* and do not save/restore SRAM when power cycling. * and do not save/restore SRAM when power cycling.
*/ */
ret = iwl_poll_bit(priv, CSR_GP_CNTRL, ret = iwl_poll_bit(bus, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
if (ret < 0) { if (ret < 0) {
iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); iwl_write32(bus, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
return -EIO; return -EIO;
} }
return 0; return 0;
} }
int iwl_grab_nic_access(struct iwl_priv *priv) int iwl_grab_nic_access(struct iwl_bus *bus)
{ {
int ret = iwl_grab_nic_access_silent(priv); int ret = iwl_grab_nic_access_silent(bus);
if (ret) { if (ret) {
u32 val = iwl_read32(priv, CSR_GP_CNTRL); u32 val = iwl_read32(bus, CSR_GP_CNTRL);
IWL_ERR(priv, IWL_ERR(bus,
"MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val);
} }
return ret; return ret;
} }
void iwl_release_nic_access(struct iwl_priv *priv) void iwl_release_nic_access(struct iwl_bus *bus)
{ {
lockdep_assert_held(&priv->reg_lock); lockdep_assert_held(&bus->reg_lock);
__iwl_clear_bit(priv, CSR_GP_CNTRL, __iwl_clear_bit(bus, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
} }
u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg)
{ {
u32 value; u32 value;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
iwl_grab_nic_access(priv); iwl_grab_nic_access(bus);
value = iwl_read32(priv, reg); value = iwl_read32(bus(bus), reg);
iwl_release_nic_access(priv); iwl_release_nic_access(bus);
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
return value; return value;
} }
void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
if (!iwl_grab_nic_access(priv)) { if (!iwl_grab_nic_access(bus)) {
iwl_write32(priv, reg, value); iwl_write32(bus, reg, value);
iwl_release_nic_access(priv); iwl_release_nic_access(bus);
} }
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
} }
int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask,
int timeout) int timeout)
{ {
int t = 0; int t = 0;
do { do {
if ((iwl_read_direct32(priv, addr) & mask) == mask) if ((iwl_read_direct32(bus, addr) & mask) == mask)
return t; return t;
udelay(IWL_POLL_INTERVAL); udelay(IWL_POLL_INTERVAL);
t += IWL_POLL_INTERVAL; t += IWL_POLL_INTERVAL;
@ -173,122 +177,122 @@ int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask,
return -ETIMEDOUT; return -ETIMEDOUT;
} }
static inline u32 __iwl_read_prph(struct iwl_priv *priv, u32 reg) static inline u32 __iwl_read_prph(struct iwl_bus *bus, u32 reg)
{ {
iwl_write32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); iwl_write32(bus, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
rmb(); rmb();
return iwl_read32(priv, HBUS_TARG_PRPH_RDAT); return iwl_read32(bus, HBUS_TARG_PRPH_RDAT);
} }
static inline void __iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) static inline void __iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val)
{ {
iwl_write32(priv, HBUS_TARG_PRPH_WADDR, iwl_write32(bus, HBUS_TARG_PRPH_WADDR,
((addr & 0x0000FFFF) | (3 << 24))); ((addr & 0x0000FFFF) | (3 << 24)));
wmb(); wmb();
iwl_write32(priv, HBUS_TARG_PRPH_WDAT, val); iwl_write32(bus, HBUS_TARG_PRPH_WDAT, val);
} }
u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) u32 iwl_read_prph(struct iwl_bus *bus, u32 reg)
{ {
unsigned long flags; unsigned long flags;
u32 val; u32 val;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
iwl_grab_nic_access(priv); iwl_grab_nic_access(bus);
val = __iwl_read_prph(priv, reg); val = __iwl_read_prph(bus, reg);
iwl_release_nic_access(priv); iwl_release_nic_access(bus);
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
return val; return val;
} }
void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
if (!iwl_grab_nic_access(priv)) { if (!iwl_grab_nic_access(bus)) {
__iwl_write_prph(priv, addr, val); __iwl_write_prph(bus, addr, val);
iwl_release_nic_access(priv); iwl_release_nic_access(bus);
} }
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
} }
void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
iwl_grab_nic_access(priv); iwl_grab_nic_access(bus);
__iwl_write_prph(priv, reg, __iwl_read_prph(priv, reg) | mask); __iwl_write_prph(bus, reg, __iwl_read_prph(bus, reg) | mask);
iwl_release_nic_access(priv); iwl_release_nic_access(bus);
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
} }
void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg,
u32 bits, u32 mask) u32 bits, u32 mask)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
iwl_grab_nic_access(priv); iwl_grab_nic_access(bus);
__iwl_write_prph(priv, reg, __iwl_write_prph(bus, reg,
(__iwl_read_prph(priv, reg) & mask) | bits); (__iwl_read_prph(bus, reg) & mask) | bits);
iwl_release_nic_access(priv); iwl_release_nic_access(bus);
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
} }
void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask)
{ {
unsigned long flags; unsigned long flags;
u32 val; u32 val;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
iwl_grab_nic_access(priv); iwl_grab_nic_access(bus);
val = __iwl_read_prph(priv, reg); val = __iwl_read_prph(bus, reg);
__iwl_write_prph(priv, reg, (val & ~mask)); __iwl_write_prph(bus, reg, (val & ~mask));
iwl_release_nic_access(priv); iwl_release_nic_access(bus);
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
} }
void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr,
void *buf, int words) void *buf, int words)
{ {
unsigned long flags; unsigned long flags;
int offs; int offs;
u32 *vals = buf; u32 *vals = buf;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
iwl_grab_nic_access(priv); iwl_grab_nic_access(bus);
iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr); iwl_write32(bus, HBUS_TARG_MEM_RADDR, addr);
rmb(); rmb();
for (offs = 0; offs < words; offs++) for (offs = 0; offs < words; offs++)
vals[offs] = iwl_read32(priv, HBUS_TARG_MEM_RDAT); vals[offs] = iwl_read32(bus, HBUS_TARG_MEM_RDAT);
iwl_release_nic_access(priv); iwl_release_nic_access(bus);
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
} }
u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr)
{ {
u32 value; u32 value;
_iwl_read_targ_mem_words(priv, addr, &value, 1); _iwl_read_targ_mem_words(bus, addr, &value, 1);
return value; return value;
} }
void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
if (!iwl_grab_nic_access(priv)) { if (!iwl_grab_nic_access(bus)) {
iwl_write32(priv, HBUS_TARG_MEM_WADDR, addr); iwl_write32(bus, HBUS_TARG_MEM_WADDR, addr);
wmb(); wmb();
iwl_write32(priv, HBUS_TARG_MEM_WDAT, val); iwl_write32(bus, HBUS_TARG_MEM_WDAT, val);
iwl_release_nic_access(priv); iwl_release_nic_access(bus);
} }
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
} }

View file

@ -29,65 +29,62 @@
#ifndef __iwl_io_h__ #ifndef __iwl_io_h__
#define __iwl_io_h__ #define __iwl_io_h__
#include <linux/io.h>
#include "iwl-dev.h"
#include "iwl-debug.h"
#include "iwl-devtrace.h" #include "iwl-devtrace.h"
#include "iwl-shared.h"
#include "iwl-bus.h" #include "iwl-bus.h"
static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) static inline void iwl_write8(struct iwl_bus *bus, u32 ofs, u8 val)
{ {
trace_iwlwifi_dev_iowrite8(priv, ofs, val); trace_iwlwifi_dev_iowrite8(priv(bus), ofs, val);
bus_write8(priv->bus, ofs, val); bus_write8(bus, ofs, val);
} }
static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) static inline void iwl_write32(struct iwl_bus *bus, u32 ofs, u32 val)
{ {
trace_iwlwifi_dev_iowrite32(priv, ofs, val); trace_iwlwifi_dev_iowrite32(priv(bus), ofs, val);
bus_write32(priv->bus, ofs, val); bus_write32(bus, ofs, val);
} }
static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs) static inline u32 iwl_read32(struct iwl_bus *bus, u32 ofs)
{ {
u32 val = bus_read32(priv->bus, ofs); u32 val = bus_read32(bus, ofs);
trace_iwlwifi_dev_ioread32(priv, ofs, val); trace_iwlwifi_dev_ioread32(priv(bus), ofs, val);
return val; return val;
} }
void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask); void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask);
void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask); void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask);
int iwl_poll_bit(struct iwl_priv *priv, u32 addr, int iwl_poll_bit(struct iwl_bus *bus, u32 addr,
u32 bits, u32 mask, int timeout); u32 bits, u32 mask, int timeout);
int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask,
int timeout); int timeout);
int iwl_grab_nic_access_silent(struct iwl_priv *priv); int iwl_grab_nic_access_silent(struct iwl_bus *bus);
int iwl_grab_nic_access(struct iwl_priv *priv); int iwl_grab_nic_access(struct iwl_bus *bus);
void iwl_release_nic_access(struct iwl_priv *priv); void iwl_release_nic_access(struct iwl_bus *bus);
u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg); u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg);
void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value); void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value);
u32 iwl_read_prph(struct iwl_priv *priv, u32 reg); u32 iwl_read_prph(struct iwl_bus *bus, u32 reg);
void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val); void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val);
void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask);
void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg,
u32 bits, u32 mask); u32 bits, u32 mask);
void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask);
void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr,
void *buf, int words); void *buf, int words);
#define iwl_read_targ_mem_words(priv, addr, buf, bufsize) \ #define iwl_read_targ_mem_words(bus, addr, buf, bufsize) \
do { \ do { \
BUILD_BUG_ON((bufsize) % sizeof(u32)); \ BUILD_BUG_ON((bufsize) % sizeof(u32)); \
_iwl_read_targ_mem_words(priv, addr, buf, \ _iwl_read_targ_mem_words(bus, addr, buf, \
(bufsize) / sizeof(u32));\ (bufsize) / sizeof(u32));\
} while (0) } while (0)
u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr); u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr);
void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val); void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val);
#endif #endif

View file

@ -40,6 +40,7 @@
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-io.h" #include "iwl-io.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-shared.h"
/* Throughput OFF time(ms) ON time (ms) /* Throughput OFF time(ms) ON time (ms)
* >300 25 25 * >300 25 25
@ -70,7 +71,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = {
/* Set led register off */ /* Set led register off */
void iwlagn_led_enable(struct iwl_priv *priv) void iwlagn_led_enable(struct iwl_priv *priv)
{ {
iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); iwl_write32(bus(priv), CSR_LED_REG, CSR_LED_REG_TRUN_ON);
} }
/* /*
@ -107,11 +108,11 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
}; };
u32 reg; u32 reg;
reg = iwl_read32(priv, CSR_LED_REG); reg = iwl_read32(bus(priv), CSR_LED_REG);
if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); iwl_write32(bus(priv), CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
return trans_send_cmd(&priv->trans, &cmd); return iwl_trans_send_cmd(trans(priv), &cmd);
} }
/* Set led pattern command */ /* Set led pattern command */
@ -125,7 +126,7 @@ static int iwl_led_cmd(struct iwl_priv *priv,
}; };
int ret; int ret;
if (!test_bit(STATUS_READY, &priv->status)) if (!test_bit(STATUS_READY, &priv->shrd->status))
return -EBUSY; return -EBUSY;
if (priv->blink_on == on && priv->blink_off == off) if (priv->blink_on == on && priv->blink_off == off)

View file

@ -64,9 +64,11 @@
#include <linux/pci-aspm.h> #include <linux/pci-aspm.h>
#include "iwl-bus.h" #include "iwl-bus.h"
#include "iwl-agn.h"
#include "iwl-core.h"
#include "iwl-io.h" #include "iwl-io.h"
#include "iwl-shared.h"
#include "iwl-trans.h"
#include "iwl-csr.h"
#include "iwl-pci.h"
/* PCI registers */ /* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041 #define PCI_CFG_RETRY_TIMEOUT 0x041
@ -91,6 +93,7 @@ static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus)
{ {
int pos; int pos;
u16 pci_lnk_ctl; u16 pci_lnk_ctl;
struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
pos = pci_pcie_cap(pci_dev); pos = pci_pcie_cap(pci_dev);
@ -120,21 +123,21 @@ static void iwl_pci_apm_config(struct iwl_bus *bus)
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
PCI_CFG_LINK_CTRL_VAL_L1_EN) { PCI_CFG_LINK_CTRL_VAL_L1_EN) {
/* L1-ASPM enabled; disable(!) L0S */ /* L1-ASPM enabled; disable(!) L0S */
iwl_set_bit(bus->drv_data, CSR_GIO_REG, iwl_set_bit(bus, CSR_GIO_REG,
CSR_GIO_REG_VAL_L0S_ENABLED); CSR_GIO_REG_VAL_L0S_ENABLED);
dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n"); dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n");
} else { } else {
/* L1-ASPM disabled; enable(!) L0S */ /* L1-ASPM disabled; enable(!) L0S */
iwl_clear_bit(bus->drv_data, CSR_GIO_REG, iwl_clear_bit(bus, CSR_GIO_REG,
CSR_GIO_REG_VAL_L0S_ENABLED); CSR_GIO_REG_VAL_L0S_ENABLED);
dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n"); dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n");
} }
} }
static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_data) static void iwl_pci_set_drv_data(struct iwl_bus *bus, struct iwl_shared *shrd)
{ {
bus->drv_data = drv_data; bus->shrd = shrd;
pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_data); pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), shrd);
} }
static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[],
@ -162,7 +165,7 @@ static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs)
return val; return val;
} }
static struct iwl_bus_ops pci_ops = { static const struct iwl_bus_ops bus_ops_pci = {
.get_pm_support = iwl_pci_is_pm_supported, .get_pm_support = iwl_pci_is_pm_supported,
.apm_config = iwl_pci_apm_config, .apm_config = iwl_pci_apm_config,
.set_drv_data = iwl_pci_set_drv_data, .set_drv_data = iwl_pci_set_drv_data,
@ -256,6 +259,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)}, {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)}, {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)}, {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
{IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)},
/* 6x30 Series */ /* 6x30 Series */
{IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)}, {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
@ -328,6 +332,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)}, {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
{IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)}, {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
{IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)}, {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
{IWL_PCI_DEVICE(0x0890, 0x4822, iwl2000_2bgn_d_cfg)},
/* 2x30 Series */ /* 2x30 Series */
{IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)}, {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
@ -457,9 +462,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
bus->dev = &pdev->dev; bus->dev = &pdev->dev;
bus->irq = pdev->irq; bus->irq = pdev->irq;
bus->ops = &pci_ops; bus->ops = &bus_ops_pci;
err = iwl_probe(bus, cfg); err = iwl_probe(bus, &trans_ops_pcie, cfg);
if (err) if (err)
goto out_disable_msi; goto out_disable_msi;
return 0; return 0;
@ -493,33 +498,33 @@ static void iwl_pci_down(struct iwl_bus *bus)
static void __devexit iwl_pci_remove(struct pci_dev *pdev) static void __devexit iwl_pci_remove(struct pci_dev *pdev)
{ {
struct iwl_priv *priv = pci_get_drvdata(pdev); struct iwl_shared *shrd = pci_get_drvdata(pdev);
void *bus_specific = priv->bus->bus_specific; struct iwl_bus *bus = shrd->bus;
iwl_remove(priv); iwl_remove(shrd->priv);
iwl_pci_down(bus_specific); iwl_pci_down(bus);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int iwl_pci_suspend(struct device *device) static int iwl_pci_suspend(struct device *device)
{ {
struct pci_dev *pdev = to_pci_dev(device); struct pci_dev *pdev = to_pci_dev(device);
struct iwl_priv *priv = pci_get_drvdata(pdev); struct iwl_shared *shrd = pci_get_drvdata(pdev);
/* Before you put code here, think about WoWLAN. You cannot check here /* Before you put code here, think about WoWLAN. You cannot check here
* whether WoWLAN is enabled or not, and your code will run even if * whether WoWLAN is enabled or not, and your code will run even if
* WoWLAN is enabled - don't kill the NIC, someone may need it in Sx. * WoWLAN is enabled - don't kill the NIC, someone may need it in Sx.
*/ */
return iwl_suspend(priv); return iwl_trans_suspend(shrd->trans);
} }
static int iwl_pci_resume(struct device *device) static int iwl_pci_resume(struct device *device)
{ {
struct pci_dev *pdev = to_pci_dev(device); struct pci_dev *pdev = to_pci_dev(device);
struct iwl_priv *priv = pci_get_drvdata(pdev); struct iwl_shared *shrd = pci_get_drvdata(pdev);
/* Before you put code here, think about WoWLAN. You cannot check here /* Before you put code here, think about WoWLAN. You cannot check here
* whether WoWLAN is enabled or not, and your code will run even if * whether WoWLAN is enabled or not, and your code will run even if
@ -532,7 +537,7 @@ static int iwl_pci_resume(struct device *device)
*/ */
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
return iwl_resume(priv); return iwl_trans_resume(shrd->trans);
} }
static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume);

View file

@ -0,0 +1,116 @@
/******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#ifndef __iwl_pci_h__
#define __iwl_pci_h__
/* This file includes the declaration that are internal to the PCI
* implementation of the bus layer
*/
/* configuration for the _agn devices */
extern struct iwl_cfg iwl5300_agn_cfg;
extern struct iwl_cfg iwl5100_agn_cfg;
extern struct iwl_cfg iwl5350_agn_cfg;
extern struct iwl_cfg iwl5100_bgn_cfg;
extern struct iwl_cfg iwl5100_abg_cfg;
extern struct iwl_cfg iwl5150_agn_cfg;
extern struct iwl_cfg iwl5150_abg_cfg;
extern struct iwl_cfg iwl6005_2agn_cfg;
extern struct iwl_cfg iwl6005_2abg_cfg;
extern struct iwl_cfg iwl6005_2bg_cfg;
extern struct iwl_cfg iwl6005_2agn_sff_cfg;
extern struct iwl_cfg iwl1030_bgn_cfg;
extern struct iwl_cfg iwl1030_bg_cfg;
extern struct iwl_cfg iwl6030_2agn_cfg;
extern struct iwl_cfg iwl6030_2abg_cfg;
extern struct iwl_cfg iwl6030_2bgn_cfg;
extern struct iwl_cfg iwl6030_2bg_cfg;
extern struct iwl_cfg iwl6000i_2agn_cfg;
extern struct iwl_cfg iwl6000i_2abg_cfg;
extern struct iwl_cfg iwl6000i_2bg_cfg;
extern struct iwl_cfg iwl6000_3agn_cfg;
extern struct iwl_cfg iwl6050_2agn_cfg;
extern struct iwl_cfg iwl6050_2abg_cfg;
extern struct iwl_cfg iwl6150_bgn_cfg;
extern struct iwl_cfg iwl6150_bg_cfg;
extern struct iwl_cfg iwl1000_bgn_cfg;
extern struct iwl_cfg iwl1000_bg_cfg;
extern struct iwl_cfg iwl100_bgn_cfg;
extern struct iwl_cfg iwl100_bg_cfg;
extern struct iwl_cfg iwl130_bgn_cfg;
extern struct iwl_cfg iwl130_bg_cfg;
extern struct iwl_cfg iwl2000_2bgn_cfg;
extern struct iwl_cfg iwl2000_2bg_cfg;
extern struct iwl_cfg iwl2000_2bgn_d_cfg;
extern struct iwl_cfg iwl2030_2bgn_cfg;
extern struct iwl_cfg iwl2030_2bg_cfg;
extern struct iwl_cfg iwl6035_2agn_cfg;
extern struct iwl_cfg iwl6035_2abg_cfg;
extern struct iwl_cfg iwl6035_2bg_cfg;
extern struct iwl_cfg iwl105_bg_cfg;
extern struct iwl_cfg iwl105_bgn_cfg;
extern struct iwl_cfg iwl135_bg_cfg;
extern struct iwl_cfg iwl135_bgn_cfg;
#endif /* __iwl_pci_h__ */

View file

@ -43,6 +43,7 @@
#include "iwl-debug.h" #include "iwl-debug.h"
#include "iwl-power.h" #include "iwl-power.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-shared.h"
/* /*
* Setting power level allows the card to go to sleep when not busy. * Setting power level allows the card to go to sleep when not busy.
@ -214,7 +215,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
else else
cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
if (priv->cfg->base_params->shadow_reg_enable) if (hw_params(priv).shadow_reg_enable)
cmd->flags |= IWL_POWER_SHADOW_REG_ENA; cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
else else
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
@ -300,7 +301,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
if (priv->power_data.bus_pm) if (priv->power_data.bus_pm)
cmd->flags |= IWL_POWER_PCI_PM_MSK; cmd->flags |= IWL_POWER_PCI_PM_MSK;
if (priv->cfg->base_params->shadow_reg_enable) if (hw_params(priv).shadow_reg_enable)
cmd->flags |= IWL_POWER_SHADOW_REG_ENA; cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
else else
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
@ -335,7 +336,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
le32_to_cpu(cmd->sleep_interval[3]), le32_to_cpu(cmd->sleep_interval[3]),
le32_to_cpu(cmd->sleep_interval[4])); le32_to_cpu(cmd->sleep_interval[4]));
return trans_send_cmd_pdu(&priv->trans, POWER_TABLE_CMD, CMD_SYNC, return iwl_trans_send_cmd_pdu(trans(priv), POWER_TABLE_CMD, CMD_SYNC,
sizeof(struct iwl_powertable_cmd), cmd); sizeof(struct iwl_powertable_cmd), cmd);
} }
@ -347,7 +348,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
dtimper = priv->hw->conf.ps_dtim_period ?: 1; dtimper = priv->hw->conf.ps_dtim_period ?: 1;
if (priv->wowlan) if (priv->shrd->wowlan)
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper); iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
else if (!priv->cfg->base_params->no_idle_support && else if (!priv->cfg->base_params->no_idle_support &&
priv->hw->conf.flags & IEEE80211_CONF_IDLE) priv->hw->conf.flags & IEEE80211_CONF_IDLE)
@ -382,7 +383,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
int ret; int ret;
bool update_chains; bool update_chains;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
/* Don't update the RX chain when chain noise calibration is running */ /* Don't update the RX chain when chain noise calibration is running */
update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
@ -391,23 +392,23 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force) if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
return 0; return 0;
if (!iwl_is_ready_rf(priv)) if (!iwl_is_ready_rf(priv->shrd))
return -EIO; return -EIO;
/* scan complete use sleep_power_next, need to be updated */ /* scan complete use sleep_power_next, need to be updated */
memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd)); memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
if (test_bit(STATUS_SCANNING, &priv->status) && !force) { if (test_bit(STATUS_SCANNING, &priv->shrd->status) && !force) {
IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n"); IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
return 0; return 0;
} }
if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
set_bit(STATUS_POWER_PMI, &priv->status); set_bit(STATUS_POWER_PMI, &priv->shrd->status);
ret = iwl_set_power(priv, cmd); ret = iwl_set_power(priv, cmd);
if (!ret) { if (!ret) {
if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
clear_bit(STATUS_POWER_PMI, &priv->status); clear_bit(STATUS_POWER_PMI, &priv->shrd->status);
if (update_chains) if (update_chains)
iwl_update_chain_flags(priv); iwl_update_chain_flags(priv);

View file

@ -217,8 +217,8 @@
((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
#define SCD_QUEUECHAIN_SEL_ALL(priv) \ #define SCD_QUEUECHAIN_SEL_ALL(priv) \
(((1<<(priv)->hw_params.max_txq_num) - 1) &\ (((1<<hw_params(priv).max_txq_num) - 1) &\
(~(1<<(priv)->cmd_queue))) (~(1<<(priv)->shrd->cmd_queue)))
#define SCD_BASE (PRPH_BASE + 0xa02c00) #define SCD_BASE (PRPH_BASE + 0xa02c00)

View file

@ -40,6 +40,7 @@
#include "iwl-helpers.h" #include "iwl-helpers.h"
#include "iwl-agn-calib.h" #include "iwl-agn-calib.h"
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-shared.h"
/****************************************************************************** /******************************************************************************
@ -73,7 +74,7 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl_rxon_cmd *rxon = (void *)&ctx->active; struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status))
return; return;
if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
@ -121,7 +122,8 @@ static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb) struct iwl_rx_mem_buffer *rxb)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; u32 __maybe_unused len =
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
"notification for %s:\n", len, "notification for %s:\n", len,
get_cmd_string(pkt->hdr.cmd)); get_cmd_string(pkt->hdr.cmd));
@ -148,8 +150,8 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
queue_work(priv->workqueue, &priv->beacon_update); queue_work(priv->shrd->workqueue, &priv->beacon_update);
} }
/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
@ -258,7 +260,7 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv,
{ {
unsigned int msecs; unsigned int msecs;
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return; return;
msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies); msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
@ -474,7 +476,7 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
priv->rx_statistics_jiffies = stamp; priv->rx_statistics_jiffies = stamp;
set_bit(STATUS_STATISTICS, &priv->status); set_bit(STATUS_STATISTICS, &priv->shrd->status);
/* Reschedule the statistics timer to occur in /* Reschedule the statistics timer to occur in
* reg_recalib_period seconds to ensure we get a * reg_recalib_period seconds to ensure we get a
@ -483,10 +485,10 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
mod_timer(&priv->statistics_periodic, jiffies + mod_timer(&priv->statistics_periodic, jiffies +
msecs_to_jiffies(reg_recalib_period * 1000)); msecs_to_jiffies(reg_recalib_period * 1000));
if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && if (unlikely(!test_bit(STATUS_SCANNING, &priv->shrd->status)) &&
(pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
iwl_rx_calc_noise(priv); iwl_rx_calc_noise(priv);
queue_work(priv->workqueue, &priv->run_time_calib_work); queue_work(priv->shrd->workqueue, &priv->run_time_calib_work);
} }
if (priv->cfg->lib->temperature && change) if (priv->cfg->lib->temperature && change)
priv->cfg->lib->temperature(priv); priv->cfg->lib->temperature(priv);
@ -518,7 +520,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
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->shrd->status;
IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
(flags & HW_CARD_DISABLED) ? "Kill" : "On", (flags & HW_CARD_DISABLED) ? "Kill" : "On",
@ -529,16 +531,16 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
CT_CARD_DISABLED)) { CT_CARD_DISABLED)) {
iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET,
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(bus(priv), HBUS_TARG_MBX_C,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
if (!(flags & RXON_CARD_DISABLED)) { if (!(flags & RXON_CARD_DISABLED)) {
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR,
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(bus(priv), HBUS_TARG_MBX_C,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
} }
if (flags & CT_CARD_DISABLED) if (flags & CT_CARD_DISABLED)
@ -548,18 +550,18 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
iwl_tt_exit_ct_kill(priv); 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->shrd->status);
else else
clear_bit(STATUS_RF_KILL_HW, &priv->status); clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
if (!(flags & RXON_CARD_DISABLED)) if (!(flags & RXON_CARD_DISABLED))
iwl_scan_cancel(priv); iwl_scan_cancel(priv);
if ((test_bit(STATUS_RF_KILL_HW, &status) != if ((test_bit(STATUS_RF_KILL_HW, &status) !=
test_bit(STATUS_RF_KILL_HW, &priv->status))) test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)))
wiphy_rfkill_set_hw_state(priv->hw->wiphy, wiphy_rfkill_set_hw_state(priv->hw->wiphy,
test_bit(STATUS_RF_KILL_HW, &priv->status)); test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
else else
wake_up_interruptible(&priv->wait_command_queue); wake_up_interruptible(&priv->wait_command_queue);
} }
@ -580,7 +582,7 @@ static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
le32_to_cpu(missed_beacon->total_missed_becons), le32_to_cpu(missed_beacon->total_missed_becons),
le32_to_cpu(missed_beacon->num_recvd_beacons), le32_to_cpu(missed_beacon->num_recvd_beacons),
le32_to_cpu(missed_beacon->num_expected_beacons)); le32_to_cpu(missed_beacon->num_expected_beacons));
if (!test_bit(STATUS_SCANNING, &priv->status)) if (!test_bit(STATUS_SCANNING, &priv->shrd->status))
iwl_init_sensitivity(priv); iwl_init_sensitivity(priv);
} }
} }
@ -697,7 +699,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
ctx->active.bssid_addr)) ctx->active.bssid_addr))
continue; continue;
ctx->last_tx_rejected = false; ctx->last_tx_rejected = false;
iwl_wake_any_queue(priv, ctx); iwl_trans_wake_any_queue(trans(priv), ctx->ctxid);
} }
} }
@ -1018,7 +1020,7 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
* handle those that need handling via function in * handle those that need handling via function in
* rx_handlers table. See iwl_setup_rx_handlers() */ * rx_handlers table. See iwl_setup_rx_handlers() */
if (priv->rx_handlers[pkt->hdr.cmd]) { if (priv->rx_handlers[pkt->hdr.cmd]) {
priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; priv->rx_handlers_stats[pkt->hdr.cmd]++;
priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
} else { } else {
/* No handling needed */ /* No handling needed */

View file

@ -68,14 +68,14 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
/* Exit instantly with error when device is not ready /* Exit instantly with error when device is not ready
* to receive scan abort command or it does not perform * to receive scan abort command or it does not perform
* hardware scan currently */ * hardware scan currently */
if (!test_bit(STATUS_READY, &priv->status) || if (!test_bit(STATUS_READY, &priv->shrd->status) ||
!test_bit(STATUS_GEO_CONFIGURED, &priv->status) || !test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) ||
!test_bit(STATUS_SCAN_HW, &priv->status) || !test_bit(STATUS_SCAN_HW, &priv->shrd->status) ||
test_bit(STATUS_FW_ERROR, &priv->status) || test_bit(STATUS_FW_ERROR, &priv->shrd->status) ||
test_bit(STATUS_EXIT_PENDING, &priv->status)) test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return -EIO; return -EIO;
ret = trans_send_cmd(&priv->trans, &cmd); ret = iwl_trans_send_cmd(trans(priv), &cmd);
if (ret) if (ret)
return ret; return ret;
@ -91,7 +91,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
ret = -EIO; ret = -EIO;
} }
iwl_free_pages(priv, cmd.reply_page); iwl_free_pages(priv->shrd, cmd.reply_page);
return ret; return ret;
} }
@ -116,17 +116,17 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
void iwl_force_scan_end(struct iwl_priv *priv) void iwl_force_scan_end(struct iwl_priv *priv)
{ {
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
if (!test_bit(STATUS_SCANNING, &priv->status)) { if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n"); IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n");
return; return;
} }
IWL_DEBUG_SCAN(priv, "Forcing scan end\n"); IWL_DEBUG_SCAN(priv, "Forcing scan end\n");
clear_bit(STATUS_SCANNING, &priv->status); clear_bit(STATUS_SCANNING, &priv->shrd->status);
clear_bit(STATUS_SCAN_HW, &priv->status); clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
clear_bit(STATUS_SCAN_ABORTING, &priv->status); clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
iwl_complete_scan(priv, true); iwl_complete_scan(priv, true);
} }
@ -134,14 +134,14 @@ static void iwl_do_scan_abort(struct iwl_priv *priv)
{ {
int ret; int ret;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
if (!test_bit(STATUS_SCANNING, &priv->status)) { if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n"); IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
return; return;
} }
if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, "Scan abort in progress\n"); IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
return; return;
} }
@ -160,7 +160,7 @@ static void iwl_do_scan_abort(struct iwl_priv *priv)
int iwl_scan_cancel(struct iwl_priv *priv) int iwl_scan_cancel(struct iwl_priv *priv)
{ {
IWL_DEBUG_SCAN(priv, "Queuing abort scan\n"); IWL_DEBUG_SCAN(priv, "Queuing abort scan\n");
queue_work(priv->workqueue, &priv->abort_scan); queue_work(priv->shrd->workqueue, &priv->abort_scan);
return 0; return 0;
} }
@ -173,19 +173,19 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
{ {
unsigned long timeout = jiffies + msecs_to_jiffies(ms); unsigned long timeout = jiffies + msecs_to_jiffies(ms);
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n"); IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");
iwl_do_scan_abort(priv); iwl_do_scan_abort(priv);
while (time_before_eq(jiffies, timeout)) { while (time_before_eq(jiffies, timeout)) {
if (!test_bit(STATUS_SCAN_HW, &priv->status)) if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status))
break; break;
msleep(20); msleep(20);
} }
return test_bit(STATUS_SCAN_HW, &priv->status); return test_bit(STATUS_SCAN_HW, &priv->shrd->status);
} }
/* Service response to REPLY_SCAN_CMD (0x80) */ /* Service response to REPLY_SCAN_CMD (0x80) */
@ -257,13 +257,13 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
scan_notif->tsf_high, scan_notif->status); scan_notif->tsf_high, scan_notif->status);
/* The HW is no longer scanning */ /* The HW is no longer scanning */
clear_bit(STATUS_SCAN_HW, &priv->status); clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
(priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
jiffies_to_msecs(jiffies - priv->scan_start)); jiffies_to_msecs(jiffies - priv->scan_start));
queue_work(priv->workqueue, &priv->scan_completed); queue_work(priv->shrd->workqueue, &priv->scan_completed);
if (priv->iw_mode != NL80211_IFTYPE_ADHOC && if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
iwl_advanced_bt_coexist(priv) && iwl_advanced_bt_coexist(priv) &&
@ -283,7 +283,8 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
IWL_BT_COEX_TRAFFIC_LOAD_NONE; IWL_BT_COEX_TRAFFIC_LOAD_NONE;
} }
priv->bt_status = scan_notif->bt_status; priv->bt_status = scan_notif->bt_status;
queue_work(priv->workqueue, &priv->bt_traffic_change_work); queue_work(priv->shrd->workqueue,
&priv->bt_traffic_change_work);
} }
} }
@ -343,7 +344,7 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
void iwl_init_scan_params(struct iwl_priv *priv) void iwl_init_scan_params(struct iwl_priv *priv)
{ {
u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; u8 ant_idx = fls(hw_params(priv).valid_tx_ant) - 1;
if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ])
priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
@ -357,22 +358,22 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
{ {
int ret; int ret;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->shrd->mutex);
cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->scan_check);
if (!iwl_is_ready_rf(priv)) { if (!iwl_is_ready_rf(priv->shrd)) {
IWL_WARN(priv, "Request scan called when driver not ready.\n"); IWL_WARN(priv, "Request scan called when driver not ready.\n");
return -EIO; return -EIO;
} }
if (test_bit(STATUS_SCAN_HW, &priv->status)) { if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, IWL_DEBUG_SCAN(priv,
"Multiple concurrent scan requests in parallel.\n"); "Multiple concurrent scan requests in parallel.\n");
return -EBUSY; return -EBUSY;
} }
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { if (test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n"); IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n");
return -EBUSY; return -EBUSY;
} }
@ -382,19 +383,19 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
scan_type == IWL_SCAN_ROC ? "remain-on-channel " : scan_type == IWL_SCAN_ROC ? "remain-on-channel " :
"internal short "); "internal short ");
set_bit(STATUS_SCANNING, &priv->status); set_bit(STATUS_SCANNING, &priv->shrd->status);
priv->scan_type = scan_type; priv->scan_type = scan_type;
priv->scan_start = jiffies; priv->scan_start = jiffies;
priv->scan_band = band; priv->scan_band = band;
ret = iwlagn_request_scan(priv, vif); ret = iwlagn_request_scan(priv, vif);
if (ret) { if (ret) {
clear_bit(STATUS_SCANNING, &priv->status); clear_bit(STATUS_SCANNING, &priv->shrd->status);
priv->scan_type = IWL_SCAN_NORMAL; priv->scan_type = IWL_SCAN_NORMAL;
return ret; return ret;
} }
queue_delayed_work(priv->workqueue, &priv->scan_check, queue_delayed_work(priv->shrd->workqueue, &priv->scan_check,
IWL_SCAN_CHECK_WATCHDOG); IWL_SCAN_CHECK_WATCHDOG);
return 0; return 0;
@ -412,9 +413,9 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
if (req->n_channels == 0) if (req->n_channels == 0)
return -EINVAL; return -EINVAL;
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
if (test_bit(STATUS_SCANNING, &priv->status) && if (test_bit(STATUS_SCANNING, &priv->shrd->status) &&
priv->scan_type != IWL_SCAN_NORMAL) { priv->scan_type != IWL_SCAN_NORMAL) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
ret = -EAGAIN; ret = -EAGAIN;
@ -439,7 +440,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
out_unlock: out_unlock:
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
return ret; return ret;
} }
@ -450,7 +451,7 @@ out_unlock:
*/ */
void iwl_internal_short_hw_scan(struct iwl_priv *priv) void iwl_internal_short_hw_scan(struct iwl_priv *priv)
{ {
queue_work(priv->workqueue, &priv->start_internal_scan); queue_work(priv->shrd->workqueue, &priv->start_internal_scan);
} }
static void iwl_bg_start_internal_scan(struct work_struct *work) static void iwl_bg_start_internal_scan(struct work_struct *work)
@ -460,14 +461,14 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
IWL_DEBUG_SCAN(priv, "Start internal scan\n"); IWL_DEBUG_SCAN(priv, "Start internal scan\n");
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
if (priv->scan_type == IWL_SCAN_RADIO_RESET) { if (priv->scan_type == IWL_SCAN_RADIO_RESET) {
IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n"); IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
goto unlock; goto unlock;
} }
if (test_bit(STATUS_SCANNING, &priv->status)) { if (test_bit(STATUS_SCANNING, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
goto unlock; goto unlock;
} }
@ -475,7 +476,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band)) if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band))
IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n"); IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
unlock: unlock:
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
} }
static void iwl_bg_scan_check(struct work_struct *data) static void iwl_bg_scan_check(struct work_struct *data)
@ -488,9 +489,9 @@ static void iwl_bg_scan_check(struct work_struct *data)
/* Since we are here firmware does not finish scan and /* Since we are here firmware does not finish scan and
* most likely is in bad shape, so we don't bother to * most likely is in bad shape, so we don't bother to
* send abort command, just force scan complete to mac80211 */ * send abort command, just force scan complete to mac80211 */
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
iwl_force_scan_end(priv); iwl_force_scan_end(priv);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
} }
/** /**
@ -548,9 +549,9 @@ static void iwl_bg_abort_scan(struct work_struct *work)
/* We keep scan_check work queued in case when firmware will not /* We keep scan_check work queued in case when firmware will not
* report back scan completed notification */ * report back scan completed notification */
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
iwl_scan_cancel_timeout(priv, 200); iwl_scan_cancel_timeout(priv, 200);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
} }
static void iwl_bg_scan_completed(struct work_struct *work) static void iwl_bg_scan_completed(struct work_struct *work)
@ -563,13 +564,13 @@ static void iwl_bg_scan_completed(struct work_struct *work)
cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->scan_check);
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status); aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
if (aborted) if (aborted)
IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) { if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
goto out_settings; goto out_settings;
} }
@ -605,13 +606,13 @@ out_complete:
out_settings: out_settings:
/* Can we still talk to firmware ? */ /* Can we still talk to firmware ? */
if (!iwl_is_ready_rf(priv)) if (!iwl_is_ready_rf(priv->shrd))
goto out; goto out;
iwlagn_post_scan(priv); iwlagn_post_scan(priv);
out: out:
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
} }
void iwl_setup_scan_deferred_work(struct iwl_priv *priv) void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
@ -629,8 +630,8 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
cancel_work_sync(&priv->scan_completed); cancel_work_sync(&priv->scan_completed);
if (cancel_delayed_work_sync(&priv->scan_check)) { if (cancel_delayed_work_sync(&priv->scan_check)) {
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
iwl_force_scan_end(priv); iwl_force_scan_end(priv);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
} }
} }

View file

@ -0,0 +1,430 @@
/******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#ifndef __iwl_shared_h__
#define __iwl_shared_h__
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/gfp.h>
#include <net/mac80211.h>
#include "iwl-commands.h"
/*This files includes all the types / functions that are exported by the
* upper layer to the bus and transport layer */
struct iwl_cfg;
struct iwl_bus;
struct iwl_priv;
struct iwl_sensitivity_ranges;
struct iwl_trans_ops;
#define DRV_NAME "iwlagn"
#define IWLWIFI_VERSION "in-tree:"
#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation"
#define DRV_AUTHOR "<ilw@linux.intel.com>"
extern struct iwl_mod_params iwlagn_mod_params;
/**
* struct iwl_mod_params
* @sw_crypto: using hardware encryption, default = 0
* @num_of_queues: number of tx queue, HW dependent
* @disable_11n: 11n capabilities enabled, default = 0
* @amsdu_size_8K: enable 8K amsdu size, default = 1
* @antenna: both antennas (use diversity), default = 0
* @restart_fw: restart firmware, default = 1
* @plcp_check: enable plcp health check, default = true
* @ack_check: disable ack health check, default = false
* @wd_disable: enable stuck queue check, default = false
* @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0
* @no_sleep_autoadjust: disable autoadjust, default = true
* @power_save: disable power save, default = false
* @power_level: power level, default = 1
* @debug_level: levels are IWL_DL_*
* @ant_coupling: antenna coupling in dB, default = 0
* @bt_ch_announce: BT channel inhibition, default = enable
* @wanted_ucode_alternative: ucode alternative to use, default = 1
* @auto_agg: enable agg. without check, default = true
*/
struct iwl_mod_params {
int sw_crypto;
int num_of_queues;
int disable_11n;
int amsdu_size_8K;
int antenna;
int restart_fw;
bool plcp_check;
bool ack_check;
bool wd_disable;
bool bt_coex_active;
int led_mode;
bool no_sleep_autoadjust;
bool power_save;
int power_level;
u32 debug_level;
int ant_coupling;
bool bt_ch_announce;
int wanted_ucode_alternative;
bool auto_agg;
};
/**
* struct iwl_hw_params
* @max_txq_num: Max # Tx queues supported
* @num_ampdu_queues: num of ampdu queues
* @tx/rx_chains_num: Number of TX/RX chains
* @valid_tx/rx_ant: usable antennas
* @max_stations:
* @ht40_channel: is 40MHz width possible in band 2.4
* @beacon_time_tsf_bits: number of valid tsf bits for beacon time
* @sku:
* @rx_page_order: Rx buffer page order
* @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
* BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
* @sw_crypto: 0 for hw, 1 for sw
* @max_xxx_size: for ucode uses
* @ct_kill_threshold: temperature threshold
* @wd_timeout: TX queues watchdog timeout
* @calib_init_cfg: setup initial calibrations for the hw
* @calib_rt_cfg: setup runtime calibrations for the hw
* @struct iwl_sensitivity_ranges: range of sensitivity values
*/
struct iwl_hw_params {
u8 max_txq_num;
u8 num_ampdu_queues;
u8 tx_chains_num;
u8 rx_chains_num;
u8 valid_tx_ant;
u8 valid_rx_ant;
u8 max_stations;
u8 ht40_channel;
bool shadow_reg_enable;
u16 beacon_time_tsf_bits;
u16 sku;
u32 rx_page_order;
u32 max_inst_size;
u32 max_data_size;
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 */
unsigned int wd_timeout;
u32 calib_init_cfg;
u32 calib_rt_cfg;
const struct iwl_sensitivity_ranges *sens;
};
/**
* struct iwl_ht_agg - aggregation status while waiting for block-ack
* @txq_id: Tx queue used for Tx attempt
* @wait_for_ba: Expect block-ack before next Tx reply
* @rate_n_flags: Rate at which Tx was attempted
*
* If REPLY_TX indicates that aggregation was attempted, driver must wait
* for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info
* until block ack arrives.
*/
struct iwl_ht_agg {
u16 txq_id;
u16 wait_for_ba;
u32 rate_n_flags;
#define IWL_AGG_OFF 0
#define IWL_AGG_ON 1
#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
#define IWL_EMPTYING_HW_QUEUE_DELBA 3
u8 state;
};
struct iwl_tid_data {
u16 seq_number; /* agn only */
u16 tfds_in_queue;
struct iwl_ht_agg agg;
};
/**
* struct iwl_shared - shared fields for all the layers of the driver
*
* @dbg_level_dev: dbg level set per device. Prevails on
* iwlagn_mod_params.debug_level if set (!= 0)
* @ucode_owner: IWL_OWNERSHIP_*
* @cmd_queue: command queue number
* @status: STATUS_*
* @bus: pointer to the bus layer data
* @priv: pointer to the upper layer data
* @hw_params: see struct iwl_hw_params
* @workqueue: the workqueue used by all the layers of the driver
* @lock: protect general shared data
* @sta_lock: protects the station table.
* If lock and sta_lock are needed, lock must be acquired first.
* @mutex:
*/
struct iwl_shared {
#ifdef CONFIG_IWLWIFI_DEBUG
u32 dbg_level_dev;
#endif /* CONFIG_IWLWIFI_DEBUG */
#define IWL_OWNERSHIP_DRIVER 0
#define IWL_OWNERSHIP_TM 1
u8 ucode_owner;
u8 cmd_queue;
unsigned long status;
bool wowlan;
struct iwl_bus *bus;
struct iwl_priv *priv;
struct iwl_trans *trans;
struct iwl_hw_params hw_params;
struct workqueue_struct *workqueue;
spinlock_t lock;
spinlock_t sta_lock;
struct mutex mutex;
/*these 2 shouldn't really be here, but they are needed for
* iwl_queue_stop, which is called from the upper layer too
*/
u8 mac80211_registered;
struct ieee80211_hw *hw;
struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
};
/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */
#define priv(_m) ((_m)->shrd->priv)
#define bus(_m) ((_m)->shrd->bus)
#define trans(_m) ((_m)->shrd->trans)
#define hw_params(_m) ((_m)->shrd->hw_params)
#ifdef CONFIG_IWLWIFI_DEBUG
/*
* iwl_get_debug_level: Return active debug level for device
*
* Using sysfs it is possible to set per device debug level. This debug
* level will be used if set, otherwise the global debug level which can be
* set via module parameter is used.
*/
static inline u32 iwl_get_debug_level(struct iwl_shared *shrd)
{
if (shrd->dbg_level_dev)
return shrd->dbg_level_dev;
else
return iwlagn_mod_params.debug_level;
}
#else
static inline u32 iwl_get_debug_level(struct iwl_shared *shrd)
{
return iwlagn_mod_params.debug_level;
}
#endif
static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page)
{
free_pages(page, shrd->hw_params.rx_page_order);
}
struct iwl_rx_mem_buffer {
dma_addr_t page_dma;
struct page *page;
struct list_head list;
};
#define rxb_addr(r) page_address(r->page)
/*
* mac80211 queues, ACs, hardware queues, FIFOs.
*
* Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
*
* Mac80211 uses the following numbers, which we get as from it
* by way of skb_get_queue_mapping(skb):
*
* VO 0
* VI 1
* BE 2
* BK 3
*
*
* Regular (not A-MPDU) frames are put into hardware queues corresponding
* to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
* own queue per aggregation session (RA/TID combination), such queues are
* set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
* order to map frames to the right queue, we also need an AC->hw queue
* mapping. This is implemented here.
*
* Due to the way hw queues are set up (by the hw specific modules like
* iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity
* mapping.
*/
static const u8 tid_to_ac[] = {
IEEE80211_AC_BE,
IEEE80211_AC_BK,
IEEE80211_AC_BK,
IEEE80211_AC_BE,
IEEE80211_AC_VI,
IEEE80211_AC_VI,
IEEE80211_AC_VO,
IEEE80211_AC_VO
};
static inline int get_ac_from_tid(u16 tid)
{
if (likely(tid < ARRAY_SIZE(tid_to_ac)))
return tid_to_ac[tid];
/* no support for TIDs 8-15 yet */
return -EINVAL;
}
enum iwl_rxon_context_id {
IWL_RXON_CTX_BSS,
IWL_RXON_CTX_PAN,
NUM_IWL_RXON_CTX
};
#ifdef CONFIG_PM
int iwl_suspend(struct iwl_priv *priv);
int iwl_resume(struct iwl_priv *priv);
#endif /* !CONFIG_PM */
int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
struct iwl_cfg *cfg);
void __devexit iwl_remove(struct iwl_priv * priv);
void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid);
void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid);
/*****************************************************
* DRIVER STATUS FUNCTIONS
******************************************************/
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */
#define STATUS_INT_ENABLED 2
#define STATUS_RF_KILL_HW 3
#define STATUS_CT_KILL 4
#define STATUS_INIT 5
#define STATUS_ALIVE 6
#define STATUS_READY 7
#define STATUS_TEMPERATURE 8
#define STATUS_GEO_CONFIGURED 9
#define STATUS_EXIT_PENDING 10
#define STATUS_STATISTICS 12
#define STATUS_SCANNING 13
#define STATUS_SCAN_ABORTING 14
#define STATUS_SCAN_HW 15
#define STATUS_POWER_PMI 16
#define STATUS_FW_ERROR 17
#define STATUS_DEVICE_ENABLED 18
#define STATUS_CHANNEL_SWITCH_PENDING 19
static inline int iwl_is_ready(struct iwl_shared *shrd)
{
/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
* set but EXIT_PENDING is not */
return test_bit(STATUS_READY, &shrd->status) &&
test_bit(STATUS_GEO_CONFIGURED, &shrd->status) &&
!test_bit(STATUS_EXIT_PENDING, &shrd->status);
}
static inline int iwl_is_alive(struct iwl_shared *shrd)
{
return test_bit(STATUS_ALIVE, &shrd->status);
}
static inline int iwl_is_init(struct iwl_shared *shrd)
{
return test_bit(STATUS_INIT, &shrd->status);
}
static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd)
{
return test_bit(STATUS_RF_KILL_HW, &shrd->status);
}
static inline int iwl_is_rfkill(struct iwl_shared *shrd)
{
return iwl_is_rfkill_hw(shrd);
}
static inline int iwl_is_ctkill(struct iwl_shared *shrd)
{
return test_bit(STATUS_CT_KILL, &shrd->status);
}
static inline int iwl_is_ready_rf(struct iwl_shared *shrd)
{
if (iwl_is_rfkill(shrd))
return 0;
return iwl_is_ready(shrd);
}
#endif /* #__iwl_shared_h__ */

View file

@ -38,7 +38,7 @@
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-agn.h" #include "iwl-agn.h"
/* priv->sta_lock must be held */ /* priv->shrd->sta_lock must be held */
static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
{ {
@ -75,7 +75,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
sta_id); sta_id);
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
switch (pkt->u.add_sta.status) { switch (pkt->u.add_sta.status) {
case ADD_STA_SUCCESS_MSK: case ADD_STA_SUCCESS_MSK:
@ -118,7 +118,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
priv->stations[sta_id].sta.mode == priv->stations[sta_id].sta.mode ==
STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
addsta->sta.addr); addsta->sta.addr);
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return ret; return ret;
} }
@ -168,7 +168,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
} }
cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data); cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data);
ret = trans_send_cmd(&priv->trans, &cmd); ret = iwl_trans_send_cmd(trans(priv), &cmd);
if (ret || (flags & CMD_ASYNC)) if (ret || (flags & CMD_ASYNC))
return ret; return ret;
@ -177,7 +177,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
pkt = (struct iwl_rx_packet *)cmd.reply_page; pkt = (struct iwl_rx_packet *)cmd.reply_page;
ret = iwl_process_add_sta_resp(priv, sta, pkt, true); ret = iwl_process_add_sta_resp(priv, sta, pkt, true);
} }
iwl_free_pages(priv, cmd.reply_page); iwl_free_pages(priv->shrd, cmd.reply_page);
return ret; return ret;
} }
@ -251,7 +251,8 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
else if (is_broadcast_ether_addr(addr)) else if (is_broadcast_ether_addr(addr))
sta_id = ctx->bcast_sta_id; sta_id = ctx->bcast_sta_id;
else else
for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { for (i = IWL_STA_ID;
i < hw_params(priv).max_stations; i++) {
if (!compare_ether_addr(priv->stations[i].sta.sta.addr, if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
addr)) { addr)) {
sta_id = i; sta_id = i;
@ -336,12 +337,12 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct iwl_addsta_cmd sta_cmd; struct iwl_addsta_cmd sta_cmd;
*sta_id_r = 0; *sta_id_r = 0;
spin_lock_irqsave(&priv->sta_lock, flags_spin); spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta); sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta);
if (sta_id == IWL_INVALID_STATION) { if (sta_id == IWL_INVALID_STATION) {
IWL_ERR(priv, "Unable to prepare station %pM for addition\n", IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
addr); addr);
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
return -EINVAL; return -EINVAL;
} }
@ -353,7 +354,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) { if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n", IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n",
sta_id); sta_id);
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
return -EEXIST; return -EEXIST;
} }
@ -361,23 +362,23 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n", IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n",
sta_id, addr); sta_id, addr);
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
return -EEXIST; return -EEXIST;
} }
priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
/* Add station to device's station table */ /* Add station to device's station table */
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
if (ret) { if (ret) {
spin_lock_irqsave(&priv->sta_lock, flags_spin); spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
IWL_ERR(priv, "Adding station %pM failed.\n", IWL_ERR(priv, "Adding station %pM failed.\n",
priv->stations[sta_id].sta.sta.addr); priv->stations[sta_id].sta.sta.addr);
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
} }
*sta_id_r = sta_id; *sta_id_r = sta_id;
return ret; return ret;
@ -386,7 +387,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
/** /**
* iwl_sta_ucode_deactivate - deactivate ucode status for a station * iwl_sta_ucode_deactivate - deactivate ucode status for a station
* *
* priv->sta_lock must be held * priv->shrd->sta_lock must be held
*/ */
static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
{ {
@ -424,7 +425,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
cmd.flags |= CMD_WANT_SKB; cmd.flags |= CMD_WANT_SKB;
ret = trans_send_cmd(&priv->trans, &cmd); ret = iwl_trans_send_cmd(trans(priv), &cmd);
if (ret) if (ret)
return ret; return ret;
@ -440,9 +441,11 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
switch (pkt->u.rem_sta.status) { switch (pkt->u.rem_sta.status) {
case REM_STA_SUCCESS_MSK: case REM_STA_SUCCESS_MSK:
if (!temporary) { if (!temporary) {
spin_lock_irqsave(&priv->sta_lock, flags_spin); spin_lock_irqsave(&priv->shrd->sta_lock,
flags_spin);
iwl_sta_ucode_deactivate(priv, sta_id); iwl_sta_ucode_deactivate(priv, sta_id);
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock,
flags_spin);
} }
IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
break; break;
@ -452,7 +455,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
break; break;
} }
} }
iwl_free_pages(priv, cmd.reply_page); iwl_free_pages(priv->shrd, cmd.reply_page);
return ret; return ret;
} }
@ -465,7 +468,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
{ {
unsigned long flags; unsigned long flags;
if (!iwl_is_ready(priv)) { if (!iwl_is_ready(priv->shrd)) {
IWL_DEBUG_INFO(priv, IWL_DEBUG_INFO(priv,
"Unable to remove station %pM, device not ready.\n", "Unable to remove station %pM, device not ready.\n",
addr); addr);
@ -483,7 +486,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
if (WARN_ON(sta_id == IWL_INVALID_STATION)) if (WARN_ON(sta_id == IWL_INVALID_STATION))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
@ -509,11 +512,11 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
if (WARN_ON(priv->num_stations < 0)) if (WARN_ON(priv->num_stations < 0))
priv->num_stations = 0; priv->num_stations = 0;
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return iwl_send_remove_station(priv, addr, sta_id, false); return iwl_send_remove_station(priv, addr, sta_id, false);
out_err: out_err:
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return -EINVAL; return -EINVAL;
} }
@ -534,8 +537,8 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv,
IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n"); IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n");
spin_lock_irqsave(&priv->sta_lock, flags_spin); spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
for (i = 0; i < priv->hw_params.max_stations; i++) { for (i = 0; i < hw_params(priv).max_stations; i++) {
if (ctx && ctx->ctxid != priv->stations[i].ctxid) if (ctx && ctx->ctxid != priv->stations[i].ctxid)
continue; continue;
@ -545,7 +548,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv,
cleared = true; cleared = true;
} }
} }
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
if (!cleared) if (!cleared)
IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n"); IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n");
@ -569,14 +572,14 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
int ret; int ret;
bool send_lq; bool send_lq;
if (!iwl_is_ready(priv)) { if (!iwl_is_ready(priv->shrd)) {
IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n");
return; return;
} }
IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
spin_lock_irqsave(&priv->sta_lock, flags_spin); spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
for (i = 0; i < priv->hw_params.max_stations; i++) { for (i = 0; i < hw_params(priv).max_stations; i++) {
if (ctx->ctxid != priv->stations[i].ctxid) if (ctx->ctxid != priv->stations[i].ctxid)
continue; continue;
if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) && if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) &&
@ -589,7 +592,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
} }
} }
for (i = 0; i < priv->hw_params.max_stations; i++) { for (i = 0; i < hw_params(priv).max_stations; i++) {
if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) {
memcpy(&sta_cmd, &priv->stations[i].sta, memcpy(&sta_cmd, &priv->stations[i].sta,
sizeof(struct iwl_addsta_cmd)); sizeof(struct iwl_addsta_cmd));
@ -599,15 +602,18 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
sizeof(struct iwl_link_quality_cmd)); sizeof(struct iwl_link_quality_cmd));
send_lq = true; send_lq = true;
} }
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock,
flags_spin);
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
if (ret) { if (ret) {
spin_lock_irqsave(&priv->sta_lock, flags_spin); spin_lock_irqsave(&priv->shrd->sta_lock,
flags_spin);
IWL_ERR(priv, "Adding station %pM failed.\n", IWL_ERR(priv, "Adding station %pM failed.\n",
priv->stations[i].sta.sta.addr); priv->stations[i].sta.sta.addr);
priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE;
priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock,
flags_spin);
} }
/* /*
* Rate scaling has already been initialized, send * Rate scaling has already been initialized, send
@ -615,12 +621,12 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
*/ */
if (send_lq) if (send_lq)
iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
spin_lock_irqsave(&priv->sta_lock, flags_spin); spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
} }
} }
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
if (!found) if (!found)
IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n"); IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n");
else else
@ -636,9 +642,9 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
struct iwl_link_quality_cmd lq; struct iwl_link_quality_cmd lq;
bool active; bool active;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return; return;
} }
@ -648,7 +654,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE; active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE;
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
if (active) { if (active) {
ret = iwl_send_remove_station( ret = iwl_send_remove_station(
@ -658,9 +664,9 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
IWL_ERR(priv, "failed to remove STA %pM (%d)\n", IWL_ERR(priv, "failed to remove STA %pM (%d)\n",
priv->stations[sta_id].sta.sta.addr, ret); priv->stations[sta_id].sta.sta.addr, ret);
} }
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
if (ret) if (ret)
@ -685,8 +691,8 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
unsigned long flags; unsigned long flags;
int i; int i;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
for (i = 0; i < priv->hw_params.max_stations; i++) { for (i = 0; i < hw_params(priv).max_stations; i++) {
if (!(priv->stations[i].used & IWL_STA_BCAST)) if (!(priv->stations[i].used & IWL_STA_BCAST))
continue; continue;
@ -697,7 +703,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
kfree(priv->stations[i].lq); kfree(priv->stations[i].lq);
priv->stations[i].lq = NULL; priv->stations[i].lq = NULL;
} }
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
} }
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
@ -781,19 +787,19 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&priv->sta_lock, flags_spin); spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) { if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
return -EINVAL; return -EINVAL;
} }
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
iwl_dump_lq_cmd(priv, lq); iwl_dump_lq_cmd(priv, lq);
if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) if (WARN_ON(init && (cmd.flags & CMD_ASYNC)))
return -EINVAL; return -EINVAL;
if (is_lq_table_valid(priv, ctx, lq)) if (is_lq_table_valid(priv, ctx, lq))
ret = trans_send_cmd(&priv->trans, &cmd); ret = iwl_trans_send_cmd(trans(priv), &cmd);
else else
ret = -EINVAL; ret = -EINVAL;
@ -803,9 +809,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
if (init) { if (init) {
IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d\n", IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d\n",
lq->sta_id); lq->sta_id);
spin_lock_irqsave(&priv->sta_lock, flags_spin); spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
spin_unlock_irqrestore(&priv->sta_lock, flags_spin); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
} }
return ret; return ret;
} }
@ -820,13 +826,13 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
sta->addr); sta->addr);
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
sta->addr); sta->addr);
ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
if (ret) if (ret)
IWL_ERR(priv, "Error removing station %pM\n", IWL_ERR(priv, "Error removing station %pM\n",
sta->addr); sta->addr);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
return ret; return ret;
} }

View file

@ -76,7 +76,7 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
unsigned long flags; unsigned long flags;
struct iwl_rxon_context *ctx; struct iwl_rxon_context *ctx;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
memset(priv->stations, 0, sizeof(priv->stations)); memset(priv->stations, 0, sizeof(priv->stations));
priv->num_stations = 0; priv->num_stations = 0;
@ -94,7 +94,7 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
ctx->key_mapping_keys = 0; ctx->key_mapping_keys = 0;
} }
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
} }
static inline int iwl_sta_id(struct ieee80211_sta *sta) static inline int iwl_sta_id(struct ieee80211_sta *sta)

View file

@ -72,7 +72,6 @@
#include "iwl-dev.h" #include "iwl-dev.h"
#include "iwl-core.h" #include "iwl-core.h"
#include "iwl-debug.h" #include "iwl-debug.h"
#include "iwl-fh.h"
#include "iwl-io.h" #include "iwl-io.h"
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-testmode.h" #include "iwl-testmode.h"
@ -239,7 +238,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
" len %d\n", cmd.id, cmd.flags, cmd.len[0]); " len %d\n", cmd.id, cmd.flags, cmd.len[0]);
/* ok, let's submit the command to ucode */ /* ok, let's submit the command to ucode */
return trans_send_cmd(&priv->trans, &cmd); return iwl_trans_send_cmd(trans(priv), &cmd);
} }
@ -277,7 +276,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
case IWL_TM_CMD_APP2DEV_REG_READ32: case IWL_TM_CMD_APP2DEV_REG_READ32:
val32 = iwl_read32(priv, ofs); val32 = iwl_read32(bus(priv), ofs);
IWL_INFO(priv, "32bit value to read 0x%x\n", val32); IWL_INFO(priv, "32bit value to read 0x%x\n", val32);
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
@ -299,7 +298,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
} else { } else {
val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
IWL_INFO(priv, "32bit value to write 0x%x\n", val32); IWL_INFO(priv, "32bit value to write 0x%x\n", val32);
iwl_write32(priv, ofs, val32); iwl_write32(bus(priv), ofs, val32);
} }
break; break;
case IWL_TM_CMD_APP2DEV_REG_WRITE8: case IWL_TM_CMD_APP2DEV_REG_WRITE8:
@ -309,7 +308,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
} else { } else {
val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]);
IWL_INFO(priv, "8bit value to write 0x%x\n", val8); IWL_INFO(priv, "8bit value to write 0x%x\n", val8);
iwl_write8(priv, ofs, val8); iwl_write8(bus(priv), ofs, val8);
} }
break; break;
default: default:
@ -405,7 +404,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
iwl_testmode_cfg_init_calib(priv); iwl_testmode_cfg_init_calib(priv);
trans_stop_device(&priv->trans); iwl_trans_stop_device(trans(priv));
break; break;
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
@ -613,7 +612,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM)) if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
priv->ucode_owner = owner; priv->shrd->ucode_owner = owner;
else { else {
IWL_DEBUG_INFO(priv, "Invalid owner\n"); IWL_DEBUG_INFO(priv, "Invalid owner\n");
return -EINVAL; return -EINVAL;
@ -661,7 +660,7 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
return -ENOMSG; return -ENOMSG;
} }
/* in case multiple accesses to the device happens */ /* in case multiple accesses to the device happens */
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
case IWL_TM_CMD_APP2DEV_UCODE: case IWL_TM_CMD_APP2DEV_UCODE:
@ -702,7 +701,7 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
break; break;
} }
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
return result; return result;
} }
@ -738,7 +737,7 @@ int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
} }
/* in case multiple accesses to the device happens */ /* in case multiple accesses to the device happens */
mutex_lock(&priv->mutex); mutex_lock(&priv->shrd->mutex);
switch (cmd) { switch (cmd) {
case IWL_TM_CMD_APP2DEV_READ_TRACE: case IWL_TM_CMD_APP2DEV_READ_TRACE:
IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
@ -749,6 +748,6 @@ int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
break; break;
} }
mutex_unlock(&priv->mutex); mutex_unlock(&priv->shrd->mutex);
return result; return result;
} }

View file

@ -29,54 +29,318 @@
#ifndef __iwl_trans_int_pcie_h__ #ifndef __iwl_trans_int_pcie_h__
#define __iwl_trans_int_pcie_h__ #define __iwl_trans_int_pcie_h__
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include "iwl-fh.h"
#include "iwl-csr.h"
#include "iwl-shared.h"
#include "iwl-trans.h"
#include "iwl-debug.h"
#include "iwl-io.h"
struct iwl_tx_queue;
struct iwl_queue;
struct iwl_host_cmd;
/*This file includes the declaration that are internal to the /*This file includes the declaration that are internal to the
* trans_pcie layer */ * trans_pcie layer */
/**
* struct isr_statistics - interrupt statistics
*
*/
struct isr_statistics {
u32 hw;
u32 sw;
u32 err_code;
u32 sch;
u32 alive;
u32 rfkill;
u32 ctkill;
u32 wakeup;
u32 rx;
u32 tx;
u32 unhandled;
};
/**
* struct iwl_rx_queue - Rx queue
* @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
* @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
* @pool:
* @queue:
* @read: Shared index to newest available Rx buffer
* @write: Shared index to oldest written Rx packet
* @free_count: Number of pre-allocated buffers in rx_free
* @write_actual:
* @rx_free: list of free SKBs for use
* @rx_used: List of Rx buffers with no SKB
* @need_update: flag to indicate we need to update read/write index
* @rb_stts: driver's pointer to receive buffer status
* @rb_stts_dma: bus address of receive buffer status
* @lock:
*
* NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
*/
struct iwl_rx_queue {
__le32 *bd;
dma_addr_t bd_dma;
struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
u32 read;
u32 write;
u32 free_count;
u32 write_actual;
struct list_head rx_free;
struct list_head rx_used;
int need_update;
struct iwl_rb_status *rb_stts;
dma_addr_t rb_stts_dma;
spinlock_t lock;
};
struct iwl_dma_ptr {
dma_addr_t dma;
void *addr;
size_t size;
};
/*
* This queue number is required for proper operation
* because the ucode will stop/start the scheduler as
* required.
*/
#define IWL_IPAN_MCAST_QUEUE 8
/**
* struct iwl_trans_pcie - PCIe transport specific data
* @rxq: all the RX queue data
* @rx_replenish: work that will be called when buffers need to be allocated
* @trans: pointer to the generic transport area
* @scd_base_addr: scheduler sram base address in SRAM
* @scd_bc_tbls: pointer to the byte count table of the scheduler
* @kw: keep warm address
* @ac_to_fifo: to what fifo is a specifc AC mapped ?
* @ac_to_queue: to what tx queue is a specifc AC mapped ?
* @mcast_queue:
* @txq: Tx DMA processing queues
* @txq_ctx_active_msk: what queue is active
* queue_stopped: tracks what queue is stopped
* queue_stop_count: tracks what SW queue is stopped
*/
struct iwl_trans_pcie {
struct iwl_rx_queue rxq;
struct work_struct rx_replenish;
struct iwl_trans *trans;
/* INT ICT Table */
__le32 *ict_tbl;
void *ict_tbl_vir;
dma_addr_t ict_tbl_dma;
dma_addr_t aligned_ict_tbl_dma;
int ict_index;
u32 inta;
bool use_ict;
struct tasklet_struct irq_tasklet;
struct isr_statistics isr_stats;
u32 inta_mask;
u32 scd_base_addr;
struct iwl_dma_ptr scd_bc_tbls;
struct iwl_dma_ptr kw;
const u8 *ac_to_fifo[NUM_IWL_RXON_CTX];
const u8 *ac_to_queue[NUM_IWL_RXON_CTX];
u8 mcast_queue[NUM_IWL_RXON_CTX];
struct iwl_tx_queue *txq;
unsigned long txq_ctx_active_msk;
#define IWL_MAX_HW_QUEUES 32
unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
atomic_t queue_stop_count[4];
};
#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific))
/***************************************************** /*****************************************************
* RX * RX
******************************************************/ ******************************************************/
void iwl_bg_rx_replenish(struct work_struct *data); void iwl_bg_rx_replenish(struct work_struct *data);
void iwl_irq_tasklet(struct iwl_priv *priv); void iwl_irq_tasklet(struct iwl_trans *trans);
void iwlagn_rx_replenish(struct iwl_priv *priv); void iwlagn_rx_replenish(struct iwl_trans *trans);
void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
struct iwl_rx_queue *q); struct iwl_rx_queue *q);
/***************************************************** /*****************************************************
* ICT * ICT
******************************************************/ ******************************************************/
int iwl_reset_ict(struct iwl_priv *priv); int iwl_reset_ict(struct iwl_trans *trans);
void iwl_disable_ict(struct iwl_priv *priv); void iwl_disable_ict(struct iwl_trans *trans);
int iwl_alloc_isr_ict(struct iwl_priv *priv); int iwl_alloc_isr_ict(struct iwl_trans *trans);
void iwl_free_isr_ict(struct iwl_priv *priv); void iwl_free_isr_ict(struct iwl_trans *trans);
irqreturn_t iwl_isr_ict(int irq, void *data); irqreturn_t iwl_isr_ict(int irq, void *data);
/***************************************************** /*****************************************************
* TX / HCMD * TX / HCMD
******************************************************/ ******************************************************/
void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); void iwl_txq_update_write_ptr(struct iwl_trans *trans,
void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, struct iwl_tx_queue *txq);
int index); int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
struct iwl_tx_queue *txq, struct iwl_tx_queue *txq,
dma_addr_t addr, u16 len, u8 reset); dma_addr_t addr, u16 len, u8 reset);
int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id);
int count, int slots_num, u32 id); int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id,
int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u32 flags, u16 len, const void *data);
u16 len, const void *data);
void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
struct iwl_tx_queue *txq, struct iwl_tx_queue *txq,
u16 byte_cnt); u16 byte_cnt);
int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id);
u16 ssn_idx, u8 tx_fifo); int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, enum iwl_rxon_context_id ctx, int sta_id,
int txq_id, u32 index); int tid);
void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index);
void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
struct iwl_tx_queue *txq, struct iwl_tx_queue *txq,
int tx_fifo_id, int scd_retry); int tx_fifo_id, int scd_retry);
void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
int frame_limit); enum iwl_rxon_context_id ctx, int sta_id,
int tid, u16 *ssn);
void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
enum iwl_rxon_context_id ctx,
int sta_id, int tid, int frame_limit);
void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
int index);
int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
struct sk_buff_head *skbs);
int iwl_queue_space(const struct iwl_queue *q);
/*****************************************************
* Error handling
******************************************************/
int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
char **buf, bool display);
int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display);
void iwl_dump_csr(struct iwl_trans *trans);
/*****************************************************
* Helpers
******************************************************/
static inline void iwl_disable_interrupts(struct iwl_trans *trans)
{
clear_bit(STATUS_INT_ENABLED, &trans->shrd->status);
/* disable interrupts from uCode/NIC to host */
iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000);
/* acknowledge/clear/reset any interrupts still pending
* from uCode or flow handler (Rx/Tx DMA) */
iwl_write32(bus(trans), CSR_INT, 0xffffffff);
iwl_write32(bus(trans), CSR_FH_INT_STATUS, 0xffffffff);
IWL_DEBUG_ISR(trans, "Disabled interrupts\n");
}
static inline void iwl_enable_interrupts(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
set_bit(STATUS_INT_ENABLED, &trans->shrd->status);
iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask);
}
/*
* we have 8 bits used like this:
*
* 7 6 5 4 3 2 1 0
* | | | | | | | |
* | | | | | | +-+-------- AC queue (0-3)
* | | | | | |
* | +-+-+-+-+------------ HW queue ID
* |
* +---------------------- unused
*/
static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
{
BUG_ON(ac > 3); /* only have 2 bits */
BUG_ON(hwq > 31); /* only use 5 bits */
txq->swq_id = (hwq << 2) | ac;
}
static inline void iwl_wake_queue(struct iwl_trans *trans,
struct iwl_tx_queue *txq)
{
u8 queue = txq->swq_id;
u8 ac = queue & 3;
u8 hwq = (queue >> 2) & 0x1f;
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
if (unlikely(!trans->shrd->mac80211_registered))
return;
if (test_and_clear_bit(hwq, trans_pcie->queue_stopped))
if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0)
ieee80211_wake_queue(trans->shrd->hw, ac);
}
static inline void iwl_stop_queue(struct iwl_trans *trans,
struct iwl_tx_queue *txq)
{
u8 queue = txq->swq_id;
u8 ac = queue & 3;
u8 hwq = (queue >> 2) & 0x1f;
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
if (unlikely(!trans->shrd->mac80211_registered))
return;
if (!test_and_set_bit(hwq, trans_pcie->queue_stopped))
if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0)
ieee80211_stop_queue(trans->shrd->hw, ac);
}
#ifdef ieee80211_stop_queue
#undef ieee80211_stop_queue
#endif
#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
#ifdef ieee80211_wake_queue
#undef ieee80211_wake_queue
#endif
#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie,
int txq_id)
{
set_bit(txq_id, &trans_pcie->txq_ctx_active_msk);
}
static inline void iwl_txq_ctx_deactivate(struct iwl_trans_pcie *trans_pcie,
int txq_id)
{
clear_bit(txq_id, &trans_pcie->txq_ctx_active_msk);
}
static inline int iwl_queue_used(const struct iwl_queue *q, int i)
{
return q->write_ptr >= q->read_ptr ?
(i >= q->read_ptr && i < q->write_ptr) :
!(i < q->read_ptr && i >= q->write_ptr);
}
static inline u8 get_cmd_index(struct iwl_queue *q, u32 index)
{
return index & (q->n_window - 1);
}
#endif /* __iwl_trans_int_pcie_h__ */ #endif /* __iwl_trans_int_pcie_h__ */

File diff suppressed because it is too large Load diff

View file

@ -29,7 +29,6 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <net/mac80211.h>
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-dev.h" #include "iwl-dev.h"
@ -41,11 +40,13 @@
/** /**
* iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/ */
void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
struct iwl_tx_queue *txq, struct iwl_tx_queue *txq,
u16 byte_cnt) u16 byte_cnt)
{ {
struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; struct iwlagn_scd_bc_tbl *scd_bc_tbl;
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
int write_ptr = txq->q.write_ptr; int write_ptr = txq->q.write_ptr;
int txq_id = txq->q.id; int txq_id = txq->q.id;
u8 sec_ctl = 0; u8 sec_ctl = 0;
@ -53,6 +54,8 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
__le16 bc_ent; __le16 bc_ent;
scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
@ -82,7 +85,7 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
/** /**
* iwl_txq_update_write_ptr - Send new write index to hardware * iwl_txq_update_write_ptr - Send new write index to hardware
*/ */
void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
{ {
u32 reg = 0; u32 reg = 0;
int txq_id = txq->q.id; int txq_id = txq->q.id;
@ -90,28 +93,28 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
if (txq->need_update == 0) if (txq->need_update == 0)
return; return;
if (priv->cfg->base_params->shadow_reg_enable) { if (hw_params(trans).shadow_reg_enable) {
/* shadow register enabled */ /* shadow register enabled */
iwl_write32(priv, HBUS_TARG_WRPTR, iwl_write32(bus(trans), HBUS_TARG_WRPTR,
txq->q.write_ptr | (txq_id << 8)); txq->q.write_ptr | (txq_id << 8));
} else { } else {
/* if we're trying to save power */ /* if we're trying to save power */
if (test_bit(STATUS_POWER_PMI, &priv->status)) { if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) {
/* wake up nic if it's powered down ... /* wake up nic if it's powered down ...
* uCode will wake up, and interrupt us again, so next * uCode will wake up, and interrupt us again, so next
* time we'll skip this part. */ * time we'll skip this part. */
reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1);
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
IWL_DEBUG_INFO(priv, IWL_DEBUG_INFO(trans,
"Tx queue %d requesting wakeup," "Tx queue %d requesting wakeup,"
" GP1 = 0x%x\n", txq_id, reg); " GP1 = 0x%x\n", txq_id, reg);
iwl_set_bit(priv, CSR_GP_CNTRL, iwl_set_bit(bus(trans), CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
return; return;
} }
iwl_write_direct32(priv, HBUS_TARG_WRPTR, iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR,
txq->q.write_ptr | (txq_id << 8)); txq->q.write_ptr | (txq_id << 8));
/* /*
@ -120,7 +123,7 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
* trying to tx (during RFKILL, we're not trying to tx). * trying to tx (during RFKILL, we're not trying to tx).
*/ */
} else } else
iwl_write32(priv, HBUS_TARG_WRPTR, iwl_write32(bus(trans), HBUS_TARG_WRPTR,
txq->q.write_ptr | (txq_id << 8)); txq->q.write_ptr | (txq_id << 8));
} }
txq->need_update = 0; txq->need_update = 0;
@ -165,7 +168,7 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
return tfd->num_tbs & 0x1f; return tfd->num_tbs & 0x1f;
} }
static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
struct iwl_tfd *tfd, enum dma_data_direction dma_dir) struct iwl_tfd *tfd, enum dma_data_direction dma_dir)
{ {
int i; int i;
@ -175,56 +178,56 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
num_tbs = iwl_tfd_get_num_tbs(tfd); num_tbs = iwl_tfd_get_num_tbs(tfd);
if (num_tbs >= IWL_NUM_OF_TBS) { if (num_tbs >= IWL_NUM_OF_TBS) {
IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); IWL_ERR(trans, "Too many chunks: %i\n", num_tbs);
/* @todo issue fatal error, it is quite serious situation */ /* @todo issue fatal error, it is quite serious situation */
return; return;
} }
/* Unmap tx_cmd */ /* Unmap tx_cmd */
if (num_tbs) if (num_tbs)
dma_unmap_single(priv->bus->dev, dma_unmap_single(bus(trans)->dev,
dma_unmap_addr(meta, mapping), dma_unmap_addr(meta, mapping),
dma_unmap_len(meta, len), dma_unmap_len(meta, len),
DMA_BIDIRECTIONAL); DMA_BIDIRECTIONAL);
/* Unmap chunks, if any. */ /* Unmap chunks, if any. */
for (i = 1; i < num_tbs; i++) for (i = 1; i < num_tbs; i++)
dma_unmap_single(priv->bus->dev, iwl_tfd_tb_get_addr(tfd, i), dma_unmap_single(bus(trans)->dev, iwl_tfd_tb_get_addr(tfd, i),
iwl_tfd_tb_get_len(tfd, i), dma_dir); iwl_tfd_tb_get_len(tfd, i), dma_dir);
} }
/** /**
* iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
* @priv - driver private data * @trans - transport private data
* @txq - tx queue * @txq - tx queue
* @index - the index of the TFD to be freed * @index - the index of the TFD to be freed
* *
* Does NOT advance any TFD circular buffer read/write indexes * Does NOT advance any TFD circular buffer read/write indexes
* Does NOT free the TFD itself (which is within circular buffer) * Does NOT free the TFD itself (which is within circular buffer)
*/ */
void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
int index) int index)
{ {
struct iwl_tfd *tfd_tmp = txq->tfds; struct iwl_tfd *tfd_tmp = txq->tfds;
iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index], iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index],
DMA_TO_DEVICE); DMA_TO_DEVICE);
/* free SKB */ /* free SKB */
if (txq->txb) { if (txq->skbs) {
struct sk_buff *skb; struct sk_buff *skb;
skb = txq->txb[index].skb; skb = txq->skbs[index];
/* can be called from irqs-disabled context */ /* can be called from irqs-disabled context */
if (skb) { if (skb) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
txq->txb[index].skb = NULL; txq->skbs[index] = NULL;
} }
} }
} }
int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
struct iwl_tx_queue *txq, struct iwl_tx_queue *txq,
dma_addr_t addr, u16 len, dma_addr_t addr, u16 len,
u8 reset) u8 reset)
@ -244,7 +247,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
/* Each TFD can point to a maximum 20 Tx buffers */ /* Each TFD can point to a maximum 20 Tx buffers */
if (num_tbs >= IWL_NUM_OF_TBS) { if (num_tbs >= IWL_NUM_OF_TBS) {
IWL_ERR(priv, "Error can not send more than %d chunks\n", IWL_ERR(trans, "Error can not send more than %d chunks\n",
IWL_NUM_OF_TBS); IWL_NUM_OF_TBS);
return -EINVAL; return -EINVAL;
} }
@ -253,7 +256,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
return -EINVAL; return -EINVAL;
if (unlikely(addr & ~IWL_TX_DMA_MASK)) if (unlikely(addr & ~IWL_TX_DMA_MASK))
IWL_ERR(priv, "Unaligned address = %llx\n", IWL_ERR(trans, "Unaligned address = %llx\n",
(unsigned long long)addr); (unsigned long long)addr);
iwl_tfd_set_tb(tfd, num_tbs, addr, len); iwl_tfd_set_tb(tfd, num_tbs, addr, len);
@ -302,8 +305,7 @@ int iwl_queue_space(const struct iwl_queue *q)
/** /**
* iwl_queue_init - Initialize queue's high/low-water and read/write indexes * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
*/ */
int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id)
int count, int slots_num, u32 id)
{ {
q->n_bd = count; q->n_bd = count;
q->n_window = slots_num; q->n_window = slots_num;
@ -332,16 +334,12 @@ int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
return 0; return 0;
} }
/*TODO: this functions should NOT be exported from trans module - export it static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
* until the reclaim flow will be brought to the transport module too.
* Add a declaration to make sparse happy */
void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq) struct iwl_tx_queue *txq)
{ {
struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
int txq_id = txq->q.id; int txq_id = txq->q.id;
int read_ptr = txq->q.read_ptr; int read_ptr = txq->q.read_ptr;
u8 sta_id = 0; u8 sta_id = 0;
@ -349,7 +347,7 @@ void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
if (txq_id != priv->cmd_queue) if (txq_id != trans->shrd->cmd_queue)
sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
bc_ent = cpu_to_le16(1 | (sta_id << 12)); bc_ent = cpu_to_le16(1 | (sta_id << 12));
@ -360,56 +358,61 @@ void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
} }
static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid,
u16 txq_id) u16 txq_id)
{ {
u32 tbl_dw_addr; u32 tbl_dw_addr;
u32 tbl_dw; u32 tbl_dw;
u16 scd_q2ratid; u16 scd_q2ratid;
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK; scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK;
tbl_dw_addr = priv->scd_base_addr + tbl_dw_addr = trans_pcie->scd_base_addr +
SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); SCD_TRANS_TBL_OFFSET_QUEUE(txq_id);
tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); tbl_dw = iwl_read_targ_mem(bus(trans), tbl_dw_addr);
if (txq_id & 0x1) if (txq_id & 0x1)
tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
else else
tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); iwl_write_targ_mem(bus(trans), tbl_dw_addr, tbl_dw);
return 0; return 0;
} }
static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id)
{ {
/* Simply stop the queue, but don't change any configuration; /* Simply stop the queue, but don't change any configuration;
* the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
iwl_write_prph(priv, iwl_write_prph(bus(trans),
SCD_QUEUE_STATUS_BITS(txq_id), SCD_QUEUE_STATUS_BITS(txq_id),
(0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
(1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
} }
void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, void iwl_trans_set_wr_ptrs(struct iwl_trans *trans,
int txq_id, u32 index) int txq_id, u32 index)
{ {
iwl_write_direct32(priv, HBUS_TARG_WRPTR, iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR,
(index & 0xff) | (txq_id << 8)); (index & 0xff) | (txq_id << 8));
iwl_write_prph(priv, SCD_QUEUE_RDPTR(txq_id), index); iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index);
} }
void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
struct iwl_tx_queue *txq, struct iwl_tx_queue *txq,
int tx_fifo_id, int scd_retry) int tx_fifo_id, int scd_retry)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int txq_id = txq->q.id; int txq_id = txq->q.id;
int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; int active =
test_bit(txq_id, &trans_pcie->txq_ctx_active_msk) ? 1 : 0;
iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id), iwl_write_prph(bus(trans), SCD_QUEUE_STATUS_BITS(txq_id),
(active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
(tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) |
(1 << SCD_QUEUE_STTS_REG_POS_WSL) | (1 << SCD_QUEUE_STTS_REG_POS_WSL) |
@ -417,55 +420,75 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv,
txq->sched_retry = scd_retry; txq->sched_retry = scd_retry;
IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", IWL_DEBUG_INFO(trans, "%s %s Queue %d on FIFO %d\n",
active ? "Activate" : "Deactivate", active ? "Activate" : "Deactivate",
scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id);
} }
void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie,
int frame_limit) u8 ctx, u16 tid)
{
const u8 *ac_to_fifo = trans_pcie->ac_to_fifo[ctx];
if (likely(tid < ARRAY_SIZE(tid_to_ac)))
return ac_to_fifo[tid_to_ac[tid]];
/* no support for TIDs 8-15 yet */
return -EINVAL;
}
void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
enum iwl_rxon_context_id ctx, int sta_id,
int tid, int frame_limit)
{ {
int tx_fifo, txq_id, ssn_idx; int tx_fifo, txq_id, ssn_idx;
u16 ra_tid; u16 ra_tid;
unsigned long flags; unsigned long flags;
struct iwl_tid_data *tid_data; struct iwl_tid_data *tid_data;
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
if (WARN_ON(sta_id == IWL_INVALID_STATION)) if (WARN_ON(sta_id == IWL_INVALID_STATION))
return; return;
if (WARN_ON(tid >= MAX_TID_COUNT)) if (WARN_ON(tid >= IWL_MAX_TID_COUNT))
return; return;
spin_lock_irqsave(&priv->sta_lock, flags); tx_fifo = get_fifo_from_tid(trans_pcie, ctx, tid);
tid_data = &priv->stations[sta_id].tid[tid]; if (WARN_ON(tx_fifo < 0)) {
IWL_ERR(trans, "txq_agg_setup, bad fifo: %d\n", tx_fifo);
return;
}
spin_lock_irqsave(&trans->shrd->sta_lock, flags);
tid_data = &trans->shrd->tid_data[sta_id][tid];
ssn_idx = SEQ_TO_SN(tid_data->seq_number); ssn_idx = SEQ_TO_SN(tid_data->seq_number);
txq_id = tid_data->agg.txq_id; txq_id = tid_data->agg.txq_id;
tx_fifo = tid_data->agg.tx_fifo; spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
spin_unlock_irqrestore(&priv->sta_lock, flags);
ra_tid = BUILD_RAxTID(sta_id, tid); ra_tid = BUILD_RAxTID(sta_id, tid);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&trans->shrd->lock, flags);
/* Stop this Tx queue before configuring it */ /* Stop this Tx queue before configuring it */
iwlagn_tx_queue_stop_scheduler(priv, txq_id); iwlagn_tx_queue_stop_scheduler(trans, txq_id);
/* Map receiver-address / traffic-ID to this queue */ /* Map receiver-address / traffic-ID to this queue */
iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id);
/* Set this queue as a chain-building queue */ /* Set this queue as a chain-building queue */
iwl_set_bits_prph(priv, SCD_QUEUECHAIN_SEL, (1<<txq_id)); iwl_set_bits_prph(bus(trans), SCD_QUEUECHAIN_SEL, (1<<txq_id));
/* enable aggregations for the queue */ /* enable aggregations for the queue */
iwl_set_bits_prph(priv, SCD_AGGR_SEL, (1<<txq_id)); iwl_set_bits_prph(bus(trans), SCD_AGGR_SEL, (1<<txq_id));
/* Place first TFD at index corresponding to start sequence number. /* Place first TFD at index corresponding to start sequence number.
* Assumes that ssn_idx is valid (!= 0xFFF) */ * Assumes that ssn_idx is valid (!= 0xFFF) */
priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); trans_pcie->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); trans_pcie->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx);
/* Set up Tx window size and frame limit for this queue */ /* Set up Tx window size and frame limit for this queue */
iwl_write_targ_mem(priv, priv->scd_base_addr + iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
SCD_CONTEXT_QUEUE_OFFSET(txq_id) + SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
sizeof(u32), sizeof(u32),
((frame_limit << ((frame_limit <<
@ -475,40 +498,159 @@ void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid,
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
iwl_set_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); iwl_set_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id],
tx_fifo, 1);
spin_unlock_irqrestore(&priv->lock, flags); trans_pcie->txq[txq_id].sta_id = sta_id;
trans_pcie->txq[txq_id].tid = tid;
spin_unlock_irqrestore(&trans->shrd->lock, flags);
} }
int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, /*
u16 ssn_idx, u8 tx_fifo) * Find first available (lowest unused) Tx Queue, mark it "active".
* Called only when finding queue for aggregation.
* Should never return anything < 7, because they should already
* be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
*/
static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int txq_id;
for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
if (!test_and_set_bit(txq_id,
&trans_pcie->txq_ctx_active_msk))
return txq_id;
return -1;
}
int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
enum iwl_rxon_context_id ctx, int sta_id,
int tid, u16 *ssn)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tid_data *tid_data;
unsigned long flags;
u16 txq_id;
struct iwl_priv *priv = priv(trans);
txq_id = iwlagn_txq_ctx_activate_free(trans);
if (txq_id == -1) {
IWL_ERR(trans, "No free aggregation queue available\n");
return -ENXIO;
}
spin_lock_irqsave(&trans->shrd->sta_lock, flags);
tid_data = &trans->shrd->tid_data[sta_id][tid];
*ssn = SEQ_TO_SN(tid_data->seq_number);
tid_data->agg.txq_id = txq_id;
iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id);
tid_data = &trans->shrd->tid_data[sta_id][tid];
if (tid_data->tfds_in_queue == 0) {
IWL_DEBUG_HT(trans, "HW queue is empty\n");
tid_data->agg.state = IWL_AGG_ON;
iwl_start_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
} else {
IWL_DEBUG_HT(trans, "HW queue is NOT empty: %d packets in HW"
"queue\n", tid_data->tfds_in_queue);
tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
}
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return 0;
}
void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
iwlagn_tx_queue_stop_scheduler(trans, txq_id);
iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id));
trans_pcie->txq[txq_id].q.read_ptr = 0;
trans_pcie->txq[txq_id].q.write_ptr = 0;
/* supposes that ssn_idx is valid (!= 0xFFF) */
iwl_trans_set_wr_ptrs(trans, txq_id, 0);
iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
iwl_txq_ctx_deactivate(trans_pcie, txq_id);
iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0);
}
int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
enum iwl_rxon_context_id ctx, int sta_id,
int tid)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
unsigned long flags;
int read_ptr, write_ptr;
struct iwl_tid_data *tid_data;
int txq_id;
spin_lock_irqsave(&trans->shrd->sta_lock, flags);
tid_data = &trans->shrd->tid_data[sta_id][tid];
txq_id = tid_data->agg.txq_id;
if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
(IWLAGN_FIRST_AMPDU_QUEUE + (IWLAGN_FIRST_AMPDU_QUEUE +
priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { hw_params(trans).num_ampdu_queues <= txq_id)) {
IWL_ERR(priv, IWL_ERR(trans,
"queue number out of range: %d, must be %d to %d\n", "queue number out of range: %d, must be %d to %d\n",
txq_id, IWLAGN_FIRST_AMPDU_QUEUE, txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
IWLAGN_FIRST_AMPDU_QUEUE + IWLAGN_FIRST_AMPDU_QUEUE +
priv->cfg->base_params->num_of_ampdu_queues - 1); hw_params(trans).num_ampdu_queues - 1);
spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
return -EINVAL; return -EINVAL;
} }
iwlagn_tx_queue_stop_scheduler(priv, txq_id); switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
case IWL_EMPTYING_HW_QUEUE_ADDBA:
/*
* This can happen if the peer stops aggregation
* again before we've had a chance to drain the
* queue we selected previously, i.e. before the
* session was really started completely.
*/
IWL_DEBUG_HT(trans, "AGG stop before setup done\n");
goto turn_off;
case IWL_AGG_ON:
break;
default:
IWL_WARN(trans, "Stopping AGG while state not ON"
"or starting\n");
}
iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id)); write_ptr = trans_pcie->txq[txq_id].q.write_ptr;
read_ptr = trans_pcie->txq[txq_id].q.read_ptr;
priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); /* The queue is not empty */
priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); if (write_ptr != read_ptr) {
/* supposes that ssn_idx is valid (!= 0xFFF) */ IWL_DEBUG_HT(trans, "Stopping a non empty AGG HW QUEUE\n");
iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); trans->shrd->tid_data[sta_id][tid].agg.state =
IWL_EMPTYING_HW_QUEUE_DELBA;
spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
return 0;
}
iwl_clear_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); IWL_DEBUG_HT(trans, "HW queue is empty\n");
iwl_txq_ctx_deactivate(priv, txq_id); turn_off:
iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); trans->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
/* do not restore/save irqs */
spin_unlock(&trans->shrd->sta_lock);
spin_lock(&trans->shrd->lock);
iwl_trans_pcie_txq_agg_disable(trans, txq_id);
spin_unlock_irqrestore(&trans->shrd->lock, flags);
iwl_stop_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
return 0; return 0;
} }
@ -524,9 +666,10 @@ int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
* failed. On success, it turns the index (> 0) of command in the * failed. On success, it turns the index (> 0) of command in the
* command queue. * command queue.
*/ */
static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{ {
struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
struct iwl_queue *q = &txq->q; struct iwl_queue *q = &txq->q;
struct iwl_device_cmd *out_cmd; struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta; struct iwl_cmd_meta *out_meta;
@ -544,14 +687,14 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
int trace_idx; int trace_idx;
#endif #endif
if (test_bit(STATUS_FW_ERROR, &priv->status)) { if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) {
IWL_WARN(priv, "fw recovery, no hcmd send\n"); IWL_WARN(trans, "fw recovery, no hcmd send\n");
return -EIO; return -EIO;
} }
if ((priv->ucode_owner == IWL_OWNERSHIP_TM) && if ((trans->shrd->ucode_owner == IWL_OWNERSHIP_TM) &&
!(cmd->flags & CMD_ON_DEMAND)) { !(cmd->flags & CMD_ON_DEMAND)) {
IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n"); IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n");
return -EIO; return -EIO;
} }
@ -584,22 +727,22 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE)) if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
return -EINVAL; return -EINVAL;
if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { if (iwl_is_rfkill(trans->shrd) || iwl_is_ctkill(trans->shrd)) {
IWL_WARN(priv, "Not sending command - %s KILL\n", IWL_WARN(trans, "Not sending command - %s KILL\n",
iwl_is_rfkill(priv) ? "RF" : "CT"); iwl_is_rfkill(trans->shrd) ? "RF" : "CT");
return -EIO; return -EIO;
} }
spin_lock_irqsave(&priv->hcmd_lock, flags); spin_lock_irqsave(&trans->hcmd_lock, flags);
if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
spin_unlock_irqrestore(&priv->hcmd_lock, flags); spin_unlock_irqrestore(&trans->hcmd_lock, flags);
IWL_ERR(priv, "No space in command queue\n"); IWL_ERR(trans, "No space in command queue\n");
is_ct_kill = iwl_check_for_ct_kill(priv); is_ct_kill = iwl_check_for_ct_kill(priv(trans));
if (!is_ct_kill) { if (!is_ct_kill) {
IWL_ERR(priv, "Restarting adapter due to queue full\n"); IWL_ERR(trans, "Restarting adapter queue is full\n");
iwlagn_fw_error(priv, false); iwlagn_fw_error(priv(trans), false);
} }
return -ENOSPC; return -ENOSPC;
} }
@ -618,7 +761,8 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
out_cmd->hdr.cmd = cmd->id; out_cmd->hdr.cmd = cmd->id;
out_cmd->hdr.flags = 0; out_cmd->hdr.flags = 0;
out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) | out_cmd->hdr.sequence =
cpu_to_le16(QUEUE_TO_SEQ(trans->shrd->cmd_queue) |
INDEX_TO_SEQ(q->write_ptr)); INDEX_TO_SEQ(q->write_ptr));
/* and copy the data that needs to be copied */ /* and copy the data that needs to be copied */
@ -633,16 +777,16 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
cmd_dest += cmd->len[i]; cmd_dest += cmd->len[i];
} }
IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " IWL_DEBUG_HC(trans, "Sending command %s (#%x), seq: 0x%04X, "
"%d bytes at %d[%d]:%d\n", "%d bytes at %d[%d]:%d\n",
get_cmd_string(out_cmd->hdr.cmd), get_cmd_string(out_cmd->hdr.cmd),
out_cmd->hdr.cmd, out_cmd->hdr.cmd,
le16_to_cpu(out_cmd->hdr.sequence), cmd_size, le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
q->write_ptr, idx, priv->cmd_queue); q->write_ptr, idx, trans->shrd->cmd_queue);
phys_addr = dma_map_single(priv->bus->dev, &out_cmd->hdr, copy_size, phys_addr = dma_map_single(bus(trans)->dev, &out_cmd->hdr, copy_size,
DMA_BIDIRECTIONAL); DMA_BIDIRECTIONAL);
if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) {
idx = -ENOMEM; idx = -ENOMEM;
goto out; goto out;
} }
@ -650,7 +794,8 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
dma_unmap_addr_set(out_meta, mapping, phys_addr); dma_unmap_addr_set(out_meta, mapping, phys_addr);
dma_unmap_len_set(out_meta, len, copy_size); dma_unmap_len_set(out_meta, len, copy_size);
iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, copy_size, 1); iwlagn_txq_attach_buf_to_tfd(trans, txq,
phys_addr, copy_size, 1);
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING #ifdef CONFIG_IWLWIFI_DEVICE_TRACING
trace_bufs[0] = &out_cmd->hdr; trace_bufs[0] = &out_cmd->hdr;
trace_lens[0] = copy_size; trace_lens[0] = copy_size;
@ -662,17 +807,18 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
continue; continue;
if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
continue; continue;
phys_addr = dma_map_single(priv->bus->dev, (void *)cmd->data[i], phys_addr = dma_map_single(bus(trans)->dev,
(void *)cmd->data[i],
cmd->len[i], DMA_BIDIRECTIONAL); cmd->len[i], DMA_BIDIRECTIONAL);
if (dma_mapping_error(priv->bus->dev, phys_addr)) { if (dma_mapping_error(bus(trans)->dev, phys_addr)) {
iwlagn_unmap_tfd(priv, out_meta, iwlagn_unmap_tfd(trans, out_meta,
&txq->tfds[q->write_ptr], &txq->tfds[q->write_ptr],
DMA_BIDIRECTIONAL); DMA_BIDIRECTIONAL);
idx = -ENOMEM; idx = -ENOMEM;
goto out; goto out;
} }
iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr,
cmd->len[i], 0); cmd->len[i], 0);
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING #ifdef CONFIG_IWLWIFI_DEVICE_TRACING
trace_bufs[trace_idx] = cmd->data[i]; trace_bufs[trace_idx] = cmd->data[i];
@ -688,7 +834,7 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
/* check that tracing gets all possible blocks */ /* check that tracing gets all possible blocks */
BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3); BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING #ifdef CONFIG_IWLWIFI_DEVICE_TRACING
trace_iwlwifi_dev_hcmd(priv, cmd->flags, trace_iwlwifi_dev_hcmd(priv(trans), cmd->flags,
trace_bufs[0], trace_lens[0], trace_bufs[0], trace_lens[0],
trace_bufs[1], trace_lens[1], trace_bufs[1], trace_lens[1],
trace_bufs[2], trace_lens[2]); trace_bufs[2], trace_lens[2]);
@ -696,10 +842,10 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
/* Increment and update queue's write index */ /* Increment and update queue's write index */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
iwl_txq_update_write_ptr(priv, txq); iwl_txq_update_write_ptr(trans, txq);
out: out:
spin_unlock_irqrestore(&priv->hcmd_lock, flags); spin_unlock_irqrestore(&trans->hcmd_lock, flags);
return idx; return idx;
} }
@ -712,7 +858,9 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
*/ */
static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx) static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
{ {
struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans(priv));
struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
struct iwl_queue *q = &txq->q; struct iwl_queue *q = &txq->q;
int nfreed = 0; int nfreed = 0;
@ -752,17 +900,19 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
int cmd_index; int cmd_index;
struct iwl_device_cmd *cmd; struct iwl_device_cmd *cmd;
struct iwl_cmd_meta *meta; struct iwl_cmd_meta *meta;
struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; struct iwl_trans *trans = trans(priv);
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
unsigned long flags; unsigned long flags;
/* If a Tx command is being handled and it isn't in the actual /* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced * command queue then there a command routing bug has been introduced
* in the queue management code. */ * in the queue management code. */
if (WARN(txq_id != priv->cmd_queue, if (WARN(txq_id != trans->shrd->cmd_queue,
"wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
txq_id, priv->cmd_queue, sequence, txq_id, trans->shrd->cmd_queue, sequence,
priv->txq[priv->cmd_queue].q.read_ptr, trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr,
priv->txq[priv->cmd_queue].q.write_ptr)) { trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) {
iwl_print_hex_error(priv, pkt, 32); iwl_print_hex_error(priv, pkt, 32);
return; return;
} }
@ -771,7 +921,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
cmd = txq->cmd[cmd_index]; cmd = txq->cmd[cmd_index];
meta = &txq->meta[cmd_index]; meta = &txq->meta[cmd_index];
iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); iwlagn_unmap_tfd(trans, meta, &txq->tfds[index],
DMA_BIDIRECTIONAL);
/* Input error checking is done when commands are added to queue. */ /* Input error checking is done when commands are added to queue. */
if (meta->flags & CMD_WANT_SKB) { if (meta->flags & CMD_WANT_SKB) {
@ -780,20 +931,20 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
} else if (meta->callback) } else if (meta->callback)
meta->callback(priv, cmd, pkt); meta->callback(priv, cmd, pkt);
spin_lock_irqsave(&priv->hcmd_lock, flags); spin_lock_irqsave(&trans->hcmd_lock, flags);
iwl_hcmd_queue_reclaim(priv, txq_id, index); iwl_hcmd_queue_reclaim(priv, txq_id, index);
if (!(meta->flags & CMD_ASYNC)) { if (!(meta->flags & CMD_ASYNC)) {
clear_bit(STATUS_HCMD_ACTIVE, &priv->status); clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
get_cmd_string(cmd->hdr.cmd)); get_cmd_string(cmd->hdr.cmd));
wake_up_interruptible(&priv->wait_command_queue); wake_up_interruptible(&priv->wait_command_queue);
} }
meta->flags = 0; meta->flags = 0;
spin_unlock_irqrestore(&priv->hcmd_lock, flags); spin_unlock_irqrestore(&trans->hcmd_lock, flags);
} }
const char *get_cmd_string(u8 cmd) const char *get_cmd_string(u8 cmd)
@ -904,7 +1055,7 @@ static void iwl_generic_cmd_callback(struct iwl_priv *priv,
#endif #endif
} }
static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{ {
int ret; int ret;
@ -916,77 +1067,78 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (!cmd->callback) if (!cmd->callback)
cmd->callback = iwl_generic_cmd_callback; cmd->callback = iwl_generic_cmd_callback;
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
return -EBUSY; return -EBUSY;
ret = iwl_enqueue_hcmd(priv, cmd); ret = iwl_enqueue_hcmd(trans, cmd);
if (ret < 0) { if (ret < 0) {
IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret); get_cmd_string(cmd->id), ret);
return ret; return ret;
} }
return 0; return 0;
} }
static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int cmd_idx; int cmd_idx;
int ret; int ret;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&trans->shrd->mutex);
/* A synchronous command can not have a callback set. */ /* A synchronous command can not have a callback set. */
if (WARN_ON(cmd->callback)) if (WARN_ON(cmd->callback))
return -EINVAL; return -EINVAL;
IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
get_cmd_string(cmd->id)); get_cmd_string(cmd->id));
set_bit(STATUS_HCMD_ACTIVE, &priv->status); set_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n",
get_cmd_string(cmd->id)); get_cmd_string(cmd->id));
cmd_idx = iwl_enqueue_hcmd(priv, cmd); cmd_idx = iwl_enqueue_hcmd(trans, cmd);
if (cmd_idx < 0) { if (cmd_idx < 0) {
ret = cmd_idx; ret = cmd_idx;
clear_bit(STATUS_HCMD_ACTIVE, &priv->status); clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret); get_cmd_string(cmd->id), ret);
return ret; return ret;
} }
ret = wait_event_interruptible_timeout(priv->wait_command_queue, ret = wait_event_interruptible_timeout(priv(trans)->wait_command_queue,
!test_bit(STATUS_HCMD_ACTIVE, &priv->status), !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status),
HOST_COMPLETE_TIMEOUT); HOST_COMPLETE_TIMEOUT);
if (!ret) { if (!ret) {
if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) {
IWL_ERR(priv, IWL_ERR(trans,
"Error sending %s: time out after %dms.\n", "Error sending %s: time out after %dms.\n",
get_cmd_string(cmd->id), get_cmd_string(cmd->id),
jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
clear_bit(STATUS_HCMD_ACTIVE, &priv->status); clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command" IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command"
"%s\n", get_cmd_string(cmd->id)); "%s\n", get_cmd_string(cmd->id));
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
goto cancel; goto cancel;
} }
} }
if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) {
IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n", IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n",
get_cmd_string(cmd->id)); get_cmd_string(cmd->id));
ret = -ECANCELED; ret = -ECANCELED;
goto fail; goto fail;
} }
if (test_bit(STATUS_FW_ERROR, &priv->status)) { if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) {
IWL_ERR(priv, "Command %s failed: FW Error\n", IWL_ERR(trans, "Command %s failed: FW Error\n",
get_cmd_string(cmd->id)); get_cmd_string(cmd->id));
ret = -EIO; ret = -EIO;
goto fail; goto fail;
} }
if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) { if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
IWL_ERR(priv, "Error: Response NULL in '%s'\n", IWL_ERR(trans, "Error: Response NULL in '%s'\n",
get_cmd_string(cmd->id)); get_cmd_string(cmd->id));
ret = -EIO; ret = -EIO;
goto cancel; goto cancel;
@ -1002,28 +1154,28 @@ cancel:
* in later, it will possibly set an invalid * in later, it will possibly set an invalid
* address (cmd->meta.source). * address (cmd->meta.source).
*/ */
priv->txq[priv->cmd_queue].meta[cmd_idx].flags &= trans_pcie->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &=
~CMD_WANT_SKB; ~CMD_WANT_SKB;
} }
fail: fail:
if (cmd->reply_page) { if (cmd->reply_page) {
iwl_free_pages(priv, cmd->reply_page); iwl_free_pages(trans->shrd, cmd->reply_page);
cmd->reply_page = 0; cmd->reply_page = 0;
} }
return ret; return ret;
} }
int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{ {
if (cmd->flags & CMD_ASYNC) if (cmd->flags & CMD_ASYNC)
return iwl_send_cmd_async(priv, cmd); return iwl_send_cmd_async(trans, cmd);
return iwl_send_cmd_sync(priv, cmd); return iwl_send_cmd_sync(trans, cmd);
} }
int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len, int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags,
const void *data) u16 len, const void *data)
{ {
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
.id = id, .id = id,
@ -1032,5 +1184,53 @@ int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len,
.flags = flags, .flags = flags,
}; };
return iwl_send_cmd(priv, &cmd); return iwl_trans_pcie_send_cmd(trans, &cmd);
}
/* Frees buffers until index _not_ inclusive */
int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
struct sk_buff_head *skbs)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
struct iwl_queue *q = &txq->q;
int last_to_free;
int freed = 0;
/*Since we free until index _not_ inclusive, the one before index is
* the last we will free. This one must be used */
last_to_free = iwl_queue_dec_wrap(index, q->n_bd);
if ((index >= q->n_bd) ||
(iwl_queue_used(q, last_to_free) == 0)) {
IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), "
"last_to_free %d is out of range [0-%d] %d %d.\n",
__func__, txq_id, last_to_free, q->n_bd,
q->write_ptr, q->read_ptr);
return 0;
}
IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id,
q->read_ptr, index);
if (WARN_ON(!skb_queue_empty(skbs)))
return 0;
for (;
q->read_ptr != index;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
if (WARN_ON_ONCE(txq->skbs[txq->q.read_ptr] == NULL))
continue;
__skb_queue_tail(skbs, txq->skbs[txq->q.read_ptr]);
txq->skbs[txq->q.read_ptr] = NULL;
iwlagn_txq_inval_byte_cnt_tbl(trans, txq);
iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr);
freed++;
}
return freed;
} }

File diff suppressed because it is too large Load diff

View file

@ -63,163 +63,235 @@
#ifndef __iwl_trans_h__ #ifndef __iwl_trans_h__
#define __iwl_trans_h__ #define __iwl_trans_h__
#include <linux/debugfs.h>
#include <linux/skbuff.h>
#include "iwl-shared.h"
#include "iwl-commands.h"
/*This file includes the declaration that are exported from the transport /*This file includes the declaration that are exported from the transport
* layer */ * layer */
struct iwl_priv; struct iwl_priv;
struct iwl_rxon_context; struct iwl_rxon_context;
struct iwl_host_cmd; struct iwl_host_cmd;
struct iwl_shared;
struct iwl_device_cmd;
/** /**
* struct iwl_trans_ops - transport specific operations * struct iwl_trans_ops - transport specific operations
* @alloc: allocates the meta data (not the queues themselves)
* @request_irq: requests IRQ - will be called before the FW load in probe flow
* @start_device: allocates and inits all the resources for the transport * @start_device: allocates and inits all the resources for the transport
* layer. * layer.
* @prepare_card_hw: claim the ownership on the HW. Will be called during * @prepare_card_hw: claim the ownership on the HW. Will be called during
* probe. * probe.
* @tx_start: starts and configures all the Tx fifo - usually done once the fw * @tx_start: starts and configures all the Tx fifo - usually done once the fw
* is alive. * is alive.
* @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
* @stop_device:stops the whole device (embedded CPU put to reset) * @stop_device:stops the whole device (embedded CPU put to reset)
* @rx_free: frees the rx memory
* @tx_free: frees the tx memory
* @send_cmd:send a host command * @send_cmd:send a host command
* @send_cmd_pdu:send a host command: flags can be CMD_* * @send_cmd_pdu:send a host command: flags can be CMD_*
* @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use
* @tx: send an skb * @tx: send an skb
* @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is * @reclaim: free packet until ssn. Returns a list of freed packets.
* @tx_agg_alloc: allocate resources for a TX BA session
* @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is
* ready and a successful ADDBA response has been received. * ready and a successful ADDBA response has been received.
* @txq_agg_disable: de-configure a Tx queue to send AMPDUs * @tx_agg_disable: de-configure a Tx queue to send AMPDUs
* @kick_nic: remove the RESET from the embedded CPU and let it run * @kick_nic: remove the RESET from the embedded CPU and let it run
* @sync_irq: the upper layer will typically disable interrupt and call this
* handler. After this handler returns, it is guaranteed that all
* the ISR / tasklet etc... have finished running and the transport
* layer shall not pass any Rx.
* @free: release all the ressource for the transport layer itself such as * @free: release all the ressource for the transport layer itself such as
* irq, tasklet etc... * irq, tasklet etc...
* @stop_queue: stop a specific queue
* @check_stuck_queue: check if a specific queue is stuck
* @wait_tx_queue_empty: wait until all tx queues are empty
* @dbgfs_register: add the dbgfs files under this directory. Files will be
* automatically deleted.
* @suspend: stop the device unless WoWLAN is configured
* @resume: resume activity of the device
*/ */
struct iwl_trans_ops { struct iwl_trans_ops {
int (*start_device)(struct iwl_priv *priv); struct iwl_trans *(*alloc)(struct iwl_shared *shrd);
int (*prepare_card_hw)(struct iwl_priv *priv); int (*request_irq)(struct iwl_trans *iwl_trans);
void (*stop_device)(struct iwl_priv *priv); int (*start_device)(struct iwl_trans *trans);
void (*tx_start)(struct iwl_priv *priv); int (*prepare_card_hw)(struct iwl_trans *trans);
void (*tx_free)(struct iwl_priv *priv); void (*stop_device)(struct iwl_trans *trans);
void (*rx_free)(struct iwl_priv *priv); void (*tx_start)(struct iwl_trans *trans);
int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); void (*wake_any_queue)(struct iwl_trans *trans, u8 ctx);
int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
int (*send_cmd_pdu)(struct iwl_trans *trans, u8 id, u32 flags, u16 len,
const void *data); const void *data);
struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_priv *priv, int txq_id); int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id);
struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
struct iwl_rxon_context *ctx); int txq_id, int ssn, u32 status,
struct sk_buff_head *skbs);
int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, int (*tx_agg_disable)(struct iwl_trans *trans,
u16 ssn_idx, u8 tx_fifo); enum iwl_rxon_context_id ctx, int sta_id,
void (*txq_agg_setup)(struct iwl_priv *priv, int sta_id, int tid, int tid);
int (*tx_agg_alloc)(struct iwl_trans *trans,
enum iwl_rxon_context_id ctx, int sta_id, int tid,
u16 *ssn);
void (*tx_agg_setup)(struct iwl_trans *trans,
enum iwl_rxon_context_id ctx, int sta_id, int tid,
int frame_limit); int frame_limit);
void (*kick_nic)(struct iwl_priv *priv); void (*kick_nic)(struct iwl_trans *trans);
void (*sync_irq)(struct iwl_priv *priv); void (*free)(struct iwl_trans *trans);
void (*free)(struct iwl_priv *priv);
void (*stop_queue)(struct iwl_trans *trans, int q);
int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
int (*check_stuck_queue)(struct iwl_trans *trans, int q);
int (*wait_tx_queue_empty)(struct iwl_trans *trans);
int (*suspend)(struct iwl_trans *trans);
int (*resume)(struct iwl_trans *trans);
}; };
/**
* struct iwl_trans - transport common data
* @ops - pointer to iwl_trans_ops
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
* @hcmd_lock: protects HCMD
*/
struct iwl_trans { struct iwl_trans {
const struct iwl_trans_ops *ops; const struct iwl_trans_ops *ops;
struct iwl_priv *priv; struct iwl_shared *shrd;
spinlock_t hcmd_lock;
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[0] __attribute__((__aligned__(sizeof(void *))));
}; };
static inline int trans_start_device(struct iwl_trans *trans) static inline int iwl_trans_request_irq(struct iwl_trans *trans)
{ {
return trans->ops->start_device(trans->priv); return trans->ops->request_irq(trans);
} }
static inline int trans_prepare_card_hw(struct iwl_trans *trans) static inline int iwl_trans_start_device(struct iwl_trans *trans)
{ {
return trans->ops->prepare_card_hw(trans->priv); return trans->ops->start_device(trans);
} }
static inline void trans_stop_device(struct iwl_trans *trans) static inline int iwl_trans_prepare_card_hw(struct iwl_trans *trans)
{ {
trans->ops->stop_device(trans->priv); return trans->ops->prepare_card_hw(trans);
} }
static inline void trans_tx_start(struct iwl_trans *trans) static inline void iwl_trans_stop_device(struct iwl_trans *trans)
{ {
trans->ops->tx_start(trans->priv); trans->ops->stop_device(trans);
} }
static inline void trans_rx_free(struct iwl_trans *trans) static inline void iwl_trans_tx_start(struct iwl_trans *trans)
{ {
trans->ops->rx_free(trans->priv); trans->ops->tx_start(trans);
} }
static inline void trans_tx_free(struct iwl_trans *trans) static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, u8 ctx)
{ {
trans->ops->tx_free(trans->priv); trans->ops->wake_any_queue(trans, ctx);
} }
static inline int trans_send_cmd(struct iwl_trans *trans,
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd) struct iwl_host_cmd *cmd)
{ {
return trans->ops->send_cmd(trans->priv, cmd); return trans->ops->send_cmd(trans, cmd);
} }
static inline int trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, static inline int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
u16 len, const void *data) u32 flags, u16 len, const void *data)
{ {
return trans->ops->send_cmd_pdu(trans->priv, id, flags, len, data); return trans->ops->send_cmd_pdu(trans, id, flags, len, data);
} }
static inline struct iwl_tx_cmd *trans_get_tx_cmd(struct iwl_trans *trans, static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
int txq_id) struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id)
{ {
return trans->ops->get_tx_cmd(trans->priv, txq_id); return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id);
} }
static inline int trans_tx(struct iwl_trans *trans, struct sk_buff *skb, static inline void iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, int tid, int txq_id, int ssn, u32 status,
struct iwl_rxon_context *ctx) struct sk_buff_head *skbs)
{ {
return trans->ops->tx(trans->priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, status, skbs);
} }
static inline int trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id, static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
u16 ssn_idx, u8 tx_fifo) enum iwl_rxon_context_id ctx,
int sta_id, int tid)
{ {
return trans->ops->txq_agg_disable(trans->priv, txq_id, return trans->ops->tx_agg_disable(trans, ctx, sta_id, tid);
ssn_idx, tx_fifo);
} }
static inline void trans_txq_agg_setup(struct iwl_trans *trans, int sta_id, static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans,
int tid, int frame_limit) enum iwl_rxon_context_id ctx,
int sta_id, int tid, u16 *ssn)
{ {
trans->ops->txq_agg_setup(trans->priv, sta_id, tid, frame_limit); return trans->ops->tx_agg_alloc(trans, ctx, sta_id, tid, ssn);
} }
static inline void trans_kick_nic(struct iwl_trans *trans)
static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans,
enum iwl_rxon_context_id ctx,
int sta_id, int tid,
int frame_limit)
{ {
trans->ops->kick_nic(trans->priv); trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit);
} }
static inline void trans_sync_irq(struct iwl_trans *trans) static inline void iwl_trans_kick_nic(struct iwl_trans *trans)
{ {
trans->ops->sync_irq(trans->priv); trans->ops->kick_nic(trans);
} }
static inline void trans_free(struct iwl_trans *trans) static inline void iwl_trans_free(struct iwl_trans *trans)
{ {
trans->ops->free(trans->priv); trans->ops->free(trans);
} }
int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv); static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q)
{
trans->ops->stop_queue(trans, q);
}
/*TODO: this functions should NOT be exported from trans module - export it static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
* until the reclaim flow will be brought to the transport module too */ {
return trans->ops->wait_tx_queue_empty(trans);
}
struct iwl_tx_queue; static inline int iwl_trans_check_stuck_queue(struct iwl_trans *trans, int q)
void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, {
struct iwl_tx_queue *txq); return trans->ops->check_stuck_queue(trans, q);
}
static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
struct dentry *dir)
{
return trans->ops->dbgfs_register(trans, dir);
}
static inline int iwl_trans_suspend(struct iwl_trans *trans)
{
return trans->ops->suspend(trans);
}
static inline int iwl_trans_resume(struct iwl_trans *trans)
{
return trans->ops->resume(trans);
}
/*****************************************************
* Transport layers implementations
******************************************************/
extern const struct iwl_trans_ops trans_ops_pcie;
#endif /* __iwl_trans_h__ */ #endif /* __iwl_trans_h__ */

View file

@ -41,7 +41,6 @@
#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */ #endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
MODULE_FIRMWARE("3826.arm"); MODULE_FIRMWARE("3826.arm");
MODULE_ALIAS("stlc45xx");
/* /*
* gpios should be handled in board files and provided via platform data, * gpios should be handled in board files and provided via platform data,
@ -738,3 +737,4 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>"); MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
MODULE_ALIAS("spi:cx3110x"); MODULE_ALIAS("spi:cx3110x");
MODULE_ALIAS("spi:p54spi"); MODULE_ALIAS("spi:p54spi");
MODULE_ALIAS("spi:stlc45xx");

View file

@ -19,6 +19,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <asm/div64.h>
#include <net/mac80211.h> #include <net/mac80211.h>
@ -582,10 +583,13 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb)
if (chan) { if (chan) {
struct survey_info *survey = &priv->survey[chan->hw_value]; struct survey_info *survey = &priv->survey[chan->hw_value];
survey->noise = clamp_t(s8, priv->noise, -128, 127); survey->noise = clamp_t(s8, priv->noise, -128, 127);
survey->channel_time = priv->survey_raw.active / 1024; survey->channel_time = priv->survey_raw.active;
survey->channel_time_tx = priv->survey_raw.tx / 1024; survey->channel_time_tx = priv->survey_raw.tx;
survey->channel_time_busy = priv->survey_raw.cca / 1024 + survey->channel_time_busy = priv->survey_raw.tx +
survey->channel_time_tx; priv->survey_raw.cca;
do_div(survey->channel_time, 1024);
do_div(survey->channel_time_tx, 1024);
do_div(survey->channel_time_busy, 1024);
} }
tmp = p54_find_and_unlink_skb(priv, hdr->req_id); tmp = p54_find_and_unlink_skb(priv, hdr->req_id);

View file

@ -46,6 +46,7 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl)
goto out; goto out;
} }
wake_up->role_id = wl->role_id;
wake_up->wake_up_event = wl->conf.conn.wake_up_event; wake_up->wake_up_event = wl->conf.conn.wake_up_event;
wake_up->listen_interval = wl->conf.conn.listen_interval; wake_up->listen_interval = wl->conf.conn.listen_interval;
@ -101,6 +102,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
goto out; goto out;
} }
acx->role_id = wl->role_id;
acx->current_tx_power = power * 10; acx->current_tx_power = power * 10;
ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
@ -128,6 +130,7 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl)
} }
/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
feature->role_id = wl->role_id;
feature->data_flow_options = 0; feature->data_flow_options = 0;
feature->options = 0; feature->options = 0;
@ -183,34 +186,6 @@ out:
return ret; return ret;
} }
int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter)
{
struct acx_rx_config *rx_config;
int ret;
wl1271_debug(DEBUG_ACX, "acx rx config");
rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
if (!rx_config) {
ret = -ENOMEM;
goto out;
}
rx_config->config_options = cpu_to_le32(config);
rx_config->filter_options = cpu_to_le32(filter);
ret = wl1271_cmd_configure(wl, ACX_RX_CFG,
rx_config, sizeof(*rx_config));
if (ret < 0) {
wl1271_warning("failed to set rx config: %d", ret);
goto out;
}
out:
kfree(rx_config);
return ret;
}
int wl1271_acx_pd_threshold(struct wl1271 *wl) int wl1271_acx_pd_threshold(struct wl1271 *wl)
{ {
struct acx_packet_detection *pd; struct acx_packet_detection *pd;
@ -250,6 +225,7 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
goto out; goto out;
} }
slot->role_id = wl->role_id;
slot->wone_index = STATION_WONE_INDEX; slot->wone_index = STATION_WONE_INDEX;
slot->slot_time = slot_time; slot->slot_time = slot_time;
@ -279,6 +255,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
} }
/* MAC filtering */ /* MAC filtering */
acx->role_id = wl->role_id;
acx->enabled = enable; acx->enabled = enable;
acx->num_groups = mc_list_len; acx->num_groups = mc_list_len;
memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN); memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
@ -308,6 +285,7 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl)
wl1271_debug(DEBUG_ACX, "acx service period timeout"); wl1271_debug(DEBUG_ACX, "acx service period timeout");
rx_timeout->role_id = wl->role_id;
rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout); rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout);
rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout); rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout);
@ -344,6 +322,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold)
goto out; goto out;
} }
rts->role_id = wl->role_id;
rts->threshold = cpu_to_le16((u16)rts_threshold); rts->threshold = cpu_to_le16((u16)rts_threshold);
ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
@ -403,6 +382,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
goto out; goto out;
} }
beacon_filter->role_id = wl->role_id;
beacon_filter->enable = enable_filter; beacon_filter->enable = enable_filter;
/* /*
@ -439,6 +419,7 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
} }
/* configure default beacon pass-through rules */ /* configure default beacon pass-through rules */
ie_table->role_id = wl->role_id;
ie_table->num_ie = 0; ie_table->num_ie = 0;
for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) { for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) {
struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]); struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]);
@ -500,6 +481,7 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable)
timeout = wl->conf.conn.bss_lose_timeout; timeout = wl->conf.conn.bss_lose_timeout;
} }
acx->role_id = wl->role_id;
acx->synch_fail_thold = cpu_to_le32(threshold); acx->synch_fail_thold = cpu_to_le32(threshold);
acx->bss_lose_timeout = cpu_to_le32(timeout); acx->bss_lose_timeout = cpu_to_le32(timeout);
@ -546,13 +528,13 @@ out:
return ret; return ret;
} }
int wl1271_acx_sta_sg_cfg(struct wl1271 *wl) int wl12xx_acx_sg_cfg(struct wl1271 *wl)
{ {
struct acx_sta_bt_wlan_coex_param *param; struct acx_bt_wlan_coex_param *param;
struct conf_sg_settings *c = &wl->conf.sg; struct conf_sg_settings *c = &wl->conf.sg;
int i, ret; int i, ret;
wl1271_debug(DEBUG_ACX, "acx sg sta cfg"); wl1271_debug(DEBUG_ACX, "acx sg cfg");
param = kzalloc(sizeof(*param), GFP_KERNEL); param = kzalloc(sizeof(*param), GFP_KERNEL);
if (!param) { if (!param) {
@ -561,38 +543,8 @@ int wl1271_acx_sta_sg_cfg(struct wl1271 *wl)
} }
/* BT-WLAN coext parameters */ /* BT-WLAN coext parameters */
for (i = 0; i < CONF_SG_STA_PARAMS_MAX; i++) for (i = 0; i < CONF_SG_PARAMS_MAX; i++)
param->params[i] = cpu_to_le32(c->sta_params[i]); param->params[i] = cpu_to_le32(c->params[i]);
param->param_idx = CONF_SG_PARAMS_ALL;
ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
if (ret < 0) {
wl1271_warning("failed to set sg config: %d", ret);
goto out;
}
out:
kfree(param);
return ret;
}
int wl1271_acx_ap_sg_cfg(struct wl1271 *wl)
{
struct acx_ap_bt_wlan_coex_param *param;
struct conf_sg_settings *c = &wl->conf.sg;
int i, ret;
wl1271_debug(DEBUG_ACX, "acx sg ap cfg");
param = kzalloc(sizeof(*param), GFP_KERNEL);
if (!param) {
ret = -ENOMEM;
goto out;
}
/* BT-WLAN coext parameters */
for (i = 0; i < CONF_SG_AP_PARAMS_MAX; i++)
param->params[i] = cpu_to_le32(c->ap_params[i]);
param->param_idx = CONF_SG_PARAMS_ALL; param->param_idx = CONF_SG_PARAMS_ALL;
ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
@ -647,6 +599,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
goto out; goto out;
} }
bb->role_id = wl->role_id;
bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout); bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout);
bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout); bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout);
bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps; bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps;
@ -676,6 +629,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid)
goto out; goto out;
} }
acx_aid->role_id = wl->role_id;
acx_aid->aid = cpu_to_le16(aid); acx_aid->aid = cpu_to_le16(aid);
ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
@ -731,6 +685,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
goto out; goto out;
} }
acx->role_id = wl->role_id;
acx->preamble = preamble; acx->preamble = preamble;
ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
@ -758,6 +713,7 @@ int wl1271_acx_cts_protect(struct wl1271 *wl,
goto out; goto out;
} }
acx->role_id = wl->role_id;
acx->ctsprotect = ctsprotect; acx->ctsprotect = ctsprotect;
ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
@ -789,9 +745,8 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
int wl1271_acx_sta_rate_policies(struct wl1271 *wl) int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
{ {
struct acx_sta_rate_policy *acx; struct acx_rate_policy *acx;
struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf; struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf;
int idx = 0;
int ret = 0; int ret = 0;
wl1271_debug(DEBUG_ACX, "acx rate policies"); wl1271_debug(DEBUG_ACX, "acx rate policies");
@ -803,25 +758,30 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
goto out; goto out;
} }
wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
wl->basic_rate, wl->rate_set);
/* configure one basic rate class */ /* configure one basic rate class */
idx = ACX_TX_BASIC_RATE; acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE);
acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate); acx->rate_policy.enabled_rates = cpu_to_le32(wl->basic_rate);
acx->rate_class[idx].short_retry_limit = c->short_retry_limit; acx->rate_policy.short_retry_limit = c->short_retry_limit;
acx->rate_class[idx].long_retry_limit = c->long_retry_limit; acx->rate_policy.long_retry_limit = c->long_retry_limit;
acx->rate_class[idx].aflags = c->aflags; acx->rate_policy.aflags = c->aflags;
ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
if (ret < 0) {
wl1271_warning("Setting of rate policies failed: %d", ret);
goto out;
}
/* configure one AP supported rate class */ /* configure one AP supported rate class */
idx = ACX_TX_AP_FULL_RATE; acx->rate_policy_idx = cpu_to_le32(ACX_TX_AP_FULL_RATE);
acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set); acx->rate_policy.enabled_rates = cpu_to_le32(wl->rate_set);
acx->rate_class[idx].short_retry_limit = c->short_retry_limit; acx->rate_policy.short_retry_limit = c->short_retry_limit;
acx->rate_class[idx].long_retry_limit = c->long_retry_limit; acx->rate_policy.long_retry_limit = c->long_retry_limit;
acx->rate_class[idx].aflags = c->aflags; acx->rate_policy.aflags = c->aflags;
acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
acx->rate_class[ACX_TX_BASIC_RATE].enabled_rates,
acx->rate_class[ACX_TX_AP_FULL_RATE].enabled_rates);
ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
if (ret < 0) { if (ret < 0) {
@ -837,7 +797,7 @@ out:
int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
u8 idx) u8 idx)
{ {
struct acx_ap_rate_policy *acx; struct acx_rate_policy *acx;
int ret = 0; int ret = 0;
wl1271_debug(DEBUG_ACX, "acx ap rate policy %d rates 0x%x", wl1271_debug(DEBUG_ACX, "acx ap rate policy %d rates 0x%x",
@ -883,6 +843,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
goto out; goto out;
} }
acx->role_id = wl->role_id;
acx->ac = ac; acx->ac = ac;
acx->cw_min = cw_min; acx->cw_min = cw_min;
acx->cw_max = cpu_to_le16(cw_max); acx->cw_max = cpu_to_le16(cw_max);
@ -916,6 +877,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
goto out; goto out;
} }
acx->role_id = wl->role_id;
acx->queue_id = queue_id; acx->queue_id = queue_id;
acx->channel_type = channel_type; acx->channel_type = channel_type;
acx->tsid = tsid; acx->tsid = tsid;
@ -995,52 +957,9 @@ out:
return ret; return ret;
} }
int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) int wl12xx_acx_mem_cfg(struct wl1271 *wl)
{ {
struct wl1271_acx_ap_config_memory *mem_conf; struct wl12xx_acx_config_memory *mem_conf;
struct conf_memory_settings *mem;
int ret;
wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
if (!mem_conf) {
ret = -ENOMEM;
goto out;
}
if (wl->chip.id == CHIP_ID_1283_PG20)
/*
* FIXME: The 128x AP FW does not yet support dynamic memory.
* Use the base memory configuration for 128x for now. This
* should be fine tuned in the future.
*/
mem = &wl->conf.mem_wl128x;
else
mem = &wl->conf.mem_wl127x;
/* memory config */
mem_conf->num_stations = mem->num_stations;
mem_conf->rx_mem_block_num = mem->rx_block_num;
mem_conf->tx_min_mem_block_num = mem->tx_min_block_num;
mem_conf->num_ssid_profiles = mem->ssid_profiles;
mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
sizeof(*mem_conf));
if (ret < 0) {
wl1271_warning("wl1271 mem config failed: %d", ret);
goto out;
}
out:
kfree(mem_conf);
return ret;
}
int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
{
struct wl1271_acx_sta_config_memory *mem_conf;
struct conf_memory_settings *mem; struct conf_memory_settings *mem;
int ret; int ret;
@ -1183,6 +1102,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
goto out; goto out;
} }
acx->role_id = wl->role_id;
acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE; acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE;
acx->max_consecutive = wl->conf.conn.bet_max_consecutive; acx->max_consecutive = wl->conf.conn.bet_max_consecutive;
@ -1210,6 +1130,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address)
goto out; goto out;
} }
acx->role_id = wl->role_id;
acx->version = ACX_IPV4_VERSION; acx->version = ACX_IPV4_VERSION;
acx->enable = enable; acx->enable = enable;
@ -1269,6 +1190,7 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable)
goto out; goto out;
} }
acx->role_id = wl->role_id;
acx->enabled = enable; acx->enabled = enable;
ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx));
@ -1295,6 +1217,7 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid)
goto out; goto out;
} }
acx->role_id = wl->role_id;
acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval);
acx->index = index; acx->index = index;
acx->tpl_validation = tpl_valid; acx->tpl_validation = tpl_valid;
@ -1328,6 +1251,7 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
wl->last_rssi_event = -1; wl->last_rssi_event = -1;
acx->role_id = wl->role_id;
acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing); acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing);
acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON; acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON;
acx->type = WL1271_ACX_TRIG_TYPE_EDGE; acx->type = WL1271_ACX_TRIG_TYPE_EDGE;
@ -1366,6 +1290,7 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl)
goto out; goto out;
} }
acx->role_id = wl->role_id;
acx->rssi_beacon = c->avg_weight_rssi_beacon; acx->rssi_beacon = c->avg_weight_rssi_beacon;
acx->rssi_data = c->avg_weight_rssi_data; acx->rssi_data = c->avg_weight_rssi_data;
acx->snr_beacon = c->avg_weight_snr_beacon; acx->snr_beacon = c->avg_weight_snr_beacon;
@ -1384,14 +1309,15 @@ out:
int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
struct ieee80211_sta_ht_cap *ht_cap, struct ieee80211_sta_ht_cap *ht_cap,
bool allow_ht_operation) bool allow_ht_operation, u8 hlid)
{ {
struct wl1271_acx_ht_capabilities *acx; struct wl1271_acx_ht_capabilities *acx;
u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
int ret = 0; int ret = 0;
u32 ht_capabilites = 0; u32 ht_capabilites = 0;
wl1271_debug(DEBUG_ACX, "acx ht capabilities setting"); wl1271_debug(DEBUG_ACX, "acx ht capabilities setting "
"sta supp: %d sta cap: %d", ht_cap->ht_supported,
ht_cap->cap);
acx = kzalloc(sizeof(*acx), GFP_KERNEL); acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx) { if (!acx) {
@ -1399,26 +1325,22 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
goto out; goto out;
} }
/* Allow HT Operation ? */ if (allow_ht_operation && ht_cap->ht_supported) {
if (allow_ht_operation) { /* no need to translate capabilities - use the spec values */
ht_capabilites = ht_capabilites = ht_cap->cap;
WL1271_ACX_FW_CAP_HT_OPERATION;
if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD) /*
ht_capabilites |= * this bit is not employed by the spec but only by FW to
WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT; * indicate peer HT support
if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) */
ht_capabilites |= ht_capabilites |= WL12XX_HT_CAP_HT_OPERATION;
WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS;
if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT)
ht_capabilites |=
WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION;
/* get data from A-MPDU parameters field */ /* get data from A-MPDU parameters field */
acx->ampdu_max_length = ht_cap->ampdu_factor; acx->ampdu_max_length = ht_cap->ampdu_factor;
acx->ampdu_min_spacing = ht_cap->ampdu_density; acx->ampdu_min_spacing = ht_cap->ampdu_density;
} }
memcpy(acx->mac_address, mac_address, ETH_ALEN); acx->hlid = hlid;
acx->ht_capabilites = cpu_to_le32(ht_capabilites); acx->ht_capabilites = cpu_to_le32(ht_capabilites);
ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx));
@ -1446,6 +1368,7 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
goto out; goto out;
} }
acx->role_id = wl->role_id;
acx->ht_protection = acx->ht_protection =
(u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION); (u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION);
acx->rifs_mode = 0; acx->rifs_mode = 0;
@ -1467,14 +1390,12 @@ out:
} }
/* Configure BA session initiator/receiver parameters setting in the FW. */ /* Configure BA session initiator/receiver parameters setting in the FW. */
int wl1271_acx_set_ba_session(struct wl1271 *wl, int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl)
enum ieee80211_back_parties direction,
u8 tid_index, u8 policy)
{ {
struct wl1271_acx_ba_session_policy *acx; struct wl1271_acx_ba_initiator_policy *acx;
int ret; int ret;
wl1271_debug(DEBUG_ACX, "acx ba session setting"); wl1271_debug(DEBUG_ACX, "acx ba initiator policy");
acx = kzalloc(sizeof(*acx), GFP_KERNEL); acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx) { if (!acx) {
@ -1482,33 +1403,18 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
goto out; goto out;
} }
/* ANY role */ /* set for the current role */
acx->role_id = 0xff; acx->role_id = wl->role_id;
acx->tid = tid_index; acx->tid_bitmap = wl->conf.ht.tx_ba_tid_bitmap;
acx->enable = policy;
acx->ba_direction = direction;
switch (direction) {
case WLAN_BACK_INITIATOR:
acx->win_size = wl->conf.ht.tx_ba_win_size; acx->win_size = wl->conf.ht.tx_ba_win_size;
acx->inactivity_timeout = wl->conf.ht.inactivity_timeout; acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
break;
case WLAN_BACK_RECIPIENT:
acx->win_size = RX_BA_WIN_SIZE;
acx->inactivity_timeout = 0;
break;
default:
wl1271_error("Incorrect acx command id=%x\n", direction);
ret = -EINVAL;
goto out;
}
ret = wl1271_cmd_configure(wl, ret = wl1271_cmd_configure(wl,
ACX_BA_SESSION_POLICY_CFG, ACX_BA_SESSION_INIT_POLICY,
acx, acx,
sizeof(*acx)); sizeof(*acx));
if (ret < 0) { if (ret < 0) {
wl1271_warning("acx ba session setting failed: %d", ret); wl1271_warning("acx ba initiator policy failed: %d", ret);
goto out; goto out;
} }
@ -1518,8 +1424,8 @@ out:
} }
/* setup BA session receiver setting in the FW. */ /* setup BA session receiver setting in the FW. */
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
bool enable) u16 ssn, bool enable, u8 peer_hlid)
{ {
struct wl1271_acx_ba_receiver_setup *acx; struct wl1271_acx_ba_receiver_setup *acx;
int ret; int ret;
@ -1532,11 +1438,10 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
goto out; goto out;
} }
/* Single link for now */ acx->hlid = peer_hlid;
acx->link_id = 1;
acx->tid = tid_index; acx->tid = tid_index;
acx->enable = enable; acx->enable = enable;
acx->win_size = 0; acx->win_size = wl->conf.ht.rx_ba_win_size;
acx->ssn = ssn; acx->ssn = ssn;
ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx, ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx,
@ -1606,6 +1511,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
if (!(conf_queues & BIT(i))) if (!(conf_queues & BIT(i)))
continue; continue;
rx_streaming->role_id = wl->role_id;
rx_streaming->tid = i; rx_streaming->tid = i;
rx_streaming->enable = enable_queues & BIT(i); rx_streaming->enable = enable_queues & BIT(i);
rx_streaming->period = wl->conf.rx_streaming.interval; rx_streaming->period = wl->conf.rx_streaming.interval;
@ -1635,6 +1541,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
if (!acx) if (!acx)
return -ENOMEM; return -ENOMEM;
acx->role_id = wl->role_id;
acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries);
ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));
@ -1703,31 +1610,6 @@ out:
return ret; return ret;
} }
int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable)
{
struct acx_ap_beacon_filter *acx = NULL;
int ret;
wl1271_debug(DEBUG_ACX, "acx set ap beacon filter: %d", enable);
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx)
return -ENOMEM;
acx->enable = enable ? 1 : 0;
ret = wl1271_cmd_configure(wl, ACX_AP_BEACON_FILTER_OPT,
acx, sizeof(*acx));
if (ret < 0) {
wl1271_warning("acx set ap beacon filter failed: %d", ret);
goto out;
}
out:
kfree(acx);
return ret;
}
int wl1271_acx_fm_coex(struct wl1271 *wl) int wl1271_acx_fm_coex(struct wl1271 *wl)
{ {
struct wl1271_acx_fm_coex *acx; struct wl1271_acx_fm_coex *acx;
@ -1767,3 +1649,45 @@ out:
kfree(acx); kfree(acx);
return ret; return ret;
} }
int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl)
{
struct wl12xx_acx_set_rate_mgmt_params *acx = NULL;
struct conf_rate_policy_settings *conf = &wl->conf.rate;
int ret;
wl1271_debug(DEBUG_ACX, "acx set rate mgmt params");
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx)
return -ENOMEM;
acx->index = ACX_RATE_MGMT_ALL_PARAMS;
acx->rate_retry_score = cpu_to_le16(conf->rate_retry_score);
acx->per_add = cpu_to_le16(conf->per_add);
acx->per_th1 = cpu_to_le16(conf->per_th1);
acx->per_th2 = cpu_to_le16(conf->per_th2);
acx->max_per = cpu_to_le16(conf->max_per);
acx->inverse_curiosity_factor = conf->inverse_curiosity_factor;
acx->tx_fail_low_th = conf->tx_fail_low_th;
acx->tx_fail_high_th = conf->tx_fail_high_th;
acx->per_alpha_shift = conf->per_alpha_shift;
acx->per_add_shift = conf->per_add_shift;
acx->per_beta1_shift = conf->per_beta1_shift;
acx->per_beta2_shift = conf->per_beta2_shift;
acx->rate_check_up = conf->rate_check_up;
acx->rate_check_down = conf->rate_check_down;
memcpy(acx->rate_retry_policy, conf->rate_retry_policy,
sizeof(acx->rate_retry_policy));
ret = wl1271_cmd_configure(wl, ACX_SET_RATE_MGMT_PARAMS,
acx, sizeof(*acx));
if (ret < 0) {
wl1271_warning("acx set rate mgmt params failed: %d", ret);
goto out;
}
out:
kfree(acx);
return ret;
}

View file

@ -101,6 +101,17 @@ struct acx_error_counter {
__le32 seq_num_miss; __le32 seq_num_miss;
} __packed; } __packed;
enum wl12xx_role {
WL1271_ROLE_STA = 0,
WL1271_ROLE_IBSS,
WL1271_ROLE_AP,
WL1271_ROLE_DEVICE,
WL1271_ROLE_P2P_CL,
WL1271_ROLE_P2P_GO,
WL12XX_INVALID_ROLE_TYPE = 0xff
};
enum wl1271_psm_mode { enum wl1271_psm_mode {
/* Active mode */ /* Active mode */
WL1271_PSM_CAM = 0, WL1271_PSM_CAM = 0,
@ -160,94 +171,6 @@ struct acx_rx_msdu_lifetime {
__le32 lifetime; __le32 lifetime;
} __packed; } __packed;
/*
* RX Config Options Table
* Bit Definition
* === ==========
* 31:14 Reserved
* 13 Copy RX Status - when set, write three receive status words
* to top of rx'd MPDUs.
* When cleared, do not write three status words (added rev 1.5)
* 12 Reserved
* 11 RX Complete upon FCS error - when set, give rx complete
* interrupt for FCS errors, after the rx filtering, e.g. unicast
* frames not to us with FCS error will not generate an interrupt.
* 10 SSID Filter Enable - When set, the WiLink discards all beacon,
* probe request, and probe response frames with an SSID that does
* not match the SSID specified by the host in the START/JOIN
* command.
* When clear, the WiLink receives frames with any SSID.
* 9 Broadcast Filter Enable - When set, the WiLink discards all
* broadcast frames. When clear, the WiLink receives all received
* broadcast frames.
* 8:6 Reserved
* 5 BSSID Filter Enable - When set, the WiLink discards any frames
* with a BSSID that does not match the BSSID specified by the
* host.
* When clear, the WiLink receives frames from any BSSID.
* 4 MAC Addr Filter - When set, the WiLink discards any frames
* with a destination address that does not match the MAC address
* of the adaptor.
* When clear, the WiLink receives frames destined to any MAC
* address.
* 3 Promiscuous - When set, the WiLink receives all valid frames
* (i.e., all frames that pass the FCS check).
* When clear, only frames that pass the other filters specified
* are received.
* 2 FCS - When set, the WiLink includes the FCS with the received
* frame.
* When cleared, the FCS is discarded.
* 1 PLCP header - When set, write all data from baseband to frame
* buffer including PHY header.
* 0 Reserved - Always equal to 0.
*
* RX Filter Options Table
* Bit Definition
* === ==========
* 31:12 Reserved - Always equal to 0.
* 11 Association - When set, the WiLink receives all association
* related frames (association request/response, reassocation
* request/response, and disassociation). When clear, these frames
* are discarded.
* 10 Auth/De auth - When set, the WiLink receives all authentication
* and de-authentication frames. When clear, these frames are
* discarded.
* 9 Beacon - When set, the WiLink receives all beacon frames.
* When clear, these frames are discarded.
* 8 Contention Free - When set, the WiLink receives all contention
* free frames.
* When clear, these frames are discarded.
* 7 Control - When set, the WiLink receives all control frames.
* When clear, these frames are discarded.
* 6 Data - When set, the WiLink receives all data frames.
* When clear, these frames are discarded.
* 5 FCS Error - When set, the WiLink receives frames that have FCS
* errors.
* When clear, these frames are discarded.
* 4 Management - When set, the WiLink receives all management
* frames.
* When clear, these frames are discarded.
* 3 Probe Request - When set, the WiLink receives all probe request
* frames.
* When clear, these frames are discarded.
* 2 Probe Response - When set, the WiLink receives all probe
* response frames.
* When clear, these frames are discarded.
* 1 RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK
* frames.
* When clear, these frames are discarded.
* 0 Rsvd Type/Sub Type - When set, the WiLink receives all frames
* that have reserved frame types and sub types as defined by the
* 802.11 specification.
* When clear, these frames are discarded.
*/
struct acx_rx_config {
struct acx_header header;
__le32 config_options;
__le32 filter_options;
} __packed;
struct acx_packet_detection { struct acx_packet_detection {
struct acx_header header; struct acx_header header;
@ -267,9 +190,10 @@ enum acx_slot_type {
struct acx_slot { struct acx_slot {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 wone_index; /* Reserved */ u8 wone_index; /* Reserved */
u8 slot_time; u8 slot_time;
u8 reserved[6]; u8 reserved[5];
} __packed; } __packed;
@ -279,29 +203,35 @@ struct acx_slot {
struct acx_dot11_grp_addr_tbl { struct acx_dot11_grp_addr_tbl {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 enabled; u8 enabled;
u8 num_groups; u8 num_groups;
u8 pad[2]; u8 pad[1];
u8 mac_table[ADDRESS_GROUP_MAX_LEN]; u8 mac_table[ADDRESS_GROUP_MAX_LEN];
} __packed; } __packed;
struct acx_rx_timeout { struct acx_rx_timeout {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 reserved;
__le16 ps_poll_timeout; __le16 ps_poll_timeout;
__le16 upsd_timeout; __le16 upsd_timeout;
u8 padding[2];
} __packed; } __packed;
struct acx_rts_threshold { struct acx_rts_threshold {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 reserved;
__le16 threshold; __le16 threshold;
u8 pad[2];
} __packed; } __packed;
struct acx_beacon_filter_option { struct acx_beacon_filter_option {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 enable; u8 enable;
/* /*
* The number of beacons without the unicast TIM * The number of beacons without the unicast TIM
@ -311,7 +241,7 @@ struct acx_beacon_filter_option {
* without the unicast TIM bit set are dropped. * without the unicast TIM bit set are dropped.
*/ */
u8 max_num_beacons; u8 max_num_beacons;
u8 pad[2]; u8 pad[1];
} __packed; } __packed;
/* /*
@ -350,14 +280,17 @@ struct acx_beacon_filter_option {
struct acx_beacon_filter_ie_table { struct acx_beacon_filter_ie_table {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 num_ie; u8 num_ie;
u8 pad[3]; u8 pad[2];
u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
} __packed; } __packed;
struct acx_conn_monit_params { struct acx_conn_monit_params {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 padding[3];
__le32 synch_fail_thold; /* number of beacons missed */ __le32 synch_fail_thold; /* number of beacons missed */
__le32 bss_lose_timeout; /* number of TU's from synch fail */ __le32 bss_lose_timeout; /* number of TU's from synch fail */
} __packed; } __packed;
@ -369,23 +302,14 @@ struct acx_bt_wlan_coex {
u8 pad[3]; u8 pad[3];
} __packed; } __packed;
struct acx_sta_bt_wlan_coex_param { struct acx_bt_wlan_coex_param {
struct acx_header header; struct acx_header header;
__le32 params[CONF_SG_STA_PARAMS_MAX]; __le32 params[CONF_SG_PARAMS_MAX];
u8 param_idx; u8 param_idx;
u8 padding[3]; u8 padding[3];
} __packed; } __packed;
struct acx_ap_bt_wlan_coex_param {
struct acx_header header;
__le32 params[CONF_SG_AP_PARAMS_MAX];
u8 param_idx;
u8 padding[3];
} __packed;
struct acx_dco_itrim_params { struct acx_dco_itrim_params {
struct acx_header header; struct acx_header header;
@ -406,15 +330,16 @@ struct acx_energy_detection {
struct acx_beacon_broadcast { struct acx_beacon_broadcast {
struct acx_header header; struct acx_header header;
__le16 beacon_rx_timeout; u8 role_id;
__le16 broadcast_timeout;
/* Enables receiving of broadcast packets in PS mode */ /* Enables receiving of broadcast packets in PS mode */
u8 rx_broadcast_in_ps; u8 rx_broadcast_in_ps;
__le16 beacon_rx_timeout;
__le16 broadcast_timeout;
/* Consecutive PS Poll failures before updating the host */ /* Consecutive PS Poll failures before updating the host */
u8 ps_poll_threshold; u8 ps_poll_threshold;
u8 pad[2]; u8 pad[1];
} __packed; } __packed;
struct acx_event_mask { struct acx_event_mask {
@ -424,35 +349,6 @@ struct acx_event_mask {
__le32 high_event_mask; /* Unused */ __le32 high_event_mask; /* Unused */
} __packed; } __packed;
#define CFG_RX_FCS BIT(2)
#define CFG_RX_ALL_GOOD BIT(3)
#define CFG_UNI_FILTER_EN BIT(4)
#define CFG_BSSID_FILTER_EN BIT(5)
#define CFG_MC_FILTER_EN BIT(6)
#define CFG_MC_ADDR0_EN BIT(7)
#define CFG_MC_ADDR1_EN BIT(8)
#define CFG_BC_REJECT_EN BIT(9)
#define CFG_SSID_FILTER_EN BIT(10)
#define CFG_RX_INT_FCS_ERROR BIT(11)
#define CFG_RX_INT_ENCRYPTED BIT(12)
#define CFG_RX_WR_RX_STATUS BIT(13)
#define CFG_RX_FILTER_NULTI BIT(14)
#define CFG_RX_RESERVE BIT(15)
#define CFG_RX_TIMESTAMP_TSF BIT(16)
#define CFG_RX_RSV_EN BIT(0)
#define CFG_RX_RCTS_ACK BIT(1)
#define CFG_RX_PRSP_EN BIT(2)
#define CFG_RX_PREQ_EN BIT(3)
#define CFG_RX_MGMT_EN BIT(4)
#define CFG_RX_FCS_ERROR BIT(5)
#define CFG_RX_DATA_EN BIT(6)
#define CFG_RX_CTL_EN BIT(7)
#define CFG_RX_CF_EN BIT(8)
#define CFG_RX_BCN_EN BIT(9)
#define CFG_RX_AUTH_EN BIT(10)
#define CFG_RX_ASSOC_EN BIT(11)
#define SCAN_PASSIVE BIT(0) #define SCAN_PASSIVE BIT(0)
#define SCAN_5GHZ_BAND BIT(1) #define SCAN_5GHZ_BAND BIT(1)
#define SCAN_TRIGGERED BIT(2) #define SCAN_TRIGGERED BIT(2)
@ -465,6 +361,8 @@ struct acx_event_mask {
struct acx_feature_config { struct acx_feature_config {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 padding[3];
__le32 options; __le32 options;
__le32 data_flow_options; __le32 data_flow_options;
} __packed; } __packed;
@ -472,16 +370,18 @@ struct acx_feature_config {
struct acx_current_tx_power { struct acx_current_tx_power {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 current_tx_power; u8 current_tx_power;
u8 padding[3]; u8 padding[2];
} __packed; } __packed;
struct acx_wake_up_condition { struct acx_wake_up_condition {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 wake_up_event; /* Only one bit can be set */ u8 wake_up_event; /* Only one bit can be set */
u8 listen_interval; u8 listen_interval;
u8 pad[2]; u8 pad[1];
} __packed; } __packed;
struct acx_aid { struct acx_aid {
@ -490,8 +390,9 @@ struct acx_aid {
/* /*
* To be set when associated with an AP. * To be set when associated with an AP.
*/ */
u8 role_id;
u8 reserved;
__le16 aid; __le16 aid;
u8 pad[2];
} __packed; } __packed;
enum acx_preamble_type { enum acx_preamble_type {
@ -506,8 +407,9 @@ struct acx_preamble {
* When set, the WiLink transmits the frames with a short preamble and * When set, the WiLink transmits the frames with a short preamble and
* when cleared, the WiLink transmits the frames with a long preamble. * when cleared, the WiLink transmits the frames with a long preamble.
*/ */
u8 role_id;
u8 preamble; u8 preamble;
u8 padding[3]; u8 padding[2];
} __packed; } __packed;
enum acx_ctsprotect_type { enum acx_ctsprotect_type {
@ -517,8 +419,9 @@ enum acx_ctsprotect_type {
struct acx_ctsprotect { struct acx_ctsprotect {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 ctsprotect; u8 ctsprotect;
u8 padding[3]; u8 padding[2];
} __packed; } __packed;
struct acx_tx_statistics { struct acx_tx_statistics {
@ -753,18 +656,9 @@ struct acx_rate_class {
#define ACX_TX_BASIC_RATE 0 #define ACX_TX_BASIC_RATE 0
#define ACX_TX_AP_FULL_RATE 1 #define ACX_TX_AP_FULL_RATE 1
#define ACX_TX_RATE_POLICY_CNT 2
struct acx_sta_rate_policy {
struct acx_header header;
__le32 rate_class_cnt;
struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES];
} __packed;
#define ACX_TX_AP_MODE_MGMT_RATE 4 #define ACX_TX_AP_MODE_MGMT_RATE 4
#define ACX_TX_AP_MODE_BCST_RATE 5 #define ACX_TX_AP_MODE_BCST_RATE 5
struct acx_ap_rate_policy { struct acx_rate_policy {
struct acx_header header; struct acx_header header;
__le32 rate_policy_idx; __le32 rate_policy_idx;
@ -773,22 +667,23 @@ struct acx_ap_rate_policy {
struct acx_ac_cfg { struct acx_ac_cfg {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 ac; u8 ac;
u8 aifsn;
u8 cw_min; u8 cw_min;
__le16 cw_max; __le16 cw_max;
u8 aifsn;
u8 reserved;
__le16 tx_op_limit; __le16 tx_op_limit;
} __packed; } __packed;
struct acx_tid_config { struct acx_tid_config {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 queue_id; u8 queue_id;
u8 channel_type; u8 channel_type;
u8 tsid; u8 tsid;
u8 ps_scheme; u8 ps_scheme;
u8 ack_policy; u8 ack_policy;
u8 padding[3]; u8 padding[2];
__le32 apsd_conf[2]; __le32 apsd_conf[2];
} __packed; } __packed;
@ -804,19 +699,7 @@ struct acx_tx_config_options {
__le16 tx_compl_threshold; /* number of packets */ __le16 tx_compl_threshold; /* number of packets */
} __packed; } __packed;
#define ACX_TX_DESCRIPTORS 32 struct wl12xx_acx_config_memory {
struct wl1271_acx_ap_config_memory {
struct acx_header header;
u8 rx_mem_block_num;
u8 tx_min_mem_block_num;
u8 num_stations;
u8 num_ssid_profiles;
__le32 total_tx_descriptors;
} __packed;
struct wl1271_acx_sta_config_memory {
struct acx_header header; struct acx_header header;
u8 rx_mem_block_num; u8 rx_mem_block_num;
@ -890,9 +773,10 @@ struct wl1271_acx_rx_config_opt {
struct wl1271_acx_bet_enable { struct wl1271_acx_bet_enable {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 enable; u8 enable;
u8 max_consecutive; u8 max_consecutive;
u8 padding[2]; u8 padding[1];
} __packed; } __packed;
#define ACX_IPV4_VERSION 4 #define ACX_IPV4_VERSION 4
@ -905,9 +789,10 @@ struct wl1271_acx_bet_enable {
struct wl1271_acx_arp_filter { struct wl1271_acx_arp_filter {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */ u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */
u8 enable; /* bitmap of enabled ARP filtering features */ u8 enable; /* bitmap of enabled ARP filtering features */
u8 padding[2]; u8 padding[1];
u8 address[16]; /* The configured device IP address - all ARP u8 address[16]; /* The configured device IP address - all ARP
requests directed to this IP address will pass requests directed to this IP address will pass
through. For IPv4, the first four bytes are through. For IPv4, the first four bytes are
@ -925,8 +810,9 @@ struct wl1271_acx_pm_config {
struct wl1271_acx_keep_alive_mode { struct wl1271_acx_keep_alive_mode {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 enabled; u8 enabled;
u8 padding[3]; u8 padding[2];
} __packed; } __packed;
enum { enum {
@ -942,11 +828,11 @@ enum {
struct wl1271_acx_keep_alive_config { struct wl1271_acx_keep_alive_config {
struct acx_header header; struct acx_header header;
__le32 period; u8 role_id;
u8 index; u8 index;
u8 tpl_validation; u8 tpl_validation;
u8 trigger; u8 trigger;
u8 padding; __le32 period;
} __packed; } __packed;
#define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) #define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0)
@ -990,26 +876,33 @@ enum {
struct wl1271_acx_rssi_snr_trigger { struct wl1271_acx_rssi_snr_trigger {
struct acx_header header; struct acx_header header;
__le16 threshold; u8 role_id;
__le16 pacing; /* 0 - 60000 ms */
u8 metric; u8 metric;
u8 type; u8 type;
u8 dir; u8 dir;
__le16 threshold;
__le16 pacing; /* 0 - 60000 ms */
u8 hysteresis; u8 hysteresis;
u8 index; u8 index;
u8 enable; u8 enable;
u8 padding[2]; u8 padding[1];
}; };
struct wl1271_acx_rssi_snr_avg_weights { struct wl1271_acx_rssi_snr_avg_weights {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 padding[3];
u8 rssi_beacon; u8 rssi_beacon;
u8 rssi_data; u8 rssi_data;
u8 snr_beacon; u8 snr_beacon;
u8 snr_data; u8 snr_data;
}; };
/* special capability bit (not employed by the 802.11n spec) */
#define WL12XX_HT_CAP_HT_OPERATION BIT(16)
/* /*
* ACX_PEER_HT_CAP * ACX_PEER_HT_CAP
* Configure HT capabilities - declare the capabilities of the peer * Configure HT capabilities - declare the capabilities of the peer
@ -1018,28 +911,11 @@ struct wl1271_acx_rssi_snr_avg_weights {
struct wl1271_acx_ht_capabilities { struct wl1271_acx_ht_capabilities {
struct acx_header header; struct acx_header header;
/* /* bitmask of capability bits supported by the peer */
* bit 0 - Allow HT Operation
* bit 1 - Allow Greenfield format in TX
* bit 2 - Allow Short GI in TX
* bit 3 - Allow L-SIG TXOP Protection in TX
* bit 4 - Allow HT Control fields in TX.
* Note, driver will still leave space for HT control in packets
* regardless of the value of this field. FW will be responsible
* to drop the HT field from any frame when this Bit set to 0.
* bit 5 - Allow RD initiation in TXOP. FW is allowed to initate RD.
* Exact policy setting for this feature is TBD.
* Note, this bit can only be set to 1 if bit 3 is set to 1.
*/
__le32 ht_capabilites; __le32 ht_capabilites;
/* /* Indicates to which link these capabilities apply. */
* Indicates to which peer these capabilities apply. u8 hlid;
* For infrastructure use ff:ff:ff:ff:ff:ff that indicates relevance
* for all peers.
* Only valid for IBSS/DLS operation.
*/
u8 mac_address[ETH_ALEN];
/* /*
* This the maximum A-MPDU length supported by the AP. The FW may not * This the maximum A-MPDU length supported by the AP. The FW may not
@ -1049,17 +925,10 @@ struct wl1271_acx_ht_capabilities {
/* This is the minimal spacing required when sending A-MPDUs to the AP*/ /* This is the minimal spacing required when sending A-MPDUs to the AP*/
u8 ampdu_min_spacing; u8 ampdu_min_spacing;
u8 padding;
} __packed; } __packed;
/* HT Capabilites Fw Bit Mask Mapping */
#define WL1271_ACX_FW_CAP_HT_OPERATION BIT(0)
#define WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT BIT(1)
#define WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS BIT(2)
#define WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION BIT(3)
#define WL1271_ACX_FW_CAP_HT_CONTROL_FIELDS BIT(4)
#define WL1271_ACX_FW_CAP_RD_INITIATION BIT(5)
/* /*
* ACX_HT_BSS_OPERATION * ACX_HT_BSS_OPERATION
* Configure HT capabilities - AP rules for behavior in the BSS. * Configure HT capabilities - AP rules for behavior in the BSS.
@ -1067,6 +936,8 @@ struct wl1271_acx_ht_capabilities {
struct wl1271_acx_ht_information { struct wl1271_acx_ht_information {
struct acx_header header; struct acx_header header;
u8 role_id;
/* Values: 0 - RIFS not allowed, 1 - RIFS allowed */ /* Values: 0 - RIFS not allowed, 1 - RIFS allowed */
u8 rifs_mode; u8 rifs_mode;
@ -1088,60 +959,51 @@ struct wl1271_acx_ht_information {
*/ */
u8 dual_cts_protection; u8 dual_cts_protection;
u8 padding[3]; u8 padding[2];
} __packed; } __packed;
#define RX_BA_WIN_SIZE 8 #define RX_BA_MAX_SESSIONS 2
struct wl1271_acx_ba_session_policy { struct wl1271_acx_ba_initiator_policy {
struct acx_header header; struct acx_header header;
/*
* Specifies role Id, Range 0-7, 0xFF means ANY role. /* Specifies role Id, Range 0-7, 0xFF means ANY role. */
* Future use. For now this field is irrelevant
*/
u8 role_id; u8 role_id;
/* /*
* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id. * Per TID setting for allowing TX BA. Set a bit to 1 to allow
* Not applicable if Role Id is set to ANY. * TX BA sessions for the corresponding TID.
*/ */
u8 link_id; u8 tid_bitmap;
u8 tid;
u8 enable;
/* Windows size in number of packets */ /* Windows size in number of packets */
u16 win_size; u8 win_size;
/* u8 padding1[1];
* As initiator inactivity timeout in time units(TU) of 1024us.
* As receiver reserved /* As initiator inactivity timeout in time units(TU) of 1024us */
*/
u16 inactivity_timeout; u16 inactivity_timeout;
/* Initiator = 1/Receiver = 0 */ u8 padding[2];
u8 ba_direction;
u8 padding[3];
} __packed; } __packed;
struct wl1271_acx_ba_receiver_setup { struct wl1271_acx_ba_receiver_setup {
struct acx_header header; struct acx_header header;
/* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id */ /* Specifies link id, range 0-31 */
u8 link_id; u8 hlid;
u8 tid; u8 tid;
u8 enable; u8 enable;
u8 padding[1];
/* Windows size in number of packets */ /* Windows size in number of packets */
u16 win_size; u8 win_size;
/* BA session starting sequence number. RANGE 0-FFF */ /* BA session starting sequence number. RANGE 0-FFF */
u16 ssn; u16 ssn;
u8 padding[2];
} __packed; } __packed;
struct wl1271_acx_fw_tsf_information { struct wl1271_acx_fw_tsf_information {
@ -1158,6 +1020,7 @@ struct wl1271_acx_fw_tsf_information {
struct wl1271_acx_ps_rx_streaming { struct wl1271_acx_ps_rx_streaming {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 tid; u8 tid;
u8 enable; u8 enable;
@ -1166,17 +1029,20 @@ struct wl1271_acx_ps_rx_streaming {
/* timeout before first trigger (0-200 msec) */ /* timeout before first trigger (0-200 msec) */
u8 timeout; u8 timeout;
u8 padding[3];
} __packed; } __packed;
struct wl1271_acx_ap_max_tx_retry { struct wl1271_acx_ap_max_tx_retry {
struct acx_header header; struct acx_header header;
u8 role_id;
u8 padding_1;
/* /*
* the number of frames transmission failures before * the number of frames transmission failures before
* issuing the aging event. * issuing the aging event.
*/ */
__le16 max_tx_retry; __le16 max_tx_retry;
u8 padding_1[2];
} __packed; } __packed;
struct wl1271_acx_config_ps { struct wl1271_acx_config_ps {
@ -1195,13 +1061,6 @@ struct wl1271_acx_inconnection_sta {
u8 padding1[2]; u8 padding1[2];
} __packed; } __packed;
struct acx_ap_beacon_filter {
struct acx_header header;
u8 enable;
u8 pad[3];
} __packed;
/* /*
* ACX_FM_COEX_CFG * ACX_FM_COEX_CFG
* set the FM co-existence parameters. * set the FM co-existence parameters.
@ -1261,6 +1120,30 @@ struct wl1271_acx_fm_coex {
u8 swallow_clk_diff; u8 swallow_clk_diff;
} __packed; } __packed;
#define ACX_RATE_MGMT_ALL_PARAMS 0xff
struct wl12xx_acx_set_rate_mgmt_params {
struct acx_header header;
u8 index; /* 0xff to configure all params */
u8 padding1;
__le16 rate_retry_score;
__le16 per_add;
__le16 per_th1;
__le16 per_th2;
__le16 max_per;
u8 inverse_curiosity_factor;
u8 tx_fail_low_th;
u8 tx_fail_high_th;
u8 per_alpha_shift;
u8 per_add_shift;
u8 per_beta1_shift;
u8 per_beta2_shift;
u8 rate_check_up;
u8 rate_check_down;
u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES];
u8 padding2[2];
} __packed;
enum { enum {
ACX_WAKE_UP_CONDITIONS = 0x0002, ACX_WAKE_UP_CONDITIONS = 0x0002,
ACX_MEM_CFG = 0x0003, ACX_MEM_CFG = 0x0003,
@ -1268,10 +1151,7 @@ enum {
ACX_AC_CFG = 0x0007, ACX_AC_CFG = 0x0007,
ACX_MEM_MAP = 0x0008, ACX_MEM_MAP = 0x0008,
ACX_AID = 0x000A, ACX_AID = 0x000A,
/* ACX_FW_REV is missing in the ref driver, but seems to work */
ACX_FW_REV = 0x000D,
ACX_MEDIUM_USAGE = 0x000F, ACX_MEDIUM_USAGE = 0x000F,
ACX_RX_CFG = 0x0010,
ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */ ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */
ACX_STATISTICS = 0x0013, /* Debug API */ ACX_STATISTICS = 0x0013, /* Debug API */
ACX_PWR_CONSUMPTION_STATISTICS = 0x0014, ACX_PWR_CONSUMPTION_STATISTICS = 0x0014,
@ -1279,7 +1159,6 @@ enum {
ACX_TID_CFG = 0x001A, ACX_TID_CFG = 0x001A,
ACX_PS_RX_STREAMING = 0x001B, ACX_PS_RX_STREAMING = 0x001B,
ACX_BEACON_FILTER_OPT = 0x001F, ACX_BEACON_FILTER_OPT = 0x001F,
ACX_AP_BEACON_FILTER_OPT = 0x0020,
ACX_NOISE_HIST = 0x0021, ACX_NOISE_HIST = 0x0021,
ACX_HDK_VERSION = 0x0022, /* ??? */ ACX_HDK_VERSION = 0x0022, /* ??? */
ACX_PD_THRESHOLD = 0x0023, ACX_PD_THRESHOLD = 0x0023,
@ -1287,7 +1166,6 @@ enum {
ACX_CCA_THRESHOLD = 0x0025, ACX_CCA_THRESHOLD = 0x0025,
ACX_EVENT_MBOX_MASK = 0x0026, ACX_EVENT_MBOX_MASK = 0x0026,
ACX_CONN_MONIT_PARAMS = 0x002D, ACX_CONN_MONIT_PARAMS = 0x002D,
ACX_CONS_TX_FAILURE = 0x002F,
ACX_BCN_DTIM_OPTIONS = 0x0031, ACX_BCN_DTIM_OPTIONS = 0x0031,
ACX_SG_ENABLE = 0x0032, ACX_SG_ENABLE = 0x0032,
ACX_SG_CFG = 0x0033, ACX_SG_CFG = 0x0033,
@ -1314,11 +1192,14 @@ enum {
ACX_RSSI_SNR_WEIGHTS = 0x0052, ACX_RSSI_SNR_WEIGHTS = 0x0052,
ACX_KEEP_ALIVE_MODE = 0x0053, ACX_KEEP_ALIVE_MODE = 0x0053,
ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, ACX_SET_KEEP_ALIVE_CONFIG = 0x0054,
ACX_BA_SESSION_POLICY_CFG = 0x0055, ACX_BA_SESSION_INIT_POLICY = 0x0055,
ACX_BA_SESSION_RX_SETUP = 0x0056, ACX_BA_SESSION_RX_SETUP = 0x0056,
ACX_PEER_HT_CAP = 0x0057, ACX_PEER_HT_CAP = 0x0057,
ACX_HT_BSS_OPERATION = 0x0058, ACX_HT_BSS_OPERATION = 0x0058,
ACX_COEX_ACTIVITY = 0x0059, ACX_COEX_ACTIVITY = 0x0059,
ACX_BURST_MODE = 0x005C,
ACX_SET_RATE_MGMT_PARAMS = 0x005D,
ACX_SET_RATE_ADAPT_PARAMS = 0x0060,
ACX_SET_DCO_ITRIM_PARAMS = 0x0061, ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
ACX_GEN_FW_CMD = 0x0070, ACX_GEN_FW_CMD = 0x0070,
ACX_HOST_IF_CFG_BITMAP = 0x0071, ACX_HOST_IF_CFG_BITMAP = 0x0071,
@ -1342,7 +1223,6 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl);
int wl1271_acx_mem_map(struct wl1271 *wl, int wl1271_acx_mem_map(struct wl1271 *wl,
struct acx_header *mem_map, size_t len); struct acx_header *mem_map, size_t len);
int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl); int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl);
int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter);
int wl1271_acx_pd_threshold(struct wl1271 *wl); int wl1271_acx_pd_threshold(struct wl1271 *wl);
int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time);
int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
@ -1354,8 +1234,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter);
int wl1271_acx_beacon_filter_table(struct wl1271 *wl); int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable);
int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable);
int wl1271_acx_sta_sg_cfg(struct wl1271 *wl); int wl12xx_acx_sg_cfg(struct wl1271 *wl);
int wl1271_acx_ap_sg_cfg(struct wl1271 *wl);
int wl1271_acx_cca_threshold(struct wl1271 *wl); int wl1271_acx_cca_threshold(struct wl1271 *wl);
int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); int wl1271_acx_bcn_dtim_options(struct wl1271 *wl);
int wl1271_acx_aid(struct wl1271 *wl, u16 aid); int wl1271_acx_aid(struct wl1271 *wl, u16 aid);
@ -1374,8 +1253,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
u32 apsd_conf0, u32 apsd_conf1); u32 apsd_conf0, u32 apsd_conf1);
int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold); int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold);
int wl1271_acx_tx_config_options(struct wl1271 *wl); int wl1271_acx_tx_config_options(struct wl1271 *wl);
int wl1271_acx_ap_mem_cfg(struct wl1271 *wl); int wl12xx_acx_mem_cfg(struct wl1271 *wl);
int wl1271_acx_sta_mem_cfg(struct wl1271 *wl);
int wl1271_acx_init_mem_config(struct wl1271 *wl); int wl1271_acx_init_mem_config(struct wl1271 *wl);
int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap);
int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
@ -1390,20 +1268,18 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl);
int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
struct ieee80211_sta_ht_cap *ht_cap, struct ieee80211_sta_ht_cap *ht_cap,
bool allow_ht_operation); bool allow_ht_operation, u8 hlid);
int wl1271_acx_set_ht_information(struct wl1271 *wl, int wl1271_acx_set_ht_information(struct wl1271 *wl,
u16 ht_operation_mode); u16 ht_operation_mode);
int wl1271_acx_set_ba_session(struct wl1271 *wl, int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl);
enum ieee80211_back_parties direction, int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
u8 tid_index, u8 policy); u16 ssn, bool enable, u8 peer_hlid);
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
bool enable);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl);
int wl1271_acx_config_ps(struct wl1271 *wl); int wl1271_acx_config_ps(struct wl1271 *wl);
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable);
int wl1271_acx_fm_coex(struct wl1271 *wl); int wl1271_acx_fm_coex(struct wl1271 *wl);
int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
#endif /* __WL1271_ACX_H__ */ #endif /* __WL1271_ACX_H__ */

View file

@ -107,16 +107,6 @@ static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl)
unsigned int quirks = 0; unsigned int quirks = 0;
unsigned int *fw_ver = wl->chip.fw_ver; unsigned int *fw_ver = wl->chip.fw_ver;
/* Only for wl127x */
if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) &&
/* Check STA version */
(((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
(fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) ||
/* Check AP version */
((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) &&
(fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN))))
quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS;
/* Only new station firmwares support routing fw logs to the host */ /* Only new station firmwares support routing fw logs to the host */
if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
(fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN)) (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN))
@ -504,21 +494,18 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
wl->event_mask = BSS_LOSE_EVENT_ID | wl->event_mask = BSS_LOSE_EVENT_ID |
SCAN_COMPLETE_EVENT_ID | SCAN_COMPLETE_EVENT_ID |
PS_REPORT_EVENT_ID | PS_REPORT_EVENT_ID |
JOIN_EVENT_COMPLETE_ID |
DISCONNECT_EVENT_COMPLETE_ID | DISCONNECT_EVENT_COMPLETE_ID |
RSSI_SNR_TRIGGER_0_EVENT_ID | RSSI_SNR_TRIGGER_0_EVENT_ID |
PSPOLL_DELIVERY_FAILURE_EVENT_ID | PSPOLL_DELIVERY_FAILURE_EVENT_ID |
SOFT_GEMINI_SENSE_EVENT_ID | SOFT_GEMINI_SENSE_EVENT_ID |
PERIODIC_SCAN_REPORT_EVENT_ID | PERIODIC_SCAN_REPORT_EVENT_ID |
PERIODIC_SCAN_COMPLETE_EVENT_ID; PERIODIC_SCAN_COMPLETE_EVENT_ID |
DUMMY_PACKET_EVENT_ID |
if (wl->bss_type == BSS_TYPE_AP_BSS) PEER_REMOVE_COMPLETE_EVENT_ID |
wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | BA_SESSION_RX_CONSTRAINT_EVENT_ID |
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
INACTIVE_STA_EVENT_ID | INACTIVE_STA_EVENT_ID |
MAX_TX_RETRY_EVENT_ID; MAX_TX_RETRY_EVENT_ID;
else
wl->event_mask |= DUMMY_PACKET_EVENT_ID |
BA_SESSION_RX_CONSTRAINT_EVENT_ID;
ret = wl1271_event_unmask(wl); ret = wl1271_event_unmask(wl);
if (ret < 0) { if (ret < 0) {
@ -549,13 +536,13 @@ static void wl1271_boot_hw_version(struct wl1271 *wl)
{ {
u32 fuse; u32 fuse;
fuse = wl1271_top_reg_read(wl, REG_FUSE_DATA_2_1); if (wl->chip.id == CHIP_ID_1283_PG20)
fuse = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
else
fuse = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET; fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET;
wl->hw_pg_ver = (s8)fuse; wl->hw_pg_ver = (s8)fuse;
if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3)
wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
} }
static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
@ -696,7 +683,8 @@ static int wl127x_boot_clk(struct wl1271 *wl)
u32 pause; u32 pause;
u32 clk; u32 clk;
wl1271_boot_hw_version(wl); if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3)
wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
if (wl->ref_clock == CONF_REF_CLK_19_2_E || if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
wl->ref_clock == CONF_REF_CLK_38_4_E || wl->ref_clock == CONF_REF_CLK_38_4_E ||
@ -750,6 +738,8 @@ int wl1271_load_firmware(struct wl1271 *wl)
u32 tmp, clk; u32 tmp, clk;
int selected_clock = -1; int selected_clock = -1;
wl1271_boot_hw_version(wl);
if (wl->chip.id == CHIP_ID_1283_PG20) { if (wl->chip.id == CHIP_ID_1283_PG20) {
ret = wl128x_boot_clk(wl, &selected_clock); ret = wl128x_boot_clk(wl, &selected_clock);
if (ret < 0) if (ret < 0)
@ -852,9 +842,6 @@ int wl1271_boot(struct wl1271 *wl)
/* Enable firmware interrupts now */ /* Enable firmware interrupts now */
wl1271_boot_enable_interrupts(wl); wl1271_boot_enable_interrupts(wl);
/* set the wl1271 default filters */
wl1271_set_default_filters(wl);
wl1271_event_mbox_config(wl); wl1271_event_mbox_config(wl);
out: out:

View file

@ -55,7 +55,8 @@ struct wl1271_static_data {
#define OCP_REG_CLK_POLARITY 0x0cb2 #define OCP_REG_CLK_POLARITY 0x0cb2
#define OCP_REG_CLK_PULL 0x0cb4 #define OCP_REG_CLK_PULL 0x0cb4
#define REG_FUSE_DATA_2_1 0x050a #define WL127X_REG_FUSE_DATA_2_1 0x050a
#define WL128X_REG_FUSE_DATA_2_1 0x2152
#define PG_VER_MASK 0x3c #define PG_VER_MASK 0x3c
#define PG_VER_OFFSET 2 #define PG_VER_OFFSET 2

View file

@ -363,63 +363,470 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
return 0; return 0;
} }
int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id)
{ {
struct wl1271_cmd_join *join; struct wl12xx_cmd_role_enable *cmd;
int ret, i; int ret;
u8 *bssid;
join = kzalloc(sizeof(*join), GFP_KERNEL); wl1271_debug(DEBUG_CMD, "cmd role enable");
if (!join) {
if (WARN_ON(*role_id != WL12XX_INVALID_ROLE_ID))
return -EBUSY;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
wl1271_debug(DEBUG_CMD, "cmd join"); /* get role id */
cmd->role_id = find_first_zero_bit(wl->roles_map, WL12XX_MAX_ROLES);
/* Reverse order BSSID */ if (cmd->role_id >= WL12XX_MAX_ROLES) {
bssid = (u8 *) &join->bssid_lsb; ret = -EBUSY;
for (i = 0; i < ETH_ALEN; i++)
bssid[i] = wl->bssid[ETH_ALEN - i - 1];
join->rx_config_options = cpu_to_le32(wl->rx_config);
join->rx_filter_options = cpu_to_le32(wl->rx_filter);
join->bss_type = bss_type;
join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
join->supported_rate_set = cpu_to_le32(wl->rate_set);
if (wl->band == IEEE80211_BAND_5GHZ)
join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
join->beacon_interval = cpu_to_le16(wl->beacon_int);
join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD;
join->channel = wl->channel;
join->ssid_len = wl->ssid_len;
memcpy(join->ssid, wl->ssid, wl->ssid_len);
join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",
join->basic_rate_set, join->supported_rate_set);
ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd join");
goto out_free; goto out_free;
} }
ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); memcpy(cmd->mac_address, wl->mac_addr, ETH_ALEN);
if (ret < 0) cmd->role_type = role_type;
wl1271_error("cmd join event completion error");
ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd role enable");
goto out_free;
}
__set_bit(cmd->role_id, wl->roles_map);
*role_id = cmd->role_id;
out_free: out_free:
kfree(join); kfree(cmd);
out: out:
return ret; return ret;
} }
int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id)
{
struct wl12xx_cmd_role_disable *cmd;
int ret;
wl1271_debug(DEBUG_CMD, "cmd role disable");
if (WARN_ON(*role_id == WL12XX_INVALID_ROLE_ID))
return -ENOENT;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
cmd->role_id = *role_id;
ret = wl1271_cmd_send(wl, CMD_ROLE_DISABLE, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd role disable");
goto out_free;
}
__clear_bit(*role_id, wl->roles_map);
*role_id = WL12XX_INVALID_ROLE_ID;
out_free:
kfree(cmd);
out:
return ret;
}
static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid)
{
u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS);
if (link >= WL12XX_MAX_LINKS)
return -EBUSY;
__set_bit(link, wl->links_map);
*hlid = link;
return 0;
}
static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid)
{
if (*hlid == WL12XX_INVALID_LINK_ID)
return;
__clear_bit(*hlid, wl->links_map);
*hlid = WL12XX_INVALID_LINK_ID;
}
static int wl12xx_get_new_session_id(struct wl1271 *wl)
{
if (wl->session_counter >= SESSION_COUNTER_MAX)
wl->session_counter = 0;
wl->session_counter++;
return wl->session_counter;
}
int wl12xx_cmd_role_start_dev(struct wl1271 *wl)
{
struct wl12xx_cmd_role_start *cmd;
int ret;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wl->dev_role_id);
cmd->role_id = wl->dev_role_id;
if (wl->band == IEEE80211_BAND_5GHZ)
cmd->band = WL12XX_BAND_5GHZ;
cmd->channel = wl->channel;
if (wl->dev_hlid == WL12XX_INVALID_LINK_ID) {
ret = wl12xx_allocate_link(wl, &wl->dev_hlid);
if (ret)
goto out_free;
}
cmd->device.hlid = wl->dev_hlid;
cmd->device.session = wl->session_counter;
wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d",
cmd->role_id, cmd->device.hlid, cmd->device.session);
ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd role enable");
goto err_hlid;
}
goto out_free;
err_hlid:
/* clear links on error */
__clear_bit(wl->dev_hlid, wl->links_map);
wl->dev_hlid = WL12XX_INVALID_LINK_ID;
out_free:
kfree(cmd);
out:
return ret;
}
int wl12xx_cmd_role_stop_dev(struct wl1271 *wl)
{
struct wl12xx_cmd_role_stop *cmd;
int ret;
if (WARN_ON(wl->dev_hlid == WL12XX_INVALID_LINK_ID))
return -EINVAL;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
wl1271_debug(DEBUG_CMD, "cmd role stop dev");
cmd->role_id = wl->dev_role_id;
cmd->disc_type = DISCONNECT_IMMEDIATE;
cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd role stop");
goto out_free;
}
ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
if (ret < 0) {
wl1271_error("cmd role stop dev event completion error");
goto out_free;
}
wl12xx_free_link(wl, &wl->dev_hlid);
out_free:
kfree(cmd);
out:
return ret;
}
int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
{
struct wl12xx_cmd_role_start *cmd;
int ret;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wl->role_id);
cmd->role_id = wl->role_id;
if (wl->band == IEEE80211_BAND_5GHZ)
cmd->band = WL12XX_BAND_5GHZ;
cmd->channel = wl->channel;
cmd->sta.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int);
cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY;
cmd->sta.ssid_len = wl->ssid_len;
memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len);
memcpy(cmd->sta.bssid, wl->bssid, ETH_ALEN);
cmd->sta.local_rates = cpu_to_le32(wl->rate_set);
if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) {
ret = wl12xx_allocate_link(wl, &wl->sta_hlid);
if (ret)
goto out_free;
}
cmd->sta.hlid = wl->sta_hlid;
cmd->sta.session = wl12xx_get_new_session_id(wl);
cmd->sta.remote_rates = cpu_to_le32(wl->rate_set);
wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
"basic_rate_set: 0x%x, remote_rates: 0x%x",
wl->role_id, cmd->sta.hlid, cmd->sta.session,
wl->basic_rate_set, wl->rate_set);
ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd role start sta");
goto err_hlid;
}
goto out_free;
err_hlid:
/* clear links on error. */
wl12xx_free_link(wl, &wl->sta_hlid);
out_free:
kfree(cmd);
out:
return ret;
}
/* use this function to stop ibss as well */
int wl12xx_cmd_role_stop_sta(struct wl1271 *wl)
{
struct wl12xx_cmd_role_stop *cmd;
int ret;
if (WARN_ON(wl->sta_hlid == WL12XX_INVALID_LINK_ID))
return -EINVAL;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wl->role_id);
cmd->role_id = wl->role_id;
cmd->disc_type = DISCONNECT_IMMEDIATE;
cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd role stop sta");
goto out_free;
}
wl12xx_free_link(wl, &wl->sta_hlid);
out_free:
kfree(cmd);
out:
return ret;
}
int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
{
struct wl12xx_cmd_role_start *cmd;
struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
int ret;
wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id);
/*
* We currently do not support hidden SSID. The real SSID
* should be fetched from mac80211 first.
*/
if (wl->ssid_len == 0) {
wl1271_warning("Hidden SSID currently not supported for AP");
ret = -EINVAL;
goto out;
}
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
ret = wl12xx_allocate_link(wl, &wl->ap_global_hlid);
if (ret < 0)
goto out_free;
ret = wl12xx_allocate_link(wl, &wl->ap_bcast_hlid);
if (ret < 0)
goto out_free_global;
cmd->role_id = wl->role_id;
cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
cmd->ap.bss_index = WL1271_AP_BSS_INDEX;
cmd->ap.global_hlid = wl->ap_global_hlid;
cmd->ap.broadcast_hlid = wl->ap_bcast_hlid;
cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int);
cmd->ap.dtim_interval = bss_conf->dtim_period;
cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
cmd->channel = wl->channel;
cmd->ap.ssid_len = wl->ssid_len;
cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC;
memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len);
cmd->ap.local_rates = cpu_to_le32(0xffffffff);
switch (wl->band) {
case IEEE80211_BAND_2GHZ:
cmd->band = RADIO_BAND_2_4GHZ;
break;
case IEEE80211_BAND_5GHZ:
cmd->band = RADIO_BAND_5GHZ;
break;
default:
wl1271_warning("ap start - unknown band: %d", (int)wl->band);
cmd->band = RADIO_BAND_2_4GHZ;
break;
}
ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd role start ap");
goto out_free_bcast;
}
goto out_free;
out_free_bcast:
wl12xx_free_link(wl, &wl->ap_bcast_hlid);
out_free_global:
wl12xx_free_link(wl, &wl->ap_global_hlid);
out_free:
kfree(cmd);
out:
return ret;
}
int wl12xx_cmd_role_stop_ap(struct wl1271 *wl)
{
struct wl12xx_cmd_role_stop *cmd;
int ret;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wl->role_id);
cmd->role_id = wl->role_id;
ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd role stop ap");
goto out_free;
}
wl12xx_free_link(wl, &wl->ap_bcast_hlid);
wl12xx_free_link(wl, &wl->ap_global_hlid);
out_free:
kfree(cmd);
out:
return ret;
}
int wl12xx_cmd_role_start_ibss(struct wl1271 *wl)
{
struct wl12xx_cmd_role_start *cmd;
struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
int ret;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wl->role_id);
cmd->role_id = wl->role_id;
if (wl->band == IEEE80211_BAND_5GHZ)
cmd->band = WL12XX_BAND_5GHZ;
cmd->channel = wl->channel;
cmd->ibss.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int);
cmd->ibss.dtim_interval = bss_conf->dtim_period;
cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY;
cmd->ibss.ssid_len = wl->ssid_len;
memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len);
memcpy(cmd->ibss.bssid, wl->bssid, ETH_ALEN);
cmd->sta.local_rates = cpu_to_le32(wl->rate_set);
if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) {
ret = wl12xx_allocate_link(wl, &wl->sta_hlid);
if (ret)
goto out_free;
}
cmd->ibss.hlid = wl->sta_hlid;
cmd->ibss.remote_rates = cpu_to_le32(wl->rate_set);
wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
"basic_rate_set: 0x%x, remote_rates: 0x%x",
wl->role_id, cmd->sta.hlid, cmd->sta.session,
wl->basic_rate_set, wl->rate_set);
wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid);
ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd role enable");
goto err_hlid;
}
goto out_free;
err_hlid:
/* clear links on error. */
wl12xx_free_link(wl, &wl->sta_hlid);
out_free:
kfree(cmd);
out:
return ret;
}
/** /**
* send test command to firmware * send test command to firmware
* *
@ -567,6 +974,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
goto out; goto out;
} }
ps_params->role_id = wl->role_id;
ps_params->ps_mode = ps_mode; ps_params->ps_mode = ps_mode;
ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
@ -813,9 +1221,9 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
wl->basic_rate); wl->basic_rate);
} }
int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id) int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid)
{ {
struct wl1271_cmd_set_sta_keys *cmd; struct wl1271_cmd_set_keys *cmd;
int ret = 0; int ret = 0;
wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id);
@ -826,7 +1234,9 @@ int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id)
goto out; goto out;
} }
cmd->id = id; cmd->hlid = hlid;
cmd->key_id = id;
cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
cmd->key_action = cpu_to_le16(KEY_SET_ID); cmd->key_action = cpu_to_le16(KEY_SET_ID);
cmd->key_type = KEY_WEP; cmd->key_type = KEY_WEP;
@ -842,52 +1252,31 @@ out:
return ret; return ret;
} }
int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id)
{
struct wl1271_cmd_set_ap_keys *cmd;
int ret = 0;
wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
cmd->hlid = WL1271_AP_BROADCAST_HLID;
cmd->key_id = id;
cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
cmd->key_action = cpu_to_le16(KEY_SET_ID);
cmd->key_type = KEY_WEP;
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret);
goto out;
}
out:
kfree(cmd);
return ret;
}
int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr, u8 key_size, const u8 *key, const u8 *addr,
u32 tx_seq_32, u16 tx_seq_16) u32 tx_seq_32, u16 tx_seq_16)
{ {
struct wl1271_cmd_set_sta_keys *cmd; struct wl1271_cmd_set_keys *cmd;
int ret = 0; int ret = 0;
/* hlid might have already been deleted */
if (wl->sta_hlid == WL12XX_INVALID_LINK_ID)
return 0;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) { if (!cmd) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
if (key_type != KEY_WEP) cmd->hlid = wl->sta_hlid;
memcpy(cmd->addr, addr, ETH_ALEN);
if (key_type == KEY_WEP)
cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
else if (is_broadcast_ether_addr(addr))
cmd->lid_key_type = BROADCAST_LID_TYPE;
else
cmd->lid_key_type = UNICAST_LID_TYPE;
cmd->key_action = cpu_to_le16(action); cmd->key_action = cpu_to_le16(action);
cmd->key_size = key_size; cmd->key_size = key_size;
@ -896,10 +1285,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16);
cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32);
/* we have only one SSID profile */ cmd->key_id = id;
cmd->ssid_profile = 0;
cmd->id = id;
if (key_type == KEY_TKIP) { if (key_type == KEY_TKIP) {
/* /*
@ -930,11 +1316,15 @@ out:
return ret; return ret;
} }
/*
* TODO: merge with sta/ibss into 1 set_key function.
* note there are slight diffs
*/
int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
u16 tx_seq_16) u16 tx_seq_16)
{ {
struct wl1271_cmd_set_ap_keys *cmd; struct wl1271_cmd_set_keys *cmd;
int ret = 0; int ret = 0;
u8 lid_type; u8 lid_type;
@ -942,7 +1332,7 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
if (!cmd) if (!cmd)
return -ENOMEM; return -ENOMEM;
if (hlid == WL1271_AP_BROADCAST_HLID) { if (hlid == wl->ap_bcast_hlid) {
if (key_type == KEY_WEP) if (key_type == KEY_WEP)
lid_type = WEP_DEFAULT_LID_TYPE; lid_type = WEP_DEFAULT_LID_TYPE;
else else
@ -991,47 +1381,12 @@ out:
return ret; return ret;
} }
int wl1271_cmd_disconnect(struct wl1271 *wl) int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid)
{ {
struct wl1271_cmd_disconnect *cmd; struct wl12xx_cmd_set_peer_state *cmd;
int ret = 0; int ret = 0;
wl1271_debug(DEBUG_CMD, "cmd disconnect"); wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", hlid);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
cmd->rx_config_options = cpu_to_le32(wl->rx_config);
cmd->rx_filter_options = cpu_to_le32(wl->rx_filter);
/* disconnect reason is not used in immediate disconnections */
cmd->type = DISCONNECT_IMMEDIATE;
ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to send disconnect command");
goto out_free;
}
ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
if (ret < 0)
wl1271_error("cmd disconnect event completion error");
out_free:
kfree(cmd);
out:
return ret;
}
int wl1271_cmd_set_sta_state(struct wl1271 *wl)
{
struct wl1271_cmd_set_sta_state *cmd;
int ret = 0;
wl1271_debug(DEBUG_CMD, "cmd set sta state");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) { if (!cmd) {
@ -1039,11 +1394,12 @@ int wl1271_cmd_set_sta_state(struct wl1271 *wl)
goto out; goto out;
} }
cmd->hlid = hlid;
cmd->state = WL1271_CMD_STA_STATE_CONNECTED; cmd->state = WL1271_CMD_STA_STATE_CONNECTED;
ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0); ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0);
if (ret < 0) { if (ret < 0) {
wl1271_error("failed to send set STA state command"); wl1271_error("failed to send set peer state command");
goto out_free; goto out_free;
} }
@ -1054,105 +1410,13 @@ out:
return ret; return ret;
} }
int wl1271_cmd_start_bss(struct wl1271 *wl) int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
{ {
struct wl1271_cmd_bss_start *cmd; struct wl12xx_cmd_add_peer *cmd;
struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
int ret; int ret;
u32 sta_rates;
wl1271_debug(DEBUG_CMD, "cmd start bss"); wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid);
/*
* FIXME: We currently do not support hidden SSID. The real SSID
* should be fetched from mac80211 first.
*/
if (wl->ssid_len == 0) {
wl1271_warning("Hidden SSID currently not supported for AP");
ret = -EINVAL;
goto out;
}
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);
cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
cmd->bss_index = WL1271_AP_BSS_INDEX;
cmd->global_hlid = WL1271_AP_GLOBAL_HLID;
cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID;
cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
cmd->beacon_interval = cpu_to_le16(wl->beacon_int);
cmd->dtim_interval = bss_conf->dtim_period;
cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
cmd->channel = wl->channel;
cmd->ssid_len = wl->ssid_len;
cmd->ssid_type = SSID_TYPE_PUBLIC;
memcpy(cmd->ssid, wl->ssid, wl->ssid_len);
switch (wl->band) {
case IEEE80211_BAND_2GHZ:
cmd->band = RADIO_BAND_2_4GHZ;
break;
case IEEE80211_BAND_5GHZ:
cmd->band = RADIO_BAND_5GHZ;
break;
default:
wl1271_warning("bss start - unknown band: %d", (int)wl->band);
cmd->band = RADIO_BAND_2_4GHZ;
break;
}
ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd start bss");
goto out_free;
}
out_free:
kfree(cmd);
out:
return ret;
}
int wl1271_cmd_stop_bss(struct wl1271 *wl)
{
struct wl1271_cmd_bss_start *cmd;
int ret;
wl1271_debug(DEBUG_CMD, "cmd stop bss");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
cmd->bss_index = WL1271_AP_BSS_INDEX;
ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd stop bss");
goto out_free;
}
out_free:
kfree(cmd);
out:
return ret;
}
int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
{
struct wl1271_cmd_add_sta *cmd;
int ret;
wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) { if (!cmd) {
@ -1169,14 +1433,18 @@ int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
cmd->hlid = hlid; cmd->hlid = hlid;
cmd->wmm = sta->wme ? 1 : 0; cmd->wmm = sta->wme ? 1 : 0;
cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates = sta->supp_rates[wl->band];
sta->supp_rates[wl->band])); if (sta->ht_cap.ht_supported)
sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET;
wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates); cmd->supported_rates =
cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates));
ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0); wl1271_debug(DEBUG_CMD, "new peer rates: 0x%x", cmd->supported_rates);
ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0);
if (ret < 0) { if (ret < 0) {
wl1271_error("failed to initiate cmd add sta"); wl1271_error("failed to initiate cmd add peer");
goto out_free; goto out_free;
} }
@ -1187,12 +1455,12 @@ out:
return ret; return ret;
} }
int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid) int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
{ {
struct wl1271_cmd_remove_sta *cmd; struct wl12xx_cmd_remove_peer *cmd;
int ret; int ret;
wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid); wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) { if (!cmd) {
@ -1205,9 +1473,9 @@ int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
cmd->reason_opcode = 0; cmd->reason_opcode = 0;
cmd->send_deauth_flag = 0; cmd->send_deauth_flag = 0;
ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0); ret = wl1271_cmd_send(wl, CMD_REMOVE_PEER, cmd, sizeof(*cmd), 0);
if (ret < 0) { if (ret < 0) {
wl1271_error("failed to initiate cmd remove sta"); wl1271_error("failed to initiate cmd remove peer");
goto out_free; goto out_free;
} }
@ -1215,7 +1483,8 @@ int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
* We are ok with a timeout here. The event is sometimes not sent * We are ok with a timeout here. The event is sometimes not sent
* due to a firmware bug. * due to a firmware bug.
*/ */
wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID); wl1271_cmd_wait_for_event_or_timeout(wl,
PEER_REMOVE_COMPLETE_EVENT_ID);
out_free: out_free:
kfree(cmd); kfree(cmd);
@ -1307,3 +1576,115 @@ out_free:
out: out:
return ret; return ret;
} }
static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id)
{
struct wl12xx_cmd_roc *cmd;
int ret = 0;
wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wl->channel, role_id);
if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID))
return -EINVAL;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
cmd->role_id = role_id;
cmd->channel = wl->channel;
switch (wl->band) {
case IEEE80211_BAND_2GHZ:
cmd->band = RADIO_BAND_2_4GHZ;
break;
case IEEE80211_BAND_5GHZ:
cmd->band = RADIO_BAND_5GHZ;
break;
default:
wl1271_error("roc - unknown band: %d", (int)wl->band);
ret = -EINVAL;
goto out_free;
}
ret = wl1271_cmd_send(wl, CMD_REMAIN_ON_CHANNEL, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to send ROC command");
goto out_free;
}
out_free:
kfree(cmd);
out:
return ret;
}
static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id)
{
struct wl12xx_cmd_croc *cmd;
int ret = 0;
wl1271_debug(DEBUG_CMD, "cmd croc (%d)", role_id);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
cmd->role_id = role_id;
ret = wl1271_cmd_send(wl, CMD_CANCEL_REMAIN_ON_CHANNEL, cmd,
sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to send ROC command");
goto out_free;
}
out_free:
kfree(cmd);
out:
return ret;
}
int wl12xx_roc(struct wl1271 *wl, u8 role_id)
{
int ret = 0;
if (WARN_ON(test_bit(role_id, wl->roc_map)))
return 0;
ret = wl12xx_cmd_roc(wl, role_id);
if (ret < 0)
goto out;
ret = wl1271_cmd_wait_for_event(wl,
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID);
if (ret < 0) {
wl1271_error("cmd roc event completion error");
goto out;
}
__set_bit(role_id, wl->roc_map);
out:
return ret;
}
int wl12xx_croc(struct wl1271 *wl, u8 role_id)
{
int ret = 0;
if (WARN_ON(!test_bit(role_id, wl->roc_map)))
return 0;
ret = wl12xx_cmd_croc(wl, role_id);
if (ret < 0)
goto out;
__clear_bit(role_id, wl->roc_map);
out:
return ret;
}

View file

@ -36,7 +36,15 @@ int wl128x_cmd_general_parms(struct wl1271 *wl);
int wl1271_cmd_radio_parms(struct wl1271 *wl); int wl1271_cmd_radio_parms(struct wl1271 *wl);
int wl128x_cmd_radio_parms(struct wl1271 *wl); int wl128x_cmd_radio_parms(struct wl1271 *wl);
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id);
int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id);
int wl12xx_cmd_role_start_dev(struct wl1271 *wl);
int wl12xx_cmd_role_stop_dev(struct wl1271 *wl);
int wl12xx_cmd_role_start_sta(struct wl1271 *wl);
int wl12xx_cmd_role_stop_sta(struct wl1271 *wl);
int wl12xx_cmd_role_start_ap(struct wl1271 *wl);
int wl12xx_cmd_role_stop_ap(struct wl1271 *wl);
int wl12xx_cmd_role_start_ibss(struct wl1271 *wl);
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
@ -56,20 +64,18 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr);
int wl1271_build_qos_null_data(struct wl1271 *wl); int wl1271_build_qos_null_data(struct wl1271 *wl);
int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); int wl1271_cmd_build_klv_null_data(struct wl1271 *wl);
int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id); int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid);
int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id);
int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr, u8 key_size, const u8 *key, const u8 *addr,
u32 tx_seq_32, u16 tx_seq_16); u32 tx_seq_32, u16 tx_seq_16);
int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
u16 tx_seq_16); u16 tx_seq_16);
int wl1271_cmd_disconnect(struct wl1271 *wl); int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid);
int wl1271_cmd_set_sta_state(struct wl1271 *wl); int wl12xx_roc(struct wl1271 *wl, u8 role_id);
int wl1271_cmd_start_bss(struct wl1271 *wl); int wl12xx_croc(struct wl1271 *wl, u8 role_id);
int wl1271_cmd_stop_bss(struct wl1271 *wl); int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid); int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid);
int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid);
int wl12xx_cmd_config_fwlog(struct wl1271 *wl); int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
int wl12xx_cmd_start_fwlog(struct wl1271 *wl); int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
@ -83,25 +89,21 @@ enum wl1271_commands {
CMD_DISABLE_TX = 6, CMD_DISABLE_TX = 6,
CMD_SCAN = 8, CMD_SCAN = 8,
CMD_STOP_SCAN = 9, CMD_STOP_SCAN = 9,
CMD_START_JOIN = 11,
CMD_SET_KEYS = 12, CMD_SET_KEYS = 12,
CMD_READ_MEMORY = 13, CMD_READ_MEMORY = 13,
CMD_WRITE_MEMORY = 14, CMD_WRITE_MEMORY = 14,
CMD_SET_TEMPLATE = 19, CMD_SET_TEMPLATE = 19,
CMD_TEST = 23, CMD_TEST = 23,
CMD_NOISE_HIST = 28, CMD_NOISE_HIST = 28,
CMD_LNA_CONTROL = 32, CMD_QUIET_ELEMENT_SET_STATE = 29,
CMD_SET_BCN_MODE = 33, CMD_SET_BCN_MODE = 33,
CMD_MEASUREMENT = 34, CMD_MEASUREMENT = 34,
CMD_STOP_MEASUREMENT = 35, CMD_STOP_MEASUREMENT = 35,
CMD_DISCONNECT = 36,
CMD_SET_PS_MODE = 37, CMD_SET_PS_MODE = 37,
CMD_CHANNEL_SWITCH = 38, CMD_CHANNEL_SWITCH = 38,
CMD_STOP_CHANNEL_SWICTH = 39, CMD_STOP_CHANNEL_SWICTH = 39,
CMD_AP_DISCOVERY = 40, CMD_AP_DISCOVERY = 40,
CMD_STOP_AP_DISCOVERY = 41, CMD_STOP_AP_DISCOVERY = 41,
CMD_SPS_SCAN = 42,
CMD_STOP_SPS_SCAN = 43,
CMD_HEALTH_CHECK = 45, CMD_HEALTH_CHECK = 45,
CMD_DEBUG = 46, CMD_DEBUG = 46,
CMD_TRIGGER_SCAN_TO = 47, CMD_TRIGGER_SCAN_TO = 47,
@ -109,16 +111,30 @@ enum wl1271_commands {
CMD_CONNECTION_SCAN_SSID_CFG = 49, CMD_CONNECTION_SCAN_SSID_CFG = 49,
CMD_START_PERIODIC_SCAN = 50, CMD_START_PERIODIC_SCAN = 50,
CMD_STOP_PERIODIC_SCAN = 51, CMD_STOP_PERIODIC_SCAN = 51,
CMD_SET_STA_STATE = 52, CMD_SET_PEER_STATE = 52,
CMD_CONFIG_FWLOGGER = 53, CMD_REMAIN_ON_CHANNEL = 53,
CMD_START_FWLOGGER = 54, CMD_CANCEL_REMAIN_ON_CHANNEL = 54,
CMD_STOP_FWLOGGER = 55,
/* AP mode commands */ CMD_CONFIG_FWLOGGER = 55,
CMD_BSS_START = 60, CMD_START_FWLOGGER = 56,
CMD_BSS_STOP = 61, CMD_STOP_FWLOGGER = 57,
CMD_ADD_STA = 62,
CMD_REMOVE_STA = 63, /* AP commands */
CMD_ADD_PEER = 62,
CMD_REMOVE_PEER = 63,
/* Role API */
CMD_ROLE_ENABLE = 70,
CMD_ROLE_DISABLE = 71,
CMD_ROLE_START = 72,
CMD_ROLE_STOP = 73,
/* WIFI Direct */
CMD_WFD_START_DISCOVERY = 80,
CMD_WFD_STOP_DISCOVERY = 81,
CMD_WFD_ATTRIBUTE_CONFIG = 82,
CMD_NOP = 100,
NUM_COMMANDS, NUM_COMMANDS,
MAX_COMMAND_ID = 0xFFFF, MAX_COMMAND_ID = 0xFFFF,
@ -147,21 +163,20 @@ enum cmd_templ {
CMD_TEMPL_CTS, /* CMD_TEMPL_CTS, /*
* For CTS-to-self (FastCTS) mechanism * For CTS-to-self (FastCTS) mechanism
* for BT/WLAN coexistence (SoftGemini). */ * for BT/WLAN coexistence (SoftGemini). */
CMD_TEMPL_ARP_RSP, CMD_TEMPL_AP_BEACON,
CMD_TEMPL_LINK_MEASUREMENT_REPORT,
/* AP-mode specific */
CMD_TEMPL_AP_BEACON = 13,
CMD_TEMPL_AP_PROBE_RESPONSE, CMD_TEMPL_AP_PROBE_RESPONSE,
CMD_TEMPL_AP_ARP_RSP, CMD_TEMPL_ARP_RSP,
CMD_TEMPL_DEAUTH_AP, CMD_TEMPL_DEAUTH_AP,
CMD_TEMPL_TEMPORARY,
CMD_TEMPL_LINK_MEASUREMENT_REPORT,
CMD_TEMPL_MAX = 0xff CMD_TEMPL_MAX = 0xff
}; };
/* unit ms */ /* unit ms */
#define WL1271_COMMAND_TIMEOUT 2000 #define WL1271_COMMAND_TIMEOUT 2000
#define WL1271_CMD_TEMPL_MAX_SIZE 252 #define WL1271_CMD_TEMPL_DFLT_SIZE 252
#define WL1271_CMD_TEMPL_MAX_SIZE 548
#define WL1271_EVENT_TIMEOUT 750 #define WL1271_EVENT_TIMEOUT 750
struct wl1271_cmd_header { struct wl1271_cmd_header {
@ -193,6 +208,8 @@ enum {
CMD_STATUS_WRONG_NESTING = 19, CMD_STATUS_WRONG_NESTING = 19,
CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/ CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/
CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/ CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/
CMD_STATUS_TEMPLATE_OOM = 23,
CMD_STATUS_NO_RX_BA_SESSION = 24,
MAX_COMMAND_STATUS = 0xff MAX_COMMAND_STATUS = 0xff
}; };
@ -210,14 +227,50 @@ enum {
#define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1 #define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1
#define WL1271_JOIN_CMD_BSS_TYPE_5GHZ 0x10 #define WL1271_JOIN_CMD_BSS_TYPE_5GHZ 0x10
struct wl1271_cmd_join { struct wl12xx_cmd_role_enable {
struct wl1271_cmd_header header; struct wl1271_cmd_header header;
__le32 bssid_lsb; u8 role_id;
__le16 bssid_msb; u8 role_type;
__le16 beacon_interval; /* in TBTTs */ u8 mac_address[ETH_ALEN];
__le32 rx_config_options; } __packed;
__le32 rx_filter_options;
struct wl12xx_cmd_role_disable {
struct wl1271_cmd_header header;
u8 role_id;
u8 padding[3];
} __packed;
enum wl12xx_band {
WL12XX_BAND_2_4GHZ = 0,
WL12XX_BAND_5GHZ = 1,
WL12XX_BAND_JAPAN_4_9_GHZ = 2,
WL12XX_BAND_DEFAULT = WL12XX_BAND_2_4GHZ,
WL12XX_BAND_INVALID = 0x7E,
WL12XX_BAND_MAX_RADIO = 0x7F,
};
struct wl12xx_cmd_role_start {
struct wl1271_cmd_header header;
u8 role_id;
u8 band;
u8 channel;
u8 padding;
union {
struct {
u8 hlid;
u8 session;
u8 padding_1[54];
} __packed device;
/* sta & p2p_cli use the same struct */
struct {
u8 bssid[ETH_ALEN];
u8 hlid; /* data hlid */
u8 session;
__le32 remote_rates; /* remote supported rates */
/* /*
* The target uses this field to determine the rate at * The target uses this field to determine the rate at
@ -225,23 +278,63 @@ struct wl1271_cmd_join {
* ACK or CTS frames). * ACK or CTS frames).
*/ */
__le32 basic_rate_set; __le32 basic_rate_set;
__le32 supported_rate_set; __le32 local_rates; /* local supported rates */
u8 dtim_interval;
/* u8 ssid_type;
* bits 0-2: This bitwise field specifies the type
* of BSS to start or join (BSS_TYPE_*).
* bit 4: Band - The radio band in which to join
* or start.
* 0 - 2.4GHz band
* 1 - 5GHz band
* bits 3, 5-7: Reserved
*/
u8 bss_type;
u8 channel;
u8 ssid_len; u8 ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ctrl; /* JOIN_CMD_CTRL_* */
u8 reserved[3]; __le16 beacon_interval; /* in TBTTs */
} __packed sta;
struct {
u8 bssid[ETH_ALEN];
u8 hlid; /* data hlid */
u8 dtim_interval;
__le32 remote_rates; /* remote supported rates */
__le32 basic_rate_set;
__le32 local_rates; /* local supported rates */
u8 ssid_type;
u8 ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
__le16 beacon_interval; /* in TBTTs */
u8 padding_1[4];
} __packed ibss;
/* ap & p2p_go use the same struct */
struct {
__le16 aging_period; /* in secs */
u8 beacon_expiry; /* in ms */
u8 bss_index;
/* The host link id for the AP's global queue */
u8 global_hlid;
/* The host link id for the AP's broadcast queue */
u8 broadcast_hlid;
__le16 beacon_interval; /* in TBTTs */
__le32 basic_rate_set;
__le32 local_rates; /* local supported rates */
u8 dtim_interval;
u8 ssid_type;
u8 ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 padding_1[5];
} __packed ap;
};
} __packed;
struct wl12xx_cmd_role_stop {
struct wl1271_cmd_header header;
u8 role_id;
u8 disc_type; /* only STA and P2P_CLI */
__le16 reason; /* only STA and P2P_CLI */
} __packed; } __packed;
struct cmd_enabledisable_path { struct cmd_enabledisable_path {
@ -287,8 +380,9 @@ enum wl1271_cmd_ps_mode {
struct wl1271_cmd_ps_params { struct wl1271_cmd_ps_params {
struct wl1271_cmd_header header; struct wl1271_cmd_header header;
u8 role_id;
u8 ps_mode; /* STATION_* */ u8 ps_mode; /* STATION_* */
u8 padding[3]; u8 padding[2];
} __packed; } __packed;
/* HW encryption keys */ /* HW encryption keys */
@ -301,6 +395,12 @@ enum wl1271_cmd_key_action {
MAX_KEY_ACTION = 0xffff, MAX_KEY_ACTION = 0xffff,
}; };
enum wl1271_cmd_lid_key_type {
UNICAST_LID_TYPE = 0,
BROADCAST_LID_TYPE = 1,
WEP_DEFAULT_LID_TYPE = 2
};
enum wl1271_cmd_key_type { enum wl1271_cmd_key_type {
KEY_NONE = 0, KEY_NONE = 0,
KEY_WEP = 1, KEY_WEP = 1,
@ -309,44 +409,7 @@ enum wl1271_cmd_key_type {
KEY_GEM = 4, KEY_GEM = 4,
}; };
/* FIXME: Add description for key-types */ struct wl1271_cmd_set_keys {
struct wl1271_cmd_set_sta_keys {
struct wl1271_cmd_header header;
/* Ignored for default WEP key */
u8 addr[ETH_ALEN];
/* key_action_e */
__le16 key_action;
__le16 reserved_1;
/* key size in bytes */
u8 key_size;
/* key_type_e */
u8 key_type;
u8 ssid_profile;
/*
* TKIP, AES: frame's key id field.
* For WEP default key: key id;
*/
u8 id;
u8 reserved_2[6];
u8 key[MAX_KEY_SIZE];
__le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
__le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
} __packed;
enum wl1271_cmd_lid_key_type {
UNICAST_LID_TYPE = 0,
BROADCAST_LID_TYPE = 1,
WEP_DEFAULT_LID_TYPE = 2
};
struct wl1271_cmd_set_ap_keys {
struct wl1271_cmd_header header; struct wl1271_cmd_header header;
/* /*
@ -496,69 +559,39 @@ enum wl1271_disconnect_type {
DISCONNECT_DISASSOC DISCONNECT_DISASSOC
}; };
struct wl1271_cmd_disconnect {
struct wl1271_cmd_header header;
__le32 rx_config_options;
__le32 rx_filter_options;
__le16 reason;
u8 type;
u8 padding;
} __packed;
#define WL1271_CMD_STA_STATE_CONNECTED 1 #define WL1271_CMD_STA_STATE_CONNECTED 1
struct wl1271_cmd_set_sta_state { struct wl12xx_cmd_set_peer_state {
struct wl1271_cmd_header header; struct wl1271_cmd_header header;
u8 hlid;
u8 state; u8 state;
u8 padding[3]; u8 padding[2];
} __packed; } __packed;
enum wl1271_ssid_type { struct wl12xx_cmd_roc {
SSID_TYPE_PUBLIC = 0, struct wl1271_cmd_header header;
SSID_TYPE_HIDDEN = 1
u8 role_id;
u8 channel;
u8 band;
u8 padding;
}; };
struct wl1271_cmd_bss_start { struct wl12xx_cmd_croc {
struct wl1271_cmd_header header; struct wl1271_cmd_header header;
/* wl1271_ssid_type */ u8 role_id;
u8 ssid_type; u8 padding[3];
u8 ssid_len; };
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 padding_1[2];
/* Basic rate set */ enum wl12xx_ssid_type {
__le32 basic_rate_set; WL12XX_SSID_TYPE_PUBLIC = 0,
/* Aging period in seconds*/ WL12XX_SSID_TYPE_HIDDEN = 1,
__le16 aging_period; WL12XX_SSID_TYPE_ANY = 2,
};
/* struct wl12xx_cmd_add_peer {
* This field specifies the time between target beacon
* transmission times (TBTTs), in time units (TUs).
* Valid values are 1 to 1024.
*/
__le16 beacon_interval;
u8 bssid[ETH_ALEN];
u8 bss_index;
/* Radio band */
u8 band;
u8 channel;
/* The host link id for the AP's global queue */
u8 global_hlid;
/* The host link id for the AP's broadcast queue */
u8 broadcast_hlid;
/* DTIM count */
u8 dtim_interval;
/* Beacon expiry time in ms */
u8 beacon_expiry;
u8 padding_2[3];
} __packed;
struct wl1271_cmd_add_sta {
struct wl1271_cmd_header header; struct wl1271_cmd_header header;
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
@ -572,7 +605,7 @@ struct wl1271_cmd_add_sta {
u8 padding1; u8 padding1;
} __packed; } __packed;
struct wl1271_cmd_remove_sta { struct wl12xx_cmd_remove_peer {
struct wl1271_cmd_header header; struct wl1271_cmd_header header;
u8 hlid; u8 hlid;

View file

@ -99,40 +99,75 @@ enum {
enum { enum {
/* /*
* PER threshold in PPM of the BT voice * Configure the min and max time BT gains the antenna
* in WLAN / BT master basic rate
* *
* Range: 0 - 10000000 * Range: 0 - 255 (ms)
*/ */
CONF_SG_BT_PER_THRESHOLD = 0, CONF_SG_ACL_BT_MASTER_MIN_BR = 0,
CONF_SG_ACL_BT_MASTER_MAX_BR,
/* /*
* Number of consequent RX_ACTIVE activities to override BT voice * Configure the min and max time BT gains the antenna
* frames to ensure WLAN connection * in WLAN / BT slave basic rate
* *
* Range: 0 - 100 * Range: 0 - 255 (ms)
*/ */
CONF_SG_HV3_MAX_OVERRIDE, CONF_SG_ACL_BT_SLAVE_MIN_BR,
CONF_SG_ACL_BT_SLAVE_MAX_BR,
/* /*
* Defines the PER threshold of the BT voice * Configure the min and max time BT gains the antenna
* in WLAN / BT master EDR
* *
* Range: 0 - 65000 * Range: 0 - 255 (ms)
*/ */
CONF_SG_BT_NFS_SAMPLE_INTERVAL, CONF_SG_ACL_BT_MASTER_MIN_EDR,
CONF_SG_ACL_BT_MASTER_MAX_EDR,
/* /*
* Defines the load ratio of BT * Configure the min and max time BT gains the antenna
* in WLAN / BT slave EDR
* *
* Range: 0 - 100 (%) * Range: 0 - 255 (ms)
*/ */
CONF_SG_BT_LOAD_RATIO, CONF_SG_ACL_BT_SLAVE_MIN_EDR,
CONF_SG_ACL_BT_SLAVE_MAX_EDR,
/* /*
* Defines whether the SG will force WLAN host to enter/exit PSM * The maximum time WLAN can gain the antenna
* in WLAN PSM / BT master/slave BR
* *
* Range: 1 - SG can force, 0 - host handles PSM * Range: 0 - 255 (ms)
*/ */
CONF_SG_AUTO_PS_MODE, CONF_SG_ACL_WLAN_PS_MASTER_BR,
CONF_SG_ACL_WLAN_PS_SLAVE_BR,
/*
* The maximum time WLAN can gain the antenna
* in WLAN PSM / BT master/slave EDR
*
* Range: 0 - 255 (ms)
*/
CONF_SG_ACL_WLAN_PS_MASTER_EDR,
CONF_SG_ACL_WLAN_PS_SLAVE_EDR,
/* TODO: explain these values */
CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR,
CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR,
CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR,
CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR,
CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR,
CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR,
CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR,
CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR,
CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR,
CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR,
CONF_SG_ACL_PASSIVE_SCAN_BT_BR,
CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR,
CONF_SG_ACL_PASSIVE_SCAN_BT_EDR,
CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR,
/* /*
* Compensation percentage of probe requests when scan initiated * Compensation percentage of probe requests when scan initiated
@ -150,6 +185,50 @@ enum {
*/ */
CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3, CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3,
/*
* Compensation percentage of WLAN active scan window if initiated
* during BT A2DP
*
* Range: 0 - 1000 (%)
*/
CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
/*
* Compensation percentage of WLAN passive scan window if initiated
* during BT A2DP BR
*
* Range: 0 - 1000 (%)
*/
CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR,
/*
* Compensation percentage of WLAN passive scan window if initiated
* during BT A2DP EDR
*
* Range: 0 - 1000 (%)
*/
CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR,
/*
* Compensation percentage of WLAN passive scan window if initiated
* during BT voice
*
* Range: 0 - 1000 (%)
*/
CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
/* TODO: explain these values */
CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN,
CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN,
CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN,
/*
* Defines whether the SG will force WLAN host to enter/exit PSM
*
* Range: 1 - SG can force, 0 - host handles PSM
*/
CONF_SG_STA_FORCE_PS_IN_BT_SCO,
/* /*
* Defines antenna configuration (single/dual antenna) * Defines antenna configuration (single/dual antenna)
* *
@ -158,7 +237,7 @@ enum {
CONF_SG_ANTENNA_CONFIGURATION, CONF_SG_ANTENNA_CONFIGURATION,
/* /*
* The threshold (percent) of max consequtive beacon misses before * The threshold (percent) of max consecutive beacon misses before
* increasing priority of beacon reception. * increasing priority of beacon reception.
* *
* Range: 0 - 100 (%) * Range: 0 - 100 (%)
@ -166,87 +245,11 @@ enum {
CONF_SG_BEACON_MISS_PERCENT, CONF_SG_BEACON_MISS_PERCENT,
/* /*
* The rate threshold below which receiving a data frame from the AP * Protection time of the DHCP procedure.
* will increase the priority of the data frame above BT traffic.
* *
* Range: 0,2, 5(=5.5), 6, 9, 11, 12, 18, 24, 36, 48, 54 * Range: 0 - 100000 (ms)
*/ */
CONF_SG_RATE_ADAPT_THRESH, CONF_SG_DHCP_TIME,
/*
* Not used currently.
*
* Range: 0
*/
CONF_SG_RATE_ADAPT_SNR,
/*
* Configure the min and max time BT gains the antenna
* in WLAN PSM / BT master basic rate
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR,
CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR,
/*
* The time after it expires no new WLAN trigger frame is trasmitted
* in WLAN PSM / BT master basic rate
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR,
/*
* Configure the min and max time BT gains the antenna
* in WLAN PSM / BT slave basic rate
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR,
CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR,
/*
* The time after it expires no new WLAN trigger frame is trasmitted
* in WLAN PSM / BT slave basic rate
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR,
/*
* Configure the min and max time BT gains the antenna
* in WLAN PSM / BT master EDR
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR,
CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR,
/*
* The time after it expires no new WLAN trigger frame is trasmitted
* in WLAN PSM / BT master EDR
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR,
/*
* Configure the min and max time BT gains the antenna
* in WLAN PSM / BT slave EDR
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR,
CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR,
/*
* The time after it expires no new WLAN trigger frame is trasmitted
* in WLAN PSM / BT slave EDR
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR,
/* /*
* RX guard time before the beginning of a new BT voice frame during * RX guard time before the beginning of a new BT voice frame during
@ -273,6 +276,16 @@ enum {
*/ */
CONF_SG_ADAPTIVE_RXT_TXT, CONF_SG_ADAPTIVE_RXT_TXT,
/* TODO: explain this value */
CONF_SG_GENERAL_USAGE_BIT_MAP,
/*
* Number of consecutive BT voice frames not interrupted by WLAN
*
* Range: 0 - 100
*/
CONF_SG_HV3_MAX_SERVED,
/* /*
* The used WLAN legacy service period during active BT ACL link * The used WLAN legacy service period during active BT ACL link
* *
@ -287,152 +300,35 @@ enum {
*/ */
CONF_SG_UPSD_TIMEOUT, CONF_SG_UPSD_TIMEOUT,
/* CONF_SG_CONSECUTIVE_CTS_THRESHOLD,
* Configure the min and max time BT gains the antenna CONF_SG_STA_RX_WINDOW_AFTER_DTIM,
* in WLAN Active / BT master EDR CONF_SG_STA_CONNECTION_PROTECTION_TIME,
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR,
CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR,
/* /* AP params */
* The maximum time WLAN can gain the antenna for CONF_AP_BEACON_MISS_TX,
* in WLAN Active / BT master EDR CONF_AP_RX_WINDOW_AFTER_BEACON,
* CONF_AP_BEACON_WINDOW_INTERVAL,
* Range: 0 - 255 (ms) CONF_AP_CONNECTION_PROTECTION_TIME,
*/ CONF_AP_BT_ACL_VAL_BT_SERVE_TIME,
CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR, CONF_AP_BT_ACL_VAL_WL_SERVE_TIME,
/*
* Configure the min and max time BT gains the antenna
* in WLAN Active / BT slave EDR
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR,
CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR,
/*
* The maximum time WLAN can gain the antenna for
* in WLAN Active / BT slave EDR
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR,
/*
* Configure the min and max time BT gains the antenna
* in WLAN Active / BT basic rate
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR,
CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR,
/*
* The maximum time WLAN can gain the antenna for
* in WLAN Active / BT basic rate
*
* Range: 0 - 255 (ms)
*/
CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR,
/*
* Compensation percentage of WLAN passive scan window if initiated
* during BT voice
*
* Range: 0 - 1000 (%)
*/
CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
/*
* Compensation percentage of WLAN passive scan window if initiated
* during BT A2DP
*
* Range: 0 - 1000 (%)
*/
CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP,
/*
* Fixed time ensured for BT traffic to gain the antenna during WLAN
* passive scan.
*
* Range: 0 - 1000 ms
*/
CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME,
/*
* Fixed time ensured for WLAN traffic to gain the antenna during WLAN
* passive scan.
*
* Range: 0 - 1000 ms
*/
CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME,
/*
* Number of consequent BT voice frames not interrupted by WLAN
*
* Range: 0 - 100
*/
CONF_SG_HV3_MAX_SERVED,
/*
* Protection time of the DHCP procedure.
*
* Range: 0 - 100000 (ms)
*/
CONF_SG_DHCP_TIME,
/*
* Compensation percentage of WLAN active scan window if initiated
* during BT A2DP
*
* Range: 0 - 1000 (%)
*/
CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
CONF_SG_TEMP_PARAM_1, CONF_SG_TEMP_PARAM_1,
CONF_SG_TEMP_PARAM_2, CONF_SG_TEMP_PARAM_2,
CONF_SG_TEMP_PARAM_3, CONF_SG_TEMP_PARAM_3,
CONF_SG_TEMP_PARAM_4, CONF_SG_TEMP_PARAM_4,
CONF_SG_TEMP_PARAM_5, CONF_SG_TEMP_PARAM_5,
/*
* AP beacon miss
*
* Range: 0 - 255
*/
CONF_SG_AP_BEACON_MISS_TX,
/*
* AP RX window length
*
* Range: 0 - 50
*/
CONF_SG_RX_WINDOW_LENGTH,
/*
* AP connection protection time
*
* Range: 0 - 5000
*/
CONF_SG_AP_CONNECTION_PROTECTION_TIME,
CONF_SG_TEMP_PARAM_6, CONF_SG_TEMP_PARAM_6,
CONF_SG_TEMP_PARAM_7, CONF_SG_TEMP_PARAM_7,
CONF_SG_TEMP_PARAM_8, CONF_SG_TEMP_PARAM_8,
CONF_SG_TEMP_PARAM_9, CONF_SG_TEMP_PARAM_9,
CONF_SG_TEMP_PARAM_10, CONF_SG_TEMP_PARAM_10,
CONF_SG_STA_PARAMS_MAX = CONF_SG_TEMP_PARAM_5 + 1, CONF_SG_PARAMS_MAX,
CONF_SG_AP_PARAMS_MAX = CONF_SG_TEMP_PARAM_10 + 1,
CONF_SG_PARAMS_ALL = 0xff CONF_SG_PARAMS_ALL = 0xff
}; };
struct conf_sg_settings { struct conf_sg_settings {
u32 sta_params[CONF_SG_STA_PARAMS_MAX]; u32 params[CONF_SG_PARAMS_MAX];
u32 ap_params[CONF_SG_AP_PARAMS_MAX];
u8 state; u8 state;
}; };
@ -545,6 +441,11 @@ struct conf_rx_settings {
CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \
CONF_HW_BIT_RATE_54MBPS) CONF_HW_BIT_RATE_54MBPS)
#define CONF_TX_MCS_RATES (CONF_HW_BIT_RATE_MCS_0 | \
CONF_HW_BIT_RATE_MCS_1 | CONF_HW_BIT_RATE_MCS_2 | \
CONF_HW_BIT_RATE_MCS_3 | CONF_HW_BIT_RATE_MCS_4 | \
CONF_HW_BIT_RATE_MCS_5 | CONF_HW_BIT_RATE_MCS_6 | \
CONF_HW_BIT_RATE_MCS_7)
/* /*
* Default rates for management traffic when operating in AP mode. This * Default rates for management traffic when operating in AP mode. This
@ -661,6 +562,9 @@ struct conf_tx_ac_category {
#define CONF_TX_MAX_TID_COUNT 8 #define CONF_TX_MAX_TID_COUNT 8
/* Allow TX BA on all TIDs but 6,7. These are currently reserved in the FW */
#define CONF_TX_BA_ENABLED_TID_BITMAP 0x3F
enum { enum {
CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/ CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/
CONF_CHANNEL_TYPE_EDCF = 1, /* EDCA*/ CONF_CHANNEL_TYPE_EDCF = 1, /* EDCA*/
@ -913,7 +817,7 @@ struct conf_conn_settings {
struct conf_bcn_filt_rule bcn_filt_ie[CONF_MAX_BCN_FILT_IE_COUNT]; struct conf_bcn_filt_rule bcn_filt_ie[CONF_MAX_BCN_FILT_IE_COUNT];
/* /*
* The number of consequtive beacons to lose, before the firmware * The number of consecutive beacons to lose, before the firmware
* becomes out of synch. * becomes out of synch.
* *
* Range: u32 * Range: u32
@ -951,7 +855,7 @@ struct conf_conn_settings {
u8 rx_broadcast_in_ps; u8 rx_broadcast_in_ps;
/* /*
* Consequtive PS Poll failures before sending event to driver * Consecutive PS Poll failures before sending event to driver
* *
* Range: u8 * Range: u8
*/ */
@ -1199,8 +1103,12 @@ struct conf_rf_settings {
}; };
struct conf_ht_setting { struct conf_ht_setting {
u16 tx_ba_win_size; u8 rx_ba_win_size;
u8 tx_ba_win_size;
u16 inactivity_timeout; u16 inactivity_timeout;
/* bitmap of enabled TIDs for TX BA sessions */
u8 tx_ba_tid_bitmap;
}; };
struct conf_memory_settings { struct conf_memory_settings {
@ -1309,6 +1217,25 @@ struct conf_fwlog {
u8 threshold; u8 threshold;
}; };
#define ACX_RATE_MGMT_NUM_OF_RATES 13
struct conf_rate_policy_settings {
u16 rate_retry_score;
u16 per_add;
u16 per_th1;
u16 per_th2;
u16 max_per;
u8 inverse_curiosity_factor;
u8 tx_fail_low_th;
u8 tx_fail_high_th;
u8 per_alpha_shift;
u8 per_add_shift;
u8 per_beta1_shift;
u8 per_beta2_shift;
u8 rate_check_up;
u8 rate_check_down;
u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES];
};
struct conf_drv_settings { struct conf_drv_settings {
struct conf_sg_settings sg; struct conf_sg_settings sg;
struct conf_rx_settings rx; struct conf_rx_settings rx;
@ -1326,6 +1253,7 @@ struct conf_drv_settings {
struct conf_fm_coex fm_coex; struct conf_fm_coex fm_coex;
struct conf_rx_streaming_settings rx_streaming; struct conf_rx_streaming_settings rx_streaming;
struct conf_fwlog fwlog; struct conf_fwlog fwlog;
struct conf_rate_policy_settings rate;
u8 hci_io_ds; u8 hci_io_ds;
}; };

View file

@ -339,10 +339,11 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
#define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x")
DRIVER_STATE_PRINT_INT(tx_blocks_available); DRIVER_STATE_PRINT_INT(tx_blocks_available);
DRIVER_STATE_PRINT_INT(tx_allocated_blocks[0]); DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
DRIVER_STATE_PRINT_INT(tx_allocated_blocks[1]); DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]);
DRIVER_STATE_PRINT_INT(tx_allocated_blocks[2]); DRIVER_STATE_PRINT_INT(tx_allocated_pkts[1]);
DRIVER_STATE_PRINT_INT(tx_allocated_blocks[3]); DRIVER_STATE_PRINT_INT(tx_allocated_pkts[2]);
DRIVER_STATE_PRINT_INT(tx_allocated_pkts[3]);
DRIVER_STATE_PRINT_INT(tx_frames_cnt); DRIVER_STATE_PRINT_INT(tx_frames_cnt);
DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
DRIVER_STATE_PRINT_INT(tx_queue_count[0]); DRIVER_STATE_PRINT_INT(tx_queue_count[0]);
@ -352,10 +353,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT(tx_packets_count); DRIVER_STATE_PRINT_INT(tx_packets_count);
DRIVER_STATE_PRINT_INT(tx_results_count); DRIVER_STATE_PRINT_INT(tx_results_count);
DRIVER_STATE_PRINT_LHEX(flags); DRIVER_STATE_PRINT_LHEX(flags);
DRIVER_STATE_PRINT_INT(tx_blocks_freed[0]); DRIVER_STATE_PRINT_INT(tx_blocks_freed);
DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]);
DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]);
DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]);
DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb); DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb);
DRIVER_STATE_PRINT_INT(rx_counter); DRIVER_STATE_PRINT_INT(rx_counter);
DRIVER_STATE_PRINT_INT(session_counter); DRIVER_STATE_PRINT_INT(session_counter);
@ -369,9 +367,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT(beacon_int); DRIVER_STATE_PRINT_INT(beacon_int);
DRIVER_STATE_PRINT_INT(psm_entry_retry); DRIVER_STATE_PRINT_INT(psm_entry_retry);
DRIVER_STATE_PRINT_INT(ps_poll_failures); DRIVER_STATE_PRINT_INT(ps_poll_failures);
DRIVER_STATE_PRINT_HEX(filters);
DRIVER_STATE_PRINT_HEX(rx_config);
DRIVER_STATE_PRINT_HEX(rx_filter);
DRIVER_STATE_PRINT_INT(power_level); DRIVER_STATE_PRINT_INT(power_level);
DRIVER_STATE_PRINT_INT(rssi_thold); DRIVER_STATE_PRINT_INT(rssi_thold);
DRIVER_STATE_PRINT_INT(last_rssi_event); DRIVER_STATE_PRINT_INT(last_rssi_event);

View file

@ -285,13 +285,13 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) { if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) {
wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
"ba_allowed = 0x%x", mbox->ba_allowed); "ba_allowed = 0x%x", mbox->rx_ba_allowed);
if (wl->vif) if (wl->vif)
wl1271_stop_ba_event(wl, mbox->ba_allowed); wl1271_stop_ba_event(wl, mbox->rx_ba_allowed);
} }
if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) { if ((vector & DUMMY_PACKET_EVENT_ID)) {
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
if (wl->vif) if (wl->vif)
wl1271_tx_dummy_packet(wl); wl1271_tx_dummy_packet(wl);

View file

@ -49,32 +49,27 @@ enum {
MEASUREMENT_START_EVENT_ID = BIT(8), MEASUREMENT_START_EVENT_ID = BIT(8),
MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), MEASUREMENT_COMPLETE_EVENT_ID = BIT(9),
SCAN_COMPLETE_EVENT_ID = BIT(10), SCAN_COMPLETE_EVENT_ID = BIT(10),
SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(11), WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11),
AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12), AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12),
PS_REPORT_EVENT_ID = BIT(13), PS_REPORT_EVENT_ID = BIT(13),
PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14), PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14),
DISCONNECT_EVENT_COMPLETE_ID = BIT(15), DISCONNECT_EVENT_COMPLETE_ID = BIT(15),
JOIN_EVENT_COMPLETE_ID = BIT(16), /* BIT(16) is reserved */
CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
BSS_LOSE_EVENT_ID = BIT(18), BSS_LOSE_EVENT_ID = BIT(18),
REGAINED_BSS_EVENT_ID = BIT(19), REGAINED_BSS_EVENT_ID = BIT(19),
MAX_TX_RETRY_EVENT_ID = BIT(20), MAX_TX_RETRY_EVENT_ID = BIT(20),
/* STA: dummy paket for dynamic mem blocks */
DUMMY_PACKET_EVENT_ID = BIT(21), DUMMY_PACKET_EVENT_ID = BIT(21),
/* AP: STA remove complete */
STA_REMOVE_COMPLETE_EVENT_ID = BIT(21),
SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
/* STA: SG prediction */ CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID = BIT(23),
SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
/* AP: Inactive STA */
INACTIVE_STA_EVENT_ID = BIT(23),
SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25),
DBG_EVENT_ID = BIT(26), INACTIVE_STA_EVENT_ID = BIT(26),
HEALTH_CHECK_REPLY_EVENT_ID = BIT(27), PEER_REMOVE_COMPLETE_EVENT_ID = BIT(27),
PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28), PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28),
PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29), PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29),
BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30), BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30),
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(31),
EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff, EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff,
}; };
@ -83,15 +78,6 @@ enum {
EVENT_ENTER_POWER_SAVE_SUCCESS, EVENT_ENTER_POWER_SAVE_SUCCESS,
}; };
struct event_debug_report {
u8 debug_event_id;
u8 num_params;
__le16 pad;
__le32 report_1;
__le32 report_2;
__le32 report_3;
} __packed;
#define NUM_OF_RSSI_SNR_TRIGGERS 8 #define NUM_OF_RSSI_SNR_TRIGGERS 8
struct event_mailbox { struct event_mailbox {
@ -100,49 +86,45 @@ struct event_mailbox {
__le32 reserved_1; __le32 reserved_1;
__le32 reserved_2; __le32 reserved_2;
u8 dbg_event_id;
u8 num_relevant_params;
__le16 reserved_3;
__le32 event_report_p1;
__le32 event_report_p2;
__le32 event_report_p3;
u8 number_of_scan_results; u8 number_of_scan_results;
u8 scan_tag; u8 scan_tag;
u8 reserved_4[2]; u8 completed_scan_status;
__le32 compl_scheduled_scan_status; u8 reserved_3;
__le16 scheduled_scan_attended_channels;
u8 soft_gemini_sense_info; u8 soft_gemini_sense_info;
u8 soft_gemini_protective_info; u8 soft_gemini_protective_info;
s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
u8 channel_switch_status; u8 channel_switch_status;
u8 scheduled_scan_status; u8 scheduled_scan_status;
u8 ps_status; u8 ps_status;
/* tuned channel (roc) */
u8 roc_channel;
/* AP FW only */ __le16 hlid_removed_bitmap;
u8 hlid_removed;
/* a bitmap of hlids for stations that have been inactive too long */ /* bitmap of aged stations (by HLID) */
__le16 sta_aging_status; __le16 sta_aging_status;
/* a bitmap of hlids for stations which didn't respond to TX */ /* bitmap of stations (by HLID) which exceeded max tx retries */
__le16 sta_tx_retry_exceeded; __le16 sta_tx_retry_exceeded;
/* /* discovery completed results */
* Bitmap, Each bit set represents the Role ID for which this constraint u8 discovery_tag;
* is set. Range: 0 - FF, FF means ANY role u8 number_of_preq_results;
*/ u8 number_of_prsp_results;
u8 ba_role_id; u8 reserved_5;
/*
* Bitmap, Each bit set represents the Link ID for which this constraint
* is set. Not applicable if ba_role_id is set to ANY role (FF).
* Range: 0 - FFFF, FFFF means ANY link in that role
*/
u8 ba_link_id;
u8 ba_allowed;
u8 reserved_5[21]; /* rx ba constraint */
u8 role_id; /* 0xFF means any role. */
u8 rx_ba_allowed;
u8 reserved_6[2];
u8 ps_poll_delivery_failure_role_ids;
u8 stopped_role_ids;
u8 started_role_ids;
u8 change_auto_mode_timeout;
u8 reserved_7[12];
} __packed; } __packed;
int wl1271_event_unmask(struct wl1271 *wl); int wl1271_event_unmask(struct wl1271 *wl);

View file

@ -39,13 +39,13 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
/* send empty templates for fw memory reservation */ /* send empty templates for fw memory reservation */
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
WL1271_CMD_TEMPL_MAX_SIZE, WL1271_CMD_TEMPL_DFLT_SIZE,
0, WL1271_RATE_AUTOMATIC); 0, WL1271_RATE_AUTOMATIC);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0, NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0,
WL1271_RATE_AUTOMATIC); WL1271_RATE_AUTOMATIC);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -70,15 +70,13 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
return ret; return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
sizeof WL1271_CMD_TEMPL_DFLT_SIZE,
(struct wl12xx_probe_resp_template),
0, WL1271_RATE_AUTOMATIC); 0, WL1271_RATE_AUTOMATIC);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
sizeof WL1271_CMD_TEMPL_DFLT_SIZE,
(struct wl12xx_beacon_template),
0, WL1271_RATE_AUTOMATIC); 0, WL1271_RATE_AUTOMATIC);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -92,7 +90,7 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
WL1271_CMD_TEMPL_MAX_SIZE, i, WL1271_CMD_TEMPL_DFLT_SIZE, i,
WL1271_RATE_AUTOMATIC); WL1271_RATE_AUTOMATIC);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -191,15 +189,13 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl)
* reserve memory for later. * reserve memory for later.
*/ */
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
sizeof WL1271_CMD_TEMPL_MAX_SIZE,
(struct wl12xx_probe_resp_template),
0, WL1271_RATE_AUTOMATIC); 0, WL1271_RATE_AUTOMATIC);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
sizeof WL1271_CMD_TEMPL_MAX_SIZE,
(struct wl12xx_beacon_template),
0, WL1271_RATE_AUTOMATIC); 0, WL1271_RATE_AUTOMATIC);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -227,7 +223,7 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl)
return 0; return 0;
} }
static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) static int wl12xx_init_rx_config(struct wl1271 *wl)
{ {
int ret; int ret;
@ -235,10 +231,6 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = wl1271_acx_rx_config(wl, config, filter);
if (ret < 0)
return ret;
return 0; return 0;
} }
@ -285,10 +277,7 @@ int wl1271_init_pta(struct wl1271 *wl)
{ {
int ret; int ret;
if (wl->bss_type == BSS_TYPE_AP_BSS) ret = wl12xx_acx_sg_cfg(wl);
ret = wl1271_acx_ap_sg_cfg(wl);
else
ret = wl1271_acx_sta_sg_cfg(wl);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -392,7 +381,7 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = wl1271_acx_sta_mem_cfg(wl); ret = wl12xx_acx_mem_cfg(wl);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -408,12 +397,6 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
{ {
int ret, i; int ret, i;
ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
if (ret < 0) {
wl1271_warning("couldn't set default key");
return ret;
}
/* disable all keep-alive templates */ /* disable all keep-alive templates */
for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
ret = wl1271_acx_keep_alive_config(wl, i, ret = wl1271_acx_keep_alive_config(wl, i,
@ -451,7 +434,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = wl1271_acx_ap_mem_cfg(wl); ret = wl12xx_acx_mem_cfg(wl);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -483,7 +466,7 @@ int wl1271_ap_init_templates(struct wl1271 *wl)
* when operating as AP we want to receive external beacons for * when operating as AP we want to receive external beacons for
* configuring ERP protection. * configuring ERP protection.
*/ */
ret = wl1271_acx_set_ap_beacon_filter(wl, false); ret = wl1271_acx_beacon_filter_opt(wl, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -532,6 +515,9 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
else else
supported_rates = CONF_TX_AP_ENABLED_RATES; supported_rates = CONF_TX_AP_ENABLED_RATES;
/* unconditionally enable HT rates */
supported_rates |= CONF_TX_MCS_RATES;
/* configure unicast TX rate classes */ /* configure unicast TX rate classes */
for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
rc.enabled_rates = supported_rates; rc.enabled_rates = supported_rates;
@ -546,41 +532,24 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
return 0; return 0;
} }
static void wl1271_check_ba_support(struct wl1271 *wl)
{
/* validate FW cose ver x.x.x.50-60.x */
if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
(wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
wl->ba_support = true;
return;
}
wl->ba_support = false;
}
static int wl1271_set_ba_policies(struct wl1271 *wl) static int wl1271_set_ba_policies(struct wl1271 *wl)
{ {
u8 tid_index;
int ret = 0;
/* Reset the BA RX indicators */ /* Reset the BA RX indicators */
wl->ba_rx_bitmap = 0; wl->ba_rx_bitmap = 0;
wl->ba_allowed = true; wl->ba_allowed = true;
wl->ba_rx_session_count = 0;
/* validate that FW support BA */ /* BA is supported in STA/AP modes */
wl1271_check_ba_support(wl); if (wl->bss_type != BSS_TYPE_AP_BSS &&
wl->bss_type != BSS_TYPE_STA_BSS) {
if (wl->ba_support) wl->ba_support = false;
/* 802.11n initiator BA session setting */ return 0;
for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
++tid_index) {
ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
tid_index, true);
if (ret < 0)
break;
} }
return ret; wl->ba_support = true;
/* 802.11n initiator BA session setting */
return wl12xx_acx_set_ba_initiator_policy(wl);
} }
int wl1271_chip_specific_init(struct wl1271 *wl) int wl1271_chip_specific_init(struct wl1271 *wl)
@ -650,11 +619,7 @@ int wl1271_hw_init(struct wl1271 *wl)
return ret; return ret;
/* RX config */ /* RX config */
ret = wl1271_init_rx_config(wl, ret = wl12xx_init_rx_config(wl);
RX_CFG_PROMISCUOUS | RX_CFG_TSF,
RX_FILTER_OPTION_DEF);
/* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
RX_FILTER_OPTION_FILTER_ALL); */
if (ret < 0) if (ret < 0)
goto out_free_memmap; goto out_free_memmap;
@ -733,6 +698,10 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
goto out_free_memmap; goto out_free_memmap;
ret = wl12xx_acx_set_rate_mgmt_params(wl);
if (ret < 0)
goto out_free_memmap;
/* Configure initiator BA sessions policies */ /* Configure initiator BA sessions policies */
ret = wl1271_set_ba_policies(wl); ret = wl1271_set_ba_policies(wl);
if (ret < 0) if (ret < 0)

View file

@ -186,6 +186,5 @@ int wl1271_free_hw(struct wl1271 *wl);
irqreturn_t wl1271_irq(int irq, void *data); irqreturn_t wl1271_irq(int irq, void *data);
bool wl1271_set_block_size(struct wl1271 *wl); bool wl1271_set_block_size(struct wl1271 *wl);
int wl1271_tx_dummy_packet(struct wl1271 *wl); int wl1271_tx_dummy_packet(struct wl1271 *wl);
void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters);
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -226,8 +226,8 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
if (test_bit(hlid, &wl->ap_ps_map)) if (test_bit(hlid, &wl->ap_ps_map))
return; return;
wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d blks %d " wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d pkts %d "
"clean_queues %d", hlid, wl->links[hlid].allocated_blks, "clean_queues %d", hlid, wl->links[hlid].allocated_pkts,
clean_queues); clean_queues);
rcu_read_lock(); rcu_read_lock();

View file

@ -296,81 +296,6 @@
===============================================*/ ===============================================*/
#define REG_EVENT_MAILBOX_PTR (SCR_PAD1) #define REG_EVENT_MAILBOX_PTR (SCR_PAD1)
/* Misc */
#define REG_ENABLE_TX_RX (ENABLE)
/*
* Rx configuration (filter) information element
* ---------------------------------------------
*/
#define REG_RX_CONFIG (RX_CFG)
#define REG_RX_FILTER (RX_FILTER_CFG)
#define RX_CFG_ENABLE_PHY_HEADER_PLCP 0x0002
/* promiscuous - receives all valid frames */
#define RX_CFG_PROMISCUOUS 0x0008
/* receives frames from any BSSID */
#define RX_CFG_BSSID 0x0020
/* receives frames destined to any MAC address */
#define RX_CFG_MAC 0x0010
#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC 0x0010
#define RX_CFG_ENABLE_ANY_DEST_MAC 0x0000
#define RX_CFG_ENABLE_ONLY_MY_BSSID 0x0020
#define RX_CFG_ENABLE_ANY_BSSID 0x0000
/* discards all broadcast frames */
#define RX_CFG_DISABLE_BCAST 0x0200
#define RX_CFG_ENABLE_ONLY_MY_SSID 0x0400
#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800
#define RX_CFG_COPY_RX_STATUS 0x2000
#define RX_CFG_TSF 0x10000
#define RX_CONFIG_OPTION_ANY_DST_MY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
RX_CFG_ENABLE_ONLY_MY_BSSID)
#define RX_CONFIG_OPTION_MY_DST_ANY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
| RX_CFG_ENABLE_ANY_BSSID)
#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
RX_CFG_ENABLE_ANY_BSSID)
#define RX_CONFIG_OPTION_MY_DST_MY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
| RX_CFG_ENABLE_ONLY_MY_BSSID)
#define RX_CONFIG_OPTION_FOR_SCAN (RX_CFG_ENABLE_PHY_HEADER_PLCP \
| RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \
| RX_CFG_COPY_RX_STATUS | RX_CFG_TSF)
#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC)
#define RX_CONFIG_OPTION_FOR_JOIN (RX_CFG_ENABLE_ONLY_MY_BSSID | \
RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
#define RX_CONFIG_OPTION_FOR_IBSS_JOIN (RX_CFG_ENABLE_ONLY_MY_SSID | \
RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
#define RX_FILTER_OPTION_DEF (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
| CFG_RX_CTL_EN | CFG_RX_BCN_EN\
| CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
#define RX_FILTER_OPTION_FILTER_ALL 0
#define RX_FILTER_OPTION_DEF_PRSP_BCN (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\
| CFG_RX_RCTS_ACK | CFG_RX_BCN_EN)
#define RX_FILTER_OPTION_JOIN (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
| CFG_RX_BCN_EN | CFG_RX_AUTH_EN\
| CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\
| CFG_RX_PRSP_EN)
/*=============================================== /*===============================================
EEPROM Read/Write Request 32bit RW EEPROM Read/Write Request 32bit RW
------------------------------------------ ------------------------------------------

View file

@ -30,20 +30,28 @@
#include "rx.h" #include "rx.h"
#include "io.h" #include "io.h"
static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status, static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status,
u32 drv_rx_counter) u32 drv_rx_counter)
{ {
return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
RX_MEM_BLOCK_MASK; RX_MEM_BLOCK_MASK;
} }
static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status, static u32 wl12xx_rx_get_buf_size(struct wl12xx_fw_status *status,
u32 drv_rx_counter) u32 drv_rx_counter)
{ {
return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
} }
static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status,
u32 drv_rx_counter)
{
/* Convert the value to bool */
return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
RX_BUF_UNALIGNED_PAYLOAD);
}
static void wl1271_rx_status(struct wl1271 *wl, static void wl1271_rx_status(struct wl1271 *wl,
struct wl1271_rx_descriptor *desc, struct wl1271_rx_descriptor *desc,
struct ieee80211_rx_status *status, struct ieee80211_rx_status *status,
@ -89,7 +97,8 @@ static void wl1271_rx_status(struct wl1271 *wl,
} }
} }
static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
bool unaligned)
{ {
struct wl1271_rx_descriptor *desc; struct wl1271_rx_descriptor *desc;
struct sk_buff *skb; struct sk_buff *skb;
@ -97,6 +106,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
u8 *buf; u8 *buf;
u8 beacon = 0; u8 beacon = 0;
u8 is_data = 0; u8 is_data = 0;
u8 reserved = unaligned ? NET_IP_ALIGN : 0;
/* /*
* In PLT mode we seem to get frames and mac80211 warns about them, * In PLT mode we seem to get frames and mac80211 warns about them,
@ -131,17 +141,25 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
return -EINVAL; return -EINVAL;
} }
skb = __dev_alloc_skb(length, GFP_KERNEL); /* skb length not included rx descriptor */
skb = __dev_alloc_skb(length + reserved - sizeof(*desc), GFP_KERNEL);
if (!skb) { if (!skb) {
wl1271_error("Couldn't allocate RX frame"); wl1271_error("Couldn't allocate RX frame");
return -ENOMEM; return -ENOMEM;
} }
buf = skb_put(skb, length); /* reserve the unaligned payload(if any) */
memcpy(buf, data, length); skb_reserve(skb, reserved);
/* now we pull the descriptor out of the buffer */ buf = skb_put(skb, length - sizeof(*desc));
skb_pull(skb, sizeof(*desc));
/*
* Copy packets from aggregation buffer to the skbs without rx
* descriptor and with packet payload aligned care. In case of unaligned
* packets copy the packets in offset of 2 bytes guarantee IP header
* payload aligned to 4 bytes.
*/
memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_beacon(hdr->frame_control)) if (ieee80211_is_beacon(hdr->frame_control))
@ -163,7 +181,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
return is_data; return is_data;
} }
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
{ {
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
u32 buf_size; u32 buf_size;
@ -175,12 +193,13 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
u32 pkt_offset; u32 pkt_offset;
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
bool had_data = false; bool had_data = false;
bool unaligned = false;
while (drv_rx_counter != fw_rx_counter) { while (drv_rx_counter != fw_rx_counter) {
buf_size = 0; buf_size = 0;
rx_counter = drv_rx_counter; rx_counter = drv_rx_counter;
while (rx_counter != fw_rx_counter) { while (rx_counter != fw_rx_counter) {
pkt_length = wl1271_rx_get_buf_size(status, rx_counter); pkt_length = wl12xx_rx_get_buf_size(status, rx_counter);
if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE) if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
break; break;
buf_size += pkt_length; buf_size += pkt_length;
@ -199,7 +218,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
* For aggregated packets, only the first memory block * For aggregated packets, only the first memory block
* should be retrieved. The FW takes care of the rest. * should be retrieved. The FW takes care of the rest.
*/ */
mem_block = wl1271_rx_get_mem_block(status, mem_block = wl12xx_rx_get_mem_block(status,
drv_rx_counter); drv_rx_counter);
wl->rx_mem_pool_addr.addr = (mem_block << 8) + wl->rx_mem_pool_addr.addr = (mem_block << 8) +
@ -220,8 +239,12 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
/* Split data into separate packets */ /* Split data into separate packets */
pkt_offset = 0; pkt_offset = 0;
while (pkt_offset < buf_size) { while (pkt_offset < buf_size) {
pkt_length = wl1271_rx_get_buf_size(status, pkt_length = wl12xx_rx_get_buf_size(status,
drv_rx_counter); drv_rx_counter);
unaligned = wl12xx_rx_get_unaligned(status,
drv_rx_counter);
/* /*
* the handle data call can only fail in memory-outage * the handle data call can only fail in memory-outage
* conditions, in that case the received frame will just * conditions, in that case the received frame will just
@ -229,7 +252,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
*/ */
if (wl1271_rx_handle_data(wl, if (wl1271_rx_handle_data(wl,
wl->aggr_buf + pkt_offset, wl->aggr_buf + pkt_offset,
pkt_length) == 1) pkt_length, unaligned) == 1)
had_data = true; had_data = true;
wl->rx_counter++; wl->rx_counter++;
@ -260,14 +283,3 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
jiffies + msecs_to_jiffies(timeout)); jiffies + msecs_to_jiffies(timeout));
} }
} }
void wl1271_set_default_filters(struct wl1271 *wl)
{
if (wl->bss_type == BSS_TYPE_AP_BSS) {
wl->rx_config = WL1271_DEFAULT_AP_RX_CONFIG;
wl->rx_filter = WL1271_DEFAULT_AP_RX_FILTER;
} else {
wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
}
}

View file

@ -86,7 +86,7 @@
* Bits 3-5 - process_id tag (AP mode FW) * Bits 3-5 - process_id tag (AP mode FW)
* Bits 6-7 - reserved * Bits 6-7 - reserved
*/ */
#define WL1271_RX_DESC_STATUS_MASK 0x07 #define WL1271_RX_DESC_STATUS_MASK 0x03
#define WL1271_RX_DESC_SUCCESS 0x00 #define WL1271_RX_DESC_SUCCESS 0x00
#define WL1271_RX_DESC_DECRYPT_FAIL 0x01 #define WL1271_RX_DESC_DECRYPT_FAIL 0x01
@ -96,6 +96,8 @@
#define RX_MEM_BLOCK_MASK 0xFF #define RX_MEM_BLOCK_MASK 0xFF
#define RX_BUF_SIZE_MASK 0xFFF00 #define RX_BUF_SIZE_MASK 0xFFF00
#define RX_BUF_SIZE_SHIFT_DIV 6 #define RX_BUF_SIZE_SHIFT_DIV 6
/* If set, the start of IP payload is not 4 bytes aligned */
#define RX_BUF_UNALIGNED_PAYLOAD BIT(20)
enum { enum {
WL12XX_RX_CLASS_UNKNOWN, WL12XX_RX_CLASS_UNKNOWN,
@ -119,16 +121,12 @@ struct wl1271_rx_descriptor {
u8 snr; u8 snr;
__le32 timestamp; __le32 timestamp;
u8 packet_class; u8 packet_class;
union { u8 hlid;
u8 process_id; /* STA FW */
u8 hlid; /* AP FW */
} __packed;
u8 pad_len; u8 pad_len;
u8 reserved; u8 reserved;
} __packed; } __packed;
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status); void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
void wl1271_set_default_filters(struct wl1271 *wl);
#endif #endif

View file

@ -33,6 +33,8 @@ void wl1271_scan_complete_work(struct work_struct *work)
{ {
struct delayed_work *dwork; struct delayed_work *dwork;
struct wl1271 *wl; struct wl1271 *wl;
int ret;
bool is_sta, is_ibss;
dwork = container_of(work, struct delayed_work, work); dwork = container_of(work, struct delayed_work, work);
wl = container_of(dwork, struct wl1271, scan_complete_work); wl = container_of(dwork, struct wl1271, scan_complete_work);
@ -50,21 +52,34 @@ void wl1271_scan_complete_work(struct work_struct *work)
wl->scan.state = WL1271_SCAN_STATE_IDLE; wl->scan.state = WL1271_SCAN_STATE_IDLE;
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
wl->scan.req = NULL; wl->scan.req = NULL;
ieee80211_scan_completed(wl->hw, false);
/* restore hardware connection monitoring template */ ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out;
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
if (wl1271_ps_elp_wakeup(wl) == 0) { /* restore hardware connection monitoring template */
wl1271_cmd_build_ap_probe_req(wl, wl->probereq); wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
}
/* return to ROC if needed */
is_sta = (wl->bss_type == BSS_TYPE_STA_BSS);
is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
if ((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ||
(is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) {
/* restore remain on channel */
wl12xx_cmd_role_start_dev(wl);
wl12xx_roc(wl, wl->dev_role_id);
}
wl1271_ps_elp_sleep(wl); wl1271_ps_elp_sleep(wl);
}
}
if (wl->scan.failed) { if (wl->scan.failed) {
wl1271_info("Scan completed due to error."); wl1271_info("Scan completed due to error.");
wl12xx_queue_recovery_work(wl); wl12xx_queue_recovery_work(wl);
} }
ieee80211_scan_completed(wl->hw, false);
out: out:
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
@ -156,6 +171,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
if (passive || wl->scan.req->n_ssids == 0) if (passive || wl->scan.req->n_ssids == 0)
scan_options |= WL1271_SCAN_OPT_PASSIVE; scan_options |= WL1271_SCAN_OPT_PASSIVE;
if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) {
ret = -EINVAL;
goto out;
}
cmd->params.role_id = wl->role_id;
cmd->params.scan_options = cpu_to_le16(scan_options); cmd->params.scan_options = cpu_to_le16(scan_options);
cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
@ -167,10 +187,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
} }
cmd->params.tx_rate = cpu_to_le32(basic_rate); cmd->params.tx_rate = cpu_to_le32(basic_rate);
cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
cmd->params.rx_filter_options =
cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
cmd->params.tx_rate = cpu_to_le32(basic_rate); cmd->params.tx_rate = cpu_to_le32(basic_rate);
cmd->params.tid_trigger = 0; cmd->params.tid_trigger = 0;
@ -186,6 +202,8 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len); memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len);
} }
memcpy(cmd->addr, wl->mac_addr, ETH_ALEN);
ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len, ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len,
wl->scan.req->ie, wl->scan.req->ie_len, wl->scan.req->ie, wl->scan.req->ie_len,
band); band);

View file

@ -46,7 +46,10 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl);
#define WL1271_SCAN_CURRENT_TX_PWR 0 #define WL1271_SCAN_CURRENT_TX_PWR 0
#define WL1271_SCAN_OPT_ACTIVE 0 #define WL1271_SCAN_OPT_ACTIVE 0
#define WL1271_SCAN_OPT_PASSIVE 1 #define WL1271_SCAN_OPT_PASSIVE 1
#define WL1271_SCAN_OPT_TRIGGERED_SCAN 2
#define WL1271_SCAN_OPT_PRIORITY_HIGH 4 #define WL1271_SCAN_OPT_PRIORITY_HIGH 4
/* scan even if we fail to enter psm */
#define WL1271_SCAN_OPT_FORCE 8
#define WL1271_SCAN_BAND_2_4_GHZ 0 #define WL1271_SCAN_BAND_2_4_GHZ 0
#define WL1271_SCAN_BAND_5_GHZ 1 #define WL1271_SCAN_BAND_5_GHZ 1
@ -62,27 +65,27 @@ enum {
}; };
struct basic_scan_params { struct basic_scan_params {
__le32 rx_config_options;
__le32 rx_filter_options;
/* Scan option flags (WL1271_SCAN_OPT_*) */ /* Scan option flags (WL1271_SCAN_OPT_*) */
__le16 scan_options; __le16 scan_options;
u8 role_id;
/* Number of scan channels in the list (maximum 30) */ /* Number of scan channels in the list (maximum 30) */
u8 n_ch; u8 n_ch;
/* This field indicates the number of probe requests to send /* This field indicates the number of probe requests to send
per channel for an active scan */ per channel for an active scan */
u8 n_probe_reqs; u8 n_probe_reqs;
/* Rate bit field for sending the probes */
__le32 tx_rate;
u8 tid_trigger; u8 tid_trigger;
u8 ssid_len; u8 ssid_len;
/* in order to align */ u8 use_ssid_list;
u8 padding1[2];
/* Rate bit field for sending the probes */
__le32 tx_rate;
u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid[IEEE80211_MAX_SSID_LEN];
/* Band to scan */ /* Band to scan */
u8 band; u8 band;
u8 use_ssid_list;
u8 scan_tag; u8 scan_tag;
u8 padding2; u8 padding2[2];
} __packed; } __packed;
struct basic_scan_channel_params { struct basic_scan_channel_params {
@ -105,6 +108,10 @@ struct wl1271_cmd_scan {
struct basic_scan_params params; struct basic_scan_params params;
struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS]; struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS];
/* src mac address */
u8 addr[ETH_ALEN];
u8 padding[2];
} __packed; } __packed;
struct wl1271_cmd_trigger_scan_to { struct wl1271_cmd_trigger_scan_to {
@ -184,7 +191,7 @@ struct wl1271_cmd_sched_scan_config {
} __packed; } __packed;
#define SCHED_SCAN_MAX_SSIDS 8 #define SCHED_SCAN_MAX_SSIDS 16
enum { enum {
SCAN_SSID_TYPE_PUBLIC = 0, SCAN_SSID_TYPE_PUBLIC = 0,

View file

@ -412,7 +412,5 @@ module_exit(wl1271_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
MODULE_FIRMWARE(WL1271_FW_NAME); MODULE_FIRMWARE(WL127X_FW_NAME);
MODULE_FIRMWARE(WL128X_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME);
MODULE_FIRMWARE(WL127X_AP_FW_NAME);
MODULE_FIRMWARE(WL128X_AP_FW_NAME);

View file

@ -193,7 +193,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
ret = request_firmware(&fw, WL128X_FW_NAME, ret = request_firmware(&fw, WL128X_FW_NAME,
wl1271_wl_to_dev(wl)); wl1271_wl_to_dev(wl));
else else
ret = request_firmware(&fw, WL1271_FW_NAME, ret = request_firmware(&fw, WL127X_FW_NAME,
wl1271_wl_to_dev(wl)); wl1271_wl_to_dev(wl));
if (ret < 0) { if (ret < 0) {

View file

@ -486,8 +486,6 @@ module_exit(wl1271_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
MODULE_FIRMWARE(WL1271_FW_NAME); MODULE_FIRMWARE(WL127X_FW_NAME);
MODULE_FIRMWARE(WL128X_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME);
MODULE_FIRMWARE(WL127X_AP_FW_NAME);
MODULE_FIRMWARE(WL128X_AP_FW_NAME);
MODULE_ALIAS("spi:wl1271"); MODULE_ALIAS("spi:wl1271");

View file

@ -37,9 +37,10 @@ static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
if (is_ap) if (is_ap)
ret = wl1271_cmd_set_ap_default_wep_key(wl, id); ret = wl12xx_cmd_set_default_wep_key(wl, id,
wl->ap_bcast_hlid);
else else
ret = wl1271_cmd_set_sta_default_wep_key(wl, id); ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->sta_hlid);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -77,6 +78,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
int ret;
hdr = (struct ieee80211_hdr *)(skb->data + hdr = (struct ieee80211_hdr *)(skb->data +
sizeof(struct wl1271_tx_hw_descr)); sizeof(struct wl1271_tx_hw_descr));
@ -90,9 +92,19 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
if (!ieee80211_is_auth(hdr->frame_control)) if (!ieee80211_is_auth(hdr->frame_control))
return 0; return 0;
wl1271_configure_filters(wl, FIF_OTHER_BSS); if (wl->dev_hlid != WL12XX_INVALID_LINK_ID)
goto out;
return wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); wl1271_debug(DEBUG_CMD, "starting device role for roaming");
ret = wl12xx_cmd_role_start_dev(wl);
if (ret < 0)
goto out;
ret = wl12xx_roc(wl, wl->dev_role_id);
if (ret < 0)
goto out;
out:
return 0;
} }
static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
@ -114,24 +126,29 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid) static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
{ {
bool fw_ps; bool fw_ps;
u8 tx_blks; u8 tx_pkts;
/* only regulate station links */ /* only regulate station links */
if (hlid < WL1271_AP_STA_HLID_START) if (hlid < WL1271_AP_STA_HLID_START)
return; return;
fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
tx_blks = wl->links[hlid].allocated_blks; tx_pkts = wl->links[hlid].allocated_pkts;
/* /*
* if in FW PS and there is enough data in FW we can put the link * if in FW PS and there is enough data in FW we can put the link
* into high-level PS and clean out its TX queues. * into high-level PS and clean out its TX queues.
*/ */
if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS) if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
wl1271_ps_link_start(wl, hlid, true); wl1271_ps_link_start(wl, hlid, true);
} }
u8 wl1271_tx_get_hlid(struct sk_buff *skb) static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
{
return wl->dummy_packet == skb;
}
u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb)
{ {
struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb);
@ -144,14 +161,32 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb)
} else { } else {
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
return wl->system_hlid;
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_mgmt(hdr->frame_control)) if (ieee80211_is_mgmt(hdr->frame_control))
return WL1271_AP_GLOBAL_HLID; return wl->ap_global_hlid;
else else
return WL1271_AP_BROADCAST_HLID; return wl->ap_bcast_hlid;
} }
} }
static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb)
{
if (wl12xx_is_dummy_packet(wl, skb))
return wl->system_hlid;
if (wl->bss_type == BSS_TYPE_AP_BSS)
return wl12xx_tx_get_hlid_ap(wl, skb);
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))
return wl->sta_hlid;
else
return wl->dev_hlid;
}
static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl,
unsigned int packet_length) unsigned int packet_length)
{ {
@ -169,12 +204,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
u32 len; u32 len;
u32 total_blocks; u32 total_blocks;
int id, ret = -EBUSY, ac; int id, ret = -EBUSY, ac;
u32 spare_blocks;
if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS)) /* we use 1 spare block */
spare_blocks = 2; u32 spare_blocks = 1;
else
spare_blocks = 1;
if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
return -EAGAIN; return -EAGAIN;
@ -206,12 +238,14 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
desc->id = id; desc->id = id;
wl->tx_blocks_available -= total_blocks; wl->tx_blocks_available -= total_blocks;
wl->tx_allocated_blocks += total_blocks;
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
wl->tx_allocated_blocks[ac] += total_blocks; wl->tx_allocated_pkts[ac]++;
if (wl->bss_type == BSS_TYPE_AP_BSS) if (wl->bss_type == BSS_TYPE_AP_BSS &&
wl->links[hlid].allocated_blks += total_blocks; hlid >= WL1271_AP_STA_HLID_START)
wl->links[hlid].allocated_pkts++;
ret = 0; ret = 0;
@ -225,11 +259,6 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
return ret; return ret;
} }
static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
{
return wl->dummy_packet == skb;
}
static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
u32 extra, struct ieee80211_tx_info *control, u32 extra, struct ieee80211_tx_info *control,
u8 hlid) u8 hlid)
@ -280,9 +309,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
} }
if (wl->bss_type != BSS_TYPE_AP_BSS) { desc->hlid = hlid;
desc->aid = hlid;
if (wl->bss_type != BSS_TYPE_AP_BSS) {
/* if the packets are destined for AP (have a STA entry) /* if the packets are destined for AP (have a STA entry)
send them with AP rate policies, otherwise use default send them with AP rate policies, otherwise use default
basic rates */ basic rates */
@ -291,18 +320,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
else else
rate_idx = ACX_TX_BASIC_RATE; rate_idx = ACX_TX_BASIC_RATE;
} else { } else {
desc->hlid = hlid; if (hlid == wl->ap_global_hlid)
switch (hlid) {
case WL1271_AP_GLOBAL_HLID:
rate_idx = ACX_TX_AP_MODE_MGMT_RATE; rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
break; else if (hlid == wl->ap_bcast_hlid)
case WL1271_AP_BROADCAST_HLID:
rate_idx = ACX_TX_AP_MODE_BCST_RATE; rate_idx = ACX_TX_AP_MODE_BCST_RATE;
break; else
default:
rate_idx = ac; rate_idx = ac;
break;
}
} }
tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
@ -376,10 +399,11 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
} }
} }
if (wl->bss_type == BSS_TYPE_AP_BSS) hlid = wl1271_tx_get_hlid(wl, skb);
hlid = wl1271_tx_get_hlid(skb); if (hlid == WL12XX_INVALID_LINK_ID) {
else wl1271_error("invalid hlid. dropping skb 0x%p", skb);
hlid = TX_HW_DEFAULT_AID; return -EINVAL;
}
ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid); ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid);
if (ret < 0) if (ret < 0)
@ -462,19 +486,23 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
struct sk_buff_head *queues) struct sk_buff_head *queues)
{ {
int i, q = -1; int i, q = -1, ac;
u32 min_blks = 0xffffffff; u32 min_pkts = 0xffffffff;
/* /*
* Find a non-empty ac where: * Find a non-empty ac where:
* 1. There are packets to transmit * 1. There are packets to transmit
* 2. The FW has the least allocated blocks * 2. The FW has the least allocated blocks
*
* We prioritize the ACs according to VO>VI>BE>BK
*/ */
for (i = 0; i < NUM_TX_QUEUES; i++) for (i = 0; i < NUM_TX_QUEUES; i++) {
if (!skb_queue_empty(&queues[i]) && ac = wl1271_tx_get_queue(i);
(wl->tx_allocated_blocks[i] < min_blks)) { if (!skb_queue_empty(&queues[ac]) &&
q = i; (wl->tx_allocated_pkts[ac] < min_pkts)) {
min_blks = wl->tx_allocated_blocks[q]; q = ac;
min_pkts = wl->tx_allocated_pkts[q];
}
} }
if (q == -1) if (q == -1)
@ -579,7 +607,7 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
if (wl12xx_is_dummy_packet(wl, skb)) { if (wl12xx_is_dummy_packet(wl, skb)) {
set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
} else if (wl->bss_type == BSS_TYPE_AP_BSS) { } else if (wl->bss_type == BSS_TYPE_AP_BSS) {
u8 hlid = wl1271_tx_get_hlid(skb); u8 hlid = wl1271_tx_get_hlid(wl, skb);
skb_queue_head(&wl->links[hlid].tx_queue[q], skb); skb_queue_head(&wl->links[hlid].tx_queue[q], skb);
/* make sure we dequeue the same packet next time */ /* make sure we dequeue the same packet next time */
@ -826,10 +854,14 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
total[i] = 0; total[i] = 0;
while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb); wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb);
if (!wl12xx_is_dummy_packet(wl, skb)) {
info = IEEE80211_SKB_CB(skb); info = IEEE80211_SKB_CB(skb);
info->status.rates[0].idx = -1; info->status.rates[0].idx = -1;
info->status.rates[0].count = 0; info->status.rates[0].count = 0;
ieee80211_tx_status_ni(wl->hw, skb); ieee80211_tx_status_ni(wl->hw, skb);
}
total[i]++; total[i]++;
} }
} }
@ -853,8 +885,8 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
if (wl->bss_type == BSS_TYPE_AP_BSS) { if (wl->bss_type == BSS_TYPE_AP_BSS) {
for (i = 0; i < AP_MAX_LINKS; i++) { for (i = 0; i < AP_MAX_LINKS; i++) {
wl1271_tx_reset_link_queues(wl, i); wl1271_tx_reset_link_queues(wl, i);
wl->links[i].allocated_blks = 0; wl->links[i].allocated_pkts = 0;
wl->links[i].prev_freed_blks = 0; wl->links[i].prev_freed_pkts = 0;
} }
wl->last_tx_hlid = 0; wl->last_tx_hlid = 0;

View file

@ -29,9 +29,6 @@
#define TX_HW_MGMT_PKT_LIFETIME_TU 2000 #define TX_HW_MGMT_PKT_LIFETIME_TU 2000
#define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000 #define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000
/* The chipset reference driver states, that the "aid" value 1
* is for infra-BSS, but is still always used */
#define TX_HW_DEFAULT_AID 1
#define TX_HW_ATTR_SAVE_RETRIES BIT(0) #define TX_HW_ATTR_SAVE_RETRIES BIT(0)
#define TX_HW_ATTR_HEADER_PAD BIT(1) #define TX_HW_ATTR_HEADER_PAD BIT(1)
@ -116,12 +113,8 @@ struct wl1271_tx_hw_descr {
u8 id; u8 id;
/* The packet TID value (as User-Priority) */ /* The packet TID value (as User-Priority) */
u8 tid; u8 tid;
union { /* host link ID (HLID) */
/* STA - Identifier of the remote STA in IBSS, 1 in infra-BSS */
u8 aid;
/* AP - host link ID (HLID) */
u8 hlid; u8 hlid;
} __packed;
u8 reserved; u8 reserved;
} __packed; } __packed;
@ -133,7 +126,8 @@ enum wl1271_tx_hw_res_status {
TX_TIMEOUT = 4, TX_TIMEOUT = 4,
TX_KEY_NOT_FOUND = 5, TX_KEY_NOT_FOUND = 5,
TX_PEER_NOT_FOUND = 6, TX_PEER_NOT_FOUND = 6,
TX_SESSION_MISMATCH = 7 TX_SESSION_MISMATCH = 7,
TX_LINK_NOT_VALID = 8,
}; };
struct wl1271_tx_hw_res_descr { struct wl1271_tx_hw_res_descr {
@ -216,7 +210,7 @@ void wl1271_tx_flush(struct wl1271 *wl);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
u32 wl1271_tx_min_rate_get(struct wl1271 *wl); u32 wl1271_tx_min_rate_get(struct wl1271 *wl);
u8 wl1271_tx_get_hlid(struct sk_buff *skb); u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb);
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
void wl1271_handle_tx_low_watermark(struct wl1271 *wl); void wl1271_handle_tx_low_watermark(struct wl1271 *wl);

View file

@ -112,28 +112,8 @@ extern u32 wl12xx_debug_level;
true); \ true); \
} while (0) } while (0)
#define WL1271_DEFAULT_STA_RX_CONFIG (CFG_UNI_FILTER_EN | \ #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin"
CFG_BSSID_FILTER_EN | \ #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin"
CFG_MC_FILTER_EN)
#define WL1271_DEFAULT_STA_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \
CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
CFG_RX_CTL_EN | CFG_RX_BCN_EN | \
CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
#define WL1271_DEFAULT_AP_RX_CONFIG 0
#define WL1271_DEFAULT_AP_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PREQ_EN | \
CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
CFG_RX_CTL_EN | CFG_RX_AUTH_EN | \
CFG_RX_ASSOC_EN)
#define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin"
#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin"
#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin"
/* /*
* wl127x and wl128x are using the same NVS file name. However, the * wl127x and wl128x are using the same NVS file name. However, the
@ -157,25 +137,34 @@ extern u32 wl12xx_debug_level;
#define WL1271_DEFAULT_BEACON_INT 100 #define WL1271_DEFAULT_BEACON_INT 100
#define WL1271_DEFAULT_DTIM_PERIOD 1 #define WL1271_DEFAULT_DTIM_PERIOD 1
#define WL1271_AP_GLOBAL_HLID 0 #define WL12XX_MAX_ROLES 4
#define WL1271_AP_BROADCAST_HLID 1 #define WL12XX_MAX_LINKS 8
#define WL1271_AP_STA_HLID_START 2 #define WL12XX_INVALID_ROLE_ID 0xff
#define WL12XX_INVALID_LINK_ID 0xff
/* Defined by FW as 0. Will not be freed or allocated. */
#define WL12XX_SYSTEM_HLID 0
/* /*
* When in AP-mode, we allow (at least) this number of mem-blocks * TODO: we currently don't support multirole. remove
* this constant from the code when we do.
*/
#define WL1271_AP_STA_HLID_START 3
/*
* When in AP-mode, we allow (at least) this number of packets
* to be transmitted to FW for a STA in PS-mode. Only when packets are * to be transmitted to FW for a STA in PS-mode. Only when packets are
* present in the FW buffers it will wake the sleeping STA. We want to put * present in the FW buffers it will wake the sleeping STA. We want to put
* enough packets for the driver to transmit all of its buffered data before * enough packets for the driver to transmit all of its buffered data before
* the STA goes to sleep again. But we don't want to take too much mem-blocks * the STA goes to sleep again. But we don't want to take too much memory
* as it might hurt the throughput of active STAs. * as it might hurt the throughput of active STAs.
* The number of blocks (18) is enough for 2 large packets.
*/ */
#define WL1271_PS_STA_MAX_BLOCKS (2 * 9) #define WL1271_PS_STA_MAX_PACKETS 2
#define WL1271_AP_BSS_INDEX 0 #define WL1271_AP_BSS_INDEX 0
#define WL1271_AP_DEF_BEACON_EXP 20 #define WL1271_AP_DEF_BEACON_EXP 20
#define ACX_TX_DESCRIPTORS 32 #define ACX_TX_DESCRIPTORS 16
#define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
@ -247,26 +236,22 @@ struct wl1271_stats {
#define AP_MAX_STATIONS 5 #define AP_MAX_STATIONS 5
/* Broadcast and Global links + links to stations */ /* Broadcast and Global links + system link + links to stations */
#define AP_MAX_LINKS (AP_MAX_STATIONS + 2) /*
* TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all
* the places that use this.
*/
#define AP_MAX_LINKS (AP_MAX_STATIONS + 3)
/* FW status registers common for AP/STA */ /* FW status registers */
struct wl1271_fw_common_status { struct wl12xx_fw_status {
__le32 intr; __le32 intr;
u8 fw_rx_counter; u8 fw_rx_counter;
u8 drv_rx_counter; u8 drv_rx_counter;
u8 reserved; u8 reserved;
u8 tx_results_counter; u8 tx_results_counter;
__le32 rx_pkt_descs[NUM_RX_PKT_DESC]; __le32 rx_pkt_descs[NUM_RX_PKT_DESC];
__le32 tx_released_blks[NUM_TX_QUEUES];
__le32 fw_localtime; __le32 fw_localtime;
} __packed;
/* FW status registers for AP */
struct wl1271_fw_ap_status {
struct wl1271_fw_common_status common;
/* Next fields valid only in AP FW */
/* /*
* A bitmap (where each bit represents a single HLID) * A bitmap (where each bit represents a single HLID)
@ -274,30 +259,30 @@ struct wl1271_fw_ap_status {
*/ */
__le32 link_ps_bitmap; __le32 link_ps_bitmap;
/* Number of freed MBs per HLID */ /*
u8 tx_lnk_free_blks[AP_MAX_LINKS]; * A bitmap (where each bit represents a single HLID) to indicate
u8 padding_1[1]; * if the station is in Fast mode
} __packed; */
__le32 link_fast_bitmap;
/* FW status registers for STA */ /* Cumulative counter of total released mem blocks since FW-reset */
struct wl1271_fw_sta_status { __le32 total_released_blks;
struct wl1271_fw_common_status common;
u8 tx_total; /* Size (in Memory Blocks) of TX pool */
u8 reserved1; __le32 tx_total;
__le16 reserved2;
/* Cumulative counter of released packets per AC */
u8 tx_released_pkts[NUM_TX_QUEUES];
/* Cumulative counter of freed packets per HLID */
u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
/* Cumulative counter of released Voice memory blocks */
u8 tx_voice_released_blks;
u8 padding_1[7];
__le32 log_start_addr; __le32 log_start_addr;
} __packed; } __packed;
struct wl1271_fw_full_status {
union {
struct wl1271_fw_common_status common;
struct wl1271_fw_sta_status sta;
struct wl1271_fw_ap_status ap;
};
} __packed;
struct wl1271_rx_mem_pool_addr { struct wl1271_rx_mem_pool_addr {
u32 addr; u32 addr;
u32 addr_extra; u32 addr_extra;
@ -342,7 +327,7 @@ struct wl1271_ap_key {
enum wl12xx_flags { enum wl12xx_flags {
WL1271_FLAG_STA_ASSOCIATED, WL1271_FLAG_STA_ASSOCIATED,
WL1271_FLAG_JOINED, WL1271_FLAG_IBSS_JOINED,
WL1271_FLAG_GPIO_POWER, WL1271_FLAG_GPIO_POWER,
WL1271_FLAG_TX_QUEUE_STOPPED, WL1271_FLAG_TX_QUEUE_STOPPED,
WL1271_FLAG_TX_PENDING, WL1271_FLAG_TX_PENDING,
@ -369,11 +354,14 @@ struct wl1271_link {
/* AP-mode - TX queue per AC in link */ /* AP-mode - TX queue per AC in link */
struct sk_buff_head tx_queue[NUM_TX_QUEUES]; struct sk_buff_head tx_queue[NUM_TX_QUEUES];
/* accounting for allocated / available TX blocks in FW */ /* accounting for allocated / freed packets in FW */
u8 allocated_blks; u8 allocated_pkts;
u8 prev_freed_blks; u8 prev_freed_pkts;
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
/* bitmap of TIDs where RX BA sessions are active for this link */
u8 ba_bitmap;
}; };
struct wl1271 { struct wl1271 {
@ -405,7 +393,6 @@ struct wl1271 {
u8 *fw; u8 *fw;
size_t fw_len; size_t fw_len;
u8 fw_bss_type;
void *nvs; void *nvs;
size_t nvs_len; size_t nvs_len;
@ -418,15 +405,30 @@ struct wl1271 {
u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 ssid_len; u8 ssid_len;
int channel; int channel;
u8 role_id;
u8 dev_role_id;
u8 system_hlid;
u8 sta_hlid;
u8 dev_hlid;
u8 ap_global_hlid;
u8 ap_bcast_hlid;
unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
struct wl1271_acx_mem_map *target_mem_map; struct wl1271_acx_mem_map *target_mem_map;
/* Accounting for allocated / available TX blocks on HW */ /* Accounting for allocated / available TX blocks on HW */
u32 tx_blocks_freed[NUM_TX_QUEUES]; u32 tx_blocks_freed;
u32 tx_blocks_available; u32 tx_blocks_available;
u32 tx_allocated_blocks[NUM_TX_QUEUES]; u32 tx_allocated_blocks;
u32 tx_results_count; u32 tx_results_count;
/* Accounting for allocated / available Tx packets in HW */
u32 tx_pkts_freed[NUM_TX_QUEUES];
u32 tx_allocated_pkts[NUM_TX_QUEUES];
/* Transmitted TX packets counter for chipset interface */ /* Transmitted TX packets counter for chipset interface */
u32 tx_packets_count; u32 tx_packets_count;
@ -535,10 +537,6 @@ struct wl1271 {
struct work_struct rx_streaming_disable_work; struct work_struct rx_streaming_disable_work;
struct timer_list rx_streaming_timer; struct timer_list rx_streaming_timer;
unsigned int filters;
unsigned int rx_config;
unsigned int rx_filter;
struct completion *elp_compl; struct completion *elp_compl;
struct completion *ps_compl; struct completion *ps_compl;
struct delayed_work elp_work; struct delayed_work elp_work;
@ -562,7 +560,7 @@ struct wl1271 {
u32 buffer_cmd; u32 buffer_cmd;
u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
struct wl1271_fw_full_status *fw_status; struct wl12xx_fw_status *fw_status;
struct wl1271_tx_hw_res_if *tx_res_if; struct wl1271_tx_hw_res_if *tx_res_if;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
@ -622,6 +620,9 @@ struct wl1271 {
/* Platform limitations */ /* Platform limitations */
unsigned int platform_quirks; unsigned int platform_quirks;
/* number of currently active RX BA sessions */
int ba_rx_session_count;
}; };
struct wl1271_station { struct wl1271_station {
@ -659,12 +660,6 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
/* Each RX/TX transaction requires an end-of-transaction transfer */ /* Each RX/TX transaction requires an end-of-transaction transfer */
#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) #define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0)
/*
* Older firmwares use 2 spare TX blocks
* (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47)
*/
#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1)
/* WL128X requires aggregated packets to be aligned to the SDIO block size */ /* WL128X requires aggregated packets to be aligned to the SDIO block size */
#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2) #define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2)

View file

@ -105,18 +105,6 @@ struct wl12xx_ie_country {
/* Templates */ /* Templates */
struct wl12xx_beacon_template {
struct ieee80211_header header;
__le32 time_stamp[2];
__le16 beacon_interval;
__le16 capability;
struct wl12xx_ie_ssid ssid;
struct wl12xx_ie_rates rates;
struct wl12xx_ie_rates ext_rates;
struct wl12xx_ie_ds_params ds_params;
struct wl12xx_ie_country country;
} __packed;
struct wl12xx_null_data_template { struct wl12xx_null_data_template {
struct ieee80211_header header; struct ieee80211_header header;
} __packed; } __packed;
@ -146,19 +134,6 @@ struct wl12xx_arp_rsp_template {
__be32 target_ip; __be32 target_ip;
} __packed; } __packed;
struct wl12xx_probe_resp_template {
struct ieee80211_header header;
__le32 time_stamp[2];
__le16 beacon_interval;
__le16 capability;
struct wl12xx_ie_ssid ssid;
struct wl12xx_ie_rates rates;
struct wl12xx_ie_rates ext_rates;
struct wl12xx_ie_ds_params ds_params;
struct wl12xx_ie_country country;
} __packed;
struct wl12xx_disconn_template { struct wl12xx_disconn_template {
struct ieee80211_header header; struct ieee80211_header header;
__le16 disconn_reason; __le16 disconn_reason;

View file

@ -1792,6 +1792,7 @@ struct wiphy_wowlan_support {
* @debugfsdir: debugfs directory used for this wiphy, will be renamed * @debugfsdir: debugfs directory used for this wiphy, will be renamed
* automatically on wiphy renames * automatically on wiphy renames
* @dev: (virtual) struct device for this wiphy * @dev: (virtual) struct device for this wiphy
* @registered: helps synchronize suspend/resume with wiphy unregister
* @wext: wireless extension handlers * @wext: wireless extension handlers
* @priv: driver private data (sized according to wiphy_new() parameter) * @priv: driver private data (sized according to wiphy_new() parameter)
* @interface_modes: bitmask of interfaces types valid for this wiphy, * @interface_modes: bitmask of interfaces types valid for this wiphy,

View file

@ -195,20 +195,12 @@ static ssize_t uapsd_queues_write(struct file *file,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ieee80211_local *local = file->private_data; struct ieee80211_local *local = file->private_data;
unsigned long val; u8 val;
char buf[10];
size_t len;
int ret; int ret;
len = min(count, sizeof(buf) - 1); ret = kstrtou8_from_user(user_buf, count, 0, &val);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
ret = strict_strtoul(buf, 0, &val);
if (ret) if (ret)
return -EINVAL; return ret;
if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
return -ERANGE; return -ERANGE;

View file

@ -307,14 +307,14 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath,
while (num_skbs--) { while (num_skbs--) {
skb = __skb_dequeue(&failq); skb = __skb_dequeue(&failq);
if (copy) if (copy) {
cp_skb = skb_copy(skb, GFP_ATOMIC); cp_skb = skb_copy(skb, GFP_ATOMIC);
if (cp_skb)
__skb_queue_tail(&failq, cp_skb);
}
prepare_for_gate(skb, gate_mpath->dst, gate_mpath); prepare_for_gate(skb, gate_mpath->dst, gate_mpath);
__skb_queue_tail(&gateq, skb); __skb_queue_tail(&gateq, skb);
if (copy && cp_skb)
__skb_queue_tail(&failq, cp_skb);
} }
spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags); spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags);