aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r--drivers/net/wireless/libertas/scan.c145
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
270void 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 */
300static int lbs_scan_create_channel_list(struct lbs_private *priv, 283static 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 */
373static int lbs_scan_add_ssid_tlv(uint8_t *tlv, 352static 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 */
463static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, 441static 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 */
524int lbs_scan_networks(struct lbs_private *priv, 500static 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
633void 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 */
1120int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, 1102int 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 */
1319int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, 1298int 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); 1339out:
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