mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 01:41:24 +00:00
This series is based on * 2020-07-10 ipq6018-ilq-11-0_qca_oem-034672b0676c37b1f4519e5720e18e95fe6236ef Add support for * qsdk kernel/v4.4 * qsdk ethernet subsystem * v5.7 ath11k backport + QualComm staging patches (wlan_ap_1.0) * ath11k-firmware * hostapd/iw/... Feature support * full boot, system detection * sysupgrade to nand * HE support via latest hostapd * driver support for usb, crypto, hwmon, cpufreq, ... Missing * NSS/HW flow offloading - FW blob is not redistributable Using the qsdk v4.4 is an intermediate solution while the vanilla is being tested. Vanilla kernel is almost on feature par. Work has already started to upstream the ethernet and switch drivers. Once complete the target will be fully upstream. Signed-off-by: John Crispin <john@phrozen.org>
584 lines
18 KiB
Diff
584 lines
18 KiB
Diff
From a9098659ead1f0ae630e9dfc231659ba99f024dd Mon Sep 17 00:00:00 2001
|
|
From: Seevalamuthu Mariappan <seevalam@codeaurora.org>
|
|
Date: Mon, 15 Jun 2020 12:50:31 +0530
|
|
Subject: [PATCH 2/2] ath11k: Add Dynamic VLAN support
|
|
|
|
Dynamic VLAN offload implementation relies on multiple group key encryption
|
|
support in hardware. Driver should advertise IEEE80211_HW_VLAN_CRYPTO_ENABLE
|
|
flag to mac80211 about VLAN group crypto support in hardware. Also, driver
|
|
should advertise NL80211_EXT_FEATURE_VLAN_OFFLOAD to enable vlan offload in
|
|
hostapd. Group Key for multiple vlan interfaces are configured with the help
|
|
of group key index as the hardware uses this index to get the corresponding
|
|
group key during transmission. Each AP-VLAN interface chose unique group key
|
|
index and the same group key will be sent in htt meta data info in dp_tx. Set
|
|
exception to fw flag in tx meta data flags. This group key index shall be
|
|
configured in meta data info only for VLAN group traffic.
|
|
|
|
Currently, the firmware supports upto 128 group keys for an AP interface.
|
|
The multiple group key support can be enabled during resource config.
|
|
|
|
Signed-off-by: Seevalamuthu Mariappan <seevalam@codeaurora.org>
|
|
---
|
|
drivers/net/wireless/ath/ath11k/core.h | 7 ++
|
|
drivers/net/wireless/ath/ath11k/dp_tx.c | 67 ++++++++++-
|
|
drivers/net/wireless/ath/ath11k/dp_tx.h | 198 ++++++++++++++++++++++++++++++++
|
|
drivers/net/wireless/ath/ath11k/mac.c | 76 ++++++++++++
|
|
drivers/net/wireless/ath/ath11k/wmi.c | 3 +
|
|
drivers/net/wireless/ath/ath11k/wmi.h | 2 +
|
|
6 files changed, 352 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
|
|
index 49b0a9d..6699491 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -67,6 +67,11 @@ enum ath11k_crypt_mode {
|
|
ATH11K_CRYPT_MODE_SW,
|
|
};
|
|
|
|
+#define ATH11K_GROUP_KEYS_NUM_MAX 128
|
|
+#define ATH11K_FREE_GROUP_IDX_MAP_BITS 32
|
|
+#define ATH11K_FREE_GROUP_IDX_MAP_MAX (ATH11K_GROUP_KEYS_NUM_MAX / \
|
|
+ ATH11K_FREE_GROUP_IDX_MAP_BITS)
|
|
+
|
|
static inline enum wme_ac ath11k_tid_to_ac(u32 tid)
|
|
{
|
|
return (((tid == 0) || (tid == 3)) ? WME_AC_BE :
|
|
@@ -248,6 +253,8 @@ struct ath11k_vif {
|
|
int txpower;
|
|
struct dentry *debugfs_twt;
|
|
struct ath11k_mgmt_frame_stats mgmt_stats;
|
|
+ u16 *vlan_keyid_map;
|
|
+ DECLARE_BITMAP(free_groupidx_map, ATH11K_GROUP_KEYS_NUM_MAX);
|
|
};
|
|
|
|
struct ath11k_vif_iter {
|
|
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
|
|
index ba6cdd9..1549dc0 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
|
|
@@ -76,6 +76,34 @@ enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher)
|
|
}
|
|
}
|
|
|
|
+#define HTT_META_DATA_ALIGNMENT 0x8
|
|
+
|
|
+static int ath11k_dp_prepare_htt_metadata(struct sk_buff *skb,
|
|
+ u8 group_key_idx,
|
|
+ u8 *htt_metadata_size)
|
|
+{
|
|
+ u8 htt_desc_size;
|
|
+ /* Size rounded of multiple of 8 bytes */
|
|
+ u8 htt_desc_size_aligned;
|
|
+ struct htt_tx_msdu_desc_ext *desc_ext;
|
|
+
|
|
+ htt_desc_size = sizeof(struct htt_tx_msdu_desc_ext);
|
|
+ htt_desc_size_aligned = ALIGN(htt_desc_size, HTT_META_DATA_ALIGNMENT);
|
|
+
|
|
+ if (skb_headroom(skb) < htt_desc_size_aligned)
|
|
+ if (pskb_expand_head(skb, htt_desc_size_aligned, 0, GFP_ATOMIC))
|
|
+ return -ENOMEM;
|
|
+
|
|
+ skb_push(skb, htt_desc_size_aligned);
|
|
+ memset(skb->data, 0, htt_desc_size_aligned);
|
|
+ desc_ext = (struct htt_tx_msdu_desc_ext *)skb->data;
|
|
+ desc_ext->valid_key_flags = 1;
|
|
+ desc_ext->key_flags = group_key_idx;
|
|
+ *htt_metadata_size = htt_desc_size_aligned;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
|
struct sk_buff *skb)
|
|
{
|
|
@@ -86,6 +114,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
|
struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
|
|
struct hal_srng *tcl_ring;
|
|
struct ieee80211_hdr *hdr = (void *)skb->data;
|
|
+ struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
|
|
struct dp_tx_ring *tx_ring;
|
|
void *hal_tcl_desc;
|
|
u8 pool_id;
|
|
@@ -93,6 +122,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
|
int ret;
|
|
u8 ring_selector = 0, ring_map = 0;
|
|
bool tcl_ring_retry;
|
|
+ u8 align_pad, htt_meta_size = 0;
|
|
+ bool multicast;
|
|
|
|
if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
|
|
return -ESHUTDOWN;
|
|
@@ -197,6 +228,38 @@ tcl_ring_sel:
|
|
goto fail_remove_idr;
|
|
}
|
|
|
|
+ if (ti.encap_type == HAL_TCL_ENCAP_TYPE_ETHERNET)
|
|
+ multicast = is_multicast_ether_addr(ethhdr->h_dest);
|
|
+ else
|
|
+ multicast = is_multicast_ether_addr(hdr->addr1);
|
|
+
|
|
+ if (multicast && info->control.hw_key && info->control.hw_key->vlan_id) {
|
|
+ /* HW requirement is that metadata should always point to a
|
|
+ * 8-byte aligned address. So we add alignment pad to start of
|
|
+ * buffer. HTT Metadata should be ensured to be multiple of 8-bytes
|
|
+ * to get 8-byte aligned start address along with align_pad added
|
|
+ */
|
|
+
|
|
+ align_pad = ((unsigned long)skb->data) & (HTT_META_DATA_ALIGNMENT - 1);
|
|
+ if (skb_headroom(skb) < align_pad) {
|
|
+ if (pskb_expand_head(skb, align_pad, 0, GFP_ATOMIC)) {
|
|
+ ret = -ENOMEM;
|
|
+ goto fail_remove_idr;
|
|
+ }
|
|
+ }
|
|
+ skb_push(skb, align_pad);
|
|
+ ti.pkt_offset += align_pad;
|
|
+ memset(skb->data, 0, align_pad);
|
|
+ ret = ath11k_dp_prepare_htt_metadata(skb,
|
|
+ info->control.hw_key->hw_key_idx, &htt_meta_size);
|
|
+ if (ret)
|
|
+ goto fail_remove_idr;
|
|
+
|
|
+ ti.pkt_offset += htt_meta_size;
|
|
+ ti.meta_data_flags |= HTT_TCL_META_DATA_VALID_HTT;
|
|
+ ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_TO_FW, 1);
|
|
+ }
|
|
+
|
|
ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
|
|
if (dma_mapping_error(ab->dev, ti.paddr)) {
|
|
atomic_inc(&ab->soc_stats.tx_err.misc_fail);
|
|
@@ -205,7 +268,7 @@ tcl_ring_sel:
|
|
goto fail_remove_idr;
|
|
}
|
|
|
|
- ti.data_len = skb->len;
|
|
+ ti.data_len = skb->len - ti.pkt_offset;
|
|
skb_cb->paddr = ti.paddr;
|
|
skb_cb->vif = arvif->vif;
|
|
skb_cb->ar = ar;
|
|
@@ -258,6 +321,8 @@ fail_unmap_dma:
|
|
dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
|
|
|
|
fail_remove_idr:
|
|
+ if (ti.pkt_offset)
|
|
+ skb_pull(skb, ti.pkt_offset);
|
|
spin_lock_bh(&tx_ring->tx_idr_lock);
|
|
idr_remove(&tx_ring->txbuf_idr,
|
|
FIELD_GET(DP_TX_DESC_ID_MSDU_ID, ti.desc_id));
|
|
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.h b/drivers/net/wireless/ath/ath11k/dp_tx.h
|
|
index f8a9f9c..a5f0dfd 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/dp_tx.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.h
|
|
@@ -15,6 +15,204 @@ struct ath11k_dp_htt_wbm_tx_status {
|
|
int ack_rssi;
|
|
};
|
|
|
|
+/* htt_tx_msdu_desc_ext
|
|
+ *
|
|
+ * valid_pwr
|
|
+ * if set, tx pwr spec is valid
|
|
+ *
|
|
+ * valid_mcs_mask
|
|
+ * if set, tx MCS mask is valid
|
|
+ *
|
|
+ * valid_nss_mask
|
|
+ * if set, tx Nss mask is valid
|
|
+ *
|
|
+ * valid_preamble_type
|
|
+ * if set, tx preamble spec is valid
|
|
+ *
|
|
+ * valid_retries
|
|
+ * if set, tx retries spec is valid
|
|
+ *
|
|
+ * valid_bw_info
|
|
+ * if set, tx dyn_bw and bw_mask are valid
|
|
+ *
|
|
+ * valid_guard_interval
|
|
+ * if set, tx guard intv spec is valid
|
|
+ *
|
|
+ * valid_chainmask
|
|
+ * if set, tx chainmask is valid
|
|
+ *
|
|
+ * valid_encrypt_type
|
|
+ * if set, encrypt type is valid
|
|
+ *
|
|
+ * valid_key_flags
|
|
+ * if set, key flags is valid
|
|
+ *
|
|
+ * valid_expire_tsf
|
|
+ * if set, tx expire TSF spec is valid
|
|
+ *
|
|
+ * valid_chanfreq
|
|
+ * if set, chanfreq is valid
|
|
+ *
|
|
+ * is_dsrc
|
|
+ * if set, MSDU is a DSRC frame
|
|
+ *
|
|
+ * guard_interval
|
|
+ * 0.4us, 0.8us, 1.6us, 3.2us
|
|
+ *
|
|
+ * encrypt_type
|
|
+ * 0 = NO_ENCRYPT,
|
|
+ * 1 = ENCRYPT,
|
|
+ * 2 ~ 3 - Reserved
|
|
+ *
|
|
+ * retry_limit
|
|
+ * Specify the maximum number of transmissions, including the
|
|
+ * initial transmission, to attempt before giving up if no ack
|
|
+ * is received.
|
|
+ * If the tx rate is specified, then all retries shall use the
|
|
+ * same rate as the initial transmission.
|
|
+ * If no tx rate is specified, the target can choose whether to
|
|
+ * retain the original rate during the retransmissions, or to
|
|
+ * fall back to a more robust rate.
|
|
+ *
|
|
+ * use_dcm_11ax
|
|
+ * If set, Use Dual subcarrier modulation.
|
|
+ * Valid only for 11ax preamble types HE_SU
|
|
+ * and HE_EXT_SU
|
|
+ *
|
|
+ * ltf_subtype_11ax
|
|
+ * Takes enum values of htt_11ax_ltf_subtype_t
|
|
+ * Valid only for 11ax preamble types HE_SU
|
|
+ * and HE_EXT_SU
|
|
+ *
|
|
+ * dyn_bw
|
|
+ * 0 = static bw, 1 = dynamic bw
|
|
+ *
|
|
+ * bw_mask
|
|
+ * Valid only if dyn_bw == 0 (static bw).
|
|
+ *
|
|
+ * host_tx_desc_pool
|
|
+ * If set, Firmware allocates tx_descriptors
|
|
+ * in WAL_BUFFERID_TX_HOST_DATA_EXP,instead
|
|
+ * of WAL_BUFFERID_TX_TCL_DATA_EXP.
|
|
+ * Use cases:
|
|
+ * Any time firmware uses TQM-BYPASS for Data
|
|
+ * TID, firmware expect host to set this bit.
|
|
+ *
|
|
+ * power
|
|
+ * unit of the power field is 0.5 dbm
|
|
+ * signed value ranging from -64dbm to 63.5 dbm
|
|
+ *
|
|
+ * mcs_mask
|
|
+ * mcs bit mask of 0 ~ 11
|
|
+ * Setting more than one MCS isn't currently
|
|
+ * supported by the target (but is supported
|
|
+ * in the interface in case in the future
|
|
+ * the target supports specifications of
|
|
+ * a limited set of MCS values.
|
|
+ *
|
|
+ * nss_mask
|
|
+ * Nss bit mask 0 ~ 7
|
|
+ * Setting more than one Nss isn't currently
|
|
+ * supported by the target (but is supported
|
|
+ * in the interface in case in the future
|
|
+ * the target supports specifications of
|
|
+ * a limited set of Nss values.
|
|
+ *
|
|
+ * pream_type
|
|
+ * Preamble types
|
|
+ *
|
|
+ * update_peer_cache
|
|
+ * When set these custom values will be
|
|
+ * used for all packets, until the next
|
|
+ * update via this ext header.
|
|
+ * This is to make sure not all packets
|
|
+ * need to include this header.
|
|
+ *
|
|
+ * chain_mask
|
|
+ * specify which chains to transmit from
|
|
+ *
|
|
+ * key_flags
|
|
+ * Key Index and related flags - used in mesh mode
|
|
+ *
|
|
+ * chanfreq
|
|
+ * Channel frequency: This identifies the desired channel
|
|
+ * frequency (in MHz) for tx frames. This is used by FW to help
|
|
+ * determine when it is safe to transmit or drop frames for
|
|
+ * off-channel operation.
|
|
+ * The default value of zero indicates to FW that the corresponding
|
|
+ * VDEV's home channel (if there is one) is the desired channel
|
|
+ * frequency.
|
|
+ *
|
|
+ * expire_tsf_lo
|
|
+ * tx expiry time (TSF) LSBs
|
|
+ *
|
|
+ * expire_tsf_hi
|
|
+ * tx expiry time (TSF) MSBs
|
|
+ *
|
|
+ * learning_frame
|
|
+ * When this flag is set, this frame will be dropped by FW
|
|
+ * rather than being enqueued to the Transmit Queue Manager (TQM) HW.
|
|
+ *
|
|
+ * send_as_standalone
|
|
+ * This will indicate if the msdu needs to be sent as a singleton PPDU,
|
|
+ * i.e. with no A-MSDU or A-MPDU aggregation.
|
|
+ * The scope is extended to other use-cases.
|
|
+ *
|
|
+ * is_host_opaque_valid
|
|
+ * set this bit to 1 if the host_opaque_cookie is populated
|
|
+ * with valid information.
|
|
+ *
|
|
+ * host_opaque_cookie
|
|
+ * Host opaque cookie for special frames
|
|
+ */
|
|
+
|
|
+struct htt_tx_msdu_desc_ext {
|
|
+ u32
|
|
+ valid_pwr : 1,
|
|
+ valid_mcs_mask : 1,
|
|
+ valid_nss_mask : 1,
|
|
+ valid_preamble_type : 1,
|
|
+ valid_retries : 1,
|
|
+ valid_bw_info : 1,
|
|
+ valid_guard_interval : 1,
|
|
+ valid_chainmask : 1,
|
|
+ valid_encrypt_type : 1,
|
|
+ valid_key_flags : 1,
|
|
+ valid_expire_tsf : 1,
|
|
+ valid_chanfreq : 1,
|
|
+ is_dsrc : 1,
|
|
+ guard_interval : 2,
|
|
+ encrypt_type : 2,
|
|
+ retry_limit : 4,
|
|
+ use_dcm_11ax : 1,
|
|
+ ltf_subtype_11ax : 2,
|
|
+ dyn_bw : 1,
|
|
+ bw_mask : 6,
|
|
+ host_tx_desc_pool : 1;
|
|
+ u32
|
|
+ power : 8,
|
|
+ mcs_mask : 12,
|
|
+ nss_mask : 8,
|
|
+ pream_type : 3,
|
|
+ update_peer_cache : 1;
|
|
+ u32
|
|
+ chain_mask : 8,
|
|
+ key_flags : 8,
|
|
+ chanfreq : 16;
|
|
+
|
|
+ u32 expire_tsf_lo;
|
|
+ u32 expire_tsf_hi;
|
|
+
|
|
+ u32
|
|
+ learning_frame : 1,
|
|
+ send_as_standalone : 1,
|
|
+ is_host_opaque_valid : 1,
|
|
+ rsvd0 : 29;
|
|
+ u32
|
|
+ host_opaque_cookie : 16,
|
|
+ rsvd1 : 16;
|
|
+} __packed;
|
|
+
|
|
int ath11k_dp_tx_htt_h2t_ver_req_msg(struct ath11k_base *ab);
|
|
int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
|
struct sk_buff *skb);
|
|
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
|
|
index bc007d8..eac1f73 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -2897,6 +2897,9 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
|
|
if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
|
|
return 0;
|
|
|
|
+ if (key->vlan_id)
|
|
+ arg.group_key_idx = key->hw_key_idx;
|
|
+
|
|
if (cmd == DISABLE_KEY) {
|
|
/* TODO: Check if FW expects value other than NONE for del */
|
|
/* arg.key_cipher = WMI_CIPHER_NONE; */
|
|
@@ -2988,6 +2991,27 @@ static int ath11k_clear_peer_keys(struct ath11k_vif *arvif,
|
|
return first_errno;
|
|
}
|
|
|
|
+static int ath11k_get_vlan_groupkey_index(struct ath11k_vif *arvif,
|
|
+ struct ieee80211_key_conf *key)
|
|
+{
|
|
+ int map_idx = 0;
|
|
+ int free_bit;
|
|
+
|
|
+ for (map_idx = 0; map_idx < ATH11K_FREE_GROUP_IDX_MAP_MAX; map_idx++)
|
|
+ if (arvif->free_groupidx_map[map_idx] != 0)
|
|
+ break;
|
|
+
|
|
+ if (map_idx == ATH11K_FREE_GROUP_IDX_MAP_MAX)
|
|
+ return -ENOSPC;
|
|
+
|
|
+ /* select the first free key index */
|
|
+ free_bit = __ffs64(arvif->free_groupidx_map[map_idx]);
|
|
+ key->hw_key_idx = (map_idx * ATH11K_FREE_GROUP_IDX_MAP_BITS) + free_bit;
|
|
+ /* clear the selected bit from free index map */
|
|
+ clear_bit(key->hw_key_idx, arvif->free_groupidx_map);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
|
struct ieee80211_key_conf *key)
|
|
@@ -3046,6 +3070,36 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
}
|
|
}
|
|
|
|
+ if (key->vlan_id && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
|
+ key->hw_key_idx = arvif->vlan_keyid_map[key->vlan_id];
|
|
+ switch (cmd) {
|
|
+ case SET_KEY:
|
|
+ /* If the group key idx is already available,
|
|
+ * no need to find the free index again.
|
|
+ * This happens during GTK rekey. It uses
|
|
+ * the same index after rekey also.
|
|
+ */
|
|
+ if (!key->hw_key_idx)
|
|
+ ret = ath11k_get_vlan_groupkey_index(arvif, key);
|
|
+ break;
|
|
+ case DISABLE_KEY:
|
|
+ /* If the group key idx is already 0,
|
|
+ * no need of freeing the index.
|
|
+ */
|
|
+ if (key->hw_key_idx)
|
|
+ /* make the group index as available */
|
|
+ set_bit(key->hw_key_idx, arvif->free_groupidx_map);
|
|
+ break;
|
|
+ default:
|
|
+ ret = -EINVAL;
|
|
+ }
|
|
+ if (ret) {
|
|
+ ath11k_warn(ab, "failed to set group key index for vlan %u : %d\n",
|
|
+ key->vlan_id, ret);
|
|
+ goto exit;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
|
|
flags |= WMI_KEY_PAIRWISE;
|
|
else
|
|
@@ -3074,12 +3128,15 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
peer->mcast_keyidx = key->keyidx;
|
|
peer->sec_type_grp = ath11k_dp_tx_get_encrypt_type(key->cipher);
|
|
}
|
|
+ /* storing group key idx which will be used during rekey */
|
|
+ arvif->vlan_keyid_map[key->vlan_id] = key->hw_key_idx;
|
|
} else if (peer && cmd == DISABLE_KEY) {
|
|
peer->keys[key->keyidx] = NULL;
|
|
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
|
|
peer->ucast_keyidx = 0;
|
|
else
|
|
peer->mcast_keyidx = 0;
|
|
+ arvif->vlan_keyid_map[key->vlan_id] = 0;
|
|
} else if (!peer)
|
|
/* impossible unless FW goes crazy */
|
|
ath11k_warn(ab, "peer %pM disappeared!\n", peer_addr);
|
|
@@ -5012,6 +5069,18 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
|
arvif->vdev_id = bit;
|
|
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
|
|
|
|
+ /* Configure vlan specific parameters */
|
|
+ for (i = 0; i < ATH11K_FREE_GROUP_IDX_MAP_MAX; i++)
|
|
+ arvif->free_groupidx_map[i] = 0xFFFFFFFFL;
|
|
+ /* Group idx 0 is not valid for VLAN*/
|
|
+ arvif->free_groupidx_map[0] &= ~(1L);
|
|
+
|
|
+ arvif->vlan_keyid_map = kzalloc(VLAN_N_VID, GFP_KERNEL);
|
|
+ if (!arvif->vlan_keyid_map) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
switch (vif->type) {
|
|
case NL80211_IFTYPE_UNSPECIFIED:
|
|
case NL80211_IFTYPE_STATION:
|
|
@@ -5244,6 +5313,7 @@ err_vdev_del:
|
|
spin_unlock_bh(&ar->data_lock);
|
|
|
|
err:
|
|
+ kfree(arvif->vlan_keyid_map);
|
|
mutex_unlock(&ar->conf_mutex);
|
|
|
|
return ret;
|
|
@@ -5314,6 +5384,7 @@ err_vdev_del:
|
|
list_del(&arvif->list);
|
|
spin_unlock_bh(&ar->data_lock);
|
|
|
|
+ kfree(arvif->vlan_keyid_map);
|
|
ath11k_peer_cleanup(ar, arvif->vdev_id);
|
|
|
|
idr_for_each(&ar->txmgmt_idr,
|
|
@@ -7108,6 +7179,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
|
ieee80211_hw_set(ar->hw, SUPPORTS_AMSDU_IN_AMPDU);
|
|
ieee80211_hw_set(ar->hw, USES_RSS);
|
|
}
|
|
+ ieee80211_hw_set(ar->hw, VLAN_CRYPTO_CONTROL);
|
|
|
|
ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
|
|
ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
|
@@ -7152,6 +7224,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
|
|
|
wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
|
|
wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
|
|
+ wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VLAN_OFFLOAD);
|
|
|
|
if (test_bit(WMI_TLV_SERVICE_SCAN_PHYMODE_SUPPORT,
|
|
ar->ab->wmi_ab.svc_map))
|
|
@@ -7179,6 +7252,9 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
|
goto err_free;
|
|
}
|
|
|
|
+ ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
|
|
+ ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
|
|
+
|
|
/* Apply the regd received during initialization */
|
|
ret = ath11k_regd_update(ar, true);
|
|
if (ret) {
|
|
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
index e548fce..d1d4d7f 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -1804,6 +1804,7 @@ int ath11k_wmi_vdev_install_key(struct ath11k *ar,
|
|
cmd->key_len = arg->key_len;
|
|
cmd->key_txmic_len = arg->key_txmic_len;
|
|
cmd->key_rxmic_len = arg->key_rxmic_len;
|
|
+ cmd->group_key_id = arg->group_key_idx;
|
|
|
|
if (arg->key_rsc_counter)
|
|
memcpy(&cmd->key_rsc_counter, &arg->key_rsc_counter,
|
|
@@ -3465,6 +3466,7 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg,
|
|
wmi_cfg->sched_params = tg_cfg->sched_params;
|
|
wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count;
|
|
wmi_cfg->twt_ap_sta_count = tg_cfg->twt_ap_sta_count;
|
|
+ wmi_cfg->max_num_group_keys = tg_cfg->max_num_group_keys;
|
|
}
|
|
|
|
static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
|
|
@@ -3697,6 +3699,7 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
|
config.peer_map_unmap_v2_support = 1;
|
|
config.twt_ap_pdev_count = ab->num_radios;
|
|
config.twt_ap_sta_count = 1000;
|
|
+ config.max_num_group_keys = ATH11K_GROUP_KEYS_NUM_MAX;
|
|
|
|
memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config));
|
|
|
|
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
|
|
index 9d29ee2..c28fa30 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
|
@@ -3517,6 +3517,7 @@ struct wmi_vdev_install_key_arg {
|
|
u32 vdev_id;
|
|
const u8 *macaddr;
|
|
u32 key_idx;
|
|
+ u32 group_key_idx;
|
|
u32 key_flags;
|
|
u32 key_cipher;
|
|
u32 key_len;
|
|
@@ -5223,6 +5224,7 @@ struct target_resource_config {
|
|
u32 bpf_instruction_size;
|
|
u32 max_bssid_rx_filters;
|
|
u32 use_pdev_id;
|
|
+ u32 max_num_group_keys;
|
|
u32 peer_map_unmap_v2_support;
|
|
u32 sched_params;
|
|
u32 twt_ap_pdev_count;
|
|
--
|
|
2.7.4
|
|
|