|
@@ -197,6 +197,10 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
|
|
|
return -EOPNOTSUPP;
|
|
return -EOPNOTSUPP;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
|
|
|
|
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (cmd == DISABLE_KEY) {
|
|
if (cmd == DISABLE_KEY) {
|
|
|
arg.key_cipher = WMI_CIPHER_NONE;
|
|
arg.key_cipher = WMI_CIPHER_NONE;
|
|
|
arg.key_data = NULL;
|
|
arg.key_data = NULL;
|
|
@@ -218,6 +222,9 @@ static int ath10k_install_key(struct ath10k_vif *arvif,
|
|
|
|
|
|
|
|
reinit_completion(&ar->install_key_done);
|
|
reinit_completion(&ar->install_key_done);
|
|
|
|
|
|
|
|
|
|
+ if (arvif->nohwcrypt)
|
|
|
|
|
+ return 1;
|
|
|
|
|
+
|
|
|
ret = ath10k_send_key(arvif, key, cmd, macaddr, flags);
|
|
ret = ath10k_send_key(arvif, key, cmd, macaddr, flags);
|
|
|
if (ret)
|
|
if (ret)
|
|
|
return 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,
|
|
ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY,
|
|
|
addr, flags);
|
|
addr, flags);
|
|
|
- if (ret)
|
|
|
|
|
|
|
+ if (ret < 0)
|
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
|
|
flags = 0;
|
|
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,
|
|
ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY,
|
|
|
addr, flags);
|
|
addr, flags);
|
|
|
- if (ret)
|
|
|
|
|
|
|
+ if (ret < 0)
|
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
|
|
spin_lock_bh(&ar->data_lock);
|
|
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 */
|
|
/* key flags are not required to delete the key */
|
|
|
ret = ath10k_install_key(arvif, peer->keys[i],
|
|
ret = ath10k_install_key(arvif, peer->keys[i],
|
|
|
DISABLE_KEY, addr, flags);
|
|
DISABLE_KEY, addr, flags);
|
|
|
- if (ret && first_errno == 0)
|
|
|
|
|
|
|
+ if (ret < 0 && first_errno == 0)
|
|
|
first_errno = ret;
|
|
first_errno = ret;
|
|
|
|
|
|
|
|
- if (ret)
|
|
|
|
|
|
|
+ if (ret < 0)
|
|
|
ath10k_warn(ar, "failed to remove peer wep key %d: %d\n",
|
|
ath10k_warn(ar, "failed to remove peer wep key %d: %d\n",
|
|
|
i, ret);
|
|
i, ret);
|
|
|
|
|
|
|
@@ -398,7 +405,7 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
|
|
|
break;
|
|
break;
|
|
|
/* key flags are not required to delete the key */
|
|
/* key flags are not required to delete the key */
|
|
|
ret = ath10k_install_key(arvif, key, DISABLE_KEY, addr, flags);
|
|
ret = ath10k_install_key(arvif, key, DISABLE_KEY, addr, flags);
|
|
|
- if (ret && first_errno == 0)
|
|
|
|
|
|
|
+ if (ret < 0 && first_errno == 0)
|
|
|
first_errno = ret;
|
|
first_errno = ret;
|
|
|
|
|
|
|
|
if (ret)
|
|
if (ret)
|
|
@@ -591,11 +598,19 @@ ath10k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
|
|
|
static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr,
|
|
static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr,
|
|
|
enum wmi_peer_type peer_type)
|
|
enum wmi_peer_type peer_type)
|
|
|
{
|
|
{
|
|
|
|
|
+ struct ath10k_vif *arvif;
|
|
|
|
|
+ int num_peers = 0;
|
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
|
|
|
|
|
|
- if (ar->num_peers >= ar->max_num_peers)
|
|
|
|
|
|
|
+ num_peers = ar->num_peers;
|
|
|
|
|
+
|
|
|
|
|
+ /* Each vdev consumes a peer entry as well */
|
|
|
|
|
+ list_for_each_entry(arvif, &ar->arvifs, list)
|
|
|
|
|
+ num_peers++;
|
|
|
|
|
+
|
|
|
|
|
+ if (num_peers >= ar->max_num_peers)
|
|
|
return -ENOBUFS;
|
|
return -ENOBUFS;
|
|
|
|
|
|
|
|
ret = ath10k_wmi_peer_create(ar, vdev_id, addr, peer_type);
|
|
ret = ath10k_wmi_peer_create(ar, vdev_id, addr, peer_type);
|
|
@@ -671,20 +686,6 @@ static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
|
|
|
return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value);
|
|
return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int ath10k_mac_set_frag(struct ath10k_vif *arvif, u32 value)
|
|
|
|
|
-{
|
|
|
|
|
- struct ath10k *ar = arvif->ar;
|
|
|
|
|
- u32 vdev_param;
|
|
|
|
|
-
|
|
|
|
|
- if (value != 0xFFFFFFFF)
|
|
|
|
|
- value = clamp_t(u32, arvif->ar->hw->wiphy->frag_threshold,
|
|
|
|
|
- ATH10K_FRAGMT_THRESHOLD_MIN,
|
|
|
|
|
- ATH10K_FRAGMT_THRESHOLD_MAX);
|
|
|
|
|
-
|
|
|
|
|
- vdev_param = ar->wmi.vdev_param->fragmentation_threshold;
|
|
|
|
|
- return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr)
|
|
static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr)
|
|
|
{
|
|
{
|
|
|
int ret;
|
|
int ret;
|
|
@@ -836,7 +837,7 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
|
|
|
static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
|
|
static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
|
|
|
{
|
|
{
|
|
|
struct cfg80211_chan_def *chandef = NULL;
|
|
struct cfg80211_chan_def *chandef = NULL;
|
|
|
- struct ieee80211_channel *channel = chandef->chan;
|
|
|
|
|
|
|
+ struct ieee80211_channel *channel = NULL;
|
|
|
struct wmi_vdev_start_request_arg arg = {};
|
|
struct wmi_vdev_start_request_arg arg = {};
|
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
|
@@ -2502,6 +2503,9 @@ static int ath10k_mac_vif_recalc_txbf(struct ath10k *ar,
|
|
|
u32 param;
|
|
u32 param;
|
|
|
u32 value;
|
|
u32 value;
|
|
|
|
|
|
|
|
|
|
+ if (ath10k_wmi_get_txbf_conf_scheme(ar) != WMI_TXBF_CONF_AFTER_ASSOC)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
if (!(ar->vht_cap_info &
|
|
if (!(ar->vht_cap_info &
|
|
|
(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
|
(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
|
|
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
|
|
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
|
|
@@ -3149,13 +3153,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
|
|
* Some wmi-tlv firmwares for qca6174 have broken Tx key selection for
|
|
|
* NativeWifi txmode - it selects AP key instead of peer key. It seems
|
|
* NativeWifi txmode - it selects AP key instead of peer key. It seems
|
|
|
* to work with Ethernet txmode so use it.
|
|
* 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)
|
|
if (ieee80211_is_data_present(fc) && sta && sta->tdls)
|
|
|
return ATH10K_HW_TXRX_ETHERNET;
|
|
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;
|
|
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
|
|
/* HTT Tx uses Native Wifi tx mode which expects 802.11 frames without QoS
|
|
|
* Control in the header.
|
|
* Control in the header.
|
|
|
*/
|
|
*/
|
|
@@ -3322,6 +3343,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
|
|
int vdev_id;
|
|
int vdev_id;
|
|
|
int ret;
|
|
int ret;
|
|
|
unsigned long time_left;
|
|
unsigned long time_left;
|
|
|
|
|
+ bool tmp_peer_created = false;
|
|
|
|
|
|
|
|
/* FW requirement: We must create a peer before FW will send out
|
|
/* FW requirement: We must create a peer before FW will send out
|
|
|
* an offchannel frame. Otherwise the frame will be stuck and
|
|
* an offchannel frame. Otherwise the frame will be stuck and
|
|
@@ -3359,6 +3381,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
|
|
if (ret)
|
|
if (ret)
|
|
|
ath10k_warn(ar, "failed to create peer %pM on vdev %d: %d\n",
|
|
ath10k_warn(ar, "failed to create peer %pM on vdev %d: %d\n",
|
|
|
peer_addr, vdev_id, ret);
|
|
peer_addr, vdev_id, ret);
|
|
|
|
|
+ tmp_peer_created = (ret == 0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
spin_lock_bh(&ar->data_lock);
|
|
spin_lock_bh(&ar->data_lock);
|
|
@@ -3374,7 +3397,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
|
|
ath10k_warn(ar, "timed out waiting for offchannel skb %p\n",
|
|
ath10k_warn(ar, "timed out waiting for offchannel skb %p\n",
|
|
|
skb);
|
|
skb);
|
|
|
|
|
|
|
|
- if (!peer) {
|
|
|
|
|
|
|
+ if (!peer && tmp_peer_created) {
|
|
|
ret = ath10k_peer_delete(ar, vdev_id, peer_addr);
|
|
ret = ath10k_peer_delete(ar, vdev_id, peer_addr);
|
|
|
if (ret)
|
|
if (ret)
|
|
|
ath10k_warn(ar, "failed to delete peer %pM on vdev %d: %d\n",
|
|
ath10k_warn(ar, "failed to delete peer %pM on vdev %d: %d\n",
|
|
@@ -3600,6 +3623,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
|
|
|
ATH10K_SKB_CB(skb)->htt.is_offchan = false;
|
|
ATH10K_SKB_CB(skb)->htt.is_offchan = false;
|
|
|
ATH10K_SKB_CB(skb)->htt.freq = 0;
|
|
ATH10K_SKB_CB(skb)->htt.freq = 0;
|
|
|
ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
|
|
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)->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)->txmode = ath10k_tx_h_get_txmode(ar, vif, sta, skb);
|
|
|
ATH10K_SKB_CB(skb)->is_protected = ieee80211_has_protected(fc);
|
|
ATH10K_SKB_CB(skb)->is_protected = ieee80211_has_protected(fc);
|
|
@@ -3615,12 +3639,11 @@ static void ath10k_tx(struct ieee80211_hw *hw,
|
|
|
ath10k_tx_h_8023(skb);
|
|
ath10k_tx_h_8023(skb);
|
|
|
break;
|
|
break;
|
|
|
case ATH10K_HW_TXRX_RAW:
|
|
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) {
|
|
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
|
@@ -4019,6 +4042,43 @@ static u32 get_nss_from_chainmask(u16 chain_mask)
|
|
|
return 1;
|
|
return 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif)
|
|
|
|
|
+{
|
|
|
|
|
+ u32 value = 0;
|
|
|
|
|
+ struct ath10k *ar = arvif->ar;
|
|
|
|
|
+
|
|
|
|
|
+ if (ath10k_wmi_get_txbf_conf_scheme(ar) != WMI_TXBF_CONF_BEFORE_ASSOC)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
|
|
|
|
+ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE))
|
|
|
|
|
+ value |= SM((ar->num_rf_chains - 1), WMI_TXBF_STS_CAP_OFFSET);
|
|
|
|
|
+
|
|
|
|
|
+ if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
|
|
|
|
|
+ IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE))
|
|
|
|
|
+ value |= SM((ar->num_rf_chains - 1), WMI_BF_SOUND_DIM_OFFSET);
|
|
|
|
|
+
|
|
|
|
|
+ if (!value)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (ar->vht_cap_info & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)
|
|
|
|
|
+ value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
|
|
|
|
|
+
|
|
|
|
|
+ if (ar->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)
|
|
|
|
|
+ value |= (WMI_VDEV_PARAM_TXBF_MU_TX_BFER |
|
|
|
|
|
+ WMI_VDEV_PARAM_TXBF_SU_TX_BFER);
|
|
|
|
|
+
|
|
|
|
|
+ if (ar->vht_cap_info & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)
|
|
|
|
|
+ value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
|
|
|
|
|
+
|
|
|
|
|
+ if (ar->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)
|
|
|
|
|
+ value |= (WMI_VDEV_PARAM_TXBF_MU_TX_BFEE |
|
|
|
|
|
+ WMI_VDEV_PARAM_TXBF_SU_TX_BFEE);
|
|
|
|
|
+
|
|
|
|
|
+ return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
|
|
|
|
|
+ ar->wmi.vdev_param->txbf, value);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* TODO:
|
|
* TODO:
|
|
|
* Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
|
|
* Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
|
|
@@ -4060,6 +4120,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|
|
sizeof(arvif->bitrate_mask.control[i].vht_mcs));
|
|
sizeof(arvif->bitrate_mask.control[i].vht_mcs));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (ar->num_peers >= ar->max_num_peers) {
|
|
|
|
|
+ ath10k_warn(ar, "refusing vdev creation due to insufficient peer entry resources in firmware\n");
|
|
|
|
|
+ return -ENOBUFS;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (ar->free_vdev_map == 0) {
|
|
if (ar->free_vdev_map == 0) {
|
|
|
ath10k_warn(ar, "Free vdev map is empty, no more interfaces allowed.\n");
|
|
ath10k_warn(ar, "Free vdev map is empty, no more interfaces allowed.\n");
|
|
|
ret = -EBUSY;
|
|
ret = -EBUSY;
|
|
@@ -4139,6 +4204,14 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|
|
goto err;
|
|
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",
|
|
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,
|
|
arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
|
|
@@ -4237,16 +4310,16 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ret = ath10k_mac_set_rts(arvif, ar->hw->wiphy->rts_threshold);
|
|
|
|
|
|
|
+ ret = ath10k_mac_set_txbf_conf(arvif);
|
|
|
if (ret) {
|
|
if (ret) {
|
|
|
- ath10k_warn(ar, "failed to set rts threshold for vdev %d: %d\n",
|
|
|
|
|
|
|
+ ath10k_warn(ar, "failed to set txbf for vdev %d: %d\n",
|
|
|
arvif->vdev_id, ret);
|
|
arvif->vdev_id, ret);
|
|
|
goto err_peer_delete;
|
|
goto err_peer_delete;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ret = ath10k_mac_set_frag(arvif, ar->hw->wiphy->frag_threshold);
|
|
|
|
|
|
|
+ ret = ath10k_mac_set_rts(arvif, ar->hw->wiphy->rts_threshold);
|
|
|
if (ret) {
|
|
if (ret) {
|
|
|
- ath10k_warn(ar, "failed to set frag threshold for vdev %d: %d\n",
|
|
|
|
|
|
|
+ ath10k_warn(ar, "failed to set rts threshold for vdev %d: %d\n",
|
|
|
arvif->vdev_id, ret);
|
|
arvif->vdev_id, ret);
|
|
|
goto err_peer_delete;
|
|
goto err_peer_delete;
|
|
|
}
|
|
}
|
|
@@ -4728,6 +4801,9 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
|
if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
|
|
if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
|
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
+ if (arvif->nohwcrypt)
|
|
|
|
|
+ return 1;
|
|
|
|
|
+
|
|
|
if (key->keyidx > WMI_MAX_KEY_INDEX)
|
|
if (key->keyidx > WMI_MAX_KEY_INDEX)
|
|
|
return -ENOSPC;
|
|
return -ENOSPC;
|
|
|
|
|
|
|
@@ -4797,6 +4873,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);
|
|
ret = ath10k_install_key(arvif, key, cmd, peer_addr, flags);
|
|
|
if (ret) {
|
|
if (ret) {
|
|
|
|
|
+ WARN_ON(ret > 0);
|
|
|
ath10k_warn(ar, "failed to install key for vdev %i peer %pM: %d\n",
|
|
ath10k_warn(ar, "failed to install key for vdev %i peer %pM: %d\n",
|
|
|
arvif->vdev_id, peer_addr, ret);
|
|
arvif->vdev_id, peer_addr, ret);
|
|
|
goto exit;
|
|
goto exit;
|
|
@@ -4812,13 +4889,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);
|
|
ret = ath10k_install_key(arvif, key, cmd, peer_addr, flags2);
|
|
|
if (ret) {
|
|
if (ret) {
|
|
|
|
|
+ WARN_ON(ret > 0);
|
|
|
ath10k_warn(ar, "failed to install (ucast) key for vdev %i peer %pM: %d\n",
|
|
ath10k_warn(ar, "failed to install (ucast) key for vdev %i peer %pM: %d\n",
|
|
|
arvif->vdev_id, peer_addr, ret);
|
|
arvif->vdev_id, peer_addr, ret);
|
|
|
ret2 = ath10k_install_key(arvif, key, DISABLE_KEY,
|
|
ret2 = ath10k_install_key(arvif, key, DISABLE_KEY,
|
|
|
peer_addr, flags);
|
|
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",
|
|
ath10k_warn(ar, "failed to disable (mcast) key for vdev %i peer %pM: %d\n",
|
|
|
arvif->vdev_id, peer_addr, ret2);
|
|
arvif->vdev_id, peer_addr, ret2);
|
|
|
|
|
+ }
|
|
|
goto exit;
|
|
goto exit;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -5545,6 +5625,21 @@ static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
|
|
return ret;
|
|
return ret;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int ath10k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
|
|
|
|
|
+{
|
|
|
|
|
+ /* Even though there's a WMI enum for fragmentation threshold no known
|
|
|
|
|
+ * firmware actually implements it. Moreover it is not possible to rely
|
|
|
|
|
+ * frame fragmentation to mac80211 because firmware clears the "more
|
|
|
|
|
+ * fragments" bit in frame control making it impossible for remote
|
|
|
|
|
+ * devices to reassemble frames.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Hence implement a dummy callback just to say fragmentation isn't
|
|
|
|
|
+ * supported. This effectively prevents mac80211 from doing frame
|
|
|
|
|
+ * fragmentation in software.
|
|
|
|
|
+ */
|
|
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|
static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|
|
u32 queues, bool drop)
|
|
u32 queues, bool drop)
|
|
|
{
|
|
{
|
|
@@ -6387,6 +6482,7 @@ static const struct ieee80211_ops ath10k_ops = {
|
|
|
.remain_on_channel = ath10k_remain_on_channel,
|
|
.remain_on_channel = ath10k_remain_on_channel,
|
|
|
.cancel_remain_on_channel = ath10k_cancel_remain_on_channel,
|
|
.cancel_remain_on_channel = ath10k_cancel_remain_on_channel,
|
|
|
.set_rts_threshold = ath10k_set_rts_threshold,
|
|
.set_rts_threshold = ath10k_set_rts_threshold,
|
|
|
|
|
+ .set_frag_threshold = ath10k_mac_op_set_frag_threshold,
|
|
|
.flush = ath10k_flush,
|
|
.flush = ath10k_flush,
|
|
|
.tx_last_beacon = ath10k_tx_last_beacon,
|
|
.tx_last_beacon = ath10k_tx_last_beacon,
|
|
|
.set_antenna = ath10k_set_antenna,
|
|
.set_antenna = ath10k_set_antenna,
|
|
@@ -6892,7 +6988,6 @@ int ath10k_mac_register(struct ath10k *ar)
|
|
|
ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);
|
|
ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);
|
|
|
ieee80211_hw_set(ar->hw, AP_LINK_PS);
|
|
ieee80211_hw_set(ar->hw, AP_LINK_PS);
|
|
|
ieee80211_hw_set(ar->hw, SPECTRUM_MGMT);
|
|
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, SUPPORT_FAST_XMIT);
|
|
|
ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);
|
|
ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);
|
|
|
ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);
|
|
ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);
|
|
@@ -6900,6 +6995,9 @@ int ath10k_mac_register(struct ath10k *ar)
|
|
|
ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
|
|
ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
|
|
|
ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
|
|
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->features |= NL80211_FEATURE_STATIC_SMPS;
|
|
|
ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
|
ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
|
|
|
|
|
|
@@ -7003,7 +7101,8 @@ int ath10k_mac_register(struct ath10k *ar)
|
|
|
goto err_free;
|
|
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)) {
|
|
if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
|
|
|
/* Init ath dfs pattern detector */
|
|
/* Init ath dfs pattern detector */
|