@@ -646,6 +646,24 @@ static struct ath12k *ath12k_get_ar_by_ctx(struct ieee80211_hw *hw,
return ath12k_mac_get_ar_by_chan(hw, ctx->def.chan);
}
+static struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
+
+ /* If there is one pdev within ah, then we return
+ * ar directly.
+ */
+ if (ah->num_radio == 1)
+ return ah->radio;
+
+ if (arvif->is_created)
+ return arvif->ar;
+
+ return NULL;
+}
+
static void ath12k_pdev_caps_update(struct ath12k *ar)
{
struct ath12k_base *ab = ar->ab;
@@ -2828,11 +2846,17 @@ static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *info,
u64 changed)
{
- struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- ar = ath12k_ah_to_ar(ah, 0);
+ ar = ath12k_get_ar_by_vif(hw, vif);
+
+ /* TODO if the vdev is not created on a certain radio,
+ * cache the info to be updated later on vdev creation
+ */
+
+ if (!ar)
+ return;
mutex_lock(&ar->conf_mutex);
@@ -3330,7 +3354,6 @@ static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
- struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
struct ath12k_base *ab;
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
@@ -3347,7 +3370,11 @@ static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
return 1;
- ar = ath12k_ah_to_ar(ah, 0);
+ ar = ath12k_get_ar_by_vif(hw, vif);
+ if (!ar) {
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
ab = ar->ab;
if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
@@ -3925,7 +3952,6 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state)
{
- struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
@@ -3937,7 +3963,11 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
new_state == IEEE80211_STA_NOTEXIST))
cancel_work_sync(&arsta->update_wk);
- ar = ath12k_ah_to_ar(ah, 0);
+ ar = ath12k_get_ar_by_vif(hw, vif);
+ if (!ar) {
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
mutex_lock(&ar->conf_mutex);
@@ -4081,14 +4111,17 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
u32 changed)
{
- struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct ath12k_peer *peer;
u32 bw, smps;
- ar = ath12k_ah_to_ar(ah, 0);
+ ar = ath12k_get_ar_by_vif(hw, vif);
+ if (!ar) {
+ WARN_ON_ONCE(1);
+ return;
+ }
spin_lock_bh(&ar->ab->base_lock);
@@ -4264,12 +4297,15 @@ static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw,
unsigned int link_id, u16 ac,
const struct ieee80211_tx_queue_params *params)
{
- struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
int ret;
- ar = ath12k_ah_to_ar(ah, 0);
+ ar = ath12k_get_ar_by_vif(hw, vif);
+ if (!ar) {
+ /* TODO cache the info and apply after vdev is created */
+ return -EINVAL;
+ }
mutex_lock(&ar->conf_mutex);
ret = ath12k_mac_conf_tx(arvif, link_id, ac, params);
@@ -6279,6 +6315,10 @@ static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
int ret = -EINVAL;
+ ar = ath12k_get_ar_by_vif(hw, vif);
+ if (!ar)
+ return -EINVAL;
+
ar = ath12k_ah_to_ar(ah, 0);
mutex_lock(&ar->conf_mutex);
@@ -7069,11 +7109,27 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
u32 queues, bool drop)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
- struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
+ struct ath12k *ar;
+ int i;
if (drop)
return;
+ /* vif can be NULL when flush() is considered for hw */
+ if (!vif) {
+ ar = ath12k_ah_to_ar(ah, 0);
+ for (i = 0; i < ah->num_radio; i++) {
+ ath12k_mac_flush(ar);
+ ar++;
+ }
+ return;
+ }
+
+ ar = ath12k_get_ar_by_vif(hw, vif);
+
+ if (!ar)
+ return;
+
ath12k_mac_flush(ar);
}