summary refs log tree commit diff
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@intel.com>2015-03-01 09:10:04 +0200
committerJohannes Berg <johannes.berg@intel.com>2015-03-03 15:56:09 +0100
commitc8fff3dc72817d476e083c3f9bc59a11901ecfeb (patch)
treeef86e843cb03fa92654f000b7b7f85e70ac8b023 /net/mac80211/util.c
parentbe72afe0a43825ea357bf61f01ff8fe9938fe7d4 (diff)
downloadlinux-c8fff3dc72817d476e083c3f9bc59a11901ecfeb.tar.gz
mac80211: handle drv_add_interface failures properly during reconfig
If any interface fails to be added to the driver in during reconfig,
we should remove all the successfully added interfaces and report
reconfig failure, so things can be cleaned up properly.  Failing to do
so can lead to subsequent failures and leave the drivers in a messed
up state.

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index eec94447eef7..327886748a1d 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1811,8 +1811,25 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 		    sdata->vif.type != NL80211_IFTYPE_MONITOR &&
-		    ieee80211_sdata_running(sdata))
+		    ieee80211_sdata_running(sdata)) {
 			res = drv_add_interface(local, sdata);
+			if (WARN_ON(res))
+				break;
+		}
+	}
+
+	/* If adding any of the interfaces failed above, roll back and
+	 * report failure.
+	 */
+	if (res) {
+		list_for_each_entry_continue_reverse(sdata, &local->interfaces,
+						     list)
+			if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+			    sdata->vif.type != NL80211_IFTYPE_MONITOR &&
+			    ieee80211_sdata_running(sdata))
+				drv_remove_interface(local, sdata);
+		ieee80211_handle_reconfig_failure(local);
+		return res;
 	}
 
 	/* add channel contexts */