aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/scan.c
diff options
context:
space:
mode:
authorLuciano Coelho <coelho@ti.com>2011-09-02 07:28:21 -0400
committerLuciano Coelho <coelho@ti.com>2011-09-14 05:18:38 -0400
commitfb55377b2aa9464b773e8688a135d5b4c6aa91fa (patch)
tree07599fc39e1bb815d158062525817d10442dd97c /drivers/net/wireless/wl12xx/scan.c
parent1ec23f7f709b7ab5552cb9c34089633c384ec657 (diff)
wl12xx: add support for sched_scan filters
Implement support for filtering in scheduled scans. With this commit we now use the match sets passed by cfg80211 to filter on SSIDs. Due to the nature of the wl12xx firmware API, we don't allow SSIDs to be sent in the probe requests if they are not going to match any of the filters. Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/scan.c')
-rw-r--r--drivers/net/wireless/wl12xx/scan.c107
1 files changed, 72 insertions, 35 deletions
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 4a4d0d03fa1f..488033b2a39b 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -471,34 +471,77 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
471 cfg->passive[2] || cfg->active[2]; 471 cfg->passive[2] || cfg->active[2];
472} 472}
473 473
474/* Returns 0 if no wildcard is used, 1 if wildcard is used or a 474/* Returns the scan type to be used or a negative value on error */
475 * negative value on error */
476static int 475static int
477wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, 476wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
478 struct cfg80211_sched_scan_request *req) 477 struct cfg80211_sched_scan_request *req)
479{ 478{
480 struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL; 479 struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL;
481 struct cfg80211_ssid *ssid = req->ssids; 480 struct cfg80211_match_set *sets = req->match_sets;
482 int ret, wildcard = 0; 481 struct cfg80211_ssid *ssids = req->ssids;
482 int ret = 0, type, i, j;
483 483
484 wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list"); 484 wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list");
485 485
486 /* No filter, no ssids or only bcast ssid */
487 if (!req->n_match_sets &&
488 (!req->n_ssids ||
489 (req->n_ssids == 1 && req->ssids[0].ssid_len == 0))) {
490 type = SCAN_SSID_FILTER_ANY;
491 goto out;
492 }
493
486 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 494 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
487 if (!cmd) 495 if (!cmd) {
488 return -ENOMEM; 496 ret = -ENOMEM;
497 goto out;
498 }
499
500 if (!req->n_match_sets) {
501 /* No filter, with ssids */
502 type = SCAN_SSID_FILTER_DISABLED;
503
504 for (i = 0; i < req->n_ssids; i++) {
505 cmd->ssids[cmd->n_ssids].type = (ssids[i].ssid_len) ?
506 SCAN_SSID_TYPE_HIDDEN : SCAN_SSID_TYPE_PUBLIC;
507 cmd->ssids[cmd->n_ssids].len = ssids[i].ssid_len;
508 memcpy(cmd->ssids[cmd->n_ssids].ssid, ssids[i].ssid,
509 ssids[i].ssid_len);
510 cmd->n_ssids++;
511 }
512 } else {
513 type = SCAN_SSID_FILTER_LIST;
489 514
490 while ((cmd->n_ssids < req->n_ssids) && ssid) { 515 /* Add all SSIDs from the filters */
491 if (ssid->ssid_len == 0) { 516 for (i = 0; i < req->n_match_sets; i++) {
492 wildcard = 1;
493 cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC; 517 cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC;
494 } else { 518 cmd->ssids[cmd->n_ssids].len = sets[i].ssid.ssid_len;
495 cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_HIDDEN; 519 memcpy(cmd->ssids[cmd->n_ssids].ssid,
520 sets[i].ssid.ssid, sets[i].ssid.ssid_len);
521 cmd->n_ssids++;
522 }
523 if ((req->n_ssids > 1) ||
524 (req->n_ssids == 1 && req->ssids[0].ssid_len > 0)) {
525 /*
526 * Mark all the SSIDs passed in the SSID list as HIDDEN,
527 * so they're used in probe requests.
528 */
529 for (i = 0; i < req->n_ssids; i++) {
530 for (j = 0; j < cmd->n_ssids; j++)
531 if (!memcmp(req->ssids[i].ssid,
532 cmd->ssids[j].ssid,
533 req->ssids[i].ssid_len)) {
534 cmd->ssids[j].type =
535 SCAN_SSID_TYPE_HIDDEN;
536 break;
537 }
538 /* Fail if SSID isn't present in the filters */
539 if (j == req->n_ssids) {
540 ret = -EINVAL;
541 goto out_free;
542 }
543 }
496 } 544 }
497 cmd->ssids[cmd->n_ssids].len = ssid->ssid_len;
498 memcpy(cmd->ssids[cmd->n_ssids].ssid, ssid->ssid,
499 ssid->ssid_len);
500 ssid++;
501 cmd->n_ssids++;
502 } 545 }
503 546
504 wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd)); 547 wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd));
@@ -507,13 +550,15 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
507 sizeof(*cmd), 0); 550 sizeof(*cmd), 0);
508 if (ret < 0) { 551 if (ret < 0) {
509 wl1271_error("cmd sched scan ssid list failed"); 552 wl1271_error("cmd sched scan ssid list failed");
510 goto out; 553 goto out_free;
511 } 554 }
512 555
513 ret = wildcard; 556out_free:
514out:
515 kfree(cmd); 557 kfree(cmd);
516 return ret; 558out:
559 if (ret < 0)
560 return ret;
561 return type;
517} 562}
518 563
519int wl1271_scan_sched_scan_config(struct wl1271 *wl, 564int wl1271_scan_sched_scan_config(struct wl1271 *wl,
@@ -548,21 +593,13 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
548 cfg->intervals[i] = cpu_to_le32(req->interval); 593 cfg->intervals[i] = cpu_to_le32(req->interval);
549 594
550 cfg->ssid_len = 0; 595 cfg->ssid_len = 0;
551 if (req->n_ssids == 0) { 596 ret = wl12xx_scan_sched_scan_ssid_list(wl, req);
552 wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_ANY"); 597 if (ret < 0)
553 cfg->filter_type = SCAN_SSID_FILTER_ANY; 598 goto out;
554 } else { 599
555 ret = wl12xx_scan_sched_scan_ssid_list(wl, req); 600 cfg->filter_type = ret;
556 if (ret < 0) 601
557 goto out; 602 wl1271_debug(DEBUG_SCAN, "filter_type = %d", cfg->filter_type);
558 if (ret) {
559 wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_DISABLED");
560 cfg->filter_type = SCAN_SSID_FILTER_DISABLED;
561 } else {
562 wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_LIST");
563 cfg->filter_type = SCAN_SSID_FILTER_LIST;
564 }
565 }
566 603
567 if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) { 604 if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {
568 wl1271_error("scan channel list is empty"); 605 wl1271_error("scan channel list is empty");