diff options
author | Dan Williams <dcbw@redhat.com> | 2007-08-02 13:19:04 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:50:14 -0400 |
commit | 2afc0c5d71a3dec6d35f3a234ed986d635ef41ad (patch) | |
tree | e13af671f3386f8a823d3a8745c3831208c7be41 | |
parent | b031ac10264fa9b805d84b4a440407ac950390cf (diff) |
[PATCH] libertas: push WEXT scan requests to a work queue
Push WEXT scan requests to a workqueue and have each partial scan queue
the next part, then only report results when the complete scan has finished.
Full scans don't go through the work queue.
Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/libertas/assoc.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/dev.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/scan.c | 139 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/scan.h | 2 |
5 files changed, 91 insertions, 65 deletions
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h index 5e9c31f0932b..e09b7490abbd 100644 --- a/drivers/net/wireless/libertas/assoc.h +++ b/drivers/net/wireless/libertas/assoc.h | |||
@@ -17,7 +17,7 @@ static inline void wlan_postpone_association_work(wlan_private *priv) | |||
17 | if (priv->adapter->surpriseremoved) | 17 | if (priv->adapter->surpriseremoved) |
18 | return; | 18 | return; |
19 | cancel_delayed_work(&priv->assoc_work); | 19 | cancel_delayed_work(&priv->assoc_work); |
20 | queue_delayed_work(priv->assoc_thread, &priv->assoc_work, ASSOC_DELAY); | 20 | queue_delayed_work(priv->work_thread, &priv->assoc_work, ASSOC_DELAY); |
21 | } | 21 | } |
22 | 22 | ||
23 | static inline void wlan_cancel_association_work(wlan_private *priv) | 23 | static inline void wlan_cancel_association_work(wlan_private *priv) |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 5697fec0cb1d..762c4792774c 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -148,9 +148,10 @@ struct _wlan_private { | |||
148 | /** thread to service interrupts */ | 148 | /** thread to service interrupts */ |
149 | struct task_struct *main_thread; | 149 | struct task_struct *main_thread; |
150 | wait_queue_head_t waitq; | 150 | wait_queue_head_t waitq; |
151 | struct workqueue_struct *work_thread; | ||
151 | 152 | ||
153 | struct delayed_work scan_work; | ||
152 | struct delayed_work assoc_work; | 154 | struct delayed_work assoc_work; |
153 | struct workqueue_struct *assoc_thread; | ||
154 | struct work_struct sync_channel; | 155 | struct work_struct sync_channel; |
155 | 156 | ||
156 | /** Hardware access */ | 157 | /** Hardware access */ |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 9a46339ce47e..bcd845060d4a 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -1269,9 +1269,10 @@ int libertas_activate_card(wlan_private *priv) | |||
1269 | goto done; | 1269 | goto done; |
1270 | } | 1270 | } |
1271 | 1271 | ||
1272 | priv->assoc_thread = | 1272 | priv->work_thread = create_singlethread_workqueue("libertas_worker"); |
1273 | create_singlethread_workqueue("libertas_assoc"); | ||
1274 | INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker); | 1273 | INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker); |
1274 | INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker); | ||
1275 | |||
1275 | INIT_WORK(&priv->sync_channel, libertas_sync_channel); | 1276 | INIT_WORK(&priv->sync_channel, libertas_sync_channel); |
1276 | 1277 | ||
1277 | /* | 1278 | /* |
@@ -1305,7 +1306,7 @@ int libertas_activate_card(wlan_private *priv) | |||
1305 | err_init_fw: | 1306 | err_init_fw: |
1306 | priv->hw_unregister_dev(priv); | 1307 | priv->hw_unregister_dev(priv); |
1307 | err_registerdev: | 1308 | err_registerdev: |
1308 | destroy_workqueue(priv->assoc_thread); | 1309 | destroy_workqueue(priv->work_thread); |
1309 | /* Stop the thread servicing the interrupts */ | 1310 | /* Stop the thread servicing the interrupts */ |
1310 | wake_up_interruptible(&priv->waitq); | 1311 | wake_up_interruptible(&priv->waitq); |
1311 | kthread_stop(priv->main_thread); | 1312 | kthread_stop(priv->main_thread); |
@@ -1426,8 +1427,9 @@ int libertas_remove_card(wlan_private *priv) | |||
1426 | 1427 | ||
1427 | unregister_netdev(dev); | 1428 | unregister_netdev(dev); |
1428 | 1429 | ||
1430 | cancel_delayed_work(&priv->scan_work); | ||
1429 | cancel_delayed_work(&priv->assoc_work); | 1431 | cancel_delayed_work(&priv->assoc_work); |
1430 | destroy_workqueue(priv->assoc_thread); | 1432 | destroy_workqueue(priv->work_thread); |
1431 | 1433 | ||
1432 | if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) { | 1434 | if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) { |
1433 | adapter->psmode = WLAN802_11POWERMODECAM; | 1435 | adapter->psmode = WLAN802_11POWERMODECAM; |
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 8d4e1ee27395..e2e9ebcd8340 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -314,6 +314,16 @@ static void wlan_scan_create_channel_list(wlan_private * priv, | |||
314 | } | 314 | } |
315 | } | 315 | } |
316 | 316 | ||
317 | |||
318 | /* Delayed partial scan worker */ | ||
319 | void libertas_scan_worker(struct work_struct *work) | ||
320 | { | ||
321 | wlan_private *priv = container_of(work, wlan_private, scan_work.work); | ||
322 | |||
323 | wlan_scan_networks(priv, NULL, 0); | ||
324 | } | ||
325 | |||
326 | |||
317 | /** | 327 | /** |
318 | * @brief Construct a wlan_scan_cmd_config structure to use in issue scan cmds | 328 | * @brief Construct a wlan_scan_cmd_config structure to use in issue scan cmds |
319 | * | 329 | * |
@@ -408,7 +418,6 @@ wlan_scan_setup_scan_config(wlan_private * priv, | |||
408 | *pscancurrentonly = 0; | 418 | *pscancurrentonly = 0; |
409 | 419 | ||
410 | if (puserscanin) { | 420 | if (puserscanin) { |
411 | |||
412 | /* Set the bss type scan filter, use adapter setting if unset */ | 421 | /* Set the bss type scan filter, use adapter setting if unset */ |
413 | pscancfgout->bsstype = | 422 | pscancfgout->bsstype = |
414 | puserscanin->bsstype ? puserscanin->bsstype : CMD_BSS_TYPE_ANY; | 423 | puserscanin->bsstype ? puserscanin->bsstype : CMD_BSS_TYPE_ANY; |
@@ -468,59 +477,57 @@ wlan_scan_setup_scan_config(wlan_private * priv, | |||
468 | */ | 477 | */ |
469 | *ppchantlvout = (struct mrvlietypes_chanlistparamset *) ptlvpos; | 478 | *ppchantlvout = (struct mrvlietypes_chanlistparamset *) ptlvpos; |
470 | 479 | ||
471 | if (puserscanin && puserscanin->chanlist[0].channumber) { | 480 | if (!puserscanin || !puserscanin->chanlist[0].channumber) { |
481 | /* Create a default channel scan list */ | ||
482 | lbs_deb_scan("Scan: Creating full region channel list\n"); | ||
483 | wlan_scan_create_channel_list(priv, pscanchanlist, | ||
484 | *pfilteredscan); | ||
485 | goto out; | ||
486 | } | ||
472 | 487 | ||
473 | lbs_deb_scan("Scan: Using supplied channel list\n"); | 488 | lbs_deb_scan("Scan: Using supplied channel list\n"); |
489 | for (chanidx = 0; | ||
490 | chanidx < WLAN_IOCTL_USER_SCAN_CHAN_MAX | ||
491 | && puserscanin->chanlist[chanidx].channumber; chanidx++) { | ||
474 | 492 | ||
475 | for (chanidx = 0; | 493 | channel = puserscanin->chanlist[chanidx].channumber; |
476 | chanidx < WLAN_IOCTL_USER_SCAN_CHAN_MAX | 494 | (pscanchanlist + chanidx)->channumber = channel; |
477 | && puserscanin->chanlist[chanidx].channumber; chanidx++) { | ||
478 | 495 | ||
479 | channel = puserscanin->chanlist[chanidx].channumber; | 496 | radiotype = puserscanin->chanlist[chanidx].radiotype; |
480 | (pscanchanlist + chanidx)->channumber = channel; | 497 | (pscanchanlist + chanidx)->radiotype = radiotype; |
481 | 498 | ||
482 | radiotype = puserscanin->chanlist[chanidx].radiotype; | 499 | scantype = puserscanin->chanlist[chanidx].scantype; |
483 | (pscanchanlist + chanidx)->radiotype = radiotype; | ||
484 | 500 | ||
485 | scantype = puserscanin->chanlist[chanidx].scantype; | 501 | if (scantype == CMD_SCAN_TYPE_PASSIVE) { |
502 | (pscanchanlist + | ||
503 | chanidx)->chanscanmode.passivescan = 1; | ||
504 | } else { | ||
505 | (pscanchanlist + | ||
506 | chanidx)->chanscanmode.passivescan = 0; | ||
507 | } | ||
486 | 508 | ||
509 | if (puserscanin->chanlist[chanidx].scantime) { | ||
510 | scandur = puserscanin->chanlist[chanidx].scantime; | ||
511 | } else { | ||
487 | if (scantype == CMD_SCAN_TYPE_PASSIVE) { | 512 | if (scantype == CMD_SCAN_TYPE_PASSIVE) { |
488 | (pscanchanlist + | 513 | scandur = MRVDRV_PASSIVE_SCAN_CHAN_TIME; |
489 | chanidx)->chanscanmode.passivescan = 1; | ||
490 | } else { | ||
491 | (pscanchanlist + | ||
492 | chanidx)->chanscanmode.passivescan = 0; | ||
493 | } | ||
494 | |||
495 | if (puserscanin->chanlist[chanidx].scantime) { | ||
496 | scandur = | ||
497 | puserscanin->chanlist[chanidx].scantime; | ||
498 | } else { | 514 | } else { |
499 | if (scantype == CMD_SCAN_TYPE_PASSIVE) { | 515 | scandur = MRVDRV_ACTIVE_SCAN_CHAN_TIME; |
500 | scandur = MRVDRV_PASSIVE_SCAN_CHAN_TIME; | ||
501 | } else { | ||
502 | scandur = MRVDRV_ACTIVE_SCAN_CHAN_TIME; | ||
503 | } | ||
504 | } | 516 | } |
505 | |||
506 | (pscanchanlist + chanidx)->minscantime = | ||
507 | cpu_to_le16(scandur); | ||
508 | (pscanchanlist + chanidx)->maxscantime = | ||
509 | cpu_to_le16(scandur); | ||
510 | } | 517 | } |
511 | 518 | ||
512 | /* Check if we are only scanning the current channel */ | 519 | (pscanchanlist + chanidx)->minscantime = |
513 | if ((chanidx == 1) && (puserscanin->chanlist[0].channumber | 520 | cpu_to_le16(scandur); |
514 | == | 521 | (pscanchanlist + chanidx)->maxscantime = |
515 | priv->adapter->curbssparams.channel)) { | 522 | cpu_to_le16(scandur); |
516 | *pscancurrentonly = 1; | 523 | } |
517 | lbs_deb_scan("Scan: Scanning current channel only"); | ||
518 | } | ||
519 | 524 | ||
520 | } else { | 525 | /* Check if we are only scanning the current channel */ |
521 | lbs_deb_scan("Scan: Creating full region channel list\n"); | 526 | if ((chanidx == 1) && |
522 | wlan_scan_create_channel_list(priv, pscanchanlist, | 527 | (puserscanin->chanlist[0].channumber == |
523 | *pfilteredscan); | 528 | priv->adapter->curbssparams.channel)) { |
529 | *pscancurrentonly = 1; | ||
530 | lbs_deb_scan("Scan: Scanning current channel only"); | ||
524 | } | 531 | } |
525 | 532 | ||
526 | out: | 533 | out: |
@@ -604,12 +611,12 @@ static int wlan_scan_channel_list(wlan_private * priv, | |||
604 | while (tlvidx < maxchanperscan && ptmpchan->channumber | 611 | while (tlvidx < maxchanperscan && ptmpchan->channumber |
605 | && !doneearly && scanned < 2) { | 612 | && !doneearly && scanned < 2) { |
606 | 613 | ||
607 | lbs_deb_scan( | 614 | lbs_deb_scan("Scan: Chan(%3d), Radio(%d), mode(%d,%d), " |
608 | "Scan: Chan(%3d), Radio(%d), mode(%d,%d), Dur(%d)\n", | 615 | "Dur(%d)\n", |
609 | ptmpchan->channumber, ptmpchan->radiotype, | 616 | ptmpchan->channumber, ptmpchan->radiotype, |
610 | ptmpchan->chanscanmode.passivescan, | 617 | ptmpchan->chanscanmode.passivescan, |
611 | ptmpchan->chanscanmode.disablechanfilt, | 618 | ptmpchan->chanscanmode.disablechanfilt, |
612 | ptmpchan->maxscantime); | 619 | ptmpchan->maxscantime); |
613 | 620 | ||
614 | /* Copy the current channel TLV to the command being prepared */ | 621 | /* Copy the current channel TLV to the command being prepared */ |
615 | memcpy(pchantlvout->chanscanparam + tlvidx, | 622 | memcpy(pchantlvout->chanscanparam + tlvidx, |
@@ -678,9 +685,18 @@ static int wlan_scan_channel_list(wlan_private * priv, | |||
678 | done: | 685 | done: |
679 | priv->adapter->last_scanned_channel = ptmpchan->channumber; | 686 | priv->adapter->last_scanned_channel = ptmpchan->channumber; |
680 | 687 | ||
681 | /* Tell userspace the scan table has been updated */ | 688 | if (priv->adapter->last_scanned_channel) { |
682 | memset(&wrqu, 0, sizeof(union iwreq_data)); | 689 | /* Schedule the next part of the partial scan */ |
683 | wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); | 690 | if (!full_scan && !priv->adapter->surpriseremoved) { |
691 | cancel_delayed_work(&priv->scan_work); | ||
692 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
693 | msecs_to_jiffies(300)); | ||
694 | } | ||
695 | } else { | ||
696 | /* All done, tell userspace the scan table has been updated */ | ||
697 | memset(&wrqu, 0, sizeof(union iwreq_data)); | ||
698 | wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); | ||
699 | } | ||
684 | 700 | ||
685 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | 701 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); |
686 | return ret; | 702 | return ret; |
@@ -747,8 +763,8 @@ clear_selected_scan_list_entries(wlan_adapter * adapter, | |||
747 | * @return 0 or < 0 if error | 763 | * @return 0 or < 0 if error |
748 | */ | 764 | */ |
749 | int wlan_scan_networks(wlan_private * priv, | 765 | int wlan_scan_networks(wlan_private * priv, |
750 | const struct wlan_ioctl_user_scan_cfg * puserscanin, | 766 | const struct wlan_ioctl_user_scan_cfg * puserscanin, |
751 | int full_scan) | 767 | int full_scan) |
752 | { | 768 | { |
753 | wlan_adapter * adapter = priv->adapter; | 769 | wlan_adapter * adapter = priv->adapter; |
754 | struct mrvlietypes_chanlistparamset *pchantlvout; | 770 | struct mrvlietypes_chanlistparamset *pchantlvout; |
@@ -763,7 +779,13 @@ int wlan_scan_networks(wlan_private * priv, | |||
763 | int i = 0; | 779 | int i = 0; |
764 | #endif | 780 | #endif |
765 | 781 | ||
766 | lbs_deb_enter(LBS_DEB_ASSOC); | 782 | lbs_deb_enter(LBS_DEB_SCAN); |
783 | |||
784 | /* Cancel any partial outstanding partial scans if this scan | ||
785 | * is a full scan. | ||
786 | */ | ||
787 | if (full_scan && delayed_work_pending(&priv->scan_work)) | ||
788 | cancel_delayed_work(&priv->scan_work); | ||
767 | 789 | ||
768 | scan_chan_list = kzalloc(sizeof(struct chanscanparamset) * | 790 | scan_chan_list = kzalloc(sizeof(struct chanscanparamset) * |
769 | WLAN_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); | 791 | WLAN_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); |
@@ -1289,7 +1311,10 @@ int libertas_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
1289 | 1311 | ||
1290 | lbs_deb_enter(LBS_DEB_SCAN); | 1312 | lbs_deb_enter(LBS_DEB_SCAN); |
1291 | 1313 | ||
1292 | wlan_scan_networks(priv, NULL, 0); | 1314 | if (!delayed_work_pending(&priv->scan_work)) { |
1315 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
1316 | msecs_to_jiffies(50)); | ||
1317 | } | ||
1293 | 1318 | ||
1294 | if (adapter->surpriseremoved) | 1319 | if (adapter->surpriseremoved) |
1295 | return -1; | 1320 | return -1; |
@@ -1508,10 +1533,6 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1508 | 1533 | ||
1509 | lbs_deb_enter(LBS_DEB_ASSOC); | 1534 | lbs_deb_enter(LBS_DEB_ASSOC); |
1510 | 1535 | ||
1511 | /* If we've got an uncompleted scan, schedule the next part */ | ||
1512 | if (!adapter->nr_cmd_pending && adapter->last_scanned_channel) | ||
1513 | wlan_scan_networks(priv, NULL, 0); | ||
1514 | |||
1515 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ | 1536 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ |
1516 | if ((adapter->mode == IW_MODE_ADHOC) && adapter->adhoccreate) { | 1537 | if ((adapter->mode == IW_MODE_ADHOC) && adapter->adhoccreate) { |
1517 | libertas_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | 1538 | libertas_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, |
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h index 9bb1a435c28a..c29c031bef8c 100644 --- a/drivers/net/wireless/libertas/scan.h +++ b/drivers/net/wireless/libertas/scan.h | |||
@@ -210,4 +210,6 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
210 | int libertas_set_scan(struct net_device *dev, struct iw_request_info *info, | 210 | int libertas_set_scan(struct net_device *dev, struct iw_request_info *info, |
211 | struct iw_param *vwrq, char *extra); | 211 | struct iw_param *vwrq, char *extra); |
212 | 212 | ||
213 | void libertas_scan_worker(struct work_struct *work); | ||
214 | |||
213 | #endif /* _WLAN_SCAN_H */ | 215 | #endif /* _WLAN_SCAN_H */ |