2011-04-26 20:22:01

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH v2] wl12xx: support FW TX inactivity triggers

In AP mode we register for the MAX_TX_RETRY and INACTIVE_STA events.
Both are reported to the upper layers as a TX failure in the offending
stations.

In STA mode we register only for the MAX_TX_RETRY event. A TX failure is
interpreted as a loss of connection.

Support for IEEE80211_HW_REPORTS_TX_ACK_STATUS has been removed to avoid
the inherent race condition of a mac80211 TX failure counter in addition
to the FW counter.

This patch depends on "mac80211: allow low level driver to report packet
loss"

Signed-off-by: Arik Nemtsov <[email protected]>
---

v1->2: STA mode configuration for max TX retries is performed using
a different FW command.

drivers/net/wireless/wl12xx/acx.c | 34 +++++++++++++++++++++---
drivers/net/wireless/wl12xx/acx.h | 12 +++++++-
drivers/net/wireless/wl12xx/boot.c | 6 +++-
drivers/net/wireless/wl12xx/cmd.c | 2 +-
drivers/net/wireless/wl12xx/conf.h | 12 +++++++-
drivers/net/wireless/wl12xx/event.c | 47 ++++++++++++++++++++++++++++++++++
drivers/net/wireless/wl12xx/event.h | 12 ++++++++-
drivers/net/wireless/wl12xx/init.c | 6 +++-
drivers/net/wireless/wl12xx/main.c | 10 ++++++-
drivers/net/wireless/wl12xx/wl12xx.h | 1 -
10 files changed, 125 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 18a8828..8a39d1e 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1524,22 +1524,46 @@ out:
return ret;
}

-int wl1271_acx_max_tx_retry(struct wl1271 *wl)
+int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
{
- struct wl1271_acx_max_tx_retry *acx = NULL;
+ struct wl1271_acx_ap_max_tx_retry *acx = NULL;
int ret;

- wl1271_debug(DEBUG_ACX, "acx max tx retry");
+ wl1271_debug(DEBUG_ACX, "acx ap max tx retry");

acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx)
return -ENOMEM;

- acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries);
+ acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries);

ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));
if (ret < 0) {
- wl1271_warning("acx max tx retry failed: %d", ret);
+ wl1271_warning("acx ap max tx retry failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl)
+{
+ struct wl1271_acx_sta_max_tx_retry *acx = NULL;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx sta max tx retry");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx)
+ return -ENOMEM;
+
+ acx->max_tx_retry = wl->conf.tx.max_tx_retries;
+
+ ret = wl1271_cmd_configure(wl, ACX_CONS_TX_FAILURE, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("acx sta max tx retry failed: %d", ret);
goto out;
}

diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index dd75463..2dde034 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -1145,7 +1145,7 @@ struct wl1271_acx_fw_tsf_information {
u8 padding[3];
} __packed;

-struct wl1271_acx_max_tx_retry {
+struct wl1271_acx_ap_max_tx_retry {
struct acx_header header;

/*
@@ -1156,6 +1156,13 @@ struct wl1271_acx_max_tx_retry {
u8 padding_1[2];
} __packed;

+struct wl1271_acx_sta_max_tx_retry {
+ struct acx_header header;
+
+ u8 max_tx_retry;
+ u8 padding_1[3];
+} __packed;
+
struct wl1271_acx_config_ps {
struct acx_header header;

@@ -1367,7 +1374,8 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
bool enable);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
-int wl1271_acx_max_tx_retry(struct wl1271 *wl);
+int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl);
+int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl);
int wl1271_acx_config_ps(struct wl1271 *wl);
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
int wl1271_acx_fm_coex(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 2b0cf85..d263ebb 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -478,10 +478,12 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
DISCONNECT_EVENT_COMPLETE_ID |
RSSI_SNR_TRIGGER_0_EVENT_ID |
PSPOLL_DELIVERY_FAILURE_EVENT_ID |
- SOFT_GEMINI_SENSE_EVENT_ID;
+ SOFT_GEMINI_SENSE_EVENT_ID |
+ MAX_TX_RETRY_EVENT_ID;

if (wl->bss_type == BSS_TYPE_AP_BSS)
- wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
+ wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID |
+ INACTIVE_STA_EVENT_ID;
else
wl->event_mask |= DUMMY_PACKET_EVENT_ID;

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 9917129..bfe74d4 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -1077,7 +1077,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl)

memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);

- cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC);
+ cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
cmd->bss_index = WL1271_AP_BSS_INDEX;
cmd->global_hlid = WL1271_AP_GLOBAL_HLID;
cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID;
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index a5841ce..9b36944 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -690,10 +690,18 @@ struct conf_tx_settings {
struct conf_tx_rate_class ap_bcst_conf;

/*
- * AP-mode - allow this number of TX retries to a station before an
+ * Allow this number of TX retries to a connected station/AP before an
* event is triggered from FW.
+ * In AP-mode the hlids of unreachable stations are given in the
+ * "sta_tx_retry_exceeded" member in the event mailbox.
*/
- u16 ap_max_tx_retries;
+ u8 max_tx_retries;
+
+ /*
+ * AP-mode - after this number of seconds a connected station is
+ * considered inactive.
+ */
+ u16 ap_aging_period;

/*
* Configuration for TID parameters.
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index ae69330..d7be3ae 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -174,6 +174,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
u32 vector;
bool beacon_loss = false;
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+ bool disconnect_sta = false;
+ unsigned long sta_bitmap = 0;

wl1271_event_mbox_dump(mbox);

@@ -235,9 +237,54 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_tx_dummy_packet(wl);
}

+ /*
+ * "TX retries exceeded" has a different meaning according to mode.
+ * In AP mode the offending station is disconnected. In STA mode we
+ * report connection loss.
+ */
+ if (vector & MAX_TX_RETRY_EVENT_ID) {
+ wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID");
+ if (is_ap) {
+ sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded);
+ disconnect_sta = true;
+ } else {
+ beacon_loss = true;
+ }
+ }
+
+ if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) {
+ wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
+ sta_bitmap |= le16_to_cpu(mbox->sta_aging_status);
+ disconnect_sta = true;
+ }
+
if (wl->vif && beacon_loss)
ieee80211_connection_loss(wl->vif);

+ if (is_ap && disconnect_sta) {
+ u32 num_packets = wl->conf.tx.max_tx_retries;
+ struct ieee80211_sta *sta;
+ const u8 *addr;
+ int h;
+
+ for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS);
+ h < AP_MAX_LINKS;
+ h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) {
+ if (!wl1271_is_active_sta(wl, h))
+ continue;
+
+ addr = wl->links[h].addr;
+
+ rcu_read_lock();
+ sta = ieee80211_find_sta(wl->vif, addr);
+ if (sta) {
+ wl1271_debug(DEBUG_EVENT, "remove sta %d", h);
+ ieee80211_report_low_ack(sta, num_packets);
+ }
+ rcu_read_unlock();
+ }
+ }
+
return 0;
}

diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index b6cf06e..7ae5a08 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -58,13 +58,16 @@ enum {
CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
BSS_LOSE_EVENT_ID = BIT(18),
REGAINED_BSS_EVENT_ID = BIT(19),
- ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20),
+ MAX_TX_RETRY_EVENT_ID = BIT(20),
/* STA: dummy paket for dynamic mem blocks */
DUMMY_PACKET_EVENT_ID = BIT(21),
/* AP: STA remove complete */
STA_REMOVE_COMPLETE_EVENT_ID = BIT(21),
SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
+ /* STA: SG prediction */
SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
+ /* AP: Inactive STA */
+ INACTIVE_STA_EVENT_ID = BIT(23),
SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25),
DBG_EVENT_ID = BIT(26),
@@ -119,7 +122,11 @@ struct event_mailbox {

/* AP FW only */
u8 hlid_removed;
+
+ /* a bitmap of hlids for stations that have been inactive too long */
__le16 sta_aging_status;
+
+ /* a bitmap of hlids for stations which didn't respond to TX */
__le16 sta_tx_retry_exceeded;

u8 reserved_5[24];
@@ -130,4 +137,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl);
int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
void wl1271_pspoll_work(struct work_struct *work);

+/* Functions from main.c */
+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid);
+
#endif
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index d2dc09e..46fd721 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -380,6 +380,10 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;

+ ret = wl1271_acx_sta_max_tx_retry(wl);
+ if (ret < 0)
+ return ret;
+
ret = wl1271_acx_sta_mem_cfg(wl);
if (ret < 0)
return ret;
@@ -446,7 +450,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;

- ret = wl1271_acx_max_tx_retry(wl);
+ ret = wl1271_acx_ap_max_tx_retry(wl);
if (ret < 0)
return ret;

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index dad81f6..8a7a8c5 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -192,7 +192,8 @@ static struct conf_drv_settings default_conf = {
.long_retry_limit = 10,
.aflags = 0,
},
- .ap_max_tx_retries = 100,
+ .max_tx_retries = 100,
+ .ap_aging_period = 300,
.tid_conf_count = 4,
.tid_conf = {
[CONF_TX_AC_BE] = {
@@ -2996,6 +2997,12 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
}

+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
+{
+ int id = hlid - WL1271_AP_STA_HLID_START;
+ return test_bit(id, wl->ap_hlid_map);
+}
+
static int wl1271_op_sta_add(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
@@ -3578,7 +3585,6 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_HAS_RATE_CONTROL |
IEEE80211_HW_CONNECTION_MONITOR |
IEEE80211_HW_SUPPORTS_CQM_RSSI |
- IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_AP_LINK_PS;

wl->hw->wiphy->cipher_suites = cipher_suites;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index b760143..f3de962 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -172,7 +172,6 @@ extern u32 wl12xx_debug_level;
#define WL1271_PS_STA_MAX_BLOCKS (2 * 9)

#define WL1271_AP_BSS_INDEX 0
-#define WL1271_AP_DEF_INACTIV_SEC 300
#define WL1271_AP_DEF_BEACON_EXP 20

#define ACX_TX_DESCRIPTORS 32
--
1.7.1



2011-04-28 08:19:05

by Arik Nemtsov

[permalink] [raw]
Subject: Re: [PATCH v2] wl12xx: support FW TX inactivity triggers

On Tue, Apr 26, 2011 at 23:21, Arik Nemtsov <[email protected]> wrote:
> In AP mode we register for the MAX_TX_RETRY and INACTIVE_STA events.
> Both are reported to the upper layers as a TX failure in the offending
> stations.
>
> In STA mode we register only for the MAX_TX_RETRY event. A TX failure is
> interpreted as a loss of connection.
>
> Support for IEEE80211_HW_REPORTS_TX_ACK_STATUS has been removed to avoid
> the inherent race condition of a mac80211 TX failure counter in addition
> to the FW counter.
>
> This patch depends on "mac80211: allow low level driver to report packet
> loss"
>

Luca please don't take this one for now. It appears the FW sometimes
misfires the event in STA mode.
We'll need some more debugging.

Arik

2011-04-29 21:09:55

by Arik Nemtsov

[permalink] [raw]
Subject: Re: [PATCH v2] wl12xx: support FW TX inactivity triggers

Hey John,

Looking at the latest git, it seems you've picked up this patch
(commit 47684808fd89d6809c0886e06f8ac324252499d8).
This is unfortunate, since there's currently a FW bug that will cause
many disconnections in STA mode with this patch.

How would we go about reverting this?

Thanks,
Arik

On Thu, Apr 28, 2011 at 11:18, Arik Nemtsov <[email protected]> wrote:
> On Tue, Apr 26, 2011 at 23:21, Arik Nemtsov <[email protected]> wrote:
>> In AP mode we register for the MAX_TX_RETRY and INACTIVE_STA events.
>> Both are reported to the upper layers as a TX failure in the offending
>> stations.
>>
>> In STA mode we register only for the MAX_TX_RETRY event. A TX failure is
>> interpreted as a loss of connection.
>>
>> Support for IEEE80211_HW_REPORTS_TX_ACK_STATUS has been removed to avoid
>> the inherent race condition of a mac80211 TX failure counter in addition
>> to the FW counter.
>>
>> This patch depends on "mac80211: allow low level driver to report packet
>> loss"
>>
>
> Luca please don't take this one for now. It appears the FW sometimes
> misfires the event in STA mode.
> We'll need some more debugging.
>
> Arik
>

2011-05-02 14:51:25

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH v2] wl12xx: support FW TX inactivity triggers

On Mon, 2011-05-02 at 10:37 -0400, John W. Linville wrote:
> On Mon, May 02, 2011 at 12:50:55PM +0300, Luciano Coelho wrote:
> > Hi John and Arik,
> >
> > On Sat, 2011-04-30 at 00:09 +0300, Arik Nemtsov wrote:
> > > Hey John,
> > >
> > > Looking at the latest git, it seems you've picked up this patch
> > > (commit 47684808fd89d6809c0886e06f8ac324252499d8).
> > > This is unfortunate, since there's currently a FW bug that will cause
> > > many disconnections in STA mode with this patch.
> > >
> > > How would we go about reverting this?
> >
> > I have reverted this patch in the wl12xx.git tree. This required a bit
> > of merging and we needed the revert in order to proceed with our tests.
> >
> > So, John, please don't revert this in your tree. My revert will come in
> > my next pull-request which will come in a couple of days, after our
> > internal test round is done.
> >
> > Thanks!
>
> OK, sounds good. FWIW, this is what I meant when I said "Do the
> wl12xx guys still want this?" Granted, that was about the other
> patch in the series, but I kinda presumed that they were related...

Yes, no problem. I agree that sometimes it makes more sense to apply
this kind of patches together (as you did), especially when both patches
were sent as part of the same series.

The mac80211 part is ready and we thought the wl12xx was good too, but
our internal tests have shown that there are still some problems with
this in our driver, which was decreasing connection stability in
general, thus we wanted this to get reverted. So, you didn't to
anything wrong (obviously, it was our own fault. ;)

--
Cheers,
Luca.


2011-05-02 14:45:54

by John W. Linville

[permalink] [raw]
Subject: Re: [PATCH v2] wl12xx: support FW TX inactivity triggers

On Mon, May 02, 2011 at 12:50:55PM +0300, Luciano Coelho wrote:
> Hi John and Arik,
>
> On Sat, 2011-04-30 at 00:09 +0300, Arik Nemtsov wrote:
> > Hey John,
> >
> > Looking at the latest git, it seems you've picked up this patch
> > (commit 47684808fd89d6809c0886e06f8ac324252499d8).
> > This is unfortunate, since there's currently a FW bug that will cause
> > many disconnections in STA mode with this patch.
> >
> > How would we go about reverting this?
>
> I have reverted this patch in the wl12xx.git tree. This required a bit
> of merging and we needed the revert in order to proceed with our tests.
>
> So, John, please don't revert this in your tree. My revert will come in
> my next pull-request which will come in a couple of days, after our
> internal test round is done.
>
> Thanks!

OK, sounds good. FWIW, this is what I meant when I said "Do the
wl12xx guys still want this?" Granted, that was about the other
patch in the series, but I kinda presumed that they were related...

John
--
John W. Linville Someday the world will need a hero, and you
[email protected] might be all we have. Be ready.

2011-05-02 09:51:03

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH v2] wl12xx: support FW TX inactivity triggers

Hi John and Arik,

On Sat, 2011-04-30 at 00:09 +0300, Arik Nemtsov wrote:
> Hey John,
>
> Looking at the latest git, it seems you've picked up this patch
> (commit 47684808fd89d6809c0886e06f8ac324252499d8).
> This is unfortunate, since there's currently a FW bug that will cause
> many disconnections in STA mode with this patch.
>
> How would we go about reverting this?

I have reverted this patch in the wl12xx.git tree. This required a bit
of merging and we needed the revert in order to proceed with our tests.

So, John, please don't revert this in your tree. My revert will come in
my next pull-request which will come in a couple of days, after our
internal test round is done.

Thanks!

--
Cheers,
Luca.


2011-05-02 09:53:01

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH] Revert "wl12xx: support FW TX inactivity triggers"

This reverts commit 47684808fd89d6809c0886e06f8ac324252499d8.

Conflicts:

drivers/net/wireless/wl12xx/conf.h
drivers/net/wireless/wl12xx/main.c
---
drivers/net/wireless/wl12xx/acx.c | 34 +++---------------------
drivers/net/wireless/wl12xx/acx.h | 12 +-------
drivers/net/wireless/wl12xx/boot.c | 6 +---
drivers/net/wireless/wl12xx/cmd.c | 2 +-
drivers/net/wireless/wl12xx/conf.h | 12 +-------
drivers/net/wireless/wl12xx/event.c | 47 ----------------------------------
drivers/net/wireless/wl12xx/event.h | 12 +--------
drivers/net/wireless/wl12xx/init.c | 6 +---
drivers/net/wireless/wl12xx/main.c | 10 +------
drivers/net/wireless/wl12xx/wl12xx.h | 1 +
10 files changed, 17 insertions(+), 125 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index ec0156b..c6ee530 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1577,46 +1577,22 @@ out:
return ret;
}

-int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
+int wl1271_acx_max_tx_retry(struct wl1271 *wl)
{
- struct wl1271_acx_ap_max_tx_retry *acx = NULL;
+ struct wl1271_acx_max_tx_retry *acx = NULL;
int ret;

- wl1271_debug(DEBUG_ACX, "acx ap max tx retry");
+ wl1271_debug(DEBUG_ACX, "acx max tx retry");

acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx)
return -ENOMEM;

- acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries);
+ acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries);

ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));
if (ret < 0) {
- wl1271_warning("acx ap max tx retry failed: %d", ret);
- goto out;
- }
-
-out:
- kfree(acx);
- return ret;
-}
-
-int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl)
-{
- struct wl1271_acx_sta_max_tx_retry *acx = NULL;
- int ret;
-
- wl1271_debug(DEBUG_ACX, "acx sta max tx retry");
-
- acx = kzalloc(sizeof(*acx), GFP_KERNEL);
- if (!acx)
- return -ENOMEM;
-
- acx->max_tx_retry = wl->conf.tx.max_tx_retries;
-
- ret = wl1271_cmd_configure(wl, ACX_CONS_TX_FAILURE, acx, sizeof(*acx));
- if (ret < 0) {
- wl1271_warning("acx sta max tx retry failed: %d", ret);
+ wl1271_warning("acx max tx retry failed: %d", ret);
goto out;
}

diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 75338f9..9a895e3 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -1153,7 +1153,7 @@ struct wl1271_acx_fw_tsf_information {
u8 padding[3];
} __packed;

-struct wl1271_acx_ap_max_tx_retry {
+struct wl1271_acx_max_tx_retry {
struct acx_header header;

/*
@@ -1164,13 +1164,6 @@ struct wl1271_acx_ap_max_tx_retry {
u8 padding_1[2];
} __packed;

-struct wl1271_acx_sta_max_tx_retry {
- struct acx_header header;
-
- u8 max_tx_retry;
- u8 padding_1[3];
-} __packed;
-
struct wl1271_acx_config_ps {
struct acx_header header;

@@ -1391,8 +1384,7 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
bool enable);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
-int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl);
-int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl);
+int wl1271_acx_max_tx_retry(struct wl1271 *wl);
int wl1271_acx_config_ps(struct wl1271 *wl);
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable);
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index d263ebb..2b0cf85 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -478,12 +478,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
DISCONNECT_EVENT_COMPLETE_ID |
RSSI_SNR_TRIGGER_0_EVENT_ID |
PSPOLL_DELIVERY_FAILURE_EVENT_ID |
- SOFT_GEMINI_SENSE_EVENT_ID |
- MAX_TX_RETRY_EVENT_ID;
+ SOFT_GEMINI_SENSE_EVENT_ID;

if (wl->bss_type == BSS_TYPE_AP_BSS)
- wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID |
- INACTIVE_STA_EVENT_ID;
+ wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
else
wl->event_mask |= DUMMY_PACKET_EVENT_ID;

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index d8596ae..2116a37 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -1080,7 +1080,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl)

memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);

- cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
+ cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC);
cmd->bss_index = WL1271_AP_BSS_INDEX;
cmd->global_hlid = WL1271_AP_GLOBAL_HLID;
cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID;
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index c0045f0..1f94736 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -711,18 +711,10 @@ struct conf_tx_settings {
struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT];

/*
- * Allow this number of TX retries to a connected station/AP before an
+ * AP-mode - allow this number of TX retries to a station before an
* event is triggered from FW.
- * In AP-mode the hlids of unreachable stations are given in the
- * "sta_tx_retry_exceeded" member in the event mailbox.
*/
- u8 max_tx_retries;
-
- /*
- * AP-mode - after this number of seconds a connected station is
- * considered inactive.
- */
- u16 ap_aging_period;
+ u16 ap_max_tx_retries;

/*
* Configuration for TID parameters.
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index d7be3ae..ae69330 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -174,8 +174,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
u32 vector;
bool beacon_loss = false;
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
- bool disconnect_sta = false;
- unsigned long sta_bitmap = 0;

wl1271_event_mbox_dump(mbox);

@@ -237,54 +235,9 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_tx_dummy_packet(wl);
}

- /*
- * "TX retries exceeded" has a different meaning according to mode.
- * In AP mode the offending station is disconnected. In STA mode we
- * report connection loss.
- */
- if (vector & MAX_TX_RETRY_EVENT_ID) {
- wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID");
- if (is_ap) {
- sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded);
- disconnect_sta = true;
- } else {
- beacon_loss = true;
- }
- }
-
- if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) {
- wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
- sta_bitmap |= le16_to_cpu(mbox->sta_aging_status);
- disconnect_sta = true;
- }
-
if (wl->vif && beacon_loss)
ieee80211_connection_loss(wl->vif);

- if (is_ap && disconnect_sta) {
- u32 num_packets = wl->conf.tx.max_tx_retries;
- struct ieee80211_sta *sta;
- const u8 *addr;
- int h;
-
- for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS);
- h < AP_MAX_LINKS;
- h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) {
- if (!wl1271_is_active_sta(wl, h))
- continue;
-
- addr = wl->links[h].addr;
-
- rcu_read_lock();
- sta = ieee80211_find_sta(wl->vif, addr);
- if (sta) {
- wl1271_debug(DEBUG_EVENT, "remove sta %d", h);
- ieee80211_report_low_ack(sta, num_packets);
- }
- rcu_read_unlock();
- }
- }
-
return 0;
}

diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index 7ae5a08..b6cf06e 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -58,16 +58,13 @@ enum {
CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
BSS_LOSE_EVENT_ID = BIT(18),
REGAINED_BSS_EVENT_ID = BIT(19),
- MAX_TX_RETRY_EVENT_ID = BIT(20),
+ ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20),
/* STA: dummy paket for dynamic mem blocks */
DUMMY_PACKET_EVENT_ID = BIT(21),
/* AP: STA remove complete */
STA_REMOVE_COMPLETE_EVENT_ID = BIT(21),
SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
- /* STA: SG prediction */
SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
- /* AP: Inactive STA */
- INACTIVE_STA_EVENT_ID = BIT(23),
SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25),
DBG_EVENT_ID = BIT(26),
@@ -122,11 +119,7 @@ struct event_mailbox {

/* AP FW only */
u8 hlid_removed;
-
- /* a bitmap of hlids for stations that have been inactive too long */
__le16 sta_aging_status;
-
- /* a bitmap of hlids for stations which didn't respond to TX */
__le16 sta_tx_retry_exceeded;

u8 reserved_5[24];
@@ -137,7 +130,4 @@ void wl1271_event_mbox_config(struct wl1271 *wl);
int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
void wl1271_pspoll_work(struct work_struct *work);

-/* Functions from main.c */
-bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid);
-
#endif
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index b1242a6..a8f4f15 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -378,10 +378,6 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;

- ret = wl1271_acx_sta_max_tx_retry(wl);
- if (ret < 0)
- return ret;
-
ret = wl1271_acx_sta_mem_cfg(wl);
if (ret < 0)
return ret;
@@ -432,7 +428,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;

- ret = wl1271_acx_ap_max_tx_retry(wl);
+ ret = wl1271_acx_max_tx_retry(wl);
if (ret < 0)
return ret;

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 6dd42c9..6dab6f0 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -209,8 +209,7 @@ static struct conf_drv_settings default_conf = {
.tx_op_limit = 1504,
},
},
- .max_tx_retries = 100,
- .ap_aging_period = 300,
+ .ap_max_tx_retries = 100,
.tid_conf_count = 4,
.tid_conf = {
[CONF_TX_AC_BE] = {
@@ -3021,12 +3020,6 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
}

-bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
-{
- int id = hlid - WL1271_AP_STA_HLID_START;
- return test_bit(id, wl->ap_hlid_map);
-}
-
static int wl1271_op_sta_add(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
@@ -3632,6 +3625,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_HAS_RATE_CONTROL |
IEEE80211_HW_CONNECTION_MONITOR |
IEEE80211_HW_SUPPORTS_CQM_RSSI |
+ IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_AP_LINK_PS;

wl->hw->wiphy->cipher_suites = cipher_suites;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index f3de962..b760143 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -172,6 +172,7 @@ extern u32 wl12xx_debug_level;
#define WL1271_PS_STA_MAX_BLOCKS (2 * 9)

#define WL1271_AP_BSS_INDEX 0
+#define WL1271_AP_DEF_INACTIV_SEC 300
#define WL1271_AP_DEF_BEACON_EXP 20

#define ACX_TX_DESCRIPTORS 32
--
1.7.1