2011-08-13 04:57:57

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 01/11] ath9k_hw: Fix exceed transmission burst-time of 5GHz

The WAR which adds extra delimiters when using RTS/CTS
with aggregation and non-enterprise AR9003 chips.
This extra padding is done after doing all the 4ms limit
checks and hence the total aggregate sizes are exceeding
the allowed duration. This patch limits the aggregate
sizes appropriately after including these extra delimiters.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_mac.c | 28 +-------------------------
drivers/net/wireless/ath/ath9k/xmit.c | 16 ++++++++++++--
2 files changed, 15 insertions(+), 29 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 1aadc47..81ccce1 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -415,36 +415,12 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
u32 aggrLen)
{
-#define FIRST_DESC_NDELIMS 60
struct ar9003_txc *ads = (struct ar9003_txc *) ds;

ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);

- if (ah->ent_mode & AR_ENT_OTP_MPSD) {
- u32 ctl17, ndelim;
- /*
- * Add delimiter when using RTS/CTS with aggregation
- * and non enterprise AR9003 card
- */
- ctl17 = ads->ctl17;
- ndelim = MS(ctl17, AR_PadDelim);
-
- if (ndelim < FIRST_DESC_NDELIMS) {
- aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4;
- ndelim = FIRST_DESC_NDELIMS;
- }
-
- ctl17 &= ~AR_AggrLen;
- ctl17 |= SM(aggrLen, AR_AggrLen);
-
- ctl17 &= ~AR_PadDelim;
- ctl17 |= SM(ndelim, AR_PadDelim);
-
- ads->ctl17 = ctl17;
- } else {
- ads->ctl17 &= ~AR_AggrLen;
- ads->ctl17 |= SM(aggrLen, AR_AggrLen);
- }
+ ads->ctl17 &= ~AR_AggrLen;
+ ads->ctl17 |= SM(aggrLen, AR_AggrLen);
}

static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index e1d1e90..feef013 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -644,8 +644,10 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
* meet the minimum required mpdudensity.
*/
static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
- struct ath_buf *bf, u16 frmlen)
+ struct ath_buf *bf, u16 frmlen,
+ bool first_subfrm)
{
+#define FIRST_DESC_NDELIMS 60
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
u32 nsymbits, nsymbols;
@@ -668,6 +670,13 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
ndelim += ATH_AGGR_ENCRYPTDELIM;

/*
+ * Add delimiter when using RTS/CTS with aggregation
+ * and non enterprise AR9003 card
+ */
+ if (first_subfrm)
+ ndelim = max(ndelim, FIRST_DESC_NDELIMS);
+
+ /*
* Convert desired mpdu density from microeconds to bytes based
* on highest rate in rate series (i.e. first rate) to determine
* required minimum length for subframe. Take into account
@@ -756,7 +765,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
status = ATH_AGGR_LIMITED;
break;
}
- nframes++;

/* add padding for previous frame to aggregation length */
al += bpad + al_delta;
@@ -765,9 +773,11 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
* Get the delimiters needed to meet the MPDU
* density for this node.
*/
- ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen);
+ ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen,
+ !nframes);
bpad = PADBYTES(al_delta) + (ndelim << 2);

+ nframes++;
bf->bf_next = NULL;
ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);

--
1.7.6



2011-08-13 10:53:13

by Adrian Chadd

[permalink] [raw]
Subject: Re: [PATCH 03/11] ath9k: Re-enable RXOEL interrupt after processing rx buffers

.. again, I'll just point out that because I was seeing this when the
PCU honestly had hit the end of the RX descriptor list (lots of radar
phyerr frames), I needed to kick the PCU to start again.

Are you not seeing this? if not, why are you receiving the interrupt? :-)


Adrian

On 13 August 2011 12:58, Rajkumar Manoharan <[email protected]> wrote:
> Once RXEOL was disabled, it never be enabled again. This patch
> re-enables rxeol at the end of rx tasklet.
>
> Signed-off-by: Rajkumar Manoharan <[email protected]>
> ---
> ?drivers/net/wireless/ath/ath9k/recv.c | ? ?5 +++++
> ?1 files changed, 5 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
> index 7409402..c0c66e0 100644
> --- a/drivers/net/wireless/ath/ath9k/recv.c
> +++ b/drivers/net/wireless/ath/ath9k/recv.c
> @@ -1978,5 +1978,10 @@ requeue:
>
> ? ? ? ?spin_unlock_bh(&sc->rx.rxbuflock);
>
> + ? ? ? if (!(ah->imask & ATH9K_INT_RXEOL)) {
> + ? ? ? ? ? ? ? ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
> + ? ? ? ? ? ? ? ath9k_hw_set_interrupts(ah, ah->imask);
> + ? ? ? }
> +
> ? ? ? ?return 0;
> ?}
> --
> 1.7.6
>
> --
> 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
>

2011-08-13 04:58:17

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 04/11] ath9k: Remove unused argument tsf from ath9k_hw_rxprocdesc

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/mac.c | 2 +-
drivers/net/wireless/ath/ath9k/mac.h | 2 +-
drivers/net/wireless/ath/ath9k/recv.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 0f90e15..7ddca67 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -564,7 +564,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
EXPORT_SYMBOL(ath9k_hw_resettxqueue);

int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
- struct ath_rx_status *rs, u64 tsf)
+ struct ath_rx_status *rs)
{
struct ar5416_desc ads;
struct ar5416_desc *adsp = AR5416DESC(ds);
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 8e848c4..153859c 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -687,7 +687,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
- struct ath_rx_status *rs, u64 tsf);
+ struct ath_rx_status *rs);
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags);
bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index c0c66e0..a9d8f96b 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -761,7 +761,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
* on. All this is necessary because of our use of
* a self-linked list to avoid rx overruns.
*/
- ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0);
+ ret = ath9k_hw_rxprocdesc(ah, ds, rs);
if (ret == -EINPROGRESS) {
struct ath_rx_status trs;
struct ath_buf *tbf;
@@ -787,7 +787,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
*/

tds = tbf->bf_desc;
- ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0);
+ ret = ath9k_hw_rxprocdesc(ah, tds, &trs);
if (ret == -EINPROGRESS)
return NULL;
}
--
1.7.6


2011-08-13 04:58:11

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 03/11] ath9k: Re-enable RXOEL interrupt after processing rx buffers

Once RXEOL was disabled, it never be enabled again. This patch
re-enables rxeol at the end of rx tasklet.

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

diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 7409402..c0c66e0 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1978,5 +1978,10 @@ requeue:

spin_unlock_bh(&sc->rx.rxbuflock);

+ if (!(ah->imask & ATH9K_INT_RXEOL)) {
+ ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+ ath9k_hw_set_interrupts(ah, ah->imask);
+ }
+
return 0;
}
--
1.7.6


2011-08-13 04:58:59

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 10/11] ath9k: Fix invalid noisefloor reading due to channel update

While switching b/w HT20/40, the current channel's nf values
are updated into history buffer. Since the current channel's
channel type, channel flag got updated before reading
nf value from hw. This channel type mismatch is causing invalid
readings when hw is on ht20 but getnf tries to read on extn chains.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/main.c | 17 ++++++++++++++---
1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e828799..1af183f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1674,6 +1674,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)

if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ath9k_channel old_chan;
int pos = curchan->hw_value;
int old_pos = -1;
unsigned long flags;
@@ -1690,15 +1691,25 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
"Set channel: %d MHz type: %d\n",
curchan->center_freq, conf->channel_type);

- ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
- curchan, conf->channel_type);
-
/* update survey stats for the old channel before switching */
spin_lock_irqsave(&common->cc_lock, flags);
ath_update_survey_stats(sc);
spin_unlock_irqrestore(&common->cc_lock, flags);

/*
+ * Preserve the current channel values, before updating
+ * the same channel
+ */
+ if (old_pos == pos) {
+ memcpy(&old_chan, &sc->sc_ah->channels[pos],
+ sizeof(struct ath9k_channel));
+ ah->curchan = &old_chan;
+ }
+
+ ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
+ curchan, conf->channel_type);
+
+ /*
* If the operating channel changes, change the survey in-use flags
* along with it.
* Reset the survey data for the new channel, unless we're switching
--
1.7.6


2011-08-13 04:58:56

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 09/11] ath9k: Fix noisefloor history update for extn chains

Before doing hw reset the current channel's noisefloor readings
are updated into history buffer. The extension chain's readings
are considered only if the current channel was configured in HT40.
While moving from HT40 to HT20, the extn chain's readings are
skipped though the current channel is in ht40. This patch updates
extn chain reading based on channel flag.

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

diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index ac2da3c..ebaf304 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -82,7 +82,6 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
int16_t *nfarray)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_conf *conf = &common->hw->conf;
struct ath_nf_limits *limit;
struct ath9k_nfcal_hist *h;
bool high_nf_mid = false;
@@ -94,7 +93,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,

for (i = 0; i < NUM_NF_READINGS; i++) {
if (!(chainmask & (1 << i)) ||
- ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
+ ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan)))
continue;

h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
--
1.7.6


2011-08-13 10:41:05

by Adrian Chadd

[permalink] [raw]
Subject: Re: [PATCH 01/11] ath9k_hw: Fix exceed transmission burst-time of 5GHz

Does ath9k enable the relevant config bit that enforces the TXOP burst
time on transmissions?

ie, bit 12 (TXOP_TBTT_LIMIT_ ENABLE) of 0x8120 (MAC_PCU_MISC_MODE).

FreeBSD doesn't (yet) enable that bit. ath9k doesn't seem to enable
that bit, either in code or in the ar5008/ar9001/ar9002/ar9003
initvals.

What's the hardware doing when that bit isn't enabled? Is it still
enforcing TXOP limits on TXed frames? I've not (yet) seen it do so.

I came across this as a "thing to look at" after I finish off 11n TX,
as I'd like to make sure that both legacy and A-MPDU operation doesn't
exceed burst TXOP. (It's going to be important not only for QOS
compliance, but likely for correct/stable TDMA support.)

Thanks,



Adrian

On 13 August 2011 12:58, Rajkumar Manoharan <[email protected]> wrote:
> The WAR which adds extra delimiters when using RTS/CTS
> with aggregation and non-enterprise AR9003 chips.
> This extra padding is done after doing all the 4ms limit
> checks and hence the total aggregate sizes are exceeding
> the allowed duration. This patch limits the aggregate
> sizes appropriately after including these extra delimiters.
>
> Signed-off-by: Rajkumar Manoharan <[email protected]>
> ---
> ?drivers/net/wireless/ath/ath9k/ar9003_mac.c | ? 28 +-------------------------
> ?drivers/net/wireless/ath/ath9k/xmit.c ? ? ? | ? 16 ++++++++++++--
> ?2 files changed, 15 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
> index 1aadc47..81ccce1 100644
> --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
> +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
> @@ -415,36 +415,12 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
> ?static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?u32 aggrLen)
> ?{
> -#define FIRST_DESC_NDELIMS 60
> ? ? ? ?struct ar9003_txc *ads = (struct ar9003_txc *) ds;
>
> ? ? ? ?ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
>
> - ? ? ? if (ah->ent_mode & AR_ENT_OTP_MPSD) {
> - ? ? ? ? ? ? ? u32 ctl17, ndelim;
> - ? ? ? ? ? ? ? /*
> - ? ? ? ? ? ? ? ?* Add delimiter when using RTS/CTS with aggregation
> - ? ? ? ? ? ? ? ?* and non enterprise AR9003 card
> - ? ? ? ? ? ? ? ?*/
> - ? ? ? ? ? ? ? ctl17 = ads->ctl17;
> - ? ? ? ? ? ? ? ndelim = MS(ctl17, AR_PadDelim);
> -
> - ? ? ? ? ? ? ? if (ndelim < FIRST_DESC_NDELIMS) {
> - ? ? ? ? ? ? ? ? ? ? ? aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4;
> - ? ? ? ? ? ? ? ? ? ? ? ndelim = FIRST_DESC_NDELIMS;
> - ? ? ? ? ? ? ? }
> -
> - ? ? ? ? ? ? ? ctl17 &= ~AR_AggrLen;
> - ? ? ? ? ? ? ? ctl17 |= SM(aggrLen, AR_AggrLen);
> -
> - ? ? ? ? ? ? ? ctl17 &= ~AR_PadDelim;
> - ? ? ? ? ? ? ? ctl17 |= SM(ndelim, AR_PadDelim);
> -
> - ? ? ? ? ? ? ? ads->ctl17 = ctl17;
> - ? ? ? } else {
> - ? ? ? ? ? ? ? ads->ctl17 &= ~AR_AggrLen;
> - ? ? ? ? ? ? ? ads->ctl17 |= SM(aggrLen, AR_AggrLen);
> - ? ? ? }
> + ? ? ? ads->ctl17 &= ~AR_AggrLen;
> + ? ? ? ads->ctl17 |= SM(aggrLen, AR_AggrLen);
> ?}
>
> ?static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
> diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
> index e1d1e90..feef013 100644
> --- a/drivers/net/wireless/ath/ath9k/xmit.c
> +++ b/drivers/net/wireless/ath/ath9k/xmit.c
> @@ -644,8 +644,10 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
> ?* meet the minimum required mpdudensity.
> ?*/
> ?static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct ath_buf *bf, u16 frmlen)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct ath_buf *bf, u16 frmlen,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? bool first_subfrm)
> ?{
> +#define FIRST_DESC_NDELIMS 60
> ? ? ? ?struct sk_buff *skb = bf->bf_mpdu;
> ? ? ? ?struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
> ? ? ? ?u32 nsymbits, nsymbols;
> @@ -668,6 +670,13 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
> ? ? ? ? ? ? ? ?ndelim += ATH_AGGR_ENCRYPTDELIM;
>
> ? ? ? ?/*
> + ? ? ? ?* Add delimiter when using RTS/CTS with aggregation
> + ? ? ? ?* and non enterprise AR9003 card
> + ? ? ? ?*/
> + ? ? ? if (first_subfrm)
> + ? ? ? ? ? ? ? ndelim = max(ndelim, FIRST_DESC_NDELIMS);
> +
> + ? ? ? /*
> ? ? ? ? * Convert desired mpdu density from microeconds to bytes based
> ? ? ? ? * on highest rate in rate series (i.e. first rate) to determine
> ? ? ? ? * required minimum length for subframe. Take into account
> @@ -756,7 +765,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
> ? ? ? ? ? ? ? ? ? ? ? ?status = ATH_AGGR_LIMITED;
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ?}
> - ? ? ? ? ? ? ? nframes++;
>
> ? ? ? ? ? ? ? ?/* add padding for previous frame to aggregation length */
> ? ? ? ? ? ? ? ?al += bpad + al_delta;
> @@ -765,9 +773,11 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
> ? ? ? ? ? ? ? ? * Get the delimiters needed to meet the MPDU
> ? ? ? ? ? ? ? ? * density for this node.
> ? ? ? ? ? ? ? ? */
> - ? ? ? ? ? ? ? ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen);
> + ? ? ? ? ? ? ? ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? !nframes);
> ? ? ? ? ? ? ? ?bpad = PADBYTES(al_delta) + (ndelim << 2);
>
> + ? ? ? ? ? ? ? nframes++;
> ? ? ? ? ? ? ? ?bf->bf_next = NULL;
> ? ? ? ? ? ? ? ?ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
>
> --
> 1.7.6
>
> --
> 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
>

2011-08-14 04:06:33

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH 01/11] ath9k_hw: Fix exceed transmission burst-time of 5GHz

On Sun, Aug 14, 2011 at 10:39:51AM +0800, Adrian Chadd wrote:
> On 14 August 2011 10:39, Adrian Chadd <[email protected]> wrote:
>
> > Ah, makes sense now. Well, we (collectively) should likely figure out
> > how to teach the rate control and TX code how to not exceed TXOP in
> > general.
> > Do packets that exceed TXOP get marked as filtered?
>
> .. when the relevant bit in AR_PCU_MISCMODE is enabled, that is?
> (Obviously they're not being filtered now..)
>
If TXOP_TBTT_LIMIT bit is set then the logic to limit the value of the duration
to fit in the time remaining in TXOP and time remaining until TBTT will be
turned on. This logic will also will filter frames which will exceed TXOP.

--
Rajkumar

2011-08-13 18:41:52

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH 01/11] ath9k_hw: Fix exceed transmission burst-time of 5GHz

On Sat, Aug 13, 2011 at 06:41:03PM +0800, Adrian Chadd wrote:
> Does ath9k enable the relevant config bit that enforces the TXOP burst
> time on transmissions?
>
> ie, bit 12 (TXOP_TBTT_LIMIT_ ENABLE) of 0x8120 (MAC_PCU_MISC_MODE).
>
> FreeBSD doesn't (yet) enable that bit. ath9k doesn't seem to enable
> that bit, either in code or in the ar5008/ar9001/ar9002/ar9003
> initvals.
>
Correct. So the frames that are exceeding txop limit are not filtered.
The issue was originally observed while measuring XPABIAS5 signal of
AR9380 at 5GHz HT20 MCS0. It exceeds the 4ms limit due to WAR delimits.
> What's the hardware doing when that bit isn't enabled? Is it still
> enforcing TXOP limits on TXed frames? I've not (yet) seen it do so.
>
> I came across this as a "thing to look at" after I finish off 11n TX,
> as I'd like to make sure that both legacy and A-MPDU operation doesn't
> exceed burst TXOP. (It's going to be important not only for QOS
> compliance, but likely for correct/stable TDMA support.)
>
> Thanks,
>
>
>
> Adrian
>
> On 13 August 2011 12:58, Rajkumar Manoharan <[email protected]> wrote:
> > The WAR which adds extra delimiters when using RTS/CTS
> > with aggregation and non-enterprise AR9003 chips.
> > This extra padding is done after doing all the 4ms limit
> > checks and hence the total aggregate sizes are exceeding
> > the allowed duration. This patch limits the aggregate
> > sizes appropriately after including these extra delimiters.
> >
> > Signed-off-by: Rajkumar Manoharan <[email protected]>
> > ---
> > ?drivers/net/wireless/ath/ath9k/ar9003_mac.c | ? 28 +-------------------------
> > ?drivers/net/wireless/ath/ath9k/xmit.c ? ? ? | ? 16 ++++++++++++--
> > ?2 files changed, 15 insertions(+), 29 deletions(-)
> >
> > diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
> > index 1aadc47..81ccce1 100644
> > --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
> > +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
> > @@ -415,36 +415,12 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
> > ?static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?u32 aggrLen)
> > ?{
> > -#define FIRST_DESC_NDELIMS 60
> > ? ? ? ?struct ar9003_txc *ads = (struct ar9003_txc *) ds;
> >
> > ? ? ? ?ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
> >
> > - ? ? ? if (ah->ent_mode & AR_ENT_OTP_MPSD) {
> > - ? ? ? ? ? ? ? u32 ctl17, ndelim;
> > - ? ? ? ? ? ? ? /*
> > - ? ? ? ? ? ? ? ?* Add delimiter when using RTS/CTS with aggregation
> > - ? ? ? ? ? ? ? ?* and non enterprise AR9003 card
> > - ? ? ? ? ? ? ? ?*/
> > - ? ? ? ? ? ? ? ctl17 = ads->ctl17;
> > - ? ? ? ? ? ? ? ndelim = MS(ctl17, AR_PadDelim);
> > -
> > - ? ? ? ? ? ? ? if (ndelim < FIRST_DESC_NDELIMS) {
> > - ? ? ? ? ? ? ? ? ? ? ? aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4;
> > - ? ? ? ? ? ? ? ? ? ? ? ndelim = FIRST_DESC_NDELIMS;
> > - ? ? ? ? ? ? ? }
> > -
> > - ? ? ? ? ? ? ? ctl17 &= ~AR_AggrLen;
> > - ? ? ? ? ? ? ? ctl17 |= SM(aggrLen, AR_AggrLen);
> > -
> > - ? ? ? ? ? ? ? ctl17 &= ~AR_PadDelim;
> > - ? ? ? ? ? ? ? ctl17 |= SM(ndelim, AR_PadDelim);
> > -
> > - ? ? ? ? ? ? ? ads->ctl17 = ctl17;
> > - ? ? ? } else {
> > - ? ? ? ? ? ? ? ads->ctl17 &= ~AR_AggrLen;
> > - ? ? ? ? ? ? ? ads->ctl17 |= SM(aggrLen, AR_AggrLen);
> > - ? ? ? }
> > + ? ? ? ads->ctl17 &= ~AR_AggrLen;
> > + ? ? ? ads->ctl17 |= SM(aggrLen, AR_AggrLen);
> > ?}
> >
> > ?static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
> > diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
> > index e1d1e90..feef013 100644
> > --- a/drivers/net/wireless/ath/ath9k/xmit.c
> > +++ b/drivers/net/wireless/ath/ath9k/xmit.c
> > @@ -644,8 +644,10 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
> > ?* meet the minimum required mpdudensity.
> > ?*/
> > ?static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
> > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct ath_buf *bf, u16 frmlen)
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct ath_buf *bf, u16 frmlen,
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? bool first_subfrm)
> > ?{
> > +#define FIRST_DESC_NDELIMS 60
> > ? ? ? ?struct sk_buff *skb = bf->bf_mpdu;
> > ? ? ? ?struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
> > ? ? ? ?u32 nsymbits, nsymbols;
> > @@ -668,6 +670,13 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
> > ? ? ? ? ? ? ? ?ndelim += ATH_AGGR_ENCRYPTDELIM;
> >
> > ? ? ? ?/*
> > + ? ? ? ?* Add delimiter when using RTS/CTS with aggregation
> > + ? ? ? ?* and non enterprise AR9003 card
> > + ? ? ? ?*/
> > + ? ? ? if (first_subfrm)
> > + ? ? ? ? ? ? ? ndelim = max(ndelim, FIRST_DESC_NDELIMS);
> > +
> > + ? ? ? /*
> > ? ? ? ? * Convert desired mpdu density from microeconds to bytes based
> > ? ? ? ? * on highest rate in rate series (i.e. first rate) to determine
> > ? ? ? ? * required minimum length for subframe. Take into account
> > @@ -756,7 +765,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
> > ? ? ? ? ? ? ? ? ? ? ? ?status = ATH_AGGR_LIMITED;
> > ? ? ? ? ? ? ? ? ? ? ? ?break;
> > ? ? ? ? ? ? ? ?}
> > - ? ? ? ? ? ? ? nframes++;
> >
> > ? ? ? ? ? ? ? ?/* add padding for previous frame to aggregation length */
> > ? ? ? ? ? ? ? ?al += bpad + al_delta;
> > @@ -765,9 +773,11 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
> > ? ? ? ? ? ? ? ? * Get the delimiters needed to meet the MPDU
> > ? ? ? ? ? ? ? ? * density for this node.
> > ? ? ? ? ? ? ? ? */
> > - ? ? ? ? ? ? ? ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen);
> > + ? ? ? ? ? ? ? ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen,
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? !nframes);
> > ? ? ? ? ? ? ? ?bpad = PADBYTES(al_delta) + (ndelim << 2);
> >
> > + ? ? ? ? ? ? ? nframes++;
> > ? ? ? ? ? ? ? ?bf->bf_next = NULL;
> > ? ? ? ? ? ? ? ?ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
> >
> > --
> > 1.7.6
> >
> > --
> > 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
> >

2011-08-14 02:47:16

by Adrian Chadd

[permalink] [raw]
Subject: Re: [PATCH 03/11] ath9k: Re-enable RXOEL interrupt after processing rx buffers

On 14 August 2011 02:09, Rajkumar Manoharan <[email protected]> wrote:
> On Sat, Aug 13, 2011 at 06:53:12PM +0800, Adrian Chadd wrote:
>> .. again, I'll just point out that because I was seeing this when the
>> PCU honestly had hit the end of the RX descriptor list (lots of radar
>> phyerr frames), I needed to kick the PCU to start again.
>>
> so without PCU restart you are still getting rxeol. am i right?

Yup. That's because I've actually hit the end of the RX descriptor
list and since the 11n NIC code (so ath9k, and FreeBSD's ath when
using an 11n NIC) doesn't enable the self-link descriptor trick, the
PCU is now "stopped". I hit this when doing radar phyerr frame
reception and (artificially) generated lots of radar phyerr frames
whilst keeping the CPU busy. The RX thread would be CPU starved and it
wouldn't be able to service the RX descriptor list in time.

I've never hit it in normal operation, because (a) I wasn't doing RX
phyerr reception, and (b) I wasn't _trying_ to break RX under load.
:-)

The next problem (which I hinted at in another email) is that I'm
seeing an AR9280 NIC (Ubiquiti SR71-E) get itself into a situation
where its unable to do any kind of DMA, and constantly fires off RXEOL
interrupts, even if I then reset the PCU RX on RXEOL. The only fix is
a cold reset - a warm reset doesn't trigger it. So, I wonder what is
causing your underlying issues on Merlin, as it doesn't sound like
you've hit the end of the RX descriptor list (or you'd have to restart
the PCU w/ a new RX descriptor list to fix it.) Your problem may be
tangentally related to what I'm seeing :-)



Adrian

2011-08-13 04:58:31

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 06/11] ath9k_hw: Remove unnecessary chainmask configuration

The chainmasks were already configured at process_ini
before doing init calibration.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_calib.c | 15 ---------------
drivers/net/wireless/ath/ath9k/ar9003_phy.c | 2 +-
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2 --
3 files changed, 1 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index f48051c..fa35a02 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -839,20 +839,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_hw_capabilities *pCap = &ah->caps;
- int val;
bool txiqcal_done = false;

- val = REG_READ(ah, AR_ENT_OTP);
- ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);
-
- /* Configure rx/tx chains before running AGC/TxiQ cals */
- if (val & AR_ENT_OTP_CHAIN2_DISABLE)
- ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
- else
- ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask,
- pCap->tx_chainmask);
-
/* Do Tx IQ Calibration */
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
@@ -887,9 +875,6 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
if (txiqcal_done)
ar9003_hw_tx_iq_cal_post_proc(ah);

- /* Revert chainmasks to their original values before NF cal */
- ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
-
ath9k_hw_start_nfcal(ah, true);

/* Initialize list pointers */
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index dbe0b58..33edb56 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -540,7 +540,7 @@ static void ar9003_hw_init_bb(struct ath_hw *ah,
udelay(synthDelay + BASE_ACTIVATE_DELAY);
}

-void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
+static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
{
switch (rx) {
case 0x5:
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index 5c59042..80397de 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -1124,6 +1124,4 @@
#define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f
#define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0

-void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
-
#endif /* AR9003_PHY_H */
--
1.7.6


2011-08-14 02:39:24

by Adrian Chadd

[permalink] [raw]
Subject: Re: [PATCH 01/11] ath9k_hw: Fix exceed transmission burst-time of 5GHz

On 14 August 2011 02:42, Rajkumar Manoharan <[email protected]> wrote:

>> FreeBSD doesn't (yet) enable that bit. ath9k doesn't seem to enable
>> that bit, either in code or in the ar5008/ar9001/ar9002/ar9003
>> initvals.
>>
> Correct. So the frames that are exceeding txop limit are not filtered.
> The issue was originally observed while measuring XPABIAS5 signal of
> AR9380 at 5GHz HT20 MCS0. It exceeds the 4ms limit due to WAR delimits.

Ah, makes sense now. Well, we (collectively) should likely figure out
how to teach the rate control and TX code how to not exceed TXOP in
general.
Do packets that exceed TXOP get marked as filtered?

Thanks for finding that. :)



Adrian

2011-08-13 04:58:27

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 05/11] ath9k: qinfo never be NULL in setuptxqueue

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/mac.c | 17 ++---------------
1 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 7ddca67..7ce9b32 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -345,21 +345,8 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
}
memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
qi->tqi_type = type;
- if (qinfo == NULL) {
- qi->tqi_qflags =
- TXQ_FLAG_TXOKINT_ENABLE
- | TXQ_FLAG_TXERRINT_ENABLE
- | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
- qi->tqi_aifs = INIT_AIFS;
- qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
- qi->tqi_cwmax = INIT_CWMAX;
- qi->tqi_shretry = INIT_SH_RETRY;
- qi->tqi_lgretry = INIT_LG_RETRY;
- qi->tqi_physCompBuf = 0;
- } else {
- qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
- (void) ath9k_hw_set_txq_props(ah, q, qinfo);
- }
+ qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
+ (void) ath9k_hw_set_txq_props(ah, q, qinfo);

return q;
}
--
1.7.6


2011-08-13 18:08:49

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH 03/11] ath9k: Re-enable RXOEL interrupt after processing rx buffers

On Sat, Aug 13, 2011 at 06:53:12PM +0800, Adrian Chadd wrote:
> .. again, I'll just point out that because I was seeing this when the
> PCU honestly had hit the end of the RX descriptor list (lots of radar
> phyerr frames), I needed to kick the PCU to start again.
>
so without PCU restart you are still getting rxeol. am i right?
> Are you not seeing this? if not, why are you receiving the interrupt? :-)
>
Under heavy bidi traffic test, RXEOL was observed. But it never be enabled
again after processing rx bufs.
>
> Adrian
>
> On 13 August 2011 12:58, Rajkumar Manoharan <[email protected]> wrote:
> > Once RXEOL was disabled, it never be enabled again. This patch
> > re-enables rxeol at the end of rx tasklet.
> >
> > Signed-off-by: Rajkumar Manoharan <[email protected]>
> > ---
> > ?drivers/net/wireless/ath/ath9k/recv.c | ? ?5 +++++
> > ?1 files changed, 5 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
> > index 7409402..c0c66e0 100644
> > --- a/drivers/net/wireless/ath/ath9k/recv.c
> > +++ b/drivers/net/wireless/ath/ath9k/recv.c
> > @@ -1978,5 +1978,10 @@ requeue:
> >
> > ? ? ? ?spin_unlock_bh(&sc->rx.rxbuflock);
> >
> > + ? ? ? if (!(ah->imask & ATH9K_INT_RXEOL)) {
> > + ? ? ? ? ? ? ? ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
> > + ? ? ? ? ? ? ? ath9k_hw_set_interrupts(ah, ah->imask);
> > + ? ? ? }
> > +
> > ? ? ? ?return 0;
> > ?}
> > --
> > 1.7.6
> >
> > --
> > 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
> >

2011-08-13 10:51:31

by Adrian Chadd

[permalink] [raw]
Subject: Re: [PATCH 02/11] ath9k: Fix rx overrun interrupt storm

I did this in FreeBSD to fix RXEOL storms, but I was receiving them
because I had phyerr's enabled (for radar) and the PCU list end had
actually been hit.
So I added code which kicks off a PCU stop/start in the RX handler
(once whatever packets were in the RX queue) so that the PCU receive
would then begin again.

Were you seeing it occur because you hit the end of the RX descriptor
list? Or some other reason?

I ask because I'm seeing issues with an AR9280 (SR71-E) on FreeBSD,
where the PCU stops RX for some reason, and constantly fires off
RXEOLs. Warm resets don't fix it, I have to do a cold reset to fix it.
:(


Adrian

On 13 August 2011 12:58, Rajkumar Manoharan <[email protected]> wrote:
> Whenever RXEOL is received, both RXORN and RXEOL got cleared
> to avoid rx overrun interrupt storm. This was handled only for
> edma chips. The same scenario was also observered with AR9280,
> doing frequent channel type switch b/w HT20/40 with bidi traffic
> that is causing failure to stop rx dma. This patch clears
> the RXEOL & RXORN interrupts for all chips.
>
> ath: DMA failed to stop in 10 ms AR_CR=0x00000024 AR_DIAG_SW=0x42000020
> DMADBG_7=0x000062c0
> ath: Could not stop RX, we could be confusing the DMA engine when we
> start RX up
> ------------[ cut here ]------------
> WARNING: at drivers/net/wireless/ath/ath9k/recv.c:532
> ath_stoprecv+0x110/0x120 [ath9k]()
> Call Trace:
> ?[<ffffffff8104a55a>] warn_slowpath_common+0x7a/0xb0
> ?[<ffffffff8104a5a5>] warn_slowpath_null+0x15/0x20
> ?[<ffffffffa0560380>] ath_stoprecv+0x110/0x120 [ath9k]
> ?[<ffffffffa055e6fa>] ath_reset+0x6a/0x200 [ath9k]
>
> Signed-off-by: Rajkumar Manoharan <[email protected]>
> ---
> ?drivers/net/wireless/ath/ath9k/main.c | ? ?8 +++-----
> ?1 files changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
> index 1e7fe8c..097c1eb 100644
> --- a/drivers/net/wireless/ath/ath9k/main.c
> +++ b/drivers/net/wireless/ath/ath9k/main.c
> @@ -826,11 +826,9 @@ irqreturn_t ath_isr(int irq, void *dev)
> ? ? ? ?if (status & ATH9K_INT_TXURN)
> ? ? ? ? ? ? ? ?ath9k_hw_updatetxtriglevel(ah, true);
>
> - ? ? ? if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
> - ? ? ? ? ? ? ? if (status & ATH9K_INT_RXEOL) {
> - ? ? ? ? ? ? ? ? ? ? ? ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
> - ? ? ? ? ? ? ? ? ? ? ? ath9k_hw_set_interrupts(ah, ah->imask);
> - ? ? ? ? ? ? ? }
> + ? ? ? if (status & ATH9K_INT_RXEOL) {
> + ? ? ? ? ? ? ? ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
> + ? ? ? ? ? ? ? ath9k_hw_set_interrupts(ah, ah->imask);
> ? ? ? ?}
>
> ? ? ? ?if (status & ATH9K_INT_MIB) {
> --
> 1.7.6
>
> --
> 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
>

2011-08-13 04:59:11

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 11/11] ath9k: Dump modal noisefloor calibration history

Debugfs file location:
<debugfs_mnt>/ieee80211/phy#/ath9k/dump_nfcal

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/debug.c | 55 ++++++++++++++++++++++++++++++++
1 files changed, 55 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 9bec3b8..da45f32 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1163,6 +1163,59 @@ static const struct file_operations fops_regdump = {
.llseek = default_llseek,/* read accesses f_pos */
};

+static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_conf *conf = &common->hw->conf;
+ u32 len = 0, size = 1500;
+ u32 i, j;
+ ssize_t retval = 0;
+ char *buf;
+ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+ u8 nread;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ len += snprintf(buf + len, size - len,
+ "Channel Noise Floor : %d\n", ah->noise);
+ len += snprintf(buf + len, size - len,
+ "Chain | privNF | # Readings | NF Readings\n");
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (!(chainmask & (1 << i)) ||
+ ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
+ continue;
+
+ nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount;
+ len += snprintf(buf + len, size - len, " %d\t %d\t %d\t\t",
+ i, h[i].privNF, nread);
+ for (j = 0; j < nread; j++)
+ len += snprintf(buf + len, size - len,
+ " %d", h[i].nfCalBuffer[j]);
+ len += snprintf(buf + len, size - len, "\n");
+ }
+
+ if (len > size)
+ len = size;
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+static const struct file_operations fops_dump_nfcal = {
+ .read = read_file_dump_nfcal,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -1262,6 +1315,8 @@ int ath9k_init_debug(struct ath_hw *ah)
&ah->config.cwm_ignore_extcca);
debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_regdump);
+ debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_dump_nfcal);
debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_base_eeprom);
debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
--
1.7.6


2011-08-13 18:03:53

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH 02/11] ath9k: Fix rx overrun interrupt storm

On Sat, Aug 13, 2011 at 06:51:28PM +0800, Adrian Chadd wrote:
> I did this in FreeBSD to fix RXEOL storms, but I was receiving them
> because I had phyerr's enabled (for radar) and the PCU list end had
> actually been hit.
> So I added code which kicks off a PCU stop/start in the RX handler
> (once whatever packets were in the RX queue) so that the PCU receive
> would then begin again.
>
Nice. But why are you doing PCU stop/start for every RXEOL?
> Were you seeing it occur because you hit the end of the RX descriptor
> list? Or some other reason?
>
Yes. The RXORN/RXEOL intr issue was observed with AR9280 chip, while
running stress test.
> I ask because I'm seeing issues with an AR9280 (SR71-E) on FreeBSD,
> where the PCU stops RX for some reason, and constantly fires off
> RXEOLs. Warm resets don't fix it, I have to do a cold reset to fix it.
> :(
Are you still facing the issue after restarting pcu recv?
>
>
> Adrian
>
> On 13 August 2011 12:58, Rajkumar Manoharan <[email protected]> wrote:
> > Whenever RXEOL is received, both RXORN and RXEOL got cleared
> > to avoid rx overrun interrupt storm. This was handled only for
> > edma chips. The same scenario was also observered with AR9280,
> > doing frequent channel type switch b/w HT20/40 with bidi traffic
> > that is causing failure to stop rx dma. This patch clears
> > the RXEOL & RXORN interrupts for all chips.
> >
> > ath: DMA failed to stop in 10 ms AR_CR=0x00000024 AR_DIAG_SW=0x42000020
> > DMADBG_7=0x000062c0
> > ath: Could not stop RX, we could be confusing the DMA engine when we
> > start RX up
> > ------------[ cut here ]------------
> > WARNING: at drivers/net/wireless/ath/ath9k/recv.c:532
> > ath_stoprecv+0x110/0x120 [ath9k]()
> > Call Trace:
> > ?[<ffffffff8104a55a>] warn_slowpath_common+0x7a/0xb0
> > ?[<ffffffff8104a5a5>] warn_slowpath_null+0x15/0x20
> > ?[<ffffffffa0560380>] ath_stoprecv+0x110/0x120 [ath9k]
> > ?[<ffffffffa055e6fa>] ath_reset+0x6a/0x200 [ath9k]
> >
> > Signed-off-by: Rajkumar Manoharan <[email protected]>
> > ---
> > ?drivers/net/wireless/ath/ath9k/main.c | ? ?8 +++-----
> > ?1 files changed, 3 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
> > index 1e7fe8c..097c1eb 100644
> > --- a/drivers/net/wireless/ath/ath9k/main.c
> > +++ b/drivers/net/wireless/ath/ath9k/main.c
> > @@ -826,11 +826,9 @@ irqreturn_t ath_isr(int irq, void *dev)
> > ? ? ? ?if (status & ATH9K_INT_TXURN)
> > ? ? ? ? ? ? ? ?ath9k_hw_updatetxtriglevel(ah, true);
> >
> > - ? ? ? if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
> > - ? ? ? ? ? ? ? if (status & ATH9K_INT_RXEOL) {
> > - ? ? ? ? ? ? ? ? ? ? ? ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
> > - ? ? ? ? ? ? ? ? ? ? ? ath9k_hw_set_interrupts(ah, ah->imask);
> > - ? ? ? ? ? ? ? }
> > + ? ? ? if (status & ATH9K_INT_RXEOL) {
> > + ? ? ? ? ? ? ? ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
> > + ? ? ? ? ? ? ? ath9k_hw_set_interrupts(ah, ah->imask);
> > ? ? ? ?}
> >
> > ? ? ? ?if (status & ATH9K_INT_MIB) {
> > --
> > 1.7.6
> >
> > --
> > 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
> >

2011-08-14 02:39:52

by Adrian Chadd

[permalink] [raw]
Subject: Re: [PATCH 01/11] ath9k_hw: Fix exceed transmission burst-time of 5GHz

On 14 August 2011 10:39, Adrian Chadd <[email protected]> wrote:

> Ah, makes sense now. Well, we (collectively) should likely figure out
> how to teach the rate control and TX code how to not exceed TXOP in
> general.
> Do packets that exceed TXOP get marked as filtered?

.. when the relevant bit in AR_PCU_MISCMODE is enabled, that is?
(Obviously they're not being filtered now..)



Adrian

2011-08-13 04:58:05

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 02/11] ath9k: Fix rx overrun interrupt storm

Whenever RXEOL is received, both RXORN and RXEOL got cleared
to avoid rx overrun interrupt storm. This was handled only for
edma chips. The same scenario was also observered with AR9280,
doing frequent channel type switch b/w HT20/40 with bidi traffic
that is causing failure to stop rx dma. This patch clears
the RXEOL & RXORN interrupts for all chips.

ath: DMA failed to stop in 10 ms AR_CR=0x00000024 AR_DIAG_SW=0x42000020
DMADBG_7=0x000062c0
ath: Could not stop RX, we could be confusing the DMA engine when we
start RX up
------------[ cut here ]------------
WARNING: at drivers/net/wireless/ath/ath9k/recv.c:532
ath_stoprecv+0x110/0x120 [ath9k]()
Call Trace:
[<ffffffff8104a55a>] warn_slowpath_common+0x7a/0xb0
[<ffffffff8104a5a5>] warn_slowpath_null+0x15/0x20
[<ffffffffa0560380>] ath_stoprecv+0x110/0x120 [ath9k]
[<ffffffffa055e6fa>] ath_reset+0x6a/0x200 [ath9k]

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/main.c | 8 +++-----
1 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 1e7fe8c..097c1eb 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -826,11 +826,9 @@ irqreturn_t ath_isr(int irq, void *dev)
if (status & ATH9K_INT_TXURN)
ath9k_hw_updatetxtriglevel(ah, true);

- if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- if (status & ATH9K_INT_RXEOL) {
- ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
- ath9k_hw_set_interrupts(ah, ah->imask);
- }
+ if (status & ATH9K_INT_RXEOL) {
+ ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+ ath9k_hw_set_interrupts(ah, ah->imask);
}

if (status & ATH9K_INT_MIB) {
--
1.7.6


2011-08-13 05:00:57

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 08/11] ath9k: Move ath9k_init_crypto to common

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/ath9k.h | 1 -
drivers/net/wireless/ath/ath9k/common.c | 26 ++++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/common.h | 1 +
drivers/net/wireless/ath/ath9k/htc_drv_init.c | 21 +------------------
drivers/net/wireless/ath/ath9k/init.c | 27 +------------------------
drivers/net/wireless/ath/ath9k/pci.c | 2 +-
6 files changed, 30 insertions(+), 48 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 4b08a3d..3a893e1 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -663,7 +663,6 @@ extern int led_blink;
extern bool is_ath9k_unloaded;

irqreturn_t ath_isr(int irq, void *dev);
-void ath9k_init_crypto(struct ath_softc *sc);
int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops);
void ath9k_deinit_device(struct ath_softc *sc);
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index fa6bd2d..dc705a2 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -169,6 +169,32 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
}
EXPORT_SYMBOL(ath9k_cmn_update_txpow);

+void ath9k_cmn_init_crypto(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ int i = 0;
+
+ /* Get the hardware key cache size. */
+ common->keymax = AR_KEYTABLE_SIZE;
+
+ /*
+ * Check whether the separate key cache entries
+ * are required to handle both tx+rx MIC keys.
+ * With split mic keys the number of stations is limited
+ * to 27 otherwise 59.
+ */
+ if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
+ common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
+
+ /*
+ * Reset the key cache since some parts do not
+ * reset the contents on initial power up.
+ */
+ for (i = 0; i < common->keymax; i++)
+ ath_hw_keyreset(common, (u16) i);
+}
+EXPORT_SYMBOL(ath9k_cmn_init_crypto);
+
static int __init ath9k_cmn_init(void)
{
return 0;
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 77ec288..ad14fec 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -62,3 +62,4 @@ void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
enum ath_stomp_type stomp_type);
void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
u16 new_txpow, u16 *txpower);
+void ath9k_cmn_init_crypto(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 19aa5b7..9cf42f6 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -572,25 +572,6 @@ err:
return -EINVAL;
}

-static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
-{
- struct ath_common *common = ath9k_hw_common(priv->ah);
- int i = 0;
-
- /* Get the hardware key cache size. */
- common->keymax = AR_KEYTABLE_SIZE;
-
- if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
- common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
-
- /*
- * Reset the key cache since some parts do not
- * reset the contents on initial power up.
- */
- for (i = 0; i < common->keymax; i++)
- ath_hw_keyreset(common, (u16) i);
-}
-
static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
{
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
@@ -720,7 +701,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
priv->cur_beacon_conf.bslot[i] = NULL;

- ath9k_init_crypto(priv);
+ ath9k_cmn_init_crypto(ah);
ath9k_init_channels_rates(priv);
ath9k_init_misc(priv);

diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index db38a58..d7761d1 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -404,31 +404,6 @@ fail:
return error;
}

-void ath9k_init_crypto(struct ath_softc *sc)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- int i = 0;
-
- /* Get the hardware key cache size. */
- common->keymax = AR_KEYTABLE_SIZE;
-
- /*
- * Reset the key cache since some parts do not
- * reset the contents on initial power up.
- */
- for (i = 0; i < common->keymax; i++)
- ath_hw_keyreset(common, (u16) i);
-
- /*
- * Check whether the separate key cache entries
- * are required to handle both tx+rx MIC keys.
- * With split mic keys the number of stations is limited
- * to 27 otherwise 59.
- */
- if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
- common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
-}
-
static int ath9k_init_btcoex(struct ath_softc *sc)
{
struct ath_txq *txq;
@@ -630,7 +605,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
if (ret)
goto err_btcoex;

- ath9k_init_crypto(sc);
+ ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_init_misc(sc);

return 0;
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 5685cf1..b4205fa 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -338,7 +338,7 @@ static int ath_pci_resume(struct device *device)
* semi-random values after suspend/resume.
*/
ath9k_ps_wakeup(sc);
- ath9k_init_crypto(sc);
+ ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_ps_restore(sc);

sc->ps_idle = true;
--
1.7.6


2011-08-13 05:00:57

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 07/11] ath9k: Remove SC_OP_ENABLE_APM

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/ath9k.h | 3 +--
drivers/net/wireless/ath/ath9k/main.c | 4 ----
drivers/net/wireless/ath/ath9k/xmit.c | 6 +++---
3 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index c03949e..4b08a3d 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -558,8 +558,7 @@ struct ath_ant_comb {
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)
#define SC_OP_ANI_RUN BIT(14)
-#define SC_OP_ENABLE_APM BIT(15)
-#define SC_OP_PRIM_STA_VIF BIT(16)
+#define SC_OP_PRIM_STA_VIF BIT(15)

/* Powersave flags */
#define PS_WAIT_FOR_BEACON BIT(0)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 097c1eb..e828799 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -565,7 +565,6 @@ set_timer:
static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
struct ath_node *an;
- struct ath_hw *ah = sc->sc_ah;
an = (struct ath_node *)sta->drv_priv;

#ifdef CONFIG_ATH9K_DEBUGFS
@@ -574,9 +573,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
spin_unlock(&sc->nodes_lock);
an->sta = sta;
#endif
- if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM)
- sc->sc_flags |= SC_OP_ENABLE_APM;
-
if (sc->sc_flags & SC_OP_TXAGGR) {
ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index feef013..2062672 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1584,9 +1584,9 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
{
struct ath_hw *ah = sc->sc_ah;
struct ath9k_channel *curchan = ah->curchan;
- if ((sc->sc_flags & SC_OP_ENABLE_APM) &&
- (curchan->channelFlags & CHANNEL_5GHZ) &&
- (chainmask == 0x7) && (rate < 0x90))
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) &&
+ (curchan->channelFlags & CHANNEL_5GHZ) &&
+ (chainmask == 0x7) && (rate < 0x90))
return 0x3;
else
return chainmask;
--
1.7.6