|
|
@@ -0,0 +1,194 @@
|
|
|
+From af6d8265c47e46881b80c6b073f53c8c4af52d28 Mon Sep 17 00:00:00 2001
|
|
|
+From: Sergey Ryazanov <[email protected]>
|
|
|
+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 <[email protected]>
|
|
|
+Tested-by: Oldřich Jedlička <[email protected]> # TP-Link Archer C7 v4 & v5 (QCA9563 + QCA9880)
|
|
|
+Tested-by: Edward Matijevic <[email protected]> # TP-Link Archer C2600 (IPQ8064 + QCA9980 10.4.1.00030-1)
|
|
|
+Tested-by: Edward Matijevic <[email protected]> # QCA9377 PCI in Sta mode
|
|
|
+Tested-by: Zhijun You <[email protected]> # NETGEAR R7800 (QCA9984 10.4-3.9.0.2-00159)
|
|
|
+Signed-off-by: Kalle Valo <[email protected]>
|
|
|
+Link: https://lore.kernel.org/r/[email protected]
|
|
|
+---
|
|
|
+ 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) {
|
|
|
+@@ -5447,6 +5465,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,
|
|
|
+@@ -5656,15 +5698,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.
|
|
|
+@@ -9352,6 +9386,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,
|
|
|
+@@ -10021,6 +10056,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;
|