int wl1271_ap_init_templates(struct wl1271 *wl) { int ret; ret = wl1271_ap_init_deauth_template(wl); if (ret < 0) return ret; ret = wl1271_ap_init_null_template(wl); if (ret < 0) return ret; ret = wl1271_ap_init_qos_null_template(wl); if (ret < 0) return ret; /* * when operating as AP we want to receive external beacons for * configuring ERP protection. */ ret = wl1271_acx_beacon_filter_opt(wl, false); if (ret < 0) return ret; return 0; }
static ssize_t beacon_filtering_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct wl1271 *wl = file->private_data; char buf[10]; size_t len; unsigned long value; int ret; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; ret = kstrtoul(buf, 0, &value); if (ret < 0) { wl1271_warning("illegal value for beacon_filtering!"); return -EINVAL; } mutex_lock(&wl->mutex); ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; ret = wl1271_acx_beacon_filter_opt(wl, !!value); wl1271_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); return count; }
int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif) { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; ret = wl1271_ap_init_deauth_template(wl, wlvif); if (ret < 0) return ret; ret = wl1271_ap_init_null_template(wl, vif); if (ret < 0) return ret; ret = wl1271_ap_init_qos_null_template(wl, vif); if (ret < 0) return ret; /* * when operating as AP we want to receive external beacons for * configuring ERP protection. */ ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); if (ret < 0) return ret; return 0; }
static int wl1271_event_ps_report(struct wl1271 *wl, struct event_mailbox *mbox, bool *beacon_loss) { int ret = 0; u32 total_retries = wl->conf.conn.psm_entry_retries; wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); switch (mbox->ps_status) { case EVENT_ENTER_POWER_SAVE_FAIL: wl1271_debug(DEBUG_PSM, "PSM entry failed"); if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { /* remain in active mode */ wl->psm_entry_retry = 0; break; } if (wl->psm_entry_retry < total_retries) { wl->psm_entry_retry++; ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); } else { wl1271_info("No ack to nullfunc from AP."); wl->psm_entry_retry = 0; *beacon_loss = true; } break; case EVENT_ENTER_POWER_SAVE_SUCCESS: wl->psm_entry_retry = 0; /* enable beacon filtering */ ret = wl1271_acx_beacon_filter_opt(wl, true); if (ret < 0) break; /* * BET has only a minor effect in 5GHz and masks * channel switch IEs, so we only enable BET on 2.4GHz */ if (wl->band == IEEE80211_BAND_2GHZ) /* enable beacon early termination */ ret = wl1271_acx_bet_enable(wl, true); if (wl->ps_compl) { complete(wl->ps_compl); wl->ps_compl = NULL; } break; default: break; } return ret; }
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, u32 rates, bool send) { int ret; switch (mode) { case STATION_POWER_SAVE_MODE: wl1271_debug(DEBUG_PSM, "entering psm"); ret = wl1271_acx_wake_up_conditions(wl, wl->conf.conn.wake_up_event, wl->conf.conn.listen_interval); if (ret < 0) { wl1271_error("couldn't set wake up conditions"); return ret; } ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); if (ret < 0) return ret; set_bit(WL1271_FLAG_PSM, &wl->flags); break; case STATION_ACTIVE_MODE: default: wl1271_debug(DEBUG_PSM, "leaving psm"); wl->psm_entry_retry = 0; cancel_delayed_work(&wl->ps_retry_work); /* disable beacon early termination */ if (wl->band == IEEE80211_BAND_2GHZ) { ret = wl1271_acx_bet_enable(wl, false); if (ret < 0) return ret; } /* disable beacon filtering */ ret = wl1271_acx_beacon_filter_opt(wl, false); if (ret < 0) return ret; ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE); if (ret < 0) return ret; clear_bit(WL1271_FLAG_PSM, &wl->flags); break; } return ret; }
static int wl1271_init_beacon_filter(struct wl1271 *wl) { int ret; ret = wl1271_acx_beacon_filter_opt(wl); if (ret < 0) return ret; ret = wl1271_acx_beacon_filter_table(wl); if (ret < 0) return ret; return 0; }
static int wl1271_init_beacon_filter(struct wl1271 *wl) { int ret; /* disable beacon filtering at this stage */ ret = wl1271_acx_beacon_filter_opt(wl, false); if (ret < 0) return ret; ret = wl1271_acx_beacon_filter_table(wl); if (ret < 0) return ret; return 0; }
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, u32 rates, bool send) { int ret; switch (mode) { case STATION_POWER_SAVE_MODE: wl1271_debug(DEBUG_PSM, "entering psm"); ret = wl1271_acx_wake_up_conditions(wl); if (ret < 0) { wl1271_error("couldn't set wake up conditions"); return ret; } ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); if (ret < 0) return ret; set_bit(WL1271_FLAG_PSM, &wl->flags); break; case STATION_ACTIVE_MODE: default: wl1271_debug(DEBUG_PSM, "leaving psm"); ret = wl1271_ps_elp_wakeup(wl, false); if (ret < 0) return ret; /* disable beacon early termination */ ret = wl1271_acx_bet_enable(wl, false); if (ret < 0) return ret; /* disable beacon filtering */ ret = wl1271_acx_beacon_filter_opt(wl, false); if (ret < 0) return ret; ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE); if (ret < 0) return ret; clear_bit(WL1271_FLAG_PSM, &wl->flags); break; } return ret; }
static int wl1271_init_sta_beacon_filter(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret; ret = wl1271_acx_beacon_filter_table(wl, wlvif); if (ret < 0) return ret; /* enable beacon filtering */ ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); if (ret < 0) return ret; return 0; }
static int wl1271_init_sta_beacon_filter(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret; ret = wl1271_acx_beacon_filter_table(wl, wlvif); if (ret < 0) return ret; /* disable beacon filtering until we get the first beacon */ ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); if (ret < 0) return ret; return 0; }
static int wl1271_event_ps_report(struct wl1271 *wl, struct event_mailbox *mbox, bool *beacon_loss) { int ret = 0; u32 total_retries = wl->conf.conn.psm_entry_retries; wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); switch (mbox->ps_status) { case EVENT_ENTER_POWER_SAVE_FAIL: wl1271_debug(DEBUG_PSM, "PSM entry failed"); if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { /* remain in active mode */ wl->psm_entry_retry = 0; break; } if (wl->psm_entry_retry < total_retries) { wl->psm_entry_retry++; ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); } else { wl1271_info("No ack to nullfunc from AP."); wl->psm_entry_retry = 0; *beacon_loss = true; } break; case EVENT_ENTER_POWER_SAVE_SUCCESS: wl->psm_entry_retry = 0; /* enable beacon filtering */ ret = wl1271_acx_beacon_filter_opt(wl, true); if (ret < 0) break; /* enable beacon early termination */ ret = wl1271_acx_bet_enable(wl, true); if (ret < 0) break; /* go to extremely low power mode */ wl1271_ps_elp_sleep(wl); break; case EVENT_EXIT_POWER_SAVE_FAIL: wl1271_debug(DEBUG_PSM, "PSM exit failed"); if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { wl->psm_entry_retry = 0; break; } /* make sure the firmware goes to active mode - the frame to be sent next will indicate to the AP, that we are active. */ ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, wl->basic_rate, false); break; case EVENT_EXIT_POWER_SAVE_SUCCESS: default: break; } return ret; }