diff options
Diffstat (limited to 'net/mac80211/sta_info.c')
| -rw-r--r-- | net/mac80211/sta_info.c | 1568 | 
1 files changed, 1142 insertions, 426 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index eff58571fd7..a9b46d8ea22 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -9,6 +9,7 @@  #include <linux/module.h>  #include <linux/init.h> +#include <linux/etherdevice.h>  #include <linux/netdevice.h>  #include <linux/types.h>  #include <linux/slab.h> @@ -24,6 +25,7 @@  #include "sta_info.h"  #include "debugfs_sta.h"  #include "mesh.h" +#include "wme.h"  /**   * DOC: STA information lifetime rules @@ -47,9 +49,9 @@   * Station entries are added by mac80211 when you establish a link with a   * peer. This means different things for the different type of interfaces   * we support. For a regular station this mean we add the AP sta when we - * receive an assocation response from the AP. For IBSS this occurs when + * receive an association response from the AP. For IBSS this occurs when   * get to know about a peer on the same IBSS. For WDS we add the sta for - * the peer imediately upon device open. When using AP mode we add stations + * the peer immediately upon device open. When using AP mode we add stations   * for each respective station upon request from userspace through nl80211.   *   * In order to remove a STA info structure, various sta_info_destroy_*() @@ -61,13 +63,14 @@   * freed before they are done using it.   */ -/* Caller must hold local->sta_lock */ +/* Caller must hold local->sta_mtx */  static int sta_info_hash_del(struct ieee80211_local *local,  			     struct sta_info *sta)  {  	struct sta_info *s; -	s = local->sta_hash[STA_HASH(sta->sta.addr)]; +	s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)], +				      lockdep_is_held(&local->sta_mtx));  	if (!s)  		return -ENOENT;  	if (s == sta) { @@ -76,9 +79,11 @@ static int sta_info_hash_del(struct ieee80211_local *local,  		return 0;  	} -	while (s->hnext && s->hnext != sta) -		s = s->hnext; -	if (s->hnext) { +	while (rcu_access_pointer(s->hnext) && +	       rcu_access_pointer(s->hnext) != sta) +		s = rcu_dereference_protected(s->hnext, +					lockdep_is_held(&local->sta_mtx)); +	if (rcu_access_pointer(s->hnext)) {  		rcu_assign_pointer(s->hnext, sta->hnext);  		return 0;  	} @@ -86,6 +91,67 @@ static int sta_info_hash_del(struct ieee80211_local *local,  	return -ENOENT;  } +static void __cleanup_single_sta(struct sta_info *sta) +{ +	int ac, i; +	struct tid_ampdu_tx *tid_tx; +	struct ieee80211_sub_if_data *sdata = sta->sdata; +	struct ieee80211_local *local = sdata->local; +	struct ps_data *ps; + +	if (test_sta_flag(sta, WLAN_STA_PS_STA) || +	    test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { +		if (sta->sdata->vif.type == NL80211_IFTYPE_AP || +		    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +			ps = &sdata->bss->ps; +		else if (ieee80211_vif_is_mesh(&sdata->vif)) +			ps = &sdata->u.mesh.ps; +		else +			return; + +		clear_sta_flag(sta, WLAN_STA_PS_STA); +		clear_sta_flag(sta, WLAN_STA_PS_DRIVER); + +		atomic_dec(&ps->num_sta_ps); +		sta_info_recalc_tim(sta); +	} + +	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { +		local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); +		ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); +		ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]); +	} + +	if (ieee80211_vif_is_mesh(&sdata->vif)) +		mesh_sta_cleanup(sta); + +	cancel_work_sync(&sta->drv_unblock_wk); + +	/* +	 * Destroy aggregation state here. It would be nice to wait for the +	 * driver to finish aggregation stop and then clean up, but for now +	 * drivers have to handle aggregation stop being requested, followed +	 * directly by station destruction. +	 */ +	for (i = 0; i < IEEE80211_NUM_TIDS; i++) { +		kfree(sta->ampdu_mlme.tid_start_tx[i]); +		tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); +		if (!tid_tx) +			continue; +		ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); +		kfree(tid_tx); +	} +} + +static void cleanup_single_sta(struct sta_info *sta) +{ +	struct ieee80211_sub_if_data *sdata = sta->sdata; +	struct ieee80211_local *local = sdata->local; + +	__cleanup_single_sta(sta); +	sta_info_free(local, sta); +} +  /* protected by RCU */  struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,  			      const u8 *addr) @@ -94,16 +160,12 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,  	struct sta_info *sta;  	sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], -				    rcu_read_lock_held() || -				    lockdep_is_held(&local->sta_lock) ||  				    lockdep_is_held(&local->sta_mtx));  	while (sta) {  		if (sta->sdata == sdata && -		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) +		    ether_addr_equal(sta->sta.addr, addr))  			break;  		sta = rcu_dereference_check(sta->hnext, -					    rcu_read_lock_held() || -					    lockdep_is_held(&local->sta_lock) ||  					    lockdep_is_held(&local->sta_mtx));  	}  	return sta; @@ -120,17 +182,13 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,  	struct sta_info *sta;  	sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], -				    rcu_read_lock_held() || -				    lockdep_is_held(&local->sta_lock) ||  				    lockdep_is_held(&local->sta_mtx));  	while (sta) {  		if ((sta->sdata == sdata ||  		     (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && -		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) +		    ether_addr_equal(sta->sta.addr, addr))  			break;  		sta = rcu_dereference_check(sta->hnext, -					    rcu_read_lock_held() || -					    lockdep_is_held(&local->sta_lock) ||  					    lockdep_is_held(&local->sta_mtx));  	}  	return sta; @@ -157,33 +215,40 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,  }  /** - * __sta_info_free - internal STA free helper + * sta_info_free - free STA   *   * @local: pointer to the global information   * @sta: STA info to free   *   * This function must undo everything done by sta_info_alloc() - * that may happen before sta_info_insert(). + * that may happen before sta_info_insert(). It may only be + * called when sta_info_insert() has not been attempted (and + * if that fails, the station is freed anyway.)   */ -static void __sta_info_free(struct ieee80211_local *local, -			    struct sta_info *sta) +void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)  { -	if (sta->rate_ctrl) { +	int i; + +	if (sta->rate_ctrl)  		rate_control_free_sta(sta); -		rate_control_put(sta->rate_ctrl); + +	if (sta->tx_lat) { +		for (i = 0; i < IEEE80211_NUM_TIDS; i++) +			kfree(sta->tx_lat[i].bins); +		kfree(sta->tx_lat);  	} -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG -	wiphy_debug(local->hw.wiphy, "Destroyed STA %pM\n", sta->sta.addr); -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ +	sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr); +	kfree(rcu_dereference_raw(sta->sta.rates));  	kfree(sta);  } -/* Caller must hold local->sta_lock */ +/* Caller must hold local->sta_mtx */  static void sta_info_hash_add(struct ieee80211_local *local,  			      struct sta_info *sta)  { +	lockdep_assert_held(&local->sta_mtx);  	sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)];  	rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);  } @@ -197,13 +262,24 @@ static void sta_unblock(struct work_struct *wk)  	if (sta->dead)  		return; -	if (!test_sta_flags(sta, WLAN_STA_PS_STA)) +	if (!test_sta_flag(sta, WLAN_STA_PS_STA)) { +		local_bh_disable();  		ieee80211_sta_ps_deliver_wakeup(sta); -	else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) { -		clear_sta_flags(sta, WLAN_STA_PS_DRIVER); +		local_bh_enable(); +	} else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) { +		clear_sta_flag(sta, WLAN_STA_PS_DRIVER); + +		local_bh_disable();  		ieee80211_sta_ps_deliver_poll_response(sta); +		local_bh_enable(); +	} else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) { +		clear_sta_flag(sta, WLAN_STA_PS_DRIVER); + +		local_bh_disable(); +		ieee80211_sta_ps_deliver_uapsd(sta); +		local_bh_enable();  	} else -		clear_sta_flags(sta, WLAN_STA_PS_DRIVER); +		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);  }  static int sta_prepare_rate_control(struct ieee80211_local *local, @@ -212,44 +288,86 @@ static int sta_prepare_rate_control(struct ieee80211_local *local,  	if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)  		return 0; -	sta->rate_ctrl = rate_control_get(local->rate_ctrl); +	sta->rate_ctrl = local->rate_ctrl;  	sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,  						     &sta->sta, gfp); -	if (!sta->rate_ctrl_priv) { -		rate_control_put(sta->rate_ctrl); +	if (!sta->rate_ctrl_priv)  		return -ENOMEM; -	}  	return 0;  }  struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, -				u8 *addr, gfp_t gfp) +				const u8 *addr, gfp_t gfp)  {  	struct ieee80211_local *local = sdata->local;  	struct sta_info *sta; +	struct timespec uptime; +	struct ieee80211_tx_latency_bin_ranges *tx_latency;  	int i;  	sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp);  	if (!sta)  		return NULL; +	rcu_read_lock(); +	tx_latency = rcu_dereference(local->tx_latency); +	/* init stations Tx latency statistics && TID bins */ +	if (tx_latency) { +		sta->tx_lat = kzalloc(IEEE80211_NUM_TIDS * +				      sizeof(struct ieee80211_tx_latency_stat), +				      GFP_ATOMIC); +		if (!sta->tx_lat) { +			rcu_read_unlock(); +			goto free; +		} + +		if (tx_latency->n_ranges) { +			for (i = 0; i < IEEE80211_NUM_TIDS; i++) { +				/* size of bins is size of the ranges +1 */ +				sta->tx_lat[i].bin_count = +					tx_latency->n_ranges + 1; +				sta->tx_lat[i].bins = +					kcalloc(sta->tx_lat[i].bin_count, +						sizeof(u32), GFP_ATOMIC); +				if (!sta->tx_lat[i].bins) { +					rcu_read_unlock(); +					goto free; +				} +			} +		} +	} +	rcu_read_unlock(); +  	spin_lock_init(&sta->lock); -	spin_lock_init(&sta->flaglock); +	spin_lock_init(&sta->ps_lock);  	INIT_WORK(&sta->drv_unblock_wk, sta_unblock);  	INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);  	mutex_init(&sta->ampdu_mlme.mtx); +#ifdef CONFIG_MAC80211_MESH +	if (ieee80211_vif_is_mesh(&sdata->vif) && +	    !sdata->u.mesh.user_mpm) +		init_timer(&sta->plink_timer); +	sta->nonpeer_pm = NL80211_MESH_POWER_ACTIVE; +#endif  	memcpy(sta->sta.addr, addr, ETH_ALEN);  	sta->local = local;  	sta->sdata = sdata; +	sta->last_rx = jiffies; -	if (sta_prepare_rate_control(local, sta, gfp)) { -		kfree(sta); -		return NULL; -	} +	sta->sta_state = IEEE80211_STA_NONE; + +	do_posix_clock_monotonic_gettime(&uptime); +	sta->last_connected = uptime.tv_sec; +	ewma_init(&sta->avg_signal, 1024, 8); +	for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++) +		ewma_init(&sta->chain_signal_avg[i], 1024, 8); -	for (i = 0; i < STA_TID_NUM; i++) { +	if (sta_prepare_rate_control(local, sta, gfp)) +		goto free; + +	for (i = 0; i < IEEE80211_NUM_TIDS; i++) {  		/*  		 * timer_to_tid must be initialized with identity mapping  		 * to enable session_timer's data differentiation. See @@ -257,224 +375,203 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,  		 */  		sta->timer_to_tid[i] = i;  	} -	skb_queue_head_init(&sta->ps_tx_buf); -	skb_queue_head_init(&sta->tx_filtered); +	for (i = 0; i < IEEE80211_NUM_ACS; i++) { +		skb_queue_head_init(&sta->ps_tx_buf[i]); +		skb_queue_head_init(&sta->tx_filtered[i]); +	} -	for (i = 0; i < NUM_RX_DATA_QUEUES; i++) +	for (i = 0; i < IEEE80211_NUM_TIDS; i++)  		sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG -	wiphy_debug(local->hw.wiphy, "Allocated STA %pM\n", sta->sta.addr); -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - -#ifdef CONFIG_MAC80211_MESH -	sta->plink_state = PLINK_LISTEN; -	init_timer(&sta->plink_timer); -#endif +	sta->sta.smps_mode = IEEE80211_SMPS_OFF; +	if (sdata->vif.type == NL80211_IFTYPE_AP || +	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +		struct ieee80211_supported_band *sband = +			local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; +		u8 smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> +				IEEE80211_HT_CAP_SM_PS_SHIFT; +		/* +		 * Assume that hostapd advertises our caps in the beacon and +		 * this is the known_smps_mode for a station that just assciated +		 */ +		switch (smps) { +		case WLAN_HT_SMPS_CONTROL_DISABLED: +			sta->known_smps_mode = IEEE80211_SMPS_OFF; +			break; +		case WLAN_HT_SMPS_CONTROL_STATIC: +			sta->known_smps_mode = IEEE80211_SMPS_STATIC; +			break; +		case WLAN_HT_SMPS_CONTROL_DYNAMIC: +			sta->known_smps_mode = IEEE80211_SMPS_DYNAMIC; +			break; +		default: +			WARN_ON(1); +		} +	} +	sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);  	return sta; + +free: +	if (sta->tx_lat) { +		for (i = 0; i < IEEE80211_NUM_TIDS; i++) +			kfree(sta->tx_lat[i].bins); +		kfree(sta->tx_lat); +	} +	kfree(sta); +	return NULL;  } -static int sta_info_finish_insert(struct sta_info *sta, bool async) +static int sta_info_insert_check(struct sta_info *sta)  { -	struct ieee80211_local *local = sta->local;  	struct ieee80211_sub_if_data *sdata = sta->sdata; -	struct station_info sinfo; -	unsigned long flags; -	int err = 0; - -	lockdep_assert_held(&local->sta_mtx); - -	/* notify driver */ -	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -		sdata = container_of(sdata->bss, -				     struct ieee80211_sub_if_data, -				     u.ap); -	err = drv_sta_add(local, sdata, &sta->sta); -	if (err) { -		if (!async) -			return err; -		printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)" -				  " - keeping it anyway.\n", -		       sdata->name, sta->sta.addr, err); -	} else { -		sta->uploaded = true; -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG -		if (async) -			wiphy_debug(local->hw.wiphy, -				    "Finished adding IBSS STA %pM\n", -				    sta->sta.addr); -#endif -	} - -	sdata = sta->sdata; - -	if (!async) { -		local->num_sta++; -		local->sta_generation++; -		smp_mb(); - -		/* make the station visible */ -		spin_lock_irqsave(&local->sta_lock, flags); -		sta_info_hash_add(local, sta); -		spin_unlock_irqrestore(&local->sta_lock, flags); -	} - -	list_add(&sta->list, &local->sta_list); -	ieee80211_sta_debugfs_add(sta); -	rate_control_add_sta_debugfs(sta); - -	sinfo.filled = 0; -	sinfo.generation = local->sta_generation; -	cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); +	/* +	 * Can't be a WARN_ON because it can be triggered through a race: +	 * something inserts a STA (on one CPU) without holding the RTNL +	 * and another CPU turns off the net device. +	 */ +	if (unlikely(!ieee80211_sdata_running(sdata))) +		return -ENETDOWN; +	if (WARN_ON(ether_addr_equal(sta->sta.addr, sdata->vif.addr) || +		    is_multicast_ether_addr(sta->sta.addr))) +		return -EINVAL;  	return 0;  } -static void sta_info_finish_pending(struct ieee80211_local *local) +static int sta_info_insert_drv_state(struct ieee80211_local *local, +				     struct ieee80211_sub_if_data *sdata, +				     struct sta_info *sta)  { -	struct sta_info *sta; -	unsigned long flags; +	enum ieee80211_sta_state state; +	int err = 0; -	spin_lock_irqsave(&local->sta_lock, flags); -	while (!list_empty(&local->sta_pending_list)) { -		sta = list_first_entry(&local->sta_pending_list, -				       struct sta_info, list); -		list_del(&sta->list); -		spin_unlock_irqrestore(&local->sta_lock, flags); +	for (state = IEEE80211_STA_NOTEXIST; state < sta->sta_state; state++) { +		err = drv_sta_state(local, sdata, sta, state, state + 1); +		if (err) +			break; +	} -		sta_info_finish_insert(sta, true); +	if (!err) { +		/* +		 * Drivers using legacy sta_add/sta_remove callbacks only +		 * get uploaded set to true after sta_add is called. +		 */ +		if (!local->ops->sta_add) +			sta->uploaded = true; +		return 0; +	} -		spin_lock_irqsave(&local->sta_lock, flags); +	if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { +		sdata_info(sdata, +			   "failed to move IBSS STA %pM to state %d (%d) - keeping it anyway\n", +			   sta->sta.addr, state + 1, err); +		err = 0;  	} -	spin_unlock_irqrestore(&local->sta_lock, flags); -} -static void sta_info_finish_work(struct work_struct *work) -{ -	struct ieee80211_local *local = -		container_of(work, struct ieee80211_local, sta_finish_work); +	/* unwind on error */ +	for (; state > IEEE80211_STA_NOTEXIST; state--) +		WARN_ON(drv_sta_state(local, sdata, sta, state, state - 1)); -	mutex_lock(&local->sta_mtx); -	sta_info_finish_pending(local); -	mutex_unlock(&local->sta_mtx); +	return err;  } -int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) +/* + * should be called with sta_mtx locked + * this function replaces the mutex lock + * with a RCU lock + */ +static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)  {  	struct ieee80211_local *local = sta->local;  	struct ieee80211_sub_if_data *sdata = sta->sdata; -	unsigned long flags; +	struct station_info sinfo;  	int err = 0; -	/* -	 * Can't be a WARN_ON because it can be triggered through a race: -	 * something inserts a STA (on one CPU) without holding the RTNL -	 * and another CPU turns off the net device. -	 */ -	if (unlikely(!ieee80211_sdata_running(sdata))) { -		err = -ENETDOWN; -		rcu_read_lock(); -		goto out_free; -	} +	lockdep_assert_held(&local->sta_mtx); -	if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || -		    is_multicast_ether_addr(sta->sta.addr))) { -		err = -EINVAL; -		rcu_read_lock(); -		goto out_free; +	/* check if STA exists already */ +	if (sta_info_get_bss(sdata, sta->sta.addr)) { +		err = -EEXIST; +		goto out_err;  	} -	/* -	 * In ad-hoc mode, we sometimes need to insert stations -	 * from tasklet context from the RX path. To avoid races, -	 * always do so in that case -- see the comment below. -	 */ -	if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { -		spin_lock_irqsave(&local->sta_lock, flags); -		/* check if STA exists already */ -		if (sta_info_get_bss(sdata, sta->sta.addr)) { -			spin_unlock_irqrestore(&local->sta_lock, flags); -			rcu_read_lock(); -			err = -EEXIST; -			goto out_free; -		} +	local->num_sta++; +	local->sta_generation++; +	smp_mb(); -		local->num_sta++; -		local->sta_generation++; -		smp_mb(); -		sta_info_hash_add(local, sta); +	/* simplify things and don't accept BA sessions yet */ +	set_sta_flag(sta, WLAN_STA_BLOCK_BA); -		list_add_tail(&sta->list, &local->sta_pending_list); +	/* make the station visible */ +	sta_info_hash_add(local, sta); -		rcu_read_lock(); -		spin_unlock_irqrestore(&local->sta_lock, flags); +	list_add_rcu(&sta->list, &local->sta_list); -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG -		wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", -			    sta->sta.addr); -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ +	/* notify driver */ +	err = sta_info_insert_drv_state(local, sdata, sta); +	if (err) +		goto out_remove; -		ieee80211_queue_work(&local->hw, &local->sta_finish_work); +	set_sta_flag(sta, WLAN_STA_INSERTED); +	/* accept BA sessions now */ +	clear_sta_flag(sta, WLAN_STA_BLOCK_BA); -		return 0; -	} +	ieee80211_recalc_min_chandef(sdata); +	ieee80211_sta_debugfs_add(sta); +	rate_control_add_sta_debugfs(sta); -	/* -	 * On first glance, this will look racy, because the code -	 * below this point, which inserts a station with sleeping, -	 * unlocks the sta_lock between checking existence in the -	 * hash table and inserting into it. -	 * -	 * However, it is not racy against itself because it keeps -	 * the mutex locked. It still seems to race against the -	 * above code that atomically inserts the station... That, -	 * however, is not true because the above code can only -	 * be invoked for IBSS interfaces, and the below code will -	 * not be -- and the two do not race against each other as -	 * the hash table also keys off the interface. -	 */ +	memset(&sinfo, 0, sizeof(sinfo)); +	sinfo.filled = 0; +	sinfo.generation = local->sta_generation; +	cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); -	might_sleep(); +	sta_dbg(sdata, "Inserted STA %pM\n", sta->sta.addr); -	mutex_lock(&local->sta_mtx); +	/* move reference to rcu-protected */ +	rcu_read_lock(); +	mutex_unlock(&local->sta_mtx); -	spin_lock_irqsave(&local->sta_lock, flags); -	/* check if STA exists already */ -	if (sta_info_get_bss(sdata, sta->sta.addr)) { -		spin_unlock_irqrestore(&local->sta_lock, flags); -		mutex_unlock(&local->sta_mtx); -		rcu_read_lock(); -		err = -EEXIST; -		goto out_free; -	} +	if (ieee80211_vif_is_mesh(&sdata->vif)) +		mesh_accept_plinks_update(sdata); -	spin_unlock_irqrestore(&local->sta_lock, flags); +	return 0; + out_remove: +	sta_info_hash_del(local, sta); +	list_del_rcu(&sta->list); +	local->num_sta--; +	synchronize_net(); +	__cleanup_single_sta(sta); + out_err: +	mutex_unlock(&local->sta_mtx); +	rcu_read_lock(); +	return err; +} + +int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) +{ +	struct ieee80211_local *local = sta->local; +	int err; -	err = sta_info_finish_insert(sta, false); +	might_sleep(); + +	err = sta_info_insert_check(sta);  	if (err) { -		mutex_unlock(&local->sta_mtx);  		rcu_read_lock();  		goto out_free;  	} -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG -	wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - -	/* move reference to rcu-protected */ -	rcu_read_lock(); -	mutex_unlock(&local->sta_mtx); +	mutex_lock(&local->sta_mtx); -	if (ieee80211_vif_is_mesh(&sdata->vif)) -		mesh_accept_plinks_update(sdata); +	err = sta_info_insert_finish(sta); +	if (err) +		goto out_free;  	return 0;   out_free: -	BUG_ON(!err); -	__sta_info_free(local, sta); +	sta_info_free(local, sta);  	return err;  } @@ -487,82 +584,138 @@ int sta_info_insert(struct sta_info *sta)  	return err;  } -static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) +static inline void __bss_tim_set(u8 *tim, u16 id)  {  	/*  	 * This format has been mandated by the IEEE specifications,  	 * so this line may not be changed to use the __set_bit() format.  	 */ -	bss->tim[aid / 8] |= (1 << (aid % 8)); +	tim[id / 8] |= (1 << (id % 8));  } -static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid) +static inline void __bss_tim_clear(u8 *tim, u16 id)  {  	/*  	 * This format has been mandated by the IEEE specifications,  	 * so this line may not be changed to use the __clear_bit() format.  	 */ -	bss->tim[aid / 8] &= ~(1 << (aid % 8)); +	tim[id / 8] &= ~(1 << (id % 8));  } -static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, -				   struct sta_info *sta) +static inline bool __bss_tim_get(u8 *tim, u16 id)  { -	BUG_ON(!bss); - -	__bss_tim_set(bss, sta->sta.aid); +	/* +	 * This format has been mandated by the IEEE specifications, +	 * so this line may not be changed to use the test_bit() format. +	 */ +	return tim[id / 8] & (1 << (id % 8)); +} -	if (sta->local->ops->set_tim) { -		sta->local->tim_in_locked_section = true; -		drv_set_tim(sta->local, &sta->sta, true); -		sta->local->tim_in_locked_section = false; +static unsigned long ieee80211_tids_for_ac(int ac) +{ +	/* If we ever support TIDs > 7, this obviously needs to be adjusted */ +	switch (ac) { +	case IEEE80211_AC_VO: +		return BIT(6) | BIT(7); +	case IEEE80211_AC_VI: +		return BIT(4) | BIT(5); +	case IEEE80211_AC_BE: +		return BIT(0) | BIT(3); +	case IEEE80211_AC_BK: +		return BIT(1) | BIT(2); +	default: +		WARN_ON(1); +		return 0;  	}  } -void sta_info_set_tim_bit(struct sta_info *sta) +void sta_info_recalc_tim(struct sta_info *sta)  { -	unsigned long flags; +	struct ieee80211_local *local = sta->local; +	struct ps_data *ps; +	bool indicate_tim = false; +	u8 ignore_for_tim = sta->sta.uapsd_queues; +	int ac; +	u16 id; + +	if (sta->sdata->vif.type == NL80211_IFTYPE_AP || +	    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +		if (WARN_ON_ONCE(!sta->sdata->bss)) +			return; + +		ps = &sta->sdata->bss->ps; +		id = sta->sta.aid; +#ifdef CONFIG_MAC80211_MESH +	} else if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { +		ps = &sta->sdata->u.mesh.ps; +		/* TIM map only for 1 <= PLID <= IEEE80211_MAX_AID */ +		id = sta->plid % (IEEE80211_MAX_AID + 1); +#endif +	} else { +		return; +	} + +	/* No need to do anything if the driver does all */ +	if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) +		return; -	BUG_ON(!sta->sdata->bss); +	if (sta->dead) +		goto done; -	spin_lock_irqsave(&sta->local->sta_lock, flags); -	__sta_info_set_tim_bit(sta->sdata->bss, sta); -	spin_unlock_irqrestore(&sta->local->sta_lock, flags); -} +	/* +	 * If all ACs are delivery-enabled then we should build +	 * the TIM bit for all ACs anyway; if only some are then +	 * we ignore those and build the TIM bit using only the +	 * non-enabled ones. +	 */ +	if (ignore_for_tim == BIT(IEEE80211_NUM_ACS) - 1) +		ignore_for_tim = 0; -static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, -				     struct sta_info *sta) -{ -	BUG_ON(!bss); +	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { +		unsigned long tids; -	__bss_tim_clear(bss, sta->sta.aid); +		if (ignore_for_tim & BIT(ac)) +			continue; + +		indicate_tim |= !skb_queue_empty(&sta->tx_filtered[ac]) || +				!skb_queue_empty(&sta->ps_tx_buf[ac]); +		if (indicate_tim) +			break; + +		tids = ieee80211_tids_for_ac(ac); -	if (sta->local->ops->set_tim) { -		sta->local->tim_in_locked_section = true; -		drv_set_tim(sta->local, &sta->sta, false); -		sta->local->tim_in_locked_section = false; +		indicate_tim |= +			sta->driver_buffered_tids & tids;  	} -} -void sta_info_clear_tim_bit(struct sta_info *sta) -{ -	unsigned long flags; + done: +	spin_lock_bh(&local->tim_lock); -	BUG_ON(!sta->sdata->bss); +	if (indicate_tim == __bss_tim_get(ps->tim, id)) +		goto out_unlock; -	spin_lock_irqsave(&sta->local->sta_lock, flags); -	__sta_info_clear_tim_bit(sta->sdata->bss, sta); -	spin_unlock_irqrestore(&sta->local->sta_lock, flags); +	if (indicate_tim) +		__bss_tim_set(ps->tim, id); +	else +		__bss_tim_clear(ps->tim, id); + +	if (local->ops->set_tim) { +		local->tim_in_locked_section = true; +		drv_set_tim(local, &sta->sta, indicate_tim); +		local->tim_in_locked_section = false; +	} + +out_unlock: +	spin_unlock_bh(&local->tim_lock);  } -static int sta_info_buffer_expired(struct sta_info *sta, -				   struct sk_buff *skb) +static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb)  {  	struct ieee80211_tx_info *info;  	int timeout;  	if (!skb) -		return 0; +		return false;  	info = IEEE80211_SKB_CB(skb); @@ -576,50 +729,107 @@ static int sta_info_buffer_expired(struct sta_info *sta,  } -static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, -					     struct sta_info *sta) +static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, +						struct sta_info *sta, int ac)  {  	unsigned long flags;  	struct sk_buff *skb; -	struct ieee80211_sub_if_data *sdata; -	if (skb_queue_empty(&sta->ps_tx_buf)) -		return false; +	/* +	 * First check for frames that should expire on the filtered +	 * queue. Frames here were rejected by the driver and are on +	 * a separate queue to avoid reordering with normal PS-buffered +	 * frames. They also aren't accounted for right now in the +	 * total_ps_buffered counter. +	 */ +	for (;;) { +		spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); +		skb = skb_peek(&sta->tx_filtered[ac]); +		if (sta_info_buffer_expired(sta, skb)) +			skb = __skb_dequeue(&sta->tx_filtered[ac]); +		else +			skb = NULL; +		spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); + +		/* +		 * Frames are queued in order, so if this one +		 * hasn't expired yet we can stop testing. If +		 * we actually reached the end of the queue we +		 * also need to stop, of course. +		 */ +		if (!skb) +			break; +		ieee80211_free_txskb(&local->hw, skb); +	} +	/* +	 * Now also check the normal PS-buffered queue, this will +	 * only find something if the filtered queue was emptied +	 * since the filtered frames are all before the normal PS +	 * buffered frames. +	 */  	for (;;) { -		spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); -		skb = skb_peek(&sta->ps_tx_buf); +		spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); +		skb = skb_peek(&sta->ps_tx_buf[ac]);  		if (sta_info_buffer_expired(sta, skb)) -			skb = __skb_dequeue(&sta->ps_tx_buf); +			skb = __skb_dequeue(&sta->ps_tx_buf[ac]);  		else  			skb = NULL; -		spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags); +		spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); +		/* +		 * frames are queued in order, so if this one +		 * hasn't expired yet (or we reached the end of +		 * the queue) we can stop testing +		 */  		if (!skb)  			break; -		sdata = sta->sdata;  		local->total_ps_buffered--; -#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG -		printk(KERN_DEBUG "Buffered frame expired (STA %pM)\n", +		ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n",  		       sta->sta.addr); -#endif -		dev_kfree_skb(skb); - -		if (skb_queue_empty(&sta->ps_tx_buf)) -			sta_info_clear_tim_bit(sta); +		ieee80211_free_txskb(&local->hw, skb);  	} -	return true; +	/* +	 * Finally, recalculate the TIM bit for this station -- it might +	 * now be clear because the station was too slow to retrieve its +	 * frames. +	 */ +	sta_info_recalc_tim(sta); + +	/* +	 * Return whether there are any frames still buffered, this is +	 * used to check whether the cleanup timer still needs to run, +	 * if there are no frames we don't need to rearm the timer. +	 */ +	return !(skb_queue_empty(&sta->ps_tx_buf[ac]) && +		 skb_queue_empty(&sta->tx_filtered[ac]));  } -static int __must_check __sta_info_destroy(struct sta_info *sta) +static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, +					     struct sta_info *sta) +{ +	bool have_buffered = false; +	int ac; + +	/* This is only necessary for stations on BSS/MBSS interfaces */ +	if (!sta->sdata->bss && +	    !ieee80211_vif_is_mesh(&sta->sdata->vif)) +		return false; + +	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) +		have_buffered |= +			sta_info_cleanup_expire_buffered_ac(local, sta, ac); + +	return have_buffered; +} + +static int __must_check __sta_info_destroy_part1(struct sta_info *sta)  {  	struct ieee80211_local *local;  	struct ieee80211_sub_if_data *sdata; -	struct sk_buff *skb; -	unsigned long flags; -	int ret, i; +	int ret;  	might_sleep(); @@ -629,91 +839,89 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)  	local = sta->local;  	sdata = sta->sdata; +	lockdep_assert_held(&local->sta_mtx); +  	/*  	 * Before removing the station from the driver and  	 * rate control, it might still start new aggregation  	 * sessions -- block that to make sure the tear-down  	 * will be sufficient.  	 */ -	set_sta_flags(sta, WLAN_STA_BLOCK_BA); -	ieee80211_sta_tear_down_BA_sessions(sta, true); +	set_sta_flag(sta, WLAN_STA_BLOCK_BA); +	ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA); -	spin_lock_irqsave(&local->sta_lock, flags);  	ret = sta_info_hash_del(local, sta); -	/* this might still be the pending list ... which is fine */ -	if (!ret) -		list_del(&sta->list); -	spin_unlock_irqrestore(&local->sta_lock, flags); -	if (ret) +	if (WARN_ON(ret))  		return ret; -	for (i = 0; i < NUM_DEFAULT_KEYS; i++) -		ieee80211_key_free(local, sta->gtk[i]); -	if (sta->ptk) -		ieee80211_key_free(local, sta->ptk); +	list_del_rcu(&sta->list); -	sta->dead = true; +	drv_sta_pre_rcu_remove(local, sta->sdata, sta); -	if (test_and_clear_sta_flags(sta, -				WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { -		BUG_ON(!sdata->bss); +	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && +	    rcu_access_pointer(sdata->u.vlan.sta) == sta) +		RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); -		atomic_dec(&sdata->bss->num_sta_ps); -		__sta_info_clear_tim_bit(sdata->bss, sta); -	} +	return 0; +} + +static void __sta_info_destroy_part2(struct sta_info *sta) +{ +	struct ieee80211_local *local = sta->local; +	struct ieee80211_sub_if_data *sdata = sta->sdata; +	int ret; + +	/* +	 * NOTE: This assumes at least synchronize_net() was done +	 *	 after _part1 and before _part2! +	 */ + +	might_sleep(); +	lockdep_assert_held(&local->sta_mtx); + +	/* now keys can no longer be reached */ +	ieee80211_free_sta_keys(local, sta); + +	sta->dead = true;  	local->num_sta--;  	local->sta_generation++; -	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -		rcu_assign_pointer(sdata->u.vlan.sta, NULL); +	while (sta->sta_state > IEEE80211_STA_NONE) { +		ret = sta_info_move_state(sta, sta->sta_state - 1); +		if (ret) { +			WARN_ON_ONCE(1); +			break; +		} +	}  	if (sta->uploaded) { -		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -			sdata = container_of(sdata->bss, -					     struct ieee80211_sub_if_data, -					     u.ap); -		drv_sta_remove(local, sdata, &sta->sta); -		sdata = sta->sdata; +		ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE, +				    IEEE80211_STA_NOTEXIST); +		WARN_ON_ONCE(ret != 0);  	} -	/* -	 * At this point, after we wait for an RCU grace period, -	 * neither mac80211 nor the driver can reference this -	 * sta struct any more except by still existing timers -	 * associated with this station that we clean up below. -	 */ -	synchronize_rcu(); - -#ifdef CONFIG_MAC80211_MESH -	if (ieee80211_vif_is_mesh(&sdata->vif)) -		mesh_accept_plinks_update(sdata); -#endif +	sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr); -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG -	wiphy_debug(local->hw.wiphy, "Removed STA %pM\n", sta->sta.addr); -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ -	cancel_work_sync(&sta->drv_unblock_wk); +	cfg80211_del_sta(sdata->dev, sta->sta.addr, GFP_KERNEL);  	rate_control_remove_sta_debugfs(sta);  	ieee80211_sta_debugfs_remove(sta); +	ieee80211_recalc_min_chandef(sdata); -#ifdef CONFIG_MAC80211_MESH -	if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { -		mesh_plink_deactivate(sta); -		del_timer_sync(&sta->plink_timer); -	} -#endif +	cleanup_single_sta(sta); +} -	while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { -		local->total_ps_buffered--; -		dev_kfree_skb_any(skb); -	} +int __must_check __sta_info_destroy(struct sta_info *sta) +{ +	int err = __sta_info_destroy_part1(sta); -	while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) -		dev_kfree_skb_any(skb); +	if (err) +		return err; -	__sta_info_free(local, sta); +	synchronize_net(); + +	__sta_info_destroy_part2(sta);  	return 0;  } @@ -763,60 +971,52 @@ static void sta_info_cleanup(unsigned long data)  	if (!timer_needed)  		return; -	local->sta_cleanup.expires = -		round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); -	add_timer(&local->sta_cleanup); +	mod_timer(&local->sta_cleanup, +		  round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL));  }  void sta_info_init(struct ieee80211_local *local)  { -	spin_lock_init(&local->sta_lock); +	spin_lock_init(&local->tim_lock);  	mutex_init(&local->sta_mtx);  	INIT_LIST_HEAD(&local->sta_list); -	INIT_LIST_HEAD(&local->sta_pending_list); -	INIT_WORK(&local->sta_finish_work, sta_info_finish_work);  	setup_timer(&local->sta_cleanup, sta_info_cleanup,  		    (unsigned long)local); -	local->sta_cleanup.expires = -		round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); -} - -int sta_info_start(struct ieee80211_local *local) -{ -	add_timer(&local->sta_cleanup); -	return 0;  }  void sta_info_stop(struct ieee80211_local *local)  { -	del_timer(&local->sta_cleanup); -	sta_info_flush(local, NULL); +	del_timer_sync(&local->sta_cleanup);  } -/** - * sta_info_flush - flush matching STA entries from the STA table - * - * Returns the number of removed STA entries. - * - * @local: local interface data - * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs - */ -int sta_info_flush(struct ieee80211_local *local, -		   struct ieee80211_sub_if_data *sdata) + +int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans)  { +	struct ieee80211_local *local = sdata->local;  	struct sta_info *sta, *tmp; +	LIST_HEAD(free_list);  	int ret = 0;  	might_sleep(); -	mutex_lock(&local->sta_mtx); - -	sta_info_finish_pending(local); +	WARN_ON(vlans && sdata->vif.type != NL80211_IFTYPE_AP); +	WARN_ON(vlans && !sdata->bss); +	mutex_lock(&local->sta_mtx);  	list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { -		if (!sdata || sdata == sta->sdata) -			WARN_ON(__sta_info_destroy(sta)); +		if (sdata == sta->sdata || +		    (vlans && sdata->bss == sta->sdata->bss)) { +			if (!WARN_ON(__sta_info_destroy_part1(sta))) +				list_add(&sta->free_list, &free_list); +			ret++; +		} +	} + +	if (!list_empty(&free_list)) { +		synchronize_net(); +		list_for_each_entry_safe(sta, tmp, &free_list, free_list) +			__sta_info_destroy_part2(sta);  	}  	mutex_unlock(&local->sta_mtx); @@ -830,14 +1030,23 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,  	struct sta_info *sta, *tmp;  	mutex_lock(&local->sta_mtx); -	list_for_each_entry_safe(sta, tmp, &local->sta_list, list) + +	list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { +		if (sdata != sta->sdata) +			continue; +  		if (time_after(jiffies, sta->last_rx + exp_time)) { -#ifdef CONFIG_MAC80211_IBSS_DEBUG -			printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", -			       sdata->name, sta->sta.addr); -#endif +			sta_dbg(sta->sdata, "expiring inactive STA %pM\n", +				sta->sta.addr); + +			if (ieee80211_vif_is_mesh(&sdata->vif) && +			    test_sta_flag(sta, WLAN_STA_PS_STA)) +				atomic_dec(&sdata->u.mesh.ps.num_sta_ps); +  			WARN_ON(__sta_info_destroy(sta));  		} +	} +  	mutex_unlock(&local->sta_mtx);  } @@ -853,7 +1062,7 @@ struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,  	 */  	for_each_sta_info(hw_to_local(hw), addr, sta, nxt) {  		if (localaddr && -		    compare_ether_addr(sta->sdata->vif.addr, localaddr) != 0) +		    !ether_addr_equal(sta->sdata->vif.addr, localaddr))  			continue;  		if (!sta->uploaded)  			return NULL; @@ -883,96 +1092,448 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,  }  EXPORT_SYMBOL(ieee80211_find_sta); -static void clear_sta_ps_flags(void *_sta) -{ -	struct sta_info *sta = _sta; - -	clear_sta_flags(sta, WLAN_STA_PS_DRIVER | WLAN_STA_PS_STA); -} -  /* powersave support code */  void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)  {  	struct ieee80211_sub_if_data *sdata = sta->sdata;  	struct ieee80211_local *local = sdata->local; -	int sent, buffered; +	struct sk_buff_head pending; +	int filtered = 0, buffered = 0, ac; +	unsigned long flags; +	struct ps_data *ps; + +	if (sdata->vif.type == NL80211_IFTYPE_AP || +	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +		ps = &sdata->bss->ps; +	else if (ieee80211_vif_is_mesh(&sdata->vif)) +		ps = &sdata->u.mesh.ps; +	else +		return; + +	clear_sta_flag(sta, WLAN_STA_SP); -	drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); +	BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); +	sta->driver_buffered_tids = 0; -	if (!skb_queue_empty(&sta->ps_tx_buf)) -		sta_info_clear_tim_bit(sta); +	if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) +		drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); +	skb_queue_head_init(&pending); + +	/* sync with ieee80211_tx_h_unicast_ps_buf */ +	spin_lock(&sta->ps_lock);  	/* Send all buffered frames to the station */ -	sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); -	buffered = ieee80211_add_pending_skbs_fn(local, &sta->ps_tx_buf, -						 clear_sta_ps_flags, sta); -	sent += buffered; +	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { +		int count = skb_queue_len(&pending), tmp; + +		spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); +		skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending); +		spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); +		tmp = skb_queue_len(&pending); +		filtered += tmp - count; +		count = tmp; + +		spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); +		skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending); +		spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); +		tmp = skb_queue_len(&pending); +		buffered += tmp - count; +	} + +	ieee80211_add_pending_skbs(local, &pending); +	clear_sta_flag(sta, WLAN_STA_PS_DRIVER); +	clear_sta_flag(sta, WLAN_STA_PS_STA); +	spin_unlock(&sta->ps_lock); + +	atomic_dec(&ps->num_sta_ps); + +	/* This station just woke up and isn't aware of our SMPS state */ +	if (!ieee80211_vif_is_mesh(&sdata->vif) && +	    !ieee80211_smps_is_restrictive(sta->known_smps_mode, +					   sdata->smps_mode) && +	    sta->known_smps_mode != sdata->bss->req_smps && +	    sta_info_tx_streams(sta) != 1) { +		ht_dbg(sdata, +		       "%pM just woke up and MIMO capable - update SMPS\n", +		       sta->sta.addr); +		ieee80211_send_smps_action(sdata, sdata->bss->req_smps, +					   sta->sta.addr, +					   sdata->vif.bss_conf.bssid); +	} +  	local->total_ps_buffered -= buffered; -#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG -	printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " -	       "since STA not sleeping anymore\n", sdata->name, -	       sta->sta.addr, sta->sta.aid, sent - buffered, buffered); -#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ +	sta_info_recalc_tim(sta); + +	ps_dbg(sdata, +	       "STA %pM aid %d sending %d filtered/%d PS frames since STA not sleeping anymore\n", +	       sta->sta.addr, sta->sta.aid, filtered, buffered);  } -void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) +static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, +					 struct sta_info *sta, int tid, +					 enum ieee80211_frame_release_type reason, +					 bool call_driver)  { -	struct ieee80211_sub_if_data *sdata = sta->sdata;  	struct ieee80211_local *local = sdata->local; +	struct ieee80211_qos_hdr *nullfunc;  	struct sk_buff *skb; -	int no_pending_pkts; +	int size = sizeof(*nullfunc); +	__le16 fc; +	bool qos = test_sta_flag(sta, WLAN_STA_WME); +	struct ieee80211_tx_info *info; +	struct ieee80211_chanctx_conf *chanctx_conf; -	skb = skb_dequeue(&sta->tx_filtered); -	if (!skb) { -		skb = skb_dequeue(&sta->ps_tx_buf); -		if (skb) -			local->total_ps_buffered--; +	if (qos) { +		fc = cpu_to_le16(IEEE80211_FTYPE_DATA | +				 IEEE80211_STYPE_QOS_NULLFUNC | +				 IEEE80211_FCTL_FROMDS); +	} else { +		size -= 2; +		fc = cpu_to_le16(IEEE80211_FTYPE_DATA | +				 IEEE80211_STYPE_NULLFUNC | +				 IEEE80211_FCTL_FROMDS);  	} -	no_pending_pkts = skb_queue_empty(&sta->tx_filtered) && -		skb_queue_empty(&sta->ps_tx_buf); -	if (skb) { -		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -		struct ieee80211_hdr *hdr = -			(struct ieee80211_hdr *) skb->data; +	skb = dev_alloc_skb(local->hw.extra_tx_headroom + size); +	if (!skb) +		return; + +	skb_reserve(skb, local->hw.extra_tx_headroom); + +	nullfunc = (void *) skb_put(skb, size); +	nullfunc->frame_control = fc; +	nullfunc->duration_id = 0; +	memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); +	memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); +	memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); +	nullfunc->seq_ctrl = 0; + +	skb->priority = tid; +	skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); +	if (qos) { +		nullfunc->qos_ctrl = cpu_to_le16(tid); + +		if (reason == IEEE80211_FRAME_RELEASE_UAPSD) +			nullfunc->qos_ctrl |= +				cpu_to_le16(IEEE80211_QOS_CTL_EOSP); +	} + +	info = IEEE80211_SKB_CB(skb); + +	/* +	 * Tell TX path to send this frame even though the +	 * STA may still remain is PS mode after this frame +	 * exchange. Also set EOSP to indicate this packet +	 * ends the poll/service period. +	 */ +	info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER | +		       IEEE80211_TX_CTL_PS_RESPONSE | +		       IEEE80211_TX_STATUS_EOSP | +		       IEEE80211_TX_CTL_REQ_TX_STATUS; + +	if (call_driver) +		drv_allow_buffered_frames(local, sta, BIT(tid), 1, +					  reason, false); + +	skb->dev = sdata->dev; + +	rcu_read_lock(); +	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); +	if (WARN_ON(!chanctx_conf)) { +		rcu_read_unlock(); +		kfree_skb(skb); +		return; +	} + +	ieee80211_xmit(sdata, skb, chanctx_conf->def.chan->band); +	rcu_read_unlock(); +} + +static int find_highest_prio_tid(unsigned long tids) +{ +	/* lower 3 TIDs aren't ordered perfectly */ +	if (tids & 0xF8) +		return fls(tids) - 1; +	/* TID 0 is BE just like TID 3 */ +	if (tids & BIT(0)) +		return 0; +	return fls(tids) - 1; +} + +static void +ieee80211_sta_ps_deliver_response(struct sta_info *sta, +				  int n_frames, u8 ignored_acs, +				  enum ieee80211_frame_release_type reason) +{ +	struct ieee80211_sub_if_data *sdata = sta->sdata; +	struct ieee80211_local *local = sdata->local; +	bool more_data = false; +	int ac; +	unsigned long driver_release_tids = 0; +	struct sk_buff_head frames; + +	/* Service or PS-Poll period starts */ +	set_sta_flag(sta, WLAN_STA_SP); + +	__skb_queue_head_init(&frames); + +	/* Get response frame(s) and more data bit for the last one. */ +	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { +		unsigned long tids; + +		if (ignored_acs & BIT(ac)) +			continue; + +		tids = ieee80211_tids_for_ac(ac); + +		/* if we already have frames from software, then we can't also +		 * release from hardware queues +		 */ +		if (skb_queue_empty(&frames)) +			driver_release_tids |= sta->driver_buffered_tids & tids; + +		if (driver_release_tids) { +			/* If the driver has data on more than one TID then +			 * certainly there's more data if we release just a +			 * single frame now (from a single TID). This will +			 * only happen for PS-Poll. +			 */ +			if (reason == IEEE80211_FRAME_RELEASE_PSPOLL && +			    hweight16(driver_release_tids) > 1) { +				more_data = true; +				driver_release_tids = +					BIT(find_highest_prio_tid( +						driver_release_tids)); +				break; +			} +		} else { +			struct sk_buff *skb; + +			while (n_frames > 0) { +				skb = skb_dequeue(&sta->tx_filtered[ac]); +				if (!skb) { +					skb = skb_dequeue( +						&sta->ps_tx_buf[ac]); +					if (skb) +						local->total_ps_buffered--; +				} +				if (!skb) +					break; +				n_frames--; +				__skb_queue_tail(&frames, skb); +			} +		} + +		/* If we have more frames buffered on this AC, then set the +		 * more-data bit and abort the loop since we can't send more +		 * data from other ACs before the buffered frames from this. +		 */ +		if (!skb_queue_empty(&sta->tx_filtered[ac]) || +		    !skb_queue_empty(&sta->ps_tx_buf[ac])) { +			more_data = true; +			break; +		} +	} + +	if (skb_queue_empty(&frames) && !driver_release_tids) { +		int tid;  		/* -		 * Tell TX path to send this frame even though the STA may -		 * still remain is PS mode after this frame exchange. +		 * For PS-Poll, this can only happen due to a race condition +		 * when we set the TIM bit and the station notices it, but +		 * before it can poll for the frame we expire it. +		 * +		 * For uAPSD, this is said in the standard (11.2.1.5 h): +		 *	At each unscheduled SP for a non-AP STA, the AP shall +		 *	attempt to transmit at least one MSDU or MMPDU, but no +		 *	more than the value specified in the Max SP Length field +		 *	in the QoS Capability element from delivery-enabled ACs, +		 *	that are destined for the non-AP STA. +		 * +		 * Since we have no other MSDU/MMPDU, transmit a QoS null frame.  		 */ -		info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE; - -#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG -		printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n", -		       sta->sta.addr, sta->sta.aid, -		       skb_queue_len(&sta->ps_tx_buf)); -#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - -		/* Use MoreData flag to indicate whether there are more -		 * buffered frames for this STA */ -		if (no_pending_pkts) -			hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA); -		else -			hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); -		ieee80211_add_pending_skb(local, skb); +		/* This will evaluate to 1, 3, 5 or 7. */ +		tid = 7 - ((ffs(~ignored_acs) - 1) << 1); + +		ieee80211_send_null_response(sdata, sta, tid, reason, true); +	} else if (!driver_release_tids) { +		struct sk_buff_head pending; +		struct sk_buff *skb; +		int num = 0; +		u16 tids = 0; +		bool need_null = false; + +		skb_queue_head_init(&pending); + +		while ((skb = __skb_dequeue(&frames))) { +			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +			struct ieee80211_hdr *hdr = (void *) skb->data; +			u8 *qoshdr = NULL; + +			num++; + +			/* +			 * Tell TX path to send this frame even though the +			 * STA may still remain is PS mode after this frame +			 * exchange. +			 */ +			info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER | +				       IEEE80211_TX_CTL_PS_RESPONSE; + +			/* +			 * Use MoreData flag to indicate whether there are +			 * more buffered frames for this STA +			 */ +			if (more_data || !skb_queue_empty(&frames)) +				hdr->frame_control |= +					cpu_to_le16(IEEE80211_FCTL_MOREDATA); +			else +				hdr->frame_control &= +					cpu_to_le16(~IEEE80211_FCTL_MOREDATA); + +			if (ieee80211_is_data_qos(hdr->frame_control) || +			    ieee80211_is_qos_nullfunc(hdr->frame_control)) +				qoshdr = ieee80211_get_qos_ctl(hdr); + +			tids |= BIT(skb->priority); + +			__skb_queue_tail(&pending, skb); + +			/* end service period after last frame or add one */ +			if (!skb_queue_empty(&frames)) +				continue; + +			if (reason != IEEE80211_FRAME_RELEASE_UAPSD) { +				/* for PS-Poll, there's only one frame */ +				info->flags |= IEEE80211_TX_STATUS_EOSP | +					       IEEE80211_TX_CTL_REQ_TX_STATUS; +				break; +			} + +			/* For uAPSD, things are a bit more complicated. If the +			 * last frame has a QoS header (i.e. is a QoS-data or +			 * QoS-nulldata frame) then just set the EOSP bit there +			 * and be done. +			 * If the frame doesn't have a QoS header (which means +			 * it should be a bufferable MMPDU) then we can't set +			 * the EOSP bit in the QoS header; add a QoS-nulldata +			 * frame to the list to send it after the MMPDU. +			 * +			 * Note that this code is only in the mac80211-release +			 * code path, we assume that the driver will not buffer +			 * anything but QoS-data frames, or if it does, will +			 * create the QoS-nulldata frame by itself if needed. +			 * +			 * Cf. 802.11-2012 10.2.1.10 (c). +			 */ +			if (qoshdr) { +				*qoshdr |= IEEE80211_QOS_CTL_EOSP; + +				info->flags |= IEEE80211_TX_STATUS_EOSP | +					       IEEE80211_TX_CTL_REQ_TX_STATUS; +			} else { +				/* The standard isn't completely clear on this +				 * as it says the more-data bit should be set +				 * if there are more BUs. The QoS-Null frame +				 * we're about to send isn't buffered yet, we +				 * only create it below, but let's pretend it +				 * was buffered just in case some clients only +				 * expect more-data=0 when eosp=1. +				 */ +				hdr->frame_control |= +					cpu_to_le16(IEEE80211_FCTL_MOREDATA); +				need_null = true; +				num++; +			} +			break; +		} + +		drv_allow_buffered_frames(local, sta, tids, num, +					  reason, more_data); -		if (no_pending_pkts) -			sta_info_clear_tim_bit(sta); -#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG +		ieee80211_add_pending_skbs(local, &pending); + +		if (need_null) +			ieee80211_send_null_response( +				sdata, sta, find_highest_prio_tid(tids), +				reason, false); + +		sta_info_recalc_tim(sta);  	} else {  		/* -		 * FIXME: This can be the result of a race condition between -		 *	  us expiring a frame and the station polling for it. -		 *	  Should we send it a null-func frame indicating we -		 *	  have nothing buffered for it? +		 * We need to release a frame that is buffered somewhere in the +		 * driver ... it'll have to handle that. +		 * Note that the driver also has to check the number of frames +		 * on the TIDs we're releasing from - if there are more than +		 * n_frames it has to set the more-data bit (if we didn't ask +		 * it to set it anyway due to other buffered frames); if there +		 * are fewer than n_frames it has to make sure to adjust that +		 * to allow the service period to end properly.  		 */ -		printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " -		       "though there are no buffered frames for it\n", -		       sdata->name, sta->sta.addr); -#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ +		drv_release_buffered_frames(local, sta, driver_release_tids, +					    n_frames, reason, more_data); + +		/* +		 * Note that we don't recalculate the TIM bit here as it would +		 * most likely have no effect at all unless the driver told us +		 * that the TID(s) became empty before returning here from the +		 * release function. +		 * Either way, however, when the driver tells us that the TID(s) +		 * became empty we'll do the TIM recalculation. +		 */ +	} +} + +void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) +{ +	u8 ignore_for_response = sta->sta.uapsd_queues; + +	/* +	 * If all ACs are delivery-enabled then we should reply +	 * from any of them, if only some are enabled we reply +	 * only from the non-enabled ones. +	 */ +	if (ignore_for_response == BIT(IEEE80211_NUM_ACS) - 1) +		ignore_for_response = 0; + +	ieee80211_sta_ps_deliver_response(sta, 1, ignore_for_response, +					  IEEE80211_FRAME_RELEASE_PSPOLL); +} + +void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta) +{ +	int n_frames = sta->sta.max_sp; +	u8 delivery_enabled = sta->sta.uapsd_queues; + +	/* +	 * If we ever grow support for TSPEC this might happen if +	 * the TSPEC update from hostapd comes in between a trigger +	 * frame setting WLAN_STA_UAPSD in the RX path and this +	 * actually getting called. +	 */ +	if (!delivery_enabled) +		return; + +	switch (sta->sta.max_sp) { +	case 1: +		n_frames = 2; +		break; +	case 2: +		n_frames = 4; +		break; +	case 3: +		n_frames = 6; +		break; +	case 0: +		/* XXX: what is a good value? */ +		n_frames = 8; +		break;  	} + +	ieee80211_sta_ps_deliver_response(sta, n_frames, ~delivery_enabled, +					  IEEE80211_FRAME_RELEASE_UAPSD);  }  void ieee80211_sta_block_awake(struct ieee80211_hw *hw, @@ -983,8 +1544,163 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,  	trace_api_sta_block_awake(sta->local, pubsta, block);  	if (block) -		set_sta_flags(sta, WLAN_STA_PS_DRIVER); -	else if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) +		set_sta_flag(sta, WLAN_STA_PS_DRIVER); +	else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER))  		ieee80211_queue_work(hw, &sta->drv_unblock_wk);  }  EXPORT_SYMBOL(ieee80211_sta_block_awake); + +void ieee80211_sta_eosp(struct ieee80211_sta *pubsta) +{ +	struct sta_info *sta = container_of(pubsta, struct sta_info, sta); +	struct ieee80211_local *local = sta->local; + +	trace_api_eosp(local, pubsta); + +	clear_sta_flag(sta, WLAN_STA_SP); +} +EXPORT_SYMBOL(ieee80211_sta_eosp); + +void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, +				u8 tid, bool buffered) +{ +	struct sta_info *sta = container_of(pubsta, struct sta_info, sta); + +	if (WARN_ON(tid >= IEEE80211_NUM_TIDS)) +		return; + +	trace_api_sta_set_buffered(sta->local, pubsta, tid, buffered); + +	if (buffered) +		set_bit(tid, &sta->driver_buffered_tids); +	else +		clear_bit(tid, &sta->driver_buffered_tids); + +	sta_info_recalc_tim(sta); +} +EXPORT_SYMBOL(ieee80211_sta_set_buffered); + +int sta_info_move_state(struct sta_info *sta, +			enum ieee80211_sta_state new_state) +{ +	might_sleep(); + +	if (sta->sta_state == new_state) +		return 0; + +	/* check allowed transitions first */ + +	switch (new_state) { +	case IEEE80211_STA_NONE: +		if (sta->sta_state != IEEE80211_STA_AUTH) +			return -EINVAL; +		break; +	case IEEE80211_STA_AUTH: +		if (sta->sta_state != IEEE80211_STA_NONE && +		    sta->sta_state != IEEE80211_STA_ASSOC) +			return -EINVAL; +		break; +	case IEEE80211_STA_ASSOC: +		if (sta->sta_state != IEEE80211_STA_AUTH && +		    sta->sta_state != IEEE80211_STA_AUTHORIZED) +			return -EINVAL; +		break; +	case IEEE80211_STA_AUTHORIZED: +		if (sta->sta_state != IEEE80211_STA_ASSOC) +			return -EINVAL; +		break; +	default: +		WARN(1, "invalid state %d", new_state); +		return -EINVAL; +	} + +	sta_dbg(sta->sdata, "moving STA %pM to state %d\n", +		sta->sta.addr, new_state); + +	/* +	 * notify the driver before the actual changes so it can +	 * fail the transition +	 */ +	if (test_sta_flag(sta, WLAN_STA_INSERTED)) { +		int err = drv_sta_state(sta->local, sta->sdata, sta, +					sta->sta_state, new_state); +		if (err) +			return err; +	} + +	/* reflect the change in all state variables */ + +	switch (new_state) { +	case IEEE80211_STA_NONE: +		if (sta->sta_state == IEEE80211_STA_AUTH) +			clear_bit(WLAN_STA_AUTH, &sta->_flags); +		break; +	case IEEE80211_STA_AUTH: +		if (sta->sta_state == IEEE80211_STA_NONE) +			set_bit(WLAN_STA_AUTH, &sta->_flags); +		else if (sta->sta_state == IEEE80211_STA_ASSOC) +			clear_bit(WLAN_STA_ASSOC, &sta->_flags); +		break; +	case IEEE80211_STA_ASSOC: +		if (sta->sta_state == IEEE80211_STA_AUTH) { +			set_bit(WLAN_STA_ASSOC, &sta->_flags); +		} else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) { +			if (sta->sdata->vif.type == NL80211_IFTYPE_AP || +			    (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && +			     !sta->sdata->u.vlan.sta)) +				atomic_dec(&sta->sdata->bss->num_mcast_sta); +			clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); +		} +		break; +	case IEEE80211_STA_AUTHORIZED: +		if (sta->sta_state == IEEE80211_STA_ASSOC) { +			if (sta->sdata->vif.type == NL80211_IFTYPE_AP || +			    (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && +			     !sta->sdata->u.vlan.sta)) +				atomic_inc(&sta->sdata->bss->num_mcast_sta); +			set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); +		} +		break; +	default: +		break; +	} + +	sta->sta_state = new_state; + +	return 0; +} + +u8 sta_info_tx_streams(struct sta_info *sta) +{ +	struct ieee80211_sta_ht_cap *ht_cap = &sta->sta.ht_cap; +	u8 rx_streams; + +	if (!sta->sta.ht_cap.ht_supported) +		return 1; + +	if (sta->sta.vht_cap.vht_supported) { +		int i; +		u16 tx_mcs_map = +			le16_to_cpu(sta->sta.vht_cap.vht_mcs.tx_mcs_map); + +		for (i = 7; i >= 0; i--) +			if ((tx_mcs_map & (0x3 << (i * 2))) != +			    IEEE80211_VHT_MCS_NOT_SUPPORTED) +				return i + 1; +	} + +	if (ht_cap->mcs.rx_mask[3]) +		rx_streams = 4; +	else if (ht_cap->mcs.rx_mask[2]) +		rx_streams = 3; +	else if (ht_cap->mcs.rx_mask[1]) +		rx_streams = 2; +	else +		rx_streams = 1; + +	if (!(ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_RX_DIFF)) +		return rx_streams; + +	return ((ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) +			>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; +}  | 
