summaryrefslogtreecommitdiffstats
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 16:50:14 -0700
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 5e9c31f0932..e09b7490abb 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)
if (priv->adapter->surpriseremoved)
return;
cancel_delayed_work(&priv->assoc_work);
- queue_delayed_work(priv->assoc_thread, &priv->assoc_work, ASSOC_DELAY);
+ queue_delayed_work(priv->work_thread, &priv->assoc_work, ASSOC_DELAY);
}
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 5697fec0cb1..762c4792774 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -148,9 +148,10 @@ struct _wlan_private {
/** thread to service interrupts */
struct task_struct *main_thread;
wait_queue_head_t waitq;
+ struct workqueue_struct *work_thread;
+ struct delayed_work scan_work;
struct delayed_work assoc_work;
- struct workqueue_struct *assoc_thread;
struct work_struct sync_channel;
/** Hardware access */
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 9a46339ce47..bcd845060d4 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)
goto done;
}
- priv->assoc_thread =
- create_singlethread_workqueue("libertas_assoc");
+ priv->work_thread = create_singlethread_workqueue("libertas_worker");
INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker);
+ INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker);
+
INIT_WORK(&priv->sync_channel, libertas_sync_channel);
/*
@@ -1305,7 +1306,7 @@ int libertas_activate_card(wlan_private *priv)
err_init_fw:
priv->hw_unregister_dev(priv);
err_registerdev:
- destroy_workqueue(priv->assoc_thread);
+ destroy_workqueue(priv->work_thread);
/* Stop the thread servicing the interrupts */
wake_up_interruptible(&priv->waitq);
kthread_stop(priv->main_thread);
@@ -1426,8 +1427,9 @@ int libertas_remove_card(wlan_private *priv)
unregister_netdev(dev);
+ cancel_delayed_work(&priv->scan_work);
cancel_delayed_work(&priv->assoc_work);
- destroy_workqueue(priv->assoc_thread);
+ destroy_workqueue(priv->work_thread);
if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) {
adapter->psmode = WLAN802_11POWERMODECAM;
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 8d4e1ee2739..e2e9ebcd834 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,
}
}
+
+/* Delayed partial scan worker */
+void libertas_scan_worker(struct work_struct *work)
+{
+ wlan_private *priv = container_of(work, wlan_private, scan_work.work);
+
+ wlan_scan_networks(priv, NULL, 0);
+}
+
+
/**
* @brief Construct a wlan_scan_cmd_config structure to use in issue scan cmds
*
@@ -408,7 +418,6 @@ wlan_scan_setup_scan_config(wlan_private * priv,
*pscancurrentonly = 0;
if (puserscanin) {
-
/* Set the bss type scan filter, use adapter setting if unset */
pscancfgout->bsstype =
puserscanin->bsstype ? puserscanin->bsstype : CMD_BSS_TYPE_ANY;
@@ -468,59 +477,57 @@ wlan_scan_setup_scan_config(wlan_private * priv,
*/
*ppchantlvout = (struct mrvlietypes_chanlistparamset *) ptlvpos;
- if (puserscanin && puserscanin->chanlist[0].channumber) {
+ if (!puserscanin || !puserscanin->chanlist[0].channumber) {
+ /* Create a default channel scan list */
+ lbs_deb_scan("Scan: Creating full region channel list\n");
+ wlan_scan_create_channel_list(priv, pscanchanlist,
+ *pfilteredscan);
+ goto out;
+ }
- lbs_deb_scan("Scan: Using supplied channel list\n");
+ lbs_deb_scan("Scan: Using supplied channel list\n");
+ for (chanidx = 0;
+ chanidx < WLAN_IOCTL_USER_SCAN_CHAN_MAX
+ && puserscanin->chanlist[chanidx].channumber; chanidx++) {
- for (chanidx = 0;
- chanidx < WLAN_IOCTL_USER_SCAN_CHAN_MAX
- && puserscanin->chanlist[chanidx].channumber; chanidx++) {
+ channel = puserscanin->chanlist[chanidx].channumber;
+ (pscanchanlist + chanidx)->channumber = channel;
- channel = puserscanin->chanlist[chanidx].channumber;
- (pscanchanlist + chanidx)->channumber = channel;
+ radiotype = puserscanin->chanlist[chanidx].radiotype;
+ (pscanchanlist + chanidx)->radiotype = radiotype;
- radiotype = puserscanin->chanlist[chanidx].radiotype;
- (pscanchanlist + chanidx)->radiotype = radiotype;
+ scantype = puserscanin->chanlist[chanidx].scantype;
- scantype = puserscanin->chanlist[chanidx].scantype;
+ if (scantype == CMD_SCAN_TYPE_PASSIVE) {
+ (pscanchanlist +
+ chanidx)->chanscanmode.passivescan = 1;
+ } else {
+ (pscanchanlist +
+ chanidx)->chanscanmode.passivescan = 0;
+ }
+ if (puserscanin->chanlist[chanidx].scantime) {
+ scandur = puserscanin->chanlist[chanidx].scantime;
+ } else {
if (scantype == CMD_SCAN_TYPE_PASSIVE) {
- (pscanchanlist +
- chanidx)->chanscanmode.passivescan = 1;
- } else {
- (pscanchanlist +
- chanidx)->chanscanmode.passivescan = 0;
- }
-
- if (puserscanin->chanlist[chanidx].scantime) {
- scandur =
- puserscanin->chanlist[chanidx].scantime;
+ scandur = MRVDRV_PASSIVE_SCAN_CHAN_TIME;
} else {
- if (scantype == CMD_SCAN_TYPE_PASSIVE) {
- scandur = MRVDRV_PASSIVE_SCAN_CHAN_TIME;
- } else {
- scandur = MRVDRV_ACTIVE_SCAN_CHAN_TIME;
- }
+ scandur = MRVDRV_ACTIVE_SCAN_CHAN_TIME;
}
-
- (pscanchanlist + chanidx)->minscantime =
- cpu_to_le16(scandur);
- (pscanchanlist + chanidx)->maxscantime =
- cpu_to_le16(scandur);
}
- /* Check if we are only scanning the current channel */
- if ((chanidx == 1) && (puserscanin->chanlist[0].channumber
- ==
- priv->adapter->curbssparams.channel)) {
- *pscancurrentonly = 1;
- lbs_deb_scan("Scan: Scanning current channel only");
- }
+ (pscanchanlist + chanidx)->minscantime =
+ cpu_to_le16(scandur);
+ (pscanchanlist + chanidx)->maxscantime =
+ cpu_to_le16(scandur);
+ }
- } else {
- lbs_deb_scan("Scan: Creating full region channel list\n");
- wlan_scan_create_channel_list(priv, pscanchanlist,
- *pfilteredscan);
+ /* Check if we are only scanning the current channel */
+ if ((chanidx == 1) &&
+ (puserscanin->chanlist[0].channumber ==
+ priv->adapter->curbssparams.channel)) {
+ *pscancurrentonly = 1;
+ lbs_deb_scan("Scan: Scanning current channel only");
}
out:
@@ -604,12 +611,12 @@ static int wlan_scan_channel_list(wlan_private * priv,
while (tlvidx < maxchanperscan && ptmpchan->channumber
&& !doneearly && scanned < 2) {
- lbs_deb_scan(
- "Scan: Chan(%3d), Radio(%d), mode(%d,%d), Dur(%d)\n",
- ptmpchan->channumber, ptmpchan->radiotype,
- ptmpchan->chanscanmode.passivescan,
- ptmpchan->chanscanmode.disablechanfilt,
- ptmpchan->maxscantime);
+ lbs_deb_scan("Scan: Chan(%3d), Radio(%d), mode(%d,%d), "
+ "Dur(%d)\n",
+ ptmpchan->channumber, ptmpchan->radiotype,
+ ptmpchan->chanscanmode.passivescan,
+ ptmpchan->chanscanmode.disablechanfilt,
+ ptmpchan->maxscantime);
/* Copy the current channel TLV to the command being prepared */
memcpy(pchantlvout->chanscanparam + tlvidx,
@@ -678,9 +685,18 @@ static int wlan_scan_channel_list(wlan_private * priv,
done:
priv->adapter->last_scanned_channel = ptmpchan->channumber;
- /* Tell userspace the scan table has been updated */
- memset(&wrqu, 0, sizeof(union iwreq_data));
- wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+ if (priv->adapter->last_scanned_channel) {
+ /* Schedule the next part of the partial scan */
+ if (!full_scan && !priv->adapter->surpriseremoved) {
+ cancel_delayed_work(&priv->scan_work);
+ queue_delayed_work(priv->work_thread, &priv->scan_work,
+ msecs_to_jiffies(300));
+ }
+ } else {
+ /* All done, tell userspace the scan table has been updated */
+ memset(&wrqu, 0, sizeof(union iwreq_data));
+ wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+ }
lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
return ret;
@@ -747,8 +763,8 @@ clear_selected_scan_list_entries(wlan_adapter * adapter,
* @return 0 or < 0 if error
*/
int wlan_scan_networks(wlan_private * priv,
- const struct wlan_ioctl_user_scan_cfg * puserscanin,
- int full_scan)
+ const struct wlan_ioctl_user_scan_cfg * puserscanin,
+ int full_scan)
{
wlan_adapter * adapter = priv->adapter;
struct mrvlietypes_chanlistparamset *pchantlvout;
@@ -763,7 +779,13 @@ int wlan_scan_networks(wlan_private * priv,
int i = 0;
#endif
- lbs_deb_enter(LBS_DEB_ASSOC);
+ lbs_deb_enter(LBS_DEB_SCAN);
+
+ /* Cancel any partial outstanding partial scans if this scan
+ * is a full scan.
+ */
+ if (full_scan && delayed_work_pending(&priv->scan_work))
+ cancel_delayed_work(&priv->scan_work);
scan_chan_list = kzalloc(sizeof(struct chanscanparamset) *
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,
lbs_deb_enter(LBS_DEB_SCAN);
- wlan_scan_networks(priv, NULL, 0);
+ if (!delayed_work_pending(&priv->scan_work)) {
+ queue_delayed_work(priv->work_thread, &priv->scan_work,
+ msecs_to_jiffies(50));
+ }
if (adapter->surpriseremoved)
return -1;
@@ -1508,10 +1533,6 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
lbs_deb_enter(LBS_DEB_ASSOC);
- /* If we've got an uncompleted scan, schedule the next part */
- if (!adapter->nr_cmd_pending && adapter->last_scanned_channel)
- wlan_scan_networks(priv, NULL, 0);
-
/* Update RSSI if current BSS is a locally created ad-hoc BSS */
if ((adapter->mode == IW_MODE_ADHOC) && adapter->adhoccreate) {
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 9bb1a435c28..c29c031bef8 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,
int libertas_set_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra);
+void libertas_scan_worker(struct work_struct *work);
+
#endif /* _WLAN_SCAN_H */