Josh Boyer 2df5ebe
Do not scan on no-IBSS and disabled channels in IBSS mode. Doing this
Josh Boyer 2df5ebe
can trigger Microcode errors on iwlwifi and iwlegacy drivers.
Josh Boyer 2df5ebe
Josh Boyer 2df5ebe
Also rename ieee80211_request_internal_scan() function since it is only
Josh Boyer 2df5ebe
used in IBSS mode and simplify calling it from ieee80211_sta_find_ibss().
Josh Boyer 2df5ebe
Josh Boyer 2df5ebe
This patch should address:
Josh Boyer 2df5ebe
https://bugzilla.redhat.com/show_bug.cgi?id=883414
Josh Boyer 2df5ebe
https://bugzilla.kernel.org/show_bug.cgi?id=49411
Josh Boyer 2df5ebe
Josh Boyer 2df5ebe
Reported-by: Jesse Kahtava <jesse_kahtava@f-m.fm>
Josh Boyer 2df5ebe
Reported-by: Mikko Rapeli  <mikko.rapeli@iki.fi>
Josh Boyer 2df5ebe
Cc: stable@vger.kernel.org
Josh Boyer 2df5ebe
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Josh Boyer 2df5ebe
---
Josh Boyer 2df5ebe
 net/mac80211/ibss.c        |    9 ++++-----
Josh Boyer 2df5ebe
 net/mac80211/ieee80211_i.h |    6 +++---
Josh Boyer 2df5ebe
 net/mac80211/scan.c        |   34 ++++++++++++++++++++++++----------
Josh Boyer 2df5ebe
 3 files changed, 31 insertions(+), 18 deletions(-)
Josh Boyer 2df5ebe
Josh Boyer 2df5ebe
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
Josh Boyer 2df5ebe
index c21e33d..d9df6b8 100644
Josh Boyer 2df5ebe
--- a/net/mac80211/ibss.c
Josh Boyer 2df5ebe
+++ b/net/mac80211/ibss.c
Josh Boyer 2df5ebe
@@ -678,8 +678,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
Josh Boyer 2df5ebe
 	sdata_info(sdata,
Josh Boyer 2df5ebe
 		   "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n");
Josh Boyer 2df5ebe
 
Josh Boyer 2df5ebe
-	ieee80211_request_internal_scan(sdata,
Josh Boyer 2df5ebe
-			ifibss->ssid, ifibss->ssid_len, NULL);
Josh Boyer 2df5ebe
+	ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len,
Josh Boyer 2df5ebe
+				    NULL);
Josh Boyer 2df5ebe
 }
Josh Boyer 2df5ebe
 
Josh Boyer 2df5ebe
 static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
Josh Boyer 2df5ebe
@@ -777,9 +777,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
Josh Boyer 2df5ebe
 					IEEE80211_SCAN_INTERVAL)) {
Josh Boyer 2df5ebe
 		sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");
Josh Boyer 2df5ebe
 
Josh Boyer 2df5ebe
-		ieee80211_request_internal_scan(sdata,
Josh Boyer 2df5ebe
-				ifibss->ssid, ifibss->ssid_len,
Josh Boyer 2df5ebe
-				ifibss->fixed_channel ? ifibss->channel : NULL);
Josh Boyer 2df5ebe
+		ieee80211_request_ibss_scan(sdata, ifibss->ssid,
Josh Boyer 2df5ebe
+					    ifibss->ssid_len, chan);
Josh Boyer 2df5ebe
 	} else {
Josh Boyer 2df5ebe
 		int interval = IEEE80211_SCAN_INTERVAL;
Josh Boyer 2df5ebe
 
Josh Boyer 2df5ebe
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
Josh Boyer 2df5ebe
index 156e583..bc48d4d 100644
Josh Boyer 2df5ebe
--- a/net/mac80211/ieee80211_i.h
Josh Boyer 2df5ebe
+++ b/net/mac80211/ieee80211_i.h
Josh Boyer 2df5ebe
@@ -1247,9 +1247,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
Josh Boyer 2df5ebe
 
Josh Boyer 2df5ebe
 /* scan/BSS handling */
Josh Boyer 2df5ebe
 void ieee80211_scan_work(struct work_struct *work);
Josh Boyer 2df5ebe
-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
Josh Boyer 2df5ebe
-				    const u8 *ssid, u8 ssid_len,
Josh Boyer 2df5ebe
-				    struct ieee80211_channel *chan);
Josh Boyer 2df5ebe
+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
Josh Boyer 2df5ebe
+				const u8 *ssid, u8 ssid_len,
Josh Boyer 2df5ebe
+				struct ieee80211_channel *chan);
Josh Boyer 2df5ebe
 int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
Josh Boyer 2df5ebe
 			   struct cfg80211_scan_request *req);
Josh Boyer 2df5ebe
 void ieee80211_scan_cancel(struct ieee80211_local *local);
Josh Boyer 2df5ebe
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
Josh Boyer 2df5ebe
index 43e60b5..fab706f 100644
Josh Boyer 2df5ebe
--- a/net/mac80211/scan.c
Josh Boyer 2df5ebe
+++ b/net/mac80211/scan.c
Josh Boyer 2df5ebe
@@ -819,9 +819,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
Josh Boyer 2df5ebe
 	return res;
Josh Boyer 2df5ebe
 }
Josh Boyer 2df5ebe
 
Josh Boyer 2df5ebe
-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
Josh Boyer 2df5ebe
-				    const u8 *ssid, u8 ssid_len,
Josh Boyer 2df5ebe
-				    struct ieee80211_channel *chan)
Josh Boyer 2df5ebe
+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
Josh Boyer 2df5ebe
+				const u8 *ssid, u8 ssid_len,
Josh Boyer 2df5ebe
+				struct ieee80211_channel *chan)
Josh Boyer 2df5ebe
 {
Josh Boyer 2df5ebe
 	struct ieee80211_local *local = sdata->local;
Josh Boyer 2df5ebe
 	int ret = -EBUSY;
Josh Boyer 2df5ebe
@@ -835,22 +835,36 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
Josh Boyer 2df5ebe
 
Josh Boyer 2df5ebe
 	/* fill internal scan request */
Josh Boyer 2df5ebe
 	if (!chan) {
Josh Boyer 2df5ebe
-		int i, nchan = 0;
Josh Boyer 2df5ebe
+		int i, max_n;
Josh Boyer 2df5ebe
+		int n_ch = 0;
Josh Boyer 2df5ebe
 
Josh Boyer 2df5ebe
 		for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
Josh Boyer 2df5ebe
 			if (!local->hw.wiphy->bands[band])
Josh Boyer 2df5ebe
 				continue;
Josh Boyer 2df5ebe
-			for (i = 0;
Josh Boyer 2df5ebe
-			     i < local->hw.wiphy->bands[band]->n_channels;
Josh Boyer 2df5ebe
-			     i++) {
Josh Boyer 2df5ebe
-				local->int_scan_req->channels[nchan] =
Josh Boyer 2df5ebe
+
Josh Boyer 2df5ebe
+			max_n = local->hw.wiphy->bands[band]->n_channels;
Josh Boyer 2df5ebe
+			for (i = 0; i < max_n; i++) {
Josh Boyer 2df5ebe
+				struct ieee80211_channel *tmp_ch =
Josh Boyer 2df5ebe
 				    &local->hw.wiphy->bands[band]->channels[i];
Josh Boyer 2df5ebe
-				nchan++;
Josh Boyer 2df5ebe
+
Josh Boyer 2df5ebe
+				if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS |
Josh Boyer 2df5ebe
+						     IEEE80211_CHAN_DISABLED))
Josh Boyer 2df5ebe
+					continue;
Josh Boyer 2df5ebe
+
Josh Boyer 2df5ebe
+				local->int_scan_req->channels[n_ch] = tmp_ch;
Josh Boyer 2df5ebe
+				n_ch++;
Josh Boyer 2df5ebe
 			}
Josh Boyer 2df5ebe
 		}
Josh Boyer 2df5ebe
 
Josh Boyer 2df5ebe
-		local->int_scan_req->n_channels = nchan;
Josh Boyer 2df5ebe
+		if (WARN_ON_ONCE(n_ch == 0))
Josh Boyer 2df5ebe
+			goto unlock;
Josh Boyer 2df5ebe
+
Josh Boyer 2df5ebe
+		local->int_scan_req->n_channels = n_ch;
Josh Boyer 2df5ebe
 	} else {
Josh Boyer 2df5ebe
+		if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS |
Josh Boyer 2df5ebe
+						IEEE80211_CHAN_DISABLED)))
Josh Boyer 2df5ebe
+			goto unlock;
Josh Boyer 2df5ebe
+
Josh Boyer 2df5ebe
 		local->int_scan_req->channels[0] = chan;
Josh Boyer 2df5ebe
 		local->int_scan_req->n_channels = 1;
Josh Boyer 2df5ebe
 	}
Josh Boyer 2df5ebe
-- 
Josh Boyer 2df5ebe
1.7.1
Josh Boyer 2df5ebe
Josh Boyer 2df5ebe
--
Josh Boyer 2df5ebe
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
Josh Boyer 2df5ebe
the body of a message to majordomo@vger.kernel.org
Josh Boyer 2df5ebe
More majordomo info at  http://vger.kernel.org/majordomo-info.html