aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/wl1271_event.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_event.c')
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.c99
1 files changed, 70 insertions, 29 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index ca52cdec7a8f..25ce2cd5e3f3 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -26,36 +26,64 @@
26#include "wl1271_io.h" 26#include "wl1271_io.h"
27#include "wl1271_event.h" 27#include "wl1271_event.h"
28#include "wl1271_ps.h" 28#include "wl1271_ps.h"
29#include "wl1271_scan.h"
29#include "wl12xx_80211.h" 30#include "wl12xx_80211.h"
30 31
31static int wl1271_event_scan_complete(struct wl1271 *wl, 32void wl1271_pspoll_work(struct work_struct *work)
32 struct event_mailbox *mbox)
33{ 33{
34 wl1271_debug(DEBUG_EVENT, "status: 0x%x", 34 struct delayed_work *dwork;
35 mbox->scheduled_scan_status); 35 struct wl1271 *wl;
36 36
37 if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { 37 dwork = container_of(work, struct delayed_work, work);
38 if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { 38 wl = container_of(dwork, struct wl1271, pspoll_work);
39 /* 2.4 GHz band scanned, scan 5 GHz band, pretend 39
40 * to the wl1271_cmd_scan function that we are not 40 wl1271_debug(DEBUG_EVENT, "pspoll work");
41 * scanning as it checks that. 41
42 */ 42 mutex_lock(&wl->mutex);
43 clear_bit(WL1271_FLAG_SCANNING, &wl->flags); 43
44 /* FIXME: ie missing! */ 44 if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags))
45 wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, 45 goto out;
46 wl->scan.req, 46
47 wl->scan.active, 47 if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
48 wl->scan.high_prio, 48 goto out;
49 WL1271_SCAN_BAND_5_GHZ, 49
50 wl->scan.probe_requests); 50 /*
51 } else { 51 * if we end up here, then we were in powersave when the pspoll
52 mutex_unlock(&wl->mutex); 52 * delivery failure occurred, and no-one changed state since, so
53 ieee80211_scan_completed(wl->hw, false); 53 * we should go back to powersave.
54 mutex_lock(&wl->mutex); 54 */
55 clear_bit(WL1271_FLAG_SCANNING, &wl->flags); 55 wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true);
56 } 56
57out:
58 mutex_unlock(&wl->mutex);
59};
60
61static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl)
62{
63 int delay = wl->conf.conn.ps_poll_recovery_period;
64 int ret;
65
66 wl->ps_poll_failures++;
67 if (wl->ps_poll_failures == 1)
68 wl1271_info("AP with dysfunctional ps-poll, "
69 "trying to work around it.");
70
71 /* force active mode receive data from the AP */
72 if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
73 ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, true);
74 if (ret < 0)
75 return;
76 set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags);
77 ieee80211_queue_delayed_work(wl->hw, &wl->pspoll_work,
78 msecs_to_jiffies(delay));
57 } 79 }
58 return 0; 80
81 /*
82 * If already in active mode, lets we should be getting data from
83 * the AP right away. If we enter PSM too fast after this, and data
84 * remains on the AP, we will get another event like this, and we'll
85 * go into active once more.
86 */
59} 87}
60 88
61static int wl1271_event_ps_report(struct wl1271 *wl, 89static int wl1271_event_ps_report(struct wl1271 *wl,
@@ -163,9 +191,19 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
163 wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); 191 wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector);
164 192
165 if (vector & SCAN_COMPLETE_EVENT_ID) { 193 if (vector & SCAN_COMPLETE_EVENT_ID) {
166 ret = wl1271_event_scan_complete(wl, mbox); 194 wl1271_debug(DEBUG_EVENT, "status: 0x%x",
167 if (ret < 0) 195 mbox->scheduled_scan_status);
168 return ret; 196
197 wl1271_scan_stm(wl);
198 }
199
200 /* disable dynamic PS when requested by the firmware */
201 if (vector & SOFT_GEMINI_SENSE_EVENT_ID &&
202 wl->bss_type == BSS_TYPE_STA_BSS) {
203 if (mbox->soft_gemini_sense_info)
204 ieee80211_disable_dyn_ps(wl->vif);
205 else
206 ieee80211_enable_dyn_ps(wl->vif);
169 } 207 }
170 208
171 /* 209 /*
@@ -191,6 +229,9 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
191 return ret; 229 return ret;
192 } 230 }
193 231
232 if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID)
233 wl1271_event_pspoll_delivery_fail(wl);
234
194 if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { 235 if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) {
195 wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); 236 wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT");
196 if (wl->vif) 237 if (wl->vif)