Merge tag 'mac80211-next-for-net-next-2020-04-25' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says: ==================== One batch of changes, containing: * hwsim improvements from Jouni and myself, to be able to test more scenarios easily * some more HE (802.11ax) support * some initial S1G (sub 1 GHz) work for fractional MHz channels * some (action) frame registration updates to help DPP support * along with other various improvements/fixes ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -1178,8 +1178,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
|
|||||||
sizeof(arg->peer_he_cap_macinfo));
|
sizeof(arg->peer_he_cap_macinfo));
|
||||||
memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,
|
memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,
|
||||||
sizeof(arg->peer_he_cap_phyinfo));
|
sizeof(arg->peer_he_cap_phyinfo));
|
||||||
memcpy(&arg->peer_he_ops, &vif->bss_conf.he_operation,
|
arg->peer_he_ops = vif->bss_conf.he_oper.params;
|
||||||
sizeof(arg->peer_he_ops));
|
|
||||||
|
|
||||||
/* the top most byte is used to indicate BSS color info */
|
/* the top most byte is used to indicate BSS color info */
|
||||||
arg->peer_he_ops &= 0xffffff;
|
arg->peer_he_ops &= 0xffffff;
|
||||||
|
@@ -3249,22 +3249,19 @@ static int ath6kl_get_antenna(struct wiphy *wiphy,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
|
static void ath6kl_update_mgmt_frame_registrations(struct wiphy *wiphy,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
u16 frame_type, bool reg)
|
struct mgmt_frame_regs *upd)
|
||||||
{
|
{
|
||||||
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
|
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
|
||||||
|
|
||||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
|
|
||||||
__func__, frame_type, reg);
|
|
||||||
if (frame_type == IEEE80211_STYPE_PROBE_REQ) {
|
|
||||||
/*
|
/*
|
||||||
* Note: This notification callback is not allowed to sleep, so
|
* FIXME: send WMI_PROBE_REQ_REPORT_CMD here instead of hardcoding
|
||||||
* we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
|
* the reporting in the target all the time, this callback
|
||||||
* hardcode target to report Probe Request frames all the time.
|
* *is* allowed to sleep after all.
|
||||||
*/
|
*/
|
||||||
vif->probe_req_report = reg;
|
vif->probe_req_report =
|
||||||
}
|
upd->interface_stypes & BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
||||||
@@ -3464,7 +3461,8 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
|
|||||||
.remain_on_channel = ath6kl_remain_on_channel,
|
.remain_on_channel = ath6kl_remain_on_channel,
|
||||||
.cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
|
.cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
|
||||||
.mgmt_tx = ath6kl_mgmt_tx,
|
.mgmt_tx = ath6kl_mgmt_tx,
|
||||||
.mgmt_frame_register = ath6kl_mgmt_frame_register,
|
.update_mgmt_frame_registrations =
|
||||||
|
ath6kl_update_mgmt_frame_registrations,
|
||||||
.get_antenna = ath6kl_get_antenna,
|
.get_antenna = ath6kl_get_antenna,
|
||||||
.sched_scan_start = ath6kl_cfg80211_sscan_start,
|
.sched_scan_start = ath6kl_cfg80211_sscan_start,
|
||||||
.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
|
.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
|
||||||
|
@@ -5031,21 +5031,15 @@ brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
|
brcmf_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
u16 frame_type, bool reg)
|
struct mgmt_frame_regs *upd)
|
||||||
{
|
{
|
||||||
struct brcmf_cfg80211_vif *vif;
|
struct brcmf_cfg80211_vif *vif;
|
||||||
u16 mgmt_type;
|
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg);
|
|
||||||
|
|
||||||
mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
|
|
||||||
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
|
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
|
||||||
if (reg)
|
|
||||||
vif->mgmt_rx_reg |= BIT(mgmt_type);
|
vif->mgmt_rx_reg = upd->interface_stypes;
|
||||||
else
|
|
||||||
vif->mgmt_rx_reg &= ~BIT(mgmt_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -5460,7 +5454,8 @@ static struct cfg80211_ops brcmf_cfg80211_ops = {
|
|||||||
.change_station = brcmf_cfg80211_change_station,
|
.change_station = brcmf_cfg80211_change_station,
|
||||||
.sched_scan_start = brcmf_cfg80211_sched_scan_start,
|
.sched_scan_start = brcmf_cfg80211_sched_scan_start,
|
||||||
.sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
|
.sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
|
||||||
.mgmt_frame_register = brcmf_cfg80211_mgmt_frame_register,
|
.update_mgmt_frame_registrations =
|
||||||
|
brcmf_cfg80211_update_mgmt_frame_registrations,
|
||||||
.mgmt_tx = brcmf_cfg80211_mgmt_tx,
|
.mgmt_tx = brcmf_cfg80211_mgmt_tx,
|
||||||
.remain_on_channel = brcmf_p2p_remain_on_channel,
|
.remain_on_channel = brcmf_p2p_remain_on_channel,
|
||||||
.cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
|
.cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2005 - 2014, 2018 - 2020 Intel Corporation. All rights reserved.
|
||||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
|
||||||
*
|
*
|
||||||
* Contact Information:
|
* Contact Information:
|
||||||
* Intel Linux Wireless <linuxwifi@intel.com>
|
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||||
@@ -1430,7 +1429,8 @@ static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta)
|
|||||||
*/
|
*/
|
||||||
if (ieee80211_get_vht_max_nss(&vht_cap,
|
if (ieee80211_get_vht_max_nss(&vht_cap,
|
||||||
IEEE80211_VHT_CHANWIDTH_160MHZ,
|
IEEE80211_VHT_CHANWIDTH_160MHZ,
|
||||||
0, true) < sta->rx_nss)
|
0, true,
|
||||||
|
sta->rx_nss) < sta->rx_nss)
|
||||||
return RATE_MCS_CHAN_WIDTH_80;
|
return RATE_MCS_CHAN_WIDTH_80;
|
||||||
return RATE_MCS_CHAN_WIDTH_160;
|
return RATE_MCS_CHAN_WIDTH_160;
|
||||||
case IEEE80211_STA_RX_BW_80:
|
case IEEE80211_STA_RX_BW_80:
|
||||||
|
@@ -1068,6 +1068,47 @@ static int hwsim_unicast_netgroup(struct mac80211_hwsim_data *data,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mac80211_hwsim_config_mac_nl(struct ieee80211_hw *hw,
|
||||||
|
const u8 *addr, bool add)
|
||||||
|
{
|
||||||
|
struct mac80211_hwsim_data *data = hw->priv;
|
||||||
|
u32 _portid = READ_ONCE(data->wmediumd);
|
||||||
|
struct sk_buff *skb;
|
||||||
|
void *msg_head;
|
||||||
|
|
||||||
|
if (!_portid && !hwsim_virtio_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
||||||
|
if (!skb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0,
|
||||||
|
add ? HWSIM_CMD_ADD_MAC_ADDR :
|
||||||
|
HWSIM_CMD_DEL_MAC_ADDR);
|
||||||
|
if (!msg_head) {
|
||||||
|
pr_debug("mac80211_hwsim: problem with msg_head\n");
|
||||||
|
goto nla_put_failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER,
|
||||||
|
ETH_ALEN, data->addresses[1].addr))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
if (nla_put(skb, HWSIM_ATTR_ADDR_RECEIVER, ETH_ALEN, addr))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
genlmsg_end(skb, msg_head);
|
||||||
|
|
||||||
|
if (hwsim_virtio_enabled)
|
||||||
|
hwsim_tx_virtio(data, skb);
|
||||||
|
else
|
||||||
|
hwsim_unicast_netgroup(data, skb, _portid);
|
||||||
|
return;
|
||||||
|
nla_put_failure:
|
||||||
|
nlmsg_free(skb);
|
||||||
|
}
|
||||||
|
|
||||||
static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate)
|
static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate)
|
||||||
{
|
{
|
||||||
u16 result = 0;
|
u16 result = 0;
|
||||||
@@ -1545,6 +1586,9 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
|
|||||||
vif->addr);
|
vif->addr);
|
||||||
hwsim_set_magic(vif);
|
hwsim_set_magic(vif);
|
||||||
|
|
||||||
|
if (vif->type != NL80211_IFTYPE_MONITOR)
|
||||||
|
mac80211_hwsim_config_mac_nl(hw, vif->addr, true);
|
||||||
|
|
||||||
vif->cab_queue = 0;
|
vif->cab_queue = 0;
|
||||||
vif->hw_queue[IEEE80211_AC_VO] = 0;
|
vif->hw_queue[IEEE80211_AC_VO] = 0;
|
||||||
vif->hw_queue[IEEE80211_AC_VI] = 1;
|
vif->hw_queue[IEEE80211_AC_VI] = 1;
|
||||||
@@ -1584,6 +1628,8 @@ static void mac80211_hwsim_remove_interface(
|
|||||||
vif->addr);
|
vif->addr);
|
||||||
hwsim_check_magic(vif);
|
hwsim_check_magic(vif);
|
||||||
hwsim_clear_magic(vif);
|
hwsim_clear_magic(vif);
|
||||||
|
if (vif->type != NL80211_IFTYPE_MONITOR)
|
||||||
|
mac80211_hwsim_config_mac_nl(hw, vif->addr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
||||||
@@ -1781,6 +1827,8 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw,
|
|||||||
data->rx_filter = 0;
|
data->rx_filter = 0;
|
||||||
if (*total_flags & FIF_ALLMULTI)
|
if (*total_flags & FIF_ALLMULTI)
|
||||||
data->rx_filter |= FIF_ALLMULTI;
|
data->rx_filter |= FIF_ALLMULTI;
|
||||||
|
if (*total_flags & FIF_MCAST_ACTION)
|
||||||
|
data->rx_filter |= FIF_MCAST_ACTION;
|
||||||
|
|
||||||
*total_flags = data->rx_filter;
|
*total_flags = data->rx_filter;
|
||||||
}
|
}
|
||||||
@@ -2104,6 +2152,8 @@ static void hw_scan_work(struct work_struct *work)
|
|||||||
hwsim->hw_scan_vif = NULL;
|
hwsim->hw_scan_vif = NULL;
|
||||||
hwsim->tmp_chan = NULL;
|
hwsim->tmp_chan = NULL;
|
||||||
mutex_unlock(&hwsim->mutex);
|
mutex_unlock(&hwsim->mutex);
|
||||||
|
mac80211_hwsim_config_mac_nl(hwsim->hw, hwsim->scan_addr,
|
||||||
|
false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2177,6 +2227,7 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
|
|||||||
memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data));
|
memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data));
|
||||||
mutex_unlock(&hwsim->mutex);
|
mutex_unlock(&hwsim->mutex);
|
||||||
|
|
||||||
|
mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, true);
|
||||||
wiphy_dbg(hw->wiphy, "hwsim hw_scan request\n");
|
wiphy_dbg(hw->wiphy, "hwsim hw_scan request\n");
|
||||||
|
|
||||||
ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0);
|
ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0);
|
||||||
@@ -2220,6 +2271,7 @@ static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw,
|
|||||||
pr_debug("hwsim sw_scan request, prepping stuff\n");
|
pr_debug("hwsim sw_scan request, prepping stuff\n");
|
||||||
|
|
||||||
memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN);
|
memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN);
|
||||||
|
mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, true);
|
||||||
hwsim->scanning = true;
|
hwsim->scanning = true;
|
||||||
memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data));
|
memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data));
|
||||||
|
|
||||||
@@ -2236,6 +2288,7 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw,
|
|||||||
|
|
||||||
pr_debug("hwsim sw_scan_complete\n");
|
pr_debug("hwsim sw_scan_complete\n");
|
||||||
hwsim->scanning = false;
|
hwsim->scanning = false;
|
||||||
|
mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, false);
|
||||||
eth_zero_addr(hwsim->scan_addr);
|
eth_zero_addr(hwsim->scan_addr);
|
||||||
|
|
||||||
mutex_unlock(&hwsim->mutex);
|
mutex_unlock(&hwsim->mutex);
|
||||||
@@ -2413,6 +2466,11 @@ static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw,
|
|||||||
WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN);
|
WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mac80211_hwsim_tx_last_beacon(struct ieee80211_hw *hw)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#define HWSIM_COMMON_OPS \
|
#define HWSIM_COMMON_OPS \
|
||||||
.tx = mac80211_hwsim_tx, \
|
.tx = mac80211_hwsim_tx, \
|
||||||
.start = mac80211_hwsim_start, \
|
.start = mac80211_hwsim_start, \
|
||||||
@@ -2423,6 +2481,7 @@ static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw,
|
|||||||
.config = mac80211_hwsim_config, \
|
.config = mac80211_hwsim_config, \
|
||||||
.configure_filter = mac80211_hwsim_configure_filter, \
|
.configure_filter = mac80211_hwsim_configure_filter, \
|
||||||
.bss_info_changed = mac80211_hwsim_bss_info_changed, \
|
.bss_info_changed = mac80211_hwsim_bss_info_changed, \
|
||||||
|
.tx_last_beacon = mac80211_hwsim_tx_last_beacon, \
|
||||||
.sta_add = mac80211_hwsim_sta_add, \
|
.sta_add = mac80211_hwsim_sta_add, \
|
||||||
.sta_remove = mac80211_hwsim_sta_remove, \
|
.sta_remove = mac80211_hwsim_sta_remove, \
|
||||||
.sta_notify = mac80211_hwsim_sta_notify, \
|
.sta_notify = mac80211_hwsim_sta_notify, \
|
||||||
@@ -3003,6 +3062,10 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
|||||||
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
|
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
|
||||||
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
|
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
|
||||||
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION);
|
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION);
|
||||||
|
wiphy_ext_feature_set(hw->wiphy,
|
||||||
|
NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS);
|
||||||
|
wiphy_ext_feature_set(hw->wiphy,
|
||||||
|
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
|
||||||
|
|
||||||
hw->wiphy->interface_modes = param->iftypes;
|
hw->wiphy->interface_modes = param->iftypes;
|
||||||
|
|
||||||
|
@@ -75,6 +75,12 @@ enum hwsim_tx_control_flags {
|
|||||||
* @HWSIM_CMD_DEL_RADIO: destroy a radio, reply is multicasted
|
* @HWSIM_CMD_DEL_RADIO: destroy a radio, reply is multicasted
|
||||||
* @HWSIM_CMD_GET_RADIO: fetch information about existing radios, uses:
|
* @HWSIM_CMD_GET_RADIO: fetch information about existing radios, uses:
|
||||||
* %HWSIM_ATTR_RADIO_ID
|
* %HWSIM_ATTR_RADIO_ID
|
||||||
|
* @HWSIM_CMD_ADD_MAC_ADDR: add a receive MAC address (given in the
|
||||||
|
* %HWSIM_ATTR_ADDR_RECEIVER attribute) to a device identified by
|
||||||
|
* %HWSIM_ATTR_ADDR_TRANSMITTER. This lets wmediumd forward frames
|
||||||
|
* to this receiver address for a given station.
|
||||||
|
* @HWSIM_CMD_DEL_MAC_ADDR: remove the MAC address again, the attributes
|
||||||
|
* are the same as to @HWSIM_CMD_ADD_MAC_ADDR.
|
||||||
* @__HWSIM_CMD_MAX: enum limit
|
* @__HWSIM_CMD_MAX: enum limit
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
@@ -85,6 +91,8 @@ enum {
|
|||||||
HWSIM_CMD_NEW_RADIO,
|
HWSIM_CMD_NEW_RADIO,
|
||||||
HWSIM_CMD_DEL_RADIO,
|
HWSIM_CMD_DEL_RADIO,
|
||||||
HWSIM_CMD_GET_RADIO,
|
HWSIM_CMD_GET_RADIO,
|
||||||
|
HWSIM_CMD_ADD_MAC_ADDR,
|
||||||
|
HWSIM_CMD_DEL_MAC_ADDR,
|
||||||
__HWSIM_CMD_MAX,
|
__HWSIM_CMD_MAX,
|
||||||
};
|
};
|
||||||
#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
|
#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
|
||||||
|
@@ -269,17 +269,12 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||||||
* CFG802.11 operation handler to register a mgmt frame.
|
* CFG802.11 operation handler to register a mgmt frame.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
|
mwifiex_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
u16 frame_type, bool reg)
|
struct mgmt_frame_regs *upd)
|
||||||
{
|
{
|
||||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
|
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
|
||||||
u32 mask;
|
u32 mask = upd->interface_stypes;
|
||||||
|
|
||||||
if (reg)
|
|
||||||
mask = priv->mgmt_frame_mask | BIT(frame_type >> 4);
|
|
||||||
else
|
|
||||||
mask = priv->mgmt_frame_mask & ~BIT(frame_type >> 4);
|
|
||||||
|
|
||||||
if (mask != priv->mgmt_frame_mask) {
|
if (mask != priv->mgmt_frame_mask) {
|
||||||
priv->mgmt_frame_mask = mask;
|
priv->mgmt_frame_mask = mask;
|
||||||
@@ -4187,7 +4182,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
|
|||||||
.del_key = mwifiex_cfg80211_del_key,
|
.del_key = mwifiex_cfg80211_del_key,
|
||||||
.set_default_mgmt_key = mwifiex_cfg80211_set_default_mgmt_key,
|
.set_default_mgmt_key = mwifiex_cfg80211_set_default_mgmt_key,
|
||||||
.mgmt_tx = mwifiex_cfg80211_mgmt_tx,
|
.mgmt_tx = mwifiex_cfg80211_mgmt_tx,
|
||||||
.mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register,
|
.update_mgmt_frame_registrations =
|
||||||
|
mwifiex_cfg80211_update_mgmt_frame_registrations,
|
||||||
.remain_on_channel = mwifiex_cfg80211_remain_on_channel,
|
.remain_on_channel = mwifiex_cfg80211_remain_on_channel,
|
||||||
.cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,
|
.cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,
|
||||||
.set_default_key = mwifiex_cfg80211_set_default_key,
|
.set_default_key = mwifiex_cfg80211_set_default_key,
|
||||||
|
@@ -389,55 +389,57 @@ static int qtnf_set_wiphy_params(struct wiphy *wiphy, u32 changed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
qtnf_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
|
qtnf_update_mgmt_frame_registrations(struct wiphy *wiphy,
|
||||||
u16 frame_type, bool reg)
|
struct wireless_dev *wdev,
|
||||||
|
struct mgmt_frame_regs *upd)
|
||||||
{
|
{
|
||||||
struct qtnf_vif *vif = qtnf_netdev_get_priv(wdev->netdev);
|
struct qtnf_vif *vif = qtnf_netdev_get_priv(wdev->netdev);
|
||||||
u16 mgmt_type;
|
u16 new_mask = upd->interface_stypes;
|
||||||
u16 new_mask;
|
u16 old_mask = vif->mgmt_frames_bitmask;
|
||||||
u16 qlink_frame_type = 0;
|
static const struct {
|
||||||
|
u16 mask, qlink_type;
|
||||||
|
} updates[] = {
|
||||||
|
{
|
||||||
|
.mask = BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
|
||||||
|
BIT(IEEE80211_STYPE_ASSOC_REQ >> 4),
|
||||||
|
.qlink_type = QLINK_MGMT_FRAME_ASSOC_REQ,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.mask = BIT(IEEE80211_STYPE_AUTH >> 4),
|
||||||
|
.qlink_type = QLINK_MGMT_FRAME_AUTH,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.mask = BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
|
||||||
|
.qlink_type = QLINK_MGMT_FRAME_PROBE_REQ,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.mask = BIT(IEEE80211_STYPE_ACTION >> 4),
|
||||||
|
.qlink_type = QLINK_MGMT_FRAME_ACTION,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
|
if (new_mask == old_mask)
|
||||||
|
|
||||||
if (reg)
|
|
||||||
new_mask = vif->mgmt_frames_bitmask | BIT(mgmt_type);
|
|
||||||
else
|
|
||||||
new_mask = vif->mgmt_frames_bitmask & ~BIT(mgmt_type);
|
|
||||||
|
|
||||||
if (new_mask == vif->mgmt_frames_bitmask)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (frame_type & IEEE80211_FCTL_STYPE) {
|
for (i = 0; i < ARRAY_SIZE(updates); i++) {
|
||||||
case IEEE80211_STYPE_REASSOC_REQ:
|
u16 mask = updates[i].mask;
|
||||||
case IEEE80211_STYPE_ASSOC_REQ:
|
u16 qlink_frame_type = updates[i].qlink_type;
|
||||||
qlink_frame_type = QLINK_MGMT_FRAME_ASSOC_REQ;
|
bool reg;
|
||||||
break;
|
|
||||||
case IEEE80211_STYPE_AUTH:
|
|
||||||
qlink_frame_type = QLINK_MGMT_FRAME_AUTH;
|
|
||||||
break;
|
|
||||||
case IEEE80211_STYPE_PROBE_REQ:
|
|
||||||
qlink_frame_type = QLINK_MGMT_FRAME_PROBE_REQ;
|
|
||||||
break;
|
|
||||||
case IEEE80211_STYPE_ACTION:
|
|
||||||
qlink_frame_type = QLINK_MGMT_FRAME_ACTION;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pr_warn("VIF%u.%u: unsupported frame type: %X\n",
|
|
||||||
vif->mac->macid, vif->vifid,
|
|
||||||
(frame_type & IEEE80211_FCTL_STYPE) >> 4);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qtnf_cmd_send_register_mgmt(vif, qlink_frame_type, reg)) {
|
/* the ! are here due to the assoc/reassoc merge */
|
||||||
pr_warn("VIF%u.%u: failed to %sregister mgmt frame type 0x%x\n",
|
if (!(new_mask & mask) == !(old_mask & mask))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
reg = new_mask & mask;
|
||||||
|
|
||||||
|
if (qtnf_cmd_send_register_mgmt(vif, qlink_frame_type, reg))
|
||||||
|
pr_warn("VIF%u.%u: failed to %sregister qlink frame type 0x%x\n",
|
||||||
vif->mac->macid, vif->vifid, reg ? "" : "un",
|
vif->mac->macid, vif->vifid, reg ? "" : "un",
|
||||||
frame_type);
|
qlink_frame_type);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vif->mgmt_frames_bitmask = new_mask;
|
vif->mgmt_frames_bitmask = new_mask;
|
||||||
pr_debug("VIF%u.%u: %sregistered mgmt frame type 0x%x\n",
|
|
||||||
vif->mac->macid, vif->vifid, reg ? "" : "un", frame_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -1017,7 +1019,8 @@ static struct cfg80211_ops qtn_cfg80211_ops = {
|
|||||||
.change_beacon = qtnf_change_beacon,
|
.change_beacon = qtnf_change_beacon,
|
||||||
.stop_ap = qtnf_stop_ap,
|
.stop_ap = qtnf_stop_ap,
|
||||||
.set_wiphy_params = qtnf_set_wiphy_params,
|
.set_wiphy_params = qtnf_set_wiphy_params,
|
||||||
.mgmt_frame_register = qtnf_mgmt_frame_register,
|
.update_mgmt_frame_registrations =
|
||||||
|
qtnf_update_mgmt_frame_registrations,
|
||||||
.mgmt_tx = qtnf_mgmt_tx,
|
.mgmt_tx = qtnf_mgmt_tx,
|
||||||
.change_station = qtnf_change_station,
|
.change_station = qtnf_change_station,
|
||||||
.del_station = qtnf_del_station,
|
.del_station = qtnf_del_station,
|
||||||
|
@@ -3163,29 +3163,6 @@ exit:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
|
|
||||||
struct wireless_dev *wdev,
|
|
||||||
u16 frame_type, bool reg)
|
|
||||||
{
|
|
||||||
struct net_device *ndev = wdev_to_ndev(wdev);
|
|
||||||
struct adapter *adapter;
|
|
||||||
|
|
||||||
if (ndev == NULL)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
adapter = (struct adapter *)rtw_netdev_priv(ndev);
|
|
||||||
|
|
||||||
#ifdef DEBUG_CFG80211
|
|
||||||
DBG_871X(FUNC_ADPT_FMT" frame_type:%x, reg:%d\n", FUNC_ADPT_ARG(adapter),
|
|
||||||
frame_type, reg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
|
|
||||||
return;
|
|
||||||
exit:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONFIG_PNO_SUPPORT)
|
#if defined(CONFIG_PNO_SUPPORT)
|
||||||
static int cfg80211_rtw_sched_scan_start(struct wiphy *wiphy,
|
static int cfg80211_rtw_sched_scan_start(struct wiphy *wiphy,
|
||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
@@ -3397,7 +3374,6 @@ static struct cfg80211_ops rtw_cfg80211_ops = {
|
|||||||
.change_bss = cfg80211_rtw_change_bss,
|
.change_bss = cfg80211_rtw_change_bss,
|
||||||
|
|
||||||
.mgmt_tx = cfg80211_rtw_mgmt_tx,
|
.mgmt_tx = cfg80211_rtw_mgmt_tx,
|
||||||
.mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
|
|
||||||
|
|
||||||
#if defined(CONFIG_PNO_SUPPORT)
|
#if defined(CONFIG_PNO_SUPPORT)
|
||||||
.sched_scan_start = cfg80211_rtw_sched_scan_start,
|
.sched_scan_start = cfg80211_rtw_sched_scan_start,
|
||||||
|
@@ -1217,33 +1217,31 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
|
void wilc_update_mgmt_frame_registrations(struct wiphy *wiphy,
|
||||||
u16 frame_type, bool reg)
|
struct wireless_dev *wdev,
|
||||||
|
struct mgmt_frame_regs *upd)
|
||||||
{
|
{
|
||||||
struct wilc *wl = wiphy_priv(wiphy);
|
struct wilc *wl = wiphy_priv(wiphy);
|
||||||
struct wilc_vif *vif = netdev_priv(wdev->netdev);
|
struct wilc_vif *vif = netdev_priv(wdev->netdev);
|
||||||
|
u32 presp_bit = BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
|
||||||
|
u32 action_bit = BIT(IEEE80211_STYPE_ACTION >> 4);
|
||||||
|
|
||||||
if (!frame_type)
|
if (wl->initialized) {
|
||||||
return;
|
bool prev = vif->mgmt_reg_stypes & presp_bit;
|
||||||
|
bool now = upd->interface_stypes & presp_bit;
|
||||||
|
|
||||||
switch (frame_type) {
|
if (now != prev)
|
||||||
case IEEE80211_STYPE_PROBE_REQ:
|
wilc_frame_register(vif, IEEE80211_STYPE_PROBE_REQ, now);
|
||||||
vif->frame_reg[0].type = frame_type;
|
|
||||||
vif->frame_reg[0].reg = reg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IEEE80211_STYPE_ACTION:
|
prev = vif->mgmt_reg_stypes & action_bit;
|
||||||
vif->frame_reg[1].type = frame_type;
|
now = upd->interface_stypes & action_bit;
|
||||||
vif->frame_reg[1].reg = reg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
if (now != prev)
|
||||||
break;
|
wilc_frame_register(vif, IEEE80211_STYPE_ACTION, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wl->initialized)
|
vif->mgmt_reg_stypes =
|
||||||
return;
|
upd->interface_stypes & (presp_bit | action_bit);
|
||||||
wilc_frame_register(vif, frame_type, reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,
|
static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,
|
||||||
@@ -1665,7 +1663,7 @@ static const struct cfg80211_ops wilc_cfg80211_ops = {
|
|||||||
.cancel_remain_on_channel = cancel_remain_on_channel,
|
.cancel_remain_on_channel = cancel_remain_on_channel,
|
||||||
.mgmt_tx_cancel_wait = mgmt_tx_cancel_wait,
|
.mgmt_tx_cancel_wait = mgmt_tx_cancel_wait,
|
||||||
.mgmt_tx = mgmt_tx,
|
.mgmt_tx = mgmt_tx,
|
||||||
.mgmt_frame_register = wilc_mgmt_frame_register,
|
.update_mgmt_frame_registrations = wilc_update_mgmt_frame_registrations,
|
||||||
.set_power_mgmt = set_power_mgmt,
|
.set_power_mgmt = set_power_mgmt,
|
||||||
.set_cqm_rssi_config = set_cqm_rssi_config,
|
.set_cqm_rssi_config = set_cqm_rssi_config,
|
||||||
|
|
||||||
|
@@ -21,8 +21,9 @@ void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked);
|
|||||||
struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
|
struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
|
||||||
const char *name,
|
const char *name,
|
||||||
struct net_device *real_dev);
|
struct net_device *real_dev);
|
||||||
void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
|
void wilc_update_mgmt_frame_registrations(struct wiphy *wiphy,
|
||||||
u16 frame_type, bool reg);
|
struct wireless_dev *wdev,
|
||||||
|
struct mgmt_frame_regs *upd);
|
||||||
struct wilc_vif *wilc_get_interface(struct wilc *wl);
|
struct wilc_vif *wilc_get_interface(struct wilc *wl);
|
||||||
struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl);
|
struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl);
|
||||||
void wlan_deinit_locks(struct wilc *wilc);
|
void wlan_deinit_locks(struct wilc *wilc);
|
||||||
|
@@ -571,6 +571,7 @@ static int wilc_mac_open(struct net_device *ndev)
|
|||||||
struct wilc *wl = vif->wilc;
|
struct wilc *wl = vif->wilc;
|
||||||
unsigned char mac_add[ETH_ALEN] = {0};
|
unsigned char mac_add[ETH_ALEN] = {0};
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
struct mgmt_frame_regs mgmt_regs = {};
|
||||||
|
|
||||||
if (!wl || !wl->dev) {
|
if (!wl || !wl->dev) {
|
||||||
netdev_err(ndev, "device not ready\n");
|
netdev_err(ndev, "device not ready\n");
|
||||||
@@ -602,14 +603,12 @@ static int wilc_mac_open(struct net_device *ndev)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wilc_mgmt_frame_register(vif->ndev->ieee80211_ptr->wiphy,
|
mgmt_regs.interface_stypes = vif->mgmt_reg_stypes;
|
||||||
|
/* so we detect a change */
|
||||||
|
vif->mgmt_reg_stypes = 0;
|
||||||
|
wilc_update_mgmt_frame_registrations(vif->ndev->ieee80211_ptr->wiphy,
|
||||||
vif->ndev->ieee80211_ptr,
|
vif->ndev->ieee80211_ptr,
|
||||||
vif->frame_reg[0].type,
|
&mgmt_regs);
|
||||||
vif->frame_reg[0].reg);
|
|
||||||
wilc_mgmt_frame_register(vif->ndev->ieee80211_ptr->wiphy,
|
|
||||||
vif->ndev->ieee80211_ptr,
|
|
||||||
vif->frame_reg[1].type,
|
|
||||||
vif->frame_reg[1].reg);
|
|
||||||
netif_wake_queue(ndev);
|
netif_wake_queue(ndev);
|
||||||
wl->open_ifcs++;
|
wl->open_ifcs++;
|
||||||
vif->mac_opened = 1;
|
vif->mac_opened = 1;
|
||||||
@@ -792,12 +791,10 @@ void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
|
|||||||
srcu_idx = srcu_read_lock(&wilc->srcu);
|
srcu_idx = srcu_read_lock(&wilc->srcu);
|
||||||
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
|
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
|
||||||
u16 type = le16_to_cpup((__le16 *)buff);
|
u16 type = le16_to_cpup((__le16 *)buff);
|
||||||
|
u32 type_bit = BIT(type >> 4);
|
||||||
|
|
||||||
if (vif->priv.p2p_listen_state &&
|
if (vif->priv.p2p_listen_state &&
|
||||||
((type == vif->frame_reg[0].type &&
|
vif->mgmt_reg_stypes & type_bit)
|
||||||
vif->frame_reg[0].reg) ||
|
|
||||||
(type == vif->frame_reg[1].type &&
|
|
||||||
vif->frame_reg[1].reg)))
|
|
||||||
wilc_wfi_p2p_rx(vif, buff, size);
|
wilc_wfi_p2p_rx(vif, buff, size);
|
||||||
|
|
||||||
if (vif->monitor_flag)
|
if (vif->monitor_flag)
|
||||||
|
@@ -24,8 +24,6 @@
|
|||||||
#define PMKID_FOUND 1
|
#define PMKID_FOUND 1
|
||||||
#define NUM_STA_ASSOCIATED 8
|
#define NUM_STA_ASSOCIATED 8
|
||||||
|
|
||||||
#define NUM_REG_FRAME 2
|
|
||||||
|
|
||||||
#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54
|
#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54
|
||||||
#define DEFAULT_LINK_SPEED 72
|
#define DEFAULT_LINK_SPEED 72
|
||||||
|
|
||||||
@@ -151,11 +149,6 @@ struct wilc_priv {
|
|||||||
u64 inc_roc_cookie;
|
u64 inc_roc_cookie;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct frame_reg {
|
|
||||||
u16 type;
|
|
||||||
bool reg;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX_TCP_SESSION 25
|
#define MAX_TCP_SESSION 25
|
||||||
#define MAX_PENDING_ACKS 256
|
#define MAX_PENDING_ACKS 256
|
||||||
|
|
||||||
@@ -187,7 +180,7 @@ struct wilc_vif {
|
|||||||
u8 iftype;
|
u8 iftype;
|
||||||
int monitor_flag;
|
int monitor_flag;
|
||||||
int mac_opened;
|
int mac_opened;
|
||||||
struct frame_reg frame_reg[NUM_REG_FRAME];
|
u32 mgmt_reg_stypes;
|
||||||
struct net_device_stats netstats;
|
struct net_device_stats netstats;
|
||||||
struct wilc *wilc;
|
struct wilc *wilc;
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
|
@@ -9,7 +9,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 - 2019 Intel Corporation
|
* Copyright (c) 2018 - 2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LINUX_IEEE80211_H
|
#ifndef LINUX_IEEE80211_H
|
||||||
@@ -859,6 +859,7 @@ enum ieee80211_ht_chanwidth_values {
|
|||||||
* @IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ: 40 MHz channel width
|
* @IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ: 40 MHz channel width
|
||||||
* @IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ: 80 MHz channel width
|
* @IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ: 80 MHz channel width
|
||||||
* @IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ: 160 MHz or 80+80 MHz channel width
|
* @IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ: 160 MHz or 80+80 MHz channel width
|
||||||
|
* @IEEE80211_OPMODE_NOTIF_BW_160_80P80: 160 / 80+80 MHz indicator flag
|
||||||
* @IEEE80211_OPMODE_NOTIF_RX_NSS_MASK: number of spatial streams mask
|
* @IEEE80211_OPMODE_NOTIF_RX_NSS_MASK: number of spatial streams mask
|
||||||
* (the NSS value is the value of this field + 1)
|
* (the NSS value is the value of this field + 1)
|
||||||
* @IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT: number of spatial streams shift
|
* @IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT: number of spatial streams shift
|
||||||
@@ -866,11 +867,12 @@ enum ieee80211_ht_chanwidth_values {
|
|||||||
* using a beamforming steering matrix
|
* using a beamforming steering matrix
|
||||||
*/
|
*/
|
||||||
enum ieee80211_vht_opmode_bits {
|
enum ieee80211_vht_opmode_bits {
|
||||||
IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK = 3,
|
IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK = 0x03,
|
||||||
IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ = 0,
|
IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ = 0,
|
||||||
IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ = 1,
|
IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ = 1,
|
||||||
IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ = 2,
|
IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ = 2,
|
||||||
IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ = 3,
|
IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ = 3,
|
||||||
|
IEEE80211_OPMODE_NOTIF_BW_160_80P80 = 0x04,
|
||||||
IEEE80211_OPMODE_NOTIF_RX_NSS_MASK = 0x70,
|
IEEE80211_OPMODE_NOTIF_RX_NSS_MASK = 0x70,
|
||||||
IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT = 4,
|
IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT = 4,
|
||||||
IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF = 0x80,
|
IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF = 0x80,
|
||||||
@@ -1065,6 +1067,7 @@ struct ieee80211_mgmt {
|
|||||||
/* Supported rates membership selectors */
|
/* Supported rates membership selectors */
|
||||||
#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
|
#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
|
||||||
#define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126
|
#define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126
|
||||||
|
#define BSS_MEMBERSHIP_SELECTOR_HE_PHY 122
|
||||||
|
|
||||||
/* mgmt header + 1 byte category code */
|
/* mgmt header + 1 byte category code */
|
||||||
#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
|
#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
|
||||||
@@ -1731,6 +1734,9 @@ struct ieee80211_mu_edca_param_set {
|
|||||||
* @ext_nss_bw_capable: indicates whether or not the local transmitter
|
* @ext_nss_bw_capable: indicates whether or not the local transmitter
|
||||||
* (rate scaling algorithm) can deal with the new logic
|
* (rate scaling algorithm) can deal with the new logic
|
||||||
* (dot11VHTExtendedNSSBWCapable)
|
* (dot11VHTExtendedNSSBWCapable)
|
||||||
|
* @max_vht_nss: current maximum NSS as advertised by the STA in
|
||||||
|
* operating mode notification, can be 0 in which case the
|
||||||
|
* capability data will be used to derive this (from MCS support)
|
||||||
*
|
*
|
||||||
* Due to the VHT Extended NSS Bandwidth Support, the maximum NSS can
|
* Due to the VHT Extended NSS Bandwidth Support, the maximum NSS can
|
||||||
* vary for a given BW/MCS. This function parses the data.
|
* vary for a given BW/MCS. This function parses the data.
|
||||||
@@ -1739,7 +1745,8 @@ struct ieee80211_mu_edca_param_set {
|
|||||||
*/
|
*/
|
||||||
int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
|
int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
|
||||||
enum ieee80211_vht_chanwidth bw,
|
enum ieee80211_vht_chanwidth bw,
|
||||||
int mcs, bool ext_nss_bw_capable);
|
int mcs, bool ext_nss_bw_capable,
|
||||||
|
unsigned int max_vht_nss);
|
||||||
|
|
||||||
/* 802.11ax HE MAC capabilities */
|
/* 802.11ax HE MAC capabilities */
|
||||||
#define IEEE80211_HE_MAC_CAP0_HTC_HE 0x01
|
#define IEEE80211_HE_MAC_CAP0_HTC_HE 0x01
|
||||||
@@ -3323,6 +3330,16 @@ static inline int ieee80211_get_tdls_action(struct sk_buff *skb, u32 hdr_size)
|
|||||||
#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024))
|
#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024))
|
||||||
#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x))
|
#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x))
|
||||||
|
|
||||||
|
/* convert frequencies */
|
||||||
|
#define MHZ_TO_KHZ(freq) ((freq) * 1000)
|
||||||
|
#define KHZ_TO_MHZ(freq) ((freq) / 1000)
|
||||||
|
|
||||||
|
/* convert powers */
|
||||||
|
#define DBI_TO_MBI(gain) ((gain) * 100)
|
||||||
|
#define MBI_TO_DBI(gain) ((gain) / 100)
|
||||||
|
#define DBM_TO_MBM(gain) ((gain) * 100)
|
||||||
|
#define MBM_TO_DBM(gain) ((gain) / 100)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ieee80211_action_contains_tpc - checks if the frame contains TPC element
|
* ieee80211_action_contains_tpc - checks if the frame contains TPC element
|
||||||
* @skb: the skb containing the frame, length will be checked
|
* @skb: the skb containing the frame, length will be checked
|
||||||
|
@@ -128,6 +128,7 @@ enum ieee80211_channel_flags {
|
|||||||
* with cfg80211.
|
* with cfg80211.
|
||||||
*
|
*
|
||||||
* @center_freq: center frequency in MHz
|
* @center_freq: center frequency in MHz
|
||||||
|
* @freq_offset: offset from @center_freq, in KHz
|
||||||
* @hw_value: hardware-specific value for the channel
|
* @hw_value: hardware-specific value for the channel
|
||||||
* @flags: channel flags from &enum ieee80211_channel_flags.
|
* @flags: channel flags from &enum ieee80211_channel_flags.
|
||||||
* @orig_flags: channel flags at registration time, used by regulatory
|
* @orig_flags: channel flags at registration time, used by regulatory
|
||||||
@@ -149,6 +150,7 @@ enum ieee80211_channel_flags {
|
|||||||
struct ieee80211_channel {
|
struct ieee80211_channel {
|
||||||
enum nl80211_band band;
|
enum nl80211_band band;
|
||||||
u32 center_freq;
|
u32 center_freq;
|
||||||
|
u16 freq_offset;
|
||||||
u16 hw_value;
|
u16 hw_value;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
int max_antenna_gain;
|
int max_antenna_gain;
|
||||||
@@ -617,6 +619,7 @@ struct key_params {
|
|||||||
* If edmg is requested (i.e. the .channels member is non-zero),
|
* If edmg is requested (i.e. the .channels member is non-zero),
|
||||||
* chan will define the primary channel and all other
|
* chan will define the primary channel and all other
|
||||||
* parameters are ignored.
|
* parameters are ignored.
|
||||||
|
* @freq1_offset: offset from @center_freq1, in KHz
|
||||||
*/
|
*/
|
||||||
struct cfg80211_chan_def {
|
struct cfg80211_chan_def {
|
||||||
struct ieee80211_channel *chan;
|
struct ieee80211_channel *chan;
|
||||||
@@ -624,6 +627,7 @@ struct cfg80211_chan_def {
|
|||||||
u32 center_freq1;
|
u32 center_freq1;
|
||||||
u32 center_freq2;
|
u32 center_freq2;
|
||||||
struct ieee80211_edmg edmg;
|
struct ieee80211_edmg edmg;
|
||||||
|
u16 freq1_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -713,6 +717,7 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
|
|||||||
return (chandef1->chan == chandef2->chan &&
|
return (chandef1->chan == chandef2->chan &&
|
||||||
chandef1->width == chandef2->width &&
|
chandef1->width == chandef2->width &&
|
||||||
chandef1->center_freq1 == chandef2->center_freq1 &&
|
chandef1->center_freq1 == chandef2->center_freq1 &&
|
||||||
|
chandef1->freq1_offset == chandef2->freq1_offset &&
|
||||||
chandef1->center_freq2 == chandef2->center_freq2);
|
chandef1->center_freq2 == chandef2->center_freq2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1054,6 +1059,7 @@ enum cfg80211_ap_settings_flags {
|
|||||||
* @ht_required: stations must support HT
|
* @ht_required: stations must support HT
|
||||||
* @vht_required: stations must support VHT
|
* @vht_required: stations must support VHT
|
||||||
* @twt_responder: Enable Target Wait Time
|
* @twt_responder: Enable Target Wait Time
|
||||||
|
* @he_required: stations must support HE
|
||||||
* @flags: flags, as defined in enum cfg80211_ap_settings_flags
|
* @flags: flags, as defined in enum cfg80211_ap_settings_flags
|
||||||
* @he_obss_pd: OBSS Packet Detection settings
|
* @he_obss_pd: OBSS Packet Detection settings
|
||||||
* @he_bss_color: BSS Color settings
|
* @he_bss_color: BSS Color settings
|
||||||
@@ -1083,7 +1089,7 @@ struct cfg80211_ap_settings {
|
|||||||
const struct ieee80211_vht_cap *vht_cap;
|
const struct ieee80211_vht_cap *vht_cap;
|
||||||
const struct ieee80211_he_cap_elem *he_cap;
|
const struct ieee80211_he_cap_elem *he_cap;
|
||||||
const struct ieee80211_he_operation *he_oper;
|
const struct ieee80211_he_operation *he_oper;
|
||||||
bool ht_required, vht_required;
|
bool ht_required, vht_required, he_required;
|
||||||
bool twt_responder;
|
bool twt_responder;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
struct ieee80211_he_obss_pd he_obss_pd;
|
struct ieee80211_he_obss_pd he_obss_pd;
|
||||||
@@ -3384,6 +3390,21 @@ struct cfg80211_update_owe_info {
|
|||||||
size_t ie_len;
|
size_t ie_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct mgmt_frame_regs - management frame registrations data
|
||||||
|
* @global_stypes: bitmap of management frame subtypes registered
|
||||||
|
* for the entire device
|
||||||
|
* @interface_stypes: bitmap of management frame subtypes registered
|
||||||
|
* for the given interface
|
||||||
|
* @global_mcast_rx: mcast RX is needed globally for these subtypes
|
||||||
|
* @interface_mcast_stypes: mcast RX is needed on this interface
|
||||||
|
* for these subtypes
|
||||||
|
*/
|
||||||
|
struct mgmt_frame_regs {
|
||||||
|
u32 global_stypes, interface_stypes;
|
||||||
|
u32 global_mcast_stypes, interface_mcast_stypes;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct cfg80211_ops - backend description for wireless configuration
|
* struct cfg80211_ops - backend description for wireless configuration
|
||||||
*
|
*
|
||||||
@@ -3608,8 +3629,8 @@ struct cfg80211_update_owe_info {
|
|||||||
* The driver should not call cfg80211_sched_scan_stopped() for a requested
|
* The driver should not call cfg80211_sched_scan_stopped() for a requested
|
||||||
* stop (when this method returns 0).
|
* stop (when this method returns 0).
|
||||||
*
|
*
|
||||||
* @mgmt_frame_register: Notify driver that a management frame type was
|
* @update_mgmt_frame_registrations: Notify the driver that management frame
|
||||||
* registered. The callback is allowed to sleep.
|
* registrations were updated. The callback is allowed to sleep.
|
||||||
*
|
*
|
||||||
* @set_antenna: Set antenna configuration (tx_ant, rx_ant) on the device.
|
* @set_antenna: Set antenna configuration (tx_ant, rx_ant) on the device.
|
||||||
* Parameters are bitmaps of allowed antennas to use for TX/RX. Drivers may
|
* Parameters are bitmaps of allowed antennas to use for TX/RX. Drivers may
|
||||||
@@ -3932,9 +3953,9 @@ struct cfg80211_ops {
|
|||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
u32 rate, u32 pkts, u32 intvl);
|
u32 rate, u32 pkts, u32 intvl);
|
||||||
|
|
||||||
void (*mgmt_frame_register)(struct wiphy *wiphy,
|
void (*update_mgmt_frame_registrations)(struct wiphy *wiphy,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
u16 frame_type, bool reg);
|
struct mgmt_frame_regs *upd);
|
||||||
|
|
||||||
int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
|
int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
|
||||||
int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
|
int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
|
||||||
@@ -5015,6 +5036,7 @@ struct cfg80211_cqm_config;
|
|||||||
* by cfg80211 on change_interface
|
* by cfg80211 on change_interface
|
||||||
* @mgmt_registrations: list of registrations for management frames
|
* @mgmt_registrations: list of registrations for management frames
|
||||||
* @mgmt_registrations_lock: lock for the list
|
* @mgmt_registrations_lock: lock for the list
|
||||||
|
* @mgmt_registrations_update_wk: update work to defer from atomic context
|
||||||
* @mtx: mutex used to lock data in this struct, may be used by drivers
|
* @mtx: mutex used to lock data in this struct, may be used by drivers
|
||||||
* and some API functions require it held
|
* and some API functions require it held
|
||||||
* @beacon_interval: beacon interval used on this device for transmitting
|
* @beacon_interval: beacon interval used on this device for transmitting
|
||||||
@@ -5045,6 +5067,8 @@ struct cfg80211_cqm_config;
|
|||||||
* @pmsr_list: (private) peer measurement requests
|
* @pmsr_list: (private) peer measurement requests
|
||||||
* @pmsr_lock: (private) peer measurements requests/results lock
|
* @pmsr_lock: (private) peer measurements requests/results lock
|
||||||
* @pmsr_free_wk: (private) peer measurements cleanup work
|
* @pmsr_free_wk: (private) peer measurements cleanup work
|
||||||
|
* @unprot_beacon_reported: (private) timestamp of last
|
||||||
|
* unprotected beacon report
|
||||||
*/
|
*/
|
||||||
struct wireless_dev {
|
struct wireless_dev {
|
||||||
struct wiphy *wiphy;
|
struct wiphy *wiphy;
|
||||||
@@ -5058,6 +5082,7 @@ struct wireless_dev {
|
|||||||
|
|
||||||
struct list_head mgmt_registrations;
|
struct list_head mgmt_registrations;
|
||||||
spinlock_t mgmt_registrations_lock;
|
spinlock_t mgmt_registrations_lock;
|
||||||
|
struct work_struct mgmt_registrations_update_wk;
|
||||||
|
|
||||||
struct mutex mtx;
|
struct mutex mtx;
|
||||||
|
|
||||||
@@ -5121,6 +5146,8 @@ struct wireless_dev {
|
|||||||
struct list_head pmsr_list;
|
struct list_head pmsr_list;
|
||||||
spinlock_t pmsr_lock;
|
spinlock_t pmsr_lock;
|
||||||
struct work_struct pmsr_free_wk;
|
struct work_struct pmsr_free_wk;
|
||||||
|
|
||||||
|
unsigned long unprot_beacon_reported;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline u8 *wdev_address(struct wireless_dev *wdev)
|
static inline u8 *wdev_address(struct wireless_dev *wdev)
|
||||||
@@ -5155,30 +5182,92 @@ static inline void *wdev_priv(struct wireless_dev *wdev)
|
|||||||
* cfg80211 offers a number of utility functions that can be useful.
|
* cfg80211 offers a number of utility functions that can be useful.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_channel_equal - compare two struct ieee80211_channel
|
||||||
|
*
|
||||||
|
* @a: 1st struct ieee80211_channel
|
||||||
|
* @b: 2nd struct ieee80211_channel
|
||||||
|
* Return: true if center frequency of @a == @b
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
ieee80211_channel_equal(struct ieee80211_channel *a,
|
||||||
|
struct ieee80211_channel *b)
|
||||||
|
{
|
||||||
|
return (a->center_freq == b->center_freq &&
|
||||||
|
a->freq_offset == b->freq_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_channel_to_khz - convert ieee80211_channel to frequency in KHz
|
||||||
|
* @chan: struct ieee80211_channel to convert
|
||||||
|
* Return: The corresponding frequency (in KHz)
|
||||||
|
*/
|
||||||
|
static inline u32
|
||||||
|
ieee80211_channel_to_khz(const struct ieee80211_channel *chan)
|
||||||
|
{
|
||||||
|
return MHZ_TO_KHZ(chan->center_freq) + chan->freq_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_channel_to_freq_khz - convert channel number to frequency
|
||||||
|
* @chan: channel number
|
||||||
|
* @band: band, necessary due to channel number overlap
|
||||||
|
* Return: The corresponding frequency (in KHz), or 0 if the conversion failed.
|
||||||
|
*/
|
||||||
|
u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ieee80211_channel_to_frequency - convert channel number to frequency
|
* ieee80211_channel_to_frequency - convert channel number to frequency
|
||||||
* @chan: channel number
|
* @chan: channel number
|
||||||
* @band: band, necessary due to channel number overlap
|
* @band: band, necessary due to channel number overlap
|
||||||
* Return: The corresponding frequency (in MHz), or 0 if the conversion failed.
|
* Return: The corresponding frequency (in MHz), or 0 if the conversion failed.
|
||||||
*/
|
*/
|
||||||
int ieee80211_channel_to_frequency(int chan, enum nl80211_band band);
|
static inline int
|
||||||
|
ieee80211_channel_to_frequency(int chan, enum nl80211_band band)
|
||||||
|
{
|
||||||
|
return KHZ_TO_MHZ(ieee80211_channel_to_freq_khz(chan, band));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_freq_khz_to_channel - convert frequency to channel number
|
||||||
|
* @freq: center frequency in KHz
|
||||||
|
* Return: The corresponding channel, or 0 if the conversion failed.
|
||||||
|
*/
|
||||||
|
int ieee80211_freq_khz_to_channel(u32 freq);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ieee80211_frequency_to_channel - convert frequency to channel number
|
* ieee80211_frequency_to_channel - convert frequency to channel number
|
||||||
* @freq: center frequency
|
* @freq: center frequency in MHz
|
||||||
* Return: The corresponding channel, or 0 if the conversion failed.
|
* Return: The corresponding channel, or 0 if the conversion failed.
|
||||||
*/
|
*/
|
||||||
int ieee80211_frequency_to_channel(int freq);
|
static inline int
|
||||||
|
ieee80211_frequency_to_channel(int freq)
|
||||||
|
{
|
||||||
|
return ieee80211_freq_khz_to_channel(MHZ_TO_KHZ(freq));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_get_channel_khz - get channel struct from wiphy for specified
|
||||||
|
* frequency
|
||||||
|
* @wiphy: the struct wiphy to get the channel for
|
||||||
|
* @freq: the center frequency (in KHz) of the channel
|
||||||
|
* Return: The channel struct from @wiphy at @freq.
|
||||||
|
*/
|
||||||
|
struct ieee80211_channel *
|
||||||
|
ieee80211_get_channel_khz(struct wiphy *wiphy, u32 freq);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ieee80211_get_channel - get channel struct from wiphy for specified frequency
|
* ieee80211_get_channel - get channel struct from wiphy for specified frequency
|
||||||
*
|
*
|
||||||
* @wiphy: the struct wiphy to get the channel for
|
* @wiphy: the struct wiphy to get the channel for
|
||||||
* @freq: the center frequency of the channel
|
* @freq: the center frequency (in MHz) of the channel
|
||||||
*
|
|
||||||
* Return: The channel struct from @wiphy at @freq.
|
* Return: The channel struct from @wiphy at @freq.
|
||||||
*/
|
*/
|
||||||
struct ieee80211_channel *ieee80211_get_channel(struct wiphy *wiphy, int freq);
|
static inline struct ieee80211_channel *
|
||||||
|
ieee80211_get_channel(struct wiphy *wiphy, int freq)
|
||||||
|
{
|
||||||
|
return ieee80211_get_channel_khz(wiphy, MHZ_TO_KHZ(freq));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ieee80211_get_response_rate - get basic rate for a given rate
|
* ieee80211_get_response_rate - get basic rate for a given rate
|
||||||
@@ -6135,12 +6224,16 @@ void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len);
|
|||||||
/**
|
/**
|
||||||
* cfg80211_rx_unprot_mlme_mgmt - notification of unprotected mlme mgmt frame
|
* cfg80211_rx_unprot_mlme_mgmt - notification of unprotected mlme mgmt frame
|
||||||
* @dev: network device
|
* @dev: network device
|
||||||
* @buf: deauthentication frame (header + body)
|
* @buf: received management frame (header + body)
|
||||||
* @len: length of the frame data
|
* @len: length of the frame data
|
||||||
*
|
*
|
||||||
* This function is called whenever a received deauthentication or dissassoc
|
* This function is called whenever a received deauthentication or dissassoc
|
||||||
* frame has been dropped in station mode because of MFP being used but the
|
* frame has been dropped in station mode because of MFP being used but the
|
||||||
* frame was not protected. This function may sleep.
|
* frame was not protected. This is also used to notify reception of a Beacon
|
||||||
|
* frame that was dropped because it did not include a valid MME MIC while
|
||||||
|
* beacon protection was enabled (BIGTK configured in station mode).
|
||||||
|
*
|
||||||
|
* This function may sleep.
|
||||||
*/
|
*/
|
||||||
void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev,
|
void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev,
|
||||||
const u8 *buf, size_t len);
|
const u8 *buf, size_t len);
|
||||||
@@ -7202,6 +7295,19 @@ bool ieee80211_operating_class_to_band(u8 operating_class,
|
|||||||
bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
|
bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
|
||||||
u8 *op_class);
|
u8 *op_class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_chandef_to_khz - convert chandef to frequency in KHz
|
||||||
|
*
|
||||||
|
* @chandef: the chandef to convert
|
||||||
|
*
|
||||||
|
* Returns the center frequency of chandef (1st segment) in KHz.
|
||||||
|
*/
|
||||||
|
static inline u32
|
||||||
|
ieee80211_chandef_to_khz(const struct cfg80211_chan_def *chandef)
|
||||||
|
{
|
||||||
|
return MHZ_TO_KHZ(chandef->center_freq1) + chandef->freq1_offset;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cfg80211_tdls_oper_request - request userspace to perform TDLS operation
|
* cfg80211_tdls_oper_request - request userspace to perform TDLS operation
|
||||||
* @dev: the device on which the operation is requested
|
* @dev: the device on which the operation is requested
|
||||||
|
@@ -508,6 +508,7 @@ struct ieee80211_ftm_responder_params {
|
|||||||
* mode only, set if the AP advertises TWT responder role)
|
* mode only, set if the AP advertises TWT responder role)
|
||||||
* @twt_responder: does this BSS support TWT requester (relevant for managed
|
* @twt_responder: does this BSS support TWT requester (relevant for managed
|
||||||
* mode only, set if the AP advertises TWT responder role)
|
* mode only, set if the AP advertises TWT responder role)
|
||||||
|
* @twt_protected: does this BSS support protected TWT frames
|
||||||
* @assoc: association status
|
* @assoc: association status
|
||||||
* @ibss_joined: indicates whether this station is part of an IBSS
|
* @ibss_joined: indicates whether this station is part of an IBSS
|
||||||
* or not
|
* or not
|
||||||
@@ -603,7 +604,7 @@ struct ieee80211_ftm_responder_params {
|
|||||||
* nontransmitted BSSIDs
|
* nontransmitted BSSIDs
|
||||||
* @profile_periodicity: the least number of beacon frames need to be received
|
* @profile_periodicity: the least number of beacon frames need to be received
|
||||||
* in order to discover all the nontransmitted BSSIDs in the set.
|
* in order to discover all the nontransmitted BSSIDs in the set.
|
||||||
* @he_operation: HE operation information of the AP we are connected to
|
* @he_oper: HE operation information of the AP we are connected to
|
||||||
* @he_obss_pd: OBSS Packet Detection parameters.
|
* @he_obss_pd: OBSS Packet Detection parameters.
|
||||||
* @he_bss_color: BSS coloring settings, if BSS supports HE
|
* @he_bss_color: BSS coloring settings, if BSS supports HE
|
||||||
*/
|
*/
|
||||||
@@ -618,6 +619,7 @@ struct ieee80211_bss_conf {
|
|||||||
bool he_support;
|
bool he_support;
|
||||||
bool twt_requester;
|
bool twt_requester;
|
||||||
bool twt_responder;
|
bool twt_responder;
|
||||||
|
bool twt_protected;
|
||||||
/* association related data */
|
/* association related data */
|
||||||
bool assoc, ibss_joined;
|
bool assoc, ibss_joined;
|
||||||
bool ibss_creator;
|
bool ibss_creator;
|
||||||
@@ -666,7 +668,10 @@ struct ieee80211_bss_conf {
|
|||||||
u8 bssid_indicator;
|
u8 bssid_indicator;
|
||||||
bool ema_ap;
|
bool ema_ap;
|
||||||
u8 profile_periodicity;
|
u8 profile_periodicity;
|
||||||
struct ieee80211_he_operation he_operation;
|
struct {
|
||||||
|
u32 params;
|
||||||
|
u16 nss_set;
|
||||||
|
} he_oper;
|
||||||
struct ieee80211_he_obss_pd he_obss_pd;
|
struct ieee80211_he_obss_pd he_obss_pd;
|
||||||
struct cfg80211_he_bss_color he_bss_color;
|
struct cfg80211_he_bss_color he_bss_color;
|
||||||
};
|
};
|
||||||
@@ -818,6 +823,8 @@ enum mac80211_tx_info_flags {
|
|||||||
* @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
|
* @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
|
||||||
* @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xmit path
|
* @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xmit path
|
||||||
* @IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP: This frame skips mesh path lookup
|
* @IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP: This frame skips mesh path lookup
|
||||||
|
* @IEEE80211_TX_CTRL_HW_80211_ENCAP: This frame uses hardware encapsulation
|
||||||
|
* (header conversion)
|
||||||
*
|
*
|
||||||
* These flags are used in tx_info->control.flags.
|
* These flags are used in tx_info->control.flags.
|
||||||
*/
|
*/
|
||||||
@@ -1333,6 +1340,7 @@ enum mac80211_rx_encoding {
|
|||||||
* @freq: frequency the radio was tuned to when receiving this frame, in MHz
|
* @freq: frequency the radio was tuned to when receiving this frame, in MHz
|
||||||
* This field must be set for management frames, but isn't strictly needed
|
* This field must be set for management frames, but isn't strictly needed
|
||||||
* for data (other) frames - for those it only affects radiotap reporting.
|
* for data (other) frames - for those it only affects radiotap reporting.
|
||||||
|
* @freq_offset: @freq has a positive offset of 500Khz.
|
||||||
* @signal: signal strength when receiving this frame, either in dBm, in dB or
|
* @signal: signal strength when receiving this frame, either in dBm, in dB or
|
||||||
* unspecified depending on the hardware capabilities flags
|
* unspecified depending on the hardware capabilities flags
|
||||||
* @IEEE80211_HW_SIGNAL_*
|
* @IEEE80211_HW_SIGNAL_*
|
||||||
@@ -1363,7 +1371,7 @@ struct ieee80211_rx_status {
|
|||||||
u32 device_timestamp;
|
u32 device_timestamp;
|
||||||
u32 ampdu_reference;
|
u32 ampdu_reference;
|
||||||
u32 flag;
|
u32 flag;
|
||||||
u16 freq;
|
u16 freq: 13, freq_offset: 1;
|
||||||
u8 enc_flags;
|
u8 enc_flags;
|
||||||
u8 encoding:2, bw:3, he_ru:3;
|
u8 encoding:2, bw:3, he_ru:3;
|
||||||
u8 he_gi:2, he_dcm:1;
|
u8 he_gi:2, he_dcm:1;
|
||||||
@@ -1379,6 +1387,13 @@ struct ieee80211_rx_status {
|
|||||||
u8 zero_length_psdu_type;
|
u8 zero_length_psdu_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline u32
|
||||||
|
ieee80211_rx_status_to_khz(struct ieee80211_rx_status *rx_status)
|
||||||
|
{
|
||||||
|
return MHZ_TO_KHZ(rx_status->freq) +
|
||||||
|
(rx_status->freq_offset ? 500 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ieee80211_vendor_radiotap - vendor radiotap data information
|
* struct ieee80211_vendor_radiotap - vendor radiotap data information
|
||||||
* @present: presence bitmap for this vendor namespace
|
* @present: presence bitmap for this vendor namespace
|
||||||
@@ -1620,6 +1635,8 @@ enum ieee80211_vif_flags {
|
|||||||
* monitor interface (if that is requested.)
|
* monitor interface (if that is requested.)
|
||||||
* @probe_req_reg: probe requests should be reported to mac80211 for this
|
* @probe_req_reg: probe requests should be reported to mac80211 for this
|
||||||
* interface.
|
* interface.
|
||||||
|
* @rx_mcast_action_reg: multicast Action frames should be reported to mac80211
|
||||||
|
* for this interface.
|
||||||
* @drv_priv: data area for driver use, will always be aligned to
|
* @drv_priv: data area for driver use, will always be aligned to
|
||||||
* sizeof(void \*).
|
* sizeof(void \*).
|
||||||
* @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
|
* @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
|
||||||
@@ -1647,7 +1664,8 @@ struct ieee80211_vif {
|
|||||||
struct dentry *debugfs_dir;
|
struct dentry *debugfs_dir;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned int probe_req_reg;
|
bool probe_req_reg;
|
||||||
|
bool rx_mcast_action_reg;
|
||||||
|
|
||||||
bool txqs_stopped[IEEE80211_NUM_ACS];
|
bool txqs_stopped[IEEE80211_NUM_ACS];
|
||||||
|
|
||||||
@@ -3091,6 +3109,8 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
|
|||||||
* @FIF_PSPOLL: pass PS Poll frames
|
* @FIF_PSPOLL: pass PS Poll frames
|
||||||
*
|
*
|
||||||
* @FIF_PROBE_REQ: pass probe request frames
|
* @FIF_PROBE_REQ: pass probe request frames
|
||||||
|
*
|
||||||
|
* @FIF_MCAST_ACTION: pass multicast Action frames
|
||||||
*/
|
*/
|
||||||
enum ieee80211_filter_flags {
|
enum ieee80211_filter_flags {
|
||||||
FIF_ALLMULTI = 1<<1,
|
FIF_ALLMULTI = 1<<1,
|
||||||
@@ -3101,6 +3121,7 @@ enum ieee80211_filter_flags {
|
|||||||
FIF_OTHER_BSS = 1<<6,
|
FIF_OTHER_BSS = 1<<6,
|
||||||
FIF_PSPOLL = 1<<7,
|
FIF_PSPOLL = 1<<7,
|
||||||
FIF_PROBE_REQ = 1<<8,
|
FIF_PROBE_REQ = 1<<8,
|
||||||
|
FIF_MCAST_ACTION = 1<<9,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3117,7 +3138,10 @@ enum ieee80211_filter_flags {
|
|||||||
* @IEEE80211_AMPDU_RX_START: start RX aggregation
|
* @IEEE80211_AMPDU_RX_START: start RX aggregation
|
||||||
* @IEEE80211_AMPDU_RX_STOP: stop RX aggregation
|
* @IEEE80211_AMPDU_RX_STOP: stop RX aggregation
|
||||||
* @IEEE80211_AMPDU_TX_START: start TX aggregation, the driver must either
|
* @IEEE80211_AMPDU_TX_START: start TX aggregation, the driver must either
|
||||||
* call ieee80211_start_tx_ba_cb_irqsafe() or return the special
|
* call ieee80211_start_tx_ba_cb_irqsafe() or
|
||||||
|
* call ieee80211_start_tx_ba_cb_irqsafe() with status
|
||||||
|
* %IEEE80211_AMPDU_TX_START_DELAY_ADDBA to delay addba after
|
||||||
|
* ieee80211_start_tx_ba_cb_irqsafe is called, or just return the special
|
||||||
* status %IEEE80211_AMPDU_TX_START_IMMEDIATE.
|
* status %IEEE80211_AMPDU_TX_START_IMMEDIATE.
|
||||||
* @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational
|
* @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational
|
||||||
* @IEEE80211_AMPDU_TX_STOP_CONT: stop TX aggregation but continue transmitting
|
* @IEEE80211_AMPDU_TX_STOP_CONT: stop TX aggregation but continue transmitting
|
||||||
@@ -3143,6 +3167,7 @@ enum ieee80211_ampdu_mlme_action {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define IEEE80211_AMPDU_TX_START_IMMEDIATE 1
|
#define IEEE80211_AMPDU_TX_START_IMMEDIATE 1
|
||||||
|
#define IEEE80211_AMPDU_TX_START_DELAY_ADDBA 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ieee80211_ampdu_params - AMPDU action parameters
|
* struct ieee80211_ampdu_params - AMPDU action parameters
|
||||||
|
@@ -231,13 +231,6 @@ struct ieee80211_regdomain {
|
|||||||
struct ieee80211_reg_rule reg_rules[];
|
struct ieee80211_reg_rule reg_rules[];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MHZ_TO_KHZ(freq) ((freq) * 1000)
|
|
||||||
#define KHZ_TO_MHZ(freq) ((freq) / 1000)
|
|
||||||
#define DBI_TO_MBI(gain) ((gain) * 100)
|
|
||||||
#define MBI_TO_DBI(gain) ((gain) / 100)
|
|
||||||
#define DBM_TO_MBM(gain) ((gain) * 100)
|
|
||||||
#define MBM_TO_DBM(gain) ((gain) / 100)
|
|
||||||
|
|
||||||
#define REG_RULE_EXT(start, end, bw, gain, eirp, dfs_cac, reg_flags) \
|
#define REG_RULE_EXT(start, end, bw, gain, eirp, dfs_cac, reg_flags) \
|
||||||
{ \
|
{ \
|
||||||
.freq_range.start_freq_khz = MHZ_TO_KHZ(start), \
|
.freq_range.start_freq_khz = MHZ_TO_KHZ(start), \
|
||||||
|
@@ -687,6 +687,10 @@
|
|||||||
* four bytes for vendor frames including the OUI. The registration
|
* four bytes for vendor frames including the OUI. The registration
|
||||||
* cannot be dropped, but is removed automatically when the netlink
|
* cannot be dropped, but is removed automatically when the netlink
|
||||||
* socket is closed. Multiple registrations can be made.
|
* socket is closed. Multiple registrations can be made.
|
||||||
|
* The %NL80211_ATTR_RECEIVE_MULTICAST flag attribute can be given if
|
||||||
|
* %NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS is available, in which
|
||||||
|
* case the registration can also be modified to include/exclude the
|
||||||
|
* flag, rather than requiring unregistration to change it.
|
||||||
* @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for
|
* @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for
|
||||||
* backward compatibility
|
* backward compatibility
|
||||||
* @NL80211_CMD_FRAME: Management frame TX request and RX notification. This
|
* @NL80211_CMD_FRAME: Management frame TX request and RX notification. This
|
||||||
@@ -1151,6 +1155,11 @@
|
|||||||
* @NL80211_CMD_SET_TID_CONFIG: Data frame TID specific configuration
|
* @NL80211_CMD_SET_TID_CONFIG: Data frame TID specific configuration
|
||||||
* is passed using %NL80211_ATTR_TID_CONFIG attribute.
|
* is passed using %NL80211_ATTR_TID_CONFIG attribute.
|
||||||
*
|
*
|
||||||
|
* @NL80211_CMD_UNPROT_BEACON: Unprotected or incorrectly protected Beacon
|
||||||
|
* frame. This event is used to indicate that a received Beacon frame was
|
||||||
|
* dropped because it did not include a valid MME MIC while beacon
|
||||||
|
* protection was enabled (BIGTK configured in station mode).
|
||||||
|
*
|
||||||
* @NL80211_CMD_MAX: highest used command number
|
* @NL80211_CMD_MAX: highest used command number
|
||||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||||
*/
|
*/
|
||||||
@@ -1377,6 +1386,8 @@ enum nl80211_commands {
|
|||||||
|
|
||||||
NL80211_CMD_SET_TID_CONFIG,
|
NL80211_CMD_SET_TID_CONFIG,
|
||||||
|
|
||||||
|
NL80211_CMD_UNPROT_BEACON,
|
||||||
|
|
||||||
/* add new commands above here */
|
/* add new commands above here */
|
||||||
|
|
||||||
/* used to define NL80211_CMD_MAX below */
|
/* used to define NL80211_CMD_MAX below */
|
||||||
@@ -2470,6 +2481,9 @@ enum nl80211_commands {
|
|||||||
* no roaming occurs between the reauth threshold and PMK expiration,
|
* no roaming occurs between the reauth threshold and PMK expiration,
|
||||||
* disassociation is still forced.
|
* disassociation is still forced.
|
||||||
*
|
*
|
||||||
|
* @NL80211_ATTR_RECEIVE_MULTICAST: multicast flag for the
|
||||||
|
* %NL80211_CMD_REGISTER_FRAME command, see the description there.
|
||||||
|
*
|
||||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||||
@@ -2945,6 +2959,8 @@ enum nl80211_attrs {
|
|||||||
NL80211_ATTR_PMK_LIFETIME,
|
NL80211_ATTR_PMK_LIFETIME,
|
||||||
NL80211_ATTR_PMK_REAUTH_THRESHOLD,
|
NL80211_ATTR_PMK_REAUTH_THRESHOLD,
|
||||||
|
|
||||||
|
NL80211_ATTR_RECEIVE_MULTICAST,
|
||||||
|
|
||||||
/* add attributes here, update the policy in nl80211.c */
|
/* add attributes here, update the policy in nl80211.c */
|
||||||
|
|
||||||
__NL80211_ATTR_AFTER_LAST,
|
__NL80211_ATTR_AFTER_LAST,
|
||||||
@@ -5674,6 +5690,8 @@ enum nl80211_feature_flags {
|
|||||||
*
|
*
|
||||||
* @NL80211_EXT_FEATURE_BEACON_PROTECTION: The driver supports Beacon protection
|
* @NL80211_EXT_FEATURE_BEACON_PROTECTION: The driver supports Beacon protection
|
||||||
* and can receive key configuration for BIGTK using key indexes 6 and 7.
|
* and can receive key configuration for BIGTK using key indexes 6 and 7.
|
||||||
|
* @NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT: The driver supports Beacon
|
||||||
|
* protection as a client only and cannot transmit protected beacons.
|
||||||
*
|
*
|
||||||
* @NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH: The driver can disable the
|
* @NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH: The driver can disable the
|
||||||
* forwarding of preauth frames over the control port. They are then
|
* forwarding of preauth frames over the control port. They are then
|
||||||
@@ -5684,6 +5702,9 @@ enum nl80211_feature_flags {
|
|||||||
* @NL80211_EXT_FEATURE_DEL_IBSS_STA: The driver supports removing stations
|
* @NL80211_EXT_FEATURE_DEL_IBSS_STA: The driver supports removing stations
|
||||||
* in IBSS mode, essentially by dropping their state.
|
* in IBSS mode, essentially by dropping their state.
|
||||||
*
|
*
|
||||||
|
* @NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS: management frame registrations
|
||||||
|
* are possible for multicast frames and those will be reported properly.
|
||||||
|
*
|
||||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||||
*/
|
*/
|
||||||
@@ -5735,6 +5756,8 @@ enum nl80211_ext_feature_index {
|
|||||||
NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH,
|
NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH,
|
||||||
NL80211_EXT_FEATURE_PROTECTED_TWT,
|
NL80211_EXT_FEATURE_PROTECTED_TWT,
|
||||||
NL80211_EXT_FEATURE_DEL_IBSS_STA,
|
NL80211_EXT_FEATURE_DEL_IBSS_STA,
|
||||||
|
NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS,
|
||||||
|
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT,
|
||||||
|
|
||||||
/* add new features before the definition below */
|
/* add new features before the definition below */
|
||||||
NUM_NL80211_EXT_FEATURES,
|
NUM_NL80211_EXT_FEATURES,
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||||
* Copyright 2007-2010, Intel Corporation
|
* Copyright 2007-2010, Intel Corporation
|
||||||
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 - 2019 Intel Corporation
|
* Copyright (C) 2018 - 2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/ieee80211.h>
|
#include <linux/ieee80211.h>
|
||||||
@@ -448,66 +448,14 @@ static void sta_addba_resp_timer_expired(struct timer_list *t)
|
|||||||
ieee80211_stop_tx_ba_session(&sta->sta, tid);
|
ieee80211_stop_tx_ba_session(&sta->sta, tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
|
static void ieee80211_send_addba_with_timeout(struct sta_info *sta,
|
||||||
|
struct tid_ampdu_tx *tid_tx)
|
||||||
{
|
{
|
||||||
struct tid_ampdu_tx *tid_tx;
|
|
||||||
struct ieee80211_local *local = sta->local;
|
|
||||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||||
struct ieee80211_ampdu_params params = {
|
struct ieee80211_local *local = sta->local;
|
||||||
.sta = &sta->sta,
|
u8 tid = tid_tx->tid;
|
||||||
.action = IEEE80211_AMPDU_TX_START,
|
|
||||||
.tid = tid,
|
|
||||||
.buf_size = 0,
|
|
||||||
.amsdu = false,
|
|
||||||
.timeout = 0,
|
|
||||||
};
|
|
||||||
int ret;
|
|
||||||
u16 buf_size;
|
u16 buf_size;
|
||||||
|
|
||||||
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Start queuing up packets for this aggregation session.
|
|
||||||
* We're going to release them once the driver is OK with
|
|
||||||
* that.
|
|
||||||
*/
|
|
||||||
clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
|
|
||||||
|
|
||||||
ieee80211_agg_stop_txq(sta, tid);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure no packets are being processed. This ensures that
|
|
||||||
* we have a valid starting sequence number and that in-flight
|
|
||||||
* packets have been flushed out and no packets for this TID
|
|
||||||
* will go into the driver during the ampdu_action call.
|
|
||||||
*/
|
|
||||||
synchronize_net();
|
|
||||||
|
|
||||||
params.ssn = sta->tid_seq[tid] >> 4;
|
|
||||||
ret = drv_ampdu_action(local, sdata, ¶ms);
|
|
||||||
if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) {
|
|
||||||
/*
|
|
||||||
* We didn't send the request yet, so don't need to check
|
|
||||||
* here if we already got a response, just mark as driver
|
|
||||||
* ready immediately.
|
|
||||||
*/
|
|
||||||
set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state);
|
|
||||||
} else if (ret) {
|
|
||||||
ht_dbg(sdata,
|
|
||||||
"BA request denied - HW unavailable for %pM tid %d\n",
|
|
||||||
sta->sta.addr, tid);
|
|
||||||
spin_lock_bh(&sta->lock);
|
|
||||||
ieee80211_agg_splice_packets(sdata, tid_tx, tid);
|
|
||||||
ieee80211_assign_tid_tx(sta, tid, NULL);
|
|
||||||
ieee80211_agg_splice_finish(sdata, tid);
|
|
||||||
spin_unlock_bh(&sta->lock);
|
|
||||||
|
|
||||||
ieee80211_agg_start_txq(sta, tid, false);
|
|
||||||
|
|
||||||
kfree_rcu(tid_tx, rcu_head);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* activate the timer for the recipient's addBA response */
|
/* activate the timer for the recipient's addBA response */
|
||||||
mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
|
mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
|
||||||
ht_dbg(sdata, "activated addBA response timer on %pM tid %d\n",
|
ht_dbg(sdata, "activated addBA response timer on %pM tid %d\n",
|
||||||
@@ -532,8 +480,75 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
|
|||||||
|
|
||||||
/* send AddBA request */
|
/* send AddBA request */
|
||||||
ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
|
ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
|
||||||
tid_tx->dialog_token, params.ssn,
|
tid_tx->dialog_token,
|
||||||
|
sta->tid_seq[tid] >> 4,
|
||||||
buf_size, tid_tx->timeout);
|
buf_size, tid_tx->timeout);
|
||||||
|
|
||||||
|
WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
|
||||||
|
{
|
||||||
|
struct tid_ampdu_tx *tid_tx;
|
||||||
|
struct ieee80211_local *local = sta->local;
|
||||||
|
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||||
|
struct ieee80211_ampdu_params params = {
|
||||||
|
.sta = &sta->sta,
|
||||||
|
.action = IEEE80211_AMPDU_TX_START,
|
||||||
|
.tid = tid,
|
||||||
|
.buf_size = 0,
|
||||||
|
.amsdu = false,
|
||||||
|
.timeout = 0,
|
||||||
|
};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start queuing up packets for this aggregation session.
|
||||||
|
* We're going to release them once the driver is OK with
|
||||||
|
* that.
|
||||||
|
*/
|
||||||
|
clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
|
||||||
|
|
||||||
|
ieee80211_agg_stop_txq(sta, tid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure no packets are being processed. This ensures that
|
||||||
|
* we have a valid starting sequence number and that in-flight
|
||||||
|
* packets have been flushed out and no packets for this TID
|
||||||
|
* will go into the driver during the ampdu_action call.
|
||||||
|
*/
|
||||||
|
synchronize_net();
|
||||||
|
|
||||||
|
params.ssn = sta->tid_seq[tid] >> 4;
|
||||||
|
ret = drv_ampdu_action(local, sdata, ¶ms);
|
||||||
|
if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) {
|
||||||
|
return;
|
||||||
|
} else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) {
|
||||||
|
/*
|
||||||
|
* We didn't send the request yet, so don't need to check
|
||||||
|
* here if we already got a response, just mark as driver
|
||||||
|
* ready immediately.
|
||||||
|
*/
|
||||||
|
set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state);
|
||||||
|
} else if (ret) {
|
||||||
|
ht_dbg(sdata,
|
||||||
|
"BA request denied - HW unavailable for %pM tid %d\n",
|
||||||
|
sta->sta.addr, tid);
|
||||||
|
spin_lock_bh(&sta->lock);
|
||||||
|
ieee80211_agg_splice_packets(sdata, tid_tx, tid);
|
||||||
|
ieee80211_assign_tid_tx(sta, tid, NULL);
|
||||||
|
ieee80211_agg_splice_finish(sdata, tid);
|
||||||
|
spin_unlock_bh(&sta->lock);
|
||||||
|
|
||||||
|
ieee80211_agg_start_txq(sta, tid, false);
|
||||||
|
|
||||||
|
kfree_rcu(tid_tx, rcu_head);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ieee80211_send_addba_with_timeout(sta, tid_tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -754,6 +769,12 @@ void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid,
|
|||||||
if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
|
if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!test_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)) {
|
||||||
|
ieee80211_send_addba_with_timeout(sta, tid_tx);
|
||||||
|
/* RESPONSE_RECEIVED state whould trigger the flow again */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
|
if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
|
||||||
ieee80211_agg_tx_operational(local, sta, tid);
|
ieee80211_agg_tx_operational(local, sta, tid);
|
||||||
}
|
}
|
||||||
|
@@ -994,7 +994,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
BSS_CHANGED_TWT |
|
BSS_CHANGED_TWT |
|
||||||
BSS_CHANGED_HE_OBSS_PD |
|
BSS_CHANGED_HE_OBSS_PD |
|
||||||
BSS_CHANGED_HE_BSS_COLOR;
|
BSS_CHANGED_HE_BSS_COLOR;
|
||||||
int err;
|
int i, err;
|
||||||
int prev_beacon_int;
|
int prev_beacon_int;
|
||||||
|
|
||||||
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||||
@@ -1085,6 +1085,17 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
|
sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
|
||||||
IEEE80211_P2P_OPPPS_ENABLE_BIT;
|
IEEE80211_P2P_OPPPS_ENABLE_BIT;
|
||||||
|
|
||||||
|
sdata->beacon_rate_set = false;
|
||||||
|
if (wiphy_ext_feature_isset(local->hw.wiphy,
|
||||||
|
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY)) {
|
||||||
|
for (i = 0; i < NUM_NL80211_BANDS; i++) {
|
||||||
|
sdata->beacon_rateidx_mask[i] =
|
||||||
|
params->beacon_rate.control[i].legacy;
|
||||||
|
if (sdata->beacon_rateidx_mask[i])
|
||||||
|
sdata->beacon_rate_set = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL);
|
err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
ieee80211_vif_release_channel(sdata);
|
ieee80211_vif_release_channel(sdata);
|
||||||
@@ -1189,6 +1200,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||||||
ieee80211_free_keys(sdata, true);
|
ieee80211_free_keys(sdata, true);
|
||||||
|
|
||||||
sdata->vif.bss_conf.enable_beacon = false;
|
sdata->vif.bss_conf.enable_beacon = false;
|
||||||
|
sdata->beacon_rate_set = false;
|
||||||
sdata->vif.bss_conf.ssid_len = 0;
|
sdata->vif.bss_conf.ssid_len = 0;
|
||||||
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
||||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||||
@@ -1949,6 +1961,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
|
|||||||
const u8 *old_ie;
|
const u8 *old_ie;
|
||||||
struct ieee80211_sub_if_data *sdata = container_of(ifmsh,
|
struct ieee80211_sub_if_data *sdata = container_of(ifmsh,
|
||||||
struct ieee80211_sub_if_data, u.mesh);
|
struct ieee80211_sub_if_data, u.mesh);
|
||||||
|
int i;
|
||||||
|
|
||||||
/* allocate information elements */
|
/* allocate information elements */
|
||||||
new_ie = NULL;
|
new_ie = NULL;
|
||||||
@@ -1987,6 +2000,17 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
|
|||||||
sdata->vif.bss_conf.beacon_int = setup->beacon_interval;
|
sdata->vif.bss_conf.beacon_int = setup->beacon_interval;
|
||||||
sdata->vif.bss_conf.dtim_period = setup->dtim_period;
|
sdata->vif.bss_conf.dtim_period = setup->dtim_period;
|
||||||
|
|
||||||
|
sdata->beacon_rate_set = false;
|
||||||
|
if (wiphy_ext_feature_isset(sdata->local->hw.wiphy,
|
||||||
|
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY)) {
|
||||||
|
for (i = 0; i < NUM_NL80211_BANDS; i++) {
|
||||||
|
sdata->beacon_rateidx_mask[i] =
|
||||||
|
setup->beacon_rate.control[i].legacy;
|
||||||
|
if (sdata->beacon_rateidx_mask[i])
|
||||||
|
sdata->beacon_rate_set = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3287,6 +3311,12 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params->chandef.chan->freq_offset) {
|
||||||
|
/* this may work, but is untested */
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
chanctx = container_of(conf, struct ieee80211_chanctx, conf);
|
chanctx = container_of(conf, struct ieee80211_chanctx, conf);
|
||||||
|
|
||||||
ch_switch.timestamp = 0;
|
ch_switch.timestamp = 0;
|
||||||
@@ -3398,41 +3428,43 @@ int ieee80211_attach_ack_skb(struct ieee80211_local *local, struct sk_buff *skb,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
|
static void
|
||||||
|
ieee80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
u16 frame_type, bool reg)
|
struct mgmt_frame_regs *upd)
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||||
|
u32 preq_mask = BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
|
||||||
|
u32 action_mask = BIT(IEEE80211_STYPE_ACTION >> 4);
|
||||||
|
bool global_change, intf_change;
|
||||||
|
|
||||||
switch (frame_type) {
|
global_change =
|
||||||
case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ:
|
(local->probe_req_reg != !!(upd->global_stypes & preq_mask)) ||
|
||||||
if (reg) {
|
(local->rx_mcast_action_reg !=
|
||||||
local->probe_req_reg++;
|
!!(upd->global_mcast_stypes & action_mask));
|
||||||
sdata->vif.probe_req_reg++;
|
local->probe_req_reg = upd->global_stypes & preq_mask;
|
||||||
} else {
|
local->rx_mcast_action_reg = upd->global_mcast_stypes & action_mask;
|
||||||
if (local->probe_req_reg)
|
|
||||||
local->probe_req_reg--;
|
|
||||||
|
|
||||||
if (sdata->vif.probe_req_reg)
|
intf_change = (sdata->vif.probe_req_reg !=
|
||||||
sdata->vif.probe_req_reg--;
|
!!(upd->interface_stypes & preq_mask)) ||
|
||||||
}
|
(sdata->vif.rx_mcast_action_reg !=
|
||||||
|
!!(upd->interface_mcast_stypes & action_mask));
|
||||||
|
sdata->vif.probe_req_reg = upd->interface_stypes & preq_mask;
|
||||||
|
sdata->vif.rx_mcast_action_reg =
|
||||||
|
upd->interface_mcast_stypes & action_mask;
|
||||||
|
|
||||||
if (!local->open_count)
|
if (!local->open_count)
|
||||||
break;
|
return;
|
||||||
|
|
||||||
if (sdata->vif.probe_req_reg == 1)
|
if (intf_change && ieee80211_sdata_running(sdata))
|
||||||
drv_config_iface_filter(local, sdata, FIF_PROBE_REQ,
|
drv_config_iface_filter(local, sdata,
|
||||||
FIF_PROBE_REQ);
|
sdata->vif.probe_req_reg ?
|
||||||
else if (sdata->vif.probe_req_reg == 0)
|
FIF_PROBE_REQ : 0,
|
||||||
drv_config_iface_filter(local, sdata, 0,
|
|
||||||
FIF_PROBE_REQ);
|
FIF_PROBE_REQ);
|
||||||
|
|
||||||
|
if (global_change)
|
||||||
ieee80211_configure_filter(local);
|
ieee80211_configure_filter(local);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
|
static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
|
||||||
@@ -4017,7 +4049,8 @@ const struct cfg80211_ops mac80211_config_ops = {
|
|||||||
.mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,
|
.mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,
|
||||||
.set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
|
.set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
|
||||||
.set_cqm_rssi_range_config = ieee80211_set_cqm_rssi_range_config,
|
.set_cqm_rssi_range_config = ieee80211_set_cqm_rssi_range_config,
|
||||||
.mgmt_frame_register = ieee80211_mgmt_frame_register,
|
.update_mgmt_frame_registrations =
|
||||||
|
ieee80211_update_mgmt_frame_registrations,
|
||||||
.set_antenna = ieee80211_set_antenna,
|
.set_antenna = ieee80211_set_antenna,
|
||||||
.get_antenna = ieee80211_get_antenna,
|
.get_antenna = ieee80211_get_antenna,
|
||||||
.set_rekey_data = ieee80211_set_rekey_data,
|
.set_rekey_data = ieee80211_set_rekey_data,
|
||||||
|
@@ -533,6 +533,7 @@ static void ieee80211_del_chanctx(struct ieee80211_local *local,
|
|||||||
struct cfg80211_chan_def *chandef = &local->_oper_chandef;
|
struct cfg80211_chan_def *chandef = &local->_oper_chandef;
|
||||||
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
|
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||||
chandef->center_freq1 = chandef->chan->center_freq;
|
chandef->center_freq1 = chandef->chan->center_freq;
|
||||||
|
chandef->freq1_offset = chandef->chan->freq_offset;
|
||||||
chandef->center_freq2 = 0;
|
chandef->center_freq2 = 0;
|
||||||
|
|
||||||
/* NOTE: Disabling radar is only valid here for
|
/* NOTE: Disabling radar is only valid here for
|
||||||
|
@@ -236,7 +236,7 @@ IEEE80211_IF_FILE_R(hw_queues);
|
|||||||
|
|
||||||
/* STA attributes */
|
/* STA attributes */
|
||||||
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
|
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
|
||||||
IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
|
IEEE80211_IF_FILE(aid, vif.bss_conf.aid, DEC);
|
||||||
IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS);
|
IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS);
|
||||||
|
|
||||||
static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
|
static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
|
||||||
|
@@ -57,17 +57,14 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
|
|||||||
|
|
||||||
void
|
void
|
||||||
ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif,
|
ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif,
|
||||||
const struct ieee80211_he_operation *he_op_ie_elem)
|
const struct ieee80211_he_operation *he_op_ie)
|
||||||
{
|
{
|
||||||
struct ieee80211_he_operation *he_operation =
|
memset(&vif->bss_conf.he_oper, 0, sizeof(vif->bss_conf.he_oper));
|
||||||
&vif->bss_conf.he_operation;
|
if (!he_op_ie)
|
||||||
|
|
||||||
if (!he_op_ie_elem) {
|
|
||||||
memset(he_operation, 0, sizeof(*he_operation));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
vif->bss_conf.he_operation = *he_op_ie_elem;
|
vif->bss_conf.he_oper.params = __le32_to_cpu(he_op_ie->he_oper_params);
|
||||||
|
vif->bss_conf.he_oper.nss_set = __le16_to_cpu(he_op_ie->he_mcs_nss_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -1758,6 +1758,11 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
|||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (params->chandef.chan->freq_offset) {
|
||||||
|
/* this may work, but is untested */
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
|
ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
|
||||||
¶ms->chandef,
|
¶ms->chandef,
|
||||||
sdata->wdev.iftype);
|
sdata->wdev.iftype);
|
||||||
|
@@ -450,8 +450,6 @@ struct ieee80211_if_managed {
|
|||||||
|
|
||||||
u8 bssid[ETH_ALEN] __aligned(2);
|
u8 bssid[ETH_ALEN] __aligned(2);
|
||||||
|
|
||||||
u16 aid;
|
|
||||||
|
|
||||||
bool powersave; /* powersave requested for this iface */
|
bool powersave; /* powersave requested for this iface */
|
||||||
bool broken_ap; /* AP is broken -- turn off powersave */
|
bool broken_ap; /* AP is broken -- turn off powersave */
|
||||||
bool have_beacon;
|
bool have_beacon;
|
||||||
@@ -964,6 +962,10 @@ struct ieee80211_sub_if_data {
|
|||||||
bool rc_has_vht_mcs_mask[NUM_NL80211_BANDS];
|
bool rc_has_vht_mcs_mask[NUM_NL80211_BANDS];
|
||||||
u16 rc_rateidx_vht_mcs_mask[NUM_NL80211_BANDS][NL80211_VHT_NSS_MAX];
|
u16 rc_rateidx_vht_mcs_mask[NUM_NL80211_BANDS][NL80211_VHT_NSS_MAX];
|
||||||
|
|
||||||
|
/* Beacon frame (non-MCS) rate (as a bitmap) */
|
||||||
|
u32 beacon_rateidx_mask[NUM_NL80211_BANDS];
|
||||||
|
bool beacon_rate_set;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct ieee80211_if_ap ap;
|
struct ieee80211_if_ap ap;
|
||||||
struct ieee80211_if_wds wds;
|
struct ieee80211_if_wds wds;
|
||||||
@@ -1169,7 +1171,8 @@ struct ieee80211_local {
|
|||||||
/* number of interfaces with corresponding FIF_ flags */
|
/* number of interfaces with corresponding FIF_ flags */
|
||||||
int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
|
int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
|
||||||
fif_probe_req;
|
fif_probe_req;
|
||||||
int probe_req_reg;
|
bool probe_req_reg;
|
||||||
|
bool rx_mcast_action_reg;
|
||||||
unsigned int filter_flags; /* FIF_* */
|
unsigned int filter_flags; /* FIF_* */
|
||||||
|
|
||||||
bool wiphy_ciphers_allocated;
|
bool wiphy_ciphers_allocated;
|
||||||
|
@@ -644,6 +644,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
|||||||
local->fif_probe_req++;
|
local->fif_probe_req++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sdata->vif.probe_req_reg)
|
||||||
|
drv_config_iface_filter(local, sdata,
|
||||||
|
FIF_PROBE_REQ,
|
||||||
|
FIF_PROBE_REQ);
|
||||||
|
|
||||||
if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
|
if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
|
||||||
sdata->vif.type != NL80211_IFTYPE_NAN)
|
sdata->vif.type != NL80211_IFTYPE_NAN)
|
||||||
changed |= ieee80211_reset_erp_info(sdata);
|
changed |= ieee80211_reset_erp_info(sdata);
|
||||||
|
@@ -64,6 +64,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
|
|||||||
if (local->fif_pspoll)
|
if (local->fif_pspoll)
|
||||||
new_flags |= FIF_PSPOLL;
|
new_flags |= FIF_PSPOLL;
|
||||||
|
|
||||||
|
if (local->rx_mcast_action_reg)
|
||||||
|
new_flags |= FIF_MCAST_ACTION;
|
||||||
|
|
||||||
spin_lock_bh(&local->filter_lock);
|
spin_lock_bh(&local->filter_lock);
|
||||||
changed_flags = local->filter_flags ^ new_flags;
|
changed_flags = local->filter_flags ^ new_flags;
|
||||||
|
|
||||||
@@ -104,13 +107,15 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
|
|||||||
chandef.chan = local->tmp_channel;
|
chandef.chan = local->tmp_channel;
|
||||||
chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
|
chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||||
chandef.center_freq1 = chandef.chan->center_freq;
|
chandef.center_freq1 = chandef.chan->center_freq;
|
||||||
|
chandef.freq1_offset = chandef.chan->freq_offset;
|
||||||
} else
|
} else
|
||||||
chandef = local->_oper_chandef;
|
chandef = local->_oper_chandef;
|
||||||
|
|
||||||
WARN(!cfg80211_chandef_valid(&chandef),
|
WARN(!cfg80211_chandef_valid(&chandef),
|
||||||
"control:%d MHz width:%d center: %d/%d MHz",
|
"control:%d.%03d MHz width:%d center: %d.%03d/%d MHz",
|
||||||
chandef.chan->center_freq, chandef.width,
|
chandef.chan->center_freq, chandef.chan->freq_offset,
|
||||||
chandef.center_freq1, chandef.center_freq2);
|
chandef.width, chandef.center_freq1, chandef.freq1_offset,
|
||||||
|
chandef.center_freq2);
|
||||||
|
|
||||||
if (!cfg80211_chandef_identical(&chandef, &local->_oper_chandef))
|
if (!cfg80211_chandef_identical(&chandef, &local->_oper_chandef))
|
||||||
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
||||||
|
@@ -994,6 +994,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
|
|||||||
/* stop the beacon */
|
/* stop the beacon */
|
||||||
ifmsh->mesh_id_len = 0;
|
ifmsh->mesh_id_len = 0;
|
||||||
sdata->vif.bss_conf.enable_beacon = false;
|
sdata->vif.bss_conf.enable_beacon = false;
|
||||||
|
sdata->beacon_rate_set = false;
|
||||||
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
||||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||||
|
|
||||||
|
@@ -162,6 +162,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
|||||||
chandef->chan = channel;
|
chandef->chan = channel;
|
||||||
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
|
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||||
chandef->center_freq1 = channel->center_freq;
|
chandef->center_freq1 = channel->center_freq;
|
||||||
|
chandef->freq1_offset = channel->freq_offset;
|
||||||
|
|
||||||
if (!ht_oper || !sta_ht_cap.ht_supported) {
|
if (!ht_oper || !sta_ht_cap.ht_supported) {
|
||||||
ret = IEEE80211_STA_DISABLE_HT |
|
ret = IEEE80211_STA_DISABLE_HT |
|
||||||
@@ -396,9 +397,12 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sdata_info(sdata,
|
sdata_info(sdata,
|
||||||
"AP %pM changed bandwidth, new config is %d MHz, width %d (%d/%d MHz)\n",
|
"AP %pM changed bandwidth, new config is %d.%03d MHz, "
|
||||||
ifmgd->bssid, chandef.chan->center_freq, chandef.width,
|
"width %d (%d.%03d/%d MHz)\n",
|
||||||
chandef.center_freq1, chandef.center_freq2);
|
ifmgd->bssid, chandef.chan->center_freq,
|
||||||
|
chandef.chan->freq_offset, chandef.width,
|
||||||
|
chandef.center_freq1, chandef.freq1_offset,
|
||||||
|
chandef.center_freq2);
|
||||||
|
|
||||||
if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
|
if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
|
||||||
IEEE80211_STA_DISABLE_VHT |
|
IEEE80211_STA_DISABLE_VHT |
|
||||||
@@ -1364,10 +1368,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|||||||
if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef,
|
if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef,
|
||||||
IEEE80211_CHAN_DISABLED)) {
|
IEEE80211_CHAN_DISABLED)) {
|
||||||
sdata_info(sdata,
|
sdata_info(sdata,
|
||||||
"AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
|
"AP %pM switches to unsupported channel "
|
||||||
|
"(%d.%03d MHz, width:%d, CF1/2: %d.%03d/%d MHz), "
|
||||||
|
"disconnecting\n",
|
||||||
ifmgd->associated->bssid,
|
ifmgd->associated->bssid,
|
||||||
csa_ie.chandef.chan->center_freq,
|
csa_ie.chandef.chan->center_freq,
|
||||||
|
csa_ie.chandef.chan->freq_offset,
|
||||||
csa_ie.chandef.width, csa_ie.chandef.center_freq1,
|
csa_ie.chandef.width, csa_ie.chandef.center_freq1,
|
||||||
|
csa_ie.chandef.freq1_offset,
|
||||||
csa_ie.chandef.center_freq2);
|
csa_ie.chandef.center_freq2);
|
||||||
ieee80211_queue_work(&local->hw,
|
ieee80211_queue_work(&local->hw,
|
||||||
&ifmgd->csa_connection_drop_work);
|
&ifmgd->csa_connection_drop_work);
|
||||||
@@ -2948,10 +2956,15 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status_code != WLAN_STATUS_SUCCESS) {
|
if (status_code != WLAN_STATUS_SUCCESS) {
|
||||||
|
cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
|
||||||
|
|
||||||
|
if (auth_alg == WLAN_AUTH_SAE &&
|
||||||
|
status_code == WLAN_STATUS_ANTI_CLOG_REQUIRED)
|
||||||
|
return;
|
||||||
|
|
||||||
sdata_info(sdata, "%pM denied authentication (status %d)\n",
|
sdata_info(sdata, "%pM denied authentication (status %d)\n",
|
||||||
mgmt->sa, status_code);
|
mgmt->sa, status_code);
|
||||||
ieee80211_destroy_auth_data(sdata, false);
|
ieee80211_destroy_auth_data(sdata, false);
|
||||||
cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
|
|
||||||
event.u.mlme.status = MLME_DENIED;
|
event.u.mlme.status = MLME_DENIED;
|
||||||
event.u.mlme.reason = status_code;
|
event.u.mlme.reason = status_code;
|
||||||
drv_event_callback(sdata->local, sdata, &event);
|
drv_event_callback(sdata->local, sdata, &event);
|
||||||
@@ -3149,15 +3162,16 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
|
|||||||
*have_higher_than_11mbit = true;
|
*have_higher_than_11mbit = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip HT and VHT BSS membership selectors since they're not
|
* Skip HT, VHT and HE BSS membership selectors since they're
|
||||||
* rates.
|
* not rates.
|
||||||
*
|
*
|
||||||
* Note: Even though the membership selector and the basic
|
* Note: Even though the membership selector and the basic
|
||||||
* rate flag share the same bit, they are not exactly
|
* rate flag share the same bit, they are not exactly
|
||||||
* the same.
|
* the same.
|
||||||
*/
|
*/
|
||||||
if (supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY) ||
|
if (supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY) ||
|
||||||
supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY))
|
supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY) ||
|
||||||
|
supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HE_PHY))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (j = 0; j < sband->n_bitrates; j++) {
|
for (j = 0; j < sband->n_bitrates; j++) {
|
||||||
@@ -3249,7 +3263,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ifmgd->aid = aid;
|
sdata->vif.bss_conf.aid = aid;
|
||||||
ifmgd->tdls_chan_switch_prohibited =
|
ifmgd->tdls_chan_switch_prohibited =
|
||||||
elems->ext_capab && elems->ext_capab_len >= 5 &&
|
elems->ext_capab && elems->ext_capab_len >= 5 &&
|
||||||
(elems->ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED);
|
(elems->ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED);
|
||||||
@@ -3384,10 +3398,19 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||||||
sta);
|
sta);
|
||||||
|
|
||||||
bss_conf->he_support = sta->sta.he_cap.has_he;
|
bss_conf->he_support = sta->sta.he_cap.has_he;
|
||||||
|
if (elems->rsnx && elems->rsnx_len &&
|
||||||
|
(elems->rsnx[0] & WLAN_RSNX_CAPA_PROTECTED_TWT) &&
|
||||||
|
wiphy_ext_feature_isset(local->hw.wiphy,
|
||||||
|
NL80211_EXT_FEATURE_PROTECTED_TWT))
|
||||||
|
bss_conf->twt_protected = true;
|
||||||
|
else
|
||||||
|
bss_conf->twt_protected = false;
|
||||||
|
|
||||||
changed |= ieee80211_recalc_twt_req(sdata, sta, elems);
|
changed |= ieee80211_recalc_twt_req(sdata, sta, elems);
|
||||||
} else {
|
} else {
|
||||||
bss_conf->he_support = false;
|
bss_conf->he_support = false;
|
||||||
bss_conf->twt_requester = false;
|
bss_conf->twt_requester = false;
|
||||||
|
bss_conf->twt_protected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bss_conf->he_support) {
|
if (bss_conf->he_support) {
|
||||||
@@ -3521,9 +3544,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||||||
bss_conf->protected_keep_alive = false;
|
bss_conf->protected_keep_alive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set AID and assoc capability,
|
/* set assoc capability (AID was already set earlier),
|
||||||
* ieee80211_set_associated() will tell the driver */
|
* ieee80211_set_associated() will tell the driver */
|
||||||
bss_conf->aid = aid;
|
|
||||||
bss_conf->assoc_capability = capab_info;
|
bss_conf->assoc_capability = capab_info;
|
||||||
ieee80211_set_associated(sdata, cbss, changed);
|
ieee80211_set_associated(sdata, cbss, changed);
|
||||||
|
|
||||||
@@ -3661,7 +3683,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
|||||||
|
|
||||||
sdata_assert_lock(sdata);
|
sdata_assert_lock(sdata);
|
||||||
|
|
||||||
channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
|
channel = ieee80211_get_channel_khz(local->hw.wiphy,
|
||||||
|
ieee80211_rx_status_to_khz(rx_status));
|
||||||
if (!channel)
|
if (!channel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -3877,7 +3900,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
|
if (ieee80211_rx_status_to_khz(rx_status) !=
|
||||||
|
ieee80211_channel_to_khz(chanctx_conf->def.chan)) {
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3948,7 +3972,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
|||||||
mgmt->bssid, bssid);
|
mgmt->bssid, bssid);
|
||||||
|
|
||||||
if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
|
if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
|
||||||
ieee80211_check_tim(elems.tim, elems.tim_len, ifmgd->aid)) {
|
ieee80211_check_tim(elems.tim, elems.tim_len, bss_conf->aid)) {
|
||||||
if (local->hw.conf.dynamic_ps_timeout > 0) {
|
if (local->hw.conf.dynamic_ps_timeout > 0) {
|
||||||
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
|
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
|
||||||
local->hw.conf.flags &= ~IEEE80211_CONF_PS;
|
local->hw.conf.flags &= ~IEEE80211_CONF_PS;
|
||||||
@@ -5022,8 +5046,16 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
|
|||||||
* doesn't happen any more, but keep the workaround so
|
* doesn't happen any more, but keep the workaround so
|
||||||
* in case some *other* APs are buggy in different ways
|
* in case some *other* APs are buggy in different ways
|
||||||
* we can connect -- with a warning.
|
* we can connect -- with a warning.
|
||||||
|
* Allow this workaround only in case the AP provided at least
|
||||||
|
* one rate.
|
||||||
*/
|
*/
|
||||||
if (!basic_rates && min_rate_index >= 0) {
|
if (min_rate_index < 0) {
|
||||||
|
sdata_info(sdata,
|
||||||
|
"No legacy rates in association response\n");
|
||||||
|
|
||||||
|
sta_info_free(local, new_sta);
|
||||||
|
return -EINVAL;
|
||||||
|
} else if (!basic_rates) {
|
||||||
sdata_info(sdata,
|
sdata_info(sdata,
|
||||||
"No basic rates, using min rate instead\n");
|
"No basic rates, using min rate instead\n");
|
||||||
basic_rates = BIT(min_rate_index);
|
basic_rates = BIT(min_rate_index);
|
||||||
|
@@ -557,6 +557,10 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
|
|||||||
|
|
||||||
lockdep_assert_held(&local->mtx);
|
lockdep_assert_held(&local->mtx);
|
||||||
|
|
||||||
|
if (channel->freq_offset)
|
||||||
|
/* this may work, but is untested */
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (local->use_chanctx && !local->ops->remain_on_channel)
|
if (local->use_chanctx && !local->ops->remain_on_channel)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2013 Felix Fietkau <nbd@openwrt.org>
|
* Copyright (C) 2010-2013 Felix Fietkau <nbd@openwrt.org>
|
||||||
|
* Copyright (C) 2019-2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
@@ -490,7 +491,7 @@ minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi,
|
|||||||
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
|
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
|
||||||
tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
|
tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
|
||||||
|
|
||||||
if (tmp_cck_tp_rate && tmp_cck_tp > tmp_mcs_tp) {
|
if (tmp_cck_tp > tmp_mcs_tp) {
|
||||||
for(i = 0; i < MAX_THR_RATES; i++) {
|
for(i = 0; i < MAX_THR_RATES; i++) {
|
||||||
minstrel_ht_sort_best_tp_rates(mi, tmp_cck_tp_rate[i],
|
minstrel_ht_sort_best_tp_rates(mi, tmp_cck_tp_rate[i],
|
||||||
tmp_mcs_tp_rate);
|
tmp_mcs_tp_rate);
|
||||||
|
@@ -412,6 +412,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||||||
pos++;
|
pos++;
|
||||||
|
|
||||||
/* IEEE80211_RADIOTAP_CHANNEL */
|
/* IEEE80211_RADIOTAP_CHANNEL */
|
||||||
|
/* TODO: frequency offset in KHz */
|
||||||
put_unaligned_le16(status->freq, pos);
|
put_unaligned_le16(status->freq, pos);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
if (status->bw == RATE_INFO_BW_10)
|
if (status->bw == RATE_INFO_BW_10)
|
||||||
@@ -1984,8 +1985,12 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
|||||||
|
|
||||||
if (mmie_keyidx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS ||
|
if (mmie_keyidx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS ||
|
||||||
mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
|
mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
|
||||||
NUM_DEFAULT_BEACON_KEYS)
|
NUM_DEFAULT_BEACON_KEYS) {
|
||||||
|
cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
|
||||||
|
skb->data,
|
||||||
|
skb->len);
|
||||||
return RX_DROP_MONITOR; /* unexpected BIP keyidx */
|
return RX_DROP_MONITOR; /* unexpected BIP keyidx */
|
||||||
|
}
|
||||||
|
|
||||||
rx->key = ieee80211_rx_get_bigtk(rx, mmie_keyidx);
|
rx->key = ieee80211_rx_get_bigtk(rx, mmie_keyidx);
|
||||||
if (!rx->key)
|
if (!rx->key)
|
||||||
@@ -2131,6 +2136,10 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
|||||||
/* either the frame has been decrypted or will be dropped */
|
/* either the frame has been decrypted or will be dropped */
|
||||||
status->flag |= RX_FLAG_DECRYPTED;
|
status->flag |= RX_FLAG_DECRYPTED;
|
||||||
|
|
||||||
|
if (unlikely(ieee80211_is_beacon(fc) && result == RX_DROP_UNUSABLE))
|
||||||
|
cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
|
||||||
|
skb->data, skb->len);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2411,8 +2420,12 @@ static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
|
|||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
if (unlikely(ieee80211_is_beacon(fc) && rx->key &&
|
if (unlikely(ieee80211_is_beacon(fc) && rx->key &&
|
||||||
ieee80211_get_mmie_keyidx(rx->skb) < 0))
|
ieee80211_get_mmie_keyidx(rx->skb) < 0)) {
|
||||||
|
cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
|
||||||
|
rx->skb->data,
|
||||||
|
rx->skb->len);
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* When using MFP, Action frames are not allowed prior to
|
* When using MFP, Action frames are not allowed prior to
|
||||||
* having configured keys.
|
* having configured keys.
|
||||||
|
@@ -275,7 +275,8 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
|
channel = ieee80211_get_channel_khz(local->hw.wiphy,
|
||||||
|
ieee80211_rx_status_to_khz(rx_status));
|
||||||
|
|
||||||
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
|
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
|
||||||
return;
|
return;
|
||||||
@@ -896,6 +897,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
|
|||||||
|
|
||||||
local->scan_chandef.chan = chan;
|
local->scan_chandef.chan = chan;
|
||||||
local->scan_chandef.center_freq1 = chan->center_freq;
|
local->scan_chandef.center_freq1 = chan->center_freq;
|
||||||
|
local->scan_chandef.freq1_offset = chan->freq_offset;
|
||||||
local->scan_chandef.center_freq2 = 0;
|
local->scan_chandef.center_freq2 = 0;
|
||||||
switch (scan_req->scan_width) {
|
switch (scan_req->scan_width) {
|
||||||
case NL80211_BSS_CHAN_WIDTH_5:
|
case NL80211_BSS_CHAN_WIDTH_5:
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
* Copyright 2002-2005, Devicescape Software, Inc.
|
* Copyright 2002-2005, Devicescape Software, Inc.
|
||||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||||
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
||||||
|
* Copyright(c) 2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STA_INFO_H
|
#ifndef STA_INFO_H
|
||||||
@@ -68,6 +69,8 @@
|
|||||||
* @WLAN_STA_MPSP_RECIPIENT: local STA is recipient of a MPSP.
|
* @WLAN_STA_MPSP_RECIPIENT: local STA is recipient of a MPSP.
|
||||||
* @WLAN_STA_PS_DELIVER: station woke up, but we're still blocking TX
|
* @WLAN_STA_PS_DELIVER: station woke up, but we're still blocking TX
|
||||||
* until pending frames are delivered
|
* until pending frames are delivered
|
||||||
|
* @WLAN_STA_USES_ENCRYPTION: This station was configured for encryption,
|
||||||
|
* so drop all packets without a key later.
|
||||||
*
|
*
|
||||||
* @NUM_WLAN_STA_FLAGS: number of defined flags
|
* @NUM_WLAN_STA_FLAGS: number of defined flags
|
||||||
*/
|
*/
|
||||||
@@ -116,6 +119,7 @@ enum ieee80211_sta_info_flags {
|
|||||||
#define HT_AGG_STATE_WANT_STOP 5
|
#define HT_AGG_STATE_WANT_STOP 5
|
||||||
#define HT_AGG_STATE_START_CB 6
|
#define HT_AGG_STATE_START_CB 6
|
||||||
#define HT_AGG_STATE_STOP_CB 7
|
#define HT_AGG_STATE_STOP_CB 7
|
||||||
|
#define HT_AGG_STATE_SENT_ADDBA 8
|
||||||
|
|
||||||
DECLARE_EWMA(avg_signal, 10, 8)
|
DECLARE_EWMA(avg_signal, 10, 8)
|
||||||
enum ieee80211_agg_stop_reason {
|
enum ieee80211_agg_stop_reason {
|
||||||
|
@@ -226,12 +226,11 @@ static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata,
|
|||||||
static void
|
static void
|
||||||
ieee80211_tdls_add_aid(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
|
ieee80211_tdls_add_aid(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
||||||
u8 *pos = skb_put(skb, 4);
|
u8 *pos = skb_put(skb, 4);
|
||||||
|
|
||||||
*pos++ = WLAN_EID_AID;
|
*pos++ = WLAN_EID_AID;
|
||||||
*pos++ = 2; /* len */
|
*pos++ = 2; /* len */
|
||||||
put_unaligned_le16(ifmgd->aid, pos);
|
put_unaligned_le16(sdata->vif.bss_conf.aid, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* translate numbering in the WMM parameter IE to the mac80211 notation */
|
/* translate numbering in the WMM parameter IE to the mac80211 notation */
|
||||||
@@ -1567,6 +1566,10 @@ ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
u32 ch_sw_tm_ie;
|
u32 ch_sw_tm_ie;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (chandef->chan->freq_offset)
|
||||||
|
/* this may work, but is untested */
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
mutex_lock(&local->sta_mtx);
|
mutex_lock(&local->sta_mtx);
|
||||||
sta = sta_info_get(sdata, addr);
|
sta = sta_info_get(sdata, addr);
|
||||||
if (!sta) {
|
if (!sta) {
|
||||||
|
@@ -37,32 +37,42 @@
|
|||||||
#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
|
#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
|
||||||
|
|
||||||
#define CHANDEF_ENTRY __field(u32, control_freq) \
|
#define CHANDEF_ENTRY __field(u32, control_freq) \
|
||||||
|
__field(u32, freq_offset) \
|
||||||
__field(u32, chan_width) \
|
__field(u32, chan_width) \
|
||||||
__field(u32, center_freq1) \
|
__field(u32, center_freq1) \
|
||||||
|
__field(u32, freq1_offset) \
|
||||||
__field(u32, center_freq2)
|
__field(u32, center_freq2)
|
||||||
#define CHANDEF_ASSIGN(c) \
|
#define CHANDEF_ASSIGN(c) \
|
||||||
__entry->control_freq = (c) ? ((c)->chan ? (c)->chan->center_freq : 0) : 0; \
|
__entry->control_freq = (c) ? ((c)->chan ? (c)->chan->center_freq : 0) : 0; \
|
||||||
|
__entry->freq_offset = (c) ? ((c)->chan ? (c)->chan->freq_offset : 0) : 0; \
|
||||||
__entry->chan_width = (c) ? (c)->width : 0; \
|
__entry->chan_width = (c) ? (c)->width : 0; \
|
||||||
__entry->center_freq1 = (c) ? (c)->center_freq1 : 0; \
|
__entry->center_freq1 = (c) ? (c)->center_freq1 : 0; \
|
||||||
|
__entry->freq1_offset = (c) ? (c)->freq1_offset : 0; \
|
||||||
__entry->center_freq2 = (c) ? (c)->center_freq2 : 0;
|
__entry->center_freq2 = (c) ? (c)->center_freq2 : 0;
|
||||||
#define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz"
|
#define CHANDEF_PR_FMT " control:%d.%03d MHz width:%d center: %d.%03d/%d MHz"
|
||||||
#define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \
|
#define CHANDEF_PR_ARG __entry->control_freq, __entry->freq_offset, __entry->chan_width, \
|
||||||
__entry->center_freq1, __entry->center_freq2
|
__entry->center_freq1, __entry->freq1_offset, __entry->center_freq2
|
||||||
|
|
||||||
#define MIN_CHANDEF_ENTRY \
|
#define MIN_CHANDEF_ENTRY \
|
||||||
__field(u32, min_control_freq) \
|
__field(u32, min_control_freq) \
|
||||||
|
__field(u32, min_freq_offset) \
|
||||||
__field(u32, min_chan_width) \
|
__field(u32, min_chan_width) \
|
||||||
__field(u32, min_center_freq1) \
|
__field(u32, min_center_freq1) \
|
||||||
|
__field(u32, min_freq1_offset) \
|
||||||
__field(u32, min_center_freq2)
|
__field(u32, min_center_freq2)
|
||||||
|
|
||||||
#define MIN_CHANDEF_ASSIGN(c) \
|
#define MIN_CHANDEF_ASSIGN(c) \
|
||||||
__entry->min_control_freq = (c)->chan ? (c)->chan->center_freq : 0; \
|
__entry->min_control_freq = (c)->chan ? (c)->chan->center_freq : 0; \
|
||||||
|
__entry->min_freq_offset = (c)->chan ? (c)->chan->freq_offset : 0; \
|
||||||
__entry->min_chan_width = (c)->width; \
|
__entry->min_chan_width = (c)->width; \
|
||||||
__entry->min_center_freq1 = (c)->center_freq1; \
|
__entry->min_center_freq1 = (c)->center_freq1; \
|
||||||
|
__entry->freq1_offset = (c)->freq1_offset; \
|
||||||
__entry->min_center_freq2 = (c)->center_freq2;
|
__entry->min_center_freq2 = (c)->center_freq2;
|
||||||
#define MIN_CHANDEF_PR_FMT " min_control:%d MHz min_width:%d min_center: %d/%d MHz"
|
#define MIN_CHANDEF_PR_FMT " min_control:%d.%03d MHz min_width:%d min_center: %d.%03d/%d MHz"
|
||||||
#define MIN_CHANDEF_PR_ARG __entry->min_control_freq, __entry->min_chan_width, \
|
#define MIN_CHANDEF_PR_ARG __entry->min_control_freq, __entry->min_freq_offset, \
|
||||||
__entry->min_center_freq1, __entry->min_center_freq2
|
__entry->min_chan_width, \
|
||||||
|
__entry->min_center_freq1, __entry->min_freq1_offset, \
|
||||||
|
__entry->min_center_freq2
|
||||||
|
|
||||||
#define CHANCTX_ENTRY CHANDEF_ENTRY \
|
#define CHANCTX_ENTRY CHANDEF_ENTRY \
|
||||||
MIN_CHANDEF_ENTRY \
|
MIN_CHANDEF_ENTRY \
|
||||||
@@ -412,6 +422,7 @@ TRACE_EVENT(drv_bss_info_changed,
|
|||||||
__field(s32, cqm_rssi_hyst)
|
__field(s32, cqm_rssi_hyst)
|
||||||
__field(u32, channel_width)
|
__field(u32, channel_width)
|
||||||
__field(u32, channel_cfreq1)
|
__field(u32, channel_cfreq1)
|
||||||
|
__field(u32, channel_cfreq1_offset)
|
||||||
__dynamic_array(u32, arp_addr_list,
|
__dynamic_array(u32, arp_addr_list,
|
||||||
info->arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
|
info->arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
|
||||||
IEEE80211_BSS_ARP_ADDR_LIST_LEN :
|
IEEE80211_BSS_ARP_ADDR_LIST_LEN :
|
||||||
@@ -452,6 +463,7 @@ TRACE_EVENT(drv_bss_info_changed,
|
|||||||
__entry->cqm_rssi_hyst = info->cqm_rssi_hyst;
|
__entry->cqm_rssi_hyst = info->cqm_rssi_hyst;
|
||||||
__entry->channel_width = info->chandef.width;
|
__entry->channel_width = info->chandef.width;
|
||||||
__entry->channel_cfreq1 = info->chandef.center_freq1;
|
__entry->channel_cfreq1 = info->chandef.center_freq1;
|
||||||
|
__entry->channel_cfreq1_offset = info->chandef.freq1_offset;
|
||||||
__entry->arp_addr_cnt = info->arp_addr_cnt;
|
__entry->arp_addr_cnt = info->arp_addr_cnt;
|
||||||
memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list,
|
memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list,
|
||||||
sizeof(u32) * (info->arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
|
sizeof(u32) * (info->arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
|
||||||
@@ -1223,6 +1235,7 @@ TRACE_EVENT(drv_remain_on_channel,
|
|||||||
LOCAL_ENTRY
|
LOCAL_ENTRY
|
||||||
VIF_ENTRY
|
VIF_ENTRY
|
||||||
__field(int, center_freq)
|
__field(int, center_freq)
|
||||||
|
__field(int, freq_offset)
|
||||||
__field(unsigned int, duration)
|
__field(unsigned int, duration)
|
||||||
__field(u32, type)
|
__field(u32, type)
|
||||||
),
|
),
|
||||||
@@ -1231,14 +1244,16 @@ TRACE_EVENT(drv_remain_on_channel,
|
|||||||
LOCAL_ASSIGN;
|
LOCAL_ASSIGN;
|
||||||
VIF_ASSIGN;
|
VIF_ASSIGN;
|
||||||
__entry->center_freq = chan->center_freq;
|
__entry->center_freq = chan->center_freq;
|
||||||
|
__entry->freq_offset = chan->freq_offset;
|
||||||
__entry->duration = duration;
|
__entry->duration = duration;
|
||||||
__entry->type = type;
|
__entry->type = type;
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_printk(
|
TP_printk(
|
||||||
LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms type=%d",
|
LOCAL_PR_FMT VIF_PR_FMT " freq:%d.%03dMHz duration:%dms type=%d",
|
||||||
LOCAL_PR_ARG, VIF_PR_ARG,
|
LOCAL_PR_ARG, VIF_PR_ARG,
|
||||||
__entry->center_freq, __entry->duration, __entry->type
|
__entry->center_freq, __entry->freq_offset,
|
||||||
|
__entry->duration, __entry->type
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1546,8 +1561,10 @@ struct trace_vif_entry {
|
|||||||
|
|
||||||
struct trace_chandef_entry {
|
struct trace_chandef_entry {
|
||||||
u32 control_freq;
|
u32 control_freq;
|
||||||
|
u32 freq_offset;
|
||||||
u32 chan_width;
|
u32 chan_width;
|
||||||
u32 center_freq1;
|
u32 center_freq1;
|
||||||
|
u32 freq1_offset;
|
||||||
u32 center_freq2;
|
u32 center_freq2;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
@@ -1597,18 +1614,26 @@ TRACE_EVENT(drv_switch_vif_chanctx,
|
|||||||
sizeof(local_vifs[i].vif.vif_name));
|
sizeof(local_vifs[i].vif.vif_name));
|
||||||
SWITCH_ENTRY_ASSIGN(old_chandef.control_freq,
|
SWITCH_ENTRY_ASSIGN(old_chandef.control_freq,
|
||||||
old_ctx->def.chan->center_freq);
|
old_ctx->def.chan->center_freq);
|
||||||
|
SWITCH_ENTRY_ASSIGN(old_chandef.freq_offset,
|
||||||
|
old_ctx->def.chan->freq_offset);
|
||||||
SWITCH_ENTRY_ASSIGN(old_chandef.chan_width,
|
SWITCH_ENTRY_ASSIGN(old_chandef.chan_width,
|
||||||
old_ctx->def.width);
|
old_ctx->def.width);
|
||||||
SWITCH_ENTRY_ASSIGN(old_chandef.center_freq1,
|
SWITCH_ENTRY_ASSIGN(old_chandef.center_freq1,
|
||||||
old_ctx->def.center_freq1);
|
old_ctx->def.center_freq1);
|
||||||
|
SWITCH_ENTRY_ASSIGN(old_chandef.freq1_offset,
|
||||||
|
old_ctx->def.freq1_offset);
|
||||||
SWITCH_ENTRY_ASSIGN(old_chandef.center_freq2,
|
SWITCH_ENTRY_ASSIGN(old_chandef.center_freq2,
|
||||||
old_ctx->def.center_freq2);
|
old_ctx->def.center_freq2);
|
||||||
SWITCH_ENTRY_ASSIGN(new_chandef.control_freq,
|
SWITCH_ENTRY_ASSIGN(new_chandef.control_freq,
|
||||||
new_ctx->def.chan->center_freq);
|
new_ctx->def.chan->center_freq);
|
||||||
|
SWITCH_ENTRY_ASSIGN(new_chandef.freq_offset,
|
||||||
|
new_ctx->def.chan->freq_offset);
|
||||||
SWITCH_ENTRY_ASSIGN(new_chandef.chan_width,
|
SWITCH_ENTRY_ASSIGN(new_chandef.chan_width,
|
||||||
new_ctx->def.width);
|
new_ctx->def.width);
|
||||||
SWITCH_ENTRY_ASSIGN(new_chandef.center_freq1,
|
SWITCH_ENTRY_ASSIGN(new_chandef.center_freq1,
|
||||||
new_ctx->def.center_freq1);
|
new_ctx->def.center_freq1);
|
||||||
|
SWITCH_ENTRY_ASSIGN(new_chandef.freq1_offset,
|
||||||
|
new_ctx->def.freq1_offset);
|
||||||
SWITCH_ENTRY_ASSIGN(new_chandef.center_freq2,
|
SWITCH_ENTRY_ASSIGN(new_chandef.center_freq2,
|
||||||
new_ctx->def.center_freq2);
|
new_ctx->def.center_freq2);
|
||||||
}
|
}
|
||||||
|
@@ -4883,6 +4883,9 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|||||||
txrc.bss_conf = &sdata->vif.bss_conf;
|
txrc.bss_conf = &sdata->vif.bss_conf;
|
||||||
txrc.skb = skb;
|
txrc.skb = skb;
|
||||||
txrc.reported_rate.idx = -1;
|
txrc.reported_rate.idx = -1;
|
||||||
|
if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band])
|
||||||
|
txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band];
|
||||||
|
else
|
||||||
txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
|
txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
|
||||||
txrc.bss = true;
|
txrc.bss = true;
|
||||||
rate_control_get_rate(sdata, NULL, &txrc);
|
rate_control_get_rate(sdata, NULL, &txrc);
|
||||||
@@ -5006,7 +5009,7 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
|
|||||||
pspoll = skb_put_zero(skb, sizeof(*pspoll));
|
pspoll = skb_put_zero(skb, sizeof(*pspoll));
|
||||||
pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
|
pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
|
||||||
IEEE80211_STYPE_PSPOLL);
|
IEEE80211_STYPE_PSPOLL);
|
||||||
pspoll->aid = cpu_to_le16(ifmgd->aid);
|
pspoll->aid = cpu_to_le16(sdata->vif.bss_conf.aid);
|
||||||
|
|
||||||
/* aid in PS-Poll has its two MSBs each set to 1 */
|
/* aid in PS-Poll has its two MSBs each set to 1 */
|
||||||
pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
|
pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* Portions of this file
|
* Portions of this file
|
||||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 - 2019 Intel Corporation
|
* Copyright (C) 2018 - 2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/ieee80211.h>
|
#include <linux/ieee80211.h>
|
||||||
@@ -575,15 +575,21 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
|||||||
|
|
||||||
switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
|
switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
|
||||||
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ:
|
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ:
|
||||||
|
/* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
|
||||||
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20;
|
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20;
|
||||||
break;
|
break;
|
||||||
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ:
|
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ:
|
||||||
|
/* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
|
||||||
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_40;
|
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_40;
|
||||||
break;
|
break;
|
||||||
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ:
|
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ:
|
||||||
|
if (opmode & IEEE80211_OPMODE_NOTIF_BW_160_80P80)
|
||||||
|
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
|
||||||
|
else
|
||||||
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
|
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
|
||||||
break;
|
break;
|
||||||
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ:
|
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ:
|
||||||
|
/* legacy only, no longer used by newer spec */
|
||||||
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
|
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
chandef->chan = chan;
|
chandef->chan = chan;
|
||||||
|
chandef->freq1_offset = chan->freq_offset;
|
||||||
chandef->center_freq2 = 0;
|
chandef->center_freq2 = 0;
|
||||||
chandef->edmg.bw_config = 0;
|
chandef->edmg.bw_config = 0;
|
||||||
chandef->edmg.channels = 0;
|
chandef->edmg.channels = 0;
|
||||||
@@ -146,6 +147,9 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
|
|||||||
if (!chandef->chan)
|
if (!chandef->chan)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (chandef->freq1_offset >= 1000)
|
||||||
|
return false;
|
||||||
|
|
||||||
control_freq = chandef->chan->center_freq;
|
control_freq = chandef->chan->center_freq;
|
||||||
|
|
||||||
switch (chandef->width) {
|
switch (chandef->width) {
|
||||||
@@ -153,7 +157,8 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
|
|||||||
case NL80211_CHAN_WIDTH_10:
|
case NL80211_CHAN_WIDTH_10:
|
||||||
case NL80211_CHAN_WIDTH_20:
|
case NL80211_CHAN_WIDTH_20:
|
||||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||||
if (chandef->center_freq1 != control_freq)
|
if (ieee80211_chandef_to_khz(chandef) !=
|
||||||
|
ieee80211_channel_to_khz(chandef->chan))
|
||||||
return false;
|
return false;
|
||||||
if (chandef->center_freq2)
|
if (chandef->center_freq2)
|
||||||
return false;
|
return false;
|
||||||
@@ -386,10 +391,11 @@ static u32 cfg80211_get_start_freq(u32 center_freq,
|
|||||||
{
|
{
|
||||||
u32 start_freq;
|
u32 start_freq;
|
||||||
|
|
||||||
if (bandwidth <= 20)
|
bandwidth = MHZ_TO_KHZ(bandwidth);
|
||||||
|
if (bandwidth <= MHZ_TO_KHZ(20))
|
||||||
start_freq = center_freq;
|
start_freq = center_freq;
|
||||||
else
|
else
|
||||||
start_freq = center_freq - bandwidth/2 + 10;
|
start_freq = center_freq - bandwidth / 2 + MHZ_TO_KHZ(10);
|
||||||
|
|
||||||
return start_freq;
|
return start_freq;
|
||||||
}
|
}
|
||||||
@@ -399,10 +405,11 @@ static u32 cfg80211_get_end_freq(u32 center_freq,
|
|||||||
{
|
{
|
||||||
u32 end_freq;
|
u32 end_freq;
|
||||||
|
|
||||||
if (bandwidth <= 20)
|
bandwidth = MHZ_TO_KHZ(bandwidth);
|
||||||
|
if (bandwidth <= MHZ_TO_KHZ(20))
|
||||||
end_freq = center_freq;
|
end_freq = center_freq;
|
||||||
else
|
else
|
||||||
end_freq = center_freq + bandwidth/2 - 10;
|
end_freq = center_freq + bandwidth / 2 - MHZ_TO_KHZ(10);
|
||||||
|
|
||||||
return end_freq;
|
return end_freq;
|
||||||
}
|
}
|
||||||
@@ -417,8 +424,8 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
|
|||||||
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
||||||
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
||||||
|
|
||||||
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
|
||||||
c = ieee80211_get_channel(wiphy, freq);
|
c = ieee80211_get_channel_khz(wiphy, freq);
|
||||||
if (!c)
|
if (!c)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -449,7 +456,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = cfg80211_get_chans_dfs_required(wiphy,
|
ret = cfg80211_get_chans_dfs_required(wiphy,
|
||||||
chandef->center_freq1,
|
ieee80211_chandef_to_khz(chandef),
|
||||||
width);
|
width);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -460,7 +467,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = cfg80211_get_chans_dfs_required(wiphy,
|
ret = cfg80211_get_chans_dfs_required(wiphy,
|
||||||
chandef->center_freq2,
|
MHZ_TO_KHZ(chandef->center_freq2),
|
||||||
width);
|
width);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -503,8 +510,8 @@ static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy,
|
|||||||
* DFS_AVAILABLE). Return number of usable channels
|
* DFS_AVAILABLE). Return number of usable channels
|
||||||
* (require CAC). Allow DFS and non-DFS channel mix.
|
* (require CAC). Allow DFS and non-DFS channel mix.
|
||||||
*/
|
*/
|
||||||
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
|
||||||
c = ieee80211_get_channel(wiphy, freq);
|
c = ieee80211_get_channel_khz(wiphy, freq);
|
||||||
if (!c)
|
if (!c)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -536,7 +543,8 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
|
|||||||
if (width < 0)
|
if (width < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
r1 = cfg80211_get_chans_dfs_usable(wiphy, chandef->center_freq1,
|
r1 = cfg80211_get_chans_dfs_usable(wiphy,
|
||||||
|
MHZ_TO_KHZ(chandef->center_freq1),
|
||||||
width);
|
width);
|
||||||
|
|
||||||
if (r1 < 0)
|
if (r1 < 0)
|
||||||
@@ -546,7 +554,7 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
|
|||||||
case NL80211_CHAN_WIDTH_80P80:
|
case NL80211_CHAN_WIDTH_80P80:
|
||||||
WARN_ON(!chandef->center_freq2);
|
WARN_ON(!chandef->center_freq2);
|
||||||
r2 = cfg80211_get_chans_dfs_usable(wiphy,
|
r2 = cfg80211_get_chans_dfs_usable(wiphy,
|
||||||
chandef->center_freq2,
|
MHZ_TO_KHZ(chandef->center_freq2),
|
||||||
width);
|
width);
|
||||||
if (r2 < 0)
|
if (r2 < 0)
|
||||||
return false;
|
return false;
|
||||||
@@ -694,8 +702,8 @@ static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
|
|||||||
* If any channel in between is disabled or has not
|
* If any channel in between is disabled or has not
|
||||||
* had gone through CAC return false
|
* had gone through CAC return false
|
||||||
*/
|
*/
|
||||||
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
|
||||||
c = ieee80211_get_channel(wiphy, freq);
|
c = ieee80211_get_channel_khz(wiphy, freq);
|
||||||
if (!c)
|
if (!c)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -724,7 +732,8 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
|
|||||||
if (width < 0)
|
if (width < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
r = cfg80211_get_chans_dfs_available(wiphy, chandef->center_freq1,
|
r = cfg80211_get_chans_dfs_available(wiphy,
|
||||||
|
MHZ_TO_KHZ(chandef->center_freq1),
|
||||||
width);
|
width);
|
||||||
|
|
||||||
/* If any of channels unavailable for cf1 just return */
|
/* If any of channels unavailable for cf1 just return */
|
||||||
@@ -735,7 +744,7 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
|
|||||||
case NL80211_CHAN_WIDTH_80P80:
|
case NL80211_CHAN_WIDTH_80P80:
|
||||||
WARN_ON(!chandef->center_freq2);
|
WARN_ON(!chandef->center_freq2);
|
||||||
r = cfg80211_get_chans_dfs_available(wiphy,
|
r = cfg80211_get_chans_dfs_available(wiphy,
|
||||||
chandef->center_freq2,
|
MHZ_TO_KHZ(chandef->center_freq2),
|
||||||
width);
|
width);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -757,8 +766,8 @@ static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy,
|
|||||||
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
||||||
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
||||||
|
|
||||||
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
|
||||||
c = ieee80211_get_channel(wiphy, freq);
|
c = ieee80211_get_channel_khz(wiphy, freq);
|
||||||
if (!c)
|
if (!c)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -790,14 +799,14 @@ cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
t1 = cfg80211_get_chans_dfs_cac_time(wiphy,
|
t1 = cfg80211_get_chans_dfs_cac_time(wiphy,
|
||||||
chandef->center_freq1,
|
MHZ_TO_KHZ(chandef->center_freq1),
|
||||||
width);
|
width);
|
||||||
|
|
||||||
if (!chandef->center_freq2)
|
if (!chandef->center_freq2)
|
||||||
return t1;
|
return t1;
|
||||||
|
|
||||||
t2 = cfg80211_get_chans_dfs_cac_time(wiphy,
|
t2 = cfg80211_get_chans_dfs_cac_time(wiphy,
|
||||||
chandef->center_freq2,
|
MHZ_TO_KHZ(chandef->center_freq2),
|
||||||
width);
|
width);
|
||||||
|
|
||||||
return max(t1, t2);
|
return max(t1, t2);
|
||||||
@@ -813,8 +822,8 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
|||||||
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
||||||
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
||||||
|
|
||||||
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
|
||||||
c = ieee80211_get_channel(wiphy, freq);
|
c = ieee80211_get_channel_khz(wiphy, freq);
|
||||||
if (!c || c->flags & prohibited_flags)
|
if (!c || c->flags & prohibited_flags)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -976,13 +985,15 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
|
|||||||
prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
|
prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
|
||||||
|
|
||||||
|
|
||||||
if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1,
|
if (!cfg80211_secondary_chans_ok(wiphy,
|
||||||
|
ieee80211_chandef_to_khz(chandef),
|
||||||
width, prohibited_flags))
|
width, prohibited_flags))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!chandef->center_freq2)
|
if (!chandef->center_freq2)
|
||||||
return true;
|
return true;
|
||||||
return cfg80211_secondary_chans_ok(wiphy, chandef->center_freq2,
|
return cfg80211_secondary_chans_ok(wiphy,
|
||||||
|
MHZ_TO_KHZ(chandef->center_freq2),
|
||||||
width, prohibited_flags);
|
width, prohibited_flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_chandef_usable);
|
EXPORT_SYMBOL(cfg80211_chandef_usable);
|
||||||
|
@@ -480,9 +480,6 @@ use_default_name:
|
|||||||
INIT_LIST_HEAD(&rdev->bss_list);
|
INIT_LIST_HEAD(&rdev->bss_list);
|
||||||
INIT_LIST_HEAD(&rdev->sched_scan_req_list);
|
INIT_LIST_HEAD(&rdev->sched_scan_req_list);
|
||||||
INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
|
INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
|
||||||
INIT_LIST_HEAD(&rdev->mlme_unreg);
|
|
||||||
spin_lock_init(&rdev->mlme_unreg_lock);
|
|
||||||
INIT_WORK(&rdev->mlme_unreg_wk, cfg80211_mlme_unreg_wk);
|
|
||||||
INIT_DELAYED_WORK(&rdev->dfs_update_channels_wk,
|
INIT_DELAYED_WORK(&rdev->dfs_update_channels_wk,
|
||||||
cfg80211_dfs_channels_update_work);
|
cfg80211_dfs_channels_update_work);
|
||||||
#ifdef CONFIG_CFG80211_WEXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
@@ -837,6 +834,9 @@ int wiphy_register(struct wiphy *wiphy)
|
|||||||
sband->channels[i].orig_mpwr =
|
sband->channels[i].orig_mpwr =
|
||||||
sband->channels[i].max_power;
|
sband->channels[i].max_power;
|
||||||
sband->channels[i].band = band;
|
sband->channels[i].band = band;
|
||||||
|
|
||||||
|
if (WARN_ON(sband->channels[i].freq_offset >= 1000))
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < sband->n_iftype_data; i++) {
|
for (i = 0; i < sband->n_iftype_data; i++) {
|
||||||
@@ -1030,7 +1030,6 @@ void wiphy_unregister(struct wiphy *wiphy)
|
|||||||
cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
|
cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
|
||||||
flush_work(&rdev->destroy_work);
|
flush_work(&rdev->destroy_work);
|
||||||
flush_work(&rdev->sched_scan_stop_wk);
|
flush_work(&rdev->sched_scan_stop_wk);
|
||||||
flush_work(&rdev->mlme_unreg_wk);
|
|
||||||
flush_work(&rdev->propagate_radar_detect_wk);
|
flush_work(&rdev->propagate_radar_detect_wk);
|
||||||
flush_work(&rdev->propagate_cac_done_wk);
|
flush_work(&rdev->propagate_cac_done_wk);
|
||||||
|
|
||||||
@@ -1094,6 +1093,7 @@ static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync)
|
|||||||
rdev->devlist_generation++;
|
rdev->devlist_generation++;
|
||||||
|
|
||||||
cfg80211_mlme_purge_registrations(wdev);
|
cfg80211_mlme_purge_registrations(wdev);
|
||||||
|
flush_work(&wdev->mgmt_registrations_update_wk);
|
||||||
|
|
||||||
switch (wdev->iftype) {
|
switch (wdev->iftype) {
|
||||||
case NL80211_IFTYPE_P2P_DEVICE:
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
@@ -1238,6 +1238,8 @@ void cfg80211_init_wdev(struct cfg80211_registered_device *rdev,
|
|||||||
spin_lock_init(&wdev->event_lock);
|
spin_lock_init(&wdev->event_lock);
|
||||||
INIT_LIST_HEAD(&wdev->mgmt_registrations);
|
INIT_LIST_HEAD(&wdev->mgmt_registrations);
|
||||||
spin_lock_init(&wdev->mgmt_registrations_lock);
|
spin_lock_init(&wdev->mgmt_registrations_lock);
|
||||||
|
INIT_WORK(&wdev->mgmt_registrations_update_wk,
|
||||||
|
cfg80211_mgmt_registrations_update_wk);
|
||||||
INIT_LIST_HEAD(&wdev->pmsr_list);
|
INIT_LIST_HEAD(&wdev->pmsr_list);
|
||||||
spin_lock_init(&wdev->pmsr_lock);
|
spin_lock_init(&wdev->pmsr_lock);
|
||||||
INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);
|
INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);
|
||||||
|
@@ -60,10 +60,6 @@ struct cfg80211_registered_device {
|
|||||||
struct list_head beacon_registrations;
|
struct list_head beacon_registrations;
|
||||||
spinlock_t beacon_registrations_lock;
|
spinlock_t beacon_registrations_lock;
|
||||||
|
|
||||||
struct list_head mlme_unreg;
|
|
||||||
spinlock_t mlme_unreg_lock;
|
|
||||||
struct work_struct mlme_unreg_wk;
|
|
||||||
|
|
||||||
/* protected by RTNL only */
|
/* protected by RTNL only */
|
||||||
int num_running_ifaces;
|
int num_running_ifaces;
|
||||||
int num_running_monitor_ifaces;
|
int num_running_monitor_ifaces;
|
||||||
@@ -385,8 +381,9 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
|
|||||||
struct net_device *dev);
|
struct net_device *dev);
|
||||||
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
|
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
|
||||||
u16 frame_type, const u8 *match_data,
|
u16 frame_type, const u8 *match_data,
|
||||||
int match_len, struct netlink_ext_ack *extack);
|
int match_len, bool multicast_rx,
|
||||||
void cfg80211_mlme_unreg_wk(struct work_struct *wk);
|
struct netlink_ext_ack *extack);
|
||||||
|
void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk);
|
||||||
void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
|
void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
|
||||||
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
|
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
|
||||||
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
||||||
|
@@ -426,58 +426,62 @@ struct cfg80211_mgmt_registration {
|
|||||||
|
|
||||||
__le16 frame_type;
|
__le16 frame_type;
|
||||||
|
|
||||||
|
bool multicast_rx;
|
||||||
|
|
||||||
u8 match[];
|
u8 match[];
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void cfg80211_mgmt_registrations_update(struct wireless_dev *wdev)
|
||||||
cfg80211_process_mlme_unregistrations(struct cfg80211_registered_device *rdev)
|
|
||||||
{
|
{
|
||||||
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||||
|
struct wireless_dev *tmp;
|
||||||
struct cfg80211_mgmt_registration *reg;
|
struct cfg80211_mgmt_registration *reg;
|
||||||
|
struct mgmt_frame_regs upd = {};
|
||||||
|
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
|
||||||
spin_lock_bh(&rdev->mlme_unreg_lock);
|
rcu_read_lock();
|
||||||
while ((reg = list_first_entry_or_null(&rdev->mlme_unreg,
|
list_for_each_entry_rcu(tmp, &rdev->wiphy.wdev_list, list) {
|
||||||
struct cfg80211_mgmt_registration,
|
list_for_each_entry_rcu(reg, &tmp->mgmt_registrations, list) {
|
||||||
list))) {
|
u32 mask = BIT(le16_to_cpu(reg->frame_type) >> 4);
|
||||||
list_del(®->list);
|
u32 mcast_mask = 0;
|
||||||
spin_unlock_bh(&rdev->mlme_unreg_lock);
|
|
||||||
|
|
||||||
if (rdev->ops->mgmt_frame_register) {
|
if (reg->multicast_rx)
|
||||||
u16 frame_type = le16_to_cpu(reg->frame_type);
|
mcast_mask = mask;
|
||||||
|
|
||||||
rdev_mgmt_frame_register(rdev, reg->wdev,
|
upd.global_stypes |= mask;
|
||||||
frame_type, false);
|
upd.global_mcast_stypes |= mcast_mask;
|
||||||
|
|
||||||
|
if (tmp == wdev) {
|
||||||
|
upd.interface_stypes |= mask;
|
||||||
|
upd.interface_mcast_stypes |= mcast_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(reg);
|
|
||||||
|
|
||||||
spin_lock_bh(&rdev->mlme_unreg_lock);
|
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&rdev->mlme_unreg_lock);
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
rdev_update_mgmt_frame_registrations(rdev, wdev, &upd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cfg80211_mlme_unreg_wk(struct work_struct *wk)
|
void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev;
|
struct wireless_dev *wdev = container_of(wk, struct wireless_dev,
|
||||||
|
mgmt_registrations_update_wk);
|
||||||
rdev = container_of(wk, struct cfg80211_registered_device,
|
|
||||||
mlme_unreg_wk);
|
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
cfg80211_process_mlme_unregistrations(rdev);
|
cfg80211_mgmt_registrations_update(wdev);
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
||||||
u16 frame_type, const u8 *match_data,
|
u16 frame_type, const u8 *match_data,
|
||||||
int match_len, struct netlink_ext_ack *extack)
|
int match_len, bool multicast_rx,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
{
|
{
|
||||||
struct wiphy *wiphy = wdev->wiphy;
|
|
||||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
|
||||||
struct cfg80211_mgmt_registration *reg, *nreg;
|
struct cfg80211_mgmt_registration *reg, *nreg;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
u16 mgmt_type;
|
u16 mgmt_type;
|
||||||
|
bool update_multicast = false;
|
||||||
|
|
||||||
if (!wdev->wiphy->mgmt_stypes)
|
if (!wdev->wiphy->mgmt_stypes)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
@@ -528,34 +532,39 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (memcmp(reg->match, match_data, mlen) == 0) {
|
if (memcmp(reg->match, match_data, mlen) == 0) {
|
||||||
|
if (reg->multicast_rx != multicast_rx) {
|
||||||
|
update_multicast = true;
|
||||||
|
reg->multicast_rx = multicast_rx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
NL_SET_ERR_MSG(extack, "Match already configured");
|
NL_SET_ERR_MSG(extack, "Match already configured");
|
||||||
err = -EALREADY;
|
err = -EALREADY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err) {
|
if (err)
|
||||||
kfree(nreg);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
|
if (update_multicast) {
|
||||||
|
kfree(nreg);
|
||||||
|
} else {
|
||||||
memcpy(nreg->match, match_data, match_len);
|
memcpy(nreg->match, match_data, match_len);
|
||||||
nreg->match_len = match_len;
|
nreg->match_len = match_len;
|
||||||
nreg->nlportid = snd_portid;
|
nreg->nlportid = snd_portid;
|
||||||
nreg->frame_type = cpu_to_le16(frame_type);
|
nreg->frame_type = cpu_to_le16(frame_type);
|
||||||
nreg->wdev = wdev;
|
nreg->wdev = wdev;
|
||||||
|
nreg->multicast_rx = multicast_rx;
|
||||||
list_add(&nreg->list, &wdev->mgmt_registrations);
|
list_add(&nreg->list, &wdev->mgmt_registrations);
|
||||||
|
}
|
||||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||||
|
|
||||||
/* process all unregistrations to avoid driver confusion */
|
cfg80211_mgmt_registrations_update(wdev);
|
||||||
cfg80211_process_mlme_unregistrations(rdev);
|
|
||||||
|
|
||||||
if (rdev->ops->mgmt_frame_register)
|
|
||||||
rdev_mgmt_frame_register(rdev, wdev, frame_type, true);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
kfree(nreg);
|
||||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@@ -574,11 +583,9 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
list_del(®->list);
|
list_del(®->list);
|
||||||
spin_lock(&rdev->mlme_unreg_lock);
|
kfree(reg);
|
||||||
list_add_tail(®->list, &rdev->mlme_unreg);
|
|
||||||
spin_unlock(&rdev->mlme_unreg_lock);
|
|
||||||
|
|
||||||
schedule_work(&rdev->mlme_unreg_wk);
|
schedule_work(&wdev->mgmt_registrations_update_wk);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||||
@@ -594,15 +601,16 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
|
|||||||
|
|
||||||
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
|
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
struct cfg80211_mgmt_registration *reg, *tmp;
|
||||||
|
|
||||||
spin_lock_bh(&wdev->mgmt_registrations_lock);
|
spin_lock_bh(&wdev->mgmt_registrations_lock);
|
||||||
spin_lock(&rdev->mlme_unreg_lock);
|
list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
|
||||||
list_splice_tail_init(&wdev->mgmt_registrations, &rdev->mlme_unreg);
|
list_del(®->list);
|
||||||
spin_unlock(&rdev->mlme_unreg_lock);
|
kfree(reg);
|
||||||
|
}
|
||||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||||
|
|
||||||
cfg80211_process_mlme_unregistrations(rdev);
|
cfg80211_mgmt_registrations_update(wdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
||||||
|
@@ -635,6 +635,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
|||||||
[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
|
[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
|
||||||
[NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
|
[NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
|
||||||
[NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
|
[NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
|
||||||
|
[NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* policy for the key attributes */
|
/* policy for the key attributes */
|
||||||
@@ -3860,15 +3861,26 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
|
|||||||
};
|
};
|
||||||
void *hdr;
|
void *hdr;
|
||||||
struct sk_buff *msg;
|
struct sk_buff *msg;
|
||||||
|
bool bigtk_support = false;
|
||||||
|
|
||||||
|
if (wiphy_ext_feature_isset(&rdev->wiphy,
|
||||||
|
NL80211_EXT_FEATURE_BEACON_PROTECTION))
|
||||||
|
bigtk_support = true;
|
||||||
|
|
||||||
|
if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
|
||||||
|
dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
|
||||||
|
wiphy_ext_feature_isset(&rdev->wiphy,
|
||||||
|
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
|
||||||
|
bigtk_support = true;
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_KEY_IDX]) {
|
if (info->attrs[NL80211_ATTR_KEY_IDX]) {
|
||||||
key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
|
key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
|
||||||
if (key_idx > 5 &&
|
|
||||||
!wiphy_ext_feature_isset(
|
if (key_idx >= 6 && key_idx <= 7 && !bigtk_support) {
|
||||||
&rdev->wiphy,
|
GENL_SET_ERR_MSG(info, "BIGTK not supported");
|
||||||
NL80211_EXT_FEATURE_BEACON_PROTECTION))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_MAC])
|
if (info->attrs[NL80211_ATTR_MAC])
|
||||||
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||||
@@ -4679,6 +4691,8 @@ static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
|
|||||||
params->ht_required = true;
|
params->ht_required = true;
|
||||||
if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
|
if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
|
||||||
params->vht_required = true;
|
params->vht_required = true;
|
||||||
|
if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
|
||||||
|
params->he_required = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10726,9 +10740,18 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
|
|||||||
if (!rdev->ops->mgmt_tx)
|
if (!rdev->ops->mgmt_tx)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (info->attrs[NL80211_ATTR_RECEIVE_MULTICAST] &&
|
||||||
|
!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||||
|
NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) {
|
||||||
|
GENL_SET_ERR_MSG(info,
|
||||||
|
"multicast RX registrations are not supported");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
|
return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
|
||||||
nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
|
nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
|
||||||
nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
|
nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
|
||||||
|
info->attrs[NL80211_ATTR_RECEIVE_MULTICAST],
|
||||||
info->extack);
|
info->extack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15495,10 +15518,19 @@ void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
|
|||||||
if (WARN_ON(len < 2))
|
if (WARN_ON(len < 2))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ieee80211_is_deauth(mgmt->frame_control))
|
if (ieee80211_is_deauth(mgmt->frame_control)) {
|
||||||
cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
|
cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
|
||||||
else
|
} else if (ieee80211_is_disassoc(mgmt->frame_control)) {
|
||||||
cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
|
cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
|
||||||
|
} else if (ieee80211_is_beacon(mgmt->frame_control)) {
|
||||||
|
if (wdev->unprot_beacon_reported &&
|
||||||
|
elapsed_jiffies_msecs(wdev->unprot_beacon_reported) < 10000)
|
||||||
|
return;
|
||||||
|
cmd = NL80211_CMD_UNPROT_BEACON;
|
||||||
|
wdev->unprot_beacon_reported = jiffies;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
|
trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
|
||||||
nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
|
nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
|
||||||
|
@@ -819,13 +819,16 @@ rdev_set_cqm_txe_config(struct cfg80211_registered_device *rdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
rdev_mgmt_frame_register(struct cfg80211_registered_device *rdev,
|
rdev_update_mgmt_frame_registrations(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev, u16 frame_type, bool reg)
|
struct wireless_dev *wdev,
|
||||||
|
struct mgmt_frame_regs *upd)
|
||||||
{
|
{
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
|
||||||
trace_rdev_mgmt_frame_register(&rdev->wiphy, wdev , frame_type, reg);
|
trace_rdev_update_mgmt_frame_registrations(&rdev->wiphy, wdev, upd);
|
||||||
rdev->ops->mgmt_frame_register(&rdev->wiphy, wdev , frame_type, reg);
|
if (rdev->ops->update_mgmt_frame_registrations)
|
||||||
|
rdev->ops->update_mgmt_frame_registrations(&rdev->wiphy, wdev,
|
||||||
|
upd);
|
||||||
trace_rdev_return_void(&rdev->wiphy);
|
trace_rdev_return_void(&rdev->wiphy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1658,22 +1658,23 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
|
|||||||
const struct ieee80211_channel *chan)
|
const struct ieee80211_channel *chan)
|
||||||
{
|
{
|
||||||
const struct ieee80211_freq_range *freq_range = NULL;
|
const struct ieee80211_freq_range *freq_range = NULL;
|
||||||
u32 max_bandwidth_khz, bw_flags = 0;
|
u32 max_bandwidth_khz, center_freq_khz, bw_flags = 0;
|
||||||
|
|
||||||
freq_range = ®_rule->freq_range;
|
freq_range = ®_rule->freq_range;
|
||||||
|
|
||||||
max_bandwidth_khz = freq_range->max_bandwidth_khz;
|
max_bandwidth_khz = freq_range->max_bandwidth_khz;
|
||||||
|
center_freq_khz = ieee80211_channel_to_khz(chan);
|
||||||
/* Check if auto calculation requested */
|
/* Check if auto calculation requested */
|
||||||
if (reg_rule->flags & NL80211_RRF_AUTO_BW)
|
if (reg_rule->flags & NL80211_RRF_AUTO_BW)
|
||||||
max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
|
max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
|
||||||
|
|
||||||
/* If we get a reg_rule we can assume that at least 5Mhz fit */
|
/* If we get a reg_rule we can assume that at least 5Mhz fit */
|
||||||
if (!cfg80211_does_bw_fit_range(freq_range,
|
if (!cfg80211_does_bw_fit_range(freq_range,
|
||||||
MHZ_TO_KHZ(chan->center_freq),
|
center_freq_khz,
|
||||||
MHZ_TO_KHZ(10)))
|
MHZ_TO_KHZ(10)))
|
||||||
bw_flags |= IEEE80211_CHAN_NO_10MHZ;
|
bw_flags |= IEEE80211_CHAN_NO_10MHZ;
|
||||||
if (!cfg80211_does_bw_fit_range(freq_range,
|
if (!cfg80211_does_bw_fit_range(freq_range,
|
||||||
MHZ_TO_KHZ(chan->center_freq),
|
center_freq_khz,
|
||||||
MHZ_TO_KHZ(20)))
|
MHZ_TO_KHZ(20)))
|
||||||
bw_flags |= IEEE80211_CHAN_NO_20MHZ;
|
bw_flags |= IEEE80211_CHAN_NO_20MHZ;
|
||||||
|
|
||||||
@@ -1710,7 +1711,7 @@ static void handle_channel(struct wiphy *wiphy,
|
|||||||
|
|
||||||
flags = chan->orig_flags;
|
flags = chan->orig_flags;
|
||||||
|
|
||||||
reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
|
reg_rule = freq_reg_info(wiphy, ieee80211_channel_to_khz(chan));
|
||||||
if (IS_ERR(reg_rule)) {
|
if (IS_ERR(reg_rule)) {
|
||||||
/*
|
/*
|
||||||
* We will disable all channels that do not match our
|
* We will disable all channels that do not match our
|
||||||
@@ -1729,13 +1730,13 @@ static void handle_channel(struct wiphy *wiphy,
|
|||||||
if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
|
if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
|
||||||
request_wiphy && request_wiphy == wiphy &&
|
request_wiphy && request_wiphy == wiphy &&
|
||||||
request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
|
request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
|
||||||
pr_debug("Disabling freq %d MHz for good\n",
|
pr_debug("Disabling freq %d.%03d MHz for good\n",
|
||||||
chan->center_freq);
|
chan->center_freq, chan->freq_offset);
|
||||||
chan->orig_flags |= IEEE80211_CHAN_DISABLED;
|
chan->orig_flags |= IEEE80211_CHAN_DISABLED;
|
||||||
chan->flags = chan->orig_flags;
|
chan->flags = chan->orig_flags;
|
||||||
} else {
|
} else {
|
||||||
pr_debug("Disabling freq %d MHz\n",
|
pr_debug("Disabling freq %d.%03d MHz\n",
|
||||||
chan->center_freq);
|
chan->center_freq, chan->freq_offset);
|
||||||
chan->flags |= IEEE80211_CHAN_DISABLED;
|
chan->flags |= IEEE80211_CHAN_DISABLED;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -1936,7 +1937,7 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx,
|
|||||||
sband = wiphy->bands[reg_beacon->chan.band];
|
sband = wiphy->bands[reg_beacon->chan.band];
|
||||||
chan = &sband->channels[chan_idx];
|
chan = &sband->channels[chan_idx];
|
||||||
|
|
||||||
if (likely(chan->center_freq != reg_beacon->chan.center_freq))
|
if (likely(!ieee80211_channel_equal(chan, ®_beacon->chan)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (chan->beacon_found)
|
if (chan->beacon_found)
|
||||||
@@ -2269,18 +2270,18 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
|||||||
u32 bw_flags = 0;
|
u32 bw_flags = 0;
|
||||||
const struct ieee80211_reg_rule *reg_rule = NULL;
|
const struct ieee80211_reg_rule *reg_rule = NULL;
|
||||||
const struct ieee80211_power_rule *power_rule = NULL;
|
const struct ieee80211_power_rule *power_rule = NULL;
|
||||||
u32 bw;
|
u32 bw, center_freq_khz;
|
||||||
|
|
||||||
|
center_freq_khz = ieee80211_channel_to_khz(chan);
|
||||||
for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
|
for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
|
||||||
reg_rule = freq_reg_info_regd(MHZ_TO_KHZ(chan->center_freq),
|
reg_rule = freq_reg_info_regd(center_freq_khz, regd, bw);
|
||||||
regd, bw);
|
|
||||||
if (!IS_ERR(reg_rule))
|
if (!IS_ERR(reg_rule))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_ERR_OR_NULL(reg_rule)) {
|
if (IS_ERR_OR_NULL(reg_rule)) {
|
||||||
pr_debug("Disabling freq %d MHz as custom regd has no rule that fits it\n",
|
pr_debug("Disabling freq %d.%03d MHz as custom regd has no rule that fits it\n",
|
||||||
chan->center_freq);
|
chan->center_freq, chan->freq_offset);
|
||||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) {
|
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) {
|
||||||
chan->flags |= IEEE80211_CHAN_DISABLED;
|
chan->flags |= IEEE80211_CHAN_DISABLED;
|
||||||
} else {
|
} else {
|
||||||
@@ -3337,8 +3338,8 @@ static bool pending_reg_beacon(struct ieee80211_channel *beacon_chan)
|
|||||||
struct reg_beacon *pending_beacon;
|
struct reg_beacon *pending_beacon;
|
||||||
|
|
||||||
list_for_each_entry(pending_beacon, ®_pending_beacons, list)
|
list_for_each_entry(pending_beacon, ®_pending_beacons, list)
|
||||||
if (beacon_chan->center_freq ==
|
if (ieee80211_channel_equal(beacon_chan,
|
||||||
pending_beacon->chan.center_freq)
|
&pending_beacon->chan))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -3367,9 +3368,10 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
|
|||||||
if (!reg_beacon)
|
if (!reg_beacon)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
pr_debug("Found new beacon on frequency: %d MHz (Ch %d) on %s\n",
|
pr_debug("Found new beacon on frequency: %d.%03d MHz (Ch %d) on %s\n",
|
||||||
beacon_chan->center_freq,
|
beacon_chan->center_freq, beacon_chan->freq_offset,
|
||||||
ieee80211_frequency_to_channel(beacon_chan->center_freq),
|
ieee80211_freq_khz_to_channel(
|
||||||
|
ieee80211_channel_to_khz(beacon_chan)),
|
||||||
wiphy_name(wiphy));
|
wiphy_name(wiphy));
|
||||||
|
|
||||||
memcpy(®_beacon->chan, beacon_chan,
|
memcpy(®_beacon->chan, beacon_chan,
|
||||||
|
@@ -1322,8 +1322,8 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
|
|||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
freq = ieee80211_channel_to_frequency(channel_number, channel->band);
|
freq = ieee80211_channel_to_freq_khz(channel_number, channel->band);
|
||||||
alt_channel = ieee80211_get_channel(wiphy, freq);
|
alt_channel = ieee80211_get_channel_khz(wiphy, freq);
|
||||||
if (!alt_channel) {
|
if (!alt_channel) {
|
||||||
if (channel->band == NL80211_BAND_2GHZ) {
|
if (channel->band == NL80211_BAND_2GHZ) {
|
||||||
/*
|
/*
|
||||||
|
@@ -694,6 +694,7 @@ void __cfg80211_connect_result(struct net_device *dev,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wdev->unprot_beacon_reported = 0;
|
||||||
nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev, cr,
|
nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev, cr,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
||||||
@@ -921,6 +922,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev,
|
|||||||
cfg80211_hold_bss(bss_from_pub(info->bss));
|
cfg80211_hold_bss(bss_from_pub(info->bss));
|
||||||
wdev->current_bss = bss_from_pub(info->bss);
|
wdev->current_bss = bss_from_pub(info->bss);
|
||||||
|
|
||||||
|
wdev->unprot_beacon_reported = 0;
|
||||||
nl80211_send_roamed(wiphy_to_rdev(wdev->wiphy),
|
nl80211_send_roamed(wiphy_to_rdev(wdev->wiphy),
|
||||||
wdev->netdev, info, GFP_KERNEL);
|
wdev->netdev, info, GFP_KERNEL);
|
||||||
|
|
||||||
|
@@ -112,24 +112,29 @@
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define CHAN_ENTRY __field(enum nl80211_band, band) \
|
#define CHAN_ENTRY __field(enum nl80211_band, band) \
|
||||||
__field(u32, center_freq)
|
__field(u32, center_freq) \
|
||||||
|
__field(u16, freq_offset)
|
||||||
#define CHAN_ASSIGN(chan) \
|
#define CHAN_ASSIGN(chan) \
|
||||||
do { \
|
do { \
|
||||||
if (chan) { \
|
if (chan) { \
|
||||||
__entry->band = chan->band; \
|
__entry->band = chan->band; \
|
||||||
__entry->center_freq = chan->center_freq; \
|
__entry->center_freq = chan->center_freq; \
|
||||||
|
__entry->freq_offset = chan->freq_offset; \
|
||||||
} else { \
|
} else { \
|
||||||
__entry->band = 0; \
|
__entry->band = 0; \
|
||||||
__entry->center_freq = 0; \
|
__entry->center_freq = 0; \
|
||||||
|
__entry->freq_offset = 0; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define CHAN_PR_FMT "band: %d, freq: %u"
|
#define CHAN_PR_FMT "band: %d, freq: %u.%03u"
|
||||||
#define CHAN_PR_ARG __entry->band, __entry->center_freq
|
#define CHAN_PR_ARG __entry->band, __entry->center_freq, __entry->freq_offset
|
||||||
|
|
||||||
#define CHAN_DEF_ENTRY __field(enum nl80211_band, band) \
|
#define CHAN_DEF_ENTRY __field(enum nl80211_band, band) \
|
||||||
__field(u32, control_freq) \
|
__field(u32, control_freq) \
|
||||||
|
__field(u32, freq_offset) \
|
||||||
__field(u32, width) \
|
__field(u32, width) \
|
||||||
__field(u32, center_freq1) \
|
__field(u32, center_freq1) \
|
||||||
|
__field(u32, freq1_offset) \
|
||||||
__field(u32, center_freq2)
|
__field(u32, center_freq2)
|
||||||
#define CHAN_DEF_ASSIGN(chandef) \
|
#define CHAN_DEF_ASSIGN(chandef) \
|
||||||
do { \
|
do { \
|
||||||
@@ -137,21 +142,27 @@
|
|||||||
__entry->band = (chandef)->chan->band; \
|
__entry->band = (chandef)->chan->band; \
|
||||||
__entry->control_freq = \
|
__entry->control_freq = \
|
||||||
(chandef)->chan->center_freq; \
|
(chandef)->chan->center_freq; \
|
||||||
|
__entry->freq_offset = \
|
||||||
|
(chandef)->chan->freq_offset; \
|
||||||
__entry->width = (chandef)->width; \
|
__entry->width = (chandef)->width; \
|
||||||
__entry->center_freq1 = (chandef)->center_freq1;\
|
__entry->center_freq1 = (chandef)->center_freq1;\
|
||||||
|
__entry->freq1_offset = (chandef)->freq1_offset;\
|
||||||
__entry->center_freq2 = (chandef)->center_freq2;\
|
__entry->center_freq2 = (chandef)->center_freq2;\
|
||||||
} else { \
|
} else { \
|
||||||
__entry->band = 0; \
|
__entry->band = 0; \
|
||||||
__entry->control_freq = 0; \
|
__entry->control_freq = 0; \
|
||||||
|
__entry->freq_offset = 0; \
|
||||||
__entry->width = 0; \
|
__entry->width = 0; \
|
||||||
__entry->center_freq1 = 0; \
|
__entry->center_freq1 = 0; \
|
||||||
|
__entry->freq1_offset = 0; \
|
||||||
__entry->center_freq2 = 0; \
|
__entry->center_freq2 = 0; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define CHAN_DEF_PR_FMT \
|
#define CHAN_DEF_PR_FMT \
|
||||||
"band: %d, control freq: %u, width: %d, cf1: %u, cf2: %u"
|
"band: %d, control freq: %u.%03u, width: %d, cf1: %u.%03u, cf2: %u"
|
||||||
#define CHAN_DEF_PR_ARG __entry->band, __entry->control_freq, \
|
#define CHAN_DEF_PR_ARG __entry->band, __entry->control_freq, \
|
||||||
__entry->width, __entry->center_freq1, \
|
__entry->freq_offset, __entry->width, \
|
||||||
|
__entry->center_freq1, __entry->freq1_offset, \
|
||||||
__entry->center_freq2
|
__entry->center_freq2
|
||||||
|
|
||||||
#define SINFO_ENTRY __field(int, generation) \
|
#define SINFO_ENTRY __field(int, generation) \
|
||||||
@@ -1582,25 +1593,25 @@ TRACE_EVENT(rdev_set_bitrate_mask,
|
|||||||
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
|
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE_EVENT(rdev_mgmt_frame_register,
|
TRACE_EVENT(rdev_update_mgmt_frame_registrations,
|
||||||
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
|
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
u16 frame_type, bool reg),
|
struct mgmt_frame_regs *upd),
|
||||||
TP_ARGS(wiphy, wdev, frame_type, reg),
|
TP_ARGS(wiphy, wdev, upd),
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
WIPHY_ENTRY
|
WIPHY_ENTRY
|
||||||
WDEV_ENTRY
|
WDEV_ENTRY
|
||||||
__field(u16, frame_type)
|
__field(u16, global_stypes)
|
||||||
__field(bool, reg)
|
__field(u16, interface_stypes)
|
||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
WIPHY_ASSIGN;
|
WIPHY_ASSIGN;
|
||||||
WDEV_ASSIGN;
|
WDEV_ASSIGN;
|
||||||
__entry->frame_type = frame_type;
|
__entry->global_stypes = upd->global_stypes;
|
||||||
__entry->reg = reg;
|
__entry->interface_stypes = upd->interface_stypes;
|
||||||
),
|
),
|
||||||
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", frame_type: 0x%.2x, reg: %s ",
|
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", global: 0x%.2x, intf: 0x%.2x",
|
||||||
WIPHY_PR_ARG, WDEV_PR_ARG, __entry->frame_type,
|
WIPHY_PR_ARG, WDEV_PR_ARG,
|
||||||
__entry->reg ? "true" : "false")
|
__entry->global_stypes, __entry->interface_stypes)
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE_EVENT(rdev_return_int_tx_rx,
|
TRACE_EVENT(rdev_return_int_tx_rx,
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
|
* Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
|
||||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||||
* Copyright 2017 Intel Deutschland GmbH
|
* Copyright 2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018-2019 Intel Corporation
|
* Copyright (C) 2018-2020 Intel Corporation
|
||||||
*/
|
*/
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
@@ -72,7 +72,7 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_mandatory_rates);
|
EXPORT_SYMBOL(ieee80211_mandatory_rates);
|
||||||
|
|
||||||
int ieee80211_channel_to_frequency(int chan, enum nl80211_band band)
|
u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
|
||||||
{
|
{
|
||||||
/* see 802.11 17.3.8.3.2 and Annex J
|
/* see 802.11 17.3.8.3.2 and Annex J
|
||||||
* there are overlapping channel numbers in 5GHz and 2GHz bands */
|
* there are overlapping channel numbers in 5GHz and 2GHz bands */
|
||||||
@@ -81,15 +81,15 @@ int ieee80211_channel_to_frequency(int chan, enum nl80211_band band)
|
|||||||
switch (band) {
|
switch (band) {
|
||||||
case NL80211_BAND_2GHZ:
|
case NL80211_BAND_2GHZ:
|
||||||
if (chan == 14)
|
if (chan == 14)
|
||||||
return 2484;
|
return MHZ_TO_KHZ(2484);
|
||||||
else if (chan < 14)
|
else if (chan < 14)
|
||||||
return 2407 + chan * 5;
|
return MHZ_TO_KHZ(2407 + chan * 5);
|
||||||
break;
|
break;
|
||||||
case NL80211_BAND_5GHZ:
|
case NL80211_BAND_5GHZ:
|
||||||
if (chan >= 182 && chan <= 196)
|
if (chan >= 182 && chan <= 196)
|
||||||
return 4000 + chan * 5;
|
return MHZ_TO_KHZ(4000 + chan * 5);
|
||||||
else
|
else
|
||||||
return 5000 + chan * 5;
|
return MHZ_TO_KHZ(5000 + chan * 5);
|
||||||
break;
|
break;
|
||||||
case NL80211_BAND_6GHZ:
|
case NL80211_BAND_6GHZ:
|
||||||
/* see 802.11ax D4.1 27.3.22.2 */
|
/* see 802.11ax D4.1 27.3.22.2 */
|
||||||
@@ -98,17 +98,20 @@ int ieee80211_channel_to_frequency(int chan, enum nl80211_band band)
|
|||||||
break;
|
break;
|
||||||
case NL80211_BAND_60GHZ:
|
case NL80211_BAND_60GHZ:
|
||||||
if (chan < 7)
|
if (chan < 7)
|
||||||
return 56160 + chan * 2160;
|
return MHZ_TO_KHZ(56160 + chan * 2160);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
return 0; /* not supported */
|
return 0; /* not supported */
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_channel_to_frequency);
|
EXPORT_SYMBOL(ieee80211_channel_to_freq_khz);
|
||||||
|
|
||||||
int ieee80211_frequency_to_channel(int freq)
|
int ieee80211_freq_khz_to_channel(u32 freq)
|
||||||
{
|
{
|
||||||
|
/* TODO: just handle MHz for now */
|
||||||
|
freq = KHZ_TO_MHZ(freq);
|
||||||
|
|
||||||
/* see 802.11 17.3.8.3.2 and Annex J */
|
/* see 802.11 17.3.8.3.2 and Annex J */
|
||||||
if (freq == 2484)
|
if (freq == 2484)
|
||||||
return 14;
|
return 14;
|
||||||
@@ -126,9 +129,10 @@ int ieee80211_frequency_to_channel(int freq)
|
|||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_frequency_to_channel);
|
EXPORT_SYMBOL(ieee80211_freq_khz_to_channel);
|
||||||
|
|
||||||
struct ieee80211_channel *ieee80211_get_channel(struct wiphy *wiphy, int freq)
|
struct ieee80211_channel *ieee80211_get_channel_khz(struct wiphy *wiphy,
|
||||||
|
u32 freq)
|
||||||
{
|
{
|
||||||
enum nl80211_band band;
|
enum nl80211_band band;
|
||||||
struct ieee80211_supported_band *sband;
|
struct ieee80211_supported_band *sband;
|
||||||
@@ -141,14 +145,16 @@ struct ieee80211_channel *ieee80211_get_channel(struct wiphy *wiphy, int freq)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < sband->n_channels; i++) {
|
for (i = 0; i < sband->n_channels; i++) {
|
||||||
if (sband->channels[i].center_freq == freq)
|
struct ieee80211_channel *chan = &sband->channels[i];
|
||||||
return &sband->channels[i];
|
|
||||||
|
if (ieee80211_channel_to_khz(chan) == freq)
|
||||||
|
return chan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_get_channel);
|
EXPORT_SYMBOL(ieee80211_get_channel_khz);
|
||||||
|
|
||||||
static void set_mandatory_flags_band(struct ieee80211_supported_band *sband)
|
static void set_mandatory_flags_band(struct ieee80211_supported_band *sband)
|
||||||
{
|
{
|
||||||
@@ -2030,10 +2036,10 @@ EXPORT_SYMBOL(cfg80211_send_layer2_update);
|
|||||||
|
|
||||||
int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
|
int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
|
||||||
enum ieee80211_vht_chanwidth bw,
|
enum ieee80211_vht_chanwidth bw,
|
||||||
int mcs, bool ext_nss_bw_capable)
|
int mcs, bool ext_nss_bw_capable,
|
||||||
|
unsigned int max_vht_nss)
|
||||||
{
|
{
|
||||||
u16 map = le16_to_cpu(cap->supp_mcs.rx_mcs_map);
|
u16 map = le16_to_cpu(cap->supp_mcs.rx_mcs_map);
|
||||||
int max_vht_nss = 0;
|
|
||||||
int ext_nss_bw;
|
int ext_nss_bw;
|
||||||
int supp_width;
|
int supp_width;
|
||||||
int i, mcs_encoding;
|
int i, mcs_encoding;
|
||||||
@@ -2041,7 +2047,7 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
|
|||||||
if (map == 0xffff)
|
if (map == 0xffff)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (WARN_ON(mcs > 9))
|
if (WARN_ON(mcs > 9 || max_vht_nss > 8))
|
||||||
return 0;
|
return 0;
|
||||||
if (mcs <= 7)
|
if (mcs <= 7)
|
||||||
mcs_encoding = 0;
|
mcs_encoding = 0;
|
||||||
@@ -2050,6 +2056,7 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
|
|||||||
else
|
else
|
||||||
mcs_encoding = 2;
|
mcs_encoding = 2;
|
||||||
|
|
||||||
|
if (!max_vht_nss) {
|
||||||
/* find max_vht_nss for the given MCS */
|
/* find max_vht_nss for the given MCS */
|
||||||
for (i = 7; i >= 0; i--) {
|
for (i = 7; i >= 0; i--) {
|
||||||
int supp = (map >> (2 * i)) & 3;
|
int supp = (map >> (2 * i)) & 3;
|
||||||
@@ -2062,6 +2069,7 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!(cap->supp_mcs.tx_mcs_map &
|
if (!(cap->supp_mcs.tx_mcs_map &
|
||||||
cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE)))
|
cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE)))
|
||||||
|
Reference in New Issue
Block a user