ath10k handles some hw configuration per-vdev
(i.e. per-vif). When resuming/restarting hw
configuration vdevs may not be re-added yet.

Setting vdev params for non existent vdevs crashes
the firmware.

The parameters are updated when interface is
re-added.

Signed-off-by: Michal Kazior <michal.kaz...@tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c |   55 ++++++++++++++++++++++++---------
 1 file changed, 41 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c 
b/drivers/net/wireless/ath/ath10k/mac.c
index ebdaf1a..c64e7be 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1808,13 +1808,35 @@ static void ath10k_stop(struct ieee80211_hw *hw)
        cancel_work_sync(&ar->offchan_tx_work);
 }
 
-static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
+static void ath10k_config_ps(struct ath10k *ar)
 {
        struct ath10k_generic_iter ar_iter;
+
+       lockdep_assert_held(&ar->conf_mutex);
+
+       /* During HW reconfiguration mac80211 reports all interfaces that were
+        * running until reconfiguration was started. Since FW doesn't have any
+        * vdevs at this point we must not iterate over this interface list.
+        * This setting will be updated upon add_interface(). */
+       if (ar->state == ATH10K_STATE_RESTARTING)
+               return;
+
+       memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter));
+       ar_iter.ar = ar;
+
+       ieee80211_iterate_active_interfaces_atomic(
+               ar->hw, IEEE80211_IFACE_ITER_NORMAL,
+               ath10k_ps_iter, &ar_iter);
+
+       if (ar_iter.ret)
+               ath10k_warn("failed to set ps config (%d)\n", ar_iter.ret);
+}
+
+static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
+{
        struct ath10k *ar = hw->priv;
        struct ieee80211_conf *conf = &hw->conf;
        int ret = 0;
-       u32 flags;
 
        mutex_lock(&ar->conf_mutex);
 
@@ -1826,18 +1848,8 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 
changed)
                spin_unlock_bh(&ar->data_lock);
        }
 
-       if (changed & IEEE80211_CONF_CHANGE_PS) {
-               memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter));
-               ar_iter.ar = ar;
-               flags = IEEE80211_IFACE_ITER_RESUME_ALL;
-
-               ieee80211_iterate_active_interfaces_atomic(hw,
-                                                          flags,
-                                                          ath10k_ps_iter,
-                                                          &ar_iter);
-
-               ret = ar_iter.ret;
-       }
+       if (changed & IEEE80211_CONF_CHANGE_PS)
+               ath10k_config_ps(ar);
 
        if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
                if (conf->flags & IEEE80211_CONF_MONITOR)
@@ -1846,6 +1858,7 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 
changed)
                        ret = ath10k_monitor_destroy(ar);
        }
 
+       ath10k_wmi_flush_tx(ar);
        mutex_unlock(&ar->conf_mutex);
        return ret;
 }
@@ -2688,6 +2701,13 @@ static void ath10k_set_rts_iter(void *data, u8 *mac, 
struct ieee80211_vif *vif)
 
        lockdep_assert_held(&arvif->ar->conf_mutex);
 
+       /* During HW reconfiguration mac80211 reports all interfaces that were
+        * running until reconfiguration was started. Since FW doesn't have any
+        * vdevs at this point we must not iterate over this interface list.
+        * This setting will be updated upon add_interface(). */
+       if (ar_iter->ar->state == ATH10K_STATE_RESTARTING)
+               return;
+
        rts = min_t(u32, rts, ATH10K_RTS_MAX);
 
        ar_iter->ret = ath10k_wmi_vdev_set_param(ar_iter->ar, arvif->vdev_id,
@@ -2728,6 +2748,13 @@ static void ath10k_set_frag_iter(void *data, u8 *mac, 
struct ieee80211_vif *vif)
 
        lockdep_assert_held(&arvif->ar->conf_mutex);
 
+       /* During HW reconfiguration mac80211 reports all interfaces that were
+        * running until reconfiguration was started. Since FW doesn't have any
+        * vdevs at this point we must not iterate over this interface list.
+        * This setting will be updated upon add_interface(). */
+       if (ar_iter->ar->state == ATH10K_STATE_RESTARTING)
+               return;
+
        frag = clamp_t(u32, frag,
                       ATH10K_FRAGMT_THRESHOLD_MIN,
                       ATH10K_FRAGMT_THRESHOLD_MAX);
-- 
1.7.9.5

_______________________________________________
ath9k-devel mailing list
ath9k-devel@lists.ath9k.org
https://lists.ath9k.org/mailman/listinfo/ath9k-devel

Reply via email to