-From af6d8265c47e46881b80c6b073f53c8c4af52d28 Mon Sep 17 00:00:00 2001
-From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
-Date: Mon, 16 May 2022 13:26:00 +0300
-Subject: ath10k: add encapsulation offloading support
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Frame encapsulation from Ethernet into the IEEE 802.11 frame format
-takes a considerable host CPU time on the xmit path. The firmware is
-able to do this operation for us, so enable encapsulation offloading for
-AP and Sta interface types to improve overall system performance.
-
-The driver is almost ready for encapsulation offloading support. There
-are only a few places where the driver assumes the frame format is IEEE
-802.11 that need to be fixed.
-
-Encapsulation offloading is currently disabled by default and the driver
-utilizes mac80211 encapsulation support. To activate offloading, the
-frame_mode=2 parameter should be passed during module loading.
-
-On a QCA9563+QCA9888-based access point in bridged mode, encapsulation
-offloading increases TCP 16-streams DL throughput from 365 to 396 mbps
-(+8%) and UDP DL throughput from 436 to 483 mbps (+11%).
-
-Tested-on: QCA9888 hw2.0 PCI 10.4-3.9.0.2-00131
-Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00157-QCARMSWPZ-1
-Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
-Tested-by: Oldřich Jedlička <oldium.pro@gmail.com> # TP-Link Archer C7 v4 & v5 (QCA9563 + QCA9880)
-Tested-by: Edward Matijevic <motolav@gmail.com> # TP-Link Archer C2600 (IPQ8064 + QCA9980 10.4.1.00030-1)
-Tested-by: Edward Matijevic <motolav@gmail.com> # QCA9377 PCI in Sta mode
-Tested-by: Zhijun You <hujy652@gmail.com> # NETGEAR R7800 (QCA9984 10.4-3.9.0.2-00159)
-Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
-Link: https://lore.kernel.org/r/20220516032519.29831-5-ryazanov.s.a@gmail.com
----
- drivers/net/wireless/ath/ath10k/core.c | 2 +-
- drivers/net/wireless/ath/ath10k/mac.c | 67 +++++++++++++++++++++++++++-------
- 2 files changed, 55 insertions(+), 14 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/core.c
-+++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -54,7 +54,7 @@ MODULE_PARM_DESC(uart_print, "Uart targe
- MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
- MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
- MODULE_PARM_DESC(frame_mode,
-- "Datapath frame mode (0: raw, 1: native wifi (default))");
-+ "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
- MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file");
- MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging");
-
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -3710,6 +3710,9 @@ ath10k_mac_tx_h_get_txmode(struct ath10k
- const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
- __le16 fc = hdr->frame_control;
-
-+ if (IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
-+ return ATH10K_HW_TXRX_ETHERNET;
-+
- if (!vif || vif->type == NL80211_IFTYPE_MONITOR)
- return ATH10K_HW_TXRX_RAW;
-
-@@ -3870,6 +3873,12 @@ static void ath10k_mac_tx_h_fill_cb(stru
- bool noack = false;
-
- cb->flags = 0;
-+
-+ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
-+ cb->flags |= ATH10K_SKB_F_QOS; /* Assume data frames are QoS */
-+ goto finish_cb_fill;
-+ }
-+
- if (!ath10k_tx_h_use_hwcrypto(vif, skb))
- cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
-
-@@ -3908,6 +3917,7 @@ static void ath10k_mac_tx_h_fill_cb(stru
- cb->flags |= ATH10K_SKB_F_RAW_TX;
- }
-
-+finish_cb_fill:
- cb->vif = vif;
- cb->txq = txq;
- cb->airtime_est = airtime;
-@@ -4031,7 +4041,11 @@ static int ath10k_mac_tx(struct ath10k *
- ath10k_tx_h_seq_no(vif, skb);
- break;
- case ATH10K_HW_TXRX_ETHERNET:
-- ath10k_tx_h_8023(skb);
-+ /* Convert 802.11->802.3 header only if the frame was erlier
-+ * encapsulated to 802.11 by mac80211. Otherwise pass it as is.
-+ */
-+ if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
-+ ath10k_tx_h_8023(skb);
- break;
- case ATH10K_HW_TXRX_RAW:
- if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) &&
-@@ -4643,12 +4657,10 @@ static void ath10k_mac_op_tx(struct ieee
- struct ieee80211_vif *vif = info->control.vif;
- struct ieee80211_sta *sta = control->sta;
- struct ieee80211_txq *txq = NULL;
-- struct ieee80211_hdr *hdr = (void *)skb->data;
- enum ath10k_hw_txrx_mode txmode;
- enum ath10k_mac_tx_path txpath;
- bool is_htt;
- bool is_mgmt;
-- bool is_presp;
- int ret;
- u16 airtime;
-
-@@ -4662,8 +4674,14 @@ static void ath10k_mac_op_tx(struct ieee
- is_mgmt = (txpath == ATH10K_MAC_TX_HTT_MGMT);
-
- if (is_htt) {
-+ bool is_presp = false;
-+
- spin_lock_bh(&ar->htt.tx_lock);
-- is_presp = ieee80211_is_probe_resp(hdr->frame_control);
-+ if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
-+ struct ieee80211_hdr *hdr = (void *)skb->data;
-+
-+ is_presp = ieee80211_is_probe_resp(hdr->frame_control);
-+ }
-
- ret = ath10k_htt_tx_inc_pending(htt);
- if (ret) {
-@@ -5463,6 +5481,30 @@ static int ath10k_mac_set_txbf_conf(stru
- ar->wmi.vdev_param->txbf, value);
- }
-
-+static void ath10k_update_vif_offload(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif)
-+{
-+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
-+ struct ath10k *ar = hw->priv;
-+ u32 vdev_param;
-+ int ret;
-+
-+ if (ath10k_frame_mode != ATH10K_HW_TXRX_ETHERNET ||
-+ ar->wmi.vdev_param->tx_encap_type == WMI_VDEV_PARAM_UNSUPPORTED ||
-+ (vif->type != NL80211_IFTYPE_STATION &&
-+ vif->type != NL80211_IFTYPE_AP))
-+ vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
-+
-+ vdev_param = ar->wmi.vdev_param->tx_encap_type;
-+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-+ ATH10K_HW_TXRX_NATIVE_WIFI);
-+ /* 10.X firmware does not support this VDEV parameter. Do not warn */
-+ if (ret && ret != -EOPNOTSUPP) {
-+ ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n",
-+ arvif->vdev_id, ret);
-+ }
-+}
-+
- /*
- * TODO:
- * Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
-@@ -5672,15 +5714,7 @@ static int ath10k_add_interface(struct i
-
- arvif->def_wep_key_idx = -1;
-
-- vdev_param = ar->wmi.vdev_param->tx_encap_type;
-- ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-- ATH10K_HW_TXRX_NATIVE_WIFI);
-- /* 10.X firmware does not support this VDEV parameter. Do not warn */
-- if (ret && ret != -EOPNOTSUPP) {
-- ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n",
-- arvif->vdev_id, ret);
-- goto err_vdev_delete;
-- }
-+ ath10k_update_vif_offload(hw, vif);
-
- /* Configuring number of spatial stream for monitor interface is causing
- * target assert in qca9888 and qca6174.
-@@ -9368,6 +9402,7 @@ static const struct ieee80211_ops ath10k
- .stop = ath10k_stop,
- .config = ath10k_config,
- .add_interface = ath10k_add_interface,
-+ .update_vif_offload = ath10k_update_vif_offload,
- .remove_interface = ath10k_remove_interface,
- .configure_filter = ath10k_configure_filter,
- .bss_info_changed = ath10k_bss_info_changed,
-@@ -10037,6 +10072,12 @@ int ath10k_mac_register(struct ath10k *a
- if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
- ieee80211_hw_set(ar->hw, SUPPORTS_TDLS_BUFFER_STA);
-
-+ if (ath10k_frame_mode == ATH10K_HW_TXRX_ETHERNET) {
-+ if (ar->wmi.vdev_param->tx_encap_type !=
-+ WMI_VDEV_PARAM_UNSUPPORTED)
-+ ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD);
-+ }
-+
- ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
- ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
- ar->hw->wiphy->max_remain_on_channel_duration = 5000;