aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2011-10-10 04:12:57 -0400
committerLuciano Coelho <coelho@ti.com>2011-10-11 08:04:23 -0400
commit4b730b6a814fe52425d90ff3db3d8deefb22fb24 (patch)
tree32636d14ecfa0170f3299032692dc624394fee63 /drivers/net/wireless
parenta4e4130dcea01f3e0dfcbfeaf0d815b971e6e515 (diff)
wl12xx: make event handling support multirole
Some events don't indicate the role they are intended for. In these cases, iterate through all the relevant vifs, and pass the event to each one of them. This is only a workaround. future fw releases should indicate the relevant role_id for such events. Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/wl12xx/event.c121
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h10
2 files changed, 91 insertions, 40 deletions
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 486c8ee0101a..dbc40bb49bcd 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -162,10 +162,10 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
162} 162}
163 163
164static void wl1271_event_rssi_trigger(struct wl1271 *wl, 164static void wl1271_event_rssi_trigger(struct wl1271 *wl,
165 struct ieee80211_vif *vif, 165 struct wl12xx_vif *wlvif,
166 struct event_mailbox *mbox) 166 struct event_mailbox *mbox)
167{ 167{
168 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); 168 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
169 enum nl80211_cqm_rssi_threshold_event event; 169 enum nl80211_cqm_rssi_threshold_event event;
170 s8 metric = mbox->rssi_snr_trigger_metric[0]; 170 s8 metric = mbox->rssi_snr_trigger_metric[0];
171 171
@@ -183,11 +183,13 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl,
183 183
184static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) 184static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
185{ 185{
186 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
187
186 if (wlvif->bss_type != BSS_TYPE_AP_BSS) { 188 if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
187 if (!wlvif->sta.ba_rx_bitmap) 189 if (!wlvif->sta.ba_rx_bitmap)
188 return; 190 return;
189 ieee80211_stop_rx_ba_session(wl->vif, wlvif->sta.ba_rx_bitmap, 191 ieee80211_stop_rx_ba_session(vif, wlvif->sta.ba_rx_bitmap,
190 wl->vif->bss_conf.bssid); 192 vif->bss_conf.bssid);
191 } else { 193 } else {
192 u8 hlid; 194 u8 hlid;
193 struct wl1271_link *lnk; 195 struct wl1271_link *lnk;
@@ -197,7 +199,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
197 if (!lnk->ba_bitmap) 199 if (!lnk->ba_bitmap)
198 continue; 200 continue;
199 201
200 ieee80211_stop_rx_ba_session(wl->vif, 202 ieee80211_stop_rx_ba_session(vif,
201 lnk->ba_bitmap, 203 lnk->ba_bitmap,
202 lnk->addr); 204 lnk->addr);
203 } 205 }
@@ -207,12 +209,21 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
207static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, 209static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
208 u8 enable) 210 u8 enable)
209{ 211{
212 struct ieee80211_vif *vif;
213 struct wl12xx_vif *wlvif;
214
210 if (enable) { 215 if (enable) {
211 /* disable dynamic PS when requested by the firmware */ 216 /* disable dynamic PS when requested by the firmware */
212 ieee80211_disable_dyn_ps(wl->vif); 217 wl12xx_for_each_wlvif_sta(wl, wlvif) {
218 vif = wl12xx_wlvif_to_vif(wlvif);
219 ieee80211_disable_dyn_ps(vif);
220 }
213 set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); 221 set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
214 } else { 222 } else {
215 ieee80211_enable_dyn_ps(wl->vif); 223 wl12xx_for_each_wlvif_sta(wl, wlvif) {
224 vif = wl12xx_wlvif_to_vif(wlvif);
225 ieee80211_enable_dyn_ps(vif);
226 }
216 clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); 227 clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
217 wl1271_recalc_rx_streaming(wl); 228 wl1271_recalc_rx_streaming(wl);
218 } 229 }
@@ -228,12 +239,11 @@ static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
228 239
229static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) 240static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
230{ 241{
231 struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ 242 struct ieee80211_vif *vif;
232 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); 243 struct wl12xx_vif *wlvif;
233 int ret; 244 int ret;
234 u32 vector; 245 u32 vector;
235 bool beacon_loss = false; 246 bool beacon_loss = false;
236 bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
237 bool disconnect_sta = false; 247 bool disconnect_sta = false;
238 unsigned long sta_bitmap = 0; 248 unsigned long sta_bitmap = 0;
239 249
@@ -266,8 +276,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
266 } 276 }
267 } 277 }
268 278
269 if (vector & SOFT_GEMINI_SENSE_EVENT_ID && 279 if (vector & SOFT_GEMINI_SENSE_EVENT_ID)
270 wlvif->bss_type == BSS_TYPE_STA_BSS)
271 wl12xx_event_soft_gemini_sense(wl, 280 wl12xx_event_soft_gemini_sense(wl,
272 mbox->soft_gemini_sense_info); 281 mbox->soft_gemini_sense_info);
273 282
@@ -280,40 +289,54 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
280 * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. 289 * BSS_LOSE_EVENT, beacon loss has to be reported to the stack.
281 * 290 *
282 */ 291 */
283 if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) { 292 if (vector & BSS_LOSE_EVENT_ID) {
293 /* TODO: check for multi-role */
284 wl1271_info("Beacon loss detected."); 294 wl1271_info("Beacon loss detected.");
285 295
286 /* indicate to the stack, that beacons have been lost */ 296 /* indicate to the stack, that beacons have been lost */
287 beacon_loss = true; 297 beacon_loss = true;
288 } 298 }
289 299
290 if ((vector & PS_REPORT_EVENT_ID) && !is_ap) { 300 if (vector & PS_REPORT_EVENT_ID) {
291 wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); 301 wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
292 ret = wl1271_event_ps_report(wl, wlvif, mbox, &beacon_loss); 302 wl12xx_for_each_wlvif_sta(wl, wlvif) {
293 if (ret < 0) 303 ret = wl1271_event_ps_report(wl, wlvif,
294 return ret; 304 mbox, &beacon_loss);
305 if (ret < 0)
306 return ret;
307 }
295 } 308 }
296 309
297 if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap) 310 if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID)
298 wl1271_event_pspoll_delivery_fail(wl, wlvif); 311 wl12xx_for_each_wlvif_sta(wl, wlvif) {
312 wl1271_event_pspoll_delivery_fail(wl, wlvif);
313 }
299 314
300 if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { 315 if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) {
316 /* TODO: check actual multi-role support */
301 wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); 317 wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT");
302 if (wl->vif) 318 wl12xx_for_each_wlvif_sta(wl, wlvif) {
303 wl1271_event_rssi_trigger(wl, vif, mbox); 319 wl1271_event_rssi_trigger(wl, wlvif, mbox);
320 }
304 } 321 }
305 322
306 if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) { 323 if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) {
324 u8 role_id = mbox->role_id;
307 wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " 325 wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
308 "ba_allowed = 0x%x", mbox->rx_ba_allowed); 326 "ba_allowed = 0x%x, role_id=%d",
327 mbox->rx_ba_allowed, role_id);
309 328
310 wlvif->ba_allowed = !!mbox->rx_ba_allowed; 329 wl12xx_for_each_wlvif(wl, wlvif) {
330 if (role_id != 0xff && role_id != wlvif->role_id)
331 continue;
311 332
312 if (wl->vif && !wlvif->ba_allowed) 333 wlvif->ba_allowed = !!mbox->rx_ba_allowed;
313 wl1271_stop_ba_event(wl, wlvif); 334 if (!wlvif->ba_allowed)
335 wl1271_stop_ba_event(wl, wlvif);
336 }
314 } 337 }
315 338
316 if ((vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) && !is_ap) { 339 if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) {
317 wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. " 340 wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. "
318 "status = 0x%x", 341 "status = 0x%x",
319 mbox->channel_switch_status); 342 mbox->channel_switch_status);
@@ -322,48 +345,63 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
322 * 1) channel switch complete with status=0 345 * 1) channel switch complete with status=0
323 * 2) channel switch failed status=1 346 * 2) channel switch failed status=1
324 */ 347 */
325 if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags) && 348 if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) {
326 (wl->vif)) 349 /* TODO: configure only the relevant vif */
327 ieee80211_chswitch_done(wl->vif, 350 wl12xx_for_each_wlvif_sta(wl, wlvif) {
328 mbox->channel_switch_status ? false : true); 351 struct ieee80211_vif *vif =
352 wl12xx_wlvif_to_vif(wlvif);
353 bool success = mbox->channel_switch_status ?
354 false : true;
355
356 ieee80211_chswitch_done(vif, success);
357 }
358 }
329 } 359 }
330 360
331 if ((vector & DUMMY_PACKET_EVENT_ID)) { 361 if ((vector & DUMMY_PACKET_EVENT_ID)) {
332 wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); 362 wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
333 if (wl->vif) 363 wl1271_tx_dummy_packet(wl);
334 wl1271_tx_dummy_packet(wl);
335 } 364 }
336 365
337 /* 366 /*
338 * "TX retries exceeded" has a different meaning according to mode. 367 * "TX retries exceeded" has a different meaning according to mode.
339 * In AP mode the offending station is disconnected. 368 * In AP mode the offending station is disconnected.
340 */ 369 */
341 if ((vector & MAX_TX_RETRY_EVENT_ID) && is_ap) { 370 if (vector & MAX_TX_RETRY_EVENT_ID) {
342 wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); 371 wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID");
343 sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); 372 sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded);
344 disconnect_sta = true; 373 disconnect_sta = true;
345 } 374 }
346 375
347 if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { 376 if (vector & INACTIVE_STA_EVENT_ID) {
348 wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); 377 wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
349 sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); 378 sta_bitmap |= le16_to_cpu(mbox->sta_aging_status);
350 disconnect_sta = true; 379 disconnect_sta = true;
351 } 380 }
352 381
353 if (is_ap && disconnect_sta) { 382 if (disconnect_sta) {
354 u32 num_packets = wl->conf.tx.max_tx_retries; 383 u32 num_packets = wl->conf.tx.max_tx_retries;
355 struct ieee80211_sta *sta; 384 struct ieee80211_sta *sta;
356 const u8 *addr; 385 const u8 *addr;
357 int h; 386 int h;
358 387
359 for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) { 388 for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) {
360 if (!test_bit(h, wlvif->ap.sta_hlid_map)) 389 bool found = false;
390 /* find the ap vif connected to this sta */
391 wl12xx_for_each_wlvif_ap(wl, wlvif) {
392 if (!test_bit(h, wlvif->ap.sta_hlid_map))
393 continue;
394 found = true;
395 break;
396 }
397 if (!found)
361 continue; 398 continue;
362 399
400 vif = wl12xx_wlvif_to_vif(wlvif);
363 addr = wl->links[h].addr; 401 addr = wl->links[h].addr;
364 402
365 rcu_read_lock(); 403 rcu_read_lock();
366 sta = ieee80211_find_sta(wl->vif, addr); 404 sta = ieee80211_find_sta(vif, addr);
367 if (sta) { 405 if (sta) {
368 wl1271_debug(DEBUG_EVENT, "remove sta %d", h); 406 wl1271_debug(DEBUG_EVENT, "remove sta %d", h);
369 ieee80211_report_low_ack(sta, num_packets); 407 ieee80211_report_low_ack(sta, num_packets);
@@ -372,8 +410,11 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
372 } 410 }
373 } 411 }
374 412
375 if (wl->vif && beacon_loss) 413 if (beacon_loss)
376 ieee80211_connection_loss(wl->vif); 414 wl12xx_for_each_wlvif_sta(wl, wlvif) {
415 vif = wl12xx_wlvif_to_vif(wlvif);
416 ieee80211_connection_loss(vif);
417 }
377 418
378 return 0; 419 return 0;
379} 420}
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index fd78f8c1ebcc..de9a2b639403 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -661,6 +661,16 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif)
661#define wl12xx_for_each_wlvif(wl, wlvif) \ 661#define wl12xx_for_each_wlvif(wl, wlvif) \
662 list_for_each_entry(wlvif, &wl->wlvif_list, list) 662 list_for_each_entry(wlvif, &wl->wlvif_list, list)
663 663
664#define wl12xx_for_each_wlvif_bss_type(wl, wlvif, _bss_type) \
665 wl12xx_for_each_wlvif(wl, wlvif) \
666 if (wlvif->bss_type == _bss_type)
667
668#define wl12xx_for_each_wlvif_sta(wl, wlvif) \
669 wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_STA_BSS)
670
671#define wl12xx_for_each_wlvif_ap(wl, wlvif) \
672 wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_AP_BSS)
673
664int wl1271_plt_start(struct wl1271 *wl); 674int wl1271_plt_start(struct wl1271 *wl);
665int wl1271_plt_stop(struct wl1271 *wl); 675int wl1271_plt_stop(struct wl1271 *wl);
666int wl1271_recalc_rx_streaming(struct wl1271 *wl); 676int wl1271_recalc_rx_streaming(struct wl1271 *wl);