Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright 2012-2013, Marco Porsch <marco.porsch@s2005.tu-chemnitz.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright 2012-2013, cozybit Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2021 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include "mesh.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include "wme.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) /* mesh PS management */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * mps_qos_null_get - create pre-addressed QoS Null frame for mesh powersave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * @sta: the station to get the frame for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) static struct sk_buff *mps_qos_null_get(struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	struct ieee80211_hdr *nullfunc; /* use 4addr header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	int size = sizeof(*nullfunc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	__le16 fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	skb = dev_alloc_skb(local->hw.extra_tx_headroom + size + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	skb_reserve(skb, local->hw.extra_tx_headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	nullfunc = skb_put(skb, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	ieee80211_fill_mesh_addresses(nullfunc, &fc, sta->sta.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 				      sdata->vif.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	nullfunc->frame_control = fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	nullfunc->duration_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	nullfunc->seq_ctrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	/* no address resolution for this frame -> set addr 1 immediately */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	skb_put_zero(skb, 2); /* append QoS control field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	ieee80211_mps_set_frame_flags(sdata, sta, nullfunc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * mps_qos_null_tx - send a QoS Null to indicate link-specific power mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * @sta: the station to send to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) static void mps_qos_null_tx(struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	skb = mps_qos_null_get(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	mps_dbg(sta->sdata, "announcing peer-specific power mode to %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	/* don't unintentionally start a MPSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		u8 *qc = ieee80211_get_qos_ctl((void *) skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		qc[0] |= IEEE80211_QOS_CTL_EOSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	ieee80211_tx_skb(sta->sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * ieee80211_mps_local_status_update - track status of local link-specific PMs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * @sdata: local mesh subif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  * sets the non-peer power mode and triggers the driver PS (re-)configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  * Return BSS_CHANGED_BEACON if a beacon update is necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) u32 ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	bool peering = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	int light_sleep_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	int deep_sleep_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	u32 changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	enum nl80211_mesh_power_mode nonpeer_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		if (sdata != sta->sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		switch (sta->mesh->plink_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		case NL80211_PLINK_OPN_SNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		case NL80211_PLINK_OPN_RCVD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		case NL80211_PLINK_CNF_RCVD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 			peering = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		case NL80211_PLINK_ESTAB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 			if (sta->mesh->local_pm == NL80211_MESH_POWER_LIGHT_SLEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 				light_sleep_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			else if (sta->mesh->local_pm == NL80211_MESH_POWER_DEEP_SLEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 				deep_sleep_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	 * Set non-peer mode to active during peering/scanning/authentication
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	 * (see IEEE802.11-2012 13.14.8.3). The non-peer mesh power mode is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	 * deep sleep if the local STA is in light or deep sleep towards at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	 * least one mesh peer (see 13.14.3.1). Otherwise, set it to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	 * user-configured default value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	if (peering) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		mps_dbg(sdata, "setting non-peer PM to active for peering\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		nonpeer_pm = NL80211_MESH_POWER_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	} else if (light_sleep_cnt || deep_sleep_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		mps_dbg(sdata, "setting non-peer PM to deep sleep\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		nonpeer_pm = NL80211_MESH_POWER_DEEP_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		mps_dbg(sdata, "setting non-peer PM to user value\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		nonpeer_pm = ifmsh->mshcfg.power_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	/* need update if sleep counts move between 0 and non-zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	if (ifmsh->nonpeer_pm != nonpeer_pm ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	    !ifmsh->ps_peers_light_sleep != !light_sleep_cnt ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	    !ifmsh->ps_peers_deep_sleep != !deep_sleep_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		changed = BSS_CHANGED_BEACON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	ifmsh->nonpeer_pm = nonpeer_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	ifmsh->ps_peers_light_sleep = light_sleep_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	ifmsh->ps_peers_deep_sleep = deep_sleep_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)  * ieee80211_mps_set_sta_local_pm - set local PM towards a mesh STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)  * @sta: mesh STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  * @pm: the power mode to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  * Return BSS_CHANGED_BEACON if a beacon update is in order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) u32 ieee80211_mps_set_sta_local_pm(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 				   enum nl80211_mesh_power_mode pm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if (sta->mesh->local_pm == pm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	mps_dbg(sdata, "local STA operates in mode %d with %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		pm, sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	sta->mesh->local_pm = pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	 * announce peer-specific power mode transition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	 * (see IEEE802.11-2012 13.14.3.2 and 13.14.3.3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	if (sta->mesh->plink_state == NL80211_PLINK_ESTAB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		mps_qos_null_tx(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	return ieee80211_mps_local_status_update(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)  * ieee80211_mps_set_frame_flags - set mesh PS flags in FC (and QoS Control)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  * @sdata: local mesh subif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  * @sta: mesh STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  * @hdr: 802.11 frame header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)  * see IEEE802.11-2012 8.2.4.1.7 and 8.2.4.5.11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  * NOTE: sta must be given when an individually-addressed QoS frame header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * is handled, for group-addressed and management frames it is not used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) void ieee80211_mps_set_frame_flags(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 				   struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 				   struct ieee80211_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	enum nl80211_mesh_power_mode pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	u8 *qc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	if (WARN_ON(is_unicast_ether_addr(hdr->addr1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		    ieee80211_is_data_qos(hdr->frame_control) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		    !sta))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	if (is_unicast_ether_addr(hdr->addr1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	    ieee80211_is_data_qos(hdr->frame_control) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	    sta->mesh->plink_state == NL80211_PLINK_ESTAB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		pm = sta->mesh->local_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		pm = sdata->u.mesh.nonpeer_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	if (pm == NL80211_MESH_POWER_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_PM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	if (!ieee80211_is_data_qos(hdr->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	qc = ieee80211_get_qos_ctl(hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	if ((is_unicast_ether_addr(hdr->addr1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	     pm == NL80211_MESH_POWER_DEEP_SLEEP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	    (is_multicast_ether_addr(hdr->addr1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	     sdata->u.mesh.ps_peers_deep_sleep > 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		qc[1] |= (IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		qc[1] &= ~(IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  * ieee80211_mps_sta_status_update - update buffering status of neighbor STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  * @sta: mesh STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)  * called after change of peering status or non-peer/peer-specific power mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) void ieee80211_mps_sta_status_update(struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	enum nl80211_mesh_power_mode pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	bool do_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	/* For non-assoc STA, prevent buffering or frame transmission */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	if (sta->sta_state < IEEE80211_STA_ASSOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	 * use peer-specific power mode if peering is established and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	 * peer's power mode is known
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	if (sta->mesh->plink_state == NL80211_PLINK_ESTAB &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	    sta->mesh->peer_pm != NL80211_MESH_POWER_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		pm = sta->mesh->peer_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		pm = sta->mesh->nonpeer_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	do_buffer = (pm != NL80211_MESH_POWER_ACTIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	/* clear the MPSP flags for non-peers or active STA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	if (sta->mesh->plink_state != NL80211_PLINK_ESTAB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	} else if (!do_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	/* Don't let the same PS state be set twice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	if (test_sta_flag(sta, WLAN_STA_PS_STA) == do_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	if (do_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		set_sta_flag(sta, WLAN_STA_PS_STA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		atomic_inc(&sta->sdata->u.mesh.ps.num_sta_ps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		mps_dbg(sta->sdata, "start PS buffering frames towards %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 			sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		ieee80211_sta_ps_deliver_wakeup(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static void mps_set_sta_peer_pm(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 				struct ieee80211_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	enum nl80211_mesh_power_mode pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	u8 *qc = ieee80211_get_qos_ctl(hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	 * Test Power Management field of frame control (PW) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	 * mesh power save level subfield of QoS control field (PSL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	 * | PM | PSL| Mesh PM |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	 * +----+----+---------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	 * | 0  |Rsrv|  Active |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	 * | 1  | 0  |  Light  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	 * | 1  | 1  |  Deep   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	if (ieee80211_has_pm(hdr->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		if (qc[1] & (IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 			pm = NL80211_MESH_POWER_DEEP_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 			pm = NL80211_MESH_POWER_LIGHT_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		pm = NL80211_MESH_POWER_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	if (sta->mesh->peer_pm == pm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	mps_dbg(sta->sdata, "STA %pM enters mode %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		sta->sta.addr, pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	sta->mesh->peer_pm = pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	ieee80211_mps_sta_status_update(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static void mps_set_sta_nonpeer_pm(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 				   struct ieee80211_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	enum nl80211_mesh_power_mode pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	if (ieee80211_has_pm(hdr->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		pm = NL80211_MESH_POWER_DEEP_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		pm = NL80211_MESH_POWER_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	if (sta->mesh->nonpeer_pm == pm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	mps_dbg(sta->sdata, "STA %pM sets non-peer mode to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		sta->sta.addr, pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	sta->mesh->nonpeer_pm = pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	ieee80211_mps_sta_status_update(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)  * ieee80211_mps_rx_h_sta_process - frame receive handler for mesh powersave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)  * @sta: STA info that transmitted the frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)  * @hdr: IEEE 802.11 (QoS) Header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) void ieee80211_mps_rx_h_sta_process(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 				    struct ieee80211_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	if (is_unicast_ether_addr(hdr->addr1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	    ieee80211_is_data_qos(hdr->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		 * individually addressed QoS Data/Null frames contain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		 * peer link-specific PS mode towards the local STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		mps_set_sta_peer_pm(sta, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		/* check for mesh Peer Service Period trigger frames */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		ieee80211_mpsp_trigger_process(ieee80211_get_qos_ctl(hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 					       sta, false, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		 * can only determine non-peer PS mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		 * (see IEEE802.11-2012 8.2.4.1.7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		mps_set_sta_nonpeer_pm(sta, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /* mesh PS frame release */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static void mpsp_trigger_send(struct sta_info *sta, bool rspi, bool eosp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	struct ieee80211_hdr *nullfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	struct ieee80211_tx_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	u8 *qc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	skb = mps_qos_null_get(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	nullfunc = (struct ieee80211_hdr *) skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	if (!eosp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		nullfunc->frame_control |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 				cpu_to_le16(IEEE80211_FCTL_MOREDATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	 * | RSPI | EOSP |  MPSP triggering   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	 * +------+------+--------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	 * |  0   |  0   | local STA is owner |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	 * |  0   |  1   | no MPSP (MPSP end) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	 * |  1   |  0   | both STA are owner |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	 * |  1   |  1   | peer STA is owner  | see IEEE802.11-2012 13.14.9.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	qc = ieee80211_get_qos_ctl(nullfunc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	if (rspi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		qc[1] |= (IEEE80211_QOS_CTL_RSPI >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	if (eosp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		qc[0] |= IEEE80211_QOS_CTL_EOSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	info = IEEE80211_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		       IEEE80211_TX_CTL_REQ_TX_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	mps_dbg(sdata, "sending MPSP trigger%s%s to %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		rspi ? " RSPI" : "", eosp ? " EOSP" : "", sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	ieee80211_tx_skb(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)  * mpsp_qos_null_append - append QoS Null frame to MPSP skb queue if needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)  * @sta: the station to handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)  * @frames: the frame list to append to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)  * To properly end a mesh MPSP the last transmitted frame has to set the EOSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)  * flag in the QoS Control field. In case the current tailing frame is not a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)  * QoS Data frame, append a QoS Null to carry the flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static void mpsp_qos_null_append(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 				 struct sk_buff_head *frames)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	struct sk_buff *new_skb, *skb = skb_peek_tail(frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	struct ieee80211_tx_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	if (ieee80211_is_data_qos(hdr->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	new_skb = mps_qos_null_get(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	if (!new_skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	mps_dbg(sdata, "appending QoS Null in MPSP towards %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	 * This frame has to be transmitted last. Assign lowest priority to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	 * make sure it cannot pass other frames when releasing multiple ACs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	new_skb->priority = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	skb_set_queue_mapping(new_skb, IEEE80211_AC_BK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	ieee80211_set_qos_hdr(sdata, new_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	info = IEEE80211_SKB_CB(new_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	info->control.vif = &sdata->vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	__skb_queue_tail(frames, new_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)  * mps_frame_deliver - transmit frames during mesh powersave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)  * @sta: STA info to transmit to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)  * @n_frames: number of frames to transmit. -1 for all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static void mps_frame_deliver(struct sta_info *sta, int n_frames)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	struct ieee80211_local *local = sta->sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	int ac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	struct sk_buff_head frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	bool more_data = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	skb_queue_head_init(&frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	/* collect frame(s) from buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		while (n_frames != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 			skb = skb_dequeue(&sta->tx_filtered[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 			if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 				skb = skb_dequeue(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 					&sta->ps_tx_buf[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 				if (skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 					local->total_ps_buffered--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 			if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 			n_frames--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 			__skb_queue_tail(&frames, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		if (!skb_queue_empty(&sta->tx_filtered[ac]) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		    !skb_queue_empty(&sta->ps_tx_buf[ac]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 			more_data = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	/* nothing to send? -> EOSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	if (skb_queue_empty(&frames)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		mpsp_trigger_send(sta, false, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	/* in a MPSP make sure the last skb is a QoS Data frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	if (test_sta_flag(sta, WLAN_STA_MPSP_OWNER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		mpsp_qos_null_append(sta, &frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	mps_dbg(sta->sdata, "sending %d frames to PS STA %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		skb_queue_len(&frames), sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	/* prepare collected frames for transmission */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	skb_queue_walk(&frames, skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		struct ieee80211_hdr *hdr = (void *) skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		 * Tell TX path to send this frame even though the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		 * STA may still remain is PS mode after this frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		 * exchange.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 		if (more_data || !skb_queue_is_last(&frames, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 			hdr->frame_control |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 				cpu_to_le16(IEEE80211_FCTL_MOREDATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 			hdr->frame_control &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 				cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		if (skb_queue_is_last(&frames, skb) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		    ieee80211_is_data_qos(hdr->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 			u8 *qoshdr = ieee80211_get_qos_ctl(hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 			/* MPSP trigger frame ends service period */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 			*qoshdr |= IEEE80211_QOS_CTL_EOSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 			info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	ieee80211_add_pending_skbs(local, &frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	sta_info_recalc_tim(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)  * ieee80211_mpsp_trigger_process - track status of mesh Peer Service Periods
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)  * @qc: QoS Control field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)  * @sta: peer to start a MPSP with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)  * @tx: frame was transmitted by the local STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)  * @acked: frame has been transmitted successfully
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)  * NOTE: active mode STA may only serve as MPSP owner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) void ieee80211_mpsp_trigger_process(u8 *qc, struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 				    bool tx, bool acked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	u8 rspi = qc[1] & (IEEE80211_QOS_CTL_RSPI >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	u8 eosp = qc[0] & IEEE80211_QOS_CTL_EOSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	if (tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		if (rspi && acked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 			set_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		if (eosp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 			clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		else if (acked &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 			 test_sta_flag(sta, WLAN_STA_PS_STA) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 			 !test_and_set_sta_flag(sta, WLAN_STA_MPSP_OWNER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 			mps_frame_deliver(sta, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		if (eosp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 			clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		else if (sta->mesh->local_pm != NL80211_MESH_POWER_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 			set_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		if (rspi && !test_and_set_sta_flag(sta, WLAN_STA_MPSP_OWNER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 			mps_frame_deliver(sta, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)  * ieee80211_mps_frame_release - release frames buffered due to mesh power save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)  * @sta: mesh STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)  * @elems: IEs of beacon or probe response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)  * For peers if we have individually-addressed frames buffered or the peer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)  * indicates buffered frames, send a corresponding MPSP trigger frame. Since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)  * we do not evaluate the awake window duration, QoS Nulls are used as MPSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)  * trigger frames. If the neighbour STA is not a peer, only send single frames.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) void ieee80211_mps_frame_release(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 				 struct ieee802_11_elems *elems)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	int ac, buffer_local = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	bool has_buffered = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	if (sta->mesh->plink_state == NL80211_PLINK_ESTAB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 						   sta->mesh->aid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	if (has_buffered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		mps_dbg(sta->sdata, "%pM indicates buffered frames\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 			sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	/* only transmit to PS STA with announced, non-zero awake window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	    (!elems->awake_window || !get_unaligned_le16(elems->awake_window)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	if (!test_sta_flag(sta, WLAN_STA_MPSP_OWNER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 			buffer_local += skb_queue_len(&sta->ps_tx_buf[ac]) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 					skb_queue_len(&sta->tx_filtered[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	if (!has_buffered && !buffer_local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	if (sta->mesh->plink_state == NL80211_PLINK_ESTAB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 		mpsp_trigger_send(sta, has_buffered, !buffer_local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 		mps_frame_deliver(sta, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }