Commit db33aa7e authored by Johannes Berg's avatar Johannes Berg

Merge branch 'cfg80211-mac80211-multi-bssid' into mac80211-next

This finally merges the multi-BSSID code. This is the result of a
long collaboration between the team at Qualcomm (Peng and Jouni)
and our team at Intel (mostly Sara).
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parents 9f308616 851ae31d
...@@ -2801,6 +2801,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ...@@ -2801,6 +2801,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
ieee80211_hw_set(hw, TDLS_WIDER_BW); ieee80211_hw_set(hw, TDLS_WIDER_BW);
if (rctbl) if (rctbl)
ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
* Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright (c) 2016 - 2017 Intel Deutschland GmbH * Copyright (c) 2016 - 2017 Intel Deutschland GmbH
* Copyright (c) 2018 Intel Corporation * Copyright (c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
...@@ -2475,6 +2475,7 @@ enum ieee80211_eid_ext { ...@@ -2475,6 +2475,7 @@ enum ieee80211_eid_ext {
WLAN_EID_EXT_HE_OPERATION = 36, WLAN_EID_EXT_HE_OPERATION = 36,
WLAN_EID_EXT_UORA = 37, WLAN_EID_EXT_UORA = 37,
WLAN_EID_EXT_HE_MU_EDCA = 38, WLAN_EID_EXT_HE_MU_EDCA = 38,
WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION = 55,
}; };
/* Action category code */ /* Action category code */
...@@ -2656,6 +2657,11 @@ enum ieee80211_tdls_actioncode { ...@@ -2656,6 +2657,11 @@ enum ieee80211_tdls_actioncode {
*/ */
#define WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING BIT(2) #define WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING BIT(2)
/* Multiple BSSID capability is set in the 6th bit of 3rd byte of the
* @WLAN_EID_EXT_CAPABILITY information element
*/
#define WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT BIT(6)
/* TDLS capabilities in the the 4th byte of @WLAN_EID_EXT_CAPABILITY */ /* TDLS capabilities in the the 4th byte of @WLAN_EID_EXT_CAPABILITY */
#define WLAN_EXT_CAPA4_TDLS_BUFFER_STA BIT(4) #define WLAN_EXT_CAPA4_TDLS_BUFFER_STA BIT(4)
#define WLAN_EXT_CAPA4_TDLS_PEER_PSM BIT(5) #define WLAN_EXT_CAPA4_TDLS_PEER_PSM BIT(5)
...@@ -2691,6 +2697,9 @@ enum ieee80211_tdls_actioncode { ...@@ -2691,6 +2697,9 @@ enum ieee80211_tdls_actioncode {
#define WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT BIT(5) #define WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT BIT(5)
#define WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT BIT(6) #define WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT BIT(6)
/* Defines support for enhanced multi-bssid advertisement*/
#define WLAN_EXT_CAPA11_EMA_SUPPORT BIT(1)
/* TDLS specific payload type in the LLC/SNAP header */ /* TDLS specific payload type in the LLC/SNAP header */
#define WLAN_TDLS_SNAP_RFTYPE 0x2 #define WLAN_TDLS_SNAP_RFTYPE 0x2
...@@ -2882,6 +2891,34 @@ enum ieee80211_sa_query_action { ...@@ -2882,6 +2891,34 @@ enum ieee80211_sa_query_action {
WLAN_ACTION_SA_QUERY_RESPONSE = 1, WLAN_ACTION_SA_QUERY_RESPONSE = 1,
}; };
/**
* struct ieee80211_bssid_index
*
* This structure refers to "Multiple BSSID-index element"
*
* @bssid_index: BSSID index
* @dtim_period: optional, overrides transmitted BSS dtim period
* @dtim_count: optional, overrides transmitted BSS dtim count
*/
struct ieee80211_bssid_index {
u8 bssid_index;
u8 dtim_period;
u8 dtim_count;
};
/**
* struct ieee80211_multiple_bssid_configuration
*
* This structure refers to "Multiple BSSID Configuration element"
*
* @bssid_count: total number of active BSSIDs in the set
* @profile_periodicity: the least number of beacon frames need to be received
* in order to discover all the nontransmitted BSSIDs in the set.
*/
struct ieee80211_multiple_bssid_configuration {
u8 bssid_count;
u8 profile_periodicity;
};
#define SUITE(oui, id) (((oui) << 8) | (id)) #define SUITE(oui, id) (((oui) << 8) | (id))
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015-2017 Intel Deutschland GmbH * Copyright 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018-2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
...@@ -2035,9 +2035,15 @@ struct cfg80211_bss_ies { ...@@ -2035,9 +2035,15 @@ struct cfg80211_bss_ies {
* a BSS that hides the SSID in its beacon, this points to the BSS struct * a BSS that hides the SSID in its beacon, this points to the BSS struct
* that holds the beacon data. @beacon_ies is still valid, of course, and * that holds the beacon data. @beacon_ies is still valid, of course, and
* points to the same data as hidden_beacon_bss->beacon_ies in that case. * points to the same data as hidden_beacon_bss->beacon_ies in that case.
* @transmitted_bss: pointer to the transmitted BSS, if this is a
* non-transmitted one (multi-BSSID support)
* @nontrans_list: list of non-transmitted BSS, if this is a transmitted one
* (multi-BSSID support)
* @signal: signal strength value (type depends on the wiphy's signal_type) * @signal: signal strength value (type depends on the wiphy's signal_type)
* @chains: bitmask for filled values in @chain_signal. * @chains: bitmask for filled values in @chain_signal.
* @chain_signal: per-chain signal strength of last received BSS in dBm. * @chain_signal: per-chain signal strength of last received BSS in dBm.
* @bssid_index: index in the multiple BSS set
* @max_bssid_indicator: max number of members in the BSS set
* @priv: private area for driver use, has at least wiphy->bss_priv_size bytes * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
*/ */
struct cfg80211_bss { struct cfg80211_bss {
...@@ -2049,6 +2055,8 @@ struct cfg80211_bss { ...@@ -2049,6 +2055,8 @@ struct cfg80211_bss {
const struct cfg80211_bss_ies __rcu *proberesp_ies; const struct cfg80211_bss_ies __rcu *proberesp_ies;
struct cfg80211_bss *hidden_beacon_bss; struct cfg80211_bss *hidden_beacon_bss;
struct cfg80211_bss *transmitted_bss;
struct list_head nontrans_list;
s32 signal; s32 signal;
...@@ -2059,6 +2067,9 @@ struct cfg80211_bss { ...@@ -2059,6 +2067,9 @@ struct cfg80211_bss {
u8 chains; u8 chains;
s8 chain_signal[IEEE80211_MAX_CHAINS]; s8 chain_signal[IEEE80211_MAX_CHAINS];
u8 bssid_index;
u8 max_bssid_indicator;
u8 priv[0] __aligned(sizeof(void *)); u8 priv[0] __aligned(sizeof(void *));
}; };
...@@ -4313,6 +4324,11 @@ struct cfg80211_pmsr_capabilities { ...@@ -4313,6 +4324,11 @@ struct cfg80211_pmsr_capabilities {
* @txq_memory_limit: configuration internal TX queue memory limit * @txq_memory_limit: configuration internal TX queue memory limit
* @txq_quantum: configuration of internal TX queue scheduler quantum * @txq_quantum: configuration of internal TX queue scheduler quantum
* *
* @support_mbssid: can HW support association with nontransmitted AP
* @support_only_he_mbssid: don't parse MBSSID elements if it is not
* HE AP, in order to avoid compatibility issues.
* @support_mbssid must be set for this to have any effect.
*
* @pmsr_capa: peer measurement capabilities * @pmsr_capa: peer measurement capabilities
*/ */
struct wiphy { struct wiphy {
...@@ -4453,6 +4469,9 @@ struct wiphy { ...@@ -4453,6 +4469,9 @@ struct wiphy {
u32 txq_memory_limit; u32 txq_memory_limit;
u32 txq_quantum; u32 txq_quantum;
u8 support_mbssid:1,
support_only_he_mbssid:1;
const struct cfg80211_pmsr_capabilities *pmsr_capa; const struct cfg80211_pmsr_capabilities *pmsr_capa;
char priv[0] __aligned(NETDEV_ALIGN); char priv[0] __aligned(NETDEV_ALIGN);
...@@ -5451,6 +5470,29 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, ...@@ -5451,6 +5470,29 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
return cfg80211_inform_bss_frame_data(wiphy, &data, mgmt, len, gfp); return cfg80211_inform_bss_frame_data(wiphy, &data, mgmt, len, gfp);
} }
/**
* cfg80211_gen_new_bssid - generate a nontransmitted BSSID for multi-BSSID
* @bssid: transmitter BSSID
* @max_bssid: max BSSID indicator, taken from Multiple BSSID element
* @mbssid_index: BSSID index, taken from Multiple BSSID index element
* @new_bssid_addr: address of the resulting BSSID
*/
static inline void cfg80211_gen_new_bssid(const u8 *bssid, u8 max_bssid,
u8 mbssid_index, u8 *new_bssid_addr)
{
u64 bssid_tmp, new_bssid;
u64 lsb_n;
bssid_tmp = ether_addr_to_u64(bssid);
lsb_n = bssid_tmp & ((1 << max_bssid) - 1);
new_bssid = bssid_tmp;
new_bssid &= ~((1 << max_bssid) - 1);
new_bssid |= (lsb_n + mbssid_index) % (1 << max_bssid);
u64_to_ether_addr(new_bssid, new_bssid_addr);
}
/** /**
* enum cfg80211_bss_frame_type - frame type that the BSS data came from * enum cfg80211_bss_frame_type - frame type that the BSS data came from
* @CFG80211_BSS_FTYPE_UNKNOWN: driver doesn't know whether the data is * @CFG80211_BSS_FTYPE_UNKNOWN: driver doesn't know whether the data is
......
...@@ -591,6 +591,14 @@ struct ieee80211_ftm_responder_params { ...@@ -591,6 +591,14 @@ struct ieee80211_ftm_responder_params {
* @ftm_responder: whether to enable or disable fine timing measurement FTM * @ftm_responder: whether to enable or disable fine timing measurement FTM
* responder functionality. * responder functionality.
* @ftmr_params: configurable lci/civic parameter when enabling FTM responder. * @ftmr_params: configurable lci/civic parameter when enabling FTM responder.
* @nontransmitted: this BSS is a nontransmitted BSS profile
* @transmitter_bssid: the address of transmitter AP
* @bssid_index: index inside the multiple BSSID set
* @bssid_indicator: 2^bssid_indicator is the maximum number of APs in set
* @ema_ap: AP supports enhancements of discovery and advertisement of
* nontransmitted BSSIDs
* @profile_periodicity: the least number of beacon frames need to be received
* in order to discover all the nontransmitted BSSIDs in the set.
*/ */
struct ieee80211_bss_conf { struct ieee80211_bss_conf {
const u8 *bssid; const u8 *bssid;
...@@ -644,6 +652,13 @@ struct ieee80211_bss_conf { ...@@ -644,6 +652,13 @@ struct ieee80211_bss_conf {
bool protected_keep_alive; bool protected_keep_alive;
bool ftm_responder; bool ftm_responder;
struct ieee80211_ftm_responder_params *ftmr_params; struct ieee80211_ftm_responder_params *ftmr_params;
/* Multiple BSSID data */
bool nontransmitted;
u8 transmitter_bssid[ETH_ALEN];
u8 bssid_index;
u8 bssid_indicator;
bool ema_ap;
u8 profile_periodicity;
}; };
/** /**
...@@ -2219,6 +2234,11 @@ struct ieee80211_txq { ...@@ -2219,6 +2234,11 @@ struct ieee80211_txq {
* @IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN: Driver does not report accurate A-MPDU * @IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN: Driver does not report accurate A-MPDU
* length in tx status information * length in tx status information
* *
* @IEEE80211_HW_SUPPORTS_MULTI_BSSID: Hardware supports multi BSSID
*
* @IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID: Hardware supports multi BSSID
* only for HE APs. Applies if @IEEE80211_HW_SUPPORTS_MULTI_BSSID is set.
*
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/ */
enum ieee80211_hw_flags { enum ieee80211_hw_flags {
...@@ -2268,6 +2288,8 @@ enum ieee80211_hw_flags { ...@@ -2268,6 +2288,8 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW, IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW,
IEEE80211_HW_STA_MMPDU_TXQ, IEEE80211_HW_STA_MMPDU_TXQ,
IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN, IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN,
IEEE80211_HW_SUPPORTS_MULTI_BSSID,
IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
/* keep last, obviously */ /* keep last, obviously */
NUM_IEEE80211_HW_FLAGS NUM_IEEE80211_HW_FLAGS
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net> * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* *
* GPLv2 * GPLv2
* *
...@@ -219,6 +219,8 @@ static const char *hw_flag_names[] = { ...@@ -219,6 +219,8 @@ static const char *hw_flag_names[] = {
FLAG(SUPPORTS_VHT_EXT_NSS_BW), FLAG(SUPPORTS_VHT_EXT_NSS_BW),
FLAG(STA_MMPDU_TXQ), FLAG(STA_MMPDU_TXQ),
FLAG(TX_STATUS_NO_AMPDU_LEN), FLAG(TX_STATUS_NO_AMPDU_LEN),
FLAG(SUPPORTS_MULTI_BSSID),
FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
#undef FLAG #undef FLAG
}; };
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright 2009, Johannes Berg <johannes@sipsolutions.net> * Copyright 2009, Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH * Copyright(c) 2016 Intel Deutschland GmbH
* Copyright(c) 2018-2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
...@@ -1124,8 +1125,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ...@@ -1124,8 +1125,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
ieee80211_update_sta_info(sdata, mgmt, len, rx_status, elems, channel); ieee80211_update_sta_info(sdata, mgmt, len, rx_status, elems, channel);
bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, channel);
channel);
if (!bss) if (!bss)
return; return;
...@@ -1604,7 +1604,7 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -1604,7 +1604,7 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata,
return; return;
ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
false, &elems); false, &elems, mgmt->bssid, NULL);
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
} }
...@@ -1654,7 +1654,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ...@@ -1654,7 +1654,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
ieee802_11_parse_elems( ieee802_11_parse_elems(
mgmt->u.action.u.chan_switch.variable, mgmt->u.action.u.chan_switch.variable,
ies_len, true, &elems); ies_len, true, &elems, mgmt->bssid, NULL);
if (elems.parse_error) if (elems.parse_error)
break; break;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2015 Intel Mobile Communications GmbH * Copyright 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018-2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
...@@ -1495,6 +1495,12 @@ struct ieee802_11_elems { ...@@ -1495,6 +1495,12 @@ struct ieee802_11_elems {
const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
struct ieee80211_mesh_chansw_params_ie *mesh_chansw_params_ie; struct ieee80211_mesh_chansw_params_ie *mesh_chansw_params_ie;
const struct ieee80211_bss_max_idle_period_ie *max_idle_period_ie; const struct ieee80211_bss_max_idle_period_ie *max_idle_period_ie;
const struct ieee80211_multiple_bssid_configuration *mbssid_config_ie;
const struct ieee80211_bssid_index *bssid_index;
const u8 *nontransmitted_bssid_profile;
u8 max_bssid_indicator;
u8 dtim_count;
u8 dtim_period;
/* length of them, respectively */ /* length of them, respectively */
u8 ext_capab_len; u8 ext_capab_len;
...@@ -1513,6 +1519,7 @@ struct ieee802_11_elems { ...@@ -1513,6 +1519,7 @@ struct ieee802_11_elems {
u8 prep_len; u8 prep_len;
u8 perr_len; u8 perr_len;
u8 country_elem_len; u8 country_elem_len;
u8 bssid_index_len;
/* whether a parse error occurred while retrieving these elements */ /* whether a parse error occurred while retrieving these elements */
bool parse_error; bool parse_error;
...@@ -1672,7 +1679,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local, ...@@ -1672,7 +1679,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
struct ieee80211_rx_status *rx_status, struct ieee80211_rx_status *rx_status,
struct ieee80211_mgmt *mgmt, struct ieee80211_mgmt *mgmt,
size_t len, size_t len,
struct ieee802_11_elems *elems,
struct ieee80211_channel *channel); struct ieee80211_channel *channel);
void ieee80211_rx_bss_put(struct ieee80211_local *local, void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_bss *bss); struct ieee80211_bss *bss);
...@@ -1956,12 +1962,16 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, ...@@ -1956,12 +1962,16 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems, struct ieee802_11_elems *elems,
u64 filter, u32 crc); u64 filter, u32 crc, u8 *transmitter_bssid,
u8 *bss_bssid);
static inline void ieee802_11_parse_elems(const u8 *start, size_t len, static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
bool action, bool action,
struct ieee802_11_elems *elems) struct ieee802_11_elems *elems,
u8 *transmitter_bssid,
u8 *bss_bssid)
{ {
ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0,
transmitter_bssid, bss_bssid);
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH * Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
...@@ -1112,6 +1112,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -1112,6 +1112,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (ieee80211_hw_check(&local->hw, CHANCTX_STA_CSA)) if (ieee80211_hw_check(&local->hw, CHANCTX_STA_CSA))
local->ext_capa[0] |= WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING; local->ext_capa[0] |= WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING;
/* mac80211 supports multi BSSID, if the driver supports it */
if (ieee80211_hw_check(&local->hw, SUPPORTS_MULTI_BSSID)) {
local->hw.wiphy->support_mbssid = true;
if (ieee80211_hw_check(&local->hw,
SUPPORTS_ONLY_HE_MULTI_BSSID))
local->hw.wiphy->support_only_he_mbssid = true;
else
local->ext_capa[2] |=
WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT;
}
local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM; local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
result = wiphy_register(local->hw.wiphy); result = wiphy_register(local->hw.wiphy);
......
/* /*
* Copyright (c) 2008, 2009 open80211s Ltd. * Copyright (c) 2008, 2009 open80211s Ltd.
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* Authors: Luis Carlos Cobo <luisca@cozybit.com> * Authors: Luis Carlos Cobo <luisca@cozybit.com>
* Javier Cardona <javier@cozybit.com> * Javier Cardona <javier@cozybit.com>
* *
...@@ -1106,7 +1106,8 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, ...@@ -1106,7 +1106,8 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
if (baselen > len) if (baselen > len)
return; return;
ieee802_11_parse_elems(pos, len - baselen, false, &elems); ieee802_11_parse_elems(pos, len - baselen, false, &elems, mgmt->bssid,
NULL);
if (!elems.mesh_id) if (!elems.mesh_id)
return; return;
...@@ -1170,7 +1171,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, ...@@ -1170,7 +1171,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
return; return;
ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
false, &elems); false, &elems, mgmt->bssid, NULL);
/* ignore non-mesh or secure / unsecure mismatch */ /* ignore non-mesh or secure / unsecure mismatch */
if ((!elems.mesh_id || !elems.mesh_config) || if ((!elems.mesh_id || !elems.mesh_config) ||
...@@ -1306,7 +1307,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata, ...@@ -1306,7 +1307,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
pos = mgmt->u.action.u.chan_switch.variable; pos = mgmt->u.action.u.chan_switch.variable;
baselen = offsetof(struct ieee80211_mgmt, baselen = offsetof(struct ieee80211_mgmt,
u.action.u.chan_switch.variable); u.action.u.chan_switch.variable);
ieee802_11_parse_elems(pos, len - baselen, true, &elems); ieee802_11_parse_elems(pos, len - baselen, true, &elems,
mgmt->bssid, NULL);
ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl; ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
if (!--ifmsh->chsw_ttl) if (!--ifmsh->chsw_ttl)
......
/* /*
* Copyright (c) 2008, 2009 open80211s Ltd. * Copyright (c) 2008, 2009 open80211s Ltd.
* Copyright (C) 2019 Intel Corporation
* Author: Luis Carlos Cobo <luisca@cozybit.com> * Author: Luis Carlos Cobo <luisca@cozybit.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -926,7 +927,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, ...@@ -926,7 +927,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
len - baselen, false, &elems); len - baselen, false, &elems, mgmt->bssid, NULL);
if (elems.preq) { if (elems.preq) {
if (elems.preq_len != 37) if (elems.preq_len != 37)
......
/* /*
* Copyright (c) 2008, 2009 open80211s Ltd. * Copyright (c) 2008, 2009 open80211s Ltd.
* Copyright (C) 2019 Intel Corporation
* Author: Luis Carlos Cobo <luisca@cozybit.com> * Author: Luis Carlos Cobo <luisca@cozybit.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -1214,6 +1215,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, ...@@ -1214,6 +1215,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
if (baselen > len) if (baselen > len)
return; return;
} }
ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems); ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems,
mgmt->bssid, NULL);
mesh_process_plink_frame(sdata, mgmt, &elems, rx_status); mesh_process_plink_frame(sdata, mgmt, &elems, rx_status);
} }
This diff is collapsed.
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright 2007, Michael Wu <flamingice@sourmilk.net> * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2013-2015 Intel Mobile Communications GmbH * Copyright 2013-2015 Intel Mobile Communications GmbH
* Copyright 2016-2017 Intel Deutschland GmbH * Copyright 2016-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
...@@ -57,62 +58,14 @@ static bool is_uapsd_supported(struct ieee802_11_elems *elems) ...@@ -57,62 +58,14 @@ static bool is_uapsd_supported(struct ieee802_11_elems *elems)
return qos_info & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD; return qos_info & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD;
} }
struct ieee80211_bss * static void
ieee80211_bss_info_update(struct ieee80211_local *local, ieee80211_update_bss_from_elems(struct ieee80211_local *local,
struct ieee80211_rx_status *rx_status, struct ieee80211_bss *bss,
struct ieee80211_mgmt *mgmt, size_t len, struct ieee802_11_elems *elems,
struct ieee802_11_elems *elems, struct ieee80211_rx_status *rx_status,
struct ieee80211_channel *channel) bool beacon)
{ {
bool beacon = ieee80211_is_beacon(mgmt->frame_control);
struct cfg80211_bss *cbss;
struct ieee80211_bss *bss;
int clen, srlen; int clen, srlen;
struct cfg80211_inform_bss bss_meta = {
.boottime_ns = rx_status->boottime_ns,
};
bool signal_valid;
struct ieee80211_sub_if_data *scan_sdata;
if (rx_status->flag & RX_FLAG_NO_SIGNAL_VAL)
bss_meta.signal = 0; /* invalid signal indication */
else if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
bss_meta.signal = rx_status->signal * 100;
else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_20;
if (rx_status->bw == RATE_INFO_BW_5)
bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_5;
else if (rx_status->bw == RATE_INFO_BW_10)
bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10;
bss_meta.chan = channel;
rcu_read_lock();
scan_sdata = rcu_dereference(local->scan_sdata);
if (scan_sdata && scan_sdata->vif.type == NL80211_IFTYPE_STATION &&
scan_sdata->vif.bss_conf.assoc &&
ieee80211_have_rx_timestamp(rx_status)) {
bss_meta.parent_tsf =
ieee80211_calculate_rx_timestamp(local, rx_status,
len + FCS_LEN, 24);
ether_addr_copy(bss_meta.parent_bssid,
scan_sdata->vif.bss_conf.bssid);
}
rcu_read_unlock();
cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta,
mgmt, len, GFP_ATOMIC);
if (!cbss)
return NULL;
/* In case the signal is invalid update the status */
signal_valid = abs(channel->center_freq - cbss->channel->center_freq)
<= local->hw.wiphy->max_adj_channel_rssi_comp;
if (!signal_valid)
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
bss = (void *)cbss->priv;
if (beacon) if (beacon)
bss->device_ts_beacon = rx_status->device_timestamp; bss->device_ts_beacon = rx_status->device_timestamp;
...@@ -182,6 +135,89 @@ ieee80211_bss_info_update(struct ieee80211_local *local, ...@@ -182,6 +135,89 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss->beacon_rate = bss->beacon_rate =
&sband->bitrates[rx_status->rate_idx]; &sband->bitrates[rx_status->rate_idx];
} }
}
struct ieee80211_bss *
ieee80211_bss_info_update(struct ieee80211_local *local,
struct ieee80211_rx_status *rx_status,
struct ieee80211_mgmt *mgmt, size_t len,
struct ieee80211_channel *channel)
{
bool beacon = ieee80211_is_beacon(mgmt->frame_control);
struct cfg80211_bss *cbss, *non_tx_cbss;
struct ieee80211_bss *bss, *non_tx_bss;
struct cfg80211_inform_bss bss_meta = {
.boottime_ns = rx_status->boottime_ns,
};
bool signal_valid;
struct ieee80211_sub_if_data *scan_sdata;
struct ieee802_11_elems elems;
size_t baselen;
u8 *elements;
if (rx_status->flag & RX_FLAG_NO_SIGNAL_VAL)
bss_meta.signal = 0; /* invalid signal indication */
else if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
bss_meta.signal = rx_status->signal * 100;
else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_20;
if (rx_status->bw == RATE_INFO_BW_5)
bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_5;
else if (rx_status->bw == RATE_INFO_BW_10)
bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10;
bss_meta.chan = channel;
rcu_read_lock();
scan_sdata = rcu_dereference(local->scan_sdata);
if (scan_sdata && scan_sdata->vif.type == NL80211_IFTYPE_STATION &&
scan_sdata->vif.bss_conf.assoc &&
ieee80211_have_rx_timestamp(rx_status)) {
bss_meta.parent_tsf =
ieee80211_calculate_rx_timestamp(local, rx_status,
len + FCS_LEN, 24);
ether_addr_copy(bss_meta.parent_bssid,
scan_sdata->vif.bss_conf.bssid);
}
rcu_read_unlock();
cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta,
mgmt, len, GFP_ATOMIC);
if (!cbss)
return NULL;
if (ieee80211_is_probe_resp(mgmt->frame_control)) {
elements = mgmt->u.probe_resp.variable;
baselen = offsetof(struct ieee80211_mgmt,
u.probe_resp.variable);
} else {
baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
elements = mgmt->u.beacon.variable;
}
if (baselen > len)
return NULL;
ieee802_11_parse_elems(elements, len - baselen, false, &elems,
mgmt->bssid, cbss->bssid);
/* In case the signal is invalid update the status */
signal_valid = abs(channel->center_freq - cbss->channel->center_freq)
<= local->hw.wiphy->max_adj_channel_rssi_comp;
if (!signal_valid)
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
bss = (void *)cbss->priv;
ieee80211_update_bss_from_elems(local, bss, &elems, rx_status, beacon);
list_for_each_entry(non_tx_cbss, &cbss->nontrans_list, nontrans_list) {
non_tx_bss = (void *)non_tx_cbss->priv;
ieee80211_update_bss_from_elems(local, non_tx_bss, &elems,
rx_status, beacon);
}
return bss; return bss;
} }
...@@ -206,10 +242,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) ...@@ -206,10 +242,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
struct ieee80211_sub_if_data *sdata1, *sdata2; struct ieee80211_sub_if_data *sdata1, *sdata2;
struct ieee80211_mgmt *mgmt = (void *)skb->data; struct ieee80211_mgmt *mgmt = (void *)skb->data;
struct ieee80211_bss *bss; struct ieee80211_bss *bss;
u8 *elements;
struct ieee80211_channel *channel; struct ieee80211_channel *channel;
size_t baselen;
struct ieee802_11_elems elems;
if (skb->len < 24 || if (skb->len < 24 ||
(!ieee80211_is_probe_resp(mgmt->frame_control) && (!ieee80211_is_probe_resp(mgmt->frame_control) &&
...@@ -244,26 +277,15 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) ...@@ -244,26 +277,15 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
!ieee80211_scan_accept_presp(sdata2, sched_scan_req_flags, !ieee80211_scan_accept_presp(sdata2, sched_scan_req_flags,
mgmt->da)) mgmt->da))
return; return;
elements = mgmt->u.probe_resp.variable;
baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
} else {
baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
elements = mgmt->u.beacon.variable;
} }
if (baselen > skb->len)
return;
ieee802_11_parse_elems(elements, skb->len - baselen, false, &elems);
channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq); channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
return; return;
bss = ieee80211_bss_info_update(local, rx_status, bss = ieee80211_bss_info_update(local, rx_status,
mgmt, skb->len, &elems, mgmt, skb->len,
channel); channel);
if (bss) if (bss)
ieee80211_rx_bss_put(local, bss); ieee80211_rx_bss_put(local, bss);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* Copyright 2014, Intel Corporation * Copyright 2014, Intel Corporation
* Copyright 2014 Intel Mobile Communications GmbH * Copyright 2014 Intel Mobile Communications GmbH
* Copyright 2015 - 2016 Intel Deutschland GmbH * Copyright 2015 - 2016 Intel Deutschland GmbH
* Copyright (C) 2019 Intel Corporation
* *
* This file is GPLv2 as found in COPYING. * This file is GPLv2 as found in COPYING.
*/ */
...@@ -1716,7 +1717,8 @@ ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata, ...@@ -1716,7 +1717,8 @@ ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata,
} }
ieee802_11_parse_elems(tf->u.chan_switch_resp.variable, ieee802_11_parse_elems(tf->u.chan_switch_resp.variable,
skb->len - baselen, false, &elems); skb->len - baselen, false, &elems,
NULL, NULL);
if (elems.parse_error) { if (elems.parse_error) {
tdls_dbg(sdata, "Invalid IEs in TDLS channel switch resp\n"); tdls_dbg(sdata, "Invalid IEs in TDLS channel switch resp\n");
ret = -EINVAL; ret = -EINVAL;
...@@ -1828,7 +1830,7 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata, ...@@ -1828,7 +1830,7 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata,
} }
ieee802_11_parse_elems(tf->u.chan_switch_req.variable, ieee802_11_parse_elems(tf->u.chan_switch_req.variable,
skb->len - baselen, false, &elems); skb->len - baselen, false, &elems, NULL, NULL);
if (elems.parse_error) { if (elems.parse_error) {
tdls_dbg(sdata, "Invalid IEs in TDLS channel switch req\n"); tdls_dbg(sdata, "Invalid IEs in TDLS channel switch req\n");
return -EINVAL; return -EINVAL;
......
...@@ -891,19 +891,18 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, ...@@ -891,19 +891,18 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
} }
EXPORT_SYMBOL(ieee80211_queue_delayed_work); EXPORT_SYMBOL(ieee80211_queue_delayed_work);
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, static u32
struct ieee802_11_elems *elems, _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
u64 filter, u32 crc) struct ieee802_11_elems *elems,
u64 filter, u32 crc, u8 *transmitter_bssid,
u8 *bss_bssid)
{ {
struct element *elem; const struct element *elem, *sub;
bool calc_crc = filter != 0; bool calc_crc = filter != 0;
DECLARE_BITMAP(seen_elems, 256); DECLARE_BITMAP(seen_elems, 256);
const u8 *ie; const u8 *ie;
bitmap_zero(seen_elems, 256); bitmap_zero(seen_elems, 256);
memset(elems, 0, sizeof(*elems));
elems->ie_start = start;
elems->total_len = len;
for_each_element(elem, start, len) { for_each_element(elem, start, len) {
bool elem_parse_failed; bool elem_parse_failed;
...@@ -1209,6 +1208,57 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -1209,6 +1208,57 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
if (elen >= sizeof(*elems->max_idle_period_ie)) if (elen >= sizeof(*elems->max_idle_period_ie))
elems->max_idle_period_ie = (void *)pos; elems->max_idle_period_ie = (void *)pos;
break; break;
case WLAN_EID_MULTIPLE_BSSID:
if (!bss_bssid || !transmitter_bssid || elen < 4)
break;
elems->max_bssid_indicator = pos[0];
for_each_element(sub, pos + 1, elen - 1) {
u8 sub_len = sub->datalen;
u8 new_bssid[ETH_ALEN];
const u8 *index;
/*
* we only expect the "non-transmitted BSSID
* profile" subelement (subelement id 0)
*/
if (sub->id != 0 || sub->datalen < 4) {
/* not a valid BSS profile */
continue;
}
if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
sub->data[1] != 2) {
/* The first element of the
* Nontransmitted BSSID Profile is not
* the Nontransmitted BSSID Capability
* element.
*/
continue;
}
/* found a Nontransmitted BSSID Profile */
index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
sub->data, sub_len);
if (!index || index[1] < 1 || index[2] == 0) {
/* Invalid MBSSID Index element */
continue;
}
cfg80211_gen_new_bssid(transmitter_bssid,
pos[0],
index[2],
new_bssid);
if (ether_addr_equal(new_bssid, bss_bssid)) {
elems->nontransmitted_bssid_profile =
(void *)sub;
elems->bssid_index_len = index[1];
elems->bssid_index = (void *)&index[2];
break;
}
}
break;
case WLAN_EID_EXTENSION: case WLAN_EID_EXTENSION:
if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA && if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA &&
elen >= (sizeof(*elems->mu_edca_param_set) + 1)) { elen >= (sizeof(*elems->mu_edca_param_set) + 1)) {
...@@ -1224,6 +1274,10 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -1224,6 +1274,10 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
elems->he_operation = (void *)&pos[1]; elems->he_operation = (void *)&pos[1];
} else if (pos[0] == WLAN_EID_EXT_UORA && elen >= 1) { } else if (pos[0] == WLAN_EID_EXT_UORA && elen >= 1) {
elems->uora_element = (void *)&pos[1]; elems->uora_element = (void *)&pos[1];
} else if (pos[0] ==
WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION &&
elen == 3) {
elems->mbssid_config_ie = (void *)&pos[1];
} }
break; break;
default: default:
...@@ -1242,6 +1296,48 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -1242,6 +1296,48 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
return crc; return crc;
} }
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems,
u64 filter, u32 crc, u8 *transmitter_bssid,
u8 *bss_bssid)
{
memset(elems, 0, sizeof(*elems));
elems->ie_start = start;
elems->total_len = len;
crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter,
crc, transmitter_bssid, bss_bssid);
/* Override with nontransmitted profile, if found */
if (transmitter_bssid && elems->nontransmitted_bssid_profile) {
const u8 *profile = elems->nontransmitted_bssid_profile;
_ieee802_11_parse_elems_crc(&profile[2], profile[1],
action, elems, 0, 0,
transmitter_bssid, bss_bssid);
}
if (elems->tim && !elems->parse_error) {
const struct ieee80211_tim_ie *tim_ie = elems->tim;
elems->dtim_period = tim_ie->dtim_period;
elems->dtim_count = tim_ie->dtim_count;
}
/* Override DTIM period and count if needed */
if (elems->bssid_index &&
elems->bssid_index_len >=
offsetofend(struct ieee80211_bssid_index, dtim_period))
elems->dtim_period = elems->bssid_index->dtim_period;
if (elems->bssid_index &&
elems->bssid_index_len >=
offsetofend(struct ieee80211_bssid_index, dtim_count))
elems->dtim_count = elems->bssid_index->dtim_count;
return crc;
}
void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata, void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,
struct ieee80211_tx_queue_params struct ieee80211_tx_queue_params
*qparam, int ac) *qparam, int ac)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Wireless configuration interface internals. * Wireless configuration interface internals.
* *
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018-2019 Intel Corporation
*/ */
#ifndef __NET_WIRELESS_CORE_H #ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H #define __NET_WIRELESS_CORE_H
...@@ -182,12 +182,23 @@ static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pu ...@@ -182,12 +182,23 @@ static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pu
static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss) static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss)
{ {
atomic_inc(&bss->hold); atomic_inc(&bss->hold);
if (bss->pub.transmitted_bss) {
bss = container_of(bss->pub.transmitted_bss,
struct cfg80211_internal_bss, pub);
atomic_inc(&bss->hold);
}
} }
static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss) static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
{ {
int r = atomic_dec_return(&bss->hold); int r = atomic_dec_return(&bss->hold);
WARN_ON(r < 0); WARN_ON(r < 0);
if (bss->pub.transmitted_bss) {
bss = container_of(bss->pub.transmitted_bss,
struct cfg80211_internal_bss, pub);
r = atomic_dec_return(&bss->hold);
WARN_ON(r < 0);
}
} }
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment