Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2afc0c5d authored by Dan Williams's avatar Dan Williams Committed by David S. Miller
Browse files

[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: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent b031ac10
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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)
+2 −1
Original line number Diff line number Diff line
@@ -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 */
+6 −4
Original line number Diff line number Diff line
@@ -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;
+80 −59
Original line number Diff line number Diff line
@@ -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,10 +477,15 @@ 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");

	for (chanidx = 0;
	     chanidx < WLAN_IOCTL_USER_SCAN_CHAN_MAX
	     && puserscanin->chanlist[chanidx].channumber; chanidx++) {
@@ -493,8 +507,7 @@ wlan_scan_setup_scan_config(wlan_private * priv,
		}

		if (puserscanin->chanlist[chanidx].scantime) {
				scandur =
				    puserscanin->chanlist[chanidx].scantime;
			scandur = puserscanin->chanlist[chanidx].scantime;
		} else {
			if (scantype == CMD_SCAN_TYPE_PASSIVE) {
				scandur = MRVDRV_PASSIVE_SCAN_CHAN_TIME;
@@ -510,19 +523,13 @@ wlan_scan_setup_scan_config(wlan_private * priv,
	}

	/* Check if we are only scanning the current channel */
		if ((chanidx == 1) && (puserscanin->chanlist[0].channumber
				       ==
	if ((chanidx == 1) &&
	    (puserscanin->chanlist[0].channumber ==
			       priv->adapter->curbssparams.channel)) {
		*pscancurrentonly = 1;
		lbs_deb_scan("Scan: Scanning current channel only");
	}

	} else {
		lbs_deb_scan("Scan: Creating full region channel list\n");
		wlan_scan_create_channel_list(priv, pscanchanlist,
					      *pfilteredscan);
	}

out:
	return pscancfgout;
}
@@ -604,8 +611,8 @@ 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",
			lbs_deb_scan("Scan: Chan(%3d), Radio(%d), mode(%d,%d), "
			             "Dur(%d)\n",
			             ptmpchan->channumber, ptmpchan->radiotype,
			             ptmpchan->chanscanmode.passivescan,
			             ptmpchan->chanscanmode.disablechanfilt,
@@ -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 */
	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;
@@ -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,
+2 −0
Original line number Diff line number Diff line
@@ -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 */