Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/hw.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 373cef6..122447c 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -992,6 +992,11 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
rx_lat = 37;
tx_lat = 54;
+ if (IS_CHAN_5GHZ(chan))
+ sifstime = 16;
+ else
+ sifstime = 10;
+
if (IS_CHAN_HALF_RATE(chan)) {
eifs = 175;
rx_lat *= 2;
@@ -999,8 +1004,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
tx_lat += 11;
+ sifstime *= 2;
slottime = 13;
- sifstime = 32;
} else if (IS_CHAN_QUARTER_RATE(chan)) {
eifs = 340;
rx_lat = (rx_lat * 4) - 1;
@@ -1008,8 +1013,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
tx_lat += 22;
+ sifstime *= 4;
slottime = 21;
- sifstime = 64;
} else {
if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO;
@@ -1023,10 +1028,6 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
tx_lat = MS(reg, AR_USEC_TX_LAT);
slottime = ah->slottime;
- if (IS_CHAN_5GHZ(chan))
- sifstime = 16;
- else
- sifstime = 10;
}
/* As defined by IEEE 802.11-2007 17.3.8.6 */
--
1.7.3.2
Felix Fietkau wrote:
> Signed-off-by: Felix Fietkau <[email protected]>
> ---
> drivers/net/wireless/ath/ath9k/hw.c | 4 ++++
> 1 files changed, 4 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
> index ff8d58d..26e6083 100644
> --- a/drivers/net/wireless/ath/ath9k/hw.c
> +++ b/drivers/net/wireless/ath/ath9k/hw.c
> @@ -1440,6 +1440,10 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
> CHANNEL_5GHZ));
> mode_diff = (chan->chanmode != ah->curchan->chanmode);
>
> + if ((ah->curchan->channelFlags | chan->channelFlags) &
> + (CHANNEL_HALF | CHANNEL_QUARTER))
> + return false;
> +
ath9k_hw_do_fastcc() is a better place where this check can be done.
Sujith
The delay calculation is the same for all chips, however some parts of the
code missed the extra delay factor for half/quarter.
Clean up the code and move the delay calculation to a common place.
Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar5008_phy.c | 17 ++---------------
drivers/net/wireless/ath/ath9k/ar9003_phy.c | 20 ++------------------
drivers/net/wireless/ath/ath9k/hw.c | 16 ++++++++++++++++
drivers/net/wireless/ath/ath9k/hw.h | 2 ++
4 files changed, 22 insertions(+), 33 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index de30cb3..f554bff 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -618,19 +618,10 @@ static void ar5008_hw_init_bb(struct ath_hw *ah,
u32 synthDelay;
synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
- if (IS_CHAN_B(chan))
- synthDelay = (4 * synthDelay) / 22;
- else
- synthDelay /= 10;
-
- if (IS_CHAN_HALF_RATE(chan))
- synthDelay *= 2;
- else if (IS_CHAN_QUARTER_RATE(chan))
- synthDelay *= 4;
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
- udelay(synthDelay + BASE_ACTIVATE_DELAY);
+ ath9k_hw_synth_delay(ah, chan, synthDelay);
}
static void ar5008_hw_init_chain_masks(struct ath_hw *ah)
@@ -948,12 +939,8 @@ static bool ar5008_hw_rfbus_req(struct ath_hw *ah)
static void ar5008_hw_rfbus_done(struct ath_hw *ah)
{
u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
- if (IS_CHAN_B(ah->curchan))
- synthDelay = (4 * synthDelay) / 22;
- else
- synthDelay /= 10;
- udelay(synthDelay + BASE_ACTIVATE_DELAY);
+ ath9k_hw_synth_delay(ah, ah->curchan, synthDelay);
REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 5bc09a1..00afab5 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -524,22 +524,10 @@ static void ar9003_hw_init_bb(struct ath_hw *ah,
* Value is in 100ns increments.
*/
synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
- if (IS_CHAN_B(chan))
- synthDelay = (4 * synthDelay) / 22;
- else
- synthDelay /= 10;
/* Activate the PHY (includes baseband activate + synthesizer on) */
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
-
- /*
- * There is an issue if the AP starts the calibration before
- * the base band timeout completes. This could result in the
- * rx_clear false triggering. As a workaround we add delay an
- * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
- * does not happen.
- */
- udelay(synthDelay + BASE_ACTIVATE_DELAY);
+ ath9k_hw_synth_delay(ah, chan, synthDelay);
}
static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
@@ -799,12 +787,8 @@ static bool ar9003_hw_rfbus_req(struct ath_hw *ah)
static void ar9003_hw_rfbus_done(struct ath_hw *ah)
{
u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
- if (IS_CHAN_B(ah->curchan))
- synthDelay = (4 * synthDelay) / 22;
- else
- synthDelay /= 10;
- udelay(synthDelay + BASE_ACTIVATE_DELAY);
+ ath9k_hw_synth_delay(ah, ah->curchan, synthDelay);
REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
}
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 0b16e30..ff8d58d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -142,6 +142,22 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
}
EXPORT_SYMBOL(ath9k_hw_wait);
+void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan,
+ int hw_delay)
+{
+ if (IS_CHAN_B(chan))
+ hw_delay = (4 * hw_delay) / 22;
+ else
+ hw_delay /= 10;
+
+ if (IS_CHAN_HALF_RATE(chan))
+ hw_delay *= 2;
+ else if (IS_CHAN_QUARTER_RATE(chan))
+ hw_delay *= 4;
+
+ udelay(hw_delay + BASE_ACTIVATE_DELAY);
+}
+
void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array,
int column, unsigned int *writecnt)
{
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 1d4b983..a411646 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -923,6 +923,8 @@ void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
/* General Operation */
+void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan,
+ int hw_delay);
bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array,
int column, unsigned int *writecnt);
--
1.7.3.2
Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/hw.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index ff8d58d..26e6083 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1440,6 +1440,10 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
CHANNEL_5GHZ));
mode_diff = (chan->chanmode != ah->curchan->chanmode);
+ if ((ah->curchan->channelFlags | chan->channelFlags) &
+ (CHANNEL_HALF | CHANNEL_QUARTER))
+ return false;
+
for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
if (ath9k_hw_numtxpending(ah, qnum)) {
ath_dbg(common, QUEUE,
--
1.7.3.2
Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_phy.c | 4 ++++
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 3 +++
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index b9f88a2..5bc09a1 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -726,6 +726,10 @@ static void ar9003_hw_set_rfmode(struct ath_hw *ah,
if (IS_CHAN_HALF_RATE(chan))
rfMode |= AR_PHY_MODE_HALF;
+ if (rfMode & (AR_PHY_MODE_QUARTER | AR_PHY_MODE_HALF))
+ REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
+ AR_PHY_FRAME_CTL_CF_OVERLAP_WINDOW, 3);
+
REG_WRITE(ah, AR_PHY_MODE, rfMode);
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index d834d97..7268a48 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -468,6 +468,9 @@
#define AR_PHY_ADDAC_PARA_CTL (AR_SM_BASE + 0x150)
#define AR_PHY_XPA_CFG (AR_SM_BASE + 0x158)
+#define AR_PHY_FRAME_CTL_CF_OVERLAP_WINDOW 3
+#define AR_PHY_FRAME_CTL_CF_OVERLAP_WINDOW_S 0
+
#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A 0x0001FC00
#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A_S 10
#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A 0x3FF
--
1.7.3.2
Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/mac.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index f7bd253..04ef775 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -133,8 +133,16 @@ EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
{
+ int maxdelay = 1000;
int i, q;
+ if (ah->curchan) {
+ if (IS_CHAN_HALF_RATE(ah->curchan))
+ maxdelay *= 2;
+ else if (IS_CHAN_QUARTER_RATE(ah->curchan))
+ maxdelay *= 4;
+ }
+
REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
@@ -142,7 +150,7 @@ void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
for (q = 0; q < AR_NUM_QCU; q++) {
- for (i = 0; i < 1000; i++) {
+ for (i = 0; i < maxdelay; i++) {
if (i)
udelay(5);
--
1.7.3.2
For some reason the MAC timing is a bit off when waiting for ACKs, so add
some extra delay to the ACK timeout values. Significantly reduces the
number of retransmissions in my tests.
Also disable the 2.4 GHz ACK timeout workaround in half/quarter mode, it
is not required there.
Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/hw.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 122447c..0b16e30 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -971,7 +971,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
const struct ath9k_channel *chan = ah->curchan;
- int acktimeout, ctstimeout;
+ int acktimeout, ctstimeout, ack_offset = 0;
int slottime;
int sifstime;
int rx_lat = 0, tx_lat = 0, eifs = 0;
@@ -1005,6 +1005,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
tx_lat += 11;
sifstime *= 2;
+ ack_offset = 16;
slottime = 13;
} else if (IS_CHAN_QUARTER_RATE(chan)) {
eifs = 340;
@@ -1014,6 +1015,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
tx_lat += 22;
sifstime *= 4;
+ ack_offset = 32;
slottime = 21;
} else {
if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
@@ -1031,7 +1033,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
}
/* As defined by IEEE 802.11-2007 17.3.8.6 */
- acktimeout = slottime + sifstime + 3 * ah->coverage_class;
+ acktimeout = slottime + sifstime + 3 * ah->coverage_class + ack_offset;
ctstimeout = acktimeout;
/*
@@ -1041,7 +1043,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
* BA frames in some implementations, but it has been found to fix ACK
* timeout issues in other cases as well.
*/
- if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) {
+ if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ &&
+ !IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) {
acktimeout += 64 - sifstime - ah->slottime;
ctstimeout += 48 - sifstime - ah->slottime;
}
--
1.7.3.2
It does not work properly and reduces throughput.
Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_calib.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 63089cc..a0387a0 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -1000,10 +1000,12 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
if (mci && IS_CHAN_2GHZ(chan) && run_agc_cal)
ar9003_mci_init_cal_req(ah, &is_reusable);
- txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
- udelay(5);
- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+ if (!(IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))) {
+ txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+ udelay(5);
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+ }
skip_tx_iqcal:
if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
--
1.7.3.2
Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_phy.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 4c9bc9f..b9f88a2 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -721,6 +721,10 @@ static void ar9003_hw_set_rfmode(struct ath_hw *ah,
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
+ if (IS_CHAN_QUARTER_RATE(chan))
+ rfMode |= AR_PHY_MODE_QUARTER;
+ if (IS_CHAN_HALF_RATE(chan))
+ rfMode |= AR_PHY_MODE_HALF;
REG_WRITE(ah, AR_PHY_MODE, rfMode);
}
--
1.7.3.2
On 2012-04-17 6:01 AM, Sujith Manoharan wrote:
> Felix Fietkau wrote:
>> Signed-off-by: Felix Fietkau <[email protected]>
>> ---
>> drivers/net/wireless/ath/ath9k/hw.c | 4 ++++
>> 1 files changed, 4 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
>> index ff8d58d..26e6083 100644
>> --- a/drivers/net/wireless/ath/ath9k/hw.c
>> +++ b/drivers/net/wireless/ath/ath9k/hw.c
>> @@ -1440,6 +1440,10 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
>> CHANNEL_5GHZ));
>> mode_diff = (chan->chanmode != ah->curchan->chanmode);
>>
>> + if ((ah->curchan->channelFlags | chan->channelFlags) &
>> + (CHANNEL_HALF | CHANNEL_QUARTER))
>> + return false;
>> +
>
> ath9k_hw_do_fastcc() is a better place where this check can be done.
OK, will send a v3.
- Felix