2012-04-15 10:15:52

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 1/9] ath9k_hw: use lower rx latency values for half/quarter channels

Visibly improves performance on AR9280 and AR9380 - values obtained from
register dumps of UBNT NanoStation M2/M5.

Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/hw.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 373cef6..c7faf10 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -994,7 +994,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)

if (IS_CHAN_HALF_RATE(chan)) {
eifs = 175;
- rx_lat *= 2;
+ rx_lat = 10;
tx_lat *= 2;
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
tx_lat += 11;
@@ -1003,7 +1003,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
sifstime = 32;
} else if (IS_CHAN_QUARTER_RATE(chan)) {
eifs = 340;
- rx_lat = (rx_lat * 4) - 1;
+ rx_lat = 20;
tx_lat *= 4;
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
tx_lat += 22;
--
1.7.3.2



2012-04-15 10:15:52

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 7/9] ath9k_hw: disable Tx IQ calibration on half/quarter channels

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


2012-04-15 10:15:52

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 6/9] ath9k_hw: increase ACK timeout for half/quarter channels

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 5df42ab..bb7e097 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -987,7 +987,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;
@@ -1015,6 +1015,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
tx_lat += 11;

+ ack_offset = 16;
slottime = 13;
} else if (IS_CHAN_QUARTER_RATE(chan)) {
eifs = 340;
@@ -1023,6 +1024,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
tx_lat += 22;

+ ack_offset = 32;
slottime = 21;
} else {
if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
@@ -1045,7 +1047,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
sifstime = 10;

/* 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;

/*
@@ -1055,7 +1057,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


2012-04-15 10:15:52

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 4/9] ath9k_hw: increase symbol overlap window for half/quarter channels

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


2012-04-15 18:22:35

by Daniel Halperin

[permalink] [raw]
Subject: Re: [PATCH 2/9] ath9k_hw: do not override SIFS time for half/quarter channels

Felix,

This whole patch series throws the NICs out of spec compliance. For
instance, page 626 of the 802.11-2007 standard (Table 17-15) says that
aSIFStime is 32 us in 10 MHz mode and 64 us in 5 MHz mode.

This might be okay to do for certain implementations (as, apparently,
AR9280/AR9380), but will break compatibility with any device obeying
the standard instead.

(I wonder that, if this code below still works, then it seems that you
might not be properly downclocking the chips' reference clock...)

Are you aware there's a standard for this? Why violate it?

Dan

On Sun, Apr 15, 2012 at 3:15 AM, Felix Fietkau <[email protected]> wrote:
> Significantly improves performance on AR9280/AR9380
>
> Signed-off-by: Felix Fietkau <[email protected]>
> ---
> ?drivers/net/wireless/ath/ath9k/hw.c | ? 11 +++++------
> ?1 files changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
> index c7faf10..e408aaf 100644
> --- a/drivers/net/wireless/ath/ath9k/hw.c
> +++ b/drivers/net/wireless/ath/ath9k/hw.c
> @@ -1000,7 +1000,6 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
> ? ? ? ? ? ? ? ? ? ?tx_lat += 11;
>
> ? ? ? ? ? ? ? ?slottime = 13;
> - ? ? ? ? ? ? ? sifstime = 32;
> ? ? ? ?} else if (IS_CHAN_QUARTER_RATE(chan)) {
> ? ? ? ? ? ? ? ?eifs = 340;
> ? ? ? ? ? ? ? ?rx_lat = 20;
> @@ -1009,7 +1008,6 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
> ? ? ? ? ? ? ? ? ? ?tx_lat += 22;
>
> ? ? ? ? ? ? ? ?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,12 +1021,13 @@ 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;
> ? ? ? ?}
>
> + ? ? ? if (IS_CHAN_5GHZ(chan))
> + ? ? ? ? ? ? ? sifstime = 16;
> + ? ? ? else
> + ? ? ? ? ? ? ? sifstime = 10;
> +
> ? ? ? ?/* As defined by IEEE 802.11-2007 17.3.8.6 */
> ? ? ? ?acktimeout = slottime + sifstime + 3 * ah->coverage_class;
> ? ? ? ?ctstimeout = acktimeout;
> --
> 1.7.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html

2012-04-15 10:15:52

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 5/9] ath9k_hw: fix and clean up PHY activation delay

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 e408aaf..5df42ab 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


2012-04-15 10:15:52

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 2/9] ath9k_hw: do not override SIFS time for half/quarter channels

Significantly improves performance on AR9280/AR9380

Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/hw.c | 11 +++++------
1 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index c7faf10..e408aaf 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1000,7 +1000,6 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
tx_lat += 11;

slottime = 13;
- sifstime = 32;
} else if (IS_CHAN_QUARTER_RATE(chan)) {
eifs = 340;
rx_lat = 20;
@@ -1009,7 +1008,6 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
tx_lat += 22;

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,12 +1021,13 @@ 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;
}

+ if (IS_CHAN_5GHZ(chan))
+ sifstime = 16;
+ else
+ sifstime = 10;
+
/* As defined by IEEE 802.11-2007 17.3.8.6 */
acktimeout = slottime + sifstime + 3 * ah->coverage_class;
ctstimeout = acktimeout;
--
1.7.3.2


2012-04-16 09:44:53

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 2/9] ath9k_hw: do not override SIFS time for half/quarter channels

On 2012-04-16 8:30 AM, Daniel Halperin wrote:
> On Sun, Apr 15, 2012 at 11:27 AM, Felix Fietkau <[email protected]> wrote:
>> On 2012-04-15 8:22 PM, Daniel Halperin wrote:
>>> Felix,
>>>
>>> This whole patch series throws the NICs out of spec compliance. For
>>> instance, page 626 of the 802.11-2007 standard (Table 17-15) says that
>>> aSIFStime is 32 us in 10 MHz mode and 64 us in 5 MHz mode.
>>>
>>> This might be okay to do for certain implementations (as, apparently,
>>> AR9280/AR9380), but will break compatibility with any device obeying
>>> the standard instead.
>>>
>>> (I wonder that, if this code below still works, then it seems that you
>>> might not be properly downclocking the chips' reference clock...)
>>>
>>> Are you aware there's a standard for this? Why violate it?
>> I'm aware that there's a standard for it, but if I put in the standard
>> values, the connection gets unreliable to the point where it's almost
>> unusable. That's why I chose to use existing products with 5/10 MHz
>> support as reference instead.
>>
>
> I hear you, but still suspect the bug's somewhere else. Violating the
> standard likely isn't the right choice unless you have a good
> reason... it sounds like you don't know why this is happening but this
> hack 'seems to work'.
>
> (UBNT is also ath-based, right? So it's not really proof that this
> hack doesn't break compatibility..)
Right, UBNT is also ath-based, and I dumped the registers on the device
to figure out what parameters they were using, and used those as
reference for my ath9k work.
I'm not aware of *any* standard compliant 5/10 MHz product out there, do
you know any?

- Felix

2012-04-15 10:15:52

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 8/9] ath9k_hw: disable fast channel change when changing from/to half/quarter mode

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 bb7e097..a48a4cc1 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1438,6 +1438,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


2012-04-15 10:15:52

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 9/9] ath9k_hw: increase tx abort timeout for half/quarter channels

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


2012-04-16 13:16:45

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 2/9] ath9k_hw: do not override SIFS time for half/quarter channels

On 2012-04-16 11:44 AM, Felix Fietkau wrote:
> On 2012-04-16 8:30 AM, Daniel Halperin wrote:
>> On Sun, Apr 15, 2012 at 11:27 AM, Felix Fietkau <[email protected]> wrote:
>>> On 2012-04-15 8:22 PM, Daniel Halperin wrote:
>>>> Felix,
>>>>
>>>> This whole patch series throws the NICs out of spec compliance. For
>>>> instance, page 626 of the 802.11-2007 standard (Table 17-15) says that
>>>> aSIFStime is 32 us in 10 MHz mode and 64 us in 5 MHz mode.
>>>>
>>>> This might be okay to do for certain implementations (as, apparently,
>>>> AR9280/AR9380), but will break compatibility with any device obeying
>>>> the standard instead.
>>>>
>>>> (I wonder that, if this code below still works, then it seems that you
>>>> might not be properly downclocking the chips' reference clock...)
>>>>
>>>> Are you aware there's a standard for this? Why violate it?
>>> I'm aware that there's a standard for it, but if I put in the standard
>>> values, the connection gets unreliable to the point where it's almost
>>> unusable. That's why I chose to use existing products with 5/10 MHz
>>> support as reference instead.
>>>
>>
>> I hear you, but still suspect the bug's somewhere else. Violating the
>> standard likely isn't the right choice unless you have a good
>> reason... it sounds like you don't know why this is happening but this
>> hack 'seems to work'.
>>
>> (UBNT is also ath-based, right? So it's not really proof that this
>> hack doesn't break compatibility..)
> Right, UBNT is also ath-based, and I dumped the registers on the device
> to figure out what parameters they were using, and used those as
> reference for my ath9k work.
> I'm not aware of *any* standard compliant 5/10 MHz product out there, do
> you know any?
By the way, I'm doing some more testing and it seems like I may be able
to get it working with standard compliant SIFS timing after all by
tweaking the rx latency settings some more.

John: Don't merge this series just yet, I'll send a v2 when I'm done
testing.

- Felix

2012-04-15 18:27:39

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 2/9] ath9k_hw: do not override SIFS time for half/quarter channels

On 2012-04-15 8:22 PM, Daniel Halperin wrote:
> Felix,
>
> This whole patch series throws the NICs out of spec compliance. For
> instance, page 626 of the 802.11-2007 standard (Table 17-15) says that
> aSIFStime is 32 us in 10 MHz mode and 64 us in 5 MHz mode.
>
> This might be okay to do for certain implementations (as, apparently,
> AR9280/AR9380), but will break compatibility with any device obeying
> the standard instead.
>
> (I wonder that, if this code below still works, then it seems that you
> might not be properly downclocking the chips' reference clock...)
>
> Are you aware there's a standard for this? Why violate it?
I'm aware that there's a standard for it, but if I put in the standard
values, the connection gets unreliable to the point where it's almost
unusable. That's why I chose to use existing products with 5/10 MHz
support as reference instead.

- Felix

2012-04-15 10:15:52

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 3/9] ath9k_hw: set the PHY mode for half/quarter channels on AR9003

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


2012-04-16 06:30:41

by Daniel Halperin

[permalink] [raw]
Subject: Re: [PATCH 2/9] ath9k_hw: do not override SIFS time for half/quarter channels

On Sun, Apr 15, 2012 at 11:27 AM, Felix Fietkau <[email protected]> wrote:
> On 2012-04-15 8:22 PM, Daniel Halperin wrote:
>> Felix,
>>
>> This whole patch series throws the NICs out of spec compliance. For
>> instance, page 626 of the 802.11-2007 standard (Table 17-15) says that
>> aSIFStime is 32 us in 10 MHz mode and 64 us in 5 MHz mode.
>>
>> This might be okay to do for certain implementations (as, apparently,
>> AR9280/AR9380), but will break compatibility with any device obeying
>> the standard instead.
>>
>> (I wonder that, if this code below still works, then it seems that you
>> might not be properly downclocking the chips' reference clock...)
>>
>> Are you aware there's a standard for this? Why violate it?
> I'm aware that there's a standard for it, but if I put in the standard
> values, the connection gets unreliable to the point where it's almost
> unusable. That's why I chose to use existing products with 5/10 MHz
> support as reference instead.
>

I hear you, but still suspect the bug's somewhere else. Violating the
standard likely isn't the right choice unless you have a good
reason... it sounds like you don't know why this is happening but this
hack 'seems to work'.

(UBNT is also ath-based, right? So it's not really proof that this
hack doesn't break compatibility..)

Dan