mac80211: avoid reconfig if no interfaces are up
[platform/kernel/linux-starfive.git] / net / mac80211 / util.c
index 745a8a9..0f9bf47 100644 (file)
@@ -1339,6 +1339,7 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
        int ext_rates_len;
        int shift;
        u32 rate_flags;
+       bool have_80mhz = false;
 
        *offset = 0;
 
@@ -1467,7 +1468,15 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
                *offset = noffset;
        }
 
-       if (sband->vht_cap.vht_supported) {
+       /* Check if any channel in this sband supports at least 80 MHz */
+       for (i = 0; i < sband->n_channels; i++) {
+               if (!(sband->channels[i].flags & IEEE80211_CHAN_NO_80MHZ)) {
+                       have_80mhz = true;
+                       break;
+               }
+       }
+
+       if (sband->vht_cap.vht_supported && have_80mhz) {
                if (end - pos < 2 + sizeof(struct ieee80211_vht_cap))
                        goto out_err;
                pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap,
@@ -1523,7 +1532,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 };
 
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
-                                         u8 *dst, u32 ratemask,
+                                         const u8 *src, const u8 *dst,
+                                         u32 ratemask,
                                          struct ieee80211_channel *chan,
                                          const u8 *ssid, size_t ssid_len,
                                          const u8 *ie, size_t ie_len,
@@ -1548,8 +1558,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
        else
                chandef.chan = chan;
 
-       skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
-                                    ssid, ssid_len, 100 + ie_len);
+       skb = ieee80211_probereq_get(&local->hw, src, ssid, ssid_len,
+                                    100 + ie_len);
        if (!skb)
                return NULL;
 
@@ -1571,7 +1581,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
        return skb;
 }
 
-void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
+void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata,
+                             const u8 *src, const u8 *dst,
                              const u8 *ssid, size_t ssid_len,
                              const u8 *ie, size_t ie_len,
                              u32 ratemask, bool directed, u32 tx_flags,
@@ -1579,7 +1590,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 {
        struct sk_buff *skb;
 
-       skb = ieee80211_build_probe_req(sdata, dst, ratemask, channel,
+       skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel,
                                        ssid, ssid_len,
                                        ie, ie_len, directed);
        if (skb) {
@@ -1721,8 +1732,13 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        int res, i;
        bool reconfig_due_to_wowlan = false;
        struct ieee80211_sub_if_data *sched_scan_sdata;
+       struct cfg80211_sched_scan_request *sched_scan_req;
        bool sched_scan_stopped = false;
 
+       /* nothing to do if HW shouldn't run */
+       if (!local->open_count)
+               goto wake_up;
+
 #ifdef CONFIG_PM
        if (local->suspended)
                local->resuming = true;
@@ -1744,9 +1760,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                reconfig_due_to_wowlan = true;
        }
 #endif
-       /* everything else happens only if HW was up & running */
-       if (!local->open_count)
-               goto wake_up;
 
        /*
         * Upon resume hardware can sometimes be goofy due to
@@ -2011,13 +2024,15 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        mutex_lock(&local->mtx);
        sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
                                                lockdep_is_held(&local->mtx));
-       if (sched_scan_sdata && local->sched_scan_req)
+       sched_scan_req = rcu_dereference_protected(local->sched_scan_req,
+                                               lockdep_is_held(&local->mtx));
+       if (sched_scan_sdata && sched_scan_req)
                /*
                 * Sched scan stopped, but we don't want to report it. Instead,
                 * we're trying to reschedule.
                 */
                if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
-                                                        local->sched_scan_req))
+                                                        sched_scan_req))
                        sched_scan_stopped = true;
        mutex_unlock(&local->mtx);
 
@@ -2028,7 +2043,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
         * If this is for hw restart things are still running.
         * We may want to change that later, however.
         */
-       if (!local->suspended || reconfig_due_to_wowlan)
+       if (local->open_count && (!local->suspended || reconfig_due_to_wowlan))
                drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
 
        if (!local->suspended)
@@ -2040,7 +2055,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        mb();
        local->resuming = false;
 
-       if (!reconfig_due_to_wowlan)
+       if (local->open_count && !reconfig_due_to_wowlan)
                drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);
 
        list_for_each_entry(sdata, &local->interfaces, list) {