diff options
author | Juuso Oikarinen <juuso.oikarinen@nokia.com> | 2009-11-02 20:22:11 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-02 15:43:34 -0500 |
commit | 19ad0715d8d9acc259ef02f83df767df2cf1eafe (patch) | |
tree | 330fff898975a7f3a17106046e939c4049200e68 /drivers/net/wireless/wl12xx/wl1271_event.c | |
parent | 3b775b4b27818130291e7716f3ce1e24664004c9 (diff) |
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: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_event.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_event.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 31d396ba918..e135d894b42 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -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; |