if (powersave)
nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
- IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
+ IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
IEEE80211_STA_CONNECTION_POLL))
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE;
return 0;
}
-void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
-{
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_conf *conf = &local->hw.conf;
-
- WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
- !(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) ||
- (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS));
-
- local->disable_dynamic_ps = false;
- conf->dynamic_ps_timeout = local->dynamic_ps_user_timeout;
-}
-EXPORT_SYMBOL(ieee80211_enable_dyn_ps);
-
-void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif)
-{
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_conf *conf = &local->hw.conf;
-
- WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
- !(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) ||
- (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS));
-
- local->disable_dynamic_ps = true;
- conf->dynamic_ps_timeout = 0;
- del_timer_sync(&local->dynamic_ps_timer);
- ieee80211_queue_work(&local->hw,
- &local->dynamic_ps_enable_work);
-}
-EXPORT_SYMBOL(ieee80211_disable_dyn_ps);
-
/* powersave */
static void ieee80211_enable_ps(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
}
if (count == 1 && ieee80211_powersave_allowed(found)) {
- struct ieee80211_conf *conf = &local->hw.conf;
s32 beaconint_us;
if (latency < 0)
else
timeout = 100;
}
- local->dynamic_ps_user_timeout = timeout;
- if (!local->disable_dynamic_ps)
- conf->dynamic_ps_timeout =
- local->dynamic_ps_user_timeout;
+ local->hw.conf.dynamic_ps_timeout = timeout;
if (beaconint_us > latency) {
local->ps_sdata = NULL;
if (local->hw.conf.flags & IEEE80211_CONF_PS)
return;
- if (!local->disable_dynamic_ps &&
- local->hw.conf.dynamic_ps_timeout > 0) {
+ if (local->hw.conf.dynamic_ps_timeout > 0) {
/* don't enter PS if TX frames are pending */
if (drv_tx_frames_pending(local)) {
mod_timer(&local->dynamic_ps_timer, jiffies +
if (beacon)
mlme_dbg_ratelimited(sdata,
- "detected beacon loss from AP - sending probe request\n");
+ "detected beacon loss from AP - probing\n");
ieee80211_cqm_rssi_notify(&sdata->vif,
NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL);
static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_local *local = sdata->local;
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
mutex_lock(&ifmgd->mtx);
* but that's not a problem.
*/
cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
-
- mutex_lock(&local->mtx);
- ieee80211_recalc_idle(local);
- mutex_unlock(&local->mtx);
}
static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
- mutex_lock(&sdata->local->mtx);
- ieee80211_recalc_idle(sdata->local);
- mutex_unlock(&sdata->local->mtx);
-
return RX_MGMT_CFG80211_DEAUTH;
}
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
- mutex_lock(&sdata->local->mtx);
- ieee80211_recalc_idle(sdata->local);
- mutex_unlock(&sdata->local->mtx);
-
return RX_MGMT_CFG80211_DISASSOC;
}
if (elems.wmm_param)
set_sta_flag(sta, WLAN_STA_WME);
- err = sta_info_move_state(sta, IEEE80211_STA_AUTH);
- if (!err)
- err = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
+ err = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
if (err) {
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
ifmgd->assoc_data->have_beacon = true;
ifmgd->assoc_data->need_beacon = false;
+ if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
+ sdata->vif.bss_conf.sync_tsf =
+ le64_to_cpu(mgmt->u.beacon.timestamp);
+ sdata->vif.bss_conf.sync_device_ts =
+ rx_status->device_timestamp;
+ if (elems.tim)
+ sdata->vif.bss_conf.sync_dtim_count =
+ elems.tim->dtim_count;
+ else
+ sdata->vif.bss_conf.sync_dtim_count = 0;
+ }
/* continue assoc process */
ifmgd->assoc_data->timeout = jiffies;
run_again(ifmgd, ifmgd->assoc_data->timeout);
if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) {
mlme_dbg_ratelimited(sdata,
- "cancelling probereq poll due to a received beacon\n");
+ "cancelling AP probe due to a received beacon\n");
mutex_lock(&local->mtx);
ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL;
ieee80211_run_deferred_scan(local);
/*
* If we haven't had a beacon before, tell the driver about the
- * DTIM period now.
+ * DTIM period (and beacon timing if desired) now.
*/
if (!bss_conf->dtim_period) {
/* a few bogus AP send dtim_period = 0 or no TIM IE */
bss_conf->dtim_period = elems.tim->dtim_period ?: 1;
else
bss_conf->dtim_period = 1;
+
+ if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
+ sdata->vif.bss_conf.sync_tsf =
+ le64_to_cpu(mgmt->u.beacon.timestamp);
+ sdata->vif.bss_conf.sync_device_ts =
+ rx_status->device_timestamp;
+ if (elems.tim)
+ sdata->vif.bss_conf.sync_dtim_count =
+ elems.tim->dtim_count;
+ else
+ sdata->vif.bss_conf.sync_dtim_count = 0;
+ }
+
changed |= BSS_CHANGED_DTIM_PERIOD;
}
static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
u8 *bssid, u8 reason, bool tx)
{
- struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
*/
cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
- mutex_lock(&local->mtx);
- ieee80211_recalc_idle(local);
- mutex_unlock(&local->mtx);
-
mutex_lock(&ifmgd->mtx);
}
}
mutex_unlock(&ifmgd->mtx);
-
- mutex_lock(&local->mtx);
- ieee80211_recalc_idle(local);
- mutex_unlock(&local->mtx);
}
static void ieee80211_sta_bcn_mon_timer(unsigned long data)
return -ENOMEM;
}
- mutex_lock(&local->mtx);
- ieee80211_recalc_idle(sdata->local);
- mutex_unlock(&local->mtx);
-
if (new_sta) {
u32 rates = 0, basic_rates = 0;
bool have_higher_than_11mbit;
int min_rate = INT_MAX, min_rate_index = -1;
struct ieee80211_supported_band *sband;
+ const struct cfg80211_bss_ies *ies;
sband = local->hw.wiphy->bands[cbss->channel->band];
/* set timing information */
sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
- sdata->vif.bss_conf.sync_tsf = cbss->tsf;
- sdata->vif.bss_conf.sync_device_ts = bss->device_ts;
+ rcu_read_lock();
+ ies = rcu_dereference(cbss->beacon_ies);
+ if (ies) {
+ const u8 *tim_ie;
+
+ sdata->vif.bss_conf.sync_tsf = ies->tsf;
+ sdata->vif.bss_conf.sync_device_ts =
+ bss->device_ts_beacon;
+ tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
+ ies->data, ies->len);
+ if (tim_ie && tim_ie[1] >= 2)
+ sdata->vif.bss_conf.sync_dtim_count = tim_ie[2];
+ else
+ sdata->vif.bss_conf.sync_dtim_count = 0;
+ } else if (!(local->hw.flags &
+ IEEE80211_HW_TIMING_BEACON_ONLY)) {
+ ies = rcu_dereference(cbss->proberesp_ies);
+ /* must be non-NULL since beacon IEs were NULL */
+ sdata->vif.bss_conf.sync_tsf = ies->tsf;
+ sdata->vif.bss_conf.sync_device_ts =
+ bss->device_ts_presp;
+ sdata->vif.bss_conf.sync_dtim_count = 0;
+ } else {
+ sdata->vif.bss_conf.sync_tsf = 0;
+ sdata->vif.bss_conf.sync_device_ts = 0;
+ sdata->vif.bss_conf.sync_dtim_count = 0;
+ }
+ rcu_read_unlock();
/* tell driver about BSSID, basic rates and timing */
ieee80211_bss_info_change_notify(sdata,
const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
beacon_ies->data,
beacon_ies->len);
+ u8 dtim_count = 0;
+
if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) {
const struct ieee80211_tim_ie *tim;
tim = (void *)(tim_ie + 2);
ifmgd->dtim_period = tim->dtim_period;
+ dtim_count = tim->dtim_count;
}
assoc_data->have_beacon = true;
assoc_data->timeout = jiffies;
+
+ if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
+ sdata->vif.bss_conf.sync_tsf = beacon_ies->tsf;
+ sdata->vif.bss_conf.sync_device_ts =
+ bss->device_ts_beacon;
+ sdata->vif.bss_conf.sync_dtim_count = dtim_count;
+ }
} else {
assoc_data->timeout = jiffies;
}
mutex_unlock(&ifmgd->mtx);
out:
- mutex_lock(&sdata->local->mtx);
- ieee80211_recalc_idle(sdata->local);
- mutex_unlock(&sdata->local->mtx);
-
if (sent_frame)
__cfg80211_send_deauth(sdata->dev, frame_buf,
IEEE80211_DEAUTH_FRAME_LEN);
__cfg80211_send_disassoc(sdata->dev, frame_buf,
IEEE80211_DEAUTH_FRAME_LEN);
- mutex_lock(&sdata->local->mtx);
- ieee80211_recalc_idle(sdata->local);
- mutex_unlock(&sdata->local->mtx);
-
return 0;
}