diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-02-22 14:44:50 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-02-22 14:44:50 -0500 |
commit | 8715d941b2fa8591474e7d0dad66589fce1892d2 (patch) | |
tree | ec228ec158bb5b4424f898d336279c29de4cf81f /drivers/net/wireless/wl12xx/event.c | |
parent | ca994a36f585432458ead9133fcfe05440edbb7b (diff) | |
parent | 51c4ed95a857ded6017537fd53fa00db64908954 (diff) |
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
Diffstat (limited to 'drivers/net/wireless/wl12xx/event.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/event.c | 154 |
1 files changed, 2 insertions, 152 deletions
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index d3280df68f5d..c953717f38eb 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c | |||
@@ -30,133 +30,6 @@ | |||
30 | #include "scan.h" | 30 | #include "scan.h" |
31 | #include "wl12xx_80211.h" | 31 | #include "wl12xx_80211.h" |
32 | 32 | ||
33 | void wl1271_pspoll_work(struct work_struct *work) | ||
34 | { | ||
35 | struct ieee80211_vif *vif; | ||
36 | struct wl12xx_vif *wlvif; | ||
37 | struct delayed_work *dwork; | ||
38 | struct wl1271 *wl; | ||
39 | int ret; | ||
40 | |||
41 | dwork = container_of(work, struct delayed_work, work); | ||
42 | wlvif = container_of(dwork, struct wl12xx_vif, pspoll_work); | ||
43 | vif = container_of((void *)wlvif, struct ieee80211_vif, drv_priv); | ||
44 | wl = wlvif->wl; | ||
45 | |||
46 | wl1271_debug(DEBUG_EVENT, "pspoll work"); | ||
47 | |||
48 | mutex_lock(&wl->mutex); | ||
49 | |||
50 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
51 | goto out; | ||
52 | |||
53 | if (!test_and_clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags)) | ||
54 | goto out; | ||
55 | |||
56 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
57 | goto out; | ||
58 | |||
59 | /* | ||
60 | * if we end up here, then we were in powersave when the pspoll | ||
61 | * delivery failure occurred, and no-one changed state since, so | ||
62 | * we should go back to powersave. | ||
63 | */ | ||
64 | ret = wl1271_ps_elp_wakeup(wl); | ||
65 | if (ret < 0) | ||
66 | goto out; | ||
67 | |||
68 | wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, | ||
69 | wlvif->basic_rate, true); | ||
70 | |||
71 | wl1271_ps_elp_sleep(wl); | ||
72 | out: | ||
73 | mutex_unlock(&wl->mutex); | ||
74 | }; | ||
75 | |||
76 | static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl, | ||
77 | struct wl12xx_vif *wlvif) | ||
78 | { | ||
79 | int delay = wl->conf.conn.ps_poll_recovery_period; | ||
80 | int ret; | ||
81 | |||
82 | wlvif->ps_poll_failures++; | ||
83 | if (wlvif->ps_poll_failures == 1) | ||
84 | wl1271_info("AP with dysfunctional ps-poll, " | ||
85 | "trying to work around it."); | ||
86 | |||
87 | /* force active mode receive data from the AP */ | ||
88 | if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { | ||
89 | ret = wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, | ||
90 | wlvif->basic_rate, true); | ||
91 | if (ret < 0) | ||
92 | return; | ||
93 | set_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags); | ||
94 | ieee80211_queue_delayed_work(wl->hw, &wlvif->pspoll_work, | ||
95 | msecs_to_jiffies(delay)); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * If already in active mode, lets we should be getting data from | ||
100 | * the AP right away. If we enter PSM too fast after this, and data | ||
101 | * remains on the AP, we will get another event like this, and we'll | ||
102 | * go into active once more. | ||
103 | */ | ||
104 | } | ||
105 | |||
106 | static int wl1271_event_ps_report(struct wl1271 *wl, | ||
107 | struct wl12xx_vif *wlvif, | ||
108 | struct event_mailbox *mbox, | ||
109 | bool *beacon_loss) | ||
110 | { | ||
111 | int ret = 0; | ||
112 | u32 total_retries = wl->conf.conn.psm_entry_retries; | ||
113 | |||
114 | wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); | ||
115 | |||
116 | switch (mbox->ps_status) { | ||
117 | case EVENT_ENTER_POWER_SAVE_FAIL: | ||
118 | wl1271_debug(DEBUG_PSM, "PSM entry failed"); | ||
119 | |||
120 | if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { | ||
121 | /* remain in active mode */ | ||
122 | wlvif->psm_entry_retry = 0; | ||
123 | break; | ||
124 | } | ||
125 | |||
126 | if (wlvif->psm_entry_retry < total_retries) { | ||
127 | wlvif->psm_entry_retry++; | ||
128 | ret = wl1271_ps_set_mode(wl, wlvif, | ||
129 | STATION_POWER_SAVE_MODE, | ||
130 | wlvif->basic_rate, true); | ||
131 | } else { | ||
132 | wl1271_info("No ack to nullfunc from AP."); | ||
133 | wlvif->psm_entry_retry = 0; | ||
134 | *beacon_loss = true; | ||
135 | } | ||
136 | break; | ||
137 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | ||
138 | wlvif->psm_entry_retry = 0; | ||
139 | |||
140 | /* | ||
141 | * BET has only a minor effect in 5GHz and masks | ||
142 | * channel switch IEs, so we only enable BET on 2.4GHz | ||
143 | */ | ||
144 | if (wlvif->band == IEEE80211_BAND_2GHZ) | ||
145 | /* enable beacon early termination */ | ||
146 | ret = wl1271_acx_bet_enable(wl, wlvif, true); | ||
147 | |||
148 | if (wlvif->ps_compl) { | ||
149 | complete(wlvif->ps_compl); | ||
150 | wlvif->ps_compl = NULL; | ||
151 | } | ||
152 | break; | ||
153 | default: | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static void wl1271_event_rssi_trigger(struct wl1271 *wl, | 33 | static void wl1271_event_rssi_trigger(struct wl1271 *wl, |
161 | struct wl12xx_vif *wlvif, | 34 | struct wl12xx_vif *wlvif, |
162 | struct event_mailbox *mbox) | 35 | struct event_mailbox *mbox) |
@@ -205,21 +78,13 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
205 | static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, | 78 | static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, |
206 | u8 enable) | 79 | u8 enable) |
207 | { | 80 | { |
208 | struct ieee80211_vif *vif; | ||
209 | struct wl12xx_vif *wlvif; | 81 | struct wl12xx_vif *wlvif; |
210 | 82 | ||
211 | if (enable) { | 83 | if (enable) { |
212 | /* disable dynamic PS when requested by the firmware */ | ||
213 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
214 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
215 | ieee80211_disable_dyn_ps(vif); | ||
216 | } | ||
217 | set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); | 84 | set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); |
218 | } else { | 85 | } else { |
219 | clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); | 86 | clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); |
220 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 87 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
221 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
222 | ieee80211_enable_dyn_ps(vif); | ||
223 | wl1271_recalc_rx_streaming(wl, wlvif); | 88 | wl1271_recalc_rx_streaming(wl, wlvif); |
224 | } | 89 | } |
225 | } | 90 | } |
@@ -237,7 +102,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
237 | { | 102 | { |
238 | struct ieee80211_vif *vif; | 103 | struct ieee80211_vif *vif; |
239 | struct wl12xx_vif *wlvif; | 104 | struct wl12xx_vif *wlvif; |
240 | int ret; | ||
241 | u32 vector; | 105 | u32 vector; |
242 | bool beacon_loss = false; | 106 | bool beacon_loss = false; |
243 | bool disconnect_sta = false; | 107 | bool disconnect_sta = false; |
@@ -293,21 +157,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
293 | beacon_loss = true; | 157 | beacon_loss = true; |
294 | } | 158 | } |
295 | 159 | ||
296 | if (vector & PS_REPORT_EVENT_ID) { | ||
297 | wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); | ||
298 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
299 | ret = wl1271_event_ps_report(wl, wlvif, | ||
300 | mbox, &beacon_loss); | ||
301 | if (ret < 0) | ||
302 | return ret; | ||
303 | } | ||
304 | } | ||
305 | |||
306 | if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) | ||
307 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
308 | wl1271_event_pspoll_delivery_fail(wl, wlvif); | ||
309 | } | ||
310 | |||
311 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { | 160 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
312 | /* TODO: check actual multi-role support */ | 161 | /* TODO: check actual multi-role support */ |
313 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); | 162 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); |
@@ -344,7 +193,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
344 | 193 | ||
345 | /* TODO: configure only the relevant vif */ | 194 | /* TODO: configure only the relevant vif */ |
346 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 195 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
347 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | ||
348 | bool success; | 196 | bool success; |
349 | 197 | ||
350 | if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, | 198 | if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, |
@@ -352,6 +200,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
352 | continue; | 200 | continue; |
353 | 201 | ||
354 | success = mbox->channel_switch_status ? false : true; | 202 | success = mbox->channel_switch_status ? false : true; |
203 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
204 | |||
355 | ieee80211_chswitch_done(vif, success); | 205 | ieee80211_chswitch_done(vif, success); |
356 | } | 206 | } |
357 | } | 207 | } |