^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) * HT handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2002-2005, Instant802 Networks, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2005-2006, Devicescape Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright 2007-2010, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright 2017 Intel Deutschland GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright(c) 2020 Intel Corporation
^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) #include <linux/ieee80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <net/mac80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "ieee80211_i.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "rate.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static void __check_htcap_disable(struct ieee80211_ht_cap *ht_capa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct ieee80211_ht_cap *ht_capa_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct ieee80211_sta_ht_cap *ht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) u16 flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) __le16 le_flag = cpu_to_le16(flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (ht_capa_mask->cap_info & le_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (!(ht_capa->cap_info & le_flag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ht_cap->cap &= ~flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static void __check_htcap_enable(struct ieee80211_ht_cap *ht_capa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct ieee80211_ht_cap *ht_capa_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct ieee80211_sta_ht_cap *ht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u16 flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) __le16 le_flag = cpu_to_le16(flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if ((ht_capa_mask->cap_info & le_flag) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) (ht_capa->cap_info & le_flag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ht_cap->cap |= flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct ieee80211_sta_ht_cap *ht_cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct ieee80211_ht_cap *ht_capa, *ht_capa_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u8 *scaps, *smask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (!ht_cap->ht_supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) switch (sdata->vif.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ht_capa = &sdata->u.mgd.ht_capa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ht_capa_mask = &sdata->u.mgd.ht_capa_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ht_capa = &sdata->u.ibss.ht_capa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ht_capa_mask = &sdata->u.ibss.ht_capa_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) WARN_ON_ONCE(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return;
^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) scaps = (u8 *)(&ht_capa->mcs.rx_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) smask = (u8 *)(&ht_capa_mask->mcs.rx_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* NOTE: If you add more over-rides here, update register_hw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * ht_capa_mod_mask logic in main.c as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * And, if this method can ever change ht_cap.ht_supported, fix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * the check in ieee80211_add_ht_ie.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* check for HT over-rides, MCS rates first. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u8 m = smask[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ht_cap->mcs.rx_mask[i] &= ~m; /* turn off all masked bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* Add back rates that are supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ht_cap->mcs.rx_mask[i] |= (m & scaps[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Force removal of HT-40 capabilities? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) IEEE80211_HT_CAP_SUP_WIDTH_20_40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) IEEE80211_HT_CAP_SGI_40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* Allow user to disable SGI-20 (SGI-40 is handled above) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) IEEE80211_HT_CAP_SGI_20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* Allow user to disable the max-AMSDU bit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) IEEE80211_HT_CAP_MAX_AMSDU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* Allow user to disable LDPC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) IEEE80211_HT_CAP_LDPC_CODING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* Allow user to enable 40 MHz intolerant bit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) __check_htcap_enable(ht_capa, ht_capa_mask, ht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) IEEE80211_HT_CAP_40MHZ_INTOLERANT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* Allow user to enable TX STBC bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) __check_htcap_enable(ht_capa, ht_capa_mask, ht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) IEEE80211_HT_CAP_TX_STBC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Allow user to configure RX STBC bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (ht_capa_mask->cap_info & cpu_to_le16(IEEE80211_HT_CAP_RX_STBC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ht_cap->cap |= le16_to_cpu(ht_capa->cap_info) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) IEEE80211_HT_CAP_RX_STBC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Allow user to decrease AMPDU factor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (ht_capa_mask->ampdu_params_info &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) IEEE80211_HT_AMPDU_PARM_FACTOR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u8 n = ht_capa->ampdu_params_info &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) IEEE80211_HT_AMPDU_PARM_FACTOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (n < ht_cap->ampdu_factor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ht_cap->ampdu_factor = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* Allow the user to increase AMPDU density. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (ht_capa_mask->ampdu_params_info &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) IEEE80211_HT_AMPDU_PARM_DENSITY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u8 n = (ht_capa->ampdu_params_info &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) IEEE80211_HT_AMPDU_PARM_DENSITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (n > ht_cap->ampdu_density)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ht_cap->ampdu_density = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct ieee80211_supported_band *sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) const struct ieee80211_ht_cap *ht_cap_ie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct ieee80211_sta_ht_cap ht_cap, own_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) u8 ampdu_info, tx_mcs_set_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int i, max_tx_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) bool changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) enum ieee80211_sta_rx_bandwidth bw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) memset(&ht_cap, 0, sizeof(ht_cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (!ht_cap_ie || !sband->ht_cap.ht_supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) goto apply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ht_cap.ht_supported = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) own_cap = sband->ht_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * If user has specified capability over-rides, take care
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * of that if the station we're setting up is the AP or TDLS peer that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * we advertised a restricted capability set to. Override
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * our own capabilities and then use those below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (sdata->vif.type == NL80211_IFTYPE_STATION ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) sdata->vif.type == NL80211_IFTYPE_ADHOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ieee80211_apply_htcap_overrides(sdata, &own_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * The bits listed in this expression should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * the same for the peer and us, if the station
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * advertises more then we can't use those thus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * we mask them out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ht_cap.cap = le16_to_cpu(ht_cap_ie->cap_info) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) (own_cap.cap | ~(IEEE80211_HT_CAP_LDPC_CODING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) IEEE80211_HT_CAP_GRN_FLD |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) IEEE80211_HT_CAP_SGI_20 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) IEEE80211_HT_CAP_SGI_40 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) IEEE80211_HT_CAP_DSSSCCK40));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * The STBC bits are asymmetric -- if we don't have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * TX then mask out the peer's RX and vice versa.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (!(own_cap.cap & IEEE80211_HT_CAP_TX_STBC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ht_cap.cap &= ~IEEE80211_HT_CAP_RX_STBC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (!(own_cap.cap & IEEE80211_HT_CAP_RX_STBC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ht_cap.cap &= ~IEEE80211_HT_CAP_TX_STBC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ampdu_info = ht_cap_ie->ampdu_params_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ht_cap.ampdu_factor =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ampdu_info & IEEE80211_HT_AMPDU_PARM_FACTOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ht_cap.ampdu_density =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /* own MCS TX capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) tx_mcs_set_cap = own_cap.mcs.tx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* Copy peer MCS TX capabilities, the driver might need them. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ht_cap.mcs.tx_params = ht_cap_ie->mcs.tx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* can we TX with MCS rates? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (!(tx_mcs_set_cap & IEEE80211_HT_MCS_TX_DEFINED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) goto apply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* Counting from 0, therefore +1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_RX_DIFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) max_tx_streams =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ((tx_mcs_set_cap & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) max_tx_streams = IEEE80211_HT_MCS_TX_MAX_STREAMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * 802.11n-2009 20.3.5 / 20.6 says:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * - indices 0 to 7 and 32 are single spatial stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * - 8 to 31 are multiple spatial streams using equal modulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * [8..15 for two streams, 16..23 for three and 24..31 for four]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * - remainder are multiple spatial streams using unequal modulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) for (i = 0; i < max_tx_streams; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ht_cap.mcs.rx_mask[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) own_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) i < IEEE80211_HT_MCS_MASK_LEN; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ht_cap.mcs.rx_mask[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) own_cap.mcs.rx_mask[i] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) ht_cap_ie->mcs.rx_mask[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* handle MCS rate 32 too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ht_cap.mcs.rx_mask[32/8] |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* set Rx highest rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_7935;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_3839;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) apply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) memcpy(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) switch (sdata->vif.bss_conf.chandef.width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) WARN_ON_ONCE(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case NL80211_CHAN_WIDTH_20_NOHT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) case NL80211_CHAN_WIDTH_20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) bw = IEEE80211_STA_RX_BW_20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case NL80211_CHAN_WIDTH_40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) case NL80211_CHAN_WIDTH_80:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) case NL80211_CHAN_WIDTH_80P80:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case NL80211_CHAN_WIDTH_160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) bw = ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) sta->sta.bandwidth = bw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) sta->cur_max_bandwidth =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) enum ieee80211_smps_mode smps_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) switch ((ht_cap.cap & IEEE80211_HT_CAP_SM_PS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) >> IEEE80211_HT_CAP_SM_PS_SHIFT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) case WLAN_HT_CAP_SM_PS_INVALID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) case WLAN_HT_CAP_SM_PS_STATIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) smps_mode = IEEE80211_SMPS_STATIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case WLAN_HT_CAP_SM_PS_DYNAMIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) smps_mode = IEEE80211_SMPS_DYNAMIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) case WLAN_HT_CAP_SM_PS_DISABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) smps_mode = IEEE80211_SMPS_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (smps_mode != sta->sta.smps_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) sta->sta.smps_mode = smps_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) sta->sta.smps_mode = IEEE80211_SMPS_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) enum ieee80211_agg_stop_reason reason)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) mutex_lock(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) for (i = 0; i < IEEE80211_NUM_TIDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ___ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) WLAN_REASON_QSTA_LEAVE_QBSS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) reason != AGG_STOP_DESTROY_STA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) reason != AGG_STOP_PEER_REQUEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) for (i = 0; i < IEEE80211_NUM_TIDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ___ieee80211_stop_tx_ba_session(sta, i, reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) mutex_unlock(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * In case the tear down is part of a reconfigure due to HW restart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * request, it is possible that the low level driver requested to stop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * the BA session, so handle it to properly clean tid_tx data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if(reason == AGG_STOP_DESTROY_STA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) cancel_work_sync(&sta->ampdu_mlme.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) mutex_lock(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct tid_ampdu_tx *tid_tx =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) rcu_dereference_protected_tid_tx(sta, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (!tid_tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (test_and_clear_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ieee80211_stop_tx_ba_cb(sta, i, tid_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) mutex_unlock(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) void ieee80211_ba_session_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct sta_info *sta =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) container_of(work, struct sta_info, ampdu_mlme.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct tid_ampdu_tx *tid_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) bool blocked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) int tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* When this flag is set, new sessions should be blocked. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) blocked = test_sta_flag(sta, WLAN_STA_BLOCK_BA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) mutex_lock(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ___ieee80211_stop_rx_ba_session(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) sta, tid, WLAN_BACK_RECIPIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) WLAN_REASON_QSTA_TIMEOUT, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (test_and_clear_bit(tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) sta->ampdu_mlme.tid_rx_stop_requested))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) ___ieee80211_stop_rx_ba_session(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) sta, tid, WLAN_BACK_RECIPIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) WLAN_REASON_UNSPECIFIED, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (!blocked &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) test_and_clear_bit(tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) sta->ampdu_mlme.tid_rx_manage_offl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) ___ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) IEEE80211_MAX_AMPDU_BUF_HT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) false, true, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) sta->ampdu_mlme.tid_rx_manage_offl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) ___ieee80211_stop_rx_ba_session(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) sta, tid, WLAN_BACK_RECIPIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) spin_lock_bh(&sta->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (!blocked && tid_tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * Assign it over to the normal tid_tx array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * where it "goes live".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) sta->ampdu_mlme.tid_start_tx[tid] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* could there be a race? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (sta->ampdu_mlme.tid_tx[tid])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) kfree(tid_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) ieee80211_assign_tid_tx(sta, tid, tid_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) spin_unlock_bh(&sta->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) ieee80211_tx_ba_session_handle_start(sta, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) spin_unlock_bh(&sta->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (!tid_tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (!blocked &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) test_and_clear_bit(HT_AGG_STATE_START_CB, &tid_tx->state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) ieee80211_start_tx_ba_cb(sta, tid, tid_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) ___ieee80211_stop_tx_ba_session(sta, tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) AGG_STOP_LOCAL_REQUEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (test_and_clear_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ieee80211_stop_tx_ba_cb(sta, tid, tid_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) mutex_unlock(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) const u8 *da, u16 tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) u16 initiator, u16 reason_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) struct ieee80211_mgmt *mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) u16 params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) skb_reserve(skb, local->hw.extra_tx_headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) mgmt = skb_put_zero(skb, 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) memcpy(mgmt->da, da, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (sdata->vif.type == NL80211_IFTYPE_AP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) else if (sdata->vif.type == NL80211_IFTYPE_STATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) IEEE80211_STYPE_ACTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) mgmt->u.action.category = WLAN_CATEGORY_BACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) params = (u16)(initiator << 11); /* bit 11 initiator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) params |= (u16)(tid << 12); /* bit 15:12 TID number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) mgmt->u.action.u.delba.params = cpu_to_le16(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ieee80211_tx_skb(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct ieee80211_mgmt *mgmt, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) u16 tid, params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) u16 initiator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) params = le16_to_cpu(mgmt->u.action.u.delba.params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ht_dbg_ratelimited(sdata, "delba from %pM (%s) tid %d reason code %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) mgmt->sa, initiator ? "initiator" : "recipient",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) le16_to_cpu(mgmt->u.action.u.delba.reason_code));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (initiator == WLAN_BACK_INITIATOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) __ieee80211_stop_tx_ba_session(sta, tid, AGG_STOP_PEER_REQUEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) enum nl80211_smps_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) switch (smps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) case IEEE80211_SMPS_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return NL80211_SMPS_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) case IEEE80211_SMPS_STATIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return NL80211_SMPS_STATIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) case IEEE80211_SMPS_DYNAMIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return NL80211_SMPS_DYNAMIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return NL80211_SMPS_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) enum ieee80211_smps_mode smps, const u8 *da,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) const u8 *bssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct ieee80211_mgmt *action_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /* 27 = header + category + action + smps mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) skb = dev_alloc_skb(27 + local->hw.extra_tx_headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) skb_reserve(skb, local->hw.extra_tx_headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) action_frame = skb_put(skb, 27);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) memcpy(action_frame->da, da, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) memcpy(action_frame->sa, sdata->dev->dev_addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) memcpy(action_frame->bssid, bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) IEEE80211_STYPE_ACTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) action_frame->u.action.category = WLAN_CATEGORY_HT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) switch (smps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) case IEEE80211_SMPS_AUTOMATIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) case IEEE80211_SMPS_NUM_MODES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) case IEEE80211_SMPS_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) action_frame->u.action.u.ht_smps.smps_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) WLAN_HT_SMPS_CONTROL_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) case IEEE80211_SMPS_STATIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) action_frame->u.action.u.ht_smps.smps_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) WLAN_HT_SMPS_CONTROL_STATIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) case IEEE80211_SMPS_DYNAMIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) action_frame->u.action.u.ht_smps.smps_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) WLAN_HT_SMPS_CONTROL_DYNAMIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* we'll do more on status of this frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ieee80211_tx_skb(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) void ieee80211_request_smps_mgd_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct ieee80211_sub_if_data *sdata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) container_of(work, struct ieee80211_sub_if_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) u.mgd.request_smps_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) sdata_lock(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) __ieee80211_request_smps_mgd(sdata, sdata->u.mgd.driver_smps_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) sdata_unlock(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) void ieee80211_request_smps(struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) enum ieee80211_smps_mode smps_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) vif->type != NL80211_IFTYPE_AP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (vif->type == NL80211_IFTYPE_STATION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (sdata->u.mgd.driver_smps_mode == smps_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) sdata->u.mgd.driver_smps_mode = smps_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) ieee80211_queue_work(&sdata->local->hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) &sdata->u.mgd.request_smps_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /* this might change ... don't want non-open drivers using it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) EXPORT_SYMBOL_GPL(ieee80211_request_smps);