wlan-ap-Telecominfraproject/feeds/ipq95xx/mac80211/patches/qca/715-wifi-ath12k-Add-Dynamic-VLAN-support.patch
John Crispin 144c5d00f4 ipq95xx/mac80211: update to ATH12.3-CS
Signed-off-by: John Crispin <john@phrozen.org>
2024-02-28 18:56:21 +01:00

414 lines
12 KiB
Diff

From 3fe2ac33f0d0f7a9c305943f127eb11c6f871ba8 Mon Sep 17 00:00:00 2001
From: Muna Sinada <quic_msinada@quicinc.com>
Date: Tue, 7 Feb 2023 07:38:58 -0800
Subject: [PATCH] wifi: ath12k: Add Dynamic VLAN support
Add support for dynamic VLAN. VLAN group traffic is encrypted in
mac80211 and driver needs to add metadata for the SW encrypted vlan group
traffic.
Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
---
drivers/net/wireless/ath/ath12k/dp_tx.c | 71 +++++++++++-
drivers/net/wireless/ath/ath12k/dp_tx.h | 198 ++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/mac.c | 3 +
3 files changed, 270 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/ath/ath12k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_tx.c
@@ -117,6 +117,43 @@ static void ath12k_hal_tx_cmd_ext_desc_s
HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE);
}
+#define HTT_META_DATA_ALIGNMENT 0x8
+
+static int ath12k_dp_metadata_align_skb(struct sk_buff *skb, u8 align_len)
+{
+ if (unlikely(skb_cow_head(skb, align_len)))
+ return -ENOMEM;
+
+ skb_push(skb, align_len);
+ memset(skb->data, 0, align_len);
+ return 0;
+}
+
+static int ath12k_dp_prepare_htt_metadata(struct sk_buff *skb,
+ u8 *htt_metadata_size)
+{
+ u8 htt_desc_size;
+ /* Size rounded of multiple of 8 bytes */
+ u8 htt_desc_size_aligned;
+ int ret;
+ 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);
+
+ ret = ath12k_dp_metadata_align_skb(skb, htt_desc_size_aligned);
+ if (unlikely(ret))
+ return ret;
+
+ desc_ext = (struct htt_tx_msdu_desc_ext *)skb->data;
+ desc_ext->valid_encrypt_type = 1;
+ desc_ext->encrypt_type = HAL_ENCRYPT_TYPE_WEP_40;
+ desc_ext->host_tx_desc_pool = 1;
+ *htt_metadata_size = htt_desc_size_aligned;
+
+ return 0;
+}
+
int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct ath12k_sta *ahsta, struct sk_buff *skb)
{
@@ -141,6 +178,8 @@ int ath12k_dp_tx(struct ath12k *ar, stru
bool tcl_ring_retry;
u16 peer_id;
bool msdu_ext_desc = false;
+ bool is_diff_encap = false;
+ u8 align_pad, htt_meta_size = 0;
if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)))
return -ESHUTDOWN;
@@ -224,7 +263,11 @@ tcl_ring_sel:
switch (ti.encap_type) {
case HAL_TCL_ENCAP_TYPE_NATIVE_WIFI:
- ath12k_dp_tx_encap_nwifi(skb);
+ if ((ahvif->vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) &&
+ skb->protocol == cpu_to_be16(ETH_P_PAE))
+ is_diff_encap = true;
+ else
+ ath12k_dp_tx_encap_nwifi(skb);
break;
case HAL_TCL_ENCAP_TYPE_RAW:
if (!test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) {
@@ -243,14 +286,6 @@ tcl_ring_sel:
goto fail_remove_tx_buf;
}
- ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(ab->dev, ti.paddr))) {
- atomic_inc(&ab->soc_stats.tx_err.misc_fail);
- ath12k_warn(ab, "failed to DMA map data Tx buffer\n");
- ret = -ENOMEM;
- goto fail_remove_tx_buf;
- }
-
if (unlikely((ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_ETHERNET &&
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)))) {
msdu_ext_desc = true;
@@ -279,10 +314,40 @@ tcl_ring_sel:
}
}
+ /* Add metadata for sw encrypted vlan group traffic */
+ if ((!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->ag->dev_flags) &&
+ !(info->control.flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
+ !info->control.hw_key && ieee80211_has_protected(hdr->frame_control)) ||
+ is_diff_encap) {
+ align_pad = ((unsigned long)skb->data) & (HTT_META_DATA_ALIGNMENT - 1);
+ ret = ath12k_dp_metadata_align_skb(skb, align_pad);
+ if (unlikely(ret))
+ goto fail_remove_tx_buf;
+
+ ti.pkt_offset += align_pad;
+ ret = ath12k_dp_prepare_htt_metadata(skb, &htt_meta_size);
+ if (unlikely(ret))
+ goto fail_remove_tx_buf;
+
+ ti.pkt_offset += htt_meta_size;
+ ti.meta_data_flags |= HTT_TCL_META_DATA_VALID_HTT;
+ ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_TO_FW, 1);
+ ti.encap_type = HAL_TCL_ENCAP_TYPE_RAW;
+ ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
+ }
+
+ ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(ab->dev, ti.paddr))) {
+ atomic_inc(&ab->soc_stats.tx_err.misc_fail);
+ ath12k_warn(ab, "failed to DMA map data Tx buffer\n");
+ ret = -ENOMEM;
+ goto fail_remove_tx_buf;
+ }
+
tx_desc->skb = skb;
tx_desc->mac_id = ar->pdev_idx;
ti.desc_id = tx_desc->desc_id;
- ti.data_len = skb->len;
+ ti.data_len = skb->len - ti.pkt_offset;
skb_cb->paddr = ti.paddr;
skb_cb->vif = ahvif->vif;
skb_cb->ar = ar;
@@ -373,6 +438,9 @@ fail_unmap_dma:
fail_remove_tx_buf:
ath12k_dp_tx_release_txbuf(dp, tx_desc, ti.ring_id);
+ if (ti.pkt_offset)
+ skb_pull(skb, ti.pkt_offset);
+
if (tcl_ring_retry)
goto tcl_ring_sel;
--- a/drivers/net/wireless/ath/ath12k/dp_tx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_tx.h
@@ -15,6 +15,204 @@ struct ath12k_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;
+
void ath12k_dp_tx_update_txcompl(struct ath12k *ar, struct hal_tx_status *ts);
int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab);
int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -14266,6 +14266,9 @@ static int __ath12k_mac_register(struct
ar->max_num_stations = TARGET_NUM_STATIONS;
ar->max_num_peers = TARGET_NUM_PEERS_PDEV;
+ hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
+ hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
+
if (cap->nss_ratio_enabled)
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -2049,6 +2049,9 @@ void ieee80211_link_vlan_copy_chanctx(st
conf = rcu_dereference_protected(ap_conf->chanctx_conf,
lockdep_is_held(&local->chanctx_mtx));
rcu_assign_pointer(link_conf->chanctx_conf, conf);
+ memcpy(&sdata->vif.link_conf[link_id]->chandef,
+ &ap->vif.link_conf[link_id]->chandef,
+ sizeof(struct cfg80211_chan_def));
rcu_read_unlock();
mutex_unlock(&local->chanctx_mtx);
}
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2692,8 +2692,15 @@ static struct sk_buff *ieee80211_build_h
ap_sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data,
u.ap);
- chanctx_conf =
- rcu_dereference(ap_sdata->vif.bss_conf.chanctx_conf);
+
+ /* TODO: change index of link_conf[] to link id of corresponding
+ * AP for MLO cases */
+ if (ap_sdata->vif.valid_links)
+ chanctx_conf =
+ rcu_dereference(ap_sdata->vif.link_conf[0]->chanctx_conf);
+ else
+ chanctx_conf =
+ rcu_dereference(ap_sdata->vif.bss_conf.chanctx_conf);
}
if (sdata->wdev.use_4addr)
break;
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4737,7 +4737,7 @@ static int nl80211_validate_key_link_id(
GENL_SET_ERR_MSG(info, "invalid link ID for MLO group key");
return -EINVAL;
}
- } else if (link_id != -1) {
+ } else if (link_id != -1 && wdev->iftype != NL80211_IFTYPE_AP_VLAN) {
GENL_SET_ERR_MSG(info, "link ID not allowed for non-MLO group key");
return -EINVAL;
}