#define ATH_TXFIFO_DEPTH 8
struct ath_txq {
- int axq_class;
u32 axq_qnum;
u32 *axq_link;
struct list_head axq_q;
struct list_head txq_fifo_pending;
u8 txq_headidx;
u8 txq_tailidx;
+ int pending_frames;
};
struct ath_atx_ac {
+ struct ath_txq *txq;
int sched;
- int qnum;
struct list_head list;
struct list_head tid_q;
};
struct ath_atx_ac ac[WME_NUM_AC];
u16 maxampdu;
u8 mpdudensity;
- int last_rssi;
};
#define AGGR_CLEANUP BIT(1)
struct ath_tx {
u16 seq_no;
u32 txqsetup;
- int hwq_map[WME_NUM_AC];
spinlock_t txbuflock;
struct list_head txbuf;
struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
struct ath_descdma txdma;
- int pending_frames[WME_NUM_AC];
+ struct ath_txq *txq_map[WME_NUM_AC];
};
struct ath_rx_edma {
u8 rxotherant;
u32 *rxlink;
unsigned int rxfilter;
- spinlock_t pcu_lock;
spinlock_t rxbuflock;
struct list_head rxbuf;
struct ath_descdma rxdma;
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
- int ath_tx_setup(struct ath_softc *sc, int haltype);
void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
void ath_draintxq(struct ath_softc *sc,
struct ath_txq *txq, bool retry_tx);
struct ath_hw *sc_ah;
void __iomem *mem;
int irq;
- spinlock_t sc_resetlock;
spinlock_t sc_serial_rw;
spinlock_t sc_pm_lock;
+ spinlock_t sc_pcu_lock;
struct mutex mutex;
struct work_struct paprd_work;
struct work_struct hw_check_work;
bool idle;
int chan_idx;
int chan_is_ht;
+ int last_rssi;
};
void ath9k_tasklet(unsigned long data);
int ath_reset(struct ath_softc *sc, bool retry_tx);
- int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
int ath_cabq_update(struct ath_softc *);
static inline void ath_read_cachesize(struct ath_common *common, int *csz)
}
extern struct ieee80211_ops ath9k_ops;
+extern struct pm_qos_request_list ath9k_pm_qos_req;
extern int modparam_nohwcrypt;
extern int led_blink;
ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
"Failed allocating banks for "
"external radio\n");
+ ath9k_hw_rf_free_ext_banks(ah);
return ecode;
}
REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
break;
case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_MONITOR:
REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
break;
+ default:
+ if (ah->is_monitoring)
+ REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
+ break;
}
}
channel->max_antenna_gain * 2,
channel->max_power * 2,
min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit));
+ (u32) regulatory->power_limit), false);
ath9k_hw_rfbus_done(ah);
switch (ah->opmode) {
case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_MONITOR:
REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
break;
default:
+ if (ah->is_monitoring) {
+ REG_WRITE(ah, AR_NEXT_TBTT_TIMER,
+ TU_TO_USEC(next_beacon));
+ REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
+ REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
+ flags |= AR_TBTT_TIMER_EN;
+ break;
+ }
ath_print(ath9k_hw_common(ah), ATH_DBG_BEACON,
"%s: unsupported opmode: %d\n",
__func__, ah->opmode);
}
EXPORT_SYMBOL(ath9k_hw_disable);
- void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
+ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath9k_channel *chan = ah->curchan;
channel->max_antenna_gain * 2,
channel->max_power * 2,
min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit));
+ (u32) regulatory->power_limit), test);
}
EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
return timer_table->gen_timer_index[b];
}
- u32 ath9k_hw_gettsf32(struct ath_hw *ah)
+ static u32 ath9k_hw_gettsf32(struct ath_hw *ah)
{
return REG_READ(ah, AR_TSF_L32);
}
- EXPORT_SYMBOL(ath9k_hw_gettsf32);
struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
void (*trigger)(void *),
#define PAPRD_GAIN_TABLE_ENTRIES 32
#define PAPRD_TABLE_SZ 24
+ enum ath_hw_txq_subtype {
+ ATH_TXQ_AC_BE = 0,
+ ATH_TXQ_AC_BK = 1,
+ ATH_TXQ_AC_VI = 2,
+ ATH_TXQ_AC_VO = 3,
+ };
+
enum ath_ini_subsys {
ATH_INI_PRE = 0,
ATH_INI_CORE,
bool sw_mgmt_crypto;
bool is_pciexpress;
+ bool is_monitoring;
bool need_an_top2_fixup;
u16 tx_trig_level;
return &ah->ops;
}
- static inline int sign_extend(int val, const int nbits)
- {
- int order = BIT(nbits-1);
- return (val ^ order) - order;
- }
-
/* Initialization, Detach, Reset */
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
void ath9k_hw_deinit(struct ath_hw *ah);
void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
bool ath9k_hw_phy_disable(struct ath_hw *ah);
bool ath9k_hw_disable(struct ath_hw *ah);
- void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
+ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test);
void ath9k_hw_setopmode(struct ath_hw *ah);
void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
void ath9k_hw_setbssidmask(struct ath_hw *ah);
void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
void ath_gen_timer_isr(struct ath_hw *hw);
- u32 ath9k_hw_gettsf32(struct ath_hw *ah);
void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
*/
#include <linux/slab.h>
+#include <linux/pm_qos_params.h>
#include "ath9k.h"
.write = ath9k_iowrite32,
};
+struct pm_qos_request_list ath9k_pm_qos_req;
+
/**************************/
/* Initialization */
/**************************/
static int ath9k_init_btcoex(struct ath_softc *sc)
{
- int r, qnum;
+ struct ath_txq *txq;
+ int r;
switch (sc->sc_ah->btcoex_hw.scheme) {
case ATH_BTCOEX_CFG_NONE:
r = ath_init_btcoex_timer(sc);
if (r)
return -1;
- qnum = sc->tx.hwq_map[WME_AC_BE];
- ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum);
+ txq = sc->tx.txq_map[WME_AC_BE];
+ ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
break;
default:
static int ath9k_init_queues(struct ath_softc *sc)
{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int i = 0;
- for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
- sc->tx.hwq_map[i] = -1;
-
sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
- if (sc->beacon.beaconq == -1) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup a beacon xmit queue\n");
- goto err;
- }
-
sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
- if (sc->beacon.cabq == NULL) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup CAB xmit queue\n");
- goto err;
- }
sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
ath_cabq_update(sc);
- if (!ath_tx_setup(sc, WME_AC_BK)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for BK traffic\n");
- goto err;
- }
-
- if (!ath_tx_setup(sc, WME_AC_BE)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for BE traffic\n");
- goto err;
- }
- if (!ath_tx_setup(sc, WME_AC_VI)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for VI traffic\n");
- goto err;
- }
- if (!ath_tx_setup(sc, WME_AC_VO)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for VO traffic\n");
- goto err;
- }
+ for (i = 0; i < WME_NUM_AC; i++)
+ sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
return 0;
-
- err:
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
- if (ATH_TXQ_SETUP(sc, i))
- ath_tx_cleanupq(sc, &sc->tx.txq[i]);
-
- return -EIO;
}
static int ath9k_init_channels_rates(struct ath_softc *sc)
spin_lock_init(&common->cc_lock);
spin_lock_init(&sc->wiphy_lock);
- spin_lock_init(&sc->sc_resetlock);
spin_lock_init(&sc->sc_serial_rw);
spin_lock_init(&sc->sc_pm_lock);
mutex_init(&sc->mutex);
return ret;
}
+ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
+ {
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *chan;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+ int i;
+
+ sband = &sc->sbands[band];
+ for (i = 0; i < sband->n_channels; i++) {
+ chan = &sband->channels[i];
+ ah->curchan = &ah->channels[chan->hw_value];
+ ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
+ ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
+ chan->max_power = reg->max_power_level / 2;
+ }
+ }
+
+ static void ath9k_init_txpower_limits(struct ath_softc *sc)
+ {
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_channel *curchan = ah->curchan;
+
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+ ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+ ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
+
+ ah->curchan = curchan;
+ }
+
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
const struct ath_bus_ops *bus_ops)
{
struct ieee80211_hw *hw = sc->hw;
+ struct ath_wiphy *aphy = hw->priv;
struct ath_common *common;
struct ath_hw *ah;
int error = 0;
if (error != 0)
goto error_rx;
+ ath9k_init_txpower_limits(sc);
+
/* Register with mac80211 */
error = ieee80211_register_hw(hw);
if (error)
INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
sc->wiphy_scheduler_int = msecs_to_jiffies(500);
+ aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
ath_init_leds(sc);
ath_start_rfkill_poll(sc);
+ pm_qos_add_request(&ath9k_pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
+ PM_QOS_DEFAULT_VALUE);
+
return 0;
error_world:
ath9k_ps_wakeup(sc);
+ pm_qos_remove_request(&ath9k_pm_qos_req);
+
wiphy_rfkill_stop_polling(sc->hw->wiphy);
ath_deinit_leds(sc);
*/
#include <linux/nl80211.h>
+#include <linux/pm_qos_params.h>
#include "ath9k.h"
#include "btcoex.h"
struct ath_hw *ah = sc->sc_ah;
if (sc->curtxpow != sc->config.txpowlimit) {
- ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit);
+ ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
/* read back in case value is clamped */
sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
}
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
unsigned long flags;
+ enum ath9k_power_mode power_mode;
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if (++sc->ps_usecount != 1)
goto unlock;
+ power_mode = sc->sc_ah->power_mode;
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
/*
* useful data. Better clear them now so that they don't mess up
* survey data results.
*/
- spin_lock(&common->cc_lock);
- ath_hw_cycle_counters_update(common);
- memset(&common->cc_survey, 0, sizeof(common->cc_survey));
- spin_unlock(&common->cc_lock);
+ if (power_mode != ATH9K_PM_AWAKE) {
+ spin_lock(&common->cc_lock);
+ ath_hw_cycle_counters_update(common);
+ memset(&common->cc_survey, 0, sizeof(common->cc_survey));
+ spin_unlock(&common->cc_lock);
+ }
unlock:
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
ath9k_ps_wakeup(sc);
+ spin_lock_bh(&sc->sc_pcu_lock);
+
/*
* This is only performed if the channel settings have
* actually changed.
* hardware at the new frequency, and then re-enable
* the relevant bits of the h/w.
*/
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
ath_drain_all_txq(sc, false);
- spin_lock_bh(&sc->rx.pcu_lock);
-
stopped = ath_stoprecv(sc);
/* XXX: do not flush receive queue here. We don't want
channel->center_freq, conf_is_ht40(conf),
fastcc);
- spin_lock_bh(&sc->sc_resetlock);
-
r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
if (r) {
ath_print(common, ATH_DBG_FATAL,
"Unable to reset channel (%u MHz), "
"reset status %d\n",
channel->center_freq, r);
- spin_unlock_bh(&sc->sc_resetlock);
- spin_unlock_bh(&sc->rx.pcu_lock);
goto ps_restore;
}
- spin_unlock_bh(&sc->sc_resetlock);
if (ath_startrecv(sc) != 0) {
ath_print(common, ATH_DBG_FATAL,
"Unable to restart recv logic\n");
r = -EIO;
- spin_unlock_bh(&sc->rx.pcu_lock);
goto ps_restore;
}
- spin_unlock_bh(&sc->rx.pcu_lock);
-
ath_update_txpow(sc);
ath9k_hw_set_interrupts(ah, ah->imask);
}
ps_restore:
+ spin_unlock_bh(&sc->sc_pcu_lock);
+
ath9k_ps_restore(sc);
return r;
}
struct ath_tx_control txctl;
struct ath9k_hw_cal_data *caldata = ah->caldata;
struct ath_common *common = ath9k_hw_common(ah);
- int qnum, ftype;
+ int ftype;
int chain_ok = 0;
int chain;
int len = 1800;
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
memset(&txctl, 0, sizeof(txctl));
- qnum = sc->tx.hwq_map[WME_AC_BE];
- txctl.txq = &sc->tx.txq[qnum];
+ txctl.txq = sc->tx.txq_map[WME_AC_BE];
ath9k_ps_wakeup(sc);
ar9003_paprd_init_table(ah);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
- an->last_rssi = ATH_RSSI_DUMMY_MARKER;
}
}
return;
}
+ spin_lock_bh(&sc->sc_pcu_lock);
+
if (!ath9k_hw_check_alive(ah))
ieee80211_queue_work(sc->hw, &sc->hw_check_work);
rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
if (status & rxmask) {
- spin_lock_bh(&sc->rx.pcu_lock);
-
/* Check for high priority Rx first */
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
(status & ATH9K_INT_RXHP))
ath_rx_tasklet(sc, 0, true);
ath_rx_tasklet(sc, 0, false);
- spin_unlock_bh(&sc->rx.pcu_lock);
}
if (status & ATH9K_INT_TX) {
ath_gen_timer_isr(sc->sc_ah);
/* re-enable hardware interrupt */
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_enable_interrupts(ah);
+
+ spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
}
* interrupt; otherwise it will continue to
* fire.
*/
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
/*
* Let the hal handle the event. We assume
* it will clear whatever condition caused
spin_lock(&common->cc_lock);
ath9k_hw_proc_mib_event(ah);
spin_unlock(&common->cc_lock);
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_enable_interrupts(ah);
}
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
ath_debug_stat_interrupt(sc, status);
if (sched) {
- /* turn off every interrupt except SWBA */
- ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA));
+ /* turn off every interrupt */
+ ath9k_hw_disable_interrupts(ah);
tasklet_schedule(&sc->intr_tq);
}
}
static void ath9k_bss_assoc_info(struct ath_softc *sc,
+ struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf)
{
+ struct ath_wiphy *aphy = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
ath_beacon_config(sc, vif);
/* Reset rssi stats */
+ aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_flags |= SC_OP_ANI_RUN;
int r;
ath9k_ps_wakeup(sc);
+ spin_lock_bh(&sc->sc_pcu_lock);
+
ath9k_hw_configpcipowersave(ah, 0, 0);
if (!ah->curchan)
ah->curchan = ath_get_curchannel(sc, sc->hw);
- spin_lock_bh(&sc->rx.pcu_lock);
- spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (r) {
ath_print(common, ATH_DBG_FATAL,
"reset status %d\n",
channel->center_freq, r);
}
- spin_unlock_bh(&sc->sc_resetlock);
ath_update_txpow(sc);
if (ath_startrecv(sc) != 0) {
ath_print(common, ATH_DBG_FATAL,
"Unable to restart recv logic\n");
- spin_unlock_bh(&sc->rx.pcu_lock);
+ spin_unlock_bh(&sc->sc_pcu_lock);
return;
}
- spin_unlock_bh(&sc->rx.pcu_lock);
-
if (sc->sc_flags & SC_OP_BEACONS)
ath_beacon_config(sc, NULL); /* restart beacons */
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
ieee80211_wake_queues(hw);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+
ath9k_ps_restore(sc);
}
int r;
ath9k_ps_wakeup(sc);
+ spin_lock_bh(&sc->sc_pcu_lock);
+
ieee80211_stop_queues(hw);
/*
}
/* Disable interrupts */
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
ath_drain_all_txq(sc, false); /* clear pending tx frames */
- spin_lock_bh(&sc->rx.pcu_lock);
-
ath_stoprecv(sc); /* turn off frame recv */
ath_flushrecv(sc); /* flush recv queue */
if (!ah->curchan)
ah->curchan = ath_get_curchannel(sc, hw);
- spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (r) {
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
"reset status %d\n",
channel->center_freq, r);
}
- spin_unlock_bh(&sc->sc_resetlock);
ath9k_hw_phy_disable(ah);
- spin_unlock_bh(&sc->rx.pcu_lock);
-
ath9k_hw_configpcipowersave(ah, 1, 1);
+
+ spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
+
ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
}
/* Stop ANI */
del_timer_sync(&common->ani.timer);
+ spin_lock_bh(&sc->sc_pcu_lock);
+
ieee80211_stop_queues(hw);
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
ath_drain_all_txq(sc, retry_tx);
- spin_lock_bh(&sc->rx.pcu_lock);
-
ath_stoprecv(sc);
ath_flushrecv(sc);
- spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
if (r)
ath_print(common, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %d\n", r);
- spin_unlock_bh(&sc->sc_resetlock);
if (ath_startrecv(sc) != 0)
ath_print(common, ATH_DBG_FATAL,
"Unable to start recv logic\n");
- spin_unlock_bh(&sc->rx.pcu_lock);
-
/*
* We may be doing a reset in response to a request
* that changes the channel so update any state that
}
ieee80211_wake_queues(hw);
+ spin_unlock_bh(&sc->sc_pcu_lock);
/* Start ANI */
ath_start_ani(common);
return r;
}
- static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
- {
- int qnum;
-
- switch (queue) {
- case 0:
- qnum = sc->tx.hwq_map[WME_AC_VO];
- break;
- case 1:
- qnum = sc->tx.hwq_map[WME_AC_VI];
- break;
- case 2:
- qnum = sc->tx.hwq_map[WME_AC_BE];
- break;
- case 3:
- qnum = sc->tx.hwq_map[WME_AC_BK];
- break;
- default:
- qnum = sc->tx.hwq_map[WME_AC_BE];
- break;
- }
-
- return qnum;
- }
-
- int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
- {
- int qnum;
-
- switch (queue) {
- case WME_AC_VO:
- qnum = 0;
- break;
- case WME_AC_VI:
- qnum = 1;
- break;
- case WME_AC_BE:
- qnum = 2;
- break;
- case WME_AC_BK:
- qnum = 3;
- break;
- default:
- qnum = -1;
- break;
- }
-
- return qnum;
- }
-
/* XXX: Remove me once we don't depend on ath9k_channel for all
* this redundant data */
void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
* be followed by initialization of the appropriate bits
* and then setup of the interrupt mask.
*/
- spin_lock_bh(&sc->rx.pcu_lock);
- spin_lock_bh(&sc->sc_resetlock);
+ spin_lock_bh(&sc->sc_pcu_lock);
r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
if (r) {
ath_print(common, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %d "
"(freq %u MHz)\n", r,
curchan->center_freq);
- spin_unlock_bh(&sc->sc_resetlock);
- spin_unlock_bh(&sc->rx.pcu_lock);
+ spin_unlock_bh(&sc->sc_pcu_lock);
goto mutex_unlock;
}
- spin_unlock_bh(&sc->sc_resetlock);
/*
* This is needed only to setup initial state
ath_print(common, ATH_DBG_FATAL,
"Unable to start recv logic\n");
r = -EIO;
- spin_unlock_bh(&sc->rx.pcu_lock);
+ spin_unlock_bh(&sc->sc_pcu_lock);
goto mutex_unlock;
}
- spin_unlock_bh(&sc->rx.pcu_lock);
+ spin_unlock_bh(&sc->sc_pcu_lock);
/* Setup our intr mask. */
ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
ah->imask |= ATH9K_INT_CST;
sc->sc_flags &= ~SC_OP_INVALID;
+ sc->sc_ah->is_monitoring = false;
/* Disable BMISS interrupt when we're not associated */
ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
ath9k_btcoex_timer_resume(sc);
}
+ pm_qos_update_request(&ath9k_pm_qos_req, 55);
+
mutex_unlock:
mutex_unlock(&sc->mutex);
struct ath_tx_control txctl;
int padpos, padsize;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- int qnum;
if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
ath_print(common, ATH_DBG_XMIT,
memmove(skb->data, skb->data + padsize, padpos);
}
- qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
- txctl.txq = &sc->tx.txq[qnum];
+ txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
ath9k_btcoex_timer_pause(sc);
}
+ spin_lock_bh(&sc->sc_pcu_lock);
+
/* make sure h/w will not generate any interrupt
* before setting the invalid flag. */
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
- spin_lock_bh(&sc->rx.pcu_lock);
if (!(sc->sc_flags & SC_OP_INVALID)) {
ath_drain_all_txq(sc, false);
ath_stoprecv(sc);
ath9k_hw_phy_disable(ah);
} else
sc->rx.rxlink = NULL;
- spin_unlock_bh(&sc->rx.pcu_lock);
/* disable HAL and put h/w to sleep */
ath9k_hw_disable(ah);
ath9k_hw_configpcipowersave(ah, 1, 1);
+
+ spin_unlock_bh(&sc->sc_pcu_lock);
+
ath9k_ps_restore(sc);
/* Finally, put the chip in FULL SLEEP mode */
sc->sc_flags |= SC_OP_INVALID;
+ pm_qos_update_request(&ath9k_pm_qos_req, PM_QOS_DEFAULT_VALUE);
+
mutex_unlock(&sc->mutex);
ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
ath9k_hw_set_interrupts(ah, ah->imask);
if (vif->type == NL80211_IFTYPE_AP ||
- vif->type == NL80211_IFTYPE_ADHOC ||
- vif->type == NL80211_IFTYPE_MONITOR) {
+ vif->type == NL80211_IFTYPE_ADHOC) {
sc->sc_flags |= SC_OP_ANI_RUN;
ath_start_ani(common);
}
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
if (conf->flags & IEEE80211_CONF_MONITOR) {
ath_print(common, ATH_DBG_CONFIG,
- "HW opmode set to Monitor mode\n");
- sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR;
+ "Monitor mode is enabled\n");
+ sc->sc_ah->is_monitoring = true;
+ } else {
+ ath_print(common, ATH_DBG_CONFIG,
+ "Monitor mode is disabled\n");
+ sc->sc_ah->is_monitoring = false;
}
}
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_txq *txq;
struct ath9k_tx_queue_info qi;
- int ret = 0, qnum;
+ int ret = 0;
if (queue >= WME_NUM_AC)
return 0;
+ txq = sc->tx.txq_map[queue];
+
mutex_lock(&sc->mutex);
memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
qi.tqi_cwmin = params->cw_min;
qi.tqi_cwmax = params->cw_max;
qi.tqi_burstTime = params->txop;
- qnum = ath_get_hal_qnum(queue, sc);
ath_print(common, ATH_DBG_CONFIG,
"Configure tx [queue/halq] [%d/%d], "
"aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
- queue, qnum, params->aifs, params->cw_min,
+ queue, txq->axq_qnum, params->aifs, params->cw_min,
params->cw_max, params->txop);
- ret = ath_txq_update(sc, qnum, &qi);
+ ret = ath_txq_update(sc, txq->axq_qnum, &qi);
if (ret)
ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
- if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret)
+ if (queue == WME_AC_BE && !ret)
ath_beaconq_config(sc);
mutex_unlock(&sc->mutex);
if (changed & BSS_CHANGED_ASSOC) {
ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
bss_conf->assoc);
- ath9k_bss_assoc_info(sc, vif, bss_conf);
+ ath9k_bss_assoc_info(sc, hw, vif, bss_conf);
}
mutex_unlock(&sc->mutex);
struct ath_buf *bf;
int error = 0;
- spin_lock_init(&sc->rx.pcu_lock);
+ spin_lock_init(&sc->sc_pcu_lock);
sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_lock_init(&sc->rx.rxbuflock);
*/
if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) &&
(sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
- (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR))
+ (sc->sc_ah->is_monitoring))
rfilt |= ATH9K_RX_FILTER_PROM;
if (sc->rx.rxfilter & FIF_CONTROL)
sc->rx.rxlink = NULL;
spin_unlock_bh(&sc->rx.rxbuflock);
+ ATH_DBG_WARN(!stopped, "Could not stop RX, we could be "
+ "confusing the DMA engine when we start RX up\n");
return stopped;
}
* decryption and MIC failures. For monitor mode,
* we also ignore the CRC error.
*/
- if (ah->opmode == NL80211_IFTYPE_MONITOR) {
+ if (ah->is_monitoring) {
if (rx_stats->rs_status &
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
ATH9K_RXERR_CRC))
struct ieee80211_hdr *hdr,
struct ath_rx_status *rx_stats)
{
+ struct ath_wiphy *aphy = hw->priv;
struct ath_hw *ah = common->ah;
- struct ieee80211_sta *sta;
- struct ath_node *an;
- int last_rssi = ATH_RSSI_DUMMY_MARKER;
+ int last_rssi;
__le16 fc;
+ if (ah->opmode != NL80211_IFTYPE_STATION)
+ return;
+
fc = hdr->frame_control;
+ if (!ieee80211_is_beacon(fc) ||
+ compare_ether_addr(hdr->addr3, common->curbssid))
+ return;
- rcu_read_lock();
- /*
- * XXX: use ieee80211_find_sta! This requires quite a bit of work
- * under the current ath9k virtual wiphy implementation as we have
- * no way of tying a vif to wiphy. Typically vifs are attached to
- * at least one sdata of a wiphy on mac80211 but with ath9k virtual
- * wiphy you'd have to iterate over every wiphy and each sdata.
- */
- if (is_multicast_ether_addr(hdr->addr1))
- sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
- else
- sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
-
- if (sta) {
- an = (struct ath_node *) sta->drv_priv;
- if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
- !rx_stats->rs_moreaggr)
- ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
- last_rssi = an->last_rssi;
- }
- rcu_read_unlock();
+ if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
+ ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
+ last_rssi = aphy->last_rssi;
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
ATH_RSSI_EP_MULTIPLIER);
rx_stats->rs_rssi = 0;
/* Update Beacon RSSI, this is used by ANI. */
- if (ieee80211_is_beacon(fc))
- ah->stats.avgbrssi = rx_stats->rs_rssi;
+ ah->stats.avgbrssi = rx_stats->rs_rssi;
}
/*
{ USB_DEVICE(0x07d1, 0x3c10) },
/* D-Link DWA 160 A2 */
{ USB_DEVICE(0x07d1, 0x3a09) },
+ /* D-Link DWA 130 D */
+ { USB_DEVICE(0x07d1, 0x3a0f) },
/* Netgear WNA1000 */
{ USB_DEVICE(0x0846, 0x9040) },
- /* Netgear WNDA3100 */
+ /* Netgear WNDA3100 (v1) */
{ USB_DEVICE(0x0846, 0x9010) },
/* Netgear WN111 v2 */
{ USB_DEVICE(0x0846, 0x9001), .driver_info = CARL9170_ONE_LED },
* device.
*/
- carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
+ ieee80211_queue_work(ar->hw, &ar->ping_work);
}
} else {
/*
#include "iwl-helpers.h"
#include "iwl-dev.h"
#include "iwl-spectrum.h"
+ #include "iwl-legacy.h"
/*
* module name, copyright, version, etc.
mutex_unlock(&priv->mutex);
}
- void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
+ void iwl3945_post_associate(struct iwl_priv *priv)
{
int rc = 0;
struct ieee80211_conf *conf = NULL;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- if (!vif || !priv->is_open)
+ if (!ctx->vif || !priv->is_open)
return;
- if (vif->type == NL80211_IFTYPE_AP) {
+ if (ctx->vif->type == NL80211_IFTYPE_AP) {
IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
return;
}
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
- vif->bss_conf.aid, ctx->active.bssid_addr);
+ ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
- ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+ ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
- vif->bss_conf.aid, vif->bss_conf.beacon_int);
+ ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
- if (vif->bss_conf.use_short_preamble)
+ if (ctx->vif->bss_conf.use_short_preamble)
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
else
ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
- if (vif->bss_conf.use_short_slot)
+ if (ctx->vif->bss_conf.use_short_slot)
ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
else
ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
iwl3945_commit_rxon(priv, ctx);
- switch (vif->type) {
+ switch (ctx->vif->type) {
case NL80211_IFTYPE_STATION:
iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
break;
break;
default:
IWL_ERR(priv, "%s Should not be called in %d mode\n",
- __func__, vif->type);
+ __func__, ctx->vif->type);
break;
}
}
return NETDEV_TX_OK;
}
- void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
+ void iwl3945_config_ap(struct iwl_priv *priv)
{
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ struct ieee80211_vif *vif = ctx->vif;
int rc = 0;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
ctx->staging.filter_flags |= filter_or;
/*
- * Committing directly here breaks for some reason,
- * but we'll eventually commit the filter flags
- * change anyway.
+ * Not committing directly because hardware can perform a scan,
+ * but even if hw is ready, committing here breaks for some reason,
+ * we'll eventually commit the filter flags change anyway.
*/
mutex_unlock(&priv->mutex);
.attrs = iwl3945_sysfs_entries,
};
- static struct ieee80211_ops iwl3945_hw_ops = {
+ struct ieee80211_ops iwl3945_hw_ops = {
.tx = iwl3945_mac_tx,
.start = iwl3945_mac_start,
.stop = iwl3945_mac_stop,
.add_interface = iwl_mac_add_interface,
.remove_interface = iwl_mac_remove_interface,
- .config = iwl_mac_config,
+ .change_interface = iwl_mac_change_interface,
+ .config = iwl_legacy_mac_config,
.configure_filter = iwl3945_configure_filter,
.set_key = iwl3945_mac_set_key,
.conf_tx = iwl_mac_conf_tx,
- .reset_tsf = iwl_mac_reset_tsf,
- .bss_info_changed = iwl_bss_info_changed,
+ .reset_tsf = iwl_legacy_mac_reset_tsf,
+ .bss_info_changed = iwl_legacy_mac_bss_info_changed,
.hw_scan = iwl_mac_hw_scan,
.sta_add = iwl3945_mac_sta_add,
.sta_remove = iwl_mac_sta_remove,
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
+ priv->tx_power_next = IWL_DEFAULT_TX_POWER;
if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
/* mac80211 allocates memory for this device instance, including
* space for this driver's private structure */
- hw = iwl_alloc_all(cfg, &iwl3945_hw_ops);
+ hw = iwl_alloc_all(cfg);
if (hw == NULL) {
pr_err("Can not allocate network device\n");
err = -ENOMEM;
* "the hard way", rather than using device's scan.
*/
if (iwl3945_mod_params.disable_hw_scan) {
- IWL_ERR(priv, "sw scan support is deprecated\n");
+ dev_printk(KERN_DEBUG, &(pdev->dev),
+ "sw scan support is deprecated\n");
iwl3945_hw_ops.hw_scan = NULL;
}
pci_enable_msi(priv->pci_dev);
- err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
+ err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr,
IRQF_SHARED, DRV_NAME, priv);
if (err) {
IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
.id_table = iwl3945_hw_card_ids,
.probe = iwl3945_pci_probe,
.remove = __devexit_p(iwl3945_pci_remove),
- #ifdef CONFIG_PM
- .suspend = iwl_pci_suspend,
- .resume = iwl_pci_resume,
- #endif
+ .driver.pm = IWL_PM_OPS,
};
static int __init iwl3945_init(void)