Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d421c62e authored by John W. Linville's avatar John W. Linville
Browse files
parents 4885c873 e3685e03
Loading
Loading
Loading
Loading
+2 −8
Original line number Diff line number Diff line
@@ -1692,14 +1692,8 @@ void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
void ieee80211_add_pending_skb(struct ieee80211_local *local,
			       struct sk_buff *skb);
void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
				   struct sk_buff_head *skbs,
				   void (*fn)(void *data), void *data);
static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
					      struct sk_buff_head *skbs)
{
	ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL);
}
void ieee80211_add_pending_skbs(struct ieee80211_local *local,
				struct sk_buff_head *skbs);
void ieee80211_flush_queues(struct ieee80211_local *local,
			    struct ieee80211_sub_if_data *sdata);

+1 −0
Original line number Diff line number Diff line
@@ -3753,6 +3753,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
		if (WARN_ON(!chanctx_conf)) {
			rcu_read_unlock();
			sta_info_free(local, new_sta);
			return -EINVAL;
		}
		rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
+7 −0
Original line number Diff line number Diff line
@@ -1128,6 +1128,13 @@ static void sta_ps_end(struct sta_info *sta)
	       sta->sta.addr, sta->sta.aid);

	if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
		/*
		 * Clear the flag only if the other one is still set
		 * so that the TX path won't start TX'ing new frames
		 * directly ... In the case that the driver flag isn't
		 * set ieee80211_sta_ps_deliver_wakeup() will clear it.
		 */
		clear_sta_flag(sta, WLAN_STA_PS_STA);
		ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n",
		       sta->sta.addr, sta->sta.aid);
		return;
+42 −24
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
	return -ENOENT;
}

static void cleanup_single_sta(struct sta_info *sta)
static void __cleanup_single_sta(struct sta_info *sta)
{
	int ac, i;
	struct tid_ampdu_tx *tid_tx;
@@ -99,7 +99,8 @@ static void cleanup_single_sta(struct sta_info *sta)
	struct ieee80211_local *local = sdata->local;
	struct ps_data *ps;

	if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
	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;
@@ -109,6 +110,7 @@ static void cleanup_single_sta(struct sta_info *sta)
			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);
@@ -139,7 +141,14 @@ static void cleanup_single_sta(struct sta_info *sta)
		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);
}

@@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
	rcu_read_unlock();

	spin_lock_init(&sta->lock);
	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);
@@ -487,21 +497,26 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
		goto out_err;
	}

	/* notify driver */
	err = sta_info_insert_drv_state(local, sdata, sta);
	if (err)
		goto out_err;

	local->num_sta++;
	local->sta_generation++;
	smp_mb();

	/* simplify things and don't accept BA sessions yet */
	set_sta_flag(sta, WLAN_STA_BLOCK_BA);

	/* make the station visible */
	sta_info_hash_add(local, sta);

	list_add_rcu(&sta->list, &local->sta_list);

	/* notify driver */
	err = sta_info_insert_drv_state(local, sdata, sta);
	if (err)
		goto out_remove;

	set_sta_flag(sta, WLAN_STA_INSERTED);
	/* accept BA sessions now */
	clear_sta_flag(sta, WLAN_STA_BLOCK_BA);

	ieee80211_recalc_min_chandef(sdata);
	ieee80211_sta_debugfs_add(sta);
@@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
		mesh_accept_plinks_update(sdata);

	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();
@@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
}
EXPORT_SYMBOL(ieee80211_find_sta);

static void clear_sta_ps_flags(void *_sta)
/* powersave support code */
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
{
	struct sta_info *sta = _sta;
	struct ieee80211_sub_if_data *sdata = sta->sdata;
	struct ieee80211_local *local = sdata->local;
	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 ||
@@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_sta)
	else
		return;

	clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
	if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA))
		atomic_dec(&ps->num_sta_ps);
}

/* 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;
	struct sk_buff_head pending;
	int filtered = 0, buffered = 0, ac;
	unsigned long flags;

	clear_sta_flag(sta, WLAN_STA_SP);

	BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
@@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *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 */
	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
		int count = skb_queue_len(&pending), tmp;
@@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
		buffered += tmp - count;
	}

	ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta);
	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_smps_is_restrictive(sta->known_smps_mode,
+3 −4
Original line number Diff line number Diff line
@@ -267,6 +267,7 @@ struct ieee80211_tx_latency_stat {
 * @drv_unblock_wk: used for driver PS unblocking
 * @listen_interval: listen interval of this station, when we're acting as AP
 * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
 * @ps_lock: used for powersave (when mac80211 is the AP) related locking
 * @ps_tx_buf: buffers (per AC) of frames to transmit to this station
 *	when it leaves power saving state or polls
 * @tx_filtered: buffers (per AC) of frames we already tried to
@@ -356,10 +357,8 @@ struct sta_info {
	/* use the accessors defined below */
	unsigned long _flags;

	/*
	 * STA powersave frame queues, no more than the internal
	 * locking required.
	 */
	/* STA powersave lock and frame queues */
	spinlock_t ps_lock;
	struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
	struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
	unsigned long driver_buffered_tids;
Loading