summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h10
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/mlme.c12
-rw-r--r--net/mac80211/util.c33
4 files changed, 55 insertions, 3 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index f118b8fe667a..b8e8c82b53aa 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -6071,6 +6071,16 @@ void ieee80211_disconnect(struct ieee80211_vif *vif, bool reconnect);
void ieee80211_resume_disconnect(struct ieee80211_vif *vif);
/**
+ * ieee80211_hw_restart_disconnect - disconnect from AP after
+ * hardware restart
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Instructs mac80211 to disconnect from the AP after
+ * hardware restart.
+ */
+void ieee80211_hw_restart_disconnect(struct ieee80211_vif *vif);
+
+/**
* ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring
* rssi threshold triggered
*
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 6a2421a066fb..b07ccfc44115 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -767,6 +767,8 @@ struct ieee80211_if_mesh {
* back to wireless media and to the local net stack.
* @IEEE80211_SDATA_DISCONNECT_RESUME: Disconnect after resume.
* @IEEE80211_SDATA_IN_DRIVER: indicates interface was added to driver
+ * @IEEE80211_SDATA_DISCONNECT_HW_RESTART: Disconnect after hardware restart
+ * recovery
*/
enum ieee80211_sub_if_data_flags {
IEEE80211_SDATA_ALLMULTI = BIT(0),
@@ -774,6 +776,7 @@ enum ieee80211_sub_if_data_flags {
IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3),
IEEE80211_SDATA_DISCONNECT_RESUME = BIT(4),
IEEE80211_SDATA_IN_DRIVER = BIT(5),
+ IEEE80211_SDATA_DISCONNECT_HW_RESTART = BIT(6),
};
/**
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 197cad4a2768..29bfce6b3561 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -4934,6 +4934,18 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
sdata_unlock(sdata);
return;
}
+
+ if (sdata->flags & IEEE80211_SDATA_DISCONNECT_HW_RESTART) {
+ sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_HW_RESTART;
+ mlme_dbg(sdata, "driver requested disconnect after hardware restart\n");
+ ieee80211_sta_connection_lost(sdata,
+ ifmgd->associated->bssid,
+ WLAN_REASON_UNSPECIFIED,
+ true);
+ sdata_unlock(sdata);
+ return;
+ }
+
sdata_unlock(sdata);
}
#endif
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index caea8dbd1d9b..682a164f795a 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2347,6 +2347,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
struct cfg80211_sched_scan_request *sched_scan_req;
bool sched_scan_stopped = false;
bool suspended = local->suspended;
+ bool in_reconfig = false;
/* nothing to do if HW shouldn't run */
if (!local->open_count)
@@ -2698,6 +2699,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
if (local->in_reconfig) {
+ in_reconfig = local->in_reconfig;
local->in_reconfig = false;
barrier();
@@ -2715,6 +2717,15 @@ int ieee80211_reconfig(struct ieee80211_local *local)
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
false);
+ if (in_reconfig) {
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!ieee80211_sdata_running(sdata))
+ continue;
+ if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ ieee80211_sta_restart(sdata);
+ }
+ }
+
if (!suspended)
return 0;
@@ -2744,7 +2755,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
return 0;
}
-void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
+static void ieee80211_reconfig_disconnect(struct ieee80211_vif *vif, u8 flag)
{
struct ieee80211_sub_if_data *sdata;
struct ieee80211_local *local;
@@ -2756,19 +2767,35 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
sdata = vif_to_sdata(vif);
local = sdata->local;
- if (WARN_ON(!local->resuming))
+ if (WARN_ON(flag & IEEE80211_SDATA_DISCONNECT_RESUME &&
+ !local->resuming))
+ return;
+
+ if (WARN_ON(flag & IEEE80211_SDATA_DISCONNECT_HW_RESTART &&
+ !local->in_reconfig))
return;
if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
return;
- sdata->flags |= IEEE80211_SDATA_DISCONNECT_RESUME;
+ sdata->flags |= flag;
mutex_lock(&local->key_mtx);
list_for_each_entry(key, &sdata->key_list, list)
key->flags |= KEY_FLAG_TAINTED;
mutex_unlock(&local->key_mtx);
}
+
+void ieee80211_hw_restart_disconnect(struct ieee80211_vif *vif)
+{
+ ieee80211_reconfig_disconnect(vif, IEEE80211_SDATA_DISCONNECT_HW_RESTART);
+}
+EXPORT_SYMBOL_GPL(ieee80211_hw_restart_disconnect);
+
+void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
+{
+ ieee80211_reconfig_disconnect(vif, IEEE80211_SDATA_DISCONNECT_RESUME);
+}
EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect);
void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata)