diff options
-rw-r--r-- | net/mac80211/ibss.c | 81 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/scan.c | 25 |
3 files changed, 97 insertions, 12 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 6da4e72f8178..8f8391e008ed 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -1270,7 +1270,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
1270 | 1270 | ||
1271 | scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef); | 1271 | scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef); |
1272 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, | 1272 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, |
1273 | NULL, scan_width); | 1273 | NULL, 0, scan_width); |
1274 | } | 1274 | } |
1275 | 1275 | ||
1276 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | 1276 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) |
@@ -1307,6 +1307,76 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
1307 | capability, 0, true); | 1307 | capability, 0, true); |
1308 | } | 1308 | } |
1309 | 1309 | ||
1310 | static unsigned ibss_setup_channels(struct wiphy *wiphy, | ||
1311 | struct ieee80211_channel **channels, | ||
1312 | unsigned int channels_max, | ||
1313 | u32 center_freq, u32 width) | ||
1314 | { | ||
1315 | struct ieee80211_channel *chan = NULL; | ||
1316 | unsigned int n_chan = 0; | ||
1317 | u32 start_freq, end_freq, freq; | ||
1318 | |||
1319 | if (width <= 20) { | ||
1320 | start_freq = center_freq; | ||
1321 | end_freq = center_freq; | ||
1322 | } else { | ||
1323 | start_freq = center_freq - width / 2 + 10; | ||
1324 | end_freq = center_freq + width / 2 - 10; | ||
1325 | } | ||
1326 | |||
1327 | for (freq = start_freq; freq <= end_freq; freq += 20) { | ||
1328 | chan = ieee80211_get_channel(wiphy, freq); | ||
1329 | if (!chan) | ||
1330 | continue; | ||
1331 | if (n_chan >= channels_max) | ||
1332 | return n_chan; | ||
1333 | |||
1334 | channels[n_chan] = chan; | ||
1335 | n_chan++; | ||
1336 | } | ||
1337 | |||
1338 | return n_chan; | ||
1339 | } | ||
1340 | |||
1341 | static unsigned int | ||
1342 | ieee80211_ibss_setup_scan_channels(struct wiphy *wiphy, | ||
1343 | const struct cfg80211_chan_def *chandef, | ||
1344 | struct ieee80211_channel **channels, | ||
1345 | unsigned int channels_max) | ||
1346 | { | ||
1347 | unsigned int n_chan = 0; | ||
1348 | u32 width, cf1, cf2 = 0; | ||
1349 | |||
1350 | switch (chandef->width) { | ||
1351 | case NL80211_CHAN_WIDTH_40: | ||
1352 | width = 40; | ||
1353 | break; | ||
1354 | case NL80211_CHAN_WIDTH_80P80: | ||
1355 | cf2 = chandef->center_freq2; | ||
1356 | /* fall through */ | ||
1357 | case NL80211_CHAN_WIDTH_80: | ||
1358 | width = 80; | ||
1359 | break; | ||
1360 | case NL80211_CHAN_WIDTH_160: | ||
1361 | width = 160; | ||
1362 | break; | ||
1363 | default: | ||
1364 | width = 20; | ||
1365 | break; | ||
1366 | } | ||
1367 | |||
1368 | cf1 = chandef->center_freq1; | ||
1369 | |||
1370 | n_chan = ibss_setup_channels(wiphy, channels, channels_max, cf1, width); | ||
1371 | |||
1372 | if (cf2) | ||
1373 | n_chan += ibss_setup_channels(wiphy, &channels[n_chan], | ||
1374 | channels_max - n_chan, cf2, | ||
1375 | width); | ||
1376 | |||
1377 | return n_chan; | ||
1378 | } | ||
1379 | |||
1310 | /* | 1380 | /* |
1311 | * This function is called with state == IEEE80211_IBSS_MLME_SEARCH | 1381 | * This function is called with state == IEEE80211_IBSS_MLME_SEARCH |
1312 | */ | 1382 | */ |
@@ -1372,11 +1442,18 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
1372 | /* Selected IBSS not found in current scan results - try to scan */ | 1442 | /* Selected IBSS not found in current scan results - try to scan */ |
1373 | if (time_after(jiffies, ifibss->last_scan_completed + | 1443 | if (time_after(jiffies, ifibss->last_scan_completed + |
1374 | IEEE80211_SCAN_INTERVAL)) { | 1444 | IEEE80211_SCAN_INTERVAL)) { |
1445 | struct ieee80211_channel *channels[8]; | ||
1446 | unsigned int num; | ||
1447 | |||
1375 | sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); | 1448 | sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); |
1376 | 1449 | ||
1450 | num = ieee80211_ibss_setup_scan_channels(local->hw.wiphy, | ||
1451 | &ifibss->chandef, | ||
1452 | channels, | ||
1453 | ARRAY_SIZE(channels)); | ||
1377 | scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef); | 1454 | scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef); |
1378 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, | 1455 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, |
1379 | ifibss->ssid_len, chan, | 1456 | ifibss->ssid_len, channels, num, |
1380 | scan_width); | 1457 | scan_width); |
1381 | } else { | 1458 | } else { |
1382 | int interval = IEEE80211_SCAN_INTERVAL; | 1459 | int interval = IEEE80211_SCAN_INTERVAL; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3e3cfe8da4ef..3331c62b4433 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1529,7 +1529,8 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata); | |||
1529 | void ieee80211_scan_work(struct work_struct *work); | 1529 | void ieee80211_scan_work(struct work_struct *work); |
1530 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | 1530 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, |
1531 | const u8 *ssid, u8 ssid_len, | 1531 | const u8 *ssid, u8 ssid_len, |
1532 | struct ieee80211_channel *chan, | 1532 | struct ieee80211_channel **channels, |
1533 | unsigned int n_channels, | ||
1533 | enum nl80211_bss_scan_width scan_width); | 1534 | enum nl80211_bss_scan_width scan_width); |
1534 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 1535 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
1535 | struct cfg80211_scan_request *req); | 1536 | struct cfg80211_scan_request *req); |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 05f0d711b6d8..7bb6a9383f58 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -928,11 +928,12 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |||
928 | 928 | ||
929 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | 929 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, |
930 | const u8 *ssid, u8 ssid_len, | 930 | const u8 *ssid, u8 ssid_len, |
931 | struct ieee80211_channel *chan, | 931 | struct ieee80211_channel **channels, |
932 | unsigned int n_channels, | ||
932 | enum nl80211_bss_scan_width scan_width) | 933 | enum nl80211_bss_scan_width scan_width) |
933 | { | 934 | { |
934 | struct ieee80211_local *local = sdata->local; | 935 | struct ieee80211_local *local = sdata->local; |
935 | int ret = -EBUSY; | 936 | int ret = -EBUSY, i, n_ch = 0; |
936 | enum ieee80211_band band; | 937 | enum ieee80211_band band; |
937 | 938 | ||
938 | mutex_lock(&local->mtx); | 939 | mutex_lock(&local->mtx); |
@@ -942,9 +943,8 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | |||
942 | goto unlock; | 943 | goto unlock; |
943 | 944 | ||
944 | /* fill internal scan request */ | 945 | /* fill internal scan request */ |
945 | if (!chan) { | 946 | if (!channels) { |
946 | int i, max_n; | 947 | int max_n; |
947 | int n_ch = 0; | ||
948 | 948 | ||
949 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 949 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
950 | if (!local->hw.wiphy->bands[band]) | 950 | if (!local->hw.wiphy->bands[band]) |
@@ -969,12 +969,19 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | |||
969 | 969 | ||
970 | local->int_scan_req->n_channels = n_ch; | 970 | local->int_scan_req->n_channels = n_ch; |
971 | } else { | 971 | } else { |
972 | if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IR | | 972 | for (i = 0; i < n_channels; i++) { |
973 | IEEE80211_CHAN_DISABLED))) | 973 | if (channels[i]->flags & (IEEE80211_CHAN_NO_IR | |
974 | IEEE80211_CHAN_DISABLED)) | ||
975 | continue; | ||
976 | |||
977 | local->int_scan_req->channels[n_ch] = channels[i]; | ||
978 | n_ch++; | ||
979 | } | ||
980 | |||
981 | if (WARN_ON_ONCE(n_ch == 0)) | ||
974 | goto unlock; | 982 | goto unlock; |
975 | 983 | ||
976 | local->int_scan_req->channels[0] = chan; | 984 | local->int_scan_req->n_channels = n_ch; |
977 | local->int_scan_req->n_channels = 1; | ||
978 | } | 985 | } |
979 | 986 | ||
980 | local->int_scan_req->ssids = &local->scan_ssid; | 987 | local->int_scan_req->ssids = &local->scan_ssid; |