diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_event.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_event.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index ca52cdec7a8f..15f6b86f81a2 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -28,6 +28,63 @@ | |||
28 | #include "wl1271_ps.h" | 28 | #include "wl1271_ps.h" |
29 | #include "wl12xx_80211.h" | 29 | #include "wl12xx_80211.h" |
30 | 30 | ||
31 | void wl1271_pspoll_work(struct work_struct *work) | ||
32 | { | ||
33 | struct delayed_work *dwork; | ||
34 | struct wl1271 *wl; | ||
35 | |||
36 | dwork = container_of(work, struct delayed_work, work); | ||
37 | wl = container_of(dwork, struct wl1271, pspoll_work); | ||
38 | |||
39 | wl1271_debug(DEBUG_EVENT, "pspoll work"); | ||
40 | |||
41 | mutex_lock(&wl->mutex); | ||
42 | |||
43 | if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags)) | ||
44 | goto out; | ||
45 | |||
46 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
47 | goto out; | ||
48 | |||
49 | /* | ||
50 | * if we end up here, then we were in powersave when the pspoll | ||
51 | * delivery failure occurred, and no-one changed state since, so | ||
52 | * we should go back to powersave. | ||
53 | */ | ||
54 | wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true); | ||
55 | |||
56 | out: | ||
57 | mutex_unlock(&wl->mutex); | ||
58 | }; | ||
59 | |||
60 | static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) | ||
61 | { | ||
62 | int delay = wl->conf.conn.ps_poll_recovery_period; | ||
63 | int ret; | ||
64 | |||
65 | wl->ps_poll_failures++; | ||
66 | if (wl->ps_poll_failures == 1) | ||
67 | wl1271_info("AP with dysfunctional ps-poll, " | ||
68 | "trying to work around it."); | ||
69 | |||
70 | /* force active mode receive data from the AP */ | ||
71 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
72 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, true); | ||
73 | if (ret < 0) | ||
74 | return; | ||
75 | set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); | ||
76 | ieee80211_queue_delayed_work(wl->hw, &wl->pspoll_work, | ||
77 | msecs_to_jiffies(delay)); | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * If already in active mode, lets we should be getting data from | ||
82 | * the AP right away. If we enter PSM too fast after this, and data | ||
83 | * remains on the AP, we will get another event like this, and we'll | ||
84 | * go into active once more. | ||
85 | */ | ||
86 | } | ||
87 | |||
31 | static int wl1271_event_scan_complete(struct wl1271 *wl, | 88 | static int wl1271_event_scan_complete(struct wl1271 *wl, |
32 | struct event_mailbox *mbox) | 89 | struct event_mailbox *mbox) |
33 | { | 90 | { |
@@ -191,6 +248,9 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
191 | return ret; | 248 | return ret; |
192 | } | 249 | } |
193 | 250 | ||
251 | if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) | ||
252 | wl1271_event_pspoll_delivery_fail(wl); | ||
253 | |||
194 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { | 254 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
195 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); | 255 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); |
196 | if (wl->vif) | 256 | if (wl->vif) |