static int wl1251_event_ps_report(struct wl1251 *wl, struct event_mailbox *mbox) { int ret = 0; wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status); switch (mbox->ps_status) { case EVENT_ENTER_POWER_SAVE_FAIL: wl1251_debug(DEBUG_PSM, "PSM entry failed"); if (wl->station_mode != STATION_POWER_SAVE_MODE) { /* remain in active mode */ wl->psm_entry_retry = 0; break; } if (wl->psm_entry_retry < WL1251_PSM_ENTRY_RETRIES) { wl->psm_entry_retry++; ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); } else { wl1251_error("Power save entry failed, giving up"); wl->psm_entry_retry = 0; } break; case EVENT_ENTER_POWER_SAVE_SUCCESS: case EVENT_EXIT_POWER_SAVE_FAIL: case EVENT_EXIT_POWER_SAVE_SUCCESS: default: wl->psm_entry_retry = 0; break; } return 0; }
static int wl1251_event_ps_report(struct wl1251 *wl, struct event_mailbox *mbox) { int ret = 0; wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status); switch (mbox->ps_status) { case ENTER_POWER_SAVE_FAIL: if (!wl->psm) { wl->ps_entry_retry = 0; break; } if (wl->ps_entry_retry < WL1251_PS_ENTRY_RETRIES) { ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); wl->ps_entry_retry++; } else { wl1251_error("Power save entry failed, giving up"); wl->ps_entry_retry = 0; } break; case ENTER_POWER_SAVE_SUCCESS: default: wl->ps_entry_retry = 0; break; } return 0; }
static int wl1251_event_scan_complete(struct wl1251 *wl, struct event_mailbox *mbox) { int ret = 0; wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d", mbox->scheduled_scan_status, mbox->scheduled_scan_channels); if (wl->scanning) { ieee80211_scan_completed(wl->hw, false); wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed"); wl->scanning = false; if (wl->hw->conf.flags & IEEE80211_CONF_IDLE) ret = wl1251_ps_set_mode(wl, STATION_IDLE); } return ret; }
static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) { int ret; u32 vector; wl1251_event_mbox_dump(mbox); vector = mbox->events_vector & ~(mbox->events_mask); wl1251_debug(DEBUG_EVENT, "vector: 0x%x", vector); if (vector & SCAN_COMPLETE_EVENT_ID) { ret = wl1251_event_scan_complete(wl, mbox); if (ret < 0) return ret; } if (vector & BSS_LOSE_EVENT_ID) { wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); if (wl->psm_requested && wl->station_mode != STATION_ACTIVE_MODE) { ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); if (ret < 0) return ret; } } if (vector & PS_REPORT_EVENT_ID) { wl1251_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); ret = wl1251_event_ps_report(wl, mbox); if (ret < 0) return ret; } if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) { wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); /* indicate to the stack, that beacons have been lost */ if (wl->vif && wl->vif->type == NL80211_IFTYPE_STATION) ieee80211_beacon_loss(wl->vif); } if (vector & REGAINED_BSS_EVENT_ID) { if (wl->psm_requested) { ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); if (ret < 0) return ret; } } if (wl->vif && wl->rssi_thold) { if (vector & ROAMING_TRIGGER_LOW_RSSI_EVENT_ID) { wl1251_debug(DEBUG_EVENT, "ROAMING_TRIGGER_LOW_RSSI_EVENT"); ieee80211_cqm_rssi_notify(wl->vif, NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, GFP_KERNEL); } if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID) { wl1251_debug(DEBUG_EVENT, "ROAMING_TRIGGER_REGAINED_RSSI_EVENT"); ieee80211_cqm_rssi_notify(wl->vif, NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, GFP_KERNEL); } } return 0; }
static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) { int ret; u32 vector; vector = mbox->events_vector & ~(mbox->events_mask); if (vector & SCAN_COMPLETE_EVENT_ID) { ret = wl1251_event_scan_complete(wl, mbox); if (ret < 0) return ret; } if (vector & BSS_LOSE_EVENT_ID) { wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); if (wl->psm_requested && wl->psm) { ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); if (ret < 0) return ret; } } if (vector & PS_REPORT_EVENT_ID) { wl1251_debug(DEBUG_EVENT, "PS_REPORT_EVENT_ID"); ret = wl1251_event_ps_report(wl, mbox); if (ret < 0) return ret; } if (wl->vif && (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID)) { wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); /* need to unlock mutex to avoid deadlocking with rtnl */ mutex_unlock(&wl->mutex); /* indicate to the stack, that beacons have been lost */ ieee80211_beacon_loss(wl->vif); mutex_lock(&wl->mutex); } if (vector & REGAINED_BSS_EVENT_ID) { if (wl->psm_requested) { ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); if (ret < 0) return ret; } } if (wl->vif && (vector & ROAMING_TRIGGER_LOW_RSSI_EVENT_ID)) { wl1251_debug(DEBUG_EVENT, "ROAMING_TRIGGER_LOW_RSSI_EVENT"); ieee80211_rssi_changed(wl->vif, IEEE80211_RSSI_STATE_LOW); } if (wl->vif && (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID)) { wl1251_debug(DEBUG_EVENT, "ROAMING_TRIGGER_REGAINED_RSSI_EVENT"); ieee80211_rssi_changed(wl->vif, IEEE80211_RSSI_STATE_HIGH); } return 0; }