static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, u8 enable) { if (enable) { /* disable dynamic PS when the firmware senses BT*/ ieee80211_disable_dyn_ps(wl->vif); set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); } else { ieee80211_enable_dyn_ps(wl->vif); clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); wl1271_recalc_rx_streaming(wl); } }
static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) { int ret; u32 vector; bool beacon_loss = false; wl1271_event_mbox_dump(mbox); vector = le32_to_cpu(mbox->events_vector); vector &= ~(le32_to_cpu(mbox->events_mask)); wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); if (vector & SCAN_COMPLETE_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "status: 0x%x", mbox->scheduled_scan_status); wl1271_scan_stm(wl); } /* disable dynamic PS when requested by the firmware */ if (vector & SOFT_GEMINI_SENSE_EVENT_ID && wl->bss_type == BSS_TYPE_STA_BSS) { if (mbox->soft_gemini_sense_info) ieee80211_disable_dyn_ps(wl->vif); else ieee80211_enable_dyn_ps(wl->vif); } /* * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon * filtering) is enabled. Without PSM, the stack will receive all * beacons and can detect beacon loss by itself. * * As there's possibility that the driver disables PSM before receiving * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. * */ if (vector & BSS_LOSE_EVENT_ID) { wl1271_info("Beacon loss detected."); /* indicate to the stack, that beacons have been lost */ beacon_loss = true; } if (vector & PS_REPORT_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); ret = wl1271_event_ps_report(wl, mbox, &beacon_loss); if (ret < 0) return ret; } if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) wl1271_event_pspoll_delivery_fail(wl); if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); if (wl->vif) wl1271_event_rssi_trigger(wl, mbox); } if (wl->vif && beacon_loss) ieee80211_connection_loss(wl->vif); return 0; }
static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) { int ret; u32 vector; bool beacon_loss = false; bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); bool disconnect_sta = false; unsigned long sta_bitmap = 0; wl1271_event_mbox_dump(mbox); vector = le32_to_cpu(mbox->events_vector); vector &= ~(le32_to_cpu(mbox->events_mask)); wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); if (vector & SCAN_COMPLETE_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "status: 0x%x", mbox->scheduled_scan_status); wl1271_scan_stm(wl); } /* disable dynamic PS when requested by the firmware */ if (vector & SOFT_GEMINI_SENSE_EVENT_ID && wl->bss_type == BSS_TYPE_STA_BSS) { if (mbox->soft_gemini_sense_info) ieee80211_disable_dyn_ps(wl->vif); else ieee80211_enable_dyn_ps(wl->vif); } /* * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon * filtering) is enabled. Without PSM, the stack will receive all * beacons and can detect beacon loss by itself. * * As there's possibility that the driver disables PSM before receiving * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. * */ if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) { wl1271_info("Beacon loss detected."); /* indicate to the stack, that beacons have been lost */ beacon_loss = true; } if ((vector & PS_REPORT_EVENT_ID) && !is_ap) { wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); ret = wl1271_event_ps_report(wl, mbox, &beacon_loss); if (ret < 0) return ret; } if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap) wl1271_event_pspoll_delivery_fail(wl); if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); if (wl->vif) wl1271_event_rssi_trigger(wl, mbox); } if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) { wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); if (wl->vif) wl1271_tx_dummy_packet(wl); } /* * "TX retries exceeded" has a different meaning according to mode. * In AP mode the offending station is disconnected. In STA mode we * report connection loss. */ if (vector & MAX_TX_RETRY_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); if (is_ap) { sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); disconnect_sta = true; } else { beacon_loss = true; } } if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); disconnect_sta = true; } if (wl->vif && beacon_loss) ieee80211_connection_loss(wl->vif); if (is_ap && disconnect_sta) { u32 num_packets = wl->conf.tx.max_tx_retries; struct ieee80211_sta *sta; const u8 *addr; int h; for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); h < AP_MAX_LINKS; h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { if (!wl1271_is_active_sta(wl, h)) continue; addr = wl->links[h].addr; rcu_read_lock(); sta = ieee80211_find_sta(wl->vif, addr); if (sta) { wl1271_debug(DEBUG_EVENT, "remove sta %d", h); #if 0 ieee80211_report_low_ack(sta, num_packets); #endif } rcu_read_unlock(); } } return 0; }