ipq807x: tweak the AX wifi support

Fix some issues that showed up during testing. Wifi now also works
properly on cypress.

Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
John Crispin 2020-07-28 09:23:19 +02:00
parent 0a31c9f692
commit 03783d76cd
7 changed files with 86 additions and 796 deletions

View File

@ -45,8 +45,8 @@ define Package/ath11k-firmware-ipq60xx/install
$(INSTALL_DIR) $(1)/lib/firmware/IPQ6018
$(INSTALL_DATA) $(PKG_BUILD_DIR)/IPQ6018/hw1.0/2.1.0.1/WLAN.HK.2.1.0.1-01238-QCAHKSWPL_SILICONZ-2/* \
$(1)/lib/firmware/IPQ6018
$(INSTALL_DATA) $(PKG_BUILD_DIR)/IPQ6018/hw1.0/board-2.bin \
$(1)/lib/firmware/IPQ6018
# $(INSTALL_DATA) $(PKG_BUILD_DIR)/IPQ6018/hw1.0/board-2.bin \
# $(1)/lib/firmware/IPQ6018
endef
define Package/ath11k-firmware-ipq807x/install

View File

@ -0,0 +1,81 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/version.mk
PKG_NAME:=ath11k-wifi
PKG_RELEASE:=1
PKG_FLAGS:=nonshared
include $(INCLUDE_DIR)/package.mk
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
endef
define Build/Compile
endef
#
# This is intended to be used on an interim basis until device-specific
# board data for new devices is available through the upstream compilation
#
# Please send a mail with your device-specific board files upstream.
# You can find instructions and examples on the linux-wireless wiki:
# <https://wireless.wiki.kernel.org/en/users/drivers/ath10k/boardfiles>
#
ALLWIFIBOARDS:= \
cig-wf188
ALLWIFIPACKAGES:=$(foreach BOARD,$(ALLWIFIBOARDS),ath11k-wifi-$(BOARD))
define Package/ath11k-wifi-default
SUBMENU:=ath11k Board-Specific Overrides
SECTION:=firmware
CATEGORY:=Firmware
DEPENDS:=@TARGET_ipq807x
TITLE:=Custom Board
endef
define ath11k-wifi-install-one-to
$(INSTALL_DIR) $(2)/lib/firmware/$(3)/
$(INSTALL_DATA) $(1) $(2)/lib/firmware/$(3)/bdwlan.bin
endef
define ath11k-wifi-install-one
$(if $(filter $(suffix $(1)),.IPQ6018),\
$(call ath11k-wifi-install-one-to,$(1),$(2),IPQ6018),\
)
endef
# Blank line required at end of above define due to foreach context
define generate-ath11k-wifi-package
define Package/ath11k-wifi-$(1)
$(call Package/ath11k-wifi-default)
TITLE:=bdwlan.bin Overrides for $(2)
CONFLICTS:=$(PREV_BOARD)
endef
define Package/ath11k-wifi-$(1)/description
The $(2) requires board-specific, reference ("cal") data
that is not yet present in the upstream wireless firmware distribution.
This package supplies bdwlan.bin file(s) that, in the interim,
overwrite those supplied by the ath11k-firmware-* packages.
This is package is only necessary for the $(2).
Do not install it for any other device!
endef
define Package/ath11k-wifi-$(1)/install-overlay
$$$$(foreach ATH11K_WIFI_BOARD_FILE,$$$$(wildcard board-$(1).*),\
$$$$(call ath11k-wifi-install-one,$$$$(ATH11K_WIFI_BOARD_FILE),$$(1)))
endef
PREV_BOARD+=ath11k-wifi-$(1)
endef
$(eval $(call generate-ath11k-wifi-package,cig-wf188,Cigtech WF188))
$(foreach PACKAGE,$(ALLWIFIPACKAGES),$(eval $(call BuildPackage,$(PACKAGE))))

Binary file not shown.

View File

@ -136,8 +136,8 @@ hostapd_prepare_device_config() {
}
[ -n "$acs_chan_bias" ] && append base_cfg "acs_chan_bias=$acs_chan_bias" "$N"
append base_cfg "multiple_bssid=$multiple_bssid" "$N"
append base_cfg "rnr_beacon=$rnr_beacon" "$N"
#append base_cfg "multiple_bssid=$multiple_bssid" "$N"
#append base_cfg "rnr_beacon=$rnr_beacon" "$N"
local brlist= br
json_get_values basic_rate_list basic_rate

View File

@ -1384,13 +1384,6 @@ enum nl80211_commands {
NL80211_CMD_PROBE_MESH_LINK,
NL80211_CMD_OBSS_COLOR_COLLISION,
NL80211_CMD_COLOR_CHANGE,
NL80211_CMD_CCA_STARTED_NOTIFY,
NL80211_CMD_CCA_ABORTED_NOTIFY,
NL80211_CMD_CCA_NOTIFY,
NL80211_CMD_SET_TID_CONFIG,
NL80211_CMD_UNPROT_BEACON,
@ -2957,19 +2950,6 @@ enum nl80211_attrs {
NL80211_ATTR_HE_BSS_COLOR,
NL80211_ATTR_MULTI_BSSID_MODE,
NL80211_ATTR_MULTI_BSSID_PARENT,
NL80211_ATTR_MULTI_BSSID_INDEX,
NL80211_ATTR_MULTI_BSSID_COUNT,
NL80211_ATTR_OBSS_COLOR_BITMAP,
NL80211_ATTR_CCA_COUNT,
NL80211_ATTR_CCA_COLOR,
NL80211_ATTR_CCA_IES,
NL80211_ATTR_CCA_C_OFF_BEACON,
NL80211_ATTR_CCA_C_OFF_PRESP,
NL80211_ATTR_IFTYPE_AKM_SUITES,
NL80211_ATTR_TID_CONFIG,
@ -2981,7 +2961,6 @@ enum nl80211_attrs {
NL80211_ATTR_RECEIVE_MULTICAST,
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@ -2989,37 +2968,6 @@ enum nl80211_attrs {
NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
};
/**
* enum nl80211_multi_bssid_mode - Multiple BSSID beacon type
*
* Used by cfg80211_ap_settings
*
* @MULTIPLE_BSSID_LEGACY: This BSS is not part of a multiple BSSID group
* @MULTIPLE_BSSID_TRANSMITTED: This BSS is broadcasting a multiple BSSID
* beacon
* @MULTIPLE_BSSID_NON_TRANSMITTED: This BSS is not broadcasting a beacon
*/
enum nl80211_multi_bssid_mode {
NL80211_MULTIPLE_BSSID_LEGACY = 0,
NL80211_MULTIPLE_BSSID_TRANSMITTED,
NL80211_MULTIPLE_BSSID_NON_TRANSMITTED,
};
/**
* enum nl80211_beacon_tx_mode - Beacon tx mode settings
*
* @BEACON_TX_MODE_DEFAULT: The beacons shall be sent out in its default mode
* @BEACON_TX_MODE_STAGGERED: The beacons shall be sent out in staggered mode
* @BEACON_TX_MODE_BURST: The beacons shall be sent out in burst mode
* beacon
*/
enum nl80211_beacon_tx_mode {
NL80211_BEACON_TX_MODE_STAGGERED = 0,
NL80211_BEACON_TX_MODE_BURST,
};
/* source-level API compatibility */
#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
#define NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG
@ -5803,6 +5751,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_STA_TX_PWR,
NL80211_EXT_FEATURE_SAE_OFFLOAD,
NL80211_EXT_FEATURE_VLAN_OFFLOAD,
NL80211_EXT_FEATURE_WIDE_BAND_SCAN,
NL80211_EXT_FEATURE_AQL,
NL80211_EXT_FEATURE_BEACON_PROTECTION,
NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH,

View File

@ -1,157 +0,0 @@
From 0f581eec294296d42f1ada495c5846b4ec1546a4 Mon Sep 17 00:00:00 2001
From: Seevalamuthu Mariappan <seevalam@codeaurora.org>
Date: Mon, 15 Jun 2020 12:47:20 +0530
Subject: [PATCH 1/2] mac80211: Add GTK offload support for AP_VLAN
Current implementation does not support GTK encryption for VLAN interfaces
in driver/hardware since the driver is not aware AP-VLAN interfaces. This
patch adds feature flag to allow group key encryption in driver/hardware.
Drivers can identify VLAN interfaces from vlan_id in ieee80211_key_conf.
Signed-off-by: Seevalamuthu Mariappan <seevalam@codeaurora.org>
---
include/net/mac80211.h | 6 ++++++
net/mac80211/cfg.c | 1 +
net/mac80211/debugfs.c | 1 +
net/mac80211/iface.c | 8 +++++++-
net/mac80211/key.c | 3 ++-
net/mac80211/tx.c | 11 ++++++++++-
6 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index f4506ec..f87d7ac 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1773,6 +1773,7 @@ enum ieee80211_key_flags {
* - Temporal Authenticator Rx MIC Key (64 bits)
* @icv_len: The ICV length for this key type
* @iv_len: The IV length for this key type
+ * @vlan_id: For VLAN interfaces 1-4096, 0 for non-vlan interfaces
*/
struct ieee80211_key_conf {
atomic64_t tx_pn;
@@ -1783,6 +1784,7 @@ struct ieee80211_key_conf {
s8 keyidx;
u16 flags;
u8 keylen;
+ u16 vlan_id;
u8 key[0];
};
@@ -2308,6 +2310,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_VLAN_CRYPTO_CONTROL: The driver (or firmware) supports crypto
+ * algorithms for AP_VLAN interfaces
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -2360,6 +2365,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_MULTI_BSSID,
IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT,
+ IEEE80211_HW_VLAN_CRYPTO_CONTROL,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 64e807d..5e8f3a4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -460,6 +460,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_AP_VLAN:
+ key->conf.vlan_id = params->vlan_id;
/* Keys without a station are used for TX only */
if (sta && test_sta_flag(sta, WLAN_STA_MFP))
key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 2c2e07c..006afd1 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -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(VLAN_CRYPTO_CONTROL),
#undef FLAG
};
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index b2a2165..1f0822b 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -300,8 +300,14 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
* can only add VLANs to enabled APs
*/
if (iftype == NL80211_IFTYPE_AP_VLAN &&
- nsdata->vif.type == NL80211_IFTYPE_AP)
+ nsdata->vif.type == NL80211_IFTYPE_AP) {
+ if (ieee80211_hw_check(&local->hw, VLAN_CRYPTO_CONTROL) &&
+ nsdata->hw_80211_encap) {
+ sdata->dev->netdev_ops = nsdata->dev->netdev_ops;
+ sdata->hw_80211_encap = true;
+ }
sdata->bss = &nsdata->u.ap;
+ }
}
}
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 4b1c45b..96bed31 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -167,7 +167,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
goto out_unsupported;
sdata = key->sdata;
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+ if (!ieee80211_hw_check(&key->local->hw, VLAN_CRYPTO_CONTROL) &&
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
/*
* The driver doesn't know anything about VLAN interfaces.
* Hence, don't send GTKs for VLAN interfaces to the driver.
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index eed6b2c..e833cb8 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4184,6 +4184,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
bool authorized = false;
bool multicast;
unsigned char *ra = ehdr->h_dest;
+ struct ieee80211_key *key;
if (IS_ERR(sta) || (sta && !sta->uploaded))
sta = NULL;
@@ -4209,6 +4210,10 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
!atomic_read(&sdata->u.ap.num_mcast_sta))
goto out_free;
+ if (multicast && sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+ !atomic_read(&sdata->u.vlan.num_mcast_sta))
+ goto out_free;
+
if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
goto out_free;
@@ -4237,9 +4242,13 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
}
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+ if (multicast && ieee80211_hw_check(&local->hw, VLAN_CRYPTO_CONTROL) &&
+ (key = rcu_dereference(sdata->default_multicast_key)))
+ info->control.hw_key = &key->conf;
sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data, u.ap);
+ }
info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
info->control.vif = &sdata->vif;
--
2.7.4

View File

@ -1,583 +0,0 @@
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