···29902990{29912991 struct ath6kl *ar = ath6kl_priv(dev);29922992 struct ath6kl_vif *vif = netdev_priv(dev);29932993+ int err;2993299429942995 if (vif->nw_type != AP_NETWORK)29952996 return -EOPNOTSUPP;2996299729972997- /* Use this only for authorizing/unauthorizing a station */29982998- if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))29992999- return -EOPNOTSUPP;29982998+ err = cfg80211_check_station_change(wiphy, params,29992999+ CFG80211_STA_AP_MLME_CLIENT);30003000+ if (err)30013001+ return err;3000300230013003 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))30023004 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
···641641 next_reclaimed = ssn;642642 } else {643643 /* The next packet to be reclaimed is the one after this one */644644- next_reclaimed = SEQ_TO_SN(seq_ctl + 0x10);644644+ next_reclaimed = IEEE80211_SEQ_TO_SN(seq_ctl + 0x10);645645 }646646647647 IWL_DEBUG_TX_REPLY(mvm,
+1-1
drivers/net/wireless/iwlwifi/pcie/tx.c
···15811581 * Check here that the packets are in the right place on the ring.15821582 */15831583#ifdef CONFIG_IWLWIFI_DEBUG15841584- wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));15841584+ wifi_seq = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));15851585 WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) &&15861586 ((wifi_seq & 0xff) != q->write_ptr),15871587 "Q: %d WiFi Seq %d tfdNum %d",
+2-1
drivers/net/wireless/mac80211_hwsim.c
···15351535static int mac80211_hwsim_roc(struct ieee80211_hw *hw,15361536 struct ieee80211_vif *vif,15371537 struct ieee80211_channel *chan,15381538- int duration)15381538+ int duration,15391539+ enum ieee80211_roc_type type)15391540{15401541 struct mac80211_hwsim_data *hwsim = hw->priv;15411542
···611611};612612613613/**614614- * enum plink_action - actions to perform in mesh peers615615- *616616- * @PLINK_ACTION_INVALID: action 0 is reserved617617- * @PLINK_ACTION_OPEN: start mesh peer link establishment618618- * @PLINK_ACTION_BLOCK: block traffic from this mesh peer619619- */620620-enum plink_actions {621621- PLINK_ACTION_INVALID,622622- PLINK_ACTION_OPEN,623623- PLINK_ACTION_BLOCK,624624-};625625-626626-/**627614 * enum station_parameters_apply_mask - station parameter values to apply628615 * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)629616 * @STATION_PARAM_APPLY_CAPABILITY: apply new capability617617+ * @STATION_PARAM_APPLY_PLINK_STATE: apply new plink state630618 *631619 * Not all station parameters have in-band "no change" signalling,632620 * for those that don't these flags will are used.···622634enum station_parameters_apply_mask {623635 STATION_PARAM_APPLY_UAPSD = BIT(0),624636 STATION_PARAM_APPLY_CAPABILITY = BIT(1),637637+ STATION_PARAM_APPLY_PLINK_STATE = BIT(2),625638};626639627640/**···658669 * @ext_capab_len: number of extended capabilities659670 */660671struct station_parameters {661661- u8 *supported_rates;672672+ const u8 *supported_rates;662673 struct net_device *vlan;663674 u32 sta_flags_mask, sta_flags_set;664675 u32 sta_modify_mask;···667678 u8 supported_rates_len;668679 u8 plink_action;669680 u8 plink_state;670670- struct ieee80211_ht_cap *ht_capa;671671- struct ieee80211_vht_cap *vht_capa;681681+ const struct ieee80211_ht_cap *ht_capa;682682+ const struct ieee80211_vht_cap *vht_capa;672683 u8 uapsd_queues;673684 u8 max_sp;674685 enum nl80211_mesh_power_mode local_pm;675686 u16 capability;676676- u8 *ext_capab;687687+ const u8 *ext_capab;677688 u8 ext_capab_len;678689};690690+691691+/**692692+ * enum cfg80211_station_type - the type of station being modified693693+ * @CFG80211_STA_AP_CLIENT: client of an AP interface694694+ * @CFG80211_STA_AP_MLME_CLIENT: client of an AP interface that has695695+ * the AP MLME in the device696696+ * @CFG80211_STA_AP_STA: AP station on managed interface697697+ * @CFG80211_STA_IBSS: IBSS station698698+ * @CFG80211_STA_TDLS_PEER_SETUP: TDLS peer on managed interface (dummy entry699699+ * while TDLS setup is in progress, it moves out of this state when700700+ * being marked authorized; use this only if TDLS with external setup is701701+ * supported/used)702702+ * @CFG80211_STA_TDLS_PEER_ACTIVE: TDLS peer on managed interface (active703703+ * entry that is operating, has been marked authorized by userspace)704704+ * @CFG80211_STA_MESH_PEER_KERNEL: peer on mesh interface (kernel managed)705705+ * @CFG80211_STA_MESH_PEER_USER: peer on mesh interface (user managed)706706+ */707707+enum cfg80211_station_type {708708+ CFG80211_STA_AP_CLIENT,709709+ CFG80211_STA_AP_MLME_CLIENT,710710+ CFG80211_STA_AP_STA,711711+ CFG80211_STA_IBSS,712712+ CFG80211_STA_TDLS_PEER_SETUP,713713+ CFG80211_STA_TDLS_PEER_ACTIVE,714714+ CFG80211_STA_MESH_PEER_KERNEL,715715+ CFG80211_STA_MESH_PEER_USER,716716+};717717+718718+/**719719+ * cfg80211_check_station_change - validate parameter changes720720+ * @wiphy: the wiphy this operates on721721+ * @params: the new parameters for a station722722+ * @statype: the type of station being modified723723+ *724724+ * Utility function for the @change_station driver method. Call this function725725+ * with the appropriate station type looking up the station (and checking that726726+ * it exists). It will verify whether the station change is acceptable, and if727727+ * not will return an error code. Note that it may modify the parameters for728728+ * backward compatibility reasons, so don't use them before calling this.729729+ */730730+int cfg80211_check_station_change(struct wiphy *wiphy,731731+ struct station_parameters *params,732732+ enum cfg80211_station_type statype);679733680734/**681735 * enum station_info_flags - station information flags···11511119 * @ie_len: length of vendor information elements11521120 * @is_authenticated: this mesh requires authentication11531121 * @is_secure: this mesh uses security11221122+ * @user_mpm: userspace handles all MPM functions11541123 * @dtim_period: DTIM period to use11551124 * @beacon_interval: beacon interval to use11561125 * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]···11691136 u8 ie_len;11701137 bool is_authenticated;11711138 bool is_secure;11391139+ bool user_mpm;11721140 u8 dtim_period;11731141 u16 beacon_interval;11741142 int mcast_rate[IEEE80211_NUM_BANDS];···14321398 * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association.14331399 *14341400 * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n)14011401+ * @ASSOC_REQ_DISABLE_VHT: Disable VHT14351402 */14361403enum cfg80211_assoc_req_flags {14371404 ASSOC_REQ_DISABLE_HT = BIT(0),14051405+ ASSOC_REQ_DISABLE_VHT = BIT(1),14381406};1439140714401408/**···14581422 * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask14591423 * will be used in ht_capa. Un-supported values will be ignored.14601424 * @ht_capa_mask: The bits of ht_capa which are to be used.14251425+ * @vht_capa: VHT capability override14261426+ * @vht_capa_mask: VHT capability mask indicating which fields to use14611427 */14621428struct cfg80211_assoc_request {14631429 struct cfg80211_bss *bss;···14701432 u32 flags;14711433 struct ieee80211_ht_cap ht_capa;14721434 struct ieee80211_ht_cap ht_capa_mask;14351435+ struct ieee80211_vht_cap vht_capa, vht_capa_mask;14731436};1474143714751438/**···15811542 * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask15821543 * will be used in ht_capa. Un-supported values will be ignored.15831544 * @ht_capa_mask: The bits of ht_capa which are to be used.15451545+ * @vht_capa: VHT Capability overrides15461546+ * @vht_capa_mask: The bits of vht_capa which are to be used.15841547 */15851548struct cfg80211_connect_params {15861549 struct ieee80211_channel *channel;···16011560 int bg_scan_period;16021561 struct ieee80211_ht_cap ht_capa;16031562 struct ieee80211_ht_cap ht_capa_mask;15631563+ struct ieee80211_vht_cap vht_capa;15641564+ struct ieee80211_vht_cap vht_capa_mask;16041565};1605156616061567/**···17651722};1766172317671724/**17251725+ * struct cfg80211_update_ft_ies_params - FT IE Information17261726+ *17271727+ * This structure provides information needed to update the fast transition IE17281728+ *17291729+ * @md: The Mobility Domain ID, 2 Octet value17301730+ * @ie: Fast Transition IEs17311731+ * @ie_len: Length of ft_ie in octets17321732+ */17331733+struct cfg80211_update_ft_ies_params {17341734+ u16 md;17351735+ const u8 *ie;17361736+ size_t ie_len;17371737+};17381738+17391739+/**17681740 * struct cfg80211_ops - backend description for wireless configuration17691741 *17701742 * This struct is registered by fullmac card drivers and/or wireless stacks···18391781 * @change_station: Modify a given station. Note that flags changes are not much18401782 * validated in cfg80211, in particular the auth/assoc/authorized flags18411783 * might come to the driver in invalid combinations -- make sure to check18421842- * them, also against the existing state! Also, supported_rates changes are18431843- * not checked in station mode -- drivers need to reject (or ignore) them18441844- * for anything but TDLS peers.17841784+ * them, also against the existing state! Drivers must call17851785+ * cfg80211_check_station_change() to validate the information.18451786 * @get_station: get station information for the station identified by @mac18461787 * @dump_station: dump station callback -- resume dump at index @idx18471788 *···22252168 int (*start_radar_detection)(struct wiphy *wiphy,22262169 struct net_device *dev,22272170 struct cfg80211_chan_def *chandef);21712171+ int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,21722172+ struct cfg80211_update_ft_ies_params *ftie);22282173};2229217422302175/*···25442485 * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.25452486 * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden.25462487 * If null, then none can be over-ridden.24882488+ * @vht_capa_mod_mask: Specify what VHT capabilities can be over-ridden.24892489+ * If null, then none can be over-ridden.25472490 *25482491 * @max_acl_mac_addrs: Maximum number of MAC addresses that the device25492492 * supports for ACL.···26542593 struct dentry *debugfsdir;2655259426562595 const struct ieee80211_ht_cap *ht_capa_mod_mask;25962596+ const struct ieee80211_vht_cap *vht_capa_mod_mask;2657259726582598#ifdef CONFIG_NET_NS26592599 /* the network namespace this phy lives in currently */···40624000 * Requires the RTNL to be held.40634001 */40644002void cfg80211_unregister_wdev(struct wireless_dev *wdev);40034003+40044004+/**40054005+ * struct cfg80211_ft_event - FT Information Elements40064006+ * @ies: FT IEs40074007+ * @ies_len: length of the FT IE in bytes40084008+ * @target_ap: target AP's MAC address40094009+ * @ric_ies: RIC IE40104010+ * @ric_ies_len: length of the RIC IE in bytes40114011+ */40124012+struct cfg80211_ft_event_params {40134013+ const u8 *ies;40144014+ size_t ies_len;40154015+ const u8 *target_ap;40164016+ const u8 *ric_ies;40174017+ size_t ric_ies_len;40184018+};40194019+40204020+/**40214021+ * cfg80211_ft_event - notify userspace about FT IE and RIC IE40224022+ * @netdev: network device40234023+ * @ft_event: IE information40244024+ */40254025+void cfg80211_ft_event(struct net_device *netdev,40264026+ struct cfg80211_ft_event_params *ft_event);4065402740664028/**40674029 * cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer
+22-7
include/net/mac80211.h
···11011101 * These flags are used for communication about keys between the driver11021102 * and mac80211, with the @flags parameter of &struct ieee80211_key_conf.11031103 *11041104- * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates11051105- * that the STA this key will be used with could be using QoS.11061104 * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the11071105 * driver to indicate that it requires IV generation for this11081106 * particular key.···11251127 * %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW.11261128 */11271129enum ieee80211_key_flags {11281128- IEEE80211_KEY_FLAG_WMM_STA = 1<<0,11291130 IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1,11301131 IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2,11311132 IEEE80211_KEY_FLAG_PAIRWISE = 1<<3,···12281231 * @addr: MAC address12291232 * @aid: AID we assigned to the station if we're an AP12301233 * @supp_rates: Bitmap of supported rates (per band)12311231- * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities12321232- * @vht_cap: VHT capabilities of this STA; Not restricting any capabilities12331233- * of remote STA. Taking as is.12341234+ * @ht_cap: HT capabilities of this STA; restricted to our own capabilities12351235+ * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities12341236 * @wme: indicates whether the STA supports WME. Only valid during AP-mode.12351237 * @drv_priv: data area for driver use, will always be aligned to12361238 * sizeof(void *), size is determined in hw information.···21312135};2132213621332137/**21382138+ * enum ieee80211_roc_type - remain on channel type21392139+ *21402140+ * With the support for multi channel contexts and multi channel operations,21412141+ * remain on channel operations might be limited/deferred/aborted by other21422142+ * flows/operations which have higher priority (and vise versa).21432143+ * Specifying the ROC type can be used by devices to prioritize the ROC21442144+ * operations compared to other operations/flows.21452145+ *21462146+ * @IEEE80211_ROC_TYPE_NORMAL: There are no special requirements for this ROC.21472147+ * @IEEE80211_ROC_TYPE_MGMT_TX: The remain on channel request is required21482148+ * for sending managment frames offchannel.21492149+ */21502150+enum ieee80211_roc_type {21512151+ IEEE80211_ROC_TYPE_NORMAL = 0,21522152+ IEEE80211_ROC_TYPE_MGMT_TX,21532153+};21542154+21552155+/**21342156 * struct ieee80211_ops - callbacks from mac80211 to the driver21352157 *21362158 * This structure contains various callbacks that the driver may···27012687 int (*remain_on_channel)(struct ieee80211_hw *hw,27022688 struct ieee80211_vif *vif,27032689 struct ieee80211_channel *chan,27042704- int duration);26902690+ int duration,26912691+ enum ieee80211_roc_type type);27052692 int (*cancel_remain_on_channel)(struct ieee80211_hw *hw);27062693 int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);27072694 void (*get_ringparam)(struct ieee80211_hw *hw,
+106-11
include/uapi/linux/nl80211.h
···3636 * The station is still assumed to belong to the AP interface it was added3737 * to.3838 *3939- * TODO: need more info?3939+ * Station handling varies per interface type and depending on the driver's4040+ * capabilities.4141+ *4242+ * For drivers supporting TDLS with external setup (WIPHY_FLAG_SUPPORTS_TDLS4343+ * and WIPHY_FLAG_TDLS_EXTERNAL_SETUP), the station lifetime is as follows:4444+ * - a setup station entry is added, not yet authorized, without any rate4545+ * or capability information, this just exists to avoid race conditions4646+ * - when the TDLS setup is done, a single NL80211_CMD_SET_STATION is valid4747+ * to add rate and capability information to the station and at the same4848+ * time mark it authorized.4949+ * - %NL80211_TDLS_ENABLE_LINK is then used5050+ * - after this, the only valid operation is to remove it by tearing down5151+ * the TDLS link (%NL80211_TDLS_DISABLE_LINK)5252+ *5353+ * TODO: need more info for other interface types4054 */41554256/**···513499 * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a514500 * beacon or probe response from a compatible mesh peer. This is only515501 * sent while no station information (sta_info) exists for the new peer516516- * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set. On517517- * reception of this notification, userspace may decide to create a new518518- * station (@NL80211_CMD_NEW_STATION). To stop this notification from502502+ * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH,503503+ * @NL80211_MESH_SETUP_USERSPACE_AMPE, or504504+ * @NL80211_MESH_SETUP_USERSPACE_MPM is set. On reception of this505505+ * notification, userspace may decide to create a new station506506+ * (@NL80211_CMD_NEW_STATION). To stop this notification from519507 * reoccurring, the userspace authentication daemon may want to create the520508 * new station with the AUTHENTICATED flag unset and maybe change it later521509 * depending on the authentication result.···626610 * while operating on this channel.627611 * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the628612 * event.613613+ *614614+ * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features,615615+ * i.e. features for the nl80211 protocol rather than device features.616616+ * Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap.617617+ *618618+ * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition619619+ * Information Element to the WLAN driver620620+ *621621+ * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver622622+ * to the supplicant. This will carry the target AP's MAC address along623623+ * with the relevant Information Elements. This event is used to report624624+ * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).629625 *630626 * @NL80211_CMD_MAX: highest used command number631627 * @__NL80211_CMD_AFTER_LAST: internal use···793765794766 NL80211_CMD_RADAR_DETECT,795767768768+ NL80211_CMD_GET_PROTOCOL_FEATURES,769769+770770+ NL80211_CMD_UPDATE_FT_IES,771771+ NL80211_CMD_FT_EVENT,772772+796773 /* add new commands above here */797774798775 /* used to define NL80211_CMD_MAX below */···917884 * consisting of a nested array.918885 *919886 * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes).920920- * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link.887887+ * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link888888+ * (see &enum nl80211_plink_action).921889 * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.922890 * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path923891 * info given for %NL80211_CMD_GET_MPATH, nested attribute described at···12011167 * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver12021168 * allows auth frames in a mesh to be passed to userspace for processing via12031169 * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag.12041204- * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as12051205- * defined in &enum nl80211_plink_state. Used when userspace is12061206- * driving the peer link management state machine.12071207- * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled.11701170+ * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as defined in11711171+ * &enum nl80211_plink_state. Used when userspace is driving the peer link11721172+ * management state machine. @NL80211_MESH_SETUP_USERSPACE_AMPE or11731173+ * @NL80211_MESH_SETUP_USERSPACE_MPM must be enabled.12081174 *12091175 * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy12101176 * capabilities, the supported WoWLAN triggers···14011367 * @NL80211_ATTR_STA_EXT_CAPABILITY: Station extended capabilities are14021368 * advertised to the driver, e.g., to enable TDLS off channel operations14031369 * and PU-APSD.13701370+ *13711371+ * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see13721372+ * &enum nl80211_protocol_features, the attribute is a u32.13731373+ *13741374+ * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports13751375+ * receiving the data for a single wiphy split across multiple13761376+ * messages, given with wiphy dump message13771377+ *13781378+ * @NL80211_ATTR_MDID: Mobility Domain Identifier13791379+ *13801380+ * @NL80211_ATTR_IE_RIC: Resource Information Container Information13811381+ * Element14041382 *14051383 * @NL80211_ATTR_MAX: highest attribute number currently defined14061384 * @__NL80211_ATTR_AFTER_LAST: internal use···1699165317001654 NL80211_ATTR_STA_CAPABILITY,17011655 NL80211_ATTR_STA_EXT_CAPABILITY,16561656+16571657+ NL80211_ATTR_PROTOCOL_FEATURES,16581658+ NL80211_ATTR_SPLIT_WIPHY_DUMP,16591659+16601660+ NL80211_ATTR_DISABLE_VHT,16611661+ NL80211_ATTR_VHT_CAPABILITY_MASK,16621662+16631663+ NL80211_ATTR_MDID,16641664+ NL80211_ATTR_IE_RIC,1702166517031666 /* add attributes here, update the policy in nl80211.c */17041667···24672412 * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh24682413 * point.24692414 *24702470- * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically24712471- * open peer links when we detect compatible mesh peers.24152415+ * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically open24162416+ * peer links when we detect compatible mesh peers. Disabled if24172417+ * @NL80211_MESH_SETUP_USERSPACE_MPM or @NL80211_MESH_SETUP_USERSPACE_AMPE are24182418+ * set.24722419 *24732420 * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames24742421 * containing a PREQ that an MP can send to a particular destination (path···26162559 * vendor specific synchronization method or disable it to use the default26172560 * neighbor offset synchronization26182561 *25622562+ * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will25632563+ * implement an MPM which handles peer allocation and state.25642564+ *26192565 * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number26202566 *26212567 * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use···26312571 NL80211_MESH_SETUP_USERSPACE_AUTH,26322572 NL80211_MESH_SETUP_USERSPACE_AMPE,26332573 NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC,25742574+ NL80211_MESH_SETUP_USERSPACE_MPM,2634257526352576 /* keep last */26362577 __NL80211_MESH_SETUP_ATTR_AFTER_LAST,···33683307 MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 133693308};3370330933103310+/**33113311+ * enum nl80211_plink_action - actions to perform in mesh peers33123312+ *33133313+ * @NL80211_PLINK_ACTION_NO_ACTION: perform no action33143314+ * @NL80211_PLINK_ACTION_OPEN: start mesh peer link establishment33153315+ * @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer33163316+ * @NUM_NL80211_PLINK_ACTIONS: number of possible actions33173317+ */33183318+enum plink_actions {33193319+ NL80211_PLINK_ACTION_NO_ACTION,33203320+ NL80211_PLINK_ACTION_OPEN,33213321+ NL80211_PLINK_ACTION_BLOCK,33223322+33233323+ NUM_NL80211_PLINK_ACTIONS,33243324+};33253325+33263326+33713327#define NL80211_KCK_LEN 1633723328#define NL80211_KEK_LEN 1633733329#define NL80211_REPLAY_CTR_LEN 8···35343456 * stations the authenticated/associated bits have to be set in the mask.35353457 * @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits35363458 * (HT40, VHT 80/160 MHz) if this flag is set34593459+ * @NL80211_FEATURE_USERSPACE_MPM: This driver supports a userspace Mesh34603460+ * Peering Management entity which may be implemented by registering for34613461+ * beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is34623462+ * still generated by the driver.35373463 */35383464enum nl80211_feature_flags {35393465 NL80211_FEATURE_SK_TX_STATUS = 1 << 0,···35563474 /* bit 13 is reserved */35573475 NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14,35583476 NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15,34773477+ NL80211_FEATURE_USERSPACE_MPM = 1 << 16,35593478};3560347935613480/**···36683585 NL80211_DFS_USABLE,36693586 NL80211_DFS_UNAVAILABLE,36703587 NL80211_DFS_AVAILABLE,35883588+};35893589+35903590+/**35913591+ * enum enum nl80211_protocol_features - nl80211 protocol features35923592+ * @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting35933593+ * wiphy dumps (if requested by the application with the attribute35943594+ * %NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the35953595+ * wiphy dump by %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFINDEX or35963596+ * %NL80211_ATTR_WDEV.35973597+ */35983598+enum nl80211_protocol_features {35993599+ NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0,36713600};3672360136733602#endif /* __LINUX_NL80211_H */
+114-48
net/mac80211/cfg.c
···254254 goto out_unlock;255255 }256256257257- __ieee80211_key_free(key);257257+ __ieee80211_key_free(key, true);258258259259 ret = 0;260260 out_unlock:···10351035 sta_info_flush_defer(vlan);10361036 sta_info_flush_defer(sdata);10371037 rcu_barrier();10381038- list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)10381038+ list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {10391039 sta_info_flush_cleanup(vlan);10401040+ ieee80211_free_keys(vlan);10411041+ }10401042 sta_info_flush_cleanup(sdata);10431043+ ieee80211_free_keys(sdata);1041104410421045 sdata->vif.bss_conf.enable_beacon = false;10431046 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);···11801177 mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);11811178 if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))11821179 set |= BIT(NL80211_STA_FLAG_ASSOCIATED);11801180+ } else if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {11811181+ /*11821182+ * TDLS -- everything follows authorized, but11831183+ * only becoming authorized is possible, not11841184+ * going back11851185+ */11861186+ if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {11871187+ set |= BIT(NL80211_STA_FLAG_AUTHENTICATED) |11881188+ BIT(NL80211_STA_FLAG_ASSOCIATED);11891189+ mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED) |11901190+ BIT(NL80211_STA_FLAG_ASSOCIATED);11911191+ }11831192 }1184119311851194 ret = sta_apply_auth_flags(local, sta, mask, set);···12761261 if (ieee80211_vif_is_mesh(&sdata->vif)) {12771262#ifdef CONFIG_MAC80211_MESH12781263 u32 changed = 0;12791279- if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) {12641264+12651265+ if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) {12801266 switch (params->plink_state) {12811267 case NL80211_PLINK_ESTAB:12821268 if (sta->plink_state != NL80211_PLINK_ESTAB)···13081292 /* nothing */13091293 break;13101294 }13111311- } else {13121312- switch (params->plink_action) {13131313- case PLINK_ACTION_OPEN:13141314- changed |= mesh_plink_open(sta);13151315- break;13161316- case PLINK_ACTION_BLOCK:13171317- changed |= mesh_plink_block(sta);13181318- break;13191319- }12951295+ }12961296+12971297+ switch (params->plink_action) {12981298+ case NL80211_PLINK_ACTION_NO_ACTION:12991299+ /* nothing */13001300+ break;13011301+ case NL80211_PLINK_ACTION_OPEN:13021302+ changed |= mesh_plink_open(sta);13031303+ break;13041304+ case NL80211_PLINK_ACTION_BLOCK:13051305+ changed |= mesh_plink_block(sta);13061306+ break;13201307 }1321130813221309 if (params->local_pm)···13651346 * defaults -- if userspace wants something else we'll13661347 * change it accordingly in sta_apply_parameters()13671348 */13681368- sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);13691369- sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);13491349+ if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) {13501350+ sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);13511351+ sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);13521352+ }1370135313711354 err = sta_apply_parameters(local, sta, params);13721355 if (err) {···13771356 }1378135713791358 /*13801380- * for TDLS, rate control should be initialized only when supported13811381- * rates are known.13591359+ * for TDLS, rate control should be initialized only when13601360+ * rates are known and station is marked authorized13821361 */13831362 if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER))13841363 rate_control_rate_init(sta);···14151394}1416139514171396static int ieee80211_change_station(struct wiphy *wiphy,14181418- struct net_device *dev,14191419- u8 *mac,13971397+ struct net_device *dev, u8 *mac,14201398 struct station_parameters *params)14211399{14221400 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);14231401 struct ieee80211_local *local = wiphy_priv(wiphy);14241402 struct sta_info *sta;14251403 struct ieee80211_sub_if_data *vlansdata;14041404+ enum cfg80211_station_type statype;14261405 int err;1427140614281407 mutex_lock(&local->sta_mtx);1429140814301409 sta = sta_info_get_bss(sdata, mac);14311410 if (!sta) {14321432- mutex_unlock(&local->sta_mtx);14331433- return -ENOENT;14111411+ err = -ENOENT;14121412+ goto out_err;14341413 }1435141414361436- /* in station mode, some updates are only valid with TDLS */14371437- if (sdata->vif.type == NL80211_IFTYPE_STATION &&14381438- (params->supported_rates || params->ht_capa || params->vht_capa ||14391439- params->sta_modify_mask ||14401440- (params->sta_flags_mask & BIT(NL80211_STA_FLAG_WME))) &&14411441- !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {14421442- mutex_unlock(&local->sta_mtx);14431443- return -EINVAL;14151415+ switch (sdata->vif.type) {14161416+ case NL80211_IFTYPE_MESH_POINT:14171417+ if (sdata->u.mesh.user_mpm)14181418+ statype = CFG80211_STA_MESH_PEER_USER;14191419+ else14201420+ statype = CFG80211_STA_MESH_PEER_KERNEL;14211421+ break;14221422+ case NL80211_IFTYPE_ADHOC:14231423+ statype = CFG80211_STA_IBSS;14241424+ break;14251425+ case NL80211_IFTYPE_STATION:14261426+ if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {14271427+ statype = CFG80211_STA_AP_STA;14281428+ break;14291429+ }14301430+ if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))14311431+ statype = CFG80211_STA_TDLS_PEER_ACTIVE;14321432+ else14331433+ statype = CFG80211_STA_TDLS_PEER_SETUP;14341434+ break;14351435+ case NL80211_IFTYPE_AP:14361436+ case NL80211_IFTYPE_AP_VLAN:14371437+ statype = CFG80211_STA_AP_CLIENT;14381438+ break;14391439+ default:14401440+ err = -EOPNOTSUPP;14411441+ goto out_err;14441442 }14431443+14441444+ err = cfg80211_check_station_change(wiphy, params, statype);14451445+ if (err)14461446+ goto out_err;1445144714461448 if (params->vlan && params->vlan != sta->sdata->dev) {14471449 bool prev_4addr = false;···1472142814731429 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);1474143014751475- if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN &&14761476- vlansdata->vif.type != NL80211_IFTYPE_AP) {14771477- mutex_unlock(&local->sta_mtx);14781478- return -EINVAL;14791479- }14801480-14811431 if (params->vlan->ieee80211_ptr->use_4addr) {14821432 if (vlansdata->u.vlan.sta) {14831483- mutex_unlock(&local->sta_mtx);14841484- return -EBUSY;14331433+ err = -EBUSY;14341434+ goto out_err;14851435 }1486143614871437 rcu_assign_pointer(vlansdata->u.vlan.sta, sta);···15021464 }1503146515041466 err = sta_apply_parameters(local, sta, params);15051505- if (err) {15061506- mutex_unlock(&local->sta_mtx);15071507- return err;15081508- }14671467+ if (err)14681468+ goto out_err;1509146915101510- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates)14701470+ /* When peer becomes authorized, init rate control as well */14711471+ if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&14721472+ test_sta_flag(sta, WLAN_STA_AUTHORIZED))15111473 rate_control_rate_init(sta);1512147415131475 mutex_unlock(&local->sta_mtx);···15171479 ieee80211_recalc_ps(local, -1);15181480 ieee80211_recalc_ps_vif(sdata);15191481 }14821482+15201483 return 0;14841484+out_err:14851485+ mutex_unlock(&local->sta_mtx);14861486+ return err;15211487}1522148815231489#ifdef CONFIG_MAC80211_MESH···17291687 ifmsh->mesh_sp_id = setup->sync_method;17301688 ifmsh->mesh_pp_id = setup->path_sel_proto;17311689 ifmsh->mesh_pm_id = setup->path_metric;16901690+ ifmsh->user_mpm = setup->user_mpm;17321691 ifmsh->security = IEEE80211_MESH_SEC_NONE;17331692 if (setup->is_authenticated)17341693 ifmsh->security |= IEEE80211_MESH_SEC_AUTHED;···17731730 conf->dot11MeshTTL = nconf->dot11MeshTTL;17741731 if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask))17751732 conf->element_ttl = nconf->element_ttl;17761776- if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask))17331733+ if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) {17341734+ if (ifmsh->user_mpm)17351735+ return -EBUSY;17771736 conf->auto_open_plinks = nconf->auto_open_plinks;17371737+ }17781738 if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask))17791739 conf->dot11MeshNbrOffsetMaxNeighbor =17801740 nconf->dot11MeshNbrOffsetMaxNeighbor;···24172371 struct ieee80211_sub_if_data *sdata,24182372 struct ieee80211_channel *channel,24192373 unsigned int duration, u64 *cookie,24202420- struct sk_buff *txskb)23742374+ struct sk_buff *txskb,23752375+ enum ieee80211_roc_type type)24212376{24222377 struct ieee80211_roc_work *roc, *tmp;24232378 bool queued = false;···24372390 roc->duration = duration;24382391 roc->req_duration = duration;24392392 roc->frame = txskb;23932393+ roc->type = type;24402394 roc->mgmt_tx_cookie = (unsigned long)txskb;24412395 roc->sdata = sdata;24422396 INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);···24682420 if (!duration)24692421 duration = 10;2470242224712471- ret = drv_remain_on_channel(local, sdata, channel, duration);24232423+ ret = drv_remain_on_channel(local, sdata, channel, duration, type);24722424 if (ret) {24732425 kfree(roc);24742426 return ret;···24872439 *24882440 * If it hasn't started yet, just increase the duration24892441 * and add the new one to the list of dependents.24422442+ * If the type of the new ROC has higher priority, modify the24432443+ * type of the previous one to match that of the new one.24902444 */24912445 if (!tmp->started) {24922446 list_add_tail(&roc->list, &tmp->dependents);24932447 tmp->duration = max(tmp->duration, roc->duration);24482448+ tmp->type = max(tmp->type, roc->type);24942449 queued = true;24952450 break;24962451 }···25052454 /*25062455 * In the offloaded ROC case, if it hasn't begun, add25072456 * this new one to the dependent list to be handled25082508- * when the the master one begins. If it has begun,24572457+ * when the master one begins. If it has begun,25092458 * check that there's still a minimum time left and25102459 * if so, start this one, transmitting the frame, but25112511- * add it to the list directly after this one with a24602460+ * add it to the list directly after this one with25122461 * a reduced time so we'll ask the driver to execute25132462 * it right after finishing the previous one, in the25142463 * hope that it'll also be executed right afterwards,25152464 * effectively extending the old one.25162465 * If there's no minimum time left, just add it to the25172466 * normal list.24672467+ * TODO: the ROC type is ignored here, assuming that it24682468+ * is better to immediately use the current ROC.25182469 */25192470 if (!tmp->hw_begun) {25202471 list_add_tail(&roc->list, &tmp->dependents);···2610255726112558 mutex_lock(&local->mtx);26122559 ret = ieee80211_start_roc_work(local, sdata, chan,26132613- duration, cookie, NULL);25602560+ duration, cookie, NULL,25612561+ IEEE80211_ROC_TYPE_NORMAL);26142562 mutex_unlock(&local->mtx);2615256326162564 return ret;···2844279028452791 /* This will handle all kinds of coalescing and immediate TX */28462792 ret = ieee80211_start_roc_work(local, sdata, chan,28472847- wait, cookie, skb);27932793+ wait, cookie, skb,27942794+ IEEE80211_ROC_TYPE_MGMT_TX);28482795 if (ret)28492796 kfree_skb(skb);28502797 out_unlock:···33403285 struct cfg80211_chan_def *chandef)33413286{33423287 struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);32883288+ struct ieee80211_local *local = wiphy_priv(wiphy);33433289 struct ieee80211_chanctx_conf *chanctx_conf;33443290 int ret = -ENODATA;33453291···33483292 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);33493293 if (chanctx_conf) {33503294 *chandef = chanctx_conf->def;32953295+ ret = 0;32963296+ } else if (local->open_count > 0 &&32973297+ local->open_count == local->monitors &&32983298+ sdata->vif.type == NL80211_IFTYPE_MONITOR) {32993299+ if (local->use_chanctx)33003300+ *chandef = local->monitor_chandef;33013301+ else33023302+ cfg80211_chandef_create(chandef,33033303+ local->_oper_channel,33043304+ local->_oper_channel_type);33513305 ret = 0;33523306 }33533307 rcu_read_unlock();
···787787static inline int drv_remain_on_channel(struct ieee80211_local *local,788788 struct ieee80211_sub_if_data *sdata,789789 struct ieee80211_channel *chan,790790- unsigned int duration)790790+ unsigned int duration,791791+ enum ieee80211_roc_type type)791792{792793 int ret;793794794795 might_sleep();795796796796- trace_drv_remain_on_channel(local, sdata, chan, duration);797797+ trace_drv_remain_on_channel(local, sdata, chan, duration, type);797798 ret = local->ops->remain_on_channel(&local->hw, &sdata->vif,798798- chan, duration);799799+ chan, duration, type);799800 trace_drv_return_int(local, ret);800801801802 return ret;
+25-27
net/mac80211/ht.c
···4040 if (!ht_cap->ht_supported)4141 return;42424343- if (sdata->vif.type != NL80211_IFTYPE_STATION) {4444- /* AP interfaces call this code when adding new stations,4545- * so just silently ignore non station interfaces.4646- */4747- return;4848- }4949-5043 /* NOTE: If you add more over-rides here, update register_hw5144 * ht_capa_mod_msk logic in main.c as well.5245 * And, if this method can ever change ht_cap.ht_supported, fix···9097 const struct ieee80211_ht_cap *ht_cap_ie,9198 struct sta_info *sta)9299{9393- struct ieee80211_sta_ht_cap ht_cap;100100+ struct ieee80211_sta_ht_cap ht_cap, own_cap;94101 u8 ampdu_info, tx_mcs_set_cap;95102 int i, max_tx_streams;96103 bool changed;···104111105112 ht_cap.ht_supported = true;106113114114+ own_cap = sband->ht_cap;115115+116116+ /*117117+ * If user has specified capability over-rides, take care118118+ * of that if the station we're setting up is the AP that119119+ * we advertised a restricted capability set to. Override120120+ * our own capabilities and then use those below.121121+ */122122+ if (sdata->vif.type == NL80211_IFTYPE_STATION &&123123+ !test_sta_flag(sta, WLAN_STA_TDLS_PEER))124124+ ieee80211_apply_htcap_overrides(sdata, &own_cap);125125+107126 /*108127 * The bits listed in this expression should be109128 * the same for the peer and us, if the station···123118 * we mask them out.124119 */125120 ht_cap.cap = le16_to_cpu(ht_cap_ie->cap_info) &126126- (sband->ht_cap.cap |127127- ~(IEEE80211_HT_CAP_LDPC_CODING |128128- IEEE80211_HT_CAP_SUP_WIDTH_20_40 |129129- IEEE80211_HT_CAP_GRN_FLD |130130- IEEE80211_HT_CAP_SGI_20 |131131- IEEE80211_HT_CAP_SGI_40 |132132- IEEE80211_HT_CAP_DSSSCCK40));121121+ (own_cap.cap | ~(IEEE80211_HT_CAP_LDPC_CODING |122122+ IEEE80211_HT_CAP_SUP_WIDTH_20_40 |123123+ IEEE80211_HT_CAP_GRN_FLD |124124+ IEEE80211_HT_CAP_SGI_20 |125125+ IEEE80211_HT_CAP_SGI_40 |126126+ IEEE80211_HT_CAP_DSSSCCK40));133127134128 /*135129 * The STBC bits are asymmetric -- if we don't have136130 * TX then mask out the peer's RX and vice versa.137131 */138138- if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC))132132+ if (!(own_cap.cap & IEEE80211_HT_CAP_TX_STBC))139133 ht_cap.cap &= ~IEEE80211_HT_CAP_RX_STBC;140140- if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC))134134+ if (!(own_cap.cap & IEEE80211_HT_CAP_RX_STBC))141135 ht_cap.cap &= ~IEEE80211_HT_CAP_TX_STBC;142136143137 ampdu_info = ht_cap_ie->ampdu_params_info;···146142 (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;147143148144 /* own MCS TX capabilities */149149- tx_mcs_set_cap = sband->ht_cap.mcs.tx_params;145145+ tx_mcs_set_cap = own_cap.mcs.tx_params;150146151147 /* Copy peer MCS TX capabilities, the driver might need them. */152148 ht_cap.mcs.tx_params = ht_cap_ie->mcs.tx_params;···172168 */173169 for (i = 0; i < max_tx_streams; i++)174170 ht_cap.mcs.rx_mask[i] =175175- sband->ht_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i];171171+ own_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i];176172177173 if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION)178174 for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE;179175 i < IEEE80211_HT_MCS_MASK_LEN; i++)180176 ht_cap.mcs.rx_mask[i] =181181- sband->ht_cap.mcs.rx_mask[i] &177177+ own_cap.mcs.rx_mask[i] &182178 ht_cap_ie->mcs.rx_mask[i];183179184180 /* handle MCS rate 32 too */185185- if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)181181+ if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)186182 ht_cap.mcs.rx_mask[32/8] |= 1;187183188184 apply:189189- /*190190- * If user has specified capability over-rides, take care191191- * of that here.192192- */193193- ieee80211_apply_htcap_overrides(sdata, &ht_cap);194194-195185 changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap));196186197187 memcpy(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap));
···315315 u32 duration, req_duration;316316 struct sk_buff *frame;317317 u64 cookie, mgmt_tx_cookie;318318+ enum ieee80211_roc_type type;318319};319320320321/* flags used in struct ieee80211_if_managed.flags */···401400402401 u16 aid;403402404404- unsigned long timers_running; /* used for quiesce/restart */405403 bool powersave; /* powersave requested for this iface */406404 bool broken_ap; /* AP is broken -- turn off powersave */407405 u8 dtim_period;···479479480480 struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */481481 struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */482482+ struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */483483+ struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */482484};483485484486struct ieee80211_if_ibss {···491489 unsigned long last_scan_completed;492490493491 u32 basic_rates;494494-495495- bool timer_running;496492497493 bool fixed_bssid;498494 bool fixed_channel;···543543 struct timer_list mesh_path_timer;544544 struct timer_list mesh_path_root_timer;545545546546- unsigned long timers_running;547547-548546 unsigned long wrkq_flags;549547550548 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];···588590 IEEE80211_MESH_SEC_AUTHED = 0x1,589591 IEEE80211_MESH_SEC_SECURED = 0x2,590592 } security;593593+ bool user_mpm;591594 /* Extensible Synchronization Framework */592595 const struct ieee80211_mesh_sync_ops *sync_ops;593596 s64 sync_offset_clockdrift_max;···681682682683 /* count for keys needing tailroom space allocation */683684 int crypto_tx_tailroom_needed_cnt;685685+ int crypto_tx_tailroom_pending_dec;686686+ struct delayed_work dec_tailroom_needed_wk;684687685688 struct net_device *dev;686689 struct ieee80211_local *local;···764763 struct dentry *default_multicast_key;765764 struct dentry *default_mgmt_key;766765 } debugfs;767767-#endif768768-769769-#ifdef CONFIG_PM770770- struct ieee80211_bss_conf suspend_bss_conf;771766#endif772767773768 /* must be last, dynamically sized area in this! */···1133113611341137 struct ieee80211_sub_if_data __rcu *p2p_sdata;1135113811361136- /* dummy netdev for use w/ NAPI */11371137- struct net_device napi_dev;11381138-11391139- struct napi_struct napi;11401140-11411139 /* virtual monitor interface */11421140 struct ieee80211_sub_if_data __rcu *monitor_sdata;11431141 struct cfg80211_chan_def monitor_chandef;···12751283ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,12761284 const struct ieee80211_channel_sw_ie *sw_elem,12771285 struct ieee80211_bss *bss, u64 timestamp);12781278-void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata);12791279-void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);12801286void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);12811287void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,12821288 struct sk_buff *skb);···12921302int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,12931303 struct cfg80211_ibss_params *params);12941304int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);12951295-void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata);12961296-void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata);12971305void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata);12981306void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,12991307 struct sk_buff *skb);···14291441void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,14301442 struct sta_info *sta, u8 opmode,14311443 enum ieee80211_band band, bool nss_only);14441444+void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,14451445+ struct ieee80211_sta_vht_cap *vht_cap);1432144614331447/* Spectrum management */14341448void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
+14-8
net/mac80211/iface.c
···107107108108 lockdep_assert_held(&local->mtx);109109110110- active = !list_empty(&local->chanctx_list);110110+ active = !list_empty(&local->chanctx_list) || local->monitors;111111112112 if (!local->ops->remain_on_channel) {113113 list_for_each_entry(roc, &local->roc_list, list) {···485485 res = drv_start(local);486486 if (res)487487 goto err_del_bss;488488- if (local->ops->napi_poll)489489- napi_enable(&local->napi);490488 /* we're brought up, everything changes */491489 hw_reconf_flags = ~0;492490 ieee80211_led_radio(local, true);···539541540542 ieee80211_adjust_monitor_flags(sdata, 1);541543 ieee80211_configure_filter(local);544544+ mutex_lock(&local->mtx);545545+ ieee80211_recalc_idle(local);546546+ mutex_unlock(&local->mtx);542547543548 netif_carrier_on(dev);544549 break;···813812814813 ieee80211_adjust_monitor_flags(sdata, -1);815814 ieee80211_configure_filter(local);815815+ mutex_lock(&local->mtx);816816+ ieee80211_recalc_idle(local);817817+ mutex_unlock(&local->mtx);816818 break;817819 case NL80211_IFTYPE_P2P_DEVICE:818820 /* relies on synchronize_rcu() below */···836832 rcu_barrier();837833 sta_info_flush_cleanup(sdata);838834839839- skb_queue_purge(&sdata->skb_queue);840840-841835 /*842836 * Free all remaining keys, there shouldn't be any,843843- * except maybe group keys in AP more or WDS?837837+ * except maybe in WDS mode?844838 */845839 ieee80211_free_keys(sdata);840840+841841+ /* fall through */842842+ case NL80211_IFTYPE_AP:843843+ skb_queue_purge(&sdata->skb_queue);846844847845 drv_remove_interface_debugfs(local, sdata);848846···857851 ieee80211_recalc_ps(local, -1);858852859853 if (local->open_count == 0) {860860- if (local->ops->napi_poll)861861- napi_disable(&local->napi);862854 ieee80211_clear_tx_pending(local);863855 ieee80211_stop_device(local);864856···15451541 INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);15461542 INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,15471543 ieee80211_dfs_cac_timer_work);15441544+ INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk,15451545+ ieee80211_delayed_tailroom_dec);1548154615491547 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {15501548 struct ieee80211_supported_band *sband;
+56-47
net/mac80211/key.c
···397397 return key;398398}399399400400-static void __ieee80211_key_destroy(struct ieee80211_key *key)400400+static void __ieee80211_key_destroy(struct ieee80211_key *key,401401+ bool delay_tailroom)401402{402403 if (!key)403404 return;···417416 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)418417 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);419418 if (key->local) {419419+ struct ieee80211_sub_if_data *sdata = key->sdata;420420+420421 ieee80211_debugfs_key_remove(key);421421- key->sdata->crypto_tx_tailroom_needed_cnt--;422422+423423+ if (delay_tailroom) {424424+ /* see ieee80211_delayed_tailroom_dec */425425+ sdata->crypto_tx_tailroom_pending_dec++;426426+ schedule_delayed_work(&sdata->dec_tailroom_needed_wk,427427+ HZ/2);428428+ } else {429429+ sdata->crypto_tx_tailroom_needed_cnt--;430430+ }422431 }423432424433 kfree(key);···451440 key->sdata = sdata;452441 key->sta = sta;453442454454- if (sta) {455455- /*456456- * some hardware cannot handle TKIP with QoS, so457457- * we indicate whether QoS could be in use.458458- */459459- if (test_sta_flag(sta, WLAN_STA_WME))460460- key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;461461- } else {462462- if (sdata->vif.type == NL80211_IFTYPE_STATION) {463463- struct sta_info *ap;464464-465465- /*466466- * We're getting a sta pointer in, so must be under467467- * appropriate locking for sta_info_get().468468- */469469-470470- /* same here, the AP could be using QoS */471471- ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);472472- if (ap) {473473- if (test_sta_flag(ap, WLAN_STA_WME))474474- key->conf.flags |=475475- IEEE80211_KEY_FLAG_WMM_STA;476476- }477477- }478478- }479479-480443 mutex_lock(&sdata->local->key_mtx);481444482445 if (sta && pairwise)···463478 increment_tailroom_need_count(sdata);464479465480 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key);466466- __ieee80211_key_destroy(old_key);481481+ __ieee80211_key_destroy(old_key, true);467482468483 ieee80211_debugfs_key_add(key);469484···474489 return ret;475490}476491477477-void __ieee80211_key_free(struct ieee80211_key *key)492492+void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)478493{479494 if (!key)480495 return;···486501 __ieee80211_key_replace(key->sdata, key->sta,487502 key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,488503 key, NULL);489489- __ieee80211_key_destroy(key);504504+ __ieee80211_key_destroy(key, delay_tailroom);490505}491506492507void ieee80211_key_free(struct ieee80211_local *local,493508 struct ieee80211_key *key)494509{495510 mutex_lock(&local->key_mtx);496496- __ieee80211_key_free(key);511511+ __ieee80211_key_free(key, true);497512 mutex_unlock(&local->key_mtx);498513}499514···551566}552567EXPORT_SYMBOL(ieee80211_iter_keys);553568554554-void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)555555-{556556- struct ieee80211_key *key;557557-558558- ASSERT_RTNL();559559-560560- mutex_lock(&sdata->local->key_mtx);561561-562562- list_for_each_entry(key, &sdata->key_list, list)563563- ieee80211_key_disable_hw_accel(key);564564-565565- mutex_unlock(&sdata->local->key_mtx);566566-}567567-568569void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)569570{570571 struct ieee80211_key *key, *tmp;571572573573+ cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);574574+572575 mutex_lock(&sdata->local->key_mtx);576576+577577+ sdata->crypto_tx_tailroom_needed_cnt -=578578+ sdata->crypto_tx_tailroom_pending_dec;579579+ sdata->crypto_tx_tailroom_pending_dec = 0;573580574581 ieee80211_debugfs_key_remove_mgmt_default(sdata);575582576583 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)577577- __ieee80211_key_free(key);584584+ __ieee80211_key_free(key, false);578585579586 ieee80211_debugfs_key_update_default(sdata);587587+588588+ WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||589589+ sdata->crypto_tx_tailroom_pending_dec);580590581591 mutex_unlock(&sdata->local->key_mtx);582592}583593594594+void ieee80211_delayed_tailroom_dec(struct work_struct *wk)595595+{596596+ struct ieee80211_sub_if_data *sdata;597597+598598+ sdata = container_of(wk, struct ieee80211_sub_if_data,599599+ dec_tailroom_needed_wk.work);600600+601601+ /*602602+ * The reason for the delayed tailroom needed decrementing is to603603+ * make roaming faster: during roaming, all keys are first deleted604604+ * and then new keys are installed. The first new key causes the605605+ * crypto_tx_tailroom_needed_cnt to go from 0 to 1, which invokes606606+ * the cost of synchronize_net() (which can be slow). Avoid this607607+ * by deferring the crypto_tx_tailroom_needed_cnt decrementing on608608+ * key removal for a while, so if we roam the value is larger than609609+ * zero and no 0->1 transition happens.610610+ *611611+ * The cost is that if the AP switching was from an AP with keys612612+ * to one without, we still allocate tailroom while it would no613613+ * longer be needed. However, in the typical (fast) roaming case614614+ * within an ESS this usually won't happen.615615+ */616616+617617+ mutex_lock(&sdata->local->key_mtx);618618+ sdata->crypto_tx_tailroom_needed_cnt -=619619+ sdata->crypto_tx_tailroom_pending_dec;620620+ sdata->crypto_tx_tailroom_pending_dec = 0;621621+ mutex_unlock(&sdata->local->key_mtx);622622+}584623585624void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,586625 const u8 *replay_ctr, gfp_t gfp)
···66#include "driver-ops.h"77#include "led.h"8899-/* return value indicates whether the driver should be further notified */1010-static void ieee80211_quiesce(struct ieee80211_sub_if_data *sdata)1111-{1212- switch (sdata->vif.type) {1313- case NL80211_IFTYPE_STATION:1414- ieee80211_sta_quiesce(sdata);1515- break;1616- case NL80211_IFTYPE_ADHOC:1717- ieee80211_ibss_quiesce(sdata);1818- break;1919- case NL80211_IFTYPE_MESH_POINT:2020- ieee80211_mesh_quiesce(sdata);2121- break;2222- default:2323- break;2424- }2525-2626- cancel_work_sync(&sdata->work);2727-}2828-299int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)3010{3111 struct ieee80211_local *local = hw_to_local(hw);3212 struct ieee80211_sub_if_data *sdata;3313 struct sta_info *sta;3434- struct ieee80211_chanctx *ctx;35143615 if (!local->open_count)3716 goto suspend;···7293 return err;7394 } else if (err > 0) {7495 WARN_ON(err != 1);7575- local->wowlan = false;9696+ return err;7697 } else {7777- list_for_each_entry(sdata, &local->interfaces, list)7878- if (ieee80211_sdata_running(sdata))7979- ieee80211_quiesce(sdata);8098 goto suspend;8199 }82100 }8383-8484- /* disable keys */8585- list_for_each_entry(sdata, &local->interfaces, list)8686- ieee80211_disable_keys(sdata);8710188102 /* tear down aggregation sessions and remove STAs */89103 mutex_lock(&local->sta_mtx);···89117 WARN_ON(drv_sta_state(local, sta->sdata, sta,90118 state, state - 1));91119 }9292-9393- mesh_plink_quiesce(sta);94120 }95121 mutex_unlock(&local->sta_mtx);9612297123 /* remove all interfaces */98124 list_for_each_entry(sdata, &local->interfaces, list) {9999- static u8 zero_addr[ETH_ALEN] = {};100100- u32 changed = 0;101101-102125 if (!ieee80211_sdata_running(sdata))103126 continue;104104-105105- switch (sdata->vif.type) {106106- case NL80211_IFTYPE_AP_VLAN:107107- case NL80211_IFTYPE_MONITOR:108108- /* skip these */109109- continue;110110- case NL80211_IFTYPE_STATION:111111- if (sdata->vif.bss_conf.assoc)112112- changed = BSS_CHANGED_ASSOC |113113- BSS_CHANGED_BSSID |114114- BSS_CHANGED_IDLE;115115- break;116116- case NL80211_IFTYPE_AP:117117- case NL80211_IFTYPE_ADHOC:118118- case NL80211_IFTYPE_MESH_POINT:119119- if (sdata->vif.bss_conf.enable_beacon)120120- changed = BSS_CHANGED_BEACON_ENABLED;121121- break;122122- default:123123- break;124124- }125125-126126- ieee80211_quiesce(sdata);127127-128128- sdata->suspend_bss_conf = sdata->vif.bss_conf;129129- memset(&sdata->vif.bss_conf, 0, sizeof(sdata->vif.bss_conf));130130- sdata->vif.bss_conf.idle = true;131131- if (sdata->suspend_bss_conf.bssid)132132- sdata->vif.bss_conf.bssid = zero_addr;133133-134134- /* disable beaconing or remove association */135135- ieee80211_bss_info_change_notify(sdata, changed);136136-137137- if (sdata->vif.type == NL80211_IFTYPE_AP &&138138- rcu_access_pointer(sdata->u.ap.beacon))139139- drv_stop_ap(local, sdata);140140-141141- if (local->use_chanctx) {142142- struct ieee80211_chanctx_conf *conf;143143-144144- mutex_lock(&local->chanctx_mtx);145145- conf = rcu_dereference_protected(146146- sdata->vif.chanctx_conf,147147- lockdep_is_held(&local->chanctx_mtx));148148- if (conf) {149149- ctx = container_of(conf,150150- struct ieee80211_chanctx,151151- conf);152152- drv_unassign_vif_chanctx(local, sdata, ctx);153153- }154154-155155- mutex_unlock(&local->chanctx_mtx);156156- }157127 drv_remove_interface(local, sdata);158128 }159129160130 sdata = rtnl_dereference(local->monitor_sdata);161161- if (sdata) {162162- if (local->use_chanctx) {163163- struct ieee80211_chanctx_conf *conf;164164-165165- mutex_lock(&local->chanctx_mtx);166166- conf = rcu_dereference_protected(167167- sdata->vif.chanctx_conf,168168- lockdep_is_held(&local->chanctx_mtx));169169- if (conf) {170170- ctx = container_of(conf,171171- struct ieee80211_chanctx,172172- conf);173173- drv_unassign_vif_chanctx(local, sdata, ctx);174174- }175175-176176- mutex_unlock(&local->chanctx_mtx);177177- }178178-131131+ if (sdata)179132 drv_remove_interface(local, sdata);180180- }181133182182- mutex_lock(&local->chanctx_mtx);183183- list_for_each_entry(ctx, &local->chanctx_list, list)184184- drv_remove_chanctx(local, ctx);185185- mutex_unlock(&local->chanctx_mtx);134134+ /*135135+ * We disconnected on all interfaces before suspend, all channel136136+ * contexts should be released.137137+ */138138+ WARN_ON(!list_empty(&local->chanctx_list));186139187140 /* stop hardware - this must stop RX */188141 if (local->open_count)
+114-90
net/mac80211/rc80211_minstrel.c
···5555#include "rate.h"5656#include "rc80211_minstrel.h"57575858-#define SAMPLE_COLUMNS 105958#define SAMPLE_TBL(_mi, _idx, _col) \6059 _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col]6160···6970 return i;7071}71727373+/* find & sort topmost throughput rates */7474+static inline void7575+minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)7676+{7777+ int j = MAX_THR_RATES;7878+7979+ while (j > 0 && mi->r[i].cur_tp > mi->r[tp_list[j - 1]].cur_tp)8080+ j--;8181+ if (j < MAX_THR_RATES - 1)8282+ memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1));8383+ if (j < MAX_THR_RATES)8484+ tp_list[j] = i;8585+}8686+7287static void7388minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)7489{7575- u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0;7676- u32 max_prob = 0, index_max_prob = 0;9090+ u8 tmp_tp_rate[MAX_THR_RATES];9191+ u8 tmp_prob_rate = 0;7792 u32 usecs;7878- u32 p;7993 int i;80948181- mi->stats_update = jiffies;9595+ for (i=0; i < MAX_THR_RATES; i++)9696+ tmp_tp_rate[i] = 0;9797+8298 for (i = 0; i < mi->n_rates; i++) {8399 struct minstrel_rate *mr = &mi->r[i];84100···10187 if (!usecs)10288 usecs = 1000000;10389104104- /* To avoid rounding issues, probabilities scale from 0 (0%)105105- * to 18000 (100%) */106106- if (mr->attempts) {107107- p = (mr->success * 18000) / mr->attempts;9090+ if (unlikely(mr->attempts > 0)) {9191+ mr->sample_skipped = 0;9292+ mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts);10893 mr->succ_hist += mr->success;10994 mr->att_hist += mr->attempts;110110- mr->cur_prob = p;111111- p = ((p * (100 - mp->ewma_level)) + (mr->probability *112112- mp->ewma_level)) / 100;113113- mr->probability = p;114114- mr->cur_tp = p * (1000000 / usecs);115115- }9595+ mr->probability = minstrel_ewma(mr->probability,9696+ mr->cur_prob,9797+ EWMA_LEVEL);9898+ } else9999+ mr->sample_skipped++;116100117101 mr->last_success = mr->success;118102 mr->last_attempts = mr->attempts;119103 mr->success = 0;120104 mr->attempts = 0;121105106106+ /* Update throughput per rate, reset thr. below 10% success */107107+ if (mr->probability < MINSTREL_FRAC(10, 100))108108+ mr->cur_tp = 0;109109+ else110110+ mr->cur_tp = mr->probability * (1000000 / usecs);111111+122112 /* Sample less often below the 10% chance of success.123113 * Sample less often above the 95% chance of success. */124124- if ((mr->probability > 17100) || (mr->probability < 1800)) {114114+ if (mr->probability > MINSTREL_FRAC(95, 100) ||115115+ mr->probability < MINSTREL_FRAC(10, 100)) {125116 mr->adjusted_retry_count = mr->retry_count >> 1;126117 if (mr->adjusted_retry_count > 2)127118 mr->adjusted_retry_count = 2;···137118 }138119 if (!mr->adjusted_retry_count)139120 mr->adjusted_retry_count = 2;140140- }141121142142- for (i = 0; i < mi->n_rates; i++) {143143- struct minstrel_rate *mr = &mi->r[i];144144- if (max_tp < mr->cur_tp) {145145- index_max_tp = i;146146- max_tp = mr->cur_tp;147147- }148148- if (max_prob < mr->probability) {149149- index_max_prob = i;150150- max_prob = mr->probability;151151- }152152- }122122+ minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate);153123154154- max_tp = 0;155155- for (i = 0; i < mi->n_rates; i++) {156156- struct minstrel_rate *mr = &mi->r[i];157157-158158- if (i == index_max_tp)159159- continue;160160-161161- if (max_tp < mr->cur_tp) {162162- index_max_tp2 = i;163163- max_tp = mr->cur_tp;124124+ /* To determine the most robust rate (max_prob_rate) used at125125+ * 3rd mmr stage we distinct between two cases:126126+ * (1) if any success probabilitiy >= 95%, out of those rates127127+ * choose the maximum throughput rate as max_prob_rate128128+ * (2) if all success probabilities < 95%, the rate with129129+ * highest success probability is choosen as max_prob_rate */130130+ if (mr->probability >= MINSTREL_FRAC(95,100)) {131131+ if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp)132132+ tmp_prob_rate = i;133133+ } else {134134+ if (mr->probability >= mi->r[tmp_prob_rate].probability)135135+ tmp_prob_rate = i;164136 }165137 }166166- mi->max_tp_rate = index_max_tp;167167- mi->max_tp_rate2 = index_max_tp2;168168- mi->max_prob_rate = index_max_prob;138138+139139+ /* Assign the new rate set */140140+ memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate));141141+ mi->max_prob_rate = tmp_prob_rate;142142+143143+ /* Reset update timer */144144+ mi->stats_update = jiffies;169145}170146171147static void···221207minstrel_get_next_sample(struct minstrel_sta_info *mi)222208{223209 unsigned int sample_ndx;224224- sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column);225225- mi->sample_idx++;226226- if ((int) mi->sample_idx > (mi->n_rates - 2)) {227227- mi->sample_idx = 0;210210+ sample_ndx = SAMPLE_TBL(mi, mi->sample_row, mi->sample_column);211211+ mi->sample_row++;212212+ if ((int) mi->sample_row >= mi->n_rates) {213213+ mi->sample_row = 0;228214 mi->sample_column++;229215 if (mi->sample_column >= SAMPLE_COLUMNS)230216 mi->sample_column = 0;···242228 struct minstrel_priv *mp = priv;243229 struct ieee80211_tx_rate *ar = info->control.rates;244230 unsigned int ndx, sample_ndx = 0;245245- bool mrr;246246- bool sample_slower = false;247247- bool sample = false;231231+ bool mrr_capable;232232+ bool indirect_rate_sampling = false;233233+ bool rate_sampling = false;248234 int i, delta;249235 int mrr_ndx[3];250250- int sample_rate;236236+ int sampling_ratio;251237238238+ /* management/no-ack frames do not use rate control */252239 if (rate_control_send_low(sta, priv_sta, txrc))253240 return;254241255255- mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot;256256-257257- ndx = mi->max_tp_rate;258258-259259- if (mrr)260260- sample_rate = mp->lookaround_rate_mrr;242242+ /* check multi-rate-retry capabilities & adjust lookaround_rate */243243+ mrr_capable = mp->has_mrr &&244244+ !txrc->rts &&245245+ !txrc->bss_conf->use_cts_prot;246246+ if (mrr_capable)247247+ sampling_ratio = mp->lookaround_rate_mrr;261248 else262262- sample_rate = mp->lookaround_rate;249249+ sampling_ratio = mp->lookaround_rate;263250251251+ /* init rateindex [ndx] with max throughput rate */252252+ ndx = mi->max_tp_rate[0];253253+254254+ /* increase sum packet counter */264255 mi->packet_count++;265265- delta = (mi->packet_count * sample_rate / 100) -256256+257257+ delta = (mi->packet_count * sampling_ratio / 100) -266258 (mi->sample_count + mi->sample_deferred / 2);267259268260 /* delta > 0: sampling required */269269- if ((delta > 0) && (mrr || !mi->prev_sample)) {261261+ if ((delta > 0) && (mrr_capable || !mi->prev_sample)) {270262 struct minstrel_rate *msr;271263 if (mi->packet_count >= 10000) {272264 mi->sample_deferred = 0;···291271 mi->sample_count += (delta - mi->n_rates * 2);292272 }293273274274+ /* get next random rate sample */294275 sample_ndx = minstrel_get_next_sample(mi);295276 msr = &mi->r[sample_ndx];296296- sample = true;297297- sample_slower = mrr && (msr->perfect_tx_time >298298- mi->r[ndx].perfect_tx_time);277277+ rate_sampling = true;299278300300- if (!sample_slower) {279279+ /* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)280280+ * rate sampling method should be used.281281+ * Respect such rates that are not sampled for 20 interations.282282+ */283283+ if (mrr_capable &&284284+ msr->perfect_tx_time > mi->r[ndx].perfect_tx_time &&285285+ msr->sample_skipped < 20)286286+ indirect_rate_sampling = true;287287+288288+ if (!indirect_rate_sampling) {301289 if (msr->sample_limit != 0) {302290 ndx = sample_ndx;303291 mi->sample_count++;304292 if (msr->sample_limit > 0)305293 msr->sample_limit--;306306- } else {307307- sample = false;308308- }294294+ } else295295+ rate_sampling = false;309296 } else {310297 /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark311298 * packets that have the sampling rate deferred to the···324297 mi->sample_deferred++;325298 }326299 }327327- mi->prev_sample = sample;300300+ mi->prev_sample = rate_sampling;328301329302 /* If we're not using MRR and the sampling rate already330303 * has a probability of >95%, we shouldn't be attempting331304 * to use it, as this only wastes precious airtime */332332- if (!mrr && sample && (mi->r[ndx].probability > 17100))333333- ndx = mi->max_tp_rate;305305+ if (!mrr_capable && rate_sampling &&306306+ (mi->r[ndx].probability > MINSTREL_FRAC(95, 100)))307307+ ndx = mi->max_tp_rate[0];334308309309+ /* mrr setup for 1st stage */335310 ar[0].idx = mi->r[ndx].rix;336311 ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info);337312338338- if (!mrr) {339339- if (!sample)313313+ /* non mrr setup for 2nd stage */314314+ if (!mrr_capable) {315315+ if (!rate_sampling)340316 ar[0].count = mp->max_retry;341317 ar[1].idx = mi->lowest_rix;342318 ar[1].count = mp->max_retry;343319 return;344320 }345321346346- /* MRR setup */347347- if (sample) {348348- if (sample_slower)322322+ /* mrr setup for 2nd stage */323323+ if (rate_sampling) {324324+ if (indirect_rate_sampling)349325 mrr_ndx[0] = sample_ndx;350326 else351351- mrr_ndx[0] = mi->max_tp_rate;327327+ mrr_ndx[0] = mi->max_tp_rate[0];352328 } else {353353- mrr_ndx[0] = mi->max_tp_rate2;329329+ mrr_ndx[0] = mi->max_tp_rate[1];354330 }331331+332332+ /* mrr setup for 3rd & 4th stage */355333 mrr_ndx[1] = mi->max_prob_rate;356334 mrr_ndx[2] = 0;357335 for (i = 1; i < 4; i++) {···383351init_sample_table(struct minstrel_sta_info *mi)384352{385353 unsigned int i, col, new_idx;386386- unsigned int n_srates = mi->n_rates - 1;387354 u8 rnd[8];388355389356 mi->sample_column = 0;390390- mi->sample_idx = 0;391391- memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates);357357+ mi->sample_row = 0;358358+ memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates);392359393360 for (col = 0; col < SAMPLE_COLUMNS; col++) {394394- for (i = 0; i < n_srates; i++) {361361+ for (i = 0; i < mi->n_rates; i++) {395362 get_random_bytes(rnd, sizeof(rnd));396396- new_idx = (i + rnd[i & 7]) % n_srates;363363+ new_idx = (i + rnd[i & 7]) % mi->n_rates;397364398398- while (SAMPLE_TBL(mi, new_idx, col) != 0)399399- new_idx = (new_idx + 1) % n_srates;365365+ while (SAMPLE_TBL(mi, new_idx, col) != 0xff)366366+ new_idx = (new_idx + 1) % mi->n_rates;400367401401- /* Don't sample the slowest rate (i.e. slowest base402402- * rate). We must presume that the slowest rate works403403- * fine, or else other management frames will also be404404- * failing and the link will break */405405- SAMPLE_TBL(mi, new_idx, col) = i + 1;368368+ SAMPLE_TBL(mi, new_idx, col) = i;406369 }407370 }408371}···568541 * is much higher than with mrr */569542 mp->lookaround_rate = 5;570543 mp->lookaround_rate_mrr = 10;571571-572572- /* moving average weight for EWMA */573573- mp->ewma_level = 75;574544575545 /* maximum time that the hw is allowed to stay in one MRR segment */576546 mp->segment_size = 6000;
+26-5
net/mac80211/rc80211_minstrel.h
···99#ifndef __RC_MINSTREL_H1010#define __RC_MINSTREL_H11111212+#define EWMA_LEVEL 75 /* ewma weighting factor [%] */1313+#define SAMPLE_COLUMNS 10 /* number of columns in sample table */1414+1515+1616+/* scaled fraction values */1717+#define MINSTREL_SCALE 161818+#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)1919+#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)2020+2121+/* number of highest throughput rates to consider*/2222+#define MAX_THR_RATES 42323+2424+/*2525+ * Perform EWMA (Exponentially Weighted Moving Average) calculation2626+ */2727+static inline int2828+minstrel_ewma(int old, int new, int weight)2929+{3030+ return (new * (100 - weight) + old * weight) / 100;3131+}3232+3333+1234struct minstrel_rate {1335 int bitrate;1436 int rix;···4826 u32 attempts;4927 u32 last_attempts;5028 u32 last_success;2929+ u8 sample_skipped;51305231 /* parts per thousand */5332 u32 cur_prob;···68456946 unsigned int lowest_rix;70477171- unsigned int max_tp_rate;7272- unsigned int max_tp_rate2;7373- unsigned int max_prob_rate;4848+ u8 max_tp_rate[MAX_THR_RATES];4949+ u8 max_prob_rate;7450 unsigned int packet_count;7551 unsigned int sample_count;7652 int sample_deferred;77537878- unsigned int sample_idx;5454+ unsigned int sample_row;7955 unsigned int sample_column;80568157 int n_rates;···9573 unsigned int cw_min;9674 unsigned int cw_max;9775 unsigned int max_retry;9898- unsigned int ewma_level;9976 unsigned int segment_size;10077 unsigned int update_interval;10178 unsigned int lookaround_rate;
···1717#include "rc80211_minstrel_ht.h"18181919#define AVG_PKT_SIZE 12002020-#define SAMPLE_COLUMNS 102121-#define EWMA_LEVEL 7522202321/* Number of bits for an average sized packet */2422#define MCS_NBITS (AVG_PKT_SIZE << 3)···2426/* Number of symbols for a packet with (bps) bits per symbol */2527#define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps))26282727-/* Transmission time for a packet containing (syms) symbols */2929+/* Transmission time (nanoseconds) for a packet containing (syms) symbols */2830#define MCS_SYMBOL_TIME(sgi, syms) \2931 (sgi ? \3030- ((syms) * 18 + 4) / 5 : /* syms * 3.6 us */ \3131- (syms) << 2 /* syms * 4 us */ \3232+ ((syms) * 18000 + 4000) / 5 : /* syms * 3.6 us */ \3333+ ((syms) * 1000) << 2 /* syms * 4 us */ \3234 )33353436/* Transmit duration for the raw data part of an average sized packet */···6264}63656466#define CCK_DURATION(_bitrate, _short, _len) \6565- (10 /* SIFS */ + \6767+ (1000 * (10 /* SIFS */ + \6668 (_short ? 72 + 24 : 144 + 48 ) + \6767- (8 * (_len + 4) * 10) / (_bitrate))6969+ (8 * (_len + 4) * 10) / (_bitrate)))68706971#define CCK_ACK_DURATION(_bitrate, _short) \7072 (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \···125127#define MINSTREL_CCK_GROUP (ARRAY_SIZE(minstrel_mcs_groups) - 1)126128127129static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];128128-129129-/*130130- * Perform EWMA (Exponentially Weighted Moving Average) calculation131131- */132132-static int133133-minstrel_ewma(int old, int new, int weight)134134-{135135- return (new * (100 - weight) + old * weight) / 100;136136-}137130138131/*139132 * Look up an MCS group index based on mac80211 rate information···200211minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)201212{202213 struct minstrel_rate_stats *mr;203203- unsigned int usecs = 0;214214+ unsigned int nsecs = 0;215215+ unsigned int tp;204216205217 mr = &mi->groups[group].rates[rate];206218···211221 }212222213223 if (group != MINSTREL_CCK_GROUP)214214- usecs = mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);224224+ nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);215225216216- usecs += minstrel_mcs_groups[group].duration[rate];217217- mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability);226226+ nsecs += minstrel_mcs_groups[group].duration[rate];227227+ tp = 1000000 * ((mr->probability * 1000) / nsecs);228228+229229+ mr->cur_tp = MINSTREL_TRUNC(tp);218230}219231220232/*···300308 }301309 }302310303303- /* try to sample up to half of the available rates during each interval */304304- mi->sample_count *= 4;311311+ /* try to sample all available rates during each interval */312312+ mi->sample_count *= 8;305313306314 cur_prob = 0;307315 cur_prob_tp = 0;···312320 if (!mg->supported)313321 continue;314322315315- mr = minstrel_get_ratestats(mi, mg->max_prob_rate);316316- if (cur_prob_tp < mr->cur_tp &&317317- minstrel_mcs_groups[group].streams == 1) {318318- mi->max_prob_rate = mg->max_prob_rate;319319- cur_prob = mr->cur_prob;320320- cur_prob_tp = mr->cur_tp;321321- }322322-323323 mr = minstrel_get_ratestats(mi, mg->max_tp_rate);324324 if (cur_tp < mr->cur_tp) {325325 mi->max_tp_rate2 = mi->max_tp_rate;326326 cur_tp2 = cur_tp;327327 mi->max_tp_rate = mg->max_tp_rate;328328 cur_tp = mr->cur_tp;329329+ mi->max_prob_streams = minstrel_mcs_groups[group].streams - 1;329330 }330331331332 mr = minstrel_get_ratestats(mi, mg->max_tp_rate2);···327342 cur_tp2 = mr->cur_tp;328343 }329344 }345345+346346+ if (mi->max_prob_streams < 1)347347+ mi->max_prob_streams = 1;348348+349349+ for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {350350+ mg = &mi->groups[group];351351+ if (!mg->supported)352352+ continue;353353+ mr = minstrel_get_ratestats(mi, mg->max_prob_rate);354354+ if (cur_prob_tp < mr->cur_tp &&355355+ minstrel_mcs_groups[group].streams <= mi->max_prob_streams) {356356+ mi->max_prob_rate = mg->max_prob_rate;357357+ cur_prob = mr->cur_prob;358358+ cur_prob_tp = mr->cur_tp;359359+ }360360+ }361361+330362331363 mi->stats_update = jiffies;332364}···469467470468 if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {471469 mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);472472- mi->sample_tries = 2;470470+ mi->sample_tries = 1;473471 mi->sample_count--;474472 }475473···538536 mr->retry_updated = true;539537540538 group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];541541- tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len;539539+ tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000;542540543541 /* Contention time for first 2 tries */544542 ctime = (t_slot * cw) >> 1;···618616{619617 struct minstrel_rate_stats *mr;620618 struct minstrel_mcs_group_data *mg;619619+ unsigned int sample_dur, sample_group;621620 int sample_idx = 0;622621623622 if (mi->sample_wait > 0) {···629626 if (!mi->sample_tries)630627 return -1;631628632632- mi->sample_tries--;633629 mg = &mi->groups[mi->sample_group];634630 sample_idx = sample_table[mg->column][mg->index];635631 mr = &mg->rates[sample_idx];636636- sample_idx += mi->sample_group * MCS_GROUP_RATES;632632+ sample_group = mi->sample_group;633633+ sample_idx += sample_group * MCS_GROUP_RATES;637634 minstrel_next_sample_idx(mi);638635639636 /*···654651 * Make sure that lower rates get sampled only occasionally,655652 * if the link is working perfectly.656653 */657657- if (minstrel_get_duration(sample_idx) >658658- minstrel_get_duration(mi->max_tp_rate)) {654654+ sample_dur = minstrel_get_duration(sample_idx);655655+ if (sample_dur >= minstrel_get_duration(mi->max_tp_rate2) &&656656+ (mi->max_prob_streams <657657+ minstrel_mcs_groups[sample_group].streams ||658658+ sample_dur >= minstrel_get_duration(mi->max_prob_rate))) {659659 if (mr->sample_skipped < 20)660660 return -1;661661662662 if (mi->sample_slow++ > 2)663663 return -1;664664 }665665+ mi->sample_tries--;665666666667 return sample_idx;667668}
+1-5
net/mac80211/rc80211_minstrel_ht.h
···1616#define MINSTREL_MAX_STREAMS 31717#define MINSTREL_STREAM_GROUPS 418181919-/* scaled fraction values */2020-#define MINSTREL_SCALE 162121-#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)2222-#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)2323-2419#define MCS_GROUP_RATES 825202621struct mcs_group {···80858186 /* best probability rate */8287 unsigned int max_prob_rate;8888+ unsigned int max_prob_streams;83898490 /* time of last status update */8591 unsigned long stats_update;
+26-35
net/mac80211/rx.c
···648648 return RX_CONTINUE;649649}650650651651-#define SEQ_MODULO 0x1000652652-#define SEQ_MASK 0xfff653653-654654-static inline int seq_less(u16 sq1, u16 sq2)655655-{656656- return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1);657657-}658658-659659-static inline u16 seq_inc(u16 sq)660660-{661661- return (sq + 1) & SEQ_MASK;662662-}663663-664664-static inline u16 seq_sub(u16 sq1, u16 sq2)665665-{666666- return (sq1 - sq2) & SEQ_MASK;667667-}668668-669651static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,670652 struct tid_ampdu_rx *tid_agg_rx,671653 int index,···669687 __skb_queue_tail(frames, skb);670688671689no_frame:672672- tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);690690+ tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num);673691}674692675693static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata,···681699682700 lockdep_assert_held(&tid_agg_rx->reorder_lock);683701684684- while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {685685- index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %702702+ while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) {703703+ index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,704704+ tid_agg_rx->ssn) %686705 tid_agg_rx->buf_size;687706 ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,688707 frames);···710727 lockdep_assert_held(&tid_agg_rx->reorder_lock);711728712729 /* release the buffer until next missing frame */713713- index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %714714- tid_agg_rx->buf_size;730730+ index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,731731+ tid_agg_rx->ssn) % tid_agg_rx->buf_size;715732 if (!tid_agg_rx->reorder_buf[index] &&716733 tid_agg_rx->stored_mpdu_num) {717734 /*···739756 * Increment the head seq# also for the skipped slots.740757 */741758 tid_agg_rx->head_seq_num =742742- (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;759759+ (tid_agg_rx->head_seq_num +760760+ skipped) & IEEE80211_SN_MASK;743761 skipped = 0;744762 }745763 } else while (tid_agg_rx->reorder_buf[index]) {746764 ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,747765 frames);748748- index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %766766+ index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,767767+ tid_agg_rx->ssn) %749768 tid_agg_rx->buf_size;750769 }751770752771 if (tid_agg_rx->stored_mpdu_num) {753753- j = index = seq_sub(tid_agg_rx->head_seq_num,754754- tid_agg_rx->ssn) % tid_agg_rx->buf_size;772772+ j = index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,773773+ tid_agg_rx->ssn) %774774+ tid_agg_rx->buf_size;755775756776 for (; j != (index - 1) % tid_agg_rx->buf_size;757777 j = (j + 1) % tid_agg_rx->buf_size) {···795809 head_seq_num = tid_agg_rx->head_seq_num;796810797811 /* frame with out of date sequence number */798798- if (seq_less(mpdu_seq_num, head_seq_num)) {812812+ if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {799813 dev_kfree_skb(skb);800814 goto out;801815 }···804818 * If frame the sequence number exceeds our buffering window805819 * size release some previous frames to make room for this one.806820 */807807- if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) {808808- head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size));821821+ if (!ieee80211_sn_less(mpdu_seq_num, head_seq_num + buf_size)) {822822+ head_seq_num = ieee80211_sn_inc(823823+ ieee80211_sn_sub(mpdu_seq_num, buf_size));809824 /* release stored frames up to new head to stack */810825 ieee80211_release_reorder_frames(sdata, tid_agg_rx,811826 head_seq_num, frames);···814827815828 /* Now the new frame is always in the range of the reordering buffer */816829817817- index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size;830830+ index = ieee80211_sn_sub(mpdu_seq_num,831831+ tid_agg_rx->ssn) % tid_agg_rx->buf_size;818832819833 /* check if we already stored this frame */820834 if (tid_agg_rx->reorder_buf[index]) {···831843 */832844 if (mpdu_seq_num == tid_agg_rx->head_seq_num &&833845 tid_agg_rx->stored_mpdu_num == 0) {834834- tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);846846+ tid_agg_rx->head_seq_num =847847+ ieee80211_sn_inc(tid_agg_rx->head_seq_num);835848 ret = false;836849 goto out;837850 }···18831894 * 'align' will only take the values 0 or 2 here18841895 * since all frames are required to be aligned18851896 * to 2-byte boundaries when being passed to18861886- * mac80211. That also explains the __skb_push()18871887- * below.18971897+ * mac80211; the code here works just as well if18981898+ * that isn't true, but mac80211 assumes it can18991899+ * access fields as 2-byte aligned (e.g. for19001900+ * compare_ether_addr)18881901 */18891902 align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3;18901903 if (align) {···25432552 case WLAN_SP_MESH_PEERING_CONFIRM:25442553 if (!ieee80211_vif_is_mesh(&sdata->vif))25452554 goto invalid;25462546- if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)25552555+ if (sdata->u.mesh.user_mpm)25472556 /* userspace handles this frame */25482557 break;25492558 goto queue;
+9-2
net/mac80211/sta_info.c
···342342 INIT_WORK(&sta->drv_unblock_wk, sta_unblock);343343 INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);344344 mutex_init(&sta->ampdu_mlme.mtx);345345+#ifdef CONFIG_MAC80211_MESH346346+ if (ieee80211_vif_is_mesh(&sdata->vif) &&347347+ !sdata->u.mesh.user_mpm)348348+ init_timer(&sta->plink_timer);349349+#endif345350346351 memcpy(sta->sta.addr, addr, ETH_ALEN);347352 sta->local = local;···799794800795 mutex_lock(&local->key_mtx);801796 for (i = 0; i < NUM_DEFAULT_KEYS; i++)802802- __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));797797+ __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]),798798+ true);803799 if (sta->ptk)804804- __ieee80211_key_free(key_mtx_dereference(local, sta->ptk));800800+ __ieee80211_key_free(key_mtx_dereference(local, sta->ptk),801801+ true);805802 mutex_unlock(&local->key_mtx);806803807804 sta->dead = true;
-2
net/mac80211/sta_info.h
···281281 * @plink_state: peer link state282282 * @plink_timeout: timeout of peer link283283 * @plink_timer: peer link watch timer284284- * @plink_timer_was_running: used by suspend/resume to restore timers285284 * @t_offset: timing offset relative to this host286285 * @t_offset_setpoint: reference timing offset of this sta to be used when287286 * calculating clockdrift···378379 __le16 reason;379380 u8 plink_retries;380381 bool ignore_plink_timer;381381- bool plink_timer_was_running;382382 enum nl80211_plink_state plink_state;383383 u32 plink_timeout;384384 struct timer_list plink_timer;