* [PATCH 1/6] carl9170: import hw/fw header updates
2010-10-29 23:10 [PATCH 0/6] carl9170: 2.6.38 patches Christian Lamparter
@ 2010-10-29 20:44 ` Christian Lamparter
2010-10-29 21:11 ` [PATCH 2/6] carl9170: use generic sign_extend32 Christian Lamparter
` (5 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Christian Lamparter @ 2010-10-29 20:44 UTC (permalink / raw)
To: linux-wireless; +Cc: linville
This patch imports all shared header changes
from carl9170fw.git.
* add some strategic __aligned(4).
This allows the compiler generate optimized code for
architectures which can't access (unaligned/packed)
data efficiently.
("ath9k_hw: optimize all descriptor access functions")
* add a forgotten __CARL9170FW__ ifdef around
a private firmware-internal struct.
* GET_VAL macro helper
Very useful for extracting data out of the
bit-packed PHY registers.
* cosmetic changes
e.g.: _CCA_MINCCA_ to just _CCA_MIN_.
* version bump 1.8.8.3 -> 1.9.0.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
---
drivers/net/wireless/ath/carl9170/fwcmd.h | 13 +++++++++----
drivers/net/wireless/ath/carl9170/hw.h | 7 ++++++-
drivers/net/wireless/ath/carl9170/phy.h | 24 ++++++++++++------------
drivers/net/wireless/ath/carl9170/version.h | 6 +++---
4 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
index d552166..3680dfc7 100644
--- a/drivers/net/wireless/ath/carl9170/fwcmd.h
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -97,13 +97,13 @@ struct carl9170_set_key_cmd {
__le16 type;
u8 macAddr[6];
u32 key[4];
-} __packed;
+} __packed __aligned(4);
#define CARL9170_SET_KEY_CMD_SIZE 28
struct carl9170_disable_key_cmd {
__le16 user;
__le16 padding;
-} __packed;
+} __packed __aligned(4);
#define CARL9170_DISABLE_KEY_CMD_SIZE 4
struct carl9170_u32_list {
@@ -206,7 +206,7 @@ struct carl9170_cmd {
struct carl9170_rx_filter_cmd rx_filter;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
} __packed;
-} __packed;
+} __packed __aligned(4);
#define CARL9170_TX_STATUS_QUEUE 3
#define CARL9170_TX_STATUS_QUEUE_S 0
@@ -216,6 +216,7 @@ struct carl9170_cmd {
#define CARL9170_TX_STATUS_TRIES (7 << CARL9170_TX_STATUS_TRIES_S)
#define CARL9170_TX_STATUS_SUCCESS 0x80
+#ifdef __CARL9170FW__
/*
* NOTE:
* Both structs [carl9170_tx_status and _carl9170_tx_status]
@@ -232,6 +233,8 @@ struct carl9170_tx_status {
u8 tries:3;
u8 success:1;
} __packed;
+#endif /* __CARL9170FW__ */
+
struct _carl9170_tx_status {
/*
* This version should be immune to all alignment bugs.
@@ -272,13 +275,15 @@ struct carl9170_rsp {
struct carl9170_rf_init_result rf_init_res;
struct carl9170_u32_list rreg_res;
struct carl9170_u32_list echo;
+#ifdef __CARL9170FW__
struct carl9170_tx_status tx_status[0];
+#endif /* __CARL9170FW__ */
struct _carl9170_tx_status _tx_status[0];
struct carl9170_gpio gpio;
struct carl9170_tsf_rsp tsf;
struct carl9170_psm psm;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
} __packed;
-} __packed;
+} __packed __aligned(4);
#endif /* __CARL9170_SHARED_FWCMD_H */
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h
index 2f471b3..e85df6e 100644
--- a/drivers/net/wireless/ath/carl9170/hw.h
+++ b/drivers/net/wireless/ath/carl9170/hw.h
@@ -712,7 +712,8 @@ struct ar9170_stream {
__le16 tag;
u8 payload[0];
-};
+} __packed __aligned(4);
+#define AR9170_STREAM_LEN 4
#define AR9170_MAX_ACKTABLE_ENTRIES 8
#define AR9170_MAX_VIRTUAL_MAC 7
@@ -736,4 +737,8 @@ struct ar9170_stream {
#define MOD_VAL(reg, value, newvalue) \
(((value) & ~reg) | (((newvalue) << reg##_S) & reg))
+
+#define GET_VAL(reg, value) \
+ (((value) & reg) >> reg##_S)
+
#endif /* __CARL9170_SHARED_HW_H */
diff --git a/drivers/net/wireless/ath/carl9170/phy.h b/drivers/net/wireless/ath/carl9170/phy.h
index 02c34eb..024fb42 100644
--- a/drivers/net/wireless/ath/carl9170/phy.h
+++ b/drivers/net/wireless/ath/carl9170/phy.h
@@ -139,8 +139,8 @@
#define AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000
#define AR9170_PHY_REG_CCA (AR9170_PHY_REG_BASE + 0x0064)
-#define AR9170_PHY_CCA_MINCCA_PWR 0x0ff80000
-#define AR9170_PHY_CCA_MINCCA_PWR_S 19
+#define AR9170_PHY_CCA_MIN_PWR 0x0ff80000
+#define AR9170_PHY_CCA_MIN_PWR_S 19
#define AR9170_PHY_CCA_THRESH62 0x0007f000
#define AR9170_PHY_CCA_THRESH62_S 12
@@ -338,8 +338,8 @@
#define AR9170_PHY_EXT_CCA_CYCPWR_THR1_S 9
#define AR9170_PHY_EXT_CCA_THRESH62 0x007f0000
#define AR9170_PHY_EXT_CCA_THRESH62_S 16
-#define AR9170_PHY_EXT_MINCCA_PWR 0xff800000
-#define AR9170_PHY_EXT_MINCCA_PWR_S 23
+#define AR9170_PHY_EXT_CCA_MIN_PWR 0xff800000
+#define AR9170_PHY_EXT_CCA_MIN_PWR_S 23
#define AR9170_PHY_REG_SFCORR_EXT (AR9170_PHY_REG_BASE + 0x01c0)
#define AR9170_PHY_SFCORR_EXT_M1_THRESH 0x0000007f
@@ -546,19 +546,19 @@
#define AR9170_PHY_FORCE_XPA_CFG_S 0
#define AR9170_PHY_REG_CH1_CCA (AR9170_PHY_REG_BASE + 0x1064)
-#define AR9170_PHY_CH1_MINCCA_PWR 0x0ff80000
-#define AR9170_PHY_CH1_MINCCA_PWR_S 19
+#define AR9170_PHY_CH1_CCA_MIN_PWR 0x0ff80000
+#define AR9170_PHY_CH1_CCA_MIN_PWR_S 19
#define AR9170_PHY_REG_CH2_CCA (AR9170_PHY_REG_BASE + 0x2064)
-#define AR9170_PHY_CH2_MINCCA_PWR 0x0ff80000
-#define AR9170_PHY_CH2_MINCCA_PWR_S 19
+#define AR9170_PHY_CH2_CCA_MIN_PWR 0x0ff80000
+#define AR9170_PHY_CH2_CCA_MIN_PWR_S 19
#define AR9170_PHY_REG_CH1_EXT_CCA (AR9170_PHY_REG_BASE + 0x11bc)
-#define AR9170_PHY_CH1_EXT_MINCCA_PWR 0xff800000
-#define AR9170_PHY_CH1_EXT_MINCCA_PWR_S 23
+#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR 0xff800000
+#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR_S 23
#define AR9170_PHY_REG_CH2_EXT_CCA (AR9170_PHY_REG_BASE + 0x21bc)
-#define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000
-#define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23
+#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR 0xff800000
+#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR_S 23
#endif /* __CARL9170_SHARED_PHY_H */
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
index ff53f07..ee0f84f 100644
--- a/drivers/net/wireless/ath/carl9170/version.h
+++ b/drivers/net/wireless/ath/carl9170/version.h
@@ -1,7 +1,7 @@
#ifndef __CARL9170_SHARED_VERSION_H
#define __CARL9170_SHARED_VERSION_H
#define CARL9170FW_VERSION_YEAR 10
-#define CARL9170FW_VERSION_MONTH 9
-#define CARL9170FW_VERSION_DAY 28
-#define CARL9170FW_VERSION_GIT "1.8.8.3"
+#define CARL9170FW_VERSION_MONTH 10
+#define CARL9170FW_VERSION_DAY 29
+#define CARL9170FW_VERSION_GIT "1.9.0"
#endif /* __CARL9170_SHARED_VERSION_H */
--
1.7.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 2/6] carl9170: use generic sign_extend32
2010-10-29 23:10 [PATCH 0/6] carl9170: 2.6.38 patches Christian Lamparter
2010-10-29 20:44 ` [PATCH 1/6] carl9170: import hw/fw header updates Christian Lamparter
@ 2010-10-29 21:11 ` Christian Lamparter
2010-11-10 20:06 ` John W. Linville
2010-10-29 21:17 ` [PATCH 3/6] carl9170: initialize HW aMPDU parameters properly Christian Lamparter
` (4 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Christian Lamparter @ 2010-10-29 21:11 UTC (permalink / raw)
To: linux-wireless; +Cc: linville
This patch replaces the handcrafted
sign extension cruft with a generic
bitop function.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
---
drivers/net/wireless/ath/carl9170/phy.c | 17 ++++-------------
1 files changed, 4 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index 89deca3..82bc81c 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -1554,15 +1554,6 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
return carl9170_regwrite_result();
}
-/* TODO: replace this with sign_extend32(noise, 8) */
-static int carl9170_calc_noise_dbm(u32 raw_noise)
-{
- if (raw_noise & 0x100)
- return ~0x1ff | raw_noise;
- else
- return raw_noise;
-}
-
int carl9170_get_noisefloor(struct ar9170 *ar)
{
static const u32 phy_regs[] = {
@@ -1578,11 +1569,11 @@ int carl9170_get_noisefloor(struct ar9170 *ar)
return err;
for (i = 0; i < 2; i++) {
- ar->noise[i] = carl9170_calc_noise_dbm(
- (phy_res[i] >> 19) & 0x1ff);
+ ar->noise[i] = sign_extend32(GET_VAL(
+ AR9170_PHY_CCA_MIN_PWR, phy_res[i]), 8);
- ar->noise[i + 2] = carl9170_calc_noise_dbm(
- (phy_res[i + 2] >> 23) & 0x1ff);
+ ar->noise[i + 2] = sign_extend32(GET_VAL(
+ AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8);
}
return 0;
--
1.7.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 2/6] carl9170: use generic sign_extend32
2010-10-29 21:11 ` [PATCH 2/6] carl9170: use generic sign_extend32 Christian Lamparter
@ 2010-11-10 20:06 ` John W. Linville
2010-11-10 20:21 ` Christian Lamparter
0 siblings, 1 reply; 11+ messages in thread
From: John W. Linville @ 2010-11-10 20:06 UTC (permalink / raw)
To: Christian Lamparter; +Cc: linux-wireless
On Fri, Oct 29, 2010 at 11:11:23PM +0200, Christian Lamparter wrote:
> This patch replaces the handcrafted
> sign extension cruft with a generic
> bitop function.
>
> Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
CC [M] drivers/net/wireless/ath/carl9170/phy.o
drivers/net/wireless/ath/carl9170/phy.c: In function ‘carl9170_get_noisefloor’:
drivers/net/wireless/ath/carl9170/phy.c:1572: error: implicit declaration of function ‘sign_extend32’
make[3]: *** [drivers/net/wireless/ath/carl9170/phy.o] Error 1
make[2]: *** [drivers/net/wireless/ath/carl9170] Error 2
make[1]: *** [drivers/net/wireless/ath] Error 2
make: *** [drivers/net/wireless/] Error 2
Maybe we should wait until this function exists before we use it? :-)
John
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/6] carl9170: use generic sign_extend32
2010-11-10 20:06 ` John W. Linville
@ 2010-11-10 20:21 ` Christian Lamparter
2010-11-10 20:43 ` John W. Linville
0 siblings, 1 reply; 11+ messages in thread
From: Christian Lamparter @ 2010-11-10 20:21 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Andreas Herrmann
On Wednesday 10 November 2010 21:06:36 John W. Linville wrote:
> On Fri, Oct 29, 2010 at 11:11:23PM +0200, Christian Lamparter wrote:
> > This patch replaces the handcrafted
> > sign extension cruft with a generic
> > bitop function.
> >
> > Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
>
> CC [M] drivers/net/wireless/ath/carl9170/phy.o
> drivers/net/wireless/ath/carl9170/phy.c: In function ‘carl9170_get_noisefloor’:
> drivers/net/wireless/ath/carl9170/phy.c:1572: error: implicit declaration of function ‘sign_extend32’
> make[3]: *** [drivers/net/wireless/ath/carl9170/phy.o] Error 1
> make[2]: *** [drivers/net/wireless/ath/carl9170] Error 2
> make[1]: *** [drivers/net/wireless/ath] Error 2
> make: *** [drivers/net/wireless/] Error 2
>
> Maybe we should wait until this function exists before we use it? :-)
interesting,
https://patchwork.kernel.org/patch/143241/
so why exactly wasn't this patch merged?
Regards,
Chr
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/6] carl9170: use generic sign_extend32
2010-11-10 20:21 ` Christian Lamparter
@ 2010-11-10 20:43 ` John W. Linville
0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2010-11-10 20:43 UTC (permalink / raw)
To: Christian Lamparter; +Cc: linux-wireless, Andreas Herrmann
On Wed, Nov 10, 2010 at 09:21:49PM +0100, Christian Lamparter wrote:
> On Wednesday 10 November 2010 21:06:36 John W. Linville wrote:
> > On Fri, Oct 29, 2010 at 11:11:23PM +0200, Christian Lamparter wrote:
> > > This patch replaces the handcrafted
> > > sign extension cruft with a generic
> > > bitop function.
> > >
> > > Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
> >
> > CC [M] drivers/net/wireless/ath/carl9170/phy.o
> > drivers/net/wireless/ath/carl9170/phy.c: In function ‘carl9170_get_noisefloor’:
> > drivers/net/wireless/ath/carl9170/phy.c:1572: error: implicit declaration of function ‘sign_extend32’
> > make[3]: *** [drivers/net/wireless/ath/carl9170/phy.o] Error 1
> > make[2]: *** [drivers/net/wireless/ath/carl9170] Error 2
> > make[1]: *** [drivers/net/wireless/ath] Error 2
> > make: *** [drivers/net/wireless/] Error 2
> >
> > Maybe we should wait until this function exists before we use it? :-)
> interesting,
>
> https://patchwork.kernel.org/patch/143241/
>
> so why exactly wasn't this patch merged?
Probably because the combination of To: and Cc: he used made everyone
think it was someone else's patch to merge. :-(
I can take it, thanks for the link.
John
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/6] carl9170: initialize HW aMPDU parameters properly
2010-10-29 23:10 [PATCH 0/6] carl9170: 2.6.38 patches Christian Lamparter
2010-10-29 20:44 ` [PATCH 1/6] carl9170: import hw/fw header updates Christian Lamparter
2010-10-29 21:11 ` [PATCH 2/6] carl9170: use generic sign_extend32 Christian Lamparter
@ 2010-10-29 21:17 ` Christian Lamparter
2010-10-29 21:26 ` [PATCH 4/6] carl9170: fix spurious restart due to high latency Christian Lamparter
` (3 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Christian Lamparter @ 2010-10-29 21:17 UTC (permalink / raw)
To: linux-wireless; +Cc: linville
This patch changes the initial aMPDU density and
factor settings to match those of Otus.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
---
drivers/net/wireless/ath/carl9170/mac.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
index 2305bc2..c34eeee 100644
--- a/drivers/net/wireless/ath/carl9170/mac.c
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -205,8 +205,8 @@ int carl9170_init_mac(struct ar9170 *ar)
carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
/* Aggregation MAX number and timeout */
- carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0xa);
- carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a00);
+ carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0x8000a);
+ carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a07);
carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
AR9170_MAC_FTF_DEFAULTS);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 4/6] carl9170: fix spurious restart due to high latency
2010-10-29 23:10 [PATCH 0/6] carl9170: 2.6.38 patches Christian Lamparter
` (2 preceding siblings ...)
2010-10-29 21:17 ` [PATCH 3/6] carl9170: initialize HW aMPDU parameters properly Christian Lamparter
@ 2010-10-29 21:26 ` Christian Lamparter
2010-10-29 21:41 ` [PATCH 5/6] carl9170: stop stale uplink BA sessions Christian Lamparter
` (2 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Christian Lamparter @ 2010-10-29 21:26 UTC (permalink / raw)
To: linux-wireless; +Cc: linville
RX Stress tests of unidirectional bulk traffic with
bitrates of up to 220Mbit/s have revealed that the
fatal-event recovery logic [which was solely triggered
by an out-of-rx-buffer situation] is too aggressive.
The new method now "pings" the device and then
decides - based on the response - whenever
a restart is needed or not.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
---
drivers/net/wireless/ath/carl9170/carl9170.h | 3 ++-
drivers/net/wireless/ath/carl9170/main.c | 17 +++++++++++++++++
drivers/net/wireless/ath/carl9170/usb.c | 2 +-
3 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 6cf0c9e..f1212ba 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -215,7 +215,7 @@ enum carl9170_restart_reasons {
CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
CARL9170_RR_WATCHDOG,
CARL9170_RR_STUCK_TX,
- CARL9170_RR_SLOW_SYSTEM,
+ CARL9170_RR_UNRESPONSIVE_DEVICE,
CARL9170_RR_COMMAND_TIMEOUT,
CARL9170_RR_TOO_MANY_PHY_ERRORS,
CARL9170_RR_LOST_RSP,
@@ -287,6 +287,7 @@ struct ar9170 {
/* reset / stuck frames/queue detection */
struct work_struct restart_work;
+ struct work_struct ping_work;
unsigned int restart_counter;
unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index d56f440..b997844 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -428,6 +428,7 @@ static void carl9170_cancel_worker(struct ar9170 *ar)
cancel_delayed_work_sync(&ar->led_work);
#endif /* CONFIG_CARL9170_LEDS */
cancel_work_sync(&ar->ps_work);
+ cancel_work_sync(&ar->ping_work);
cancel_work_sync(&ar->ampdu_work);
}
@@ -533,6 +534,21 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
*/
}
+static void carl9170_ping_work(struct work_struct *work)
+{
+ struct ar9170 *ar = container_of(work, struct ar9170, ping_work);
+ int err;
+
+ if (!IS_STARTED(ar))
+ return;
+
+ mutex_lock(&ar->mutex);
+ err = carl9170_echo_test(ar, 0xdeadbeef);
+ if (err)
+ carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE);
+ mutex_unlock(&ar->mutex);
+}
+
static int carl9170_init_interface(struct ar9170 *ar,
struct ieee80211_vif *vif)
{
@@ -1614,6 +1630,7 @@ void *carl9170_alloc(size_t priv_size)
skb_queue_head_init(&ar->tx_pending[i]);
}
INIT_WORK(&ar->ps_work, carl9170_ps_work);
+ INIT_WORK(&ar->ping_work, carl9170_ping_work);
INIT_WORK(&ar->restart_work, carl9170_restart_work);
INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index d8607f4..ddf5373 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -431,7 +431,7 @@ static void carl9170_usb_rx_complete(struct urb *urb)
* device.
*/
- carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
+ ieee80211_queue_work(ar->hw, &ar->ping_work);
}
} else {
/*
--
1.7.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5/6] carl9170: stop stale uplink BA sessions
2010-10-29 23:10 [PATCH 0/6] carl9170: 2.6.38 patches Christian Lamparter
` (3 preceding siblings ...)
2010-10-29 21:26 ` [PATCH 4/6] carl9170: fix spurious restart due to high latency Christian Lamparter
@ 2010-10-29 21:41 ` Christian Lamparter
2010-10-29 22:36 ` [PATCH 6/6] carl9170: configurable beacon rates Christian Lamparter
2010-10-29 22:49 ` [RFT] carl9170: improve rx ampdu software deaggregation Christian Lamparter
6 siblings, 0 replies; 11+ messages in thread
From: Christian Lamparter @ 2010-10-29 21:41 UTC (permalink / raw)
To: linux-wireless; +Cc: linville
This patch fixes a possible lengthy stall if the device
is operating as an experimental 11n AP and an STA
[during heavy txrx action] suddenly signalized to go
off-channel (old NetworkManager), or (sleep - which is
unlikely, because then it wouldn't be *active* at all!?).
Because the driver has to manage the BA Window, the
sudden PSM transition can leave active uplink BA
sessions to the STA in a bad state and a proper
cleanup is needed.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
---
drivers/net/wireless/ath/carl9170/tx.c | 54 ++++++++++++++++++++++++++++++++
1 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index b575c86..b27969c 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -524,6 +524,59 @@ next:
}
}
+static void carl9170_tx_ampdu_timeout(struct ar9170 *ar)
+{
+ struct carl9170_sta_tid *iter;
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *txinfo;
+ struct carl9170_tx_info *arinfo;
+ struct _carl9170_tx_superframe *super;
+ struct ieee80211_sta *sta;
+ struct ieee80211_vif *vif;
+ struct ieee80211_hdr *hdr;
+ unsigned int vif_id;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) {
+ if (iter->state < CARL9170_TID_STATE_IDLE)
+ continue;
+
+ spin_lock_bh(&iter->lock);
+ skb = skb_peek(&iter->queue);
+ if (!skb)
+ goto unlock;
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ arinfo = (void *)txinfo->rate_driver_data;
+ if (time_is_after_jiffies(arinfo->timeout +
+ msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT)))
+ goto unlock;
+
+ super = (void *) skb->data;
+ hdr = (void *) super->frame_data;
+
+ vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >>
+ CARL9170_TX_SUPER_MISC_VIF_ID_S;
+
+ if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC))
+ goto unlock;
+
+ vif = rcu_dereference(ar->vif_priv[vif_id].vif);
+ if (WARN_ON(!vif))
+ goto unlock;
+
+ sta = ieee80211_find_sta(vif, hdr->addr1);
+ if (WARN_ON(!sta))
+ goto unlock;
+
+ ieee80211_stop_tx_ba_session(sta, iter->tid);
+unlock:
+ spin_unlock_bh(&iter->lock);
+
+ }
+ rcu_read_unlock();
+}
+
void carl9170_tx_janitor(struct work_struct *work)
{
struct ar9170 *ar = container_of(work, struct ar9170,
@@ -534,6 +587,7 @@ void carl9170_tx_janitor(struct work_struct *work)
ar->tx_janitor_last_run = jiffies;
carl9170_check_queue_stop_timeout(ar);
+ carl9170_tx_ampdu_timeout(ar);
if (!atomic_read(&ar->tx_total_queued))
return;
--
1.7.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 6/6] carl9170: configurable beacon rates
2010-10-29 23:10 [PATCH 0/6] carl9170: 2.6.38 patches Christian Lamparter
` (4 preceding siblings ...)
2010-10-29 21:41 ` [PATCH 5/6] carl9170: stop stale uplink BA sessions Christian Lamparter
@ 2010-10-29 22:36 ` Christian Lamparter
2010-10-29 22:49 ` [RFT] carl9170: improve rx ampdu software deaggregation Christian Lamparter
6 siblings, 0 replies; 11+ messages in thread
From: Christian Lamparter @ 2010-10-29 22:36 UTC (permalink / raw)
To: linux-wireless; +Cc: linville
Previously, the beacon rate was fixed to either:
* 1Mb/s [2.4GHz band]
* 6Mb/s [5GHz band]
This limitation has been addressed and now the
beacon rate is selected by ieee80211_tx_info's
rate control info, almost like any ordinary
data frame.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
---
drivers/net/wireless/ath/carl9170/mac.c | 52 +++++++++++++++++++------------
1 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
index c34eeee..385cf50 100644
--- a/drivers/net/wireless/ath/carl9170/mac.c
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -457,8 +457,9 @@ int carl9170_set_beacon_timers(struct ar9170 *ar)
int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
{
- struct sk_buff *skb;
+ struct sk_buff *skb = NULL;
struct carl9170_vif_info *cvif;
+ struct ieee80211_tx_info *txinfo;
__le32 *data, *old = NULL;
u32 word, off, addr, len;
int i = 0, err = 0;
@@ -487,7 +488,13 @@ found:
if (!skb) {
err = -ENOMEM;
- goto out_unlock;
+ goto err_free;
+ }
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) {
+ err = -EINVAL;
+ goto err_free;
}
spin_lock_bh(&ar->beacon_lock);
@@ -504,11 +511,8 @@ found:
wiphy_err(ar->hw->wiphy, "beacon does not "
"fit into device memory!\n");
}
-
- spin_unlock_bh(&ar->beacon_lock);
- dev_kfree_skb_any(skb);
err = -EINVAL;
- goto out_unlock;
+ goto err_unlock;
}
if (len > AR9170_MAC_BCN_LENGTH_MAX) {
@@ -518,22 +522,22 @@ found:
AR9170_MAC_BCN_LENGTH_MAX, len);
}
- spin_unlock_bh(&ar->beacon_lock);
- dev_kfree_skb_any(skb);
err = -EMSGSIZE;
- goto out_unlock;
+ goto err_unlock;
}
- carl9170_async_regwrite_begin(ar);
+ i = txinfo->control.rates[0].idx;
+ if (txinfo->band != IEEE80211_BAND_2GHZ)
+ i += 4;
- /* XXX: use skb->cb info */
- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
- carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
- ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400);
- } else {
- carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
- ((skb->len + FCS_LEN) << 16) + 0x001b);
- }
+ word = __carl9170_ratetable[i].hw_value & 0xf;
+ if (i < 4)
+ word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
+ else
+ word |= ((skb->len + FCS_LEN) << 16) + 0x0010;
+
+ carl9170_async_regwrite_begin(ar);
+ carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word);
for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
/*
@@ -557,7 +561,7 @@ found:
cvif->beacon = skb;
spin_unlock_bh(&ar->beacon_lock);
if (err)
- goto out_unlock;
+ goto err_free;
if (submit) {
err = carl9170_bcn_ctrl(ar, cvif->id,
@@ -565,10 +569,18 @@ found:
addr, skb->len + FCS_LEN);
if (err)
- goto out_unlock;
+ goto err_free;
}
out_unlock:
rcu_read_unlock();
+ return 0;
+
+err_unlock:
+ spin_unlock_bh(&ar->beacon_lock);
+
+err_free:
+ rcu_read_unlock();
+ dev_kfree_skb_any(skb);
return err;
}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [RFT] carl9170: improve rx ampdu software deaggregation
2010-10-29 23:10 [PATCH 0/6] carl9170: 2.6.38 patches Christian Lamparter
` (5 preceding siblings ...)
2010-10-29 22:36 ` [PATCH 6/6] carl9170: configurable beacon rates Christian Lamparter
@ 2010-10-29 22:49 ` Christian Lamparter
6 siblings, 0 replies; 11+ messages in thread
From: Christian Lamparter @ 2010-10-29 22:49 UTC (permalink / raw)
To: linux-wireless; +Cc: linville
This patch improves the stateless ampdu rx filter to
scan and salvage intact MPDUs from otherwise "bad data".
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
---
Note: The search is expensive [compared to the other approach],
but it helps in my setup and if the stats are true it saves
around 10% of the otherwise lost data [but mostly small frames].
---
drivers/net/wireless/ath/carl9170/carl9170.h | 3 +
drivers/net/wireless/ath/carl9170/main.c | 1 +
drivers/net/wireless/ath/carl9170/rx.c | 117 +++++++++++++++++++++-----
3 files changed, 101 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index f1212ba..17109cc 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -402,6 +402,9 @@ struct ar9170 {
/* rxstream mpdu merge */
struct ar9170_rx_head rx_plcp;
bool rx_has_plcp;
+ bool has_ampdu_id;
+ __le16 ampdu_id;
+ u8 ampdu_ra[ETH_ALEN];
struct sk_buff *rx_failover;
int rx_failover_missing;
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index b997844..1b1645a 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -561,6 +561,7 @@ static int carl9170_init_interface(struct ar9170 *ar,
}
memcpy(common->macaddr, vif->addr, ETH_ALEN);
+ memcpy(ar->ampdu_ra, vif->addr, ETH_ALEN);
if (modparam_nohwcrypt ||
((vif->type != NL80211_IFTYPE_STATION) &&
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index 939a0e9..0ef658b 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -576,18 +576,13 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
}
}
-static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
-{
- __le16 fc;
+/* FC + DU + RA + FCS */
+#define MIN_LEN (2 + 2 + ETH_ALEN + FCS_LEN)
- if ((ms & AR9170_RX_STATUS_MPDU) == AR9170_RX_STATUS_MPDU_SINGLE) {
- /*
- * This frame is not part of an aMPDU.
- * Therefore it is not subjected to any
- * of the following content restrictions.
- */
- return true;
- }
+static bool carl9170_ampdu_check(struct ar9170 *ar, struct ieee80211_hdr *hdr,
+ int len)
+{
+ __le16 fc = hdr->frame_control;
/*
* "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts
@@ -597,20 +592,103 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
* stateless filter solely based on the frame control field.
*/
- fc = ((struct ieee80211_hdr *)buf)->frame_control;
- if (ieee80211_is_data_qos(fc) && ieee80211_is_data_present(fc))
+ if (ieee80211_has_tods(fc) &&
+ memcmp(hdr->addr1, ar->ampdu_ra, ETH_ALEN) != 0)
+ return false;
+
+ if (ieee80211_is_data_qos(fc) && ieee80211_is_data_present(fc) &&
+ !ieee80211_has_morefrags(fc) && !(hdr->seq_ctrl & cpu_to_le16(0xf))
+ && !ieee80211_has_pm(fc) && len >= sizeof(*hdr) + FCS_LEN)
return true;
- if (ieee80211_is_ack(fc) || ieee80211_is_back(fc) ||
- ieee80211_is_back_req(fc))
+ if ((ieee80211_is_ack(fc) && len == MIN_LEN) ||
+ ((ieee80211_is_back(fc) || ieee80211_is_back_req(fc)) &&
+ len >= sizeof(struct ieee80211_bar)))
return true;
- if (ieee80211_is_action(fc))
+ if (ieee80211_is_action(fc) && len > MIN_LEN)
return true;
return false;
}
+static bool carl9170_ampdu_checker(struct ar9170 *ar, u8 **buf, int *len)
+{
+ struct ieee80211_hdr *hdr;
+
+ do {
+ hdr = (struct ieee80211_hdr *) *(buf);
+
+ /*
+ * 802.11n - 7.4a.3: "All the MPDUs within an A-MPDU are
+ * addressed to the same RA."
+ */
+ if ((memcmp(ar->ampdu_ra, hdr->addr1, ETH_ALEN) == 0)) {
+ /*
+ * 802.11n - 7.4a.3: "The Duration/ID fields in the
+ * MAC headers of all MPDUs in an A-MPDU carry the
+ * same value."
+ */
+ if (!(ar->has_ampdu_id &&
+ (ar->ampdu_id != hdr->duration_id))) {
+ if (carl9170_ampdu_check(ar, hdr, *len))
+ return true;
+ }
+ }
+
+ (*buf)++;
+ (*len)--;
+ } while (*len >= MIN_LEN);
+
+ return false;
+}
+
+static bool carl9170_ampdu_state_check(struct ar9170 *ar, u8 **buf,
+ u8 ms, int *len)
+{
+ int i;
+
+ if ((ms & AR9170_RX_STATUS_MPDU) == AR9170_RX_STATUS_MPDU_SINGLE ||
+ unlikely(ar->sniffer_enabled)) {
+ /*
+ * This frame is not part of an aMPDU.
+ * Therefore it is not subjected to any
+ * of the following content restrictions.
+ *
+ * Also, in sniffer mode we don't want
+ * anything to touch the raw frames.
+ */
+ return true;
+ }
+
+ if (carl9170_ampdu_checker(ar, buf, len))
+ return true;
+
+ if ((ms & AR9170_RX_STATUS_MPDU) != AR9170_RX_STATUS_MPDU_FIRST)
+ return false;
+
+ rcu_read_lock();
+ for_each_set_bit(i, &ar->vif_bitmap, ar->fw.vif_num) {
+ struct ieee80211_vif *vif;
+
+ vif = rcu_dereference(ar->vif_priv[i].vif);
+ if (vif) {
+ memcpy(ar->ampdu_ra, vif->addr, ETH_ALEN);
+
+ if (carl9170_ampdu_checker(ar, buf, len)) {
+ struct ieee80211_hdr *hdr = (void *)(*buf);
+
+ ar->has_ampdu_id = true;
+ ar->ampdu_id = hdr->duration_id;
+ break;
+ }
+ }
+ }
+ rcu_read_unlock();
+
+ return i == ar->fw.vif_num;
+}
+
/*
* If the frame alignment is right (or the kernel has
* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
@@ -660,7 +738,7 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
mpdu_len -= sizeof(struct ar9170_rx_head);
buf += sizeof(struct ar9170_rx_head);
-
+ ar->has_ampdu_id = false;
ar->rx_has_plcp = true;
} else {
if (net_ratelimit()) {
@@ -722,15 +800,14 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
break;
}
- /* FC + DU + RA + FCS */
- if (unlikely(mpdu_len < (2 + 2 + ETH_ALEN + FCS_LEN)))
+ if (unlikely(mpdu_len < MIN_LEN))
goto drop;
memset(&status, 0, sizeof(status));
if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status)))
goto drop;
- if (!carl9170_ampdu_check(ar, buf, mac_status))
+ if (!carl9170_ampdu_state_check(ar, &buf, mac_status, &mpdu_len))
goto drop;
if (phy)
--
1.7.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread