aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2007-08-02 13:19:04 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:50:14 -0400
commit2afc0c5d71a3dec6d35f3a234ed986d635ef41ad (patch)
treee13af671f3386f8a823d3a8745c3831208c7be41
parentb031ac10264fa9b805d84b4a440407ac950390cf (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.h2
-rw-r--r--drivers/net/wireless/libertas/dev.h3
-rw-r--r--drivers/net/wireless/libertas/main.c10
-rw-r--r--drivers/net/wireless/libertas/scan.c139
-rw-r--r--drivers/net/wireless/libertas/scan.h2
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
23static inline void wlan_cancel_association_work(wlan_private *priv) 23static 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)
1305err_init_fw: 1306err_init_fw:
1306 priv->hw_unregister_dev(priv); 1307 priv->hw_unregister_dev(priv);
1307err_registerdev: 1308err_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 */
319void 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
526out: 533out:
@@ -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,
678done: 685done:
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 */
749int wlan_scan_networks(wlan_private * priv, 765int 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,
210int libertas_set_scan(struct net_device *dev, struct iw_request_info *info, 210int 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
213void libertas_scan_worker(struct work_struct *work);
214
213#endif /* _WLAN_SCAN_H */ 215#endif /* _WLAN_SCAN_H */