aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/event.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-02-22 14:44:50 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-02-22 14:44:50 -0500
commit8715d941b2fa8591474e7d0dad66589fce1892d2 (patch)
treeec228ec158bb5b4424f898d336279c29de4cf81f /drivers/net/wireless/wl12xx/event.c
parentca994a36f585432458ead9133fcfe05440edbb7b (diff)
parent51c4ed95a857ded6017537fd53fa00db64908954 (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.c154
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
33void 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);
72out:
73 mutex_unlock(&wl->mutex);
74};
75
76static 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
106static 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
160static void wl1271_event_rssi_trigger(struct wl1271 *wl, 33static 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)
205static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, 78static 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 }