diff mbox

ath10k: add dynamic vlan support

Message ID 1524232653-22573-1-git-send-email-mpubbise@codeaurora.org (mailing list archive)
State Changes Requested
Delegated to: Kalle Valo
Headers show

Commit Message

Manikanta Pubbisetty April 20, 2018, 1:57 p.m. UTC
Mutlicast/broadcast traffic destined for a particular vlan group will
always be encrypted in software. To enable dynamic VLANs, it requires
driver support for sending software encrypted packets.

In ath10k, sending sw encrypted frames is allowed only when we insmod
the driver with cryptmode param set to 1, this configuration disables
hardware crypto and enables RAW mode implicitly. Since, enabling raw
mode has performance impact, this cannot be considered as an ideal
solution for supporting VLANs in the driver.

As an alternative take, in this approach, cryptographic keys for
unicast traffic(per peer PTKs) and keys for non-vlan group traffic
will be configured in hardware, allowing hardware encryption for unicast
and non-vlan group traffic. Only vlan group traffic will be encrypted in
software and pushed to the target with encap mode set to RAW in the TX
descriptors.

Not all firmwares can support this type of key configuration(having few
keys installed in hardware and few only in software); for this purpose a
new WMI service flag "WMI_SERVICE_PER_PACKET_SW_ENCRYPT" is introduced to
advertise this support.

Also, adding the logic required to send sw encrypted frames in raw mode.

Tested this change on QCA9984(firmware version 10.4-3.5.3-00057).

Signed-off-by: Manikanta Pubbisetty <mpubbise@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/core.h |  1 +
 drivers/net/wireless/ath/ath10k/mac.c  | 26 ++++++++++++++++++++++++--
 drivers/net/wireless/ath/ath10k/wmi.h  | 21 +++++++++++++++++++++
 3 files changed, 46 insertions(+), 2 deletions(-)

Comments

Sebastian Gottschall April 23, 2018, 7:18 p.m. UTC | #1
this patch makes no sense at some points. AP_VLAN must be enabled always 
(it is enabled by mac80211 by default, but is now disabled in very 
latest git version for drivers which announce sw_crypto support)
if its disabled wds ap / wds sta operation will not work anymore since 
mac80211 uses AP_VLAN for the local wds sta interfaces

Sebastian


Am 20.04.2018 um 15:57 schrieb Manikanta Pubbisetty:
> Mutlicast/broadcast traffic destined for a particular vlan group will
> always be encrypted in software. To enable dynamic VLANs, it requires
> driver support for sending software encrypted packets.
>
> In ath10k, sending sw encrypted frames is allowed only when we insmod
> the driver with cryptmode param set to 1, this configuration disables
> hardware crypto and enables RAW mode implicitly. Since, enabling raw
> mode has performance impact, this cannot be considered as an ideal
> solution for supporting VLANs in the driver.
>
> As an alternative take, in this approach, cryptographic keys for
> unicast traffic(per peer PTKs) and keys for non-vlan group traffic
> will be configured in hardware, allowing hardware encryption for unicast
> and non-vlan group traffic. Only vlan group traffic will be encrypted in
> software and pushed to the target with encap mode set to RAW in the TX
> descriptors.
>
> Not all firmwares can support this type of key configuration(having few
> keys installed in hardware and few only in software); for this purpose a
> new WMI service flag "WMI_SERVICE_PER_PACKET_SW_ENCRYPT" is introduced to
> advertise this support.
>
> Also, adding the logic required to send sw encrypted frames in raw mode.
>
> Tested this change on QCA9984(firmware version 10.4-3.5.3-00057).
>
> Signed-off-by: Manikanta Pubbisetty <mpubbise@codeaurora.org>
> ---
>   drivers/net/wireless/ath/ath10k/core.h |  1 +
>   drivers/net/wireless/ath/ath10k/mac.c  | 26 ++++++++++++++++++++++++--
>   drivers/net/wireless/ath/ath10k/wmi.h  | 21 +++++++++++++++++++++
>   3 files changed, 46 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
> index e4ac8f2..105438d 100644
> --- a/drivers/net/wireless/ath/ath10k/core.h
> +++ b/drivers/net/wireless/ath/ath10k/core.h
> @@ -122,6 +122,7 @@ enum ath10k_skb_flags {
>   	ATH10K_SKB_F_DELIVER_CAB = BIT(2),
>   	ATH10K_SKB_F_MGMT = BIT(3),
>   	ATH10K_SKB_F_QOS = BIT(4),
> +	ATH10K_SKB_F_RAW_TX = BIT(5),
>   };
>   
>   struct ath10k_skb_cb {
> diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
> index fc3320f..694c0aa 100644
> --- a/drivers/net/wireless/ath/ath10k/mac.c
> +++ b/drivers/net/wireless/ath/ath10k/mac.c
> @@ -3362,6 +3362,7 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
>   			   struct sk_buff *skb)
>   {
>   	const struct ieee80211_hdr *hdr = (void *)skb->data;
> +	const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
>   	__le16 fc = hdr->frame_control;
>   
>   	if (!vif || vif->type == NL80211_IFTYPE_MONITOR)
> @@ -3403,7 +3404,8 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
>   	if (ieee80211_is_data_present(fc) && sta && sta->tdls)
>   		return ATH10K_HW_TXRX_ETHERNET;
>   
> -	if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
> +	if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) ||
> +	    skb_cb->flags & ATH10K_SKB_F_RAW_TX)
>   		return ATH10K_HW_TXRX_RAW;
>   
>   	return ATH10K_HW_TXRX_NATIVE_WIFI;
> @@ -3513,6 +3515,9 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
>   {
>   	struct ieee80211_hdr *hdr = (void *)skb->data;
>   	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
> +	const struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> +	bool is_data = ieee80211_is_data(hdr->frame_control) ||
> +			ieee80211_is_data_qos(hdr->frame_control);
>   
>   	cb->flags = 0;
>   	if (!ath10k_tx_h_use_hwcrypto(vif, skb))
> @@ -3524,6 +3529,16 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
>   	if (ieee80211_is_data_qos(hdr->frame_control))
>   		cb->flags |= ATH10K_SKB_F_QOS;
>   
> +	/* Data frames encrypted in software will be posted to firmware
> +	 * with tx encap mode set to RAW. One such case would be the
> +	 * multicast traffic generated for a VLAN group.
> +	 */
> +	if (is_data && ieee80211_has_protected(hdr->frame_control) &&
> +	    !info->control.hw_key) {
> +		cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
> +		cb->flags |= ATH10K_SKB_F_RAW_TX;
> +	}
> +
>   	cb->vif = vif;
>   	cb->txq = txq;
>   }
> @@ -3632,6 +3647,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
>   {
>   	struct ieee80211_hw *hw = ar->hw;
>   	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> +	const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
>   	int ret;
>   
>   	/* We should disable CCK RATE due to P2P */
> @@ -3649,7 +3665,8 @@ static int ath10k_mac_tx(struct ath10k *ar,
>   		ath10k_tx_h_8023(skb);
>   		break;
>   	case ATH10K_HW_TXRX_RAW:
> -		if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
> +		if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) &&
> +		    !(skb_cb->flags & ATH10K_SKB_F_RAW_TX)) {
>   			WARN_ON_ONCE(1);
>   			ieee80211_free_txskb(hw, skb);
>   			return -ENOTSUPP;
> @@ -8455,6 +8472,11 @@ int ath10k_mac_register(struct ath10k *ar)
>   		goto err_dfs_detector_exit;
>   	}
>   
> +	if (test_bit(WMI_SERVICE_PER_PACKET_SW_ENCRYPT, ar->wmi.svc_map)) {
> +		ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
> +		ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
> +	}
> +
>   	if (!ath_is_world_regd(&ar->ath_common.regulatory)) {
>   		ret = regulatory_hint(ar->hw->wiphy,
>   				      ar->ath_common.regulatory.alpha2);
> diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
> index 3cc129d..e359b6af 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi.h
> +++ b/drivers/net/wireless/ath/ath10k/wmi.h
> @@ -202,6 +202,10 @@ enum wmi_service {
>   	WMI_SERVICE_HOST_DFS_CHECK_SUPPORT,
>   	WMI_SERVICE_TPC_STATS_FINAL,
>   	WMI_SERVICE_RESET_CHIP,
> +	WMI_SERVICE_CFR_CAPTURE_SUPPORT,
> +	WMI_SERVICE_TX_DATA_ACK_RSSI,
> +	WMI_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1,
> +	WMI_SERVICE_PER_PACKET_SW_ENCRYPT,
>   
>   	/* keep last */
>   	WMI_SERVICE_MAX,
> @@ -349,6 +353,10 @@ enum wmi_10_4_service {
>   	WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
>   	WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT,
>   	WMI_10_4_SERVICE_TPC_STATS_FINAL,
> +	WMI_10_4_SERVICE_CFR_CAPTURE_SUPPORT,
> +	WMI_10_4_SERVICE_TX_DATA_ACK_RSSI,
> +	WMI_10_4_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1,
> +	WMI_10_4_SERVICE_PER_PACKET_SW_ENCRYPT,
>   };
>   
>   static inline char *wmi_service_name(int service_id)
> @@ -461,6 +469,11 @@ static inline char *wmi_service_name(int service_id)
>   	SVCSTR(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS);
>   	SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT);
>   	SVCSTR(WMI_SERVICE_TPC_STATS_FINAL);
> +	SVCSTR(WMI_SERVICE_CFR_CAPTURE_SUPPORT);
> +	SVCSTR(WMI_SERVICE_TX_DATA_ACK_RSSI);
> +	SVCSTR(WMI_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1);
> +	SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT);
> +
>   	default:
>   		return NULL;
>   	}
> @@ -769,6 +782,14 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
>   	       WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, len);
>   	SVCMAP(WMI_10_4_SERVICE_TPC_STATS_FINAL,
>   	       WMI_SERVICE_TPC_STATS_FINAL, len);
> +	SVCMAP(WMI_10_4_SERVICE_CFR_CAPTURE_SUPPORT,
> +	       WMI_SERVICE_CFR_CAPTURE_SUPPORT, len);
> +	SVCMAP(WMI_10_4_SERVICE_TX_DATA_ACK_RSSI,
> +	       WMI_SERVICE_TX_DATA_ACK_RSSI, len);
> +	SVCMAP(WMI_10_4_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1,
> +	       WMI_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1, len);
> +	SVCMAP(WMI_10_4_SERVICE_PER_PACKET_SW_ENCRYPT,
> +	       WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len);
>   }
>   
>   #undef SVCMAP
Kalle Valo April 24, 2018, 8:09 a.m. UTC | #2
Manikanta Pubbisetty <mpubbise@codeaurora.org> writes:

> Mutlicast/broadcast traffic destined for a particular vlan group will
> always be encrypted in software. To enable dynamic VLANs, it requires
> driver support for sending software encrypted packets.
>
> In ath10k, sending sw encrypted frames is allowed only when we insmod
> the driver with cryptmode param set to 1, this configuration disables
> hardware crypto and enables RAW mode implicitly. Since, enabling raw
> mode has performance impact, this cannot be considered as an ideal
> solution for supporting VLANs in the driver.
>
> As an alternative take, in this approach, cryptographic keys for
> unicast traffic(per peer PTKs) and keys for non-vlan group traffic
> will be configured in hardware, allowing hardware encryption for unicast
> and non-vlan group traffic. Only vlan group traffic will be encrypted in
> software and pushed to the target with encap mode set to RAW in the TX
> descriptors.
>
> Not all firmwares can support this type of key configuration(having few
> keys installed in hardware and few only in software); for this purpose a
> new WMI service flag "WMI_SERVICE_PER_PACKET_SW_ENCRYPT" is introduced to
> advertise this support.
>
> Also, adding the logic required to send sw encrypted frames in raw mode.
>
> Tested this change on QCA9984(firmware version 10.4-3.5.3-00057).
>
> Signed-off-by: Manikanta Pubbisetty <mpubbise@codeaurora.org>

Your name in patchwork is wrong and hence my script uses the wrong
name. Please fix it by registering to patchwork[1] where it's possible
to change your name during registration, but only one time. If that
doesn't work then send a request to helpdesk@kernel.org and the admins
can fix it.

[1] https://patchwork.kernel.org/register/
Sebastian Gottschall April 24, 2018, 9:09 a.m. UTC | #3
consider my comment regarding vlan_ap.
this patch will break wds ap / wds sta support with latest mac80211 (see 
also my post on the wireless mailing list about the breaking patch in 
mac80211)
so AP_VLAN must be masked always for all chipsets. otherwise wds breaks 
and this is not just a guess. i tested it yesterday using this patch and 
found
the cause of the issue

the following lines

   +    if (test_bit(WMI_SERVICE_PER_PACKET_SW_ENCRYPT, ar->wmi.svc_map)) {
+        ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
+        ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
+    }


must be just

+        ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
+        ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);

everthing else will cause a regression

Am 24.04.2018 um 10:09 schrieb Kalle Valo:
> Manikanta Pubbisetty <mpubbise@codeaurora.org> writes:
>
>> Mutlicast/broadcast traffic destined for a particular vlan group will
>> always be encrypted in software. To enable dynamic VLANs, it requires
>> driver support for sending software encrypted packets.
>>
>> In ath10k, sending sw encrypted frames is allowed only when we insmod
>> the driver with cryptmode param set to 1, this configuration disables
>> hardware crypto and enables RAW mode implicitly. Since, enabling raw
>> mode has performance impact, this cannot be considered as an ideal
>> solution for supporting VLANs in the driver.
>>
>> As an alternative take, in this approach, cryptographic keys for
>> unicast traffic(per peer PTKs) and keys for non-vlan group traffic
>> will be configured in hardware, allowing hardware encryption for unicast
>> and non-vlan group traffic. Only vlan group traffic will be encrypted in
>> software and pushed to the target with encap mode set to RAW in the TX
>> descriptors.
>>
>> Not all firmwares can support this type of key configuration(having few
>> keys installed in hardware and few only in software); for this purpose a
>> new WMI service flag "WMI_SERVICE_PER_PACKET_SW_ENCRYPT" is introduced to
>> advertise this support.
>>
>> Also, adding the logic required to send sw encrypted frames in raw mode.
>>
>> Tested this change on QCA9984(firmware version 10.4-3.5.3-00057).
>>
>> Signed-off-by: Manikanta Pubbisetty <mpubbise@codeaurora.org>
> Your name in patchwork is wrong and hence my script uses the wrong
> name. Please fix it by registering to patchwork[1] where it's possible
> to change your name during registration, but only one time. If that
> doesn't work then send a request to helpdesk@kernel.org and the admins
> can fix it.
>
> [1] https://patchwork.kernel.org/register/
>
Manikanta Pubbisetty April 24, 2018, 9:18 a.m. UTC | #4
Yes Sebastian, Your point is valid. This would break the 4-addr 
operation on other ath10k devices which does not support the new WMI 
service.

I have another approach to solve this problem, I will come with a small 
patch and see what johannes has to say on that approach.

Manikanta

On 4/24/2018 2:39 PM, Sebastian Gottschall wrote:
> consider my comment regarding vlan_ap.
> this patch will break wds ap / wds sta support with latest mac80211 
> (see also my post on the wireless mailing list about the breaking 
> patch in mac80211)
> so AP_VLAN must be masked always for all chipsets. otherwise wds 
> breaks and this is not just a guess. i tested it yesterday using this 
> patch and found
> the cause of the issue
>
> the following lines
>
>   +    if (test_bit(WMI_SERVICE_PER_PACKET_SW_ENCRYPT, 
> ar->wmi.svc_map)) {
> +        ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
> +        ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
> +    }
>
>
> must be just
>
> +        ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
> +        ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
>
> everthing else will cause a regression
>
> Am 24.04.2018 um 10:09 schrieb Kalle Valo:
>> Manikanta Pubbisetty <mpubbise@codeaurora.org> writes:
>>
>>> Mutlicast/broadcast traffic destined for a particular vlan group will
>>> always be encrypted in software. To enable dynamic VLANs, it requires
>>> driver support for sending software encrypted packets.
>>>
>>> In ath10k, sending sw encrypted frames is allowed only when we insmod
>>> the driver with cryptmode param set to 1, this configuration disables
>>> hardware crypto and enables RAW mode implicitly. Since, enabling raw
>>> mode has performance impact, this cannot be considered as an ideal
>>> solution for supporting VLANs in the driver.
>>>
>>> As an alternative take, in this approach, cryptographic keys for
>>> unicast traffic(per peer PTKs) and keys for non-vlan group traffic
>>> will be configured in hardware, allowing hardware encryption for 
>>> unicast
>>> and non-vlan group traffic. Only vlan group traffic will be 
>>> encrypted in
>>> software and pushed to the target with encap mode set to RAW in the TX
>>> descriptors.
>>>
>>> Not all firmwares can support this type of key configuration(having few
>>> keys installed in hardware and few only in software); for this 
>>> purpose a
>>> new WMI service flag "WMI_SERVICE_PER_PACKET_SW_ENCRYPT" is 
>>> introduced to
>>> advertise this support.
>>>
>>> Also, adding the logic required to send sw encrypted frames in raw 
>>> mode.
>>>
>>> Tested this change on QCA9984(firmware version 10.4-3.5.3-00057).
>>>
>>> Signed-off-by: Manikanta Pubbisetty <mpubbise@codeaurora.org>
>> Your name in patchwork is wrong and hence my script uses the wrong
>> name. Please fix it by registering to patchwork[1] where it's possible
>> to change your name during registration, but only one time. If that
>> doesn't work then send a request to helpdesk@kernel.org and the admins
>> can fix it.
>>
>> [1] https://patchwork.kernel.org/register/
>>
>
Kalle Valo April 24, 2018, 9:52 a.m. UTC | #5
Sebastian Gottschall <s.gottschall@dd-wrt.com> writes:

> consider my comment regarding vlan_ap.

I am considering comment, I just go one issue at a time and haven't had
a time to look at your comment. But PLEASE do not top post, it's very
annoying and creates a mess in patchwork.

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches#do_not_top_post_and_edit_your_quotes
Sebastian Gottschall April 24, 2018, 9:55 a.m. UTC | #6
Am 24.04.2018 um 11:52 schrieb Kalle Valo:
> Sebastian Gottschall <s.gottschall@dd-wrt.com> writes:
>
>> consider my comment regarding vlan_ap.
> I am considering comment, I just go one issue at a time and haven't had
> a time to look at your comment. But PLEASE do not top post, it's very
> annoying and creates a mess in patchwork.
>
> https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches#do_not_top_post_and_edit_your_quotes
i almost do top posts for a single reason. you have to scroll down a 
long time sometimes to get the essential information.
i dont know why most people in my country prefer top posting. i will try 
to remember and change it in future
>
Johannes Berg May 18, 2018, 9:53 a.m. UTC | #7
On Mon, 2018-04-23 at 21:18 +0200, Sebastian Gottschall wrote:
> this patch makes no sense at some points. AP_VLAN must be enabled always 
> (it is enabled by mac80211 by default, but is now disabled in very 
> latest git version for drivers which announce sw_crypto support)
> if its disabled wds ap / wds sta operation will not work anymore since 
> mac80211 uses AP_VLAN for the local wds sta interfaces

You'd do you well to learn the correct terminology used in Linux if you
try to communicate with us...

What you say there makes no sense, WDS is a separate mode. Maybe you
mean 4-addr mode?

johannes
Sebastian Gottschall May 18, 2018, 10:40 a.m. UTC | #8
Am 18.05.2018 um 11:53 schrieb Johannes Berg:
> On Mon, 2018-04-23 at 21:18 +0200, Sebastian Gottschall wrote:
>> this patch makes no sense at some points. AP_VLAN must be enabled always
>> (it is enabled by mac80211 by default, but is now disabled in very
>> latest git version for drivers which announce sw_crypto support)
>> if its disabled wds ap / wds sta operation will not work anymore since
>> mac80211 uses AP_VLAN for the local wds sta interfaces
> You'd do you well to learn the correct terminology used in Linux if you
> try to communicate with us...
>
> What you say there makes no sense, WDS is a separate mode. Maybe you
> mean 4-addr mode?
yes 4-addr mode which is common known as WDS mode. (terminology used by 
all sorts of vendors)

Sebastian
>
> johannes
>
diff mbox

Patch

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index e4ac8f2..105438d 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -122,6 +122,7 @@  enum ath10k_skb_flags {
 	ATH10K_SKB_F_DELIVER_CAB = BIT(2),
 	ATH10K_SKB_F_MGMT = BIT(3),
 	ATH10K_SKB_F_QOS = BIT(4),
+	ATH10K_SKB_F_RAW_TX = BIT(5),
 };
 
 struct ath10k_skb_cb {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index fc3320f..694c0aa 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3362,6 +3362,7 @@  ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
 			   struct sk_buff *skb)
 {
 	const struct ieee80211_hdr *hdr = (void *)skb->data;
+	const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
 	__le16 fc = hdr->frame_control;
 
 	if (!vif || vif->type == NL80211_IFTYPE_MONITOR)
@@ -3403,7 +3404,8 @@  ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
 	if (ieee80211_is_data_present(fc) && sta && sta->tdls)
 		return ATH10K_HW_TXRX_ETHERNET;
 
-	if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
+	if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) ||
+	    skb_cb->flags & ATH10K_SKB_F_RAW_TX)
 		return ATH10K_HW_TXRX_RAW;
 
 	return ATH10K_HW_TXRX_NATIVE_WIFI;
@@ -3513,6 +3515,9 @@  static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
 {
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
+	const struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	bool is_data = ieee80211_is_data(hdr->frame_control) ||
+			ieee80211_is_data_qos(hdr->frame_control);
 
 	cb->flags = 0;
 	if (!ath10k_tx_h_use_hwcrypto(vif, skb))
@@ -3524,6 +3529,16 @@  static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
 	if (ieee80211_is_data_qos(hdr->frame_control))
 		cb->flags |= ATH10K_SKB_F_QOS;
 
+	/* Data frames encrypted in software will be posted to firmware
+	 * with tx encap mode set to RAW. One such case would be the
+	 * multicast traffic generated for a VLAN group.
+	 */
+	if (is_data && ieee80211_has_protected(hdr->frame_control) &&
+	    !info->control.hw_key) {
+		cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
+		cb->flags |= ATH10K_SKB_F_RAW_TX;
+	}
+
 	cb->vif = vif;
 	cb->txq = txq;
 }
@@ -3632,6 +3647,7 @@  static int ath10k_mac_tx(struct ath10k *ar,
 {
 	struct ieee80211_hw *hw = ar->hw;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
 	int ret;
 
 	/* We should disable CCK RATE due to P2P */
@@ -3649,7 +3665,8 @@  static int ath10k_mac_tx(struct ath10k *ar,
 		ath10k_tx_h_8023(skb);
 		break;
 	case ATH10K_HW_TXRX_RAW:
-		if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
+		if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) &&
+		    !(skb_cb->flags & ATH10K_SKB_F_RAW_TX)) {
 			WARN_ON_ONCE(1);
 			ieee80211_free_txskb(hw, skb);
 			return -ENOTSUPP;
@@ -8455,6 +8472,11 @@  int ath10k_mac_register(struct ath10k *ar)
 		goto err_dfs_detector_exit;
 	}
 
+	if (test_bit(WMI_SERVICE_PER_PACKET_SW_ENCRYPT, ar->wmi.svc_map)) {
+		ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
+		ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
+	}
+
 	if (!ath_is_world_regd(&ar->ath_common.regulatory)) {
 		ret = regulatory_hint(ar->hw->wiphy,
 				      ar->ath_common.regulatory.alpha2);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 3cc129d..e359b6af 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -202,6 +202,10 @@  enum wmi_service {
 	WMI_SERVICE_HOST_DFS_CHECK_SUPPORT,
 	WMI_SERVICE_TPC_STATS_FINAL,
 	WMI_SERVICE_RESET_CHIP,
+	WMI_SERVICE_CFR_CAPTURE_SUPPORT,
+	WMI_SERVICE_TX_DATA_ACK_RSSI,
+	WMI_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1,
+	WMI_SERVICE_PER_PACKET_SW_ENCRYPT,
 
 	/* keep last */
 	WMI_SERVICE_MAX,
@@ -349,6 +353,10 @@  enum wmi_10_4_service {
 	WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
 	WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT,
 	WMI_10_4_SERVICE_TPC_STATS_FINAL,
+	WMI_10_4_SERVICE_CFR_CAPTURE_SUPPORT,
+	WMI_10_4_SERVICE_TX_DATA_ACK_RSSI,
+	WMI_10_4_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1,
+	WMI_10_4_SERVICE_PER_PACKET_SW_ENCRYPT,
 };
 
 static inline char *wmi_service_name(int service_id)
@@ -461,6 +469,11 @@  static inline char *wmi_service_name(int service_id)
 	SVCSTR(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS);
 	SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT);
 	SVCSTR(WMI_SERVICE_TPC_STATS_FINAL);
+	SVCSTR(WMI_SERVICE_CFR_CAPTURE_SUPPORT);
+	SVCSTR(WMI_SERVICE_TX_DATA_ACK_RSSI);
+	SVCSTR(WMI_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1);
+	SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT);
+
 	default:
 		return NULL;
 	}
@@ -769,6 +782,14 @@  static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
 	       WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, len);
 	SVCMAP(WMI_10_4_SERVICE_TPC_STATS_FINAL,
 	       WMI_SERVICE_TPC_STATS_FINAL, len);
+	SVCMAP(WMI_10_4_SERVICE_CFR_CAPTURE_SUPPORT,
+	       WMI_SERVICE_CFR_CAPTURE_SUPPORT, len);
+	SVCMAP(WMI_10_4_SERVICE_TX_DATA_ACK_RSSI,
+	       WMI_SERVICE_TX_DATA_ACK_RSSI, len);
+	SVCMAP(WMI_10_4_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1,
+	       WMI_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1, len);
+	SVCMAP(WMI_10_4_SERVICE_PER_PACKET_SW_ENCRYPT,
+	       WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len);
 }
 
 #undef SVCMAP