summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath9k
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_mac.c26
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c28
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c24
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h16
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c54
-rw-r--r--drivers/net/wireless/ath/ath9k/dynack.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw-ops.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c29
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c79
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h15
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c29
14 files changed, 233 insertions, 87 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 00fb8badbacc..b72d0be716db 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -1004,9 +1004,11 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
case ATH9K_ANI_FIRSTEP_LEVEL:{
u32 level = param;
- value = level;
+ value = level * 2;
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
AR_PHY_FIND_SIG_FIRSTEP, value);
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
+ AR_PHY_FIND_SIG_FIRSTEP_LOW, value);
if (level != aniState->firstepLevel) {
ath_dbg(common, ANI,
@@ -1040,9 +1042,8 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_TIMING5,
AR_PHY_TIMING5_CYCPWR_THR1, value);
- if (IS_CHAN_HT40(ah->curchan))
- REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
- AR_PHY_EXT_TIMING5_CYCPWR_THR1, value);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+ AR_PHY_EXT_TIMING5_CYCPWR_THR1, value - 1);
if (level != aniState->spurImmunityLevel) {
ath_dbg(common, ANI,
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 669cb3747208..2a93519f4bdf 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -381,16 +381,27 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
ts->evm1 = ads->AR_TxEVM1;
ts->evm2 = ads->AR_TxEVM2;
- status = ACCESS_ONCE(ads->ds_ctl4);
- ts->duration[0] = MS(status, AR_PacketDur0);
- ts->duration[1] = MS(status, AR_PacketDur1);
- status = ACCESS_ONCE(ads->ds_ctl5);
- ts->duration[2] = MS(status, AR_PacketDur2);
- ts->duration[3] = MS(status, AR_PacketDur3);
-
return 0;
}
+static int ar9002_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ switch (index) {
+ case 0:
+ return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur0);
+ case 1:
+ return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur1);
+ case 2:
+ return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur2);
+ case 3:
+ return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur3);
+ default:
+ return -1;
+ }
+}
+
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags)
{
@@ -413,4 +424,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
ops->get_isr = ar9002_hw_get_isr;
ops->set_txdesc = ar9002_set_txdesc;
ops->proc_txdesc = ar9002_hw_proc_txdesc;
+ ops->get_duration = ar9002_hw_get_duration;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index e5f7c11fa144..057b1657c428 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -355,11 +355,9 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
struct ar9003_txs *ads;
- struct ar9003_txc *adc;
u32 status;
ads = &ah->ts_ring[ah->ts_tail];
- adc = (struct ar9003_txc *)ads;
status = ACCESS_ONCE(ads->status8);
if ((status & AR_TxDone) == 0)
@@ -428,18 +426,29 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
- status = ACCESS_ONCE(adc->ctl15);
- ts->duration[0] = MS(status, AR_PacketDur0);
- ts->duration[1] = MS(status, AR_PacketDur1);
- status = ACCESS_ONCE(adc->ctl16);
- ts->duration[2] = MS(status, AR_PacketDur2);
- ts->duration[3] = MS(status, AR_PacketDur3);
-
memset(ads, 0, sizeof(*ads));
return 0;
}
+static int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
+{
+ const struct ar9003_txc *adc = ds;
+
+ switch (index) {
+ case 0:
+ return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur0);
+ case 1:
+ return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur1);
+ case 2:
+ return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur2);
+ case 3:
+ return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur3);
+ default:
+ return 0;
+ }
+}
+
void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
{
struct ath_hw_ops *ops = ath9k_hw_ops(hw);
@@ -449,6 +458,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
ops->get_isr = ar9003_hw_get_isr;
ops->set_txdesc = ar9003_set_txdesc;
ops->proc_txdesc = ar9003_hw_proc_txdesc;
+ ops->get_duration = ar9003_hw_get_duration;
}
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 542a8d51d3b0..697c4ae90af0 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -517,6 +517,23 @@ static void ar9003_hw_spur_mitigate(struct ath_hw *ah,
ar9003_hw_spur_mitigate_ofdm(ah, chan);
}
+static u32 ar9003_hw_compute_pll_control_soc(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ u32 pll;
+
+ pll = SM(0x5, AR_RTC_9300_SOC_PLL_REFDIV);
+
+ if (chan && IS_CHAN_HALF_RATE(chan))
+ pll |= SM(0x1, AR_RTC_9300_SOC_PLL_CLKSEL);
+ else if (chan && IS_CHAN_QUARTER_RATE(chan))
+ pll |= SM(0x2, AR_RTC_9300_SOC_PLL_CLKSEL);
+
+ pll |= SM(0x2c, AR_RTC_9300_SOC_PLL_DIV_INT);
+
+ return pll;
+}
+
static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
@@ -1781,7 +1798,12 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->rf_set_freq = ar9003_hw_set_channel;
priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate;
- priv_ops->compute_pll_control = ar9003_hw_compute_pll_control;
+
+ if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah))
+ priv_ops->compute_pll_control = ar9003_hw_compute_pll_control_soc;
+ else
+ priv_ops->compute_pll_control = ar9003_hw_compute_pll_control;
+
priv_ops->set_channel_regs = ar9003_hw_set_channel_regs;
priv_ops->init_bb = ar9003_hw_init_bb;
priv_ops->process_ini = ar9003_hw_process_ini;
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 8cd116efe3ea..bfa0b1518da1 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -354,6 +354,7 @@ struct ath_chanctx {
bool switch_after_beacon;
short nvifs;
+ short nvifs_assigned;
unsigned int rxfilter;
};
@@ -454,7 +455,8 @@ void ath9k_p2p_bss_info_changed(struct ath_softc *sc,
void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp,
struct sk_buff *skb);
void ath9k_p2p_ps_timer(void *priv);
-void ath9k_chanctx_wake_queues(struct ath_softc *sc);
+void ath9k_chanctx_wake_queues(struct ath_softc *sc, struct ath_chanctx *ctx);
+void ath9k_chanctx_stop_queues(struct ath_softc *sc, struct ath_chanctx *ctx);
void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx);
void ath_chanctx_beacon_recv_ev(struct ath_softc *sc,
@@ -524,7 +526,12 @@ static inline void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *av
static inline void ath9k_p2p_ps_timer(struct ath_softc *sc)
{
}
-static inline void ath9k_chanctx_wake_queues(struct ath_softc *sc)
+static inline void ath9k_chanctx_wake_queues(struct ath_softc *sc,
+ struct ath_chanctx *ctx)
+{
+}
+static inline void ath9k_chanctx_stop_queues(struct ath_softc *sc,
+ struct ath_chanctx *ctx)
{
}
static inline void ath_chanctx_check_active(struct ath_softc *sc,
@@ -585,6 +592,11 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
struct ath_vif {
struct list_head list;
+ /* BSS info */
+ u8 bssid[ETH_ALEN];
+ u16 aid;
+ bool assoc;
+
struct ieee80211_vif *vif;
struct ath_node mcast_node;
int av_bslot;
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 77c99eb55834..945c89826b14 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -211,7 +211,7 @@ void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
switch (vif->type) {
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION:
- if (vif->bss_conf.assoc)
+ if (avp->assoc)
active = true;
break;
default:
@@ -761,6 +761,13 @@ void ath_offchannel_next(struct ath_softc *sc)
void ath_roc_complete(struct ath_softc *sc, bool abort)
{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+ if (abort)
+ ath_dbg(common, CHAN_CTX, "RoC aborted\n");
+ else
+ ath_dbg(common, CHAN_CTX, "RoC expired\n");
+
sc->offchannel.roc_vif = NULL;
sc->offchannel.roc_chan = NULL;
if (!abort)
@@ -917,7 +924,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
switch (vif->type) {
case NL80211_IFTYPE_STATION:
- if (!vif->bss_conf.assoc)
+ if (!avp->assoc)
return false;
skb = ieee80211_nullfunc_get(sc->hw, vif);
@@ -1037,9 +1044,11 @@ static void ath_offchannel_channel_change(struct ath_softc *sc)
void ath_chanctx_set_next(struct ath_softc *sc, bool force)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_chanctx *old_ctx;
struct timespec ts;
bool measure_time = false;
bool send_ps = false;
+ bool queues_stopped = false;
spin_lock_bh(&sc->chan_lock);
if (!sc->next_chan) {
@@ -1069,6 +1078,10 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
getrawmonotonic(&ts);
measure_time = true;
}
+
+ ath9k_chanctx_stop_queues(sc, sc->cur_chan);
+ queues_stopped = true;
+
__ath9k_flush(sc->hw, ~0, true);
if (ath_chanctx_send_ps_frame(sc, true))
@@ -1082,6 +1095,7 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah);
}
}
+ old_ctx = sc->cur_chan;
sc->cur_chan = sc->next_chan;
sc->cur_chan->stopped = false;
sc->next_chan = NULL;
@@ -1104,7 +1118,16 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
if (measure_time)
sc->sched.channel_switch_time =
ath9k_hw_get_tsf_offset(&ts, NULL);
+ /*
+ * A reset will ensure that all queues are woken up,
+ * so there is no need to awaken them again.
+ */
+ goto out;
}
+
+ if (queues_stopped)
+ ath9k_chanctx_wake_queues(sc, old_ctx);
+out:
if (send_ps)
ath_chanctx_send_ps_frame(sc, false);
@@ -1170,18 +1193,37 @@ bool ath9k_is_chanctx_enabled(void)
/* Queue management */
/********************/
-void ath9k_chanctx_wake_queues(struct ath_softc *sc)
+void ath9k_chanctx_stop_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ int i;
+
+ if (ctx == &sc->offchannel.chan) {
+ ieee80211_stop_queue(sc->hw,
+ sc->hw->offchannel_tx_hw_queue);
+ } else {
+ for (i = 0; i < IEEE80211_NUM_ACS; i++)
+ ieee80211_stop_queue(sc->hw,
+ ctx->hw_queue_base + i);
+ }
+
+ if (ah->opmode == NL80211_IFTYPE_AP)
+ ieee80211_stop_queue(sc->hw, sc->hw->queues - 2);
+}
+
+
+void ath9k_chanctx_wake_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
{
struct ath_hw *ah = sc->sc_ah;
int i;
- if (sc->cur_chan == &sc->offchannel.chan) {
+ if (ctx == &sc->offchannel.chan) {
ieee80211_wake_queue(sc->hw,
sc->hw->offchannel_tx_hw_queue);
} else {
for (i = 0; i < IEEE80211_NUM_ACS; i++)
ieee80211_wake_queue(sc->hw,
- sc->cur_chan->hw_queue_base + i);
+ ctx->hw_queue_base + i);
}
if (ah->opmode == NL80211_IFTYPE_AP)
@@ -1339,7 +1381,7 @@ void ath9k_p2p_ps_timer(void *priv)
rcu_read_lock();
vif = avp->vif;
- sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
+ sta = ieee80211_find_sta(vif, avp->bssid);
if (!sta)
goto out;
diff --git a/drivers/net/wireless/ath/ath9k/dynack.c b/drivers/net/wireless/ath/ath9k/dynack.c
index 6ae8e0bc9e1f..22b3cc4c27cd 100644
--- a/drivers/net/wireless/ath/ath9k/dynack.c
+++ b/drivers/net/wireless/ath/ath9k/dynack.c
@@ -202,7 +202,7 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
ridx = ts->ts_rateindex;
da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp;
- da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration[ts->ts_rateindex];
+ da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration;
ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1);
ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2);
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index a47ea8423f1e..8e85efeaeffc 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -67,6 +67,12 @@ static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
}
+static inline int ath9k_hw_get_duration(struct ath_hw *ah, const void *ds,
+ int index)
+{
+ return ath9k_hw_ops(ah)->get_duration(ah, ds, index);
+}
+
static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
struct ath_hw_antcomb_conf *antconf)
{
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 3aed729e4d5e..8be4b1453394 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -222,31 +222,28 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
{
u32 val;
+ if (ah->get_mac_revision)
+ ah->hw_version.macRev = ah->get_mac_revision();
+
switch (ah->hw_version.devid) {
case AR5416_AR9100_DEVID:
ah->hw_version.macVersion = AR_SREV_VERSION_9100;
break;
case AR9300_DEVID_AR9330:
ah->hw_version.macVersion = AR_SREV_VERSION_9330;
- if (ah->get_mac_revision) {
- ah->hw_version.macRev = ah->get_mac_revision();
- } else {
+ if (!ah->get_mac_revision) {
val = REG_READ(ah, AR_SREV);
ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
}
return;
case AR9300_DEVID_AR9340:
ah->hw_version.macVersion = AR_SREV_VERSION_9340;
- val = REG_READ(ah, AR_SREV);
- ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
return;
case AR9300_DEVID_QCA955X:
ah->hw_version.macVersion = AR_SREV_VERSION_9550;
return;
case AR9300_DEVID_AR953X:
ah->hw_version.macVersion = AR_SREV_VERSION_9531;
- if (ah->get_mac_revision)
- ah->hw_version.macRev = ah->get_mac_revision();
return;
}
@@ -704,6 +701,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
{
u32 pll;
+ pll = ath9k_hw_compute_pll_control(ah, chan);
+
if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) {
/* program BB PLL ki and kd value, ki=0x4, kd=0x40 */
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
@@ -754,7 +753,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
AR_CH0_DPLL3_PHASE_SHIFT, 0x1);
- REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+ REG_WRITE(ah, AR_RTC_PLL_CONTROL,
+ pll | AR_RTC_9300_PLL_BYPASS);
udelay(1000);
/* program refdiv, nint, frac to RTC register */
@@ -770,7 +770,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
} else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
u32 regval, pll2_divint, pll2_divfrac, refdiv;
- REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+ REG_WRITE(ah, AR_RTC_PLL_CONTROL,
+ pll | AR_RTC_9300_SOC_PLL_BYPASS);
udelay(1000);
REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1 << 16);
@@ -843,7 +844,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
udelay(1000);
}
- pll = ath9k_hw_compute_pll_control(ah, chan);
if (AR_SREV_9565(ah))
pll |= 0x40000;
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
@@ -1192,9 +1192,12 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
switch (opmode) {
case NL80211_IFTYPE_ADHOC:
- set |= AR_STA_ID1_ADHOC;
- REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
- break;
+ if (!AR_SREV_9340_13(ah)) {
+ set |= AR_STA_ID1_ADHOC;
+ REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+ break;
+ }
+ /* fall through */
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
set |= AR_STA_ID1_STA_AP;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index b9eef3362fbb..975074fc11bc 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -691,6 +691,7 @@ struct ath_hw_ops {
struct ath_tx_info *i);
int (*proc_txdesc)(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts);
+ int (*get_duration)(struct ath_hw *ah, const void *ds, int index);
void (*antdiv_comb_conf_get)(struct ath_hw *ah,
struct ath_hw_antcomb_conf *antconf);
void (*antdiv_comb_conf_set)(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index cd05a7791073..aa69ceaad0be 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -121,7 +121,7 @@ struct ath_tx_status {
u32 evm0;
u32 evm1;
u32 evm2;
- u32 duration[4];
+ u32 duration;
};
struct ath_rx_status {
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index fbf23ac61c97..205162449b72 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -60,8 +60,10 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
spin_lock_bh(&txq->axq_lock);
- if (txq->axq_depth)
+ if (txq->axq_depth) {
pending = true;
+ goto out;
+ }
if (txq->mac80211_qnum >= 0) {
struct list_head *list;
@@ -70,6 +72,7 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
if (!list_empty(list))
pending = true;
}
+out:
spin_unlock_bh(&txq->axq_lock);
return pending;
}
@@ -261,12 +264,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
ath9k_hw_set_interrupts(ah);
ath9k_hw_enable_interrupts(ah);
-
- if (!ath9k_is_chanctx_enabled())
- ieee80211_wake_queues(sc->hw);
- else
- ath9k_chanctx_wake_queues(sc);
-
+ ieee80211_wake_queues(sc->hw);
ath9k_p2p_ps_timer(sc);
return true;
@@ -898,6 +896,7 @@ static bool ath9k_uses_beacons(int type)
static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
u8 *mac, struct ieee80211_vif *vif)
{
+ struct ath_vif *avp = (struct ath_vif *)vif->drv_priv;
int i;
if (iter_data->has_hw_macaddr) {
@@ -918,7 +917,7 @@ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
break;
case NL80211_IFTYPE_STATION:
iter_data->nstations++;
- if (vif->bss_conf.assoc && !iter_data->primary_sta)
+ if (avp->assoc && !iter_data->primary_sta)
iter_data->primary_sta = vif;
break;
case NL80211_IFTYPE_ADHOC:
@@ -939,6 +938,34 @@ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
}
}
+static void ath9k_update_bssid_mask(struct ath_softc *sc,
+ struct ath_chanctx *ctx,
+ struct ath9k_vif_iter_data *iter_data)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_vif *avp;
+ int i;
+
+ if (!ath9k_is_chanctx_enabled())
+ return;
+
+ list_for_each_entry(avp, &ctx->vifs, list) {
+ if (ctx->nvifs_assigned != 1)
+ continue;
+
+ if (!avp->vif->p2p || !iter_data->has_hw_macaddr)
+ continue;
+
+ ether_addr_copy(common->curbssid, avp->bssid);
+
+ /* perm_addr will be used as the p2p device address. */
+ for (i = 0; i < ETH_ALEN; i++)
+ iter_data->mask[i] &=
+ ~(iter_data->hw_macaddr[i] ^
+ sc->hw->wiphy->perm_addr[i]);
+ }
+}
+
/* Called with sc->mutex held. */
void ath9k_calculate_iter_data(struct ath_softc *sc,
struct ath_chanctx *ctx,
@@ -957,19 +984,21 @@ void ath9k_calculate_iter_data(struct ath_softc *sc,
list_for_each_entry(avp, &ctx->vifs, list)
ath9k_vif_iter(iter_data, avp->vif->addr, avp->vif);
+
+ ath9k_update_bssid_mask(sc, ctx, iter_data);
}
static void ath9k_set_assoc_state(struct ath_softc *sc,
struct ieee80211_vif *vif, bool changed)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ struct ath_vif *avp = (struct ath_vif *)vif->drv_priv;
unsigned long flags;
set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
- ether_addr_copy(common->curbssid, bss_conf->bssid);
- common->curaid = bss_conf->aid;
+ ether_addr_copy(common->curbssid, avp->bssid);
+ common->curaid = avp->aid;
ath9k_hw_write_associd(sc->sc_ah);
if (changed) {
@@ -1121,6 +1150,10 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
else
clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
+ ath_dbg(common, CONFIG,
+ "macaddr: %pM, bssid: %pM, bssidmask: %pM\n",
+ common->macaddr, common->curbssid, common->bssidmask);
+
ath9k_ps_restore(sc);
}
@@ -1698,6 +1731,10 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
bss_conf->bssid, bss_conf->assoc);
+ ether_addr_copy(avp->bssid, bss_conf->bssid);
+ avp->aid = bss_conf->aid;
+ avp->assoc = bss_conf->assoc;
+
ath9k_calculate_summary_state(sc, avp->chanctx);
if (ath9k_is_chanctx_enabled()) {
@@ -1932,9 +1969,6 @@ static bool ath9k_has_tx_pending(struct ath_softc *sc)
if (!ATH_TXQ_SETUP(sc, i))
continue;
- if (!sc->tx.txq[i].axq_depth)
- continue;
-
npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
if (npend)
break;
@@ -1960,7 +1994,6 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
struct ath_common *common = ath9k_hw_common(ah);
int timeout = HZ / 5; /* 200 ms */
bool drain_txq;
- int i;
cancel_delayed_work_sync(&sc->tx_complete_work);
@@ -1988,10 +2021,6 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
ath_reset(sc);
ath9k_ps_restore(sc);
- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
- ieee80211_wake_queue(sc->hw,
- sc->cur_chan->hw_queue_base + i);
- }
}
ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
@@ -2000,16 +2029,8 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
- int i;
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
- if (!ATH_TXQ_SETUP(sc, i))
- continue;
-
- if (ath9k_has_pending_frames(sc, &sc->tx.txq[i]))
- return true;
- }
- return false;
+ return ath9k_has_tx_pending(sc);
}
static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
@@ -2351,6 +2372,7 @@ static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw,
conf->def.chan->center_freq);
avp->chanctx = ctx;
+ ctx->nvifs_assigned++;
list_add_tail(&avp->list, &ctx->vifs);
ath9k_calculate_summary_state(sc, ctx);
for (i = 0; i < IEEE80211_NUM_ACS; i++)
@@ -2379,6 +2401,7 @@ static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw,
conf->def.chan->center_freq);
avp->chanctx = NULL;
+ ctx->nvifs_assigned--;
list_del(&avp->list);
ath9k_calculate_summary_state(sc, ctx);
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index a1499700bcf2..2a938f4feac5 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -903,6 +903,10 @@
#define AR_SREV_9340(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340))
+#define AR_SREV_9340_13(_ah) \
+ (AR_SREV_9340((_ah)) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9340_13))
+
#define AR_SREV_9340_13_OR_LATER(_ah) \
(AR_SREV_9340((_ah)) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9340_13))
@@ -1240,12 +1244,23 @@ enum {
#define AR_CH0_DPLL3_PHASE_SHIFT_S 23
#define AR_PHY_CCA_NOM_VAL_2GHZ -118
+#define AR_RTC_9300_SOC_PLL_DIV_INT 0x0000003f
+#define AR_RTC_9300_SOC_PLL_DIV_INT_S 0
+#define AR_RTC_9300_SOC_PLL_DIV_FRAC 0x000fffc0
+#define AR_RTC_9300_SOC_PLL_DIV_FRAC_S 6
+#define AR_RTC_9300_SOC_PLL_REFDIV 0x01f00000
+#define AR_RTC_9300_SOC_PLL_REFDIV_S 20
+#define AR_RTC_9300_SOC_PLL_CLKSEL 0x06000000
+#define AR_RTC_9300_SOC_PLL_CLKSEL_S 25
+#define AR_RTC_9300_SOC_PLL_BYPASS 0x08000000
+
#define AR_RTC_9300_PLL_DIV 0x000003ff
#define AR_RTC_9300_PLL_DIV_S 0
#define AR_RTC_9300_PLL_REFDIV 0x00003C00
#define AR_RTC_9300_PLL_REFDIV_S 10
#define AR_RTC_9300_PLL_CLKSEL 0x0000C000
#define AR_RTC_9300_PLL_CLKSEL_S 14
+#define AR_RTC_9300_PLL_BYPASS 0x00010000
#define AR_RTC_9160_PLL_DIV 0x000003ff
#define AR_RTC_9160_PLL_DIV_S 0
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 93ad31be0ada..151ae49fa57e 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -158,7 +158,6 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ath_frame_info *fi = get_frame_info(skb);
- int hw_queue;
int q = fi->txq;
if (q < 0)
@@ -168,10 +167,9 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
if (WARN_ON(--txq->pending_frames < 0))
txq->pending_frames = 0;
- hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue;
if (txq->stopped &&
txq->pending_frames < sc->tx.txq_max_pending[q]) {
- ieee80211_wake_queue(sc->hw, hw_queue);
+ ieee80211_wake_queue(sc->hw, info->hw_queue);
txq->stopped = false;
}
}
@@ -685,6 +683,8 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth--;
+ ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc,
+ ts->ts_rateindex);
if (!bf_isampdu(bf)) {
if (!flush) {
info = IEEE80211_SKB_CB(bf->bf_mpdu);
@@ -1841,15 +1841,17 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
if (txq->mac80211_qnum < 0)
return;
+ if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
+ return;
+
spin_lock_bh(&sc->chan_lock);
ac_list = &sc->cur_chan->acq[txq->mac80211_qnum];
- spin_unlock_bh(&sc->chan_lock);
- if (test_bit(ATH_OP_HW_RESET, &common->op_flags) ||
- list_empty(ac_list))
+ if (list_empty(ac_list)) {
+ spin_unlock_bh(&sc->chan_lock);
return;
+ }
- spin_lock_bh(&sc->chan_lock);
rcu_read_lock();
last_ac = list_entry(ac_list->prev, struct ath_atx_ac, list);
@@ -2207,9 +2209,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_txq *txq = txctl->txq;
struct ath_atx_tid *tid = NULL;
struct ath_buf *bf;
- bool queue;
- int q, hw_queue;
- int ret;
+ bool queue, skip_uapsd = false;
+ int q, ret;
if (vif)
avp = (void *)vif->drv_priv;
@@ -2228,14 +2229,13 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
*/
q = skb_get_queue_mapping(skb);
- hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue;
ath_txq_lock(sc, txq);
if (txq == sc->tx.txq_map[q]) {
fi->txq = q;
if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
!txq->stopped) {
- ieee80211_stop_queue(sc->hw, hw_queue);
+ ieee80211_stop_queue(sc->hw, info->hw_queue);
txq->stopped = true;
}
}
@@ -2250,15 +2250,14 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
sc->cur_chan->stopped) && !txctl->force_channel) {
if (!txctl->an)
txctl->an = &avp->mcast_node;
- info->flags &= ~IEEE80211_TX_CTL_PS_RESPONSE;
queue = true;
+ skip_uapsd = true;
}
if (txctl->an && queue)
tid = ath_get_skb_tid(sc, txctl->an, skb);
- if (info->flags & (IEEE80211_TX_CTL_PS_RESPONSE |
- IEEE80211_TX_CTL_TX_OFFCHAN)) {
+ if (!skip_uapsd && (info->flags & IEEE80211_TX_CTL_PS_RESPONSE)) {
ath_txq_unlock(sc, txq);
txq = sc->tx.uapsdq;
ath_txq_lock(sc, txq);