Subject: [PATCH 1/3] ath9k: Fix regression in starting ANI after association

Author: Felix Fietkau <[email protected]>
Date: Sat Jul 31 00:11:59 2010 +0200

ath9k: prevent calibration during off-channel activity

The above patch checks for off-channel before starting ANI,
but when the operating channel is set right after association,
IEEE80211_CONF_OFFCHANNEL would be set as still local->tmp_channel
is non-NULL. This would result in not starting calibration after
the association. Fix this by clearing off-channel state in sc_flags
after association.

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

diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a2f7eb2..b529c3e 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -820,7 +820,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
/* Reset rssi stats */
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;

- sc->sc_flags |= SC_OP_ANI_RUN;
+ sc->sc_flags = (sc->sc_flags | SC_OP_ANI_RUN) & ~SC_OP_OFFCHANNEL;
ath_start_ani(common);
} else {
ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
--
1.7.0.4



2010-09-15 16:22:05

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 1/3] ath9k: Fix regression in starting ANI after association

On Wed, Sep 15, 2010 at 7:22 AM, Vasanthakumar Thiagarajan
<[email protected]> wrote:
> Author: Felix Fietkau <[email protected]>
> Date:   Sat Jul 31 00:11:59 2010 +0200
>
>    ath9k: prevent calibration during off-channel activity
>
> The above patch checks for off-channel before starting ANI,
> but when the operating channel is set right after association,
> IEEE80211_CONF_OFFCHANNEL would be set as still local->tmp_channel
> is non-NULL. This would result in not starting calibration after
> the association.

Why not fix this in mac80211 then?

Luis

Subject: Re: [PATCH 1/3] ath9k: Fix regression in starting ANI after association

On Wed, Sep 15, 2010 at 09:51:43PM +0530, Luis R. Rodriguez wrote:
> On Wed, Sep 15, 2010 at 7:22 AM, Vasanthakumar Thiagarajan
> <[email protected]> wrote:
> > Author: Felix Fietkau <[email protected]>
> > Date: ? Sat Jul 31 00:11:59 2010 +0200
> >
> > ? ?ath9k: prevent calibration during off-channel activity
> >
> > The above patch checks for off-channel before starting ANI,
> > but when the operating channel is set right after association,
> > IEEE80211_CONF_OFFCHANNEL would be set as still local->tmp_channel
> > is non-NULL. This would result in not starting calibration after
> > the association.

Yes, the bug is in mac80211, but fixing this one in mac80211 looks
not straight forward and probably Felix would know this one better,
for now let me do this in driver and remove it once it is cleanly
fixed in mac80211.

Vasanth

2010-09-16 14:20:00

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 1/3] ath9k: Fix regression in starting ANI after association

On Wed, Sep 15, 2010 at 9:49 PM, Vasanthakumar Thiagarajan
<[email protected]> wrote:
> On Wed, Sep 15, 2010 at 09:51:43PM +0530, Luis R. Rodriguez wrote:
>> On Wed, Sep 15, 2010 at 7:22 AM, Vasanthakumar Thiagarajan
>> <[email protected]> wrote:
>> > Author: Felix Fietkau <[email protected]>
>> > Date:   Sat Jul 31 00:11:59 2010 +0200
>> >
>> >    ath9k: prevent calibration during off-channel activity
>> >
>> > The above patch checks for off-channel before starting ANI,
>> > but when the operating channel is set right after association,
>> > IEEE80211_CONF_OFFCHANNEL would be set as still local->tmp_channel
>> > is non-NULL. This would result in not starting calibration after
>> > the association.
>
> Yes, the bug is in mac80211, but fixing this one in mac80211 looks
> not straight forward and probably Felix would know this one better,
> for now let me do this in driver and remove it once it is cleanly
> fixed in mac80211.

No, please address in mac80211, if we clean this up as a work around
we likely are overlooking other possible issues which can be affected
as well.

Luis

Subject: Re: [PATCH 2/3] ath9k: Paprd calibration should be per channel

On Wed, Sep 15, 2010 at 08:53:34PM +0530, Felix Fietkau wrote:
> On 2010-09-15 4:22 PM, Vasanthakumar Thiagarajan wrote:
> > Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>
> NACK. The point of the caldata struct is to keep calibration data for
> the operating channel and reset it whenever that changes (but not just
> for off-channel activity).
> Since the PAPRD data uses quite a bit of memory and doesn't take that
> long to generate, we don't really need to make it per-channel.

Yes, it takes some memory, this looked clean and simple. It is not
unusual case that we would be operating on different channels
(think about roaming,dfs,p2p and etc). The existing implementation
does not do paprd calibration when the operating channel is changed.
Having a single caldata might require us depend on SC_OP_SCANNING/
SC_OP_OFFCHANNEL, but we are already dealing with some bugs in those
flags. I completely agree that it takes memory, would try to fix
existing issues in paprd rather than keeping channel specific data.
thanks for the review.

Vasanth

Subject: [PATCH 3/3] ath9k: Fix sparse warning: symbol 'ath_ant_div_conf_fast_divbias' was not declared

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

diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 6fb3b45..aa9a14d 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1338,7 +1338,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
}
}

-void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf)
+static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf)
{
/* Adjust the fast_div_bias based on main and alt lna conf */
switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) {
--
1.7.0.4


2010-09-15 15:23:39

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 2/3] ath9k: Paprd calibration should be per channel

On 2010-09-15 4:22 PM, Vasanthakumar Thiagarajan wrote:
> Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>
NACK. The point of the caldata struct is to keep calibration data for
the operating channel and reset it whenever that changes (but not just
for off-channel activity).
Since the PAPRD data uses quite a bit of memory and doesn't take that
long to generate, we don't really need to make it per-channel.

- Felix

Subject: [PATCH 2/3] ath9k: Paprd calibration should be per channel

Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 5 ++-
drivers/net/wireless/ath/ath9k/hw.h | 12 +++++++---
drivers/net/wireless/ath/ath9k/main.c | 28 +++++++++++-------------
3 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index 7c38229..fc283d2 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -577,7 +577,7 @@ static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain)
}

void ar9003_paprd_populate_single_table(struct ath_hw *ah,
- struct ath9k_hw_cal_data *caldata,
+ struct ath9k_hw_paprd_caldata *caldata,
int chain)
{
u32 *paprd_table_val = caldata->pa_table[chain];
@@ -656,7 +656,8 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
EXPORT_SYMBOL(ar9003_paprd_setup_gain_table);

int ar9003_paprd_create_curve(struct ath_hw *ah,
- struct ath9k_hw_cal_data *caldata, int chain)
+ struct ath9k_hw_paprd_caldata *caldata,
+ int chain)
{
u16 *small_signal_gain = &caldata->small_signal_gain[chain];
u32 *pa_table = caldata->pa_table[chain];
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index a3c2ce2..daad373 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -343,16 +343,20 @@ struct ath9k_hw_cal_data {
int8_t iCoff;
int8_t qCoff;
int16_t rawNoiseFloor;
- bool paprd_done;
bool nfcal_pending;
bool nfcal_interference;
+ struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
+};
+
+struct ath9k_hw_paprd_caldata {
+ u8 paprd_done_txchainmask;
u16 small_signal_gain[AR9300_MAX_CHAINS];
u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
- struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
};

struct ath9k_channel {
struct ieee80211_channel *chan;
+ struct ath9k_hw_paprd_caldata paprd_caldata;
u16 channel;
u32 channelFlags;
u32 chanmode;
@@ -965,10 +969,10 @@ void ar9003_hw_bb_watchdog_read(struct ath_hw *ah);
void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah);
void ar9003_paprd_enable(struct ath_hw *ah, bool val);
void ar9003_paprd_populate_single_table(struct ath_hw *ah,
- struct ath9k_hw_cal_data *caldata,
+ struct ath9k_hw_paprd_caldata *caldata,
int chain);
int ar9003_paprd_create_curve(struct ath_hw *ah,
- struct ath9k_hw_cal_data *caldata, int chain);
+ struct ath9k_hw_paprd_caldata *caldata, int chain);
int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain);
int ar9003_paprd_init_table(struct ath_hw *ah);
bool ar9003_paprd_is_done(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index b529c3e..f316061 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -269,16 +269,14 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
static void ath_paprd_activate(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
- struct ath9k_hw_cal_data *caldata = ah->caldata;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_paprd_caldata *caldata = &ah->curchan->paprd_caldata;
int chain;

- if (!caldata || !caldata->paprd_done)
- return;
-
ath9k_ps_wakeup(sc);
ar9003_paprd_enable(ah, false);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
- if (!(ah->caps.tx_chainmask & BIT(chain)))
+ if (!(common->tx_chainmask & BIT(chain)))
continue;

ar9003_paprd_populate_single_table(ah, caldata, chain);
@@ -299,7 +297,8 @@ void ath_paprd_calibrate(struct work_struct *work)
int band = hw->conf.channel->band;
struct ieee80211_supported_band *sband = &sc->sbands[band];
struct ath_tx_control txctl;
- struct ath9k_hw_cal_data *caldata = ah->caldata;
+ struct ath9k_hw_paprd_caldata *caldata = &ah->curchan->paprd_caldata;
+ struct ath_common *common = ath9k_hw_common(ah);
int qnum, ftype;
int chain_ok = 0;
int chain;
@@ -307,9 +306,6 @@ void ath_paprd_calibrate(struct work_struct *work)
int time_left;
int i;

- if (!caldata)
- return;
-
skb = alloc_skb(len, GFP_KERNEL);
if (!skb)
return;
@@ -333,7 +329,8 @@ void ath_paprd_calibrate(struct work_struct *work)
ath9k_ps_wakeup(sc);
ar9003_paprd_init_table(ah);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
- if (!(ah->caps.tx_chainmask & BIT(chain)))
+ if (!(common->tx_chainmask & BIT(chain)) ||
+ (caldata->paprd_done_txchainmask & BIT(chain)))
continue;

chain_ok = 0;
@@ -367,14 +364,13 @@ void ath_paprd_calibrate(struct work_struct *work)
if (ar9003_paprd_create_curve(ah, caldata, chain) != 0)
break;

+ caldata->paprd_done_txchainmask |= BIT(chain);
chain_ok = 1;
}
kfree_skb(skb);

- if (chain_ok) {
- caldata->paprd_done = true;
+ if (chain_ok)
ath_paprd_activate(sc);
- }

fail_paprd:
ath9k_ps_restore(sc);
@@ -392,6 +388,7 @@ void ath_ani_calibrate(unsigned long data)
struct ath_softc *sc = (struct ath_softc *)data;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_paprd_caldata *caldata = &ah->curchan->paprd_caldata;
bool longcal = false;
bool shortcal = false;
bool aniflag = false;
@@ -486,8 +483,9 @@ set_timer:
cal_interval = min(cal_interval, (u32)short_cal_interval);

mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
- if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) {
- if (!ah->caldata->paprd_done)
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) {
+ if ((caldata->paprd_done_txchainmask & common->tx_chainmask)
+ != common->tx_chainmask)
ieee80211_queue_work(sc->hw, &sc->paprd_work);
else
ath_paprd_activate(sc);
--
1.7.0.4


Subject: Re: [PATCH 1/3] ath9k: Fix regression in starting ANI after association

On Thu, Sep 16, 2010 at 07:49:39PM +0530, Luis R. Rodriguez wrote:
> On Wed, Sep 15, 2010 at 9:49 PM, Vasanthakumar Thiagarajan
> <[email protected]> wrote:
> > On Wed, Sep 15, 2010 at 09:51:43PM +0530, Luis R. Rodriguez wrote:
> >> On Wed, Sep 15, 2010 at 7:22 AM, Vasanthakumar Thiagarajan
> >> <[email protected]> wrote:
> >> > Author: Felix Fietkau <[email protected]>
> >> > Date: ? Sat Jul 31 00:11:59 2010 +0200
> >> >
> >> > ? ?ath9k: prevent calibration during off-channel activity
> >> >
> >> > The above patch checks for off-channel before starting ANI,
> >> > but when the operating channel is set right after association,
> >> > IEEE80211_CONF_OFFCHANNEL would be set as still local->tmp_channel
> >> > is non-NULL. This would result in not starting calibration after
> >> > the association.
> >
> > Yes, the bug is in mac80211, but fixing this one in mac80211 looks
> > not straight forward and probably Felix would know this one better,
> > for now let me do this in driver and remove it once it is cleanly
> > fixed in mac80211.
>
> No, please address in mac80211, if we clean this up as a work around
> we likely are overlooking other possible issues which can be affected
> as well.

It is not easy (from my understanding at least) to fix this in
mac80211 as the assumption of off-channel activity (IEEE80211_CONF_OFFCHANNEL)
itself seems to be wrong sometimes (in case of station mode, setting this flag
before the association does not look right). As I dont know any
clean fix in mac80211, this patch can be an interim fix for the
regression.

Vasanth

2010-09-16 06:47:42

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 2/3] ath9k: Paprd calibration should be per channel

On 2010-09-16 7:17 AM, Vasanthakumar Thiagarajan wrote:
> On Wed, Sep 15, 2010 at 08:53:34PM +0530, Felix Fietkau wrote:
>> On 2010-09-15 4:22 PM, Vasanthakumar Thiagarajan wrote:
>> > Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>
>> NACK. The point of the caldata struct is to keep calibration data for
>> the operating channel and reset it whenever that changes (but not just
>> for off-channel activity).
>> Since the PAPRD data uses quite a bit of memory and doesn't take that
>> long to generate, we don't really need to make it per-channel.
>
> Yes, it takes some memory, this looked clean and simple. It is not
> unusual case that we would be operating on different channels
> (think about roaming,dfs,p2p and etc).
Roaming is fine, since the driver is unlikely to switch back and forth
often enough for the re-calibration to matter.
As far as I know, the plan for p2p is to have a per-vif channel in the
long run. Once that is implemented, the calibration data will also be
made per-vif.

> The existing implementation
> does not do paprd calibration when the operating channel is changed.
> Having a single caldata might require us depend on SC_OP_SCANNING/
> SC_OP_OFFCHANNEL, but we are already dealing with some bugs in those
> flags. I completely agree that it takes memory, would try to fix
> existing issues in paprd rather than keeping channel specific data.
> thanks for the review.
If PAPRD is not started after the return to the operating channel, then
other calibrations will be affected as well. In that case, we definitely
need to fix the root cause and not paper over the bug by moving the
PAPRD state.

- Felix

2010-09-27 17:22:04

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 1/3] ath9k: Fix regression in starting ANI after association

On Wed, Sep 22, 2010 at 6:49 AM, Vasanthakumar Thiagarajan
<[email protected]> wrote:
> On Thu, Sep 16, 2010 at 07:49:39PM +0530, Luis R. Rodriguez wrote:
>> On Wed, Sep 15, 2010 at 9:49 PM, Vasanthakumar Thiagarajan
>> <[email protected]> wrote:
>> > On Wed, Sep 15, 2010 at 09:51:43PM +0530, Luis R. Rodriguez wrote:
>> >> On Wed, Sep 15, 2010 at 7:22 AM, Vasanthakumar Thiagarajan
>> >> <[email protected]> wrote:
>> >> > Author: Felix Fietkau <[email protected]>
>> >> > Date:   Sat Jul 31 00:11:59 2010 +0200
>> >> >
>> >> >    ath9k: prevent calibration during off-channel activity
>> >> >
>> >> > The above patch checks for off-channel before starting ANI,
>> >> > but when the operating channel is set right after association,
>> >> > IEEE80211_CONF_OFFCHANNEL would be set as still local->tmp_channel
>> >> > is non-NULL. This would result in not starting calibration after
>> >> > the association.
>> >
>> > Yes, the bug is in mac80211, but fixing this one in mac80211 looks
>> > not straight forward and probably Felix would know this one better,
>> > for now let me do this in driver and remove it once it is cleanly
>> > fixed in mac80211.
>>
>> No, please address in mac80211, if we clean this up as a work around
>> we likely are overlooking other possible issues which can be affected
>> as well.
>
> It is not easy (from my understanding at least) to fix this in
> mac80211 as the assumption of off-channel activity (IEEE80211_CONF_OFFCHANNEL)
> itself seems to be wrong sometimes (in case of station mode, setting this flag
> before the association does not look right). As I dont know any
> clean fix in mac80211, this patch can be an interim fix for the
> regression.

It was tricky indeed, mac80211 does use the offchannel operation to
associate as an atomic operation, the fix was to lif the offchannel
flag when we have already decided we are going to switch to it as our
home channel. Please try the patch "mac80211: fix offchannel
assumption upon association". Works for me.

Luis