Commit 19ad0715 authored by Juuso Oikarinen's avatar Juuso Oikarinen Committed by John W. Linville

wl1271: Add retry implementation for PSM entries

PSM entries can fail (transmitting the corresponding null-func may not
be heard by the AP.) Previously, this scenario was not detected, and
out-of-sync between STA and AP could occur.

Add retry implementation for the entries to recover from the situation.
Signed-off-by: default avatarJuuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: default avatarLuciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: default avatarLuciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 3b775b4b
......@@ -417,6 +417,9 @@ struct wl1271 {
/* PSM mode requested */
bool psm_requested;
/* retry counter for PSM entries */
u8 psm_entry_retry;
/* in dBm */
int power_level;
......
......@@ -407,7 +407,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
/* unmask required mbox events */
wl->event_mask = BSS_LOSE_EVENT_ID |
SCAN_COMPLETE_EVENT_ID;
SCAN_COMPLETE_EVENT_ID |
PS_REPORT_EVENT_ID;
ret = wl1271_event_unmask(wl);
if (ret < 0) {
......
......@@ -712,6 +712,14 @@ struct conf_conn_settings {
* Range 0 - 255
*/
u8 bet_max_consecutive;
/*
* Specifies the maximum number of times to try PSM entry if it fails
* (if sending the appropriate null-func message fails.)
*
* Range 0 - 255
*/
u8 psm_entry_retries;
};
#define CONF_SR_ERR_TBL_MAX_VALUES 14
......
......@@ -68,6 +68,40 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
return 0;
}
static int wl1271_event_ps_report(struct wl1271 *wl,
struct event_mailbox *mbox,
bool *beacon_loss)
{
int ret = 0;
wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status);
switch (mbox->ps_status) {
case EVENT_ENTER_POWER_SAVE_FAIL:
if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) {
wl->psm_entry_retry++;
wl1271_error("PSM entry failed, retrying %d\n",
wl->psm_entry_retry);
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
} else {
wl->psm_entry_retry = 0;
*beacon_loss = true;
}
break;
case EVENT_ENTER_POWER_SAVE_SUCCESS:
wl->psm_entry_retry = 0;
break;
case EVENT_EXIT_POWER_SAVE_FAIL:
wl1271_info("PSM exit failed");
break;
case EVENT_EXIT_POWER_SAVE_SUCCESS:
default:
break;
}
return ret;
}
static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
{
wl1271_debug(DEBUG_EVENT, "MBOX DUMP:");
......@@ -79,6 +113,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
{
int ret;
u32 vector;
bool beacon_loss = false;
wl1271_event_mbox_dump(mbox);
......@@ -101,7 +136,25 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
/* indicate to the stack, that beacons have been lost */
beacon_loss = true;
}
if (vector & PS_REPORT_EVENT_ID) {
wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
ret = wl1271_event_ps_report(wl, mbox, &beacon_loss);
if (ret < 0)
return ret;
}
if (beacon_loss) {
/* Obviously, it's dangerous to release the mutex while
we are holding many of the variables in the wl struct.
That's why it's done last in the function, and care must
be taken that nothing more is done after this function
returns. */
mutex_unlock(&wl->mutex);
ieee80211_beacon_loss(wl->vif);
mutex_lock(&wl->mutex);
}
return 0;
......
......@@ -63,6 +63,13 @@ enum {
EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff,
};
enum {
EVENT_ENTER_POWER_SAVE_FAIL = 0,
EVENT_ENTER_POWER_SAVE_SUCCESS,
EVENT_EXIT_POWER_SAVE_FAIL,
EVENT_EXIT_POWER_SAVE_SUCCESS,
};
struct event_debug_report {
u8 debug_event_id;
u8 num_params;
......
......@@ -222,7 +222,8 @@ static struct conf_drv_settings default_conf = {
.snr_pkt_avg_weight = 10
},
.bet_enable = CONF_BET_MODE_ENABLE,
.bet_max_consecutive = 100
.bet_max_consecutive = 100,
.psm_entry_retries = 3
},
.init = {
.sr_err_tbl = {
......@@ -973,6 +974,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl->rx_counter = 0;
wl->elp = false;
wl->psm = 0;
wl->psm_entry_retry = 0;
wl->tx_queue_stopped = false;
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
wl->tx_blocks_available = 0;
......@@ -1822,6 +1824,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
wl->elp = false;
wl->psm = 0;
wl->psm_requested = false;
wl->psm_entry_retry = 0;
wl->tx_queue_stopped = false;
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment