|
@@ -197,6 +197,10 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
|
|
|
return -EOPNOTSUPP;
|
|
|
}
|
|
|
|
|
|
+ if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
|
|
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
|
|
+ }
|
|
|
+
|
|
|
if (cmd == DISABLE_KEY) {
|
|
|
arg.key_cipher = WMI_CIPHER_NONE;
|
|
|
arg.key_data = NULL;
|
|
@@ -218,6 +222,9 @@ static int ath10k_install_key(struct ath10k_vif *arvif,
|
|
|
|
|
|
reinit_completion(&ar->install_key_done);
|
|
|
|
|
|
+ if (arvif->nohwcrypt)
|
|
|
+ return 1;
|
|
|
+
|
|
|
ret = ath10k_send_key(arvif, key, cmd, macaddr, flags);
|
|
|
if (ret)
|
|
|
return ret;
|
|
@@ -256,7 +263,7 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif,
|
|
|
|
|
|
ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY,
|
|
|
addr, flags);
|
|
|
- if (ret)
|
|
|
+ if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
flags = 0;
|
|
@@ -264,7 +271,7 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif,
|
|
|
|
|
|
ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY,
|
|
|
addr, flags);
|
|
|
- if (ret)
|
|
|
+ if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
spin_lock_bh(&ar->data_lock);
|
|
@@ -322,10 +329,10 @@ static int ath10k_clear_peer_keys(struct ath10k_vif *arvif,
|
|
|
/* key flags are not required to delete the key */
|
|
|
ret = ath10k_install_key(arvif, peer->keys[i],
|
|
|
DISABLE_KEY, addr, flags);
|
|
|
- if (ret && first_errno == 0)
|
|
|
+ if (ret < 0 && first_errno == 0)
|
|
|
first_errno = ret;
|
|
|
|
|
|
- if (ret)
|
|
|
+ if (ret < 0)
|
|
|
ath10k_warn(ar, "failed to remove peer wep key %d: %d\n",
|
|
|
i, ret);
|
|
|
|
|
@@ -398,7 +405,7 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
|
|
|
break;
|
|
|
/* key flags are not required to delete the key */
|
|
|
ret = ath10k_install_key(arvif, key, DISABLE_KEY, addr, flags);
|
|
|
- if (ret && first_errno == 0)
|
|
|
+ if (ret < 0 && first_errno == 0)
|
|
|
first_errno = ret;
|
|
|
|
|
|
if (ret)
|
|
@@ -3149,13 +3156,30 @@ ath10k_tx_h_get_txmode(struct ath10k *ar, struct ieee80211_vif *vif,
|
|
|
* Some wmi-tlv firmwares for qca6174 have broken Tx key selection for
|
|
|
* NativeWifi txmode - it selects AP key instead of peer key. It seems
|
|
|
* to work with Ethernet txmode so use it.
|
|
|
+ *
|
|
|
+ * FIXME: Check if raw mode works with TDLS.
|
|
|
*/
|
|
|
if (ieee80211_is_data_present(fc) && sta && sta->tdls)
|
|
|
return ATH10K_HW_TXRX_ETHERNET;
|
|
|
|
|
|
+ if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
|
|
|
+ return ATH10K_HW_TXRX_RAW;
|
|
|
+
|
|
|
return ATH10K_HW_TXRX_NATIVE_WIFI;
|
|
|
}
|
|
|
|
|
|
+static bool ath10k_tx_h_use_hwcrypto(struct ieee80211_vif *vif,
|
|
|
+ struct sk_buff *skb) {
|
|
|
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
|
+ const u32 mask = IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
|
|
+ IEEE80211_TX_CTL_INJECTED;
|
|
|
+ if ((info->flags & mask) == mask)
|
|
|
+ return false;
|
|
|
+ if (vif)
|
|
|
+ return !ath10k_vif_to_arvif(vif)->nohwcrypt;
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
/* HTT Tx uses Native Wifi tx mode which expects 802.11 frames without QoS
|
|
|
* Control in the header.
|
|
|
*/
|
|
@@ -3600,6 +3624,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
|
|
|
ATH10K_SKB_CB(skb)->htt.is_offchan = false;
|
|
|
ATH10K_SKB_CB(skb)->htt.freq = 0;
|
|
|
ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
|
|
|
+ ATH10K_SKB_CB(skb)->htt.nohwcrypt = !ath10k_tx_h_use_hwcrypto(vif, skb);
|
|
|
ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, vif);
|
|
|
ATH10K_SKB_CB(skb)->txmode = ath10k_tx_h_get_txmode(ar, vif, sta, skb);
|
|
|
ATH10K_SKB_CB(skb)->is_protected = ieee80211_has_protected(fc);
|
|
@@ -3615,12 +3640,11 @@ static void ath10k_tx(struct ieee80211_hw *hw,
|
|
|
ath10k_tx_h_8023(skb);
|
|
|
break;
|
|
|
case ATH10K_HW_TXRX_RAW:
|
|
|
- /* FIXME: Packet injection isn't implemented. It should be
|
|
|
- * doable with firmware 10.2 on qca988x.
|
|
|
- */
|
|
|
- WARN_ON_ONCE(1);
|
|
|
- ieee80211_free_txskb(hw, skb);
|
|
|
- return;
|
|
|
+ if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
|
|
+ WARN_ON_ONCE(1);
|
|
|
+ ieee80211_free_txskb(hw, skb);
|
|
|
+ return;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
|
@@ -4139,6 +4163,14 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|
|
goto err;
|
|
|
}
|
|
|
}
|
|
|
+ if (test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags))
|
|
|
+ arvif->nohwcrypt = true;
|
|
|
+
|
|
|
+ if (arvif->nohwcrypt &&
|
|
|
+ !test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
|
|
+ ath10k_warn(ar, "cryptmode module param needed for sw crypto\n");
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
|
|
|
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d bcnmode %s\n",
|
|
|
arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
|
|
@@ -4728,6 +4760,9 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
|
if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
|
|
|
return 1;
|
|
|
|
|
|
+ if (arvif->nohwcrypt)
|
|
|
+ return 1;
|
|
|
+
|
|
|
if (key->keyidx > WMI_MAX_KEY_INDEX)
|
|
|
return -ENOSPC;
|
|
|
|
|
@@ -4797,6 +4832,7 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
|
|
|
|
ret = ath10k_install_key(arvif, key, cmd, peer_addr, flags);
|
|
|
if (ret) {
|
|
|
+ WARN_ON(ret > 0);
|
|
|
ath10k_warn(ar, "failed to install key for vdev %i peer %pM: %d\n",
|
|
|
arvif->vdev_id, peer_addr, ret);
|
|
|
goto exit;
|
|
@@ -4812,13 +4848,16 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
|
|
|
|
ret = ath10k_install_key(arvif, key, cmd, peer_addr, flags2);
|
|
|
if (ret) {
|
|
|
+ WARN_ON(ret > 0);
|
|
|
ath10k_warn(ar, "failed to install (ucast) key for vdev %i peer %pM: %d\n",
|
|
|
arvif->vdev_id, peer_addr, ret);
|
|
|
ret2 = ath10k_install_key(arvif, key, DISABLE_KEY,
|
|
|
peer_addr, flags);
|
|
|
- if (ret2)
|
|
|
+ if (ret2) {
|
|
|
+ WARN_ON(ret2 > 0);
|
|
|
ath10k_warn(ar, "failed to disable (mcast) key for vdev %i peer %pM: %d\n",
|
|
|
arvif->vdev_id, peer_addr, ret2);
|
|
|
+ }
|
|
|
goto exit;
|
|
|
}
|
|
|
}
|
|
@@ -6892,7 +6931,6 @@ int ath10k_mac_register(struct ath10k *ar)
|
|
|
ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);
|
|
|
ieee80211_hw_set(ar->hw, AP_LINK_PS);
|
|
|
ieee80211_hw_set(ar->hw, SPECTRUM_MGMT);
|
|
|
- ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
|
|
|
ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
|
|
|
ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);
|
|
|
ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);
|
|
@@ -6900,6 +6938,9 @@ int ath10k_mac_register(struct ath10k *ar)
|
|
|
ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
|
|
|
ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
|
|
|
|
|
|
+ if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
|
|
|
+ ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
|
|
|
+
|
|
|
ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
|
|
|
ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
|
|
|
|
@@ -7003,7 +7044,8 @@ int ath10k_mac_register(struct ath10k *ar)
|
|
|
goto err_free;
|
|
|
}
|
|
|
|
|
|
- ar->hw->netdev_features = NETIF_F_HW_CSUM;
|
|
|
+ if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
|
|
|
+ ar->hw->netdev_features = NETIF_F_HW_CSUM;
|
|
|
|
|
|
if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
|
|
|
/* Init ath dfs pattern detector */
|