mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-03 12:24:45 +08:00
This time we have:
* some AP-side infrastructure for FILS discovery and unsolicited probe resonses * a major rework of the encapsulation/header conversion offload from Felix, to fit better with e.g. AP_VLAN interfaces * performance fix for VHT A-MPDU size, don't limit to HT * some initial patches for S1G (sub 1 GHz) support, more will come in this area * minor cleanups -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAl9oqc0ACgkQB8qZga/f l8TdMxAAnGTS7p6n//5RrdNmbT/UgMPBPhdHJTXZy7q1z3hDI5xrWRrx26fQeB31 exslnHd6q28bNGKscExcLRsP63SKn+P3PdUWJzbusya46OZnMgajNQYiQkL3ISfS MkF0Uyv7GmkkRn8nBg1ZbLMtzONxqn9uT6o3qyNODHwYgf/QjlEWstL7Q0fEy5UU gftBz4WOhMOsEQQu3XvLu2hMd6EI14ZWkChdwboYJ29GgJrCYnhO/0B4QpVJxBpp ROYQgF3c3Fis2tJpyZ0FNqG7T16MhjOD2+hyNAcX2+ZkkbSzn6B89jOd/qeowJOT FwYbJNQTUxBYH8+IYZeGVWRMyPuZdazrfccbTd9Lfrk3y/Hi+cuuneFFXykST6Zd EqRkumAOJY9b6HgcGTkfRFdY4SU4v3lcAOcAgg1fJVFvmLKcHfhD3xKyGz3Q1JLv v9x/9S+G69YWyxl09rMY9c78S6enxKmhJdV1wnv3zbALvqNTa2OpaZnCBx+hmkEy NoSowwYeb0PANk9PfA1N0+uQPVKu8SGT0FhxLj6NEAhCbbVBTqZ3z4TkdYByy/a0 L80zk1ziyC4uS24+TcILHyCzRHkdLdsD8lEeVTDZIusU6nXX9imZ+yWGwIkbi35Y v+6fUns/1UMJqBc3J/wtr9pamoIBJT3Qe0lHC4Uy7CxuO5S1UVM= =Bnsm -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-net-next-2020-09-21' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== This time we have: * some AP-side infrastructure for FILS discovery and unsolicited probe resonses * a major rework of the encapsulation/header conversion offload from Felix, to fit better with e.g. AP_VLAN interfaces * performance fix for VHT A-MPDU size, don't limit to HT * some initial patches for S1G (sub 1 GHz) support, more will come in this area * minor cleanups ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ae4dd9a8c2
@ -18,7 +18,7 @@ ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb)
|
||||
if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
|
||||
return HAL_TCL_ENCAP_TYPE_RAW;
|
||||
|
||||
if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
|
||||
return HAL_TCL_ENCAP_TYPE_ETHERNET;
|
||||
|
||||
return HAL_TCL_ENCAP_TYPE_NATIVE_WIFI;
|
||||
@ -98,7 +98,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
|
||||
return -ESHUTDOWN;
|
||||
|
||||
if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
|
||||
if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
||||
!ieee80211_is_data(hdr->frame_control))
|
||||
return -ENOTSUPP;
|
||||
|
||||
|
@ -3936,7 +3936,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
return -ENOSPC;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)) {
|
||||
if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
|
||||
if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
ieee80211_is_deauth(hdr->frame_control) ||
|
||||
ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
@ -4063,7 +4063,7 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
|
||||
bool is_prb_rsp;
|
||||
int ret;
|
||||
|
||||
if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
|
||||
if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
|
||||
skb_cb->flags |= ATH11K_SKB_HW_80211_ENCAP;
|
||||
} else if (ieee80211_is_mgmt(hdr->frame_control)) {
|
||||
is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
|
||||
@ -4349,6 +4349,37 @@ static int ath11k_set_he_mu_sounding_mode(struct ath11k *ar,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath11k *ar = hw->priv;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
||||
u32 param_id, param_value;
|
||||
int ret;
|
||||
|
||||
param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
|
||||
if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET ||
|
||||
(vif->type != NL80211_IFTYPE_STATION &&
|
||||
vif->type != NL80211_IFTYPE_AP))
|
||||
vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
|
||||
|
||||
if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
|
||||
param_value = ATH11K_HW_TXRX_ETHERNET;
|
||||
else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
|
||||
param_value = ATH11K_HW_TXRX_RAW;
|
||||
else
|
||||
param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
|
||||
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
param_id, param_value);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -4358,7 +4389,6 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct vdev_create_params vdev_param = {0};
|
||||
struct peer_create_params peer_param;
|
||||
u32 param_id, param_value;
|
||||
int hw_encap = 0;
|
||||
u16 nss;
|
||||
int i;
|
||||
int ret;
|
||||
@ -4452,32 +4482,7 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
list_add(&arvif->list, &ar->arvifs);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
|
||||
if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET)
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
case NL80211_IFTYPE_AP:
|
||||
hw_encap = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ieee80211_set_hw_80211_encap(vif, hw_encap))
|
||||
param_value = ATH11K_HW_TXRX_ETHERNET;
|
||||
else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
|
||||
param_value = ATH11K_HW_TXRX_RAW;
|
||||
else
|
||||
param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
|
||||
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
param_id, param_value);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
goto err_vdev_del;
|
||||
}
|
||||
ath11k_mac_op_update_vif_offload(hw, vif);
|
||||
|
||||
nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1;
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
@ -5840,6 +5845,7 @@ static const struct ieee80211_ops ath11k_ops = {
|
||||
.reconfig_complete = ath11k_mac_op_reconfig_complete,
|
||||
.add_interface = ath11k_mac_op_add_interface,
|
||||
.remove_interface = ath11k_mac_op_remove_interface,
|
||||
.update_vif_offload = ath11k_mac_op_update_vif_offload,
|
||||
.config = ath11k_mac_op_config,
|
||||
.bss_info_changed = ath11k_mac_op_bss_info_changed,
|
||||
.configure_filter = ath11k_mac_op_configure_filter,
|
||||
@ -6148,6 +6154,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
|
||||
ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD);
|
||||
if (ht_cap & WMI_HT_CAP_ENABLED) {
|
||||
ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION);
|
||||
ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);
|
||||
|
@ -2330,84 +2330,84 @@ ieee80211_he_spr_size(const u8 *he_spr_ie)
|
||||
}
|
||||
|
||||
/* S1G Capabilities Information field */
|
||||
#define S1G_CAPAB_B0_S1G_LONG BIT(0)
|
||||
#define S1G_CAPAB_B0_SGI_1MHZ BIT(1)
|
||||
#define S1G_CAPAB_B0_SGI_2MHZ BIT(2)
|
||||
#define S1G_CAPAB_B0_SGI_4MHZ BIT(3)
|
||||
#define S1G_CAPAB_B0_SGI_8MHZ BIT(4)
|
||||
#define S1G_CAPAB_B0_SGI_16MHZ BIT(5)
|
||||
#define S1G_CAPAB_B0_SUPP_CH_WIDTH_MASK (BIT(6) | BIT(7))
|
||||
#define S1G_CAPAB_B0_SUPP_CH_WIDTH_SHIFT 6
|
||||
#define S1G_CAP0_S1G_LONG BIT(0)
|
||||
#define S1G_CAP0_SGI_1MHZ BIT(1)
|
||||
#define S1G_CAP0_SGI_2MHZ BIT(2)
|
||||
#define S1G_CAP0_SGI_4MHZ BIT(3)
|
||||
#define S1G_CAP0_SGI_8MHZ BIT(4)
|
||||
#define S1G_CAP0_SGI_16MHZ BIT(5)
|
||||
#define S1G_CAP0_SUPP_CH_WIDTH GENMASK(7, 6)
|
||||
|
||||
#define S1G_CAPAB_B1_RX_LDPC BIT(0)
|
||||
#define S1G_CAPAB_B1_TX_STBC BIT(1)
|
||||
#define S1G_CAPAB_B1_RX_STBC BIT(2)
|
||||
#define S1G_CAPAB_B1_SU_BFER BIT(3)
|
||||
#define S1G_CAPAB_B1_SU_BFEE BIT(4)
|
||||
#define S1G_CAPAB_B1_BFEE_STS_MASK (BIT(5) | BIT(6) | BIT(7))
|
||||
#define S1G_CAPAB_B1_BFEE_STS_SHIFT 5
|
||||
#define S1G_SUPP_CH_WIDTH_2 0
|
||||
#define S1G_SUPP_CH_WIDTH_4 1
|
||||
#define S1G_SUPP_CH_WIDTH_8 2
|
||||
#define S1G_SUPP_CH_WIDTH_16 3
|
||||
#define S1G_SUPP_CH_WIDTH_MAX(cap) ((1 << FIELD_GET(S1G_CAP0_SUPP_CH_WIDTH, \
|
||||
cap[0])) << 1)
|
||||
|
||||
#define S1G_CAPAB_B2_SOUNDING_DIMENSIONS_MASK (BIT(0) | BIT(1) | BIT(2))
|
||||
#define S1G_CAPAB_B2_SOUNDING_DIMENSIONS_SHIFT 0
|
||||
#define S1G_CAPAB_B2_MU_BFER BIT(3)
|
||||
#define S1G_CAPAB_B2_MU_BFEE BIT(4)
|
||||
#define S1G_CAPAB_B2_PLUS_HTC_VHT BIT(5)
|
||||
#define S1G_CAPAB_B2_TRAVELING_PILOT_MASK (BIT(6) | BIT(7))
|
||||
#define S1G_CAPAB_B2_TRAVELING_PILOT_SHIFT 6
|
||||
#define S1G_CAP1_RX_LDPC BIT(0)
|
||||
#define S1G_CAP1_TX_STBC BIT(1)
|
||||
#define S1G_CAP1_RX_STBC BIT(2)
|
||||
#define S1G_CAP1_SU_BFER BIT(3)
|
||||
#define S1G_CAP1_SU_BFEE BIT(4)
|
||||
#define S1G_CAP1_BFEE_STS GENMASK(7, 5)
|
||||
|
||||
#define S1G_CAPAB_B3_RD_RESPONDER BIT(0)
|
||||
#define S1G_CAPAB_B3_HT_DELAYED_BA BIT(1)
|
||||
#define S1G_CAPAB_B3_MAX_MPDU_LEN BIT(2)
|
||||
#define S1G_CAPAB_B3_MAX_AMPDU_LEN_EXP_MASK (BIT(3) | BIT(4))
|
||||
#define S1G_CAPAB_B3_MAX_AMPDU_LEN_EXP_SHIFT 3
|
||||
#define S1G_CAPAB_B3_MIN_MPDU_START_MASK (BIT(5) | BIT(6) | BIT(7))
|
||||
#define S1G_CAPAB_B3_MIN_MPDU_START_SHIFT 5
|
||||
#define S1G_CAP2_SOUNDING_DIMENSIONS GENMASK(2, 0)
|
||||
#define S1G_CAP2_MU_BFER BIT(3)
|
||||
#define S1G_CAP2_MU_BFEE BIT(4)
|
||||
#define S1G_CAP2_PLUS_HTC_VHT BIT(5)
|
||||
#define S1G_CAP2_TRAVELING_PILOT GENMASK(7, 6)
|
||||
|
||||
#define S1G_CAPAB_B4_UPLINK_SYNC BIT(0)
|
||||
#define S1G_CAPAB_B4_DYNAMIC_AID BIT(1)
|
||||
#define S1G_CAPAB_B4_BAT BIT(2)
|
||||
#define S1G_CAPAB_B4_TIME_ADE BIT(3)
|
||||
#define S1G_CAPAB_B4_NON_TIM BIT(4)
|
||||
#define S1G_CAPAB_B4_GROUP_AID BIT(5)
|
||||
#define S1G_CAPAB_B4_STA_TYPE_MASK (BIT(6) | BIT(7))
|
||||
#define S1G_CAPAB_B4_STA_TYPE_SHIFT 6
|
||||
#define S1G_CAP3_RD_RESPONDER BIT(0)
|
||||
#define S1G_CAP3_HT_DELAYED_BA BIT(1)
|
||||
#define S1G_CAP3_MAX_MPDU_LEN BIT(2)
|
||||
#define S1G_CAP3_MAX_AMPDU_LEN_EXP GENMASK(4, 3)
|
||||
#define S1G_CAP3_MIN_MPDU_START GENMASK(7, 5)
|
||||
|
||||
#define S1G_CAPAB_B5_CENT_AUTH_CONTROL BIT(0)
|
||||
#define S1G_CAPAB_B5_DIST_AUTH_CONTROL BIT(1)
|
||||
#define S1G_CAPAB_B5_AMSDU BIT(2)
|
||||
#define S1G_CAPAB_B5_AMPDU BIT(3)
|
||||
#define S1G_CAPAB_B5_ASYMMETRIC_BA BIT(4)
|
||||
#define S1G_CAPAB_B5_FLOW_CONTROL BIT(5)
|
||||
#define S1G_CAPAB_B5_SECTORIZED_BEAM_MASK (BIT(6) | BIT(7))
|
||||
#define S1G_CAPAB_B5_SECTORIZED_BEAM_SHIFT 6
|
||||
#define S1G_CAP4_UPLINK_SYNC BIT(0)
|
||||
#define S1G_CAP4_DYNAMIC_AID BIT(1)
|
||||
#define S1G_CAP4_BAT BIT(2)
|
||||
#define S1G_CAP4_TIME_ADE BIT(3)
|
||||
#define S1G_CAP4_NON_TIM BIT(4)
|
||||
#define S1G_CAP4_GROUP_AID BIT(5)
|
||||
#define S1G_CAP4_STA_TYPE GENMASK(7, 6)
|
||||
|
||||
#define S1G_CAPAB_B6_OBSS_MITIGATION BIT(0)
|
||||
#define S1G_CAPAB_B6_FRAGMENT_BA BIT(1)
|
||||
#define S1G_CAPAB_B6_NDP_PS_POLL BIT(2)
|
||||
#define S1G_CAPAB_B6_RAW_OPERATION BIT(3)
|
||||
#define S1G_CAPAB_B6_PAGE_SLICING BIT(4)
|
||||
#define S1G_CAPAB_B6_TXOP_SHARING_IMP_ACK BIT(5)
|
||||
#define S1G_CAPAB_B6_VHT_LINK_ADAPT_MASK (BIT(6) | BIT(7))
|
||||
#define S1G_CAPAB_B6_VHT_LINK_ADAPT_SHIFT 6
|
||||
#define S1G_CAP5_CENT_AUTH_CONTROL BIT(0)
|
||||
#define S1G_CAP5_DIST_AUTH_CONTROL BIT(1)
|
||||
#define S1G_CAP5_AMSDU BIT(2)
|
||||
#define S1G_CAP5_AMPDU BIT(3)
|
||||
#define S1G_CAP5_ASYMMETRIC_BA BIT(4)
|
||||
#define S1G_CAP5_FLOW_CONTROL BIT(5)
|
||||
#define S1G_CAP5_SECTORIZED_BEAM GENMASK(7, 6)
|
||||
|
||||
#define S1G_CAPAB_B7_TACK_AS_PS_POLL BIT(0)
|
||||
#define S1G_CAPAB_B7_DUP_1MHZ BIT(1)
|
||||
#define S1G_CAPAB_B7_MCS_NEGOTIATION BIT(2)
|
||||
#define S1G_CAPAB_B7_1MHZ_CTL_RESPONSE_PREAMBLE BIT(3)
|
||||
#define S1G_CAPAB_B7_NDP_BFING_REPORT_POLL BIT(4)
|
||||
#define S1G_CAPAB_B7_UNSOLICITED_DYN_AID BIT(5)
|
||||
#define S1G_CAPAB_B7_SECTOR_TRAINING_OPERATION BIT(6)
|
||||
#define S1G_CAPAB_B7_TEMP_PS_MODE_SWITCH BIT(7)
|
||||
#define S1G_CAP6_OBSS_MITIGATION BIT(0)
|
||||
#define S1G_CAP6_FRAGMENT_BA BIT(1)
|
||||
#define S1G_CAP6_NDP_PS_POLL BIT(2)
|
||||
#define S1G_CAP6_RAW_OPERATION BIT(3)
|
||||
#define S1G_CAP6_PAGE_SLICING BIT(4)
|
||||
#define S1G_CAP6_TXOP_SHARING_IMP_ACK BIT(5)
|
||||
#define S1G_CAP6_VHT_LINK_ADAPT GENMASK(7, 6)
|
||||
|
||||
#define S1G_CAPAB_B8_TWT_GROUPING BIT(0)
|
||||
#define S1G_CAPAB_B8_BDT BIT(1)
|
||||
#define S1G_CAPAB_B8_COLOR_MASK (BIT(2) | BIT(3) | BIT(4))
|
||||
#define S1G_CAPAB_B8_COLOR_SHIFT 2
|
||||
#define S1G_CAPAB_B8_TWT_REQUEST BIT(5)
|
||||
#define S1G_CAPAB_B8_TWT_RESPOND BIT(6)
|
||||
#define S1G_CAPAB_B8_PV1_FRAME BIT(7)
|
||||
#define S1G_CAP7_TACK_AS_PS_POLL BIT(0)
|
||||
#define S1G_CAP7_DUP_1MHZ BIT(1)
|
||||
#define S1G_CAP7_MCS_NEGOTIATION BIT(2)
|
||||
#define S1G_CAP7_1MHZ_CTL_RESPONSE_PREAMBLE BIT(3)
|
||||
#define S1G_CAP7_NDP_BFING_REPORT_POLL BIT(4)
|
||||
#define S1G_CAP7_UNSOLICITED_DYN_AID BIT(5)
|
||||
#define S1G_CAP7_SECTOR_TRAINING_OPERATION BIT(6)
|
||||
#define S1G_CAP7_TEMP_PS_MODE_SWITCH BIT(7)
|
||||
|
||||
#define S1G_CAPAB_B9_LINK_ADAPT_PER_CONTROL_RESPONSE BIT(0)
|
||||
#define S1G_CAP8_TWT_GROUPING BIT(0)
|
||||
#define S1G_CAP8_BDT BIT(1)
|
||||
#define S1G_CAP8_COLOR GENMASK(4, 2)
|
||||
#define S1G_CAP8_TWT_REQUEST BIT(5)
|
||||
#define S1G_CAP8_TWT_RESPOND BIT(6)
|
||||
#define S1G_CAP8_PV1_FRAME BIT(7)
|
||||
|
||||
#define S1G_CAP9_LINK_ADAPT_PER_CONTROL_RESPONSE BIT(0)
|
||||
|
||||
#define S1G_OPER_CH_WIDTH_PRIMARY_1MHZ BIT(0)
|
||||
#define S1G_OPER_CH_WIDTH_OPER GENMASK(4, 1)
|
||||
|
||||
/* Authentication algorithms */
|
||||
#define WLAN_AUTH_OPEN 0
|
||||
|
@ -96,6 +96,16 @@ struct wiphy;
|
||||
* @IEEE80211_CHAN_NO_10MHZ: 10 MHz bandwidth is not permitted
|
||||
* on this channel.
|
||||
* @IEEE80211_CHAN_NO_HE: HE operation is not permitted on this channel.
|
||||
* @IEEE80211_CHAN_1MHZ: 1 MHz bandwidth is permitted
|
||||
* on this channel.
|
||||
* @IEEE80211_CHAN_2MHZ: 2 MHz bandwidth is permitted
|
||||
* on this channel.
|
||||
* @IEEE80211_CHAN_4MHZ: 4 MHz bandwidth is permitted
|
||||
* on this channel.
|
||||
* @IEEE80211_CHAN_8MHZ: 8 MHz bandwidth is permitted
|
||||
* on this channel.
|
||||
* @IEEE80211_CHAN_16MHZ: 16 MHz bandwidth is permitted
|
||||
* on this channel.
|
||||
*
|
||||
*/
|
||||
enum ieee80211_channel_flags {
|
||||
@ -113,6 +123,11 @@ enum ieee80211_channel_flags {
|
||||
IEEE80211_CHAN_NO_20MHZ = 1<<11,
|
||||
IEEE80211_CHAN_NO_10MHZ = 1<<12,
|
||||
IEEE80211_CHAN_NO_HE = 1<<13,
|
||||
IEEE80211_CHAN_1MHZ = 1<<14,
|
||||
IEEE80211_CHAN_2MHZ = 1<<15,
|
||||
IEEE80211_CHAN_4MHZ = 1<<16,
|
||||
IEEE80211_CHAN_8MHZ = 1<<17,
|
||||
IEEE80211_CHAN_16MHZ = 1<<18,
|
||||
};
|
||||
|
||||
#define IEEE80211_CHAN_NO_HT40 \
|
||||
@ -450,6 +465,7 @@ struct ieee80211_sta_s1g_cap {
|
||||
* @ht_cap: HT capabilities in this band
|
||||
* @vht_cap: VHT capabilities in this band
|
||||
* @edmg_cap: EDMG capabilities in this band
|
||||
* @s1g_cap: S1G capabilities in this band (S1B band only, of course)
|
||||
* @n_iftype_data: number of iftype data entries
|
||||
* @iftype_data: interface type data entries. Note that the bits in
|
||||
* @types_mask inside this structure cannot overlap (i.e. only
|
||||
@ -1067,6 +1083,39 @@ struct cfg80211_acl_data {
|
||||
struct mac_address mac_addrs[];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_fils_discovery - FILS discovery parameters from
|
||||
* IEEE Std 802.11ai-2016, Annex C.3 MIB detail.
|
||||
*
|
||||
* @min_interval: Minimum packet interval in TUs (0 - 10000)
|
||||
* @max_interval: Maximum packet interval in TUs (0 - 10000)
|
||||
* @tmpl_len: Template length
|
||||
* @tmpl: Template data for FILS discovery frame including the action
|
||||
* frame headers.
|
||||
*/
|
||||
struct cfg80211_fils_discovery {
|
||||
u32 min_interval;
|
||||
u32 max_interval;
|
||||
size_t tmpl_len;
|
||||
const u8 *tmpl;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_unsol_bcast_probe_resp - Unsolicited broadcast probe
|
||||
* response parameters in 6GHz.
|
||||
*
|
||||
* @interval: Packet interval in TUs. Maximum allowed is 20 TU, as mentioned
|
||||
* in IEEE P802.11ax/D6.0 26.17.2.3.2 - AP behavior for fast passive
|
||||
* scanning
|
||||
* @tmpl_len: Template length
|
||||
* @tmpl: Template data for probe response
|
||||
*/
|
||||
struct cfg80211_unsol_bcast_probe_resp {
|
||||
u32 interval;
|
||||
size_t tmpl_len;
|
||||
const u8 *tmpl;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cfg80211_ap_settings_flags - AP settings flags
|
||||
*
|
||||
@ -1114,6 +1163,8 @@ enum cfg80211_ap_settings_flags {
|
||||
* @he_obss_pd: OBSS Packet Detection settings
|
||||
* @he_bss_color: BSS Color settings
|
||||
* @he_oper: HE operation IE (or %NULL if HE isn't enabled)
|
||||
* @fils_discovery: FILS discovery transmission parameters
|
||||
* @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
|
||||
*/
|
||||
struct cfg80211_ap_settings {
|
||||
struct cfg80211_chan_def chandef;
|
||||
@ -1144,6 +1195,8 @@ struct cfg80211_ap_settings {
|
||||
u32 flags;
|
||||
struct ieee80211_he_obss_pd he_obss_pd;
|
||||
struct cfg80211_he_bss_color he_bss_color;
|
||||
struct cfg80211_fils_discovery fils_discovery;
|
||||
struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1787,6 +1840,7 @@ struct mpath_info {
|
||||
* (or NULL for no change)
|
||||
* @basic_rates_len: number of basic rates
|
||||
* @ap_isolate: do not forward packets between connected stations
|
||||
* (0 = no, 1 = yes, -1 = do not change)
|
||||
* @ht_opmode: HT Operation mode
|
||||
* (u16 = opmode, -1 = do not change)
|
||||
* @p2p_ctwindow: P2P CT Window (-1 = no change)
|
||||
@ -5278,6 +5332,16 @@ ieee80211_channel_to_khz(const struct ieee80211_channel *chan)
|
||||
return MHZ_TO_KHZ(chan->center_freq) + chan->freq_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee80211_s1g_channel_width - get allowed channel width from @chan
|
||||
*
|
||||
* Only allowed for band NL80211_BAND_S1GHZ
|
||||
* @chan: channel
|
||||
* Return: The allowed channel width for this center_freq
|
||||
*/
|
||||
enum nl80211_chan_width
|
||||
ieee80211_s1g_channel_width(const struct ieee80211_channel *chan);
|
||||
|
||||
/**
|
||||
* ieee80211_channel_to_freq_khz - convert channel number to frequency
|
||||
* @chan: channel number
|
||||
|
@ -317,6 +317,9 @@ struct ieee80211_vif_chanctx_switch {
|
||||
* @BSS_CHANGED_TWT: TWT status changed
|
||||
* @BSS_CHANGED_HE_OBSS_PD: OBSS Packet Detection status changed.
|
||||
* @BSS_CHANGED_HE_BSS_COLOR: BSS Color has changed
|
||||
* @BSS_CHANGED_FILS_DISCOVERY: FILS discovery status changed.
|
||||
* @BSS_CHANGED_UNSOL_BCAST_PROBE_RESP: Unsolicited broadcast probe response
|
||||
* status changed.
|
||||
*
|
||||
*/
|
||||
enum ieee80211_bss_change {
|
||||
@ -350,6 +353,8 @@ enum ieee80211_bss_change {
|
||||
BSS_CHANGED_TWT = 1<<27,
|
||||
BSS_CHANGED_HE_OBSS_PD = 1<<28,
|
||||
BSS_CHANGED_HE_BSS_COLOR = 1<<29,
|
||||
BSS_CHANGED_FILS_DISCOVERY = 1<<30,
|
||||
BSS_CHANGED_UNSOL_BCAST_PROBE_RESP = 1<<31,
|
||||
|
||||
/* when adding here, make sure to change ieee80211_reconfig */
|
||||
};
|
||||
@ -490,6 +495,18 @@ struct ieee80211_ftm_responder_params {
|
||||
size_t civicloc_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ieee80211_fils_discovery - FILS discovery parameters from
|
||||
* IEEE Std 802.11ai-2016, Annex C.3 MIB detail.
|
||||
*
|
||||
* @min_interval: Minimum packet interval in TUs (0 - 10000)
|
||||
* @max_interval: Maximum packet interval in TUs (0 - 10000)
|
||||
*/
|
||||
struct ieee80211_fils_discovery {
|
||||
u32 min_interval;
|
||||
u32 max_interval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ieee80211_bss_conf - holds the BSS's changing parameters
|
||||
*
|
||||
@ -607,6 +624,9 @@ struct ieee80211_ftm_responder_params {
|
||||
* @he_oper: HE operation information of the AP we are connected to
|
||||
* @he_obss_pd: OBSS Packet Detection parameters.
|
||||
* @he_bss_color: BSS coloring settings, if BSS supports HE
|
||||
* @fils_discovery: FILS discovery configuration
|
||||
* @unsol_bcast_probe_resp_interval: Unsolicited broadcast probe response
|
||||
* interval.
|
||||
*/
|
||||
struct ieee80211_bss_conf {
|
||||
const u8 *bssid;
|
||||
@ -674,6 +694,8 @@ struct ieee80211_bss_conf {
|
||||
} he_oper;
|
||||
struct ieee80211_he_obss_pd he_obss_pd;
|
||||
struct cfg80211_he_bss_color he_bss_color;
|
||||
struct ieee80211_fils_discovery fils_discovery;
|
||||
u32 unsol_bcast_probe_resp_interval;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -720,9 +742,8 @@ struct ieee80211_bss_conf {
|
||||
* @IEEE80211_TX_INTFL_OFFCHAN_TX_OK: Internal to mac80211. Used to indicate
|
||||
* that a frame can be transmitted while the queues are stopped for
|
||||
* off-channel operation.
|
||||
* @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211,
|
||||
* used to indicate that a pending frame requires TX processing before
|
||||
* it can be sent out.
|
||||
* @IEEE80211_TX_CTL_HW_80211_ENCAP: This frame uses hardware encapsulation
|
||||
* (header conversion)
|
||||
* @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211,
|
||||
* used to indicate that a frame was already retried due to PS
|
||||
* @IEEE80211_TX_INTFL_DONT_ENCRYPT: completely internal to mac80211,
|
||||
@ -791,7 +812,7 @@ enum mac80211_tx_info_flags {
|
||||
IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11),
|
||||
IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12),
|
||||
IEEE80211_TX_INTFL_OFFCHAN_TX_OK = BIT(13),
|
||||
IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14),
|
||||
IEEE80211_TX_CTL_HW_80211_ENCAP = BIT(14),
|
||||
IEEE80211_TX_INTFL_RETRIED = BIT(15),
|
||||
IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16),
|
||||
IEEE80211_TX_CTL_NO_PS_BUFFER = BIT(17),
|
||||
@ -823,8 +844,9 @@ enum mac80211_tx_info_flags {
|
||||
* @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_SKIP_MPATH_LOOKUP: This frame skips mesh path lookup
|
||||
* @IEEE80211_TX_CTRL_HW_80211_ENCAP: This frame uses hardware encapsulation
|
||||
* (header conversion)
|
||||
* @IEEE80211_TX_INTCFL_NEED_TXPROCESSING: completely internal to mac80211,
|
||||
* used to indicate that a pending frame requires TX processing before
|
||||
* it can be sent out.
|
||||
* @IEEE80211_TX_CTRL_NO_SEQNO: Do not overwrite the sequence number that
|
||||
* has already been assigned to this frame.
|
||||
*
|
||||
@ -837,7 +859,7 @@ enum mac80211_tx_control_flags {
|
||||
IEEE80211_TX_CTRL_AMSDU = BIT(3),
|
||||
IEEE80211_TX_CTRL_FAST_XMIT = BIT(4),
|
||||
IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP = BIT(5),
|
||||
IEEE80211_TX_CTRL_HW_80211_ENCAP = BIT(6),
|
||||
IEEE80211_TX_INTCFL_NEED_TXPROCESSING = BIT(6),
|
||||
IEEE80211_TX_CTRL_NO_SEQNO = BIT(7),
|
||||
};
|
||||
|
||||
@ -1002,7 +1024,8 @@ ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate)
|
||||
* @status.ampdu_ack_len: AMPDU ack length
|
||||
* @status.ampdu_len: AMPDU length
|
||||
* @status.antenna: (legacy, kept only for iwlegacy)
|
||||
* @status.tx_time: airtime consumed for transmission
|
||||
* @status.tx_time: airtime consumed for transmission; note this is only
|
||||
* used for WMM AC, not for airtime fairness
|
||||
* @status.is_valid_ack_signal: ACK signal is valid
|
||||
* @status.status_driver_data: driver use area
|
||||
* @ack: union part for pure ACK data
|
||||
@ -1095,12 +1118,14 @@ ieee80211_info_get_tx_time_est(struct ieee80211_tx_info *info)
|
||||
* @info: Basic tx status information
|
||||
* @skb: Packet skb (can be NULL if not provided by the driver)
|
||||
* @rate: The TX rate that was used when sending the packet
|
||||
* @free_list: list where processed skbs are stored to be free'd by the driver
|
||||
*/
|
||||
struct ieee80211_tx_status {
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct sk_buff *skb;
|
||||
struct rate_info *rate;
|
||||
struct list_head *free_list;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1606,6 +1631,21 @@ enum ieee80211_vif_flags {
|
||||
IEEE80211_VIF_GET_NOA_UPDATE = BIT(3),
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* enum ieee80211_offload_flags - virtual interface offload flags
|
||||
*
|
||||
* @IEEE80211_OFFLOAD_ENCAP_ENABLED: tx encapsulation offload is enabled
|
||||
* The driver supports sending frames passed as 802.3 frames by mac80211.
|
||||
* It must also support sending 802.11 packets for the same interface.
|
||||
* @IEEE80211_OFFLOAD_ENCAP_4ADDR: support 4-address mode encapsulation offload
|
||||
*/
|
||||
|
||||
enum ieee80211_offload_flags {
|
||||
IEEE80211_OFFLOAD_ENCAP_ENABLED = BIT(0),
|
||||
IEEE80211_OFFLOAD_ENCAP_4ADDR = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ieee80211_vif - per-interface data
|
||||
*
|
||||
@ -1626,6 +1666,11 @@ enum ieee80211_vif_flags {
|
||||
* these need to be set (or cleared) when the interface is added
|
||||
* or, if supported by the driver, the interface type is changed
|
||||
* at runtime, mac80211 will never touch this field
|
||||
* @offloaad_flags: hardware offload capabilities/flags for this interface.
|
||||
* These are initialized by mac80211 before calling .add_interface,
|
||||
* .change_interface or .update_vif_offload and updated by the driver
|
||||
* within these ops, based on supported features or runtime change
|
||||
* restrictions.
|
||||
* @hw_queue: hardware queue for each AC
|
||||
* @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only
|
||||
* @chanctx_conf: The channel context this interface is assigned to, or %NULL
|
||||
@ -1645,6 +1690,8 @@ enum ieee80211_vif_flags {
|
||||
* @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
|
||||
* @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped,
|
||||
* protected by fq->lock.
|
||||
* @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
|
||||
* &enum ieee80211_offload_flags.
|
||||
*/
|
||||
struct ieee80211_vif {
|
||||
enum nl80211_iftype type;
|
||||
@ -1662,6 +1709,7 @@ struct ieee80211_vif {
|
||||
struct ieee80211_chanctx_conf __rcu *chanctx_conf;
|
||||
|
||||
u32 driver_flags;
|
||||
u32 offload_flags;
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
struct dentry *debugfs_dir;
|
||||
@ -2328,6 +2376,9 @@ struct ieee80211_txq {
|
||||
* aggregating MPDUs with the same keyid, allowing mac80211 to keep Tx
|
||||
* A-MPDU sessions active while rekeying with Extended Key ID.
|
||||
*
|
||||
* @IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD: Hardware supports tx encapsulation
|
||||
* offload
|
||||
*
|
||||
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
|
||||
*/
|
||||
enum ieee80211_hw_flags {
|
||||
@ -2380,6 +2431,7 @@ enum ieee80211_hw_flags {
|
||||
IEEE80211_HW_SUPPORTS_MULTI_BSSID,
|
||||
IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
|
||||
IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT,
|
||||
IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD,
|
||||
|
||||
/* keep last, obviously */
|
||||
NUM_IEEE80211_HW_FLAGS
|
||||
@ -3814,6 +3866,10 @@ enum ieee80211_reconfig_type {
|
||||
* @set_tid_config: Apply TID specific configurations. This callback may sleep.
|
||||
* @reset_tid_config: Reset TID specific configuration for the peer.
|
||||
* This callback may sleep.
|
||||
* @update_vif_offload: Update virtual interface offload flags
|
||||
* This callback may sleep.
|
||||
* @sta_set_4addr: Called to notify the driver when a station starts/stops using
|
||||
* 4-address mode
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw,
|
||||
@ -4125,6 +4181,10 @@ struct ieee80211_ops {
|
||||
int (*reset_tid_config)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u8 tids);
|
||||
void (*update_vif_offload)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
void (*sta_set_4addr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool enabled);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -5647,7 +5707,7 @@ void ieee80211_send_eosp_nullfunc(struct ieee80211_sta *pubsta, int tid);
|
||||
/**
|
||||
* ieee80211_sta_register_airtime - register airtime usage for a sta/tid
|
||||
*
|
||||
* Register airtime usage for a given sta on a given tid. The driver can call
|
||||
* Register airtime usage for a given sta on a given tid. The driver must call
|
||||
* this function to notify mac80211 that a station used a certain amount of
|
||||
* airtime. This information will be used by the TXQ scheduler to schedule
|
||||
* stations in a way that ensures airtime fairness.
|
||||
@ -6593,4 +6653,29 @@ u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,
|
||||
*/
|
||||
bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable);
|
||||
|
||||
/**
|
||||
* ieee80211_get_fils_discovery_tmpl - Get FILS discovery template.
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
*
|
||||
* The driver is responsible for freeing the returned skb.
|
||||
*
|
||||
* Return: FILS discovery template. %NULL on error.
|
||||
*/
|
||||
struct sk_buff *ieee80211_get_fils_discovery_tmpl(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_get_unsol_bcast_probe_resp_tmpl - Get unsolicited broadcast
|
||||
* probe response template.
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
*
|
||||
* The driver is responsible for freeing the returned skb.
|
||||
*
|
||||
* Return: Unsolicited broadcast probe response template. %NULL on error.
|
||||
*/
|
||||
struct sk_buff *
|
||||
ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
#endif /* MAC80211_H */
|
||||
|
@ -2513,6 +2513,14 @@ enum nl80211_commands {
|
||||
* @NL80211_ATTR_HE_6GHZ_CAPABILITY: HE 6 GHz Band Capability element (from
|
||||
* association request when used with NL80211_CMD_NEW_STATION).
|
||||
*
|
||||
* @NL80211_ATTR_FILS_DISCOVERY: Optional parameter to configure FILS
|
||||
* discovery. It is a nested attribute, see
|
||||
* &enum nl80211_fils_discovery_attributes.
|
||||
*
|
||||
* @NL80211_ATTR_UNSOL_BCAST_PROBE_RESP: Optional parameter to configure
|
||||
* unsolicited broadcast probe response. It is a nested attribute, see
|
||||
* &enum nl80211_unsol_bcast_probe_resp_attributes.
|
||||
*
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@ -2995,6 +3003,10 @@ enum nl80211_attrs {
|
||||
|
||||
NL80211_ATTR_HE_6GHZ_CAPABILITY,
|
||||
|
||||
NL80211_ATTR_FILS_DISCOVERY,
|
||||
|
||||
NL80211_ATTR_UNSOL_BCAST_PROBE_RESP,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
@ -3737,6 +3749,16 @@ enum nl80211_wmm_rule {
|
||||
* @NL80211_FREQUENCY_ATTR_NO_HE: HE operation is not allowed on this channel
|
||||
* in current regulatory domain.
|
||||
* @NL80211_FREQUENCY_ATTR_OFFSET: frequency offset in KHz
|
||||
* @NL80211_FREQUENCY_ATTR_1MHZ: 1 MHz operation is allowed
|
||||
* on this channel in current regulatory domain.
|
||||
* @NL80211_FREQUENCY_ATTR_2MHZ: 2 MHz operation is allowed
|
||||
* on this channel in current regulatory domain.
|
||||
* @NL80211_FREQUENCY_ATTR_4MHZ: 4 MHz operation is allowed
|
||||
* on this channel in current regulatory domain.
|
||||
* @NL80211_FREQUENCY_ATTR_8MHZ: 8 MHz operation is allowed
|
||||
* on this channel in current regulatory domain.
|
||||
* @NL80211_FREQUENCY_ATTR_16MHZ: 16 MHz operation is allowed
|
||||
* on this channel in current regulatory domain.
|
||||
* @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
|
||||
* currently defined
|
||||
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
|
||||
@ -3768,6 +3790,11 @@ enum nl80211_frequency_attr {
|
||||
NL80211_FREQUENCY_ATTR_WMM,
|
||||
NL80211_FREQUENCY_ATTR_NO_HE,
|
||||
NL80211_FREQUENCY_ATTR_OFFSET,
|
||||
NL80211_FREQUENCY_ATTR_1MHZ,
|
||||
NL80211_FREQUENCY_ATTR_2MHZ,
|
||||
NL80211_FREQUENCY_ATTR_4MHZ,
|
||||
NL80211_FREQUENCY_ATTR_8MHZ,
|
||||
NL80211_FREQUENCY_ATTR_16MHZ,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
|
||||
@ -5852,6 +5879,12 @@ enum nl80211_feature_flags {
|
||||
* @NL80211_EXT_FEATURE_SAE_OFFLOAD_AP: Device wants to do SAE authentication
|
||||
* in AP mode (SAE password is passed as part of the start AP command).
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_FILS_DISCOVERY: Driver/device supports FILS discovery
|
||||
* frames transmission
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP: Driver/device supports
|
||||
* unsolicited broadcast probe response transmission
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
@ -5910,6 +5943,8 @@ enum nl80211_ext_feature_index {
|
||||
NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION,
|
||||
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK,
|
||||
NL80211_EXT_FEATURE_SAE_OFFLOAD_AP,
|
||||
NL80211_EXT_FEATURE_FILS_DISCOVERY,
|
||||
NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
@ -7004,4 +7039,64 @@ enum nl80211_iftype_akm_attributes {
|
||||
NL80211_IFTYPE_AKM_ATTR_MAX = __NL80211_IFTYPE_AKM_ATTR_LAST - 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_fils_discovery_attributes - FILS discovery configuration
|
||||
* from IEEE Std 802.11ai-2016, Annex C.3 MIB detail.
|
||||
*
|
||||
* @__NL80211_FILS_DISCOVERY_ATTR_INVALID: Invalid
|
||||
*
|
||||
* @NL80211_FILS_DISCOVERY_ATTR_INT_MIN: Minimum packet interval (u32, TU).
|
||||
* Allowed range: 0..10000 (TU = Time Unit)
|
||||
* @NL80211_FILS_DISCOVERY_ATTR_INT_MAX: Maximum packet interval (u32, TU).
|
||||
* Allowed range: 0..10000 (TU = Time Unit)
|
||||
* @NL80211_FILS_DISCOVERY_ATTR_TMPL: Template data for FILS discovery action
|
||||
* frame including the headers.
|
||||
*
|
||||
* @__NL80211_FILS_DISCOVERY_ATTR_LAST: Internal
|
||||
* @NL80211_FILS_DISCOVERY_ATTR_MAX: highest attribute
|
||||
*/
|
||||
enum nl80211_fils_discovery_attributes {
|
||||
__NL80211_FILS_DISCOVERY_ATTR_INVALID,
|
||||
|
||||
NL80211_FILS_DISCOVERY_ATTR_INT_MIN,
|
||||
NL80211_FILS_DISCOVERY_ATTR_INT_MAX,
|
||||
NL80211_FILS_DISCOVERY_ATTR_TMPL,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_FILS_DISCOVERY_ATTR_LAST,
|
||||
NL80211_FILS_DISCOVERY_ATTR_MAX = __NL80211_FILS_DISCOVERY_ATTR_LAST - 1
|
||||
};
|
||||
|
||||
/*
|
||||
* FILS discovery template minimum length with action frame headers and
|
||||
* mandatory fields.
|
||||
*/
|
||||
#define NL80211_FILS_DISCOVERY_TMPL_MIN_LEN 42
|
||||
|
||||
/**
|
||||
* enum nl80211_unsol_bcast_probe_resp_attributes - Unsolicited broadcast probe
|
||||
* response configuration. Applicable only in 6GHz.
|
||||
*
|
||||
* @__NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INVALID: Invalid
|
||||
*
|
||||
* @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT: Maximum packet interval (u32, TU).
|
||||
* Allowed range: 0..20 (TU = Time Unit). IEEE P802.11ax/D6.0
|
||||
* 26.17.2.3.2 (AP behavior for fast passive scanning).
|
||||
* @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL: Unsolicited broadcast probe response
|
||||
* frame template (binary).
|
||||
*
|
||||
* @__NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST: Internal
|
||||
* @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX: highest attribute
|
||||
*/
|
||||
enum nl80211_unsol_bcast_probe_resp_attributes {
|
||||
__NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INVALID,
|
||||
|
||||
NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT,
|
||||
NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST,
|
||||
NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX =
|
||||
__NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST - 1
|
||||
};
|
||||
#endif /* __LINUX_NL80211_H */
|
||||
|
@ -837,6 +837,59 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_fils_discovery *params)
|
||||
{
|
||||
struct fils_discovery_data *new, *old = NULL;
|
||||
struct ieee80211_fils_discovery *fd;
|
||||
|
||||
if (!params->tmpl || !params->tmpl_len)
|
||||
return -EINVAL;
|
||||
|
||||
fd = &sdata->vif.bss_conf.fils_discovery;
|
||||
fd->min_interval = params->min_interval;
|
||||
fd->max_interval = params->max_interval;
|
||||
|
||||
old = sdata_dereference(sdata->u.ap.fils_discovery, sdata);
|
||||
new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
new->len = params->tmpl_len;
|
||||
memcpy(new->data, params->tmpl, params->tmpl_len);
|
||||
rcu_assign_pointer(sdata->u.ap.fils_discovery, new);
|
||||
|
||||
if (old)
|
||||
kfree_rcu(old, rcu_head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_unsol_bcast_probe_resp *params)
|
||||
{
|
||||
struct unsol_bcast_probe_resp_data *new, *old = NULL;
|
||||
|
||||
if (!params->tmpl || !params->tmpl_len)
|
||||
return -EINVAL;
|
||||
|
||||
old = sdata_dereference(sdata->u.ap.unsol_bcast_probe_resp, sdata);
|
||||
new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
new->len = params->tmpl_len;
|
||||
memcpy(new->data, params->tmpl, params->tmpl_len);
|
||||
rcu_assign_pointer(sdata->u.ap.unsol_bcast_probe_resp, new);
|
||||
|
||||
if (old)
|
||||
kfree_rcu(old, rcu_head);
|
||||
|
||||
sdata->vif.bss_conf.unsol_bcast_probe_resp_interval =
|
||||
params->interval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_set_ftm_responder_params(
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
const u8 *lci, size_t lci_len,
|
||||
@ -1099,12 +1152,26 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
}
|
||||
|
||||
err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL);
|
||||
if (err < 0) {
|
||||
ieee80211_vif_release_channel(sdata);
|
||||
return err;
|
||||
}
|
||||
if (err < 0)
|
||||
goto error;
|
||||
changed |= err;
|
||||
|
||||
if (params->fils_discovery.max_interval) {
|
||||
err = ieee80211_set_fils_discovery(sdata,
|
||||
¶ms->fils_discovery);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
changed |= BSS_CHANGED_FILS_DISCOVERY;
|
||||
}
|
||||
|
||||
if (params->unsol_bcast_probe_resp.interval) {
|
||||
err = ieee80211_set_unsol_bcast_probe_resp(sdata,
|
||||
¶ms->unsol_bcast_probe_resp);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP;
|
||||
}
|
||||
|
||||
err = drv_start_ap(sdata->local, sdata);
|
||||
if (err) {
|
||||
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||
@ -1112,8 +1179,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
if (old)
|
||||
kfree_rcu(old, rcu_head);
|
||||
RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
|
||||
ieee80211_vif_release_channel(sdata);
|
||||
return err;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ieee80211_recalc_dtim(local, sdata);
|
||||
@ -1124,6 +1190,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
netif_carrier_on(vlan->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
ieee80211_vif_release_channel(sdata);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
|
||||
@ -1160,6 +1230,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct beacon_data *old_beacon;
|
||||
struct probe_resp *old_probe_resp;
|
||||
struct fils_discovery_data *old_fils_discovery;
|
||||
struct unsol_bcast_probe_resp_data *old_unsol_bcast_probe_resp;
|
||||
struct cfg80211_chan_def chandef;
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
@ -1168,6 +1240,11 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||
if (!old_beacon)
|
||||
return -ENOENT;
|
||||
old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata);
|
||||
old_fils_discovery = sdata_dereference(sdata->u.ap.fils_discovery,
|
||||
sdata);
|
||||
old_unsol_bcast_probe_resp =
|
||||
sdata_dereference(sdata->u.ap.unsol_bcast_probe_resp,
|
||||
sdata);
|
||||
|
||||
/* abort any running channel switch */
|
||||
mutex_lock(&local->mtx);
|
||||
@ -1191,9 +1268,15 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||
/* remove beacon and probe response */
|
||||
RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
|
||||
RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL);
|
||||
RCU_INIT_POINTER(sdata->u.ap.fils_discovery, NULL);
|
||||
RCU_INIT_POINTER(sdata->u.ap.unsol_bcast_probe_resp, NULL);
|
||||
kfree_rcu(old_beacon, rcu_head);
|
||||
if (old_probe_resp)
|
||||
kfree_rcu(old_probe_resp, rcu_head);
|
||||
if (old_fils_discovery)
|
||||
kfree_rcu(old_fils_discovery, rcu_head);
|
||||
if (old_unsol_bcast_probe_resp)
|
||||
kfree_rcu(old_unsol_bcast_probe_resp, rcu_head);
|
||||
|
||||
kfree(sdata->vif.bss_conf.ftmr_params);
|
||||
sdata->vif.bss_conf.ftmr_params = NULL;
|
||||
@ -1696,6 +1779,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
|
||||
|
||||
rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
|
||||
__ieee80211_check_fast_rx_iface(vlansdata);
|
||||
drv_sta_set_4addr(local, sta->sdata, &sta->sta, true);
|
||||
}
|
||||
|
||||
if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
|
||||
|
@ -408,6 +408,7 @@ static const char *hw_flag_names[] = {
|
||||
FLAG(SUPPORTS_MULTI_BSSID),
|
||||
FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
|
||||
FLAG(AMPDU_KEYBORDER_SUPPORT),
|
||||
FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
|
||||
#undef FLAG
|
||||
};
|
||||
|
||||
|
@ -1384,4 +1384,33 @@ static inline int drv_reset_tid_config(struct ieee80211_local *local,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void drv_update_vif_offload(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
might_sleep();
|
||||
check_sdata_in_driver(sdata);
|
||||
|
||||
if (!local->ops->update_vif_offload)
|
||||
return;
|
||||
|
||||
trace_drv_update_vif_offload(local, sdata);
|
||||
local->ops->update_vif_offload(&local->hw, &sdata->vif);
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
static inline void drv_sta_set_4addr(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta *sta, bool enabled)
|
||||
{
|
||||
sdata = get_bss_sdata(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_sta_set_4addr(local, sdata, sta, enabled);
|
||||
if (local->ops->sta_set_4addr)
|
||||
local->ops->sta_set_4addr(&local->hw, &sdata->vif, sta, enabled);
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
|
@ -271,6 +271,18 @@ struct probe_resp {
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
struct fils_discovery_data {
|
||||
struct rcu_head rcu_head;
|
||||
int len;
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
struct unsol_bcast_probe_resp_data {
|
||||
struct rcu_head rcu_head;
|
||||
int len;
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
struct ps_data {
|
||||
/* yes, this looks ugly, but guarantees that we can later use
|
||||
* bitmap_empty :)
|
||||
@ -286,6 +298,8 @@ struct ps_data {
|
||||
struct ieee80211_if_ap {
|
||||
struct beacon_data __rcu *beacon;
|
||||
struct probe_resp __rcu *probe_resp;
|
||||
struct fils_discovery_data __rcu *fils_discovery;
|
||||
struct unsol_bcast_probe_resp_data __rcu *unsol_bcast_probe_resp;
|
||||
|
||||
/* to be used after channel switch. */
|
||||
struct cfg80211_beacon_data *next_beacon;
|
||||
@ -989,8 +1003,6 @@ struct ieee80211_sub_if_data {
|
||||
} debugfs;
|
||||
#endif
|
||||
|
||||
bool hw_80211_encap;
|
||||
|
||||
/* must be last, dynamically sized area in this! */
|
||||
struct ieee80211_vif vif;
|
||||
};
|
||||
@ -1767,6 +1779,7 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
|
||||
bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
|
||||
bool update_bss);
|
||||
void ieee80211_recalc_offload(struct ieee80211_local *local);
|
||||
|
||||
static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
@ -2040,8 +2053,6 @@ void ieee80211_dynamic_ps_timer(struct timer_list *t);
|
||||
void ieee80211_send_nullfunc(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
bool powersave);
|
||||
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_hdr *hdr);
|
||||
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
|
||||
|
||||
|
1007
net/mac80211/iface.c
1007
net/mac80211/iface.c
File diff suppressed because it is too large
Load Diff
@ -177,13 +177,6 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
|
||||
}
|
||||
}
|
||||
|
||||
/* TKIP countermeasures don't work in encap offload mode */
|
||||
if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
|
||||
sdata->hw_80211_encap) {
|
||||
sdata_dbg(sdata, "TKIP is not allowed in hw 80211 encap mode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = drv_set_key(key->local, SET_KEY, sdata,
|
||||
sta ? &sta->sta : NULL, &key->conf);
|
||||
|
||||
@ -219,14 +212,6 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
|
||||
case WLAN_CIPHER_SUITE_CCMP_256:
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
/* We cannot do software crypto of data frames with
|
||||
* encapsulation offload enabled. However for 802.11w to
|
||||
* function properly we need cmac/gmac keys.
|
||||
*/
|
||||
if (sdata->hw_80211_encap)
|
||||
return -EINVAL;
|
||||
fallthrough;
|
||||
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
|
@ -212,7 +212,7 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
|
||||
skb->priority = 7;
|
||||
|
||||
info->control.vif = &sdata->vif;
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
|
||||
ieee80211_set_qos_hdr(sdata, skb);
|
||||
ieee80211_mps_set_frame_flags(sdata, NULL, hdr);
|
||||
}
|
||||
@ -1163,7 +1163,7 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
|
||||
if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN)
|
||||
skb_to_free = skb_dequeue(&mpath->frame_queue);
|
||||
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
|
||||
ieee80211_set_qos_hdr(sdata, skb);
|
||||
skb_queue_tail(&mpath->frame_queue, skb);
|
||||
if (skb_to_free)
|
||||
|
@ -432,7 +432,7 @@ static void mpsp_qos_null_append(struct sta_info *sta,
|
||||
|
||||
info = IEEE80211_SKB_CB(new_skb);
|
||||
info->control.vif = &sdata->vif;
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
|
||||
|
||||
__skb_queue_tail(frames, new_skb);
|
||||
}
|
||||
|
@ -2432,23 +2432,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||
}
|
||||
|
||||
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_hdr *hdr)
|
||||
{
|
||||
/*
|
||||
* We can postpone the mgd.timer whenever receiving unicast frames
|
||||
* from AP because we know that the connection is working both ways
|
||||
* at that time. But multicast frames (and hence also beacons) must
|
||||
* be ignored here, because we need to trigger the timer during
|
||||
* data idle periods for sending the periodic probe request to the
|
||||
* AP we're connected to.
|
||||
*/
|
||||
if (is_multicast_ether_addr(hdr->addr1))
|
||||
return;
|
||||
|
||||
ieee80211_sta_reset_conn_monitor(sdata);
|
||||
}
|
||||
|
||||
static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
@ -2521,21 +2504,13 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
|
||||
{
|
||||
ieee80211_sta_tx_wmm_ac_notify(sdata, hdr, tx_time);
|
||||
|
||||
if (!ieee80211_is_data(hdr->frame_control))
|
||||
return;
|
||||
|
||||
if (ieee80211_is_any_nullfunc(hdr->frame_control) &&
|
||||
sdata->u.mgd.probe_send_count > 0) {
|
||||
if (ack)
|
||||
ieee80211_sta_reset_conn_monitor(sdata);
|
||||
else
|
||||
sdata->u.mgd.nullfunc_failed = true;
|
||||
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
|
||||
if (!ieee80211_is_any_nullfunc(hdr->frame_control) ||
|
||||
!sdata->u.mgd.probe_send_count)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ack)
|
||||
ieee80211_sta_reset_conn_monitor(sdata);
|
||||
if (!ack)
|
||||
sdata->u.mgd.nullfunc_failed = true;
|
||||
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
|
||||
}
|
||||
|
||||
static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata,
|
||||
@ -3548,6 +3523,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sdata->wdev.use_4addr)
|
||||
drv_sta_set_4addr(local, sdata, &sta->sta, true);
|
||||
|
||||
mutex_unlock(&sdata->local->sta_mtx);
|
||||
|
||||
/*
|
||||
@ -3605,8 +3583,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
||||
* Start timer to probe the connection to the AP now.
|
||||
* Also start the timer that will detect beacon loss.
|
||||
*/
|
||||
ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
|
||||
ieee80211_sta_reset_beacon_monitor(sdata);
|
||||
ieee80211_sta_reset_conn_monitor(sdata);
|
||||
|
||||
ret = true;
|
||||
out:
|
||||
@ -4577,10 +4555,26 @@ static void ieee80211_sta_conn_mon_timer(struct timer_list *t)
|
||||
from_timer(sdata, t, u.mgd.conn_mon_timer);
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sta_info *sta;
|
||||
unsigned long timeout;
|
||||
|
||||
if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
|
||||
return;
|
||||
|
||||
sta = sta_info_get(sdata, ifmgd->bssid);
|
||||
if (!sta)
|
||||
return;
|
||||
|
||||
timeout = sta->status_stats.last_ack;
|
||||
if (time_before(sta->status_stats.last_ack, sta->rx_stats.last_rx))
|
||||
timeout = sta->rx_stats.last_rx;
|
||||
timeout += IEEE80211_CONNECTION_IDLE_TIME;
|
||||
|
||||
if (time_is_before_jiffies(timeout)) {
|
||||
mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout));
|
||||
return;
|
||||
}
|
||||
|
||||
ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
|
||||
}
|
||||
|
||||
|
@ -1811,9 +1811,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
||||
sta->rx_stats.last_rate = sta_stats_encode_rate(status);
|
||||
}
|
||||
|
||||
if (rx->sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_sta_rx_notify(rx->sdata, hdr);
|
||||
|
||||
sta->rx_stats.fragments++;
|
||||
|
||||
u64_stats_update_begin(&rx->sta->rx_stats.syncp);
|
||||
@ -2899,7 +2896,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||
fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
|
||||
info = IEEE80211_SKB_CB(fwd_skb);
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
|
||||
info->control.vif = &rx->sdata->vif;
|
||||
info->control.jiffies = jiffies;
|
||||
if (is_multicast_ether_addr(fwd_hdr->addr1)) {
|
||||
@ -4148,7 +4145,6 @@ void ieee80211_check_fast_rx(struct sta_info *sta)
|
||||
fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2);
|
||||
fastrx.expected_ds_bits = 0;
|
||||
} else {
|
||||
fastrx.sta_notify = sdata->u.mgd.probe_send_count > 0;
|
||||
fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1);
|
||||
fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr3);
|
||||
fastrx.expected_ds_bits =
|
||||
@ -4378,11 +4374,6 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
|
||||
pskb_trim(skb, skb->len - fast_rx->icv_len))
|
||||
goto drop;
|
||||
|
||||
if (unlikely(fast_rx->sta_notify)) {
|
||||
ieee80211_sta_rx_notify(rx->sdata, hdr);
|
||||
fast_rx->sta_notify = false;
|
||||
}
|
||||
|
||||
/* statistics part of ieee80211_rx_h_sta_process() */
|
||||
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
|
||||
stats->last_signal = status->signal;
|
||||
|
@ -336,7 +336,6 @@ struct ieee80211_fast_tx {
|
||||
* @expected_ds_bits: from/to DS bits expected
|
||||
* @icv_len: length of the MIC if present
|
||||
* @key: bool indicating encryption is expected (key is set)
|
||||
* @sta_notify: notify the MLME code (once)
|
||||
* @internal_forward: forward froms internally on AP/VLAN type interfaces
|
||||
* @uses_rss: copy of USES_RSS hw flag
|
||||
* @da_offs: offset of the DA in the header (for header conversion)
|
||||
@ -352,7 +351,6 @@ struct ieee80211_fast_rx {
|
||||
__le16 expected_ds_bits;
|
||||
u8 icv_len;
|
||||
u8 key:1,
|
||||
sta_notify:1,
|
||||
internal_forward:1,
|
||||
uses_rss:1;
|
||||
u8 da_offs, sa_offs;
|
||||
|
@ -66,8 +66,8 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||
|
||||
info->control.jiffies = jiffies;
|
||||
info->control.vif = &sta->sdata->vif;
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
|
||||
IEEE80211_TX_INTFL_RETRANSMISSION;
|
||||
info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
|
||||
info->flags |= IEEE80211_TX_INTFL_RETRANSMISSION;
|
||||
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
|
||||
|
||||
sta->status_stats.filtered++;
|
||||
@ -184,18 +184,6 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
|
||||
struct ieee80211_mgmt *mgmt = (void *) skb->data;
|
||||
struct ieee80211_local *local = sta->local;
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
|
||||
|
||||
if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
|
||||
sta->status_stats.last_ack = jiffies;
|
||||
if (txinfo->status.is_valid_ack_signal) {
|
||||
sta->status_stats.last_ack_signal =
|
||||
(s8)txinfo->status.ack_signal;
|
||||
sta->status_stats.ack_signal_filled = true;
|
||||
ewma_avg_signal_add(&sta->status_stats.avg_ack_signal,
|
||||
-txinfo->status.ack_signal);
|
||||
}
|
||||
}
|
||||
|
||||
if (ieee80211_is_data_qos(mgmt->frame_control)) {
|
||||
struct ieee80211_hdr *hdr = (void *) skb->data;
|
||||
@ -890,7 +878,8 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_status *status)
|
||||
struct ieee80211_tx_status *status,
|
||||
int rates_idx, int retry_count)
|
||||
{
|
||||
struct sk_buff *skb = status->skb;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
@ -899,17 +888,12 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
||||
struct sta_info *sta;
|
||||
__le16 fc;
|
||||
struct ieee80211_supported_band *sband;
|
||||
int retry_count;
|
||||
int rates_idx;
|
||||
bool send_to_cooked;
|
||||
bool acked;
|
||||
bool noack_success;
|
||||
struct ieee80211_bar *bar;
|
||||
int shift = 0;
|
||||
int tid = IEEE80211_NUM_TIDS;
|
||||
u16 tx_time_est;
|
||||
|
||||
rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
|
||||
|
||||
sband = local->hw.wiphy->bands[info->band];
|
||||
fc = hdr->frame_control;
|
||||
@ -987,24 +971,14 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
||||
if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
|
||||
ieee80211_handle_filtered_frame(local, sta, skb);
|
||||
return;
|
||||
} else {
|
||||
} else if (ieee80211_is_data_present(fc)) {
|
||||
if (!acked && !noack_success)
|
||||
sta->status_stats.retry_failed++;
|
||||
sta->status_stats.retry_count += retry_count;
|
||||
sta->status_stats.msdu_failed[tid]++;
|
||||
|
||||
if (ieee80211_is_data_present(fc)) {
|
||||
if (!acked && !noack_success)
|
||||
sta->status_stats.msdu_failed[tid]++;
|
||||
|
||||
sta->status_stats.msdu_retries[tid] +=
|
||||
retry_count;
|
||||
}
|
||||
sta->status_stats.msdu_retries[tid] +=
|
||||
retry_count;
|
||||
}
|
||||
|
||||
rate_control_tx_status(local, sband, status);
|
||||
if (ieee80211_vif_is_mesh(&sta->sdata->vif))
|
||||
ieee80211s_update_metric(local, sta, status);
|
||||
|
||||
if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked)
|
||||
ieee80211_frame_acked(sta, skb);
|
||||
|
||||
@ -1012,37 +986,6 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
||||
ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
|
||||
ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data,
|
||||
acked, info->status.tx_time);
|
||||
|
||||
if (info->status.tx_time &&
|
||||
wiphy_ext_feature_isset(local->hw.wiphy,
|
||||
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
|
||||
ieee80211_sta_register_airtime(&sta->sta, tid,
|
||||
info->status.tx_time, 0);
|
||||
|
||||
if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) {
|
||||
/* Do this here to avoid the expensive lookup of the sta
|
||||
* in ieee80211_report_used_skb().
|
||||
*/
|
||||
ieee80211_sta_update_pending_airtime(local, sta,
|
||||
skb_get_queue_mapping(skb),
|
||||
tx_time_est,
|
||||
true);
|
||||
ieee80211_info_set_tx_time_est(info, 0);
|
||||
}
|
||||
|
||||
if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
|
||||
if (acked) {
|
||||
if (sta->status_stats.lost_packets)
|
||||
sta->status_stats.lost_packets = 0;
|
||||
|
||||
/* Track when last TDLS packet was ACKed */
|
||||
sta->status_stats.last_pkt_time = jiffies;
|
||||
} else if (noack_success) {
|
||||
/* nothing to do here, do not account as lost */
|
||||
} else {
|
||||
ieee80211_lost_packet(sta, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* SNMP counters
|
||||
@ -1101,7 +1044,10 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
||||
* with this test...
|
||||
*/
|
||||
if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) {
|
||||
dev_kfree_skb(skb);
|
||||
if (status->free_list)
|
||||
list_add_tail(&skb->list, status->free_list);
|
||||
else
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1126,7 +1072,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
if (sta)
|
||||
status.sta = &sta->sta;
|
||||
|
||||
__ieee80211_tx_status(hw, &status);
|
||||
ieee80211_tx_status_ext(hw, &status);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_tx_status);
|
||||
@ -1137,10 +1083,12 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct ieee80211_tx_info *info = status->info;
|
||||
struct ieee80211_sta *pubsta = status->sta;
|
||||
struct sk_buff *skb = status->skb;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct sta_info *sta;
|
||||
int retry_count;
|
||||
struct sta_info *sta = NULL;
|
||||
int rates_idx, retry_count;
|
||||
bool acked, noack_success;
|
||||
u16 tx_time_est;
|
||||
|
||||
if (pubsta) {
|
||||
sta = container_of(pubsta, struct sta_info, sta);
|
||||
@ -1149,13 +1097,22 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
|
||||
sta->tx_stats.last_rate_info = *status->rate;
|
||||
}
|
||||
|
||||
if (status->skb)
|
||||
return __ieee80211_tx_status(hw, status);
|
||||
if (skb && (tx_time_est =
|
||||
ieee80211_info_get_tx_time_est(IEEE80211_SKB_CB(skb))) > 0) {
|
||||
/* Do this here to avoid the expensive lookup of the sta
|
||||
* in ieee80211_report_used_skb().
|
||||
*/
|
||||
ieee80211_sta_update_pending_airtime(local, sta,
|
||||
skb_get_queue_mapping(skb),
|
||||
tx_time_est,
|
||||
true);
|
||||
ieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0);
|
||||
}
|
||||
|
||||
if (!status->sta)
|
||||
return;
|
||||
if (!status->info)
|
||||
goto free;
|
||||
|
||||
ieee80211_tx_get_rates(hw, info, &retry_count);
|
||||
rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
|
||||
|
||||
sband = hw->wiphy->bands[info->band];
|
||||
|
||||
@ -1167,20 +1124,30 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
|
||||
sta->status_stats.retry_failed++;
|
||||
sta->status_stats.retry_count += retry_count;
|
||||
|
||||
if (acked) {
|
||||
sta->status_stats.last_ack = jiffies;
|
||||
if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
|
||||
if (acked) {
|
||||
sta->status_stats.last_ack = jiffies;
|
||||
|
||||
if (sta->status_stats.lost_packets)
|
||||
sta->status_stats.lost_packets = 0;
|
||||
if (sta->status_stats.lost_packets)
|
||||
sta->status_stats.lost_packets = 0;
|
||||
|
||||
/* Track when last packet was ACKed */
|
||||
sta->status_stats.last_pkt_time = jiffies;
|
||||
} else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
||||
return;
|
||||
} else if (noack_success) {
|
||||
/* nothing to do here, do not account as lost */
|
||||
} else {
|
||||
ieee80211_lost_packet(sta, info);
|
||||
/* Track when last packet was ACKed */
|
||||
sta->status_stats.last_pkt_time = jiffies;
|
||||
|
||||
if (info->status.is_valid_ack_signal) {
|
||||
sta->status_stats.last_ack_signal =
|
||||
(s8)info->status.ack_signal;
|
||||
sta->status_stats.ack_signal_filled = true;
|
||||
ewma_avg_signal_add(&sta->status_stats.avg_ack_signal,
|
||||
-info->status.ack_signal);
|
||||
}
|
||||
} else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
||||
return;
|
||||
} else if (noack_success) {
|
||||
/* nothing to do here, do not account as lost */
|
||||
} else {
|
||||
ieee80211_lost_packet(sta, info);
|
||||
}
|
||||
}
|
||||
|
||||
rate_control_tx_status(local, sband, status);
|
||||
@ -1188,6 +1155,10 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
|
||||
ieee80211s_update_metric(local, sta, status);
|
||||
}
|
||||
|
||||
if (skb && !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
|
||||
return __ieee80211_tx_status(hw, status, rates_idx,
|
||||
retry_count);
|
||||
|
||||
if (acked || noack_success) {
|
||||
I802_DEBUG_INC(local->dot11TransmittedFrameCount);
|
||||
if (!pubsta)
|
||||
@ -1199,6 +1170,16 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
|
||||
} else {
|
||||
I802_DEBUG_INC(local->dot11FailedCount);
|
||||
}
|
||||
|
||||
free:
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
ieee80211_report_used_skb(local, skb, false);
|
||||
if (status->free_list)
|
||||
list_add_tail(&skb->list, status->free_list);
|
||||
else
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_tx_status_ext);
|
||||
|
||||
@ -1225,69 +1206,23 @@ void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_status status = {
|
||||
.skb = skb,
|
||||
.info = IEEE80211_SKB_CB(skb),
|
||||
};
|
||||
struct sta_info *sta;
|
||||
int retry_count;
|
||||
int rates_idx;
|
||||
bool acked;
|
||||
|
||||
sdata = vif_to_sdata(vif);
|
||||
|
||||
acked = info->flags & IEEE80211_TX_STAT_ACK;
|
||||
rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
|
||||
goto counters_update;
|
||||
if (!ieee80211_lookup_ra_sta(sdata, skb, &sta) && !IS_ERR(sta))
|
||||
status.sta = &sta->sta;
|
||||
|
||||
if (IS_ERR(sta))
|
||||
goto counters_update;
|
||||
ieee80211_tx_status_ext(hw, &status);
|
||||
|
||||
if (!acked)
|
||||
sta->status_stats.retry_failed++;
|
||||
|
||||
if (rates_idx != -1)
|
||||
sta->tx_stats.last_rate = info->status.rates[rates_idx];
|
||||
|
||||
sta->status_stats.retry_count += retry_count;
|
||||
|
||||
if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) {
|
||||
if (acked && vif->type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_sta_reset_conn_monitor(sdata);
|
||||
|
||||
sta->status_stats.last_ack = jiffies;
|
||||
if (info->flags & IEEE80211_TX_STAT_ACK) {
|
||||
if (sta->status_stats.lost_packets)
|
||||
sta->status_stats.lost_packets = 0;
|
||||
|
||||
sta->status_stats.last_pkt_time = jiffies;
|
||||
} else {
|
||||
ieee80211_lost_packet(sta, info);
|
||||
}
|
||||
}
|
||||
|
||||
counters_update:
|
||||
rcu_read_unlock();
|
||||
ieee80211_led_tx(local);
|
||||
|
||||
if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
|
||||
!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED))
|
||||
goto skip_stats_update;
|
||||
|
||||
I802_DEBUG_INC(local->dot11TransmittedFrameCount);
|
||||
if (is_multicast_ether_addr(skb->data))
|
||||
I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount);
|
||||
if (retry_count > 0)
|
||||
I802_DEBUG_INC(local->dot11RetryCount);
|
||||
if (retry_count > 1)
|
||||
I802_DEBUG_INC(local->dot11MultipleRetryCount);
|
||||
|
||||
skip_stats_update:
|
||||
ieee80211_report_used_skb(local, skb, false);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_tx_status_8023);
|
||||
|
||||
|
@ -2734,6 +2734,39 @@ TRACE_EVENT(drv_get_ftm_responder_stats,
|
||||
)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(local_sdata_addr_evt, drv_update_vif_offload,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata),
|
||||
TP_ARGS(local, sdata)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_sta_set_4addr,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta *sta, bool enabled),
|
||||
|
||||
TP_ARGS(local, sdata, sta, enabled),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
VIF_ENTRY
|
||||
STA_ENTRY
|
||||
__field(bool, enabled)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
VIF_ASSIGN;
|
||||
STA_ASSIGN;
|
||||
__entry->enabled = enabled;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " enabled:%d",
|
||||
LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->enabled
|
||||
)
|
||||
);
|
||||
|
||||
#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
@ -531,7 +531,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
|
||||
info->control.jiffies = jiffies;
|
||||
info->control.vif = &tx->sdata->vif;
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
|
||||
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
|
||||
skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
|
||||
spin_unlock(&sta->ps_lock);
|
||||
@ -1134,7 +1134,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
|
||||
tx->sta->sta.addr, tx->sta->sta.aid);
|
||||
}
|
||||
info->control.vif = &tx->sdata->vif;
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
|
||||
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
|
||||
__skb_queue_tail(&tid_tx->pending, skb);
|
||||
if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
|
||||
@ -1179,7 +1179,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
|
||||
* we are doing the needed processing, so remove the flag
|
||||
* now.
|
||||
*/
|
||||
info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->control.flags &= ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
|
||||
@ -1258,7 +1258,7 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
|
||||
(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
|
||||
return NULL;
|
||||
|
||||
if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
|
||||
if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
||||
unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
|
||||
if ((!ieee80211_is_mgmt(hdr->frame_control) ||
|
||||
ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
|
||||
@ -3649,7 +3649,7 @@ begin:
|
||||
else
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
|
||||
if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
|
||||
if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
|
||||
goto encap_out;
|
||||
|
||||
if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
|
||||
@ -4190,38 +4190,18 @@ static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
|
||||
struct net_device *dev, struct sta_info *sta,
|
||||
struct sk_buff *skb)
|
||||
struct ieee80211_key *key, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ethhdr *ehdr = (struct ethhdr *)skb->data;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
bool authorized = false;
|
||||
bool multicast;
|
||||
unsigned char *ra = ehdr->h_dest;
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
u8 tid;
|
||||
|
||||
if (IS_ERR(sta) || (sta && !sta->uploaded))
|
||||
sta = NULL;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
(!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER)))
|
||||
ra = sdata->u.mgd.bssid;
|
||||
|
||||
if (is_zero_ether_addr(ra))
|
||||
goto out_free;
|
||||
|
||||
multicast = is_multicast_ether_addr(ra);
|
||||
|
||||
if (sta)
|
||||
authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
|
||||
|
||||
if (!multicast && !authorized &&
|
||||
(ehdr->h_proto != sdata->control_port_protocol ||
|
||||
!ether_addr_equal(sdata->vif.addr, ehdr->h_source)))
|
||||
goto out_free;
|
||||
|
||||
if (multicast && sdata->vif.type == NL80211_IFTYPE_AP &&
|
||||
!atomic_read(&sdata->u.ap.num_mcast_sta))
|
||||
goto out_free;
|
||||
if (local->ops->wake_tx_queue) {
|
||||
u16 queue = __ieee80211_select_queue(sdata, sta, skb);
|
||||
skb_set_queue_mapping(skb, queue);
|
||||
skb_get_hash(skb);
|
||||
}
|
||||
|
||||
if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
|
||||
test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
|
||||
@ -4229,36 +4209,42 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
if (unlikely(!multicast && skb->sk &&
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
|
||||
if (tid_tx) {
|
||||
if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
|
||||
/* fall back to non-offload slow path */
|
||||
__ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
info->flags |= IEEE80211_TX_CTL_AMPDU;
|
||||
if (tid_tx->timeout)
|
||||
tid_tx->last_tx = jiffies;
|
||||
}
|
||||
|
||||
if (unlikely(skb->sk &&
|
||||
skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
|
||||
info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
|
||||
&info->flags, NULL);
|
||||
|
||||
if (unlikely(sdata->control_port_protocol == ehdr->h_proto)) {
|
||||
if (sdata->control_port_no_encrypt)
|
||||
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||
info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
|
||||
}
|
||||
|
||||
if (multicast)
|
||||
info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||
|
||||
info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
|
||||
|
||||
ieee80211_tx_stats(dev, skb->len);
|
||||
|
||||
if (sta) {
|
||||
sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
|
||||
sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
|
||||
}
|
||||
sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
|
||||
sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
sdata = container_of(sdata->bss,
|
||||
struct ieee80211_sub_if_data, u.ap);
|
||||
|
||||
info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
|
||||
info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP;
|
||||
info->control.vif = &sdata->vif;
|
||||
|
||||
if (key)
|
||||
info->control.hw_key = &key->conf;
|
||||
|
||||
ieee80211_tx_8023(sdata, skb, skb->len, sta, false);
|
||||
|
||||
return;
|
||||
@ -4271,12 +4257,10 @@ netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ethhdr *ehdr = (struct ethhdr *)skb->data;
|
||||
struct ieee80211_key *key;
|
||||
struct sta_info *sta;
|
||||
|
||||
if (WARN_ON(!sdata->hw_80211_encap)) {
|
||||
kfree_skb(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
bool offload = true;
|
||||
|
||||
if (unlikely(skb->len < ETH_HLEN)) {
|
||||
kfree_skb(skb);
|
||||
@ -4285,11 +4269,26 @@ netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
|
||||
if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
|
||||
kfree_skb(skb);
|
||||
else
|
||||
ieee80211_8023_xmit(sdata, dev, sta, skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded ||
|
||||
!test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
|
||||
sdata->control_port_protocol == ehdr->h_proto))
|
||||
offload = false;
|
||||
else if ((key = rcu_dereference(sta->ptk[sta->ptk_idx])) &&
|
||||
(!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
|
||||
key->conf.cipher == WLAN_CIPHER_SUITE_TKIP))
|
||||
offload = false;
|
||||
|
||||
if (offload)
|
||||
ieee80211_8023_xmit(sdata, dev, sta, key, skb);
|
||||
else
|
||||
ieee80211_subif_start_xmit(skb, dev);
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
@ -4365,7 +4364,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
|
||||
|
||||
sdata = vif_to_sdata(info->control.vif);
|
||||
|
||||
if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) {
|
||||
if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) {
|
||||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||
if (unlikely(!chanctx_conf)) {
|
||||
dev_kfree_skb(skb);
|
||||
@ -4373,7 +4372,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
|
||||
}
|
||||
info->band = chanctx_conf->def.chan->band;
|
||||
result = ieee80211_tx(sdata, NULL, skb, true);
|
||||
} else if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
|
||||
} else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
|
||||
if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
|
||||
dev_kfree_skb(skb);
|
||||
return true;
|
||||
@ -5000,6 +4999,63 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_proberesp_get);
|
||||
|
||||
struct sk_buff *ieee80211_get_fils_discovery_tmpl(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct fils_discovery_data *tmpl = NULL;
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_AP)
|
||||
return NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
tmpl = rcu_dereference(sdata->u.ap.fils_discovery);
|
||||
if (!tmpl) {
|
||||
rcu_read_unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len);
|
||||
if (skb) {
|
||||
skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
|
||||
skb_put_data(skb, tmpl->data, tmpl->len);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
return skb;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_get_fils_discovery_tmpl);
|
||||
|
||||
struct sk_buff *
|
||||
ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct unsol_bcast_probe_resp_data *tmpl = NULL;
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_AP)
|
||||
return NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
tmpl = rcu_dereference(sdata->u.ap.unsol_bcast_probe_resp);
|
||||
if (!tmpl) {
|
||||
rcu_read_unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len);
|
||||
if (skb) {
|
||||
skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
|
||||
skb_put_data(skb, tmpl->data, tmpl->len);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
return skb;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_get_unsol_bcast_probe_resp_tmpl);
|
||||
|
||||
struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
|
@ -315,10 +315,6 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
|
||||
|
||||
/* If HT IE reported 3839 bytes only, stay with that size. */
|
||||
if (sta->sta.max_amsdu_len == IEEE80211_MAX_MPDU_LEN_HT_3839)
|
||||
return;
|
||||
|
||||
switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
|
||||
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
|
||||
sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
|
||||
|
@ -141,9 +141,62 @@ static bool cfg80211_edmg_chandef_valid(const struct cfg80211_chan_def *chandef)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width)
|
||||
{
|
||||
int mhz;
|
||||
|
||||
switch (chan_width) {
|
||||
case NL80211_CHAN_WIDTH_1:
|
||||
mhz = 1;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_2:
|
||||
mhz = 2;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_4:
|
||||
mhz = 4;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_8:
|
||||
mhz = 8;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_16:
|
||||
mhz = 16;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_5:
|
||||
mhz = 5;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_10:
|
||||
mhz = 10;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
mhz = 20;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
mhz = 40;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
mhz = 80;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
mhz = 160;
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
return -1;
|
||||
}
|
||||
return mhz;
|
||||
}
|
||||
|
||||
static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
|
||||
{
|
||||
return nl80211_chan_width_to_mhz(c->width);
|
||||
}
|
||||
|
||||
bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
u32 control_freq;
|
||||
u32 control_freq, oper_freq;
|
||||
int oper_width, control_width;
|
||||
|
||||
if (!chandef->chan)
|
||||
return false;
|
||||
@ -155,10 +208,6 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
|
||||
|
||||
switch (chandef->width) {
|
||||
case NL80211_CHAN_WIDTH_1:
|
||||
case NL80211_CHAN_WIDTH_2:
|
||||
case NL80211_CHAN_WIDTH_4:
|
||||
case NL80211_CHAN_WIDTH_8:
|
||||
case NL80211_CHAN_WIDTH_16:
|
||||
case NL80211_CHAN_WIDTH_5:
|
||||
case NL80211_CHAN_WIDTH_10:
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
@ -169,6 +218,30 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
|
||||
if (chandef->center_freq2)
|
||||
return false;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_2:
|
||||
case NL80211_CHAN_WIDTH_4:
|
||||
case NL80211_CHAN_WIDTH_8:
|
||||
case NL80211_CHAN_WIDTH_16:
|
||||
control_freq = ieee80211_channel_to_khz(chandef->chan);
|
||||
oper_freq = ieee80211_chandef_to_khz(chandef);
|
||||
control_width = nl80211_chan_width_to_mhz(
|
||||
ieee80211_s1g_channel_width(
|
||||
chandef->chan));
|
||||
oper_width = cfg80211_chandef_get_width(chandef);
|
||||
|
||||
if (oper_width < 0 || control_width < 0)
|
||||
return false;
|
||||
if (chandef->center_freq2)
|
||||
return false;
|
||||
|
||||
if (control_freq + MHZ_TO_KHZ(control_width) / 2 >
|
||||
oper_freq + MHZ_TO_KHZ(oper_width) / 2)
|
||||
return false;
|
||||
|
||||
if (control_freq - MHZ_TO_KHZ(control_width) / 2 <
|
||||
oper_freq - MHZ_TO_KHZ(oper_width) / 2)
|
||||
return false;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
if (chandef->center_freq1 != control_freq + 10 &&
|
||||
chandef->center_freq1 != control_freq - 10)
|
||||
@ -264,53 +337,6 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
|
||||
}
|
||||
}
|
||||
|
||||
static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
|
||||
{
|
||||
int width;
|
||||
|
||||
switch (c->width) {
|
||||
case NL80211_CHAN_WIDTH_1:
|
||||
width = 1;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_2:
|
||||
width = 2;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_4:
|
||||
width = 4;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_8:
|
||||
width = 8;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_16:
|
||||
width = 16;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_5:
|
||||
width = 5;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_10:
|
||||
width = 10;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
width = 20;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
width = 40;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
width = 80;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
width = 160;
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
return -1;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
const struct cfg80211_chan_def *
|
||||
cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
|
||||
const struct cfg80211_chan_def *c2)
|
||||
|
@ -26,8 +26,6 @@
|
||||
|
||||
#include <net/lib80211.h>
|
||||
|
||||
#define DRV_NAME "lib80211"
|
||||
|
||||
#define DRV_DESCRIPTION "common routines for IEEE802.11 drivers"
|
||||
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
|
@ -209,14 +209,23 @@ static int validate_beacon_head(const struct nlattr *attr,
|
||||
unsigned int len = nla_len(attr);
|
||||
const struct element *elem;
|
||||
const struct ieee80211_mgmt *mgmt = (void *)data;
|
||||
unsigned int fixedlen = offsetof(struct ieee80211_mgmt,
|
||||
u.beacon.variable);
|
||||
bool s1g_bcn = ieee80211_is_s1g_beacon(mgmt->frame_control);
|
||||
unsigned int fixedlen, hdrlen;
|
||||
|
||||
if (s1g_bcn) {
|
||||
fixedlen = offsetof(struct ieee80211_ext,
|
||||
u.s1g_beacon.variable);
|
||||
hdrlen = offsetof(struct ieee80211_ext, u.s1g_beacon);
|
||||
} else {
|
||||
fixedlen = offsetof(struct ieee80211_mgmt,
|
||||
u.beacon.variable);
|
||||
hdrlen = offsetof(struct ieee80211_mgmt, u.beacon);
|
||||
}
|
||||
|
||||
if (len < fixedlen)
|
||||
goto err;
|
||||
|
||||
if (ieee80211_hdrlen(mgmt->frame_control) !=
|
||||
offsetof(struct ieee80211_mgmt, u.beacon))
|
||||
if (ieee80211_hdrlen(mgmt->frame_control) != hdrlen)
|
||||
goto err;
|
||||
|
||||
data += fixedlen;
|
||||
@ -367,6 +376,22 @@ nl80211_tid_config_attr_policy[NL80211_TID_CONFIG_ATTR_MAX + 1] = {
|
||||
NLA_POLICY_NESTED(nl80211_txattr_policy),
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
nl80211_fils_discovery_policy[NL80211_FILS_DISCOVERY_ATTR_MAX + 1] = {
|
||||
[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] = NLA_POLICY_MAX(NLA_U32, 10000),
|
||||
[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] = NLA_POLICY_MAX(NLA_U32, 10000),
|
||||
NLA_POLICY_RANGE(NLA_BINARY,
|
||||
NL80211_FILS_DISCOVERY_TMPL_MIN_LEN,
|
||||
IEEE80211_MAX_DATA_LEN),
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
nl80211_unsol_bcast_probe_resp_policy[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1] = {
|
||||
[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] = NLA_POLICY_MAX(NLA_U32, 20),
|
||||
[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_MAX_DATA_LEN }
|
||||
};
|
||||
|
||||
static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
||||
[0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
|
||||
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
|
||||
@ -675,6 +700,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
||||
[NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED },
|
||||
[NL80211_ATTR_HE_6GHZ_CAPABILITY] =
|
||||
NLA_POLICY_EXACT_LEN(sizeof(struct ieee80211_he_6ghz_capa)),
|
||||
[NL80211_ATTR_FILS_DISCOVERY] =
|
||||
NLA_POLICY_NESTED(nl80211_fils_discovery_policy),
|
||||
[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
|
||||
NLA_POLICY_NESTED(nl80211_unsol_bcast_probe_resp_policy),
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
@ -1010,6 +1039,21 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
|
||||
if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
|
||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
|
||||
goto nla_put_failure;
|
||||
if ((chan->flags & IEEE80211_CHAN_1MHZ) &&
|
||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_1MHZ))
|
||||
goto nla_put_failure;
|
||||
if ((chan->flags & IEEE80211_CHAN_2MHZ) &&
|
||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_2MHZ))
|
||||
goto nla_put_failure;
|
||||
if ((chan->flags & IEEE80211_CHAN_4MHZ) &&
|
||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_4MHZ))
|
||||
goto nla_put_failure;
|
||||
if ((chan->flags & IEEE80211_CHAN_8MHZ) &&
|
||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_8MHZ))
|
||||
goto nla_put_failure;
|
||||
if ((chan->flags & IEEE80211_CHAN_16MHZ) &&
|
||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
|
||||
@ -4850,6 +4894,65 @@ static int nl80211_parse_he_bss_color(struct nlattr *attrs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
|
||||
struct nlattr *attrs,
|
||||
struct cfg80211_ap_settings *params)
|
||||
{
|
||||
struct nlattr *tb[NL80211_FILS_DISCOVERY_ATTR_MAX + 1];
|
||||
int ret;
|
||||
struct cfg80211_fils_discovery *fd = ¶ms->fils_discovery;
|
||||
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_FILS_DISCOVERY))
|
||||
return -EINVAL;
|
||||
|
||||
ret = nla_parse_nested(tb, NL80211_FILS_DISCOVERY_ATTR_MAX, attrs,
|
||||
NULL, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] ||
|
||||
!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] ||
|
||||
!tb[NL80211_FILS_DISCOVERY_ATTR_TMPL])
|
||||
return -EINVAL;
|
||||
|
||||
fd->tmpl_len = nla_len(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
|
||||
fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
|
||||
fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
|
||||
fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev,
|
||||
struct nlattr *attrs,
|
||||
struct cfg80211_ap_settings *params)
|
||||
{
|
||||
struct nlattr *tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1];
|
||||
int ret;
|
||||
struct cfg80211_unsol_bcast_probe_resp *presp =
|
||||
¶ms->unsol_bcast_probe_resp;
|
||||
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP))
|
||||
return -EINVAL;
|
||||
|
||||
ret = nla_parse_nested(tb, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX,
|
||||
attrs, NULL, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] ||
|
||||
!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL])
|
||||
return -EINVAL;
|
||||
|
||||
presp->tmpl = nla_data(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
|
||||
presp->tmpl_len = nla_len(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
|
||||
presp->interval = nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
|
||||
const u8 *rates)
|
||||
{
|
||||
@ -5158,6 +5261,22 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
|
||||
err = nl80211_parse_fils_discovery(rdev,
|
||||
info->attrs[NL80211_ATTR_FILS_DISCOVERY],
|
||||
¶ms);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
|
||||
err = nl80211_parse_unsol_bcast_probe_resp(
|
||||
rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
|
||||
¶ms);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
nl80211_calculate_ap_params(¶ms);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
|
||||
|
@ -1617,9 +1617,11 @@ __freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
|
||||
{
|
||||
const struct ieee80211_regdomain *regd = reg_get_regdomain(wiphy);
|
||||
const struct ieee80211_reg_rule *reg_rule = NULL;
|
||||
const u32 bws[] = {0, 1, 2, 4, 5, 8, 10, 16, 20};
|
||||
int i = ARRAY_SIZE(bws) - 1;
|
||||
u32 bw;
|
||||
|
||||
for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
|
||||
for (bw = MHZ_TO_KHZ(bws[i]); bw >= min_bw; bw = MHZ_TO_KHZ(bws[i--])) {
|
||||
reg_rule = freq_reg_info_regd(center_freq, regd, bw);
|
||||
if (!IS_ERR(reg_rule))
|
||||
return reg_rule;
|
||||
@ -1631,7 +1633,9 @@ __freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
|
||||
const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
|
||||
u32 center_freq)
|
||||
{
|
||||
return __freq_reg_info(wiphy, center_freq, MHZ_TO_KHZ(20));
|
||||
u32 min_bw = center_freq < MHZ_TO_KHZ(1000) ? 1 : 20;
|
||||
|
||||
return __freq_reg_info(wiphy, center_freq, MHZ_TO_KHZ(min_bw));
|
||||
}
|
||||
EXPORT_SYMBOL(freq_reg_info);
|
||||
|
||||
@ -1659,6 +1663,7 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
|
||||
{
|
||||
const struct ieee80211_freq_range *freq_range = NULL;
|
||||
u32 max_bandwidth_khz, center_freq_khz, bw_flags = 0;
|
||||
bool is_s1g = chan->band == NL80211_BAND_S1GHZ;
|
||||
|
||||
freq_range = ®_rule->freq_range;
|
||||
|
||||
@ -1678,16 +1683,57 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
|
||||
MHZ_TO_KHZ(20)))
|
||||
bw_flags |= IEEE80211_CHAN_NO_20MHZ;
|
||||
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(10))
|
||||
bw_flags |= IEEE80211_CHAN_NO_10MHZ;
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(20))
|
||||
bw_flags |= IEEE80211_CHAN_NO_20MHZ;
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(40))
|
||||
bw_flags |= IEEE80211_CHAN_NO_HT40;
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(80))
|
||||
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
|
||||
bw_flags |= IEEE80211_CHAN_NO_160MHZ;
|
||||
if (is_s1g) {
|
||||
/* S1G is strict about non overlapping channels. We can
|
||||
* calculate which bandwidth is allowed per channel by finding
|
||||
* the largest bandwidth which cleanly divides the freq_range.
|
||||
*/
|
||||
int edge_offset;
|
||||
int ch_bw = max_bandwidth_khz;
|
||||
|
||||
while (ch_bw) {
|
||||
edge_offset = (center_freq_khz - ch_bw / 2) -
|
||||
freq_range->start_freq_khz;
|
||||
if (edge_offset % ch_bw == 0) {
|
||||
switch (KHZ_TO_MHZ(ch_bw)) {
|
||||
case 1:
|
||||
bw_flags |= IEEE80211_CHAN_1MHZ;
|
||||
break;
|
||||
case 2:
|
||||
bw_flags |= IEEE80211_CHAN_2MHZ;
|
||||
break;
|
||||
case 4:
|
||||
bw_flags |= IEEE80211_CHAN_4MHZ;
|
||||
break;
|
||||
case 8:
|
||||
bw_flags |= IEEE80211_CHAN_8MHZ;
|
||||
break;
|
||||
case 16:
|
||||
bw_flags |= IEEE80211_CHAN_16MHZ;
|
||||
break;
|
||||
default:
|
||||
/* If we got here, no bandwidths fit on
|
||||
* this frequency, ie. band edge.
|
||||
*/
|
||||
bw_flags |= IEEE80211_CHAN_DISABLED;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ch_bw /= 2;
|
||||
}
|
||||
} else {
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(10))
|
||||
bw_flags |= IEEE80211_CHAN_NO_10MHZ;
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(20))
|
||||
bw_flags |= IEEE80211_CHAN_NO_20MHZ;
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(40))
|
||||
bw_flags |= IEEE80211_CHAN_NO_HT40;
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(80))
|
||||
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
|
||||
bw_flags |= IEEE80211_CHAN_NO_160MHZ;
|
||||
}
|
||||
return bw_flags;
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,33 @@ u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_channel_to_freq_khz);
|
||||
|
||||
enum nl80211_chan_width
|
||||
ieee80211_s1g_channel_width(const struct ieee80211_channel *chan)
|
||||
{
|
||||
if (WARN_ON(!chan || chan->band != NL80211_BAND_S1GHZ))
|
||||
return NL80211_CHAN_WIDTH_20_NOHT;
|
||||
|
||||
/*S1G defines a single allowed channel width per channel.
|
||||
* Extract that width here.
|
||||
*/
|
||||
if (chan->flags & IEEE80211_CHAN_1MHZ)
|
||||
return NL80211_CHAN_WIDTH_1;
|
||||
else if (chan->flags & IEEE80211_CHAN_2MHZ)
|
||||
return NL80211_CHAN_WIDTH_2;
|
||||
else if (chan->flags & IEEE80211_CHAN_4MHZ)
|
||||
return NL80211_CHAN_WIDTH_4;
|
||||
else if (chan->flags & IEEE80211_CHAN_8MHZ)
|
||||
return NL80211_CHAN_WIDTH_8;
|
||||
else if (chan->flags & IEEE80211_CHAN_16MHZ)
|
||||
return NL80211_CHAN_WIDTH_16;
|
||||
|
||||
pr_err("unknown channel width for channel at %dKHz?\n",
|
||||
ieee80211_channel_to_khz(chan));
|
||||
|
||||
return NL80211_CHAN_WIDTH_1;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_s1g_channel_width);
|
||||
|
||||
int ieee80211_freq_khz_to_channel(u32 freq)
|
||||
{
|
||||
/* TODO: just handle MHz for now */
|
||||
@ -399,6 +426,11 @@ unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc)
|
||||
{
|
||||
unsigned int hdrlen = 24;
|
||||
|
||||
if (ieee80211_is_ext(fc)) {
|
||||
hdrlen = 4;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ieee80211_is_data(fc)) {
|
||||
if (ieee80211_has_a4(fc))
|
||||
hdrlen = 30;
|
||||
|
Loading…
Reference in New Issue
Block a user