diff options
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r-- | drivers/net/wireless/libertas/scan.c | 145 |
1 files changed, 67 insertions, 78 deletions
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 99f11a56d84e..0598541451d8 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -260,24 +260,12 @@ done: | |||
260 | 260 | ||
261 | 261 | ||
262 | 262 | ||
263 | |||
264 | /*********************************************************************/ | 263 | /*********************************************************************/ |
265 | /* */ | 264 | /* */ |
266 | /* Main scanning support */ | 265 | /* Main scanning support */ |
267 | /* */ | 266 | /* */ |
268 | /*********************************************************************/ | 267 | /*********************************************************************/ |
269 | 268 | ||
270 | void lbs_scan_worker(struct work_struct *work) | ||
271 | { | ||
272 | struct lbs_private *priv = | ||
273 | container_of(work, struct lbs_private, scan_work.work); | ||
274 | |||
275 | lbs_deb_enter(LBS_DEB_SCAN); | ||
276 | lbs_scan_networks(priv, NULL, 0); | ||
277 | lbs_deb_leave(LBS_DEB_SCAN); | ||
278 | } | ||
279 | |||
280 | |||
281 | /** | 269 | /** |
282 | * @brief Create a channel list for the driver to scan based on region info | 270 | * @brief Create a channel list for the driver to scan based on region info |
283 | * | 271 | * |
@@ -289,17 +277,11 @@ void lbs_scan_worker(struct work_struct *work) | |||
289 | * | 277 | * |
290 | * @param priv A pointer to struct lbs_private structure | 278 | * @param priv A pointer to struct lbs_private structure |
291 | * @param scanchanlist Output parameter: resulting channel list to scan | 279 | * @param scanchanlist Output parameter: resulting channel list to scan |
292 | * @param filteredscan Flag indicating whether or not a BSSID or SSID filter | ||
293 | * is being sent in the command to firmware. Used to | ||
294 | * increase the number of channels sent in a scan | ||
295 | * command and to disable the firmware channel scan | ||
296 | * filter. | ||
297 | * | 280 | * |
298 | * @return void | 281 | * @return void |
299 | */ | 282 | */ |
300 | static int lbs_scan_create_channel_list(struct lbs_private *priv, | 283 | static int lbs_scan_create_channel_list(struct lbs_private *priv, |
301 | struct chanscanparamset *scanchanlist, | 284 | struct chanscanparamset *scanchanlist) |
302 | uint8_t filteredscan) | ||
303 | { | 285 | { |
304 | struct region_channel *scanregion; | 286 | struct region_channel *scanregion; |
305 | struct chan_freq_power *cfp; | 287 | struct chan_freq_power *cfp; |
@@ -354,9 +336,6 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
354 | } | 336 | } |
355 | 337 | ||
356 | chan->channumber = cfp->channel; | 338 | chan->channumber = cfp->channel; |
357 | |||
358 | if (filteredscan) | ||
359 | chan->chanscanmode.disablechanfilt = 1; | ||
360 | } | 339 | } |
361 | } | 340 | } |
362 | return chanidx; | 341 | return chanidx; |
@@ -370,15 +349,14 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
370 | * length 06 00 | 349 | * length 06 00 |
371 | * ssid 4d 4e 54 45 53 54 | 350 | * ssid 4d 4e 54 45 53 54 |
372 | */ | 351 | */ |
373 | static int lbs_scan_add_ssid_tlv(uint8_t *tlv, | 352 | static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv) |
374 | const struct lbs_ioctl_user_scan_cfg *user_cfg) | ||
375 | { | 353 | { |
376 | struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv; | 354 | struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv; |
377 | 355 | ||
378 | ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); | 356 | ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); |
379 | ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len); | 357 | ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len); |
380 | memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len); | 358 | memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len); |
381 | return sizeof(ssid_tlv->header) + user_cfg->ssid_len; | 359 | return sizeof(ssid_tlv->header) + priv->scan_ssid_len; |
382 | } | 360 | } |
383 | 361 | ||
384 | 362 | ||
@@ -461,8 +439,7 @@ static int lbs_scan_add_rates_tlv(uint8_t *tlv) | |||
461 | * for a bunch of channels. | 439 | * for a bunch of channels. |
462 | */ | 440 | */ |
463 | static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, | 441 | static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, |
464 | struct chanscanparamset *chan_list, int chan_count, | 442 | struct chanscanparamset *chan_list, int chan_count) |
465 | const struct lbs_ioctl_user_scan_cfg *user_cfg) | ||
466 | { | 443 | { |
467 | int ret = -ENOMEM; | 444 | int ret = -ENOMEM; |
468 | struct cmd_ds_802_11_scan *scan_cmd; | 445 | struct cmd_ds_802_11_scan *scan_cmd; |
@@ -477,13 +454,13 @@ static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, | |||
477 | goto out; | 454 | goto out; |
478 | 455 | ||
479 | tlv = scan_cmd->tlvbuffer; | 456 | tlv = scan_cmd->tlvbuffer; |
480 | if (user_cfg) | 457 | /* TODO: do we need to scan for a specific BSSID? |
481 | memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN); | 458 | memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */ |
482 | scan_cmd->bsstype = bsstype; | 459 | scan_cmd->bsstype = bsstype; |
483 | 460 | ||
484 | /* add TLVs */ | 461 | /* add TLVs */ |
485 | if (user_cfg && user_cfg->ssid_len) | 462 | if (priv->scan_ssid_len) |
486 | tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg); | 463 | tlv += lbs_scan_add_ssid_tlv(priv, tlv); |
487 | if (chan_list && chan_count) | 464 | if (chan_list && chan_count) |
488 | tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); | 465 | tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); |
489 | tlv += lbs_scan_add_rates_tlv(tlv); | 466 | tlv += lbs_scan_add_rates_tlv(tlv); |
@@ -516,14 +493,11 @@ out: | |||
516 | * update the internal driver scan table | 493 | * update the internal driver scan table |
517 | * | 494 | * |
518 | * @param priv A pointer to struct lbs_private structure | 495 | * @param priv A pointer to struct lbs_private structure |
519 | * @param puserscanin Pointer to the input configuration for the requested | 496 | * @param full_scan Do a full-scan (blocking) |
520 | * scan. | ||
521 | * | 497 | * |
522 | * @return 0 or < 0 if error | 498 | * @return 0 or < 0 if error |
523 | */ | 499 | */ |
524 | int lbs_scan_networks(struct lbs_private *priv, | 500 | static int lbs_scan_networks(struct lbs_private *priv, int full_scan) |
525 | const struct lbs_ioctl_user_scan_cfg *user_cfg, | ||
526 | int full_scan) | ||
527 | { | 501 | { |
528 | int ret = -ENOMEM; | 502 | int ret = -ENOMEM; |
529 | struct chanscanparamset *chan_list; | 503 | struct chanscanparamset *chan_list; |
@@ -531,7 +505,6 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
531 | int chan_count; | 505 | int chan_count; |
532 | uint8_t bsstype = CMD_BSS_TYPE_ANY; | 506 | uint8_t bsstype = CMD_BSS_TYPE_ANY; |
533 | int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; | 507 | int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; |
534 | int filteredscan = 0; | ||
535 | union iwreq_data wrqu; | 508 | union iwreq_data wrqu; |
536 | #ifdef CONFIG_LIBERTAS_DEBUG | 509 | #ifdef CONFIG_LIBERTAS_DEBUG |
537 | struct bss_descriptor *iter; | 510 | struct bss_descriptor *iter; |
@@ -547,17 +520,16 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
547 | if (full_scan && delayed_work_pending(&priv->scan_work)) | 520 | if (full_scan && delayed_work_pending(&priv->scan_work)) |
548 | cancel_delayed_work(&priv->scan_work); | 521 | cancel_delayed_work(&priv->scan_work); |
549 | 522 | ||
550 | /* Determine same scan parameters */ | 523 | /* User-specified bsstype or channel list |
524 | TODO: this can be implemented if some user-space application | ||
525 | need the feature. Formerly, it was accessible from debugfs, | ||
526 | but then nowhere used. | ||
551 | if (user_cfg) { | 527 | if (user_cfg) { |
552 | if (user_cfg->bsstype) | 528 | if (user_cfg->bsstype) |
553 | bsstype = user_cfg->bsstype; | 529 | bsstype = user_cfg->bsstype; |
554 | if (!is_zero_ether_addr(user_cfg->bssid)) { | 530 | } */ |
555 | numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN; | 531 | |
556 | filteredscan = 1; | 532 | lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype); |
557 | } | ||
558 | } | ||
559 | lbs_deb_scan("numchannels %d, bsstype %d, filteredscan %d\n", | ||
560 | numchannels, bsstype, filteredscan); | ||
561 | 533 | ||
562 | /* Create list of channels to scan */ | 534 | /* Create list of channels to scan */ |
563 | chan_list = kzalloc(sizeof(struct chanscanparamset) * | 535 | chan_list = kzalloc(sizeof(struct chanscanparamset) * |
@@ -568,7 +540,7 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
568 | } | 540 | } |
569 | 541 | ||
570 | /* We want to scan all channels */ | 542 | /* We want to scan all channels */ |
571 | chan_count = lbs_scan_create_channel_list(priv, chan_list, filteredscan); | 543 | chan_count = lbs_scan_create_channel_list(priv, chan_list); |
572 | 544 | ||
573 | netif_stop_queue(priv->dev); | 545 | netif_stop_queue(priv->dev); |
574 | netif_carrier_off(priv->dev); | 546 | netif_carrier_off(priv->dev); |
@@ -597,7 +569,7 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
597 | lbs_deb_scan("scanning %d of %d channels\n", | 569 | lbs_deb_scan("scanning %d of %d channels\n", |
598 | to_scan, chan_count); | 570 | to_scan, chan_count); |
599 | ret = lbs_do_scan(priv, bsstype, curr_chans, | 571 | ret = lbs_do_scan(priv, bsstype, curr_chans, |
600 | to_scan, user_cfg); | 572 | to_scan); |
601 | if (ret) { | 573 | if (ret) { |
602 | lbs_pr_err("SCAN_CMD failed\n"); | 574 | lbs_pr_err("SCAN_CMD failed\n"); |
603 | goto out2; | 575 | goto out2; |
@@ -658,6 +630,17 @@ out: | |||
658 | 630 | ||
659 | 631 | ||
660 | 632 | ||
633 | void lbs_scan_worker(struct work_struct *work) | ||
634 | { | ||
635 | struct lbs_private *priv = | ||
636 | container_of(work, struct lbs_private, scan_work.work); | ||
637 | |||
638 | lbs_deb_enter(LBS_DEB_SCAN); | ||
639 | lbs_scan_networks(priv, 0); | ||
640 | lbs_deb_leave(LBS_DEB_SCAN); | ||
641 | } | ||
642 | |||
643 | |||
661 | /*********************************************************************/ | 644 | /*********************************************************************/ |
662 | /* */ | 645 | /* */ |
663 | /* Result interpretation */ | 646 | /* Result interpretation */ |
@@ -1068,7 +1051,7 @@ static struct bss_descriptor *lbs_find_best_ssid_in_list(struct lbs_private *pri | |||
1068 | } | 1051 | } |
1069 | 1052 | ||
1070 | /** | 1053 | /** |
1071 | * @brief Find the AP with specific ssid in the scan list | 1054 | * @brief Find the best AP |
1072 | * | 1055 | * |
1073 | * Used from association worker. | 1056 | * Used from association worker. |
1074 | * | 1057 | * |
@@ -1086,7 +1069,8 @@ int lbs_find_best_network_ssid(struct lbs_private *priv, uint8_t *out_ssid, | |||
1086 | 1069 | ||
1087 | lbs_deb_enter(LBS_DEB_SCAN); | 1070 | lbs_deb_enter(LBS_DEB_SCAN); |
1088 | 1071 | ||
1089 | lbs_scan_networks(priv, NULL, 1); | 1072 | priv->scan_ssid_len = 0; |
1073 | lbs_scan_networks(priv, 1); | ||
1090 | if (priv->surpriseremoved) | 1074 | if (priv->surpriseremoved) |
1091 | goto out; | 1075 | goto out; |
1092 | 1076 | ||
@@ -1112,29 +1096,24 @@ out: | |||
1112 | * @param priv A pointer to struct lbs_private structure | 1096 | * @param priv A pointer to struct lbs_private structure |
1113 | * @param ssid A pointer to the SSID to scan for | 1097 | * @param ssid A pointer to the SSID to scan for |
1114 | * @param ssid_len Length of the SSID | 1098 | * @param ssid_len Length of the SSID |
1115 | * @param clear_ssid Should existing scan results with this SSID | ||
1116 | * be cleared? | ||
1117 | * | 1099 | * |
1118 | * @return 0-success, otherwise fail | 1100 | * @return 0-success, otherwise fail |
1119 | */ | 1101 | */ |
1120 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, | 1102 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, |
1121 | uint8_t ssid_len, uint8_t clear_ssid) | 1103 | uint8_t ssid_len) |
1122 | { | 1104 | { |
1123 | struct lbs_ioctl_user_scan_cfg scancfg; | ||
1124 | int ret = 0; | 1105 | int ret = 0; |
1125 | 1106 | ||
1126 | lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d", | 1107 | lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n", |
1127 | escape_essid(ssid, ssid_len), clear_ssid); | 1108 | escape_essid(ssid, ssid_len)); |
1128 | 1109 | ||
1129 | if (!ssid_len) | 1110 | if (!ssid_len) |
1130 | goto out; | 1111 | goto out; |
1131 | 1112 | ||
1132 | memset(&scancfg, 0x00, sizeof(scancfg)); | 1113 | memcpy(priv->scan_ssid, ssid, ssid_len); |
1133 | memcpy(scancfg.ssid, ssid, ssid_len); | 1114 | priv->scan_ssid_len = ssid_len; |
1134 | scancfg.ssid_len = ssid_len; | ||
1135 | scancfg.clear_ssid = clear_ssid; | ||
1136 | 1115 | ||
1137 | lbs_scan_networks(priv, &scancfg, 1); | 1116 | lbs_scan_networks(priv, 1); |
1138 | if (priv->surpriseremoved) { | 1117 | if (priv->surpriseremoved) { |
1139 | ret = -1; | 1118 | ret = -1; |
1140 | goto out; | 1119 | goto out; |
@@ -1317,27 +1296,36 @@ out: | |||
1317 | * @return 0 --success, otherwise fail | 1296 | * @return 0 --success, otherwise fail |
1318 | */ | 1297 | */ |
1319 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | 1298 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, |
1320 | struct iw_param *wrqu, char *extra) | 1299 | union iwreq_data *wrqu, char *extra) |
1321 | { | 1300 | { |
1322 | struct lbs_private *priv = dev->priv; | 1301 | struct lbs_private *priv = dev->priv; |
1302 | int ret = 0; | ||
1323 | 1303 | ||
1324 | lbs_deb_enter(LBS_DEB_SCAN); | 1304 | lbs_deb_enter(LBS_DEB_WEXT); |
1325 | 1305 | ||
1326 | if (!netif_running(dev)) | 1306 | if (!netif_running(dev)) { |
1327 | return -ENETDOWN; | 1307 | ret = -ENETDOWN; |
1308 | goto out; | ||
1309 | } | ||
1328 | 1310 | ||
1329 | /* mac80211 does this: | 1311 | /* mac80211 does this: |
1330 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1312 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1331 | if (sdata->type != IEEE80211_IF_TYPE_xxx) | 1313 | if (sdata->type != IEEE80211_IF_TYPE_xxx) { |
1332 | return -EOPNOTSUPP; | 1314 | ret = -EOPNOTSUPP; |
1315 | goto out; | ||
1316 | } | ||
1317 | */ | ||
1333 | 1318 | ||
1334 | if (wrqu->data.length == sizeof(struct iw_scan_req) && | 1319 | if (wrqu->data.length == sizeof(struct iw_scan_req) && |
1335 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { | 1320 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { |
1336 | req = (struct iw_scan_req *)extra; | 1321 | struct iw_scan_req *req = (struct iw_scan_req *)extra; |
1337 | ssid = req->essid; | 1322 | priv->scan_ssid_len = req->essid_len; |
1338 | ssid_len = req->essid_len; | 1323 | memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len); |
1324 | lbs_deb_wext("set_scan, essid '%s'\n", | ||
1325 | escape_essid(priv->scan_ssid, priv->scan_ssid_len)); | ||
1326 | } else { | ||
1327 | priv->scan_ssid_len = 0; | ||
1339 | } | 1328 | } |
1340 | */ | ||
1341 | 1329 | ||
1342 | if (!delayed_work_pending(&priv->scan_work)) | 1330 | if (!delayed_work_pending(&priv->scan_work)) |
1343 | queue_delayed_work(priv->work_thread, &priv->scan_work, | 1331 | queue_delayed_work(priv->work_thread, &priv->scan_work, |
@@ -1346,10 +1334,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
1346 | priv->scan_channel = -1; | 1334 | priv->scan_channel = -1; |
1347 | 1335 | ||
1348 | if (priv->surpriseremoved) | 1336 | if (priv->surpriseremoved) |
1349 | return -EIO; | 1337 | ret = -EIO; |
1350 | 1338 | ||
1351 | lbs_deb_leave(LBS_DEB_SCAN); | 1339 | out: |
1352 | return 0; | 1340 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
1341 | return ret; | ||
1353 | } | 1342 | } |
1354 | 1343 | ||
1355 | 1344 | ||
@@ -1374,7 +1363,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1374 | struct bss_descriptor *iter_bss; | 1363 | struct bss_descriptor *iter_bss; |
1375 | struct bss_descriptor *safe; | 1364 | struct bss_descriptor *safe; |
1376 | 1365 | ||
1377 | lbs_deb_enter(LBS_DEB_SCAN); | 1366 | lbs_deb_enter(LBS_DEB_WEXT); |
1378 | 1367 | ||
1379 | /* iwlist should wait until the current scan is finished */ | 1368 | /* iwlist should wait until the current scan is finished */ |
1380 | if (priv->scan_channel) | 1369 | if (priv->scan_channel) |
@@ -1418,7 +1407,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1418 | dwrq->length = (ev - extra); | 1407 | dwrq->length = (ev - extra); |
1419 | dwrq->flags = 0; | 1408 | dwrq->flags = 0; |
1420 | 1409 | ||
1421 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", err); | 1410 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); |
1422 | return err; | 1411 | return err; |
1423 | } | 1412 | } |
1424 | 1413 | ||