@@ -55,7 +55,7 @@ MODULE_PARM_DESC(uart_print, "Uart target debugging");
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");
@@ -3713,6 +3713,9 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
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;
@@ -3873,6 +3876,12 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
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;
@@ -3911,6 +3920,7 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
cb->flags |= ATH10K_SKB_F_RAW_TX;
}
+finish_cb_fill:
cb->vif = vif;
cb->txq = txq;
cb->airtime_est = airtime;
@@ -4034,7 +4044,11 @@ static int ath10k_mac_tx(struct ath10k *ar,
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) &&
@@ -4645,12 +4659,10 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
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;
@@ -4664,8 +4676,14 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
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) {
@@ -5465,6 +5483,30 @@ static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif)
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,
@@ -5674,15 +5716,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
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.
@@ -9375,6 +9409,7 @@ static const struct ieee80211_ops ath10k_ops = {
.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,
@@ -10044,6 +10079,12 @@ int ath10k_mac_register(struct ath10k *ar)
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;