2020-04-30 15:31:52

by John Crispin

[permalink] [raw]
Subject: [PATCH V2] ath11k: add tx hw 802.11 encapusaltion offloading support

This patch adds support for ethernet rxtx mode to the driver. The feature
is enabled via a new module parameter. If enabled to driver will enable
the feature on a per vif basis if all other requirements were met.

Signed-off-by: Shashidhar Lakkavalli <[email protected]>
Signed-off-by: John Crispin <[email protected]>
---
Changes in V2
* use an enum for datapath mode
* minor fixes as suggested by Julian

drivers/net/wireless/ath/ath11k/core.h | 5 +++
drivers/net/wireless/ath/ath11k/dp_tx.c | 17 +++++++--
drivers/net/wireless/ath/ath11k/mac.c | 46 ++++++++++++++++++++-----
3 files changed, 56 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 5c767d87c174..12c0a4de3506 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -60,9 +60,14 @@ static inline enum wme_ac ath11k_tid_to_ac(u32 tid)
WME_AC_VO);
}

+enum ath11k_skb_flags {
+ ATH11K_SKB_HW_80211_ENCAP = BIT(0),
+};
+
struct ath11k_skb_cb {
dma_addr_t paddr;
u8 eid;
+ u8 flags;
struct ath11k *ar;
struct ieee80211_vif *vif;
} __packed;
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index 8c3f973923d6..a8f3accb7d3e 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -16,7 +16,11 @@ ath11k_txq_tcl_ring_map[ATH11K_HW_MAX_QUEUES] = { 0x0, 0x1, 0x2, 0x2 };
static enum hal_tcl_encap_type
ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb)
{
- /* TODO: Determine encap type based on vif_type and configuration */
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+
+ if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
+ return HAL_TCL_ENCAP_TYPE_ETHERNET;
+
return HAL_TCL_ENCAP_TYPE_NATIVE_WIFI;
}

@@ -40,8 +44,11 @@ static void ath11k_dp_tx_encap_nwifi(struct sk_buff *skb)
static u8 ath11k_dp_tx_get_tid(struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct ath11k_skb_cb *cb = ATH11K_SKB_CB(skb);

- if (!ieee80211_is_data_qos(hdr->frame_control))
+ if (cb->flags & ATH11K_SKB_HW_80211_ENCAP)
+ return skb->priority & IEEE80211_QOS_CTL_TID_MASK;
+ else if (!ieee80211_is_data_qos(hdr->frame_control))
return HAL_DESC_REO_NON_QOS_TID;
else
return skb->priority & IEEE80211_QOS_CTL_TID_MASK;
@@ -88,7 +95,8 @@ 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 (!ieee80211_is_data(hdr->frame_control))
+ if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
+ !ieee80211_is_data(hdr->frame_control))
return -ENOTSUPP;

pool_id = skb_get_queue_mapping(skb) & (ATH11K_HW_MAX_QUEUES - 1);
@@ -149,7 +157,10 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
* skb_checksum_help() is needed
*/
case HAL_TCL_ENCAP_TYPE_ETHERNET:
+ /* no need to encap */
+ break;
case HAL_TCL_ENCAP_TYPE_802_3:
+ default:
/* TODO: Take care of other encap modes as well */
ret = -EINVAL;
goto fail_remove_idr;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index aef012912003..735526b34024 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -33,6 +33,11 @@
.max_power = 30, \
}

+/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
+static unsigned int ath11k_ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
+module_param_named(ath11k_frame_mode, ath11k_ath11k_frame_mode, uint, 0644);
+MODULE_PARM_DESC(ath11k_frame_mode, "Datapath frame mode");
+
static const struct ieee80211_channel ath11k_2ghz_channels[] = {
CHAN2G(1, 2412, 0),
CHAN2G(2, 2417, 0),
@@ -3806,10 +3811,10 @@ static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant)

int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
{
+ struct sk_buff *msdu = skb;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
struct ath11k *ar = ctx;
struct ath11k_base *ab = ar->ab;
- struct sk_buff *msdu = skb;
- struct ieee80211_tx_info *info;

spin_lock_bh(&ar->txmgmt_idr_lock);
idr_remove(&ar->txmgmt_idr, buf_id);
@@ -3849,6 +3854,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
{
struct ath11k_base *ab = ar->ab;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_tx_info *info;
dma_addr_t paddr;
int buf_id;
int ret;
@@ -3860,11 +3866,14 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
if (buf_id < 0)
return -ENOSPC;

- if ((ieee80211_is_action(hdr->frame_control) ||
- ieee80211_is_deauth(hdr->frame_control) ||
- ieee80211_is_disassoc(hdr->frame_control)) &&
- ieee80211_has_protected(hdr->frame_control)) {
- skb_put(skb, IEEE80211_CCMP_MIC_LEN);
+ info = IEEE80211_SKB_CB(skb);
+ if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)) {
+ if ((ieee80211_is_action(hdr->frame_control) ||
+ ieee80211_is_deauth(hdr->frame_control) ||
+ ieee80211_is_disassoc(hdr->frame_control)) &&
+ ieee80211_has_protected(hdr->frame_control)) {
+ skb_put(skb, IEEE80211_CCMP_MIC_LEN);
+ }
}

paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
@@ -3961,6 +3970,7 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
{
+ struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
struct ath11k *ar = hw->priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
@@ -3969,7 +3979,9 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
bool is_prb_rsp;
int ret;

- if (ieee80211_is_mgmt(hdr->frame_control)) {
+ if (info->control.flags & IEEE80211_TX_CTRL_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);
ret = ath11k_mac_mgmt_tx(ar, skb, is_prb_rsp);
if (ret) {
@@ -4245,6 +4257,7 @@ 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;
@@ -4339,7 +4352,22 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->data_lock);

param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
- param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
+ if (ath11k_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
+ param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
+
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
param_id, param_value);
if (ret) {
--
2.20.1


2020-05-05 08:07:16

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH V2] ath11k: add tx hw 802.11 encapusaltion offloading support

John Crispin <[email protected]> writes:

> This patch adds support for ethernet rxtx mode to the driver. The feature
> is enabled via a new module parameter. If enabled to driver will enable
> the feature on a per vif basis if all other requirements were met.
>
> Signed-off-by: Shashidhar Lakkavalli <[email protected]>
> Signed-off-by: John Crispin <[email protected]>

[...]

> --- a/drivers/net/wireless/ath/ath11k/mac.c
> +++ b/drivers/net/wireless/ath/ath11k/mac.c
> @@ -33,6 +33,11 @@
> .max_power = 30, \
> }
>
> +/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
> +static unsigned int ath11k_ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
> +module_param_named(ath11k_frame_mode, ath11k_ath11k_frame_mode, uint, 0644);
> +MODULE_PARM_DESC(ath11k_frame_mode, "Datapath frame mode");

I don't think we should add ath11k_ prefix to module names, right? So I
changed that and documented the values:

/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
static unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
MODULE_PARM_DESC(frame_mode,
"Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");

Also I added a comment to enum ath11k_hw_txrx_mode so that we don't
accidentally change the values. This is now in pending branch:

https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git/commit/?h=pending&id=f0717ed39d06a9f2fd32edbdf88f29939dc25516

Please check my changes.

--
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

2020-05-05 08:18:21

by John Crispin

[permalink] [raw]
Subject: Re: [PATCH V2] ath11k: add tx hw 802.11 encapusaltion offloading support

On 05.05.20 10:06, Kalle Valo wrote:
> John Crispin <[email protected]> writes:
>
>> This patch adds support for ethernet rxtx mode to the driver. The feature
>> is enabled via a new module parameter. If enabled to driver will enable
>> the feature on a per vif basis if all other requirements were met.
>>
>> Signed-off-by: Shashidhar Lakkavalli <[email protected]>
>> Signed-off-by: John Crispin <[email protected]>
>
> [...]
>
>> --- a/drivers/net/wireless/ath/ath11k/mac.c
>> +++ b/drivers/net/wireless/ath/ath11k/mac.c
>> @@ -33,6 +33,11 @@
>> .max_power = 30, \
>> }
>>
>> +/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
>> +static unsigned int ath11k_ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
>> +module_param_named(ath11k_frame_mode, ath11k_ath11k_frame_mode, uint, 0644);
>> +MODULE_PARM_DESC(ath11k_frame_mode, "Datapath frame mode");
>
> I don't think we should add ath11k_ prefix to module names, right? So I
> changed that and documented the values:
>
> /* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
> static unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
> module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
> MODULE_PARM_DESC(frame_mode,
> "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
>
> Also I added a comment to enum ath11k_hw_txrx_mode so that we don't
> accidentally change the values. This is now in pending branch:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git/commit/?h=pending&id=f0717ed39d06a9f2fd32edbdf88f29939dc25516
>
> Please check my changes.
>

Thanks, looks good.
John

2020-05-06 06:16:38

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH V2] ath11k: add tx hw 802.11 encapusaltion offloading support

John Crispin <[email protected]> wrote:

> This patch adds support for ethernet rxtx mode to the driver. The feature
> is enabled via a new module parameter. If enabled to driver will enable
> the feature on a per vif basis if all other requirements were met.
>
> Signed-off-by: Shashidhar Lakkavalli <[email protected]>
> Signed-off-by: John Crispin <[email protected]>
> Signed-off-by: Kalle Valo <[email protected]>

Patch applied to ath-next branch of ath.git, thanks.

e7f33e0c52c0 ath11k: add tx hw 802.11 encapsulation offloading support

--
https://patchwork.kernel.org/patch/11520703/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

2020-09-18 11:07:11

by Wen Gong

[permalink] [raw]
Subject: Re: [PATCH V2] ath11k: add tx hw 802.11 encapusaltion offloading support

On 2020-04-30 23:28, John Crispin wrote:
> This patch adds support for ethernet rxtx mode to the driver. The
> feature
> is enabled via a new module parameter. If enabled to driver will enable
> the feature on a per vif basis if all other requirements were met.
>
[...]
> @@ -4339,7 +4352,22 @@ static int ath11k_mac_op_add_interface(struct
> ieee80211_hw *hw,
> spin_unlock_bh(&ar->data_lock);
>
> param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
> - param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
> + if (ath11k_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))
I see ieee80211_set_hw_80211_encap have check like this:
if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
enable = false;

so is it beeter to call it after associated/install key?
> + param_value = ATH11K_HW_TXRX_ETHERNET;
> + 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) {