2010-12-20 17:37:44

by Senthil Balasubramanian

[permalink] [raw]
Subject: [PATCH 1/2] ath9k_hw: Fix incorrect macversion and macrev checks

There are few places where we are checking for macversion and revsions
before RTC is powered ON. However we are reading the macversion and
revisions only after RTC is powered ON and so both macversion and
revisions are actully zero and this leads to incorrect srev checks.

fix this by reading the macversion and revisisons even before we start
using them. There is no reason why should we delay reading this info
until RTC is powered on as this is just a register information.

Cc: Stable Kernel <[email protected]>
Signed-off-by: Senthil Balasubramanian <[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 ddda76f..c9b7f1e 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1078,13 +1078,13 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
return false;
}

- ath9k_hw_read_revisions(ah);
-
return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
}

static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
{
+ ath9k_hw_read_revisions(ah);
+
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10);
--
1.7.3.4



2010-12-20 17:37:52

by Senthil Balasubramanian

[permalink] [raw]
Subject: [PATCH 2/2] ath9k_hw: read and backup AR_WA register value even before chip reset on.

We need to read and backup AR_WA register value permanently and reading
this after the chip is awakened results in this register being zeroed out.

This seems to fix the ASPM with L1 enabled issue that we have observed.
The laptop becomes very slow and hangs mostly with ASPM L1 enabled without
this fix.

Cc: Stable Kernel <[email protected]>
Signed-off-by: Senthil Balasubramanian <[email protected]>
---
drivers/net/wireless/ath/ath9k/hw.c | 17 +++++++++--------
1 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index c9b7f1e..c6eed46 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -491,6 +491,15 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (ah->hw_version.devid == AR5416_AR9100_DEVID)
ah->hw_version.macVersion = AR_SREV_VERSION_9100;

+ /*
+ * Read back AR_WA into a permanent copy and set bits 14 and 17.
+ * We need to do this to avoid RMW of this register. We cannot
+ * read the reg when chip is asleep.
+ */
+ ah->WARegVal = REG_READ(ah, AR_WA);
+ ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
+ AR_WA_ASPM_TIMER_BASED_DISABLE);
+
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
ath_err(common, "Couldn't reset chip\n");
return -EIO;
@@ -559,14 +568,6 @@ static int __ath9k_hw_init(struct ath_hw *ah)

ath9k_hw_init_mode_regs(ah);

- /*
- * Read back AR_WA into a permanent copy and set bits 14 and 17.
- * We need to do this to avoid RMW of this register. We cannot
- * read the reg when chip is asleep.
- */
- ah->WARegVal = REG_READ(ah, AR_WA);
- ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
- AR_WA_ASPM_TIMER_BASED_DISABLE);

if (ah->is_pciexpress)
ath9k_hw_configpcipowersave(ah, 0, 0);
--
1.7.3.4


2010-12-21 13:36:21

by Senthil Balasubramanian

[permalink] [raw]
Subject: Re: [PATCH 1/2] ath9k_hw: Fix incorrect macversion and macrev checks

On Mon, Dec 20, 2010 at 11:49:56PM +0530, Felix Fietkau wrote:
> On 2010-12-20 6:37 PM, Senthil Balasubramanian wrote:
> > There are few places where we are checking for macversion and revsions
> > before RTC is powered ON. However we are reading the macversion and
> > revisions only after RTC is powered ON and so both macversion and
> > revisions are actully zero and this leads to incorrect srev checks.
> >
> > fix this by reading the macversion and revisisons even before we start
> > using them. There is no reason why should we delay reading this info
> > until RTC is powered on as this is just a register information.
> >
> > Cc: Stable Kernel <[email protected]>
> > Signed-off-by: Senthil Balasubramanian <[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 ddda76f..c9b7f1e 100644
> > --- a/drivers/net/wireless/ath/ath9k/hw.c
> > +++ b/drivers/net/wireless/ath/ath9k/hw.c
> > @@ -1078,13 +1078,13 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
> > return false;
> > }
> >
> > - ath9k_hw_read_revisions(ah);
> > -
> > return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
> > }
> >
> > static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
> > {
> > + ath9k_hw_read_revisions(ah);
> > +
> > if (AR_SREV_9300_20_OR_LATER(ah)) {
> > REG_WRITE(ah, AR_WA, ah->WARegVal);
> > udelay(10);
> Why re-read the revision on every reset?
yes.. not required on every reset and we can read it in __ath9k_hw_init itself
right before ath9k_hw_set_reset_reg().

I just overlooked the reset part for WARM/COLD which is mostly the case except
for ar9280 with olc and just wanted to retain how it was before for POWER_ON.

will send v2 thanks.

>
> - Felix

2010-12-20 18:20:07

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 1/2] ath9k_hw: Fix incorrect macversion and macrev checks

On 2010-12-20 6:37 PM, Senthil Balasubramanian wrote:
> There are few places where we are checking for macversion and revsions
> before RTC is powered ON. However we are reading the macversion and
> revisions only after RTC is powered ON and so both macversion and
> revisions are actully zero and this leads to incorrect srev checks.
>
> fix this by reading the macversion and revisisons even before we start
> using them. There is no reason why should we delay reading this info
> until RTC is powered on as this is just a register information.
>
> Cc: Stable Kernel <[email protected]>
> Signed-off-by: Senthil Balasubramanian <[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 ddda76f..c9b7f1e 100644
> --- a/drivers/net/wireless/ath/ath9k/hw.c
> +++ b/drivers/net/wireless/ath/ath9k/hw.c
> @@ -1078,13 +1078,13 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
> return false;
> }
>
> - ath9k_hw_read_revisions(ah);
> -
> return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
> }
>
> static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
> {
> + ath9k_hw_read_revisions(ah);
> +
> if (AR_SREV_9300_20_OR_LATER(ah)) {
> REG_WRITE(ah, AR_WA, ah->WARegVal);
> udelay(10);
Why re-read the revision on every reset?

- Felix