Linux Audio

Check our new training course

Embedded Linux training

Mar 31-Apr 8, 2025
Register
Loading...
Note: File does not exist in v6.8.
  1/******************************************************************************
  2 *
  3 * GPL LICENSE SUMMARY
  4 *
  5 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of version 2 of the GNU General Public License as
  9 * published by the Free Software Foundation.
 10 *
 11 * This program is distributed in the hope that it will be useful, but
 12 * WITHOUT ANY WARRANTY; without even the implied warranty of
 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14 * General Public License for more details.
 15 *
 16 * You should have received a copy of the GNU General Public License
 17 * along with this program; if not, write to the Free Software
 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
 19 * USA
 20 *
 21 * The full GNU General Public License is included in this distribution
 22 * in the file called LICENSE.GPL.
 23 *
 24 * Contact Information:
 25 *  Intel Linux Wireless <ilw@linux.intel.com>
 26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 27 *****************************************************************************/
 28#include <linux/slab.h>
 29#include <linux/types.h>
 30#include <linux/etherdevice.h>
 31#include <net/mac80211.h>
 32
 33#include "iwl-eeprom.h"
 34#include "iwl-dev.h"
 35#include "iwl-core.h"
 36#include "iwl-sta.h"
 37#include "iwl-io.h"
 38#include "iwl-helpers.h"
 39#include "iwl-agn.h"
 40#include "iwl-trans.h"
 41
 42/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
 43 * sending probe req.  This should be set long enough to hear probe responses
 44 * from more than one AP.  */
 45#define IWL_ACTIVE_DWELL_TIME_24    (30)       /* all times in msec */
 46#define IWL_ACTIVE_DWELL_TIME_52    (20)
 47
 48#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3)
 49#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2)
 50
 51/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
 52 * Must be set longer than active dwell time.
 53 * For the most reliable scan, set > AP beacon interval (typically 100msec). */
 54#define IWL_PASSIVE_DWELL_TIME_24   (20)       /* all times in msec */
 55#define IWL_PASSIVE_DWELL_TIME_52   (10)
 56#define IWL_PASSIVE_DWELL_BASE      (100)
 57#define IWL_CHANNEL_TUNE_TIME       5
 58
 59static int iwl_send_scan_abort(struct iwl_priv *priv)
 60{
 61	int ret;
 62	struct iwl_rx_packet *pkt;
 63	struct iwl_host_cmd cmd = {
 64		.id = REPLY_SCAN_ABORT_CMD,
 65		.flags = CMD_SYNC | CMD_WANT_SKB,
 66	};
 67
 68	/* Exit instantly with error when device is not ready
 69	 * to receive scan abort command or it does not perform
 70	 * hardware scan currently */
 71	if (!test_bit(STATUS_READY, &priv->status) ||
 72	    !test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
 73	    !test_bit(STATUS_SCAN_HW, &priv->status) ||
 74	    test_bit(STATUS_FW_ERROR, &priv->status) ||
 75	    test_bit(STATUS_EXIT_PENDING, &priv->status))
 76		return -EIO;
 77
 78	ret = trans_send_cmd(&priv->trans, &cmd);
 79	if (ret)
 80		return ret;
 81
 82	pkt = (struct iwl_rx_packet *)cmd.reply_page;
 83	if (pkt->u.status != CAN_ABORT_STATUS) {
 84		/* The scan abort will return 1 for success or
 85		 * 2 for "failure".  A failure condition can be
 86		 * due to simply not being in an active scan which
 87		 * can occur if we send the scan abort before we
 88		 * the microcode has notified us that a scan is
 89		 * completed. */
 90		IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status);
 91		ret = -EIO;
 92	}
 93
 94	iwl_free_pages(priv, cmd.reply_page);
 95	return ret;
 96}
 97
 98static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
 99{
100	/* check if scan was requested from mac80211 */
101	if (priv->scan_request) {
102		IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n");
103		ieee80211_scan_completed(priv->hw, aborted);
104	}
105
106	priv->scan_type = IWL_SCAN_NORMAL;
107	priv->scan_vif = NULL;
108	priv->scan_request = NULL;
109}
110
111void iwl_force_scan_end(struct iwl_priv *priv)
112{
113	lockdep_assert_held(&priv->mutex);
114
115	if (!test_bit(STATUS_SCANNING, &priv->status)) {
116		IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n");
117		return;
118	}
119
120	IWL_DEBUG_SCAN(priv, "Forcing scan end\n");
121	clear_bit(STATUS_SCANNING, &priv->status);
122	clear_bit(STATUS_SCAN_HW, &priv->status);
123	clear_bit(STATUS_SCAN_ABORTING, &priv->status);
124	iwl_complete_scan(priv, true);
125}
126
127static void iwl_do_scan_abort(struct iwl_priv *priv)
128{
129	int ret;
130
131	lockdep_assert_held(&priv->mutex);
132
133	if (!test_bit(STATUS_SCANNING, &priv->status)) {
134		IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
135		return;
136	}
137
138	if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
139		IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
140		return;
141	}
142
143	ret = iwl_send_scan_abort(priv);
144	if (ret) {
145		IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret);
146		iwl_force_scan_end(priv);
147	} else
148		IWL_DEBUG_SCAN(priv, "Successfully send scan abort\n");
149}
150
151/**
152 * iwl_scan_cancel - Cancel any currently executing HW scan
153 */
154int iwl_scan_cancel(struct iwl_priv *priv)
155{
156	IWL_DEBUG_SCAN(priv, "Queuing abort scan\n");
157	queue_work(priv->workqueue, &priv->abort_scan);
158	return 0;
159}
160
161/**
162 * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
163 * @ms: amount of time to wait (in milliseconds) for scan to abort
164 *
165 */
166int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
167{
168	unsigned long timeout = jiffies + msecs_to_jiffies(ms);
169
170	lockdep_assert_held(&priv->mutex);
171
172	IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");
173
174	iwl_do_scan_abort(priv);
175
176	while (time_before_eq(jiffies, timeout)) {
177		if (!test_bit(STATUS_SCAN_HW, &priv->status))
178			break;
179		msleep(20);
180	}
181
182	return test_bit(STATUS_SCAN_HW, &priv->status);
183}
184
185/* Service response to REPLY_SCAN_CMD (0x80) */
186static void iwl_rx_reply_scan(struct iwl_priv *priv,
187			      struct iwl_rx_mem_buffer *rxb)
188{
189#ifdef CONFIG_IWLWIFI_DEBUG
190	struct iwl_rx_packet *pkt = rxb_addr(rxb);
191	struct iwl_scanreq_notification *notif =
192	    (struct iwl_scanreq_notification *)pkt->u.raw;
193
194	IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
195#endif
196}
197
198/* Service SCAN_START_NOTIFICATION (0x82) */
199static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
200				    struct iwl_rx_mem_buffer *rxb)
201{
202	struct iwl_rx_packet *pkt = rxb_addr(rxb);
203	struct iwl_scanstart_notification *notif =
204	    (struct iwl_scanstart_notification *)pkt->u.raw;
205	priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
206	IWL_DEBUG_SCAN(priv, "Scan start: "
207		       "%d [802.11%s] "
208		       "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
209		       notif->channel,
210		       notif->band ? "bg" : "a",
211		       le32_to_cpu(notif->tsf_high),
212		       le32_to_cpu(notif->tsf_low),
213		       notif->status, notif->beacon_timer);
214}
215
216/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
217static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
218				      struct iwl_rx_mem_buffer *rxb)
219{
220#ifdef CONFIG_IWLWIFI_DEBUG
221	struct iwl_rx_packet *pkt = rxb_addr(rxb);
222	struct iwl_scanresults_notification *notif =
223	    (struct iwl_scanresults_notification *)pkt->u.raw;
224
225	IWL_DEBUG_SCAN(priv, "Scan ch.res: "
226		       "%d [802.11%s] "
227		       "(TSF: 0x%08X:%08X) - %d "
228		       "elapsed=%lu usec\n",
229		       notif->channel,
230		       notif->band ? "bg" : "a",
231		       le32_to_cpu(notif->tsf_high),
232		       le32_to_cpu(notif->tsf_low),
233		       le32_to_cpu(notif->statistics[0]),
234		       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
235#endif
236}
237
238/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
239static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
240				       struct iwl_rx_mem_buffer *rxb)
241{
242	struct iwl_rx_packet *pkt = rxb_addr(rxb);
243	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
244
245	IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
246		       scan_notif->scanned_channels,
247		       scan_notif->tsf_low,
248		       scan_notif->tsf_high, scan_notif->status);
249
250	/* The HW is no longer scanning */
251	clear_bit(STATUS_SCAN_HW, &priv->status);
252
253	IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
254		       (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
255		       jiffies_to_msecs(jiffies - priv->scan_start));
256
257	queue_work(priv->workqueue, &priv->scan_completed);
258
259	if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
260	    iwl_advanced_bt_coexist(priv) &&
261	    priv->bt_status != scan_notif->bt_status) {
262		if (scan_notif->bt_status) {
263			/* BT on */
264			if (!priv->bt_ch_announce)
265				priv->bt_traffic_load =
266					IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
267			/*
268			 * otherwise, no traffic load information provided
269			 * no changes made
270			 */
271		} else {
272			/* BT off */
273			priv->bt_traffic_load =
274				IWL_BT_COEX_TRAFFIC_LOAD_NONE;
275		}
276		priv->bt_status = scan_notif->bt_status;
277		queue_work(priv->workqueue, &priv->bt_traffic_change_work);
278	}
279}
280
281void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
282{
283	/* scan handlers */
284	priv->rx_handlers[REPLY_SCAN_CMD] = iwl_rx_reply_scan;
285	priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl_rx_scan_start_notif;
286	priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
287					iwl_rx_scan_results_notif;
288	priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
289					iwl_rx_scan_complete_notif;
290}
291
292inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
293				     enum ieee80211_band band,
294				     u8 n_probes)
295{
296	if (band == IEEE80211_BAND_5GHZ)
297		return IWL_ACTIVE_DWELL_TIME_52 +
298			IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1);
299	else
300		return IWL_ACTIVE_DWELL_TIME_24 +
301			IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
302}
303
304u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
305			       enum ieee80211_band band,
306			       struct ieee80211_vif *vif)
307{
308	struct iwl_rxon_context *ctx;
309	u16 passive = (band == IEEE80211_BAND_2GHZ) ?
310	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
311	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
312
313	if (iwl_is_any_associated(priv)) {
314		/*
315		 * If we're associated, we clamp the maximum passive
316		 * dwell time to be 98% of the smallest beacon interval
317		 * (minus 2 * channel tune time)
318		 */
319		for_each_context(priv, ctx) {
320			u16 value;
321
322			if (!iwl_is_associated_ctx(ctx))
323				continue;
324			value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
325			if ((value > IWL_PASSIVE_DWELL_BASE) || !value)
326				value = IWL_PASSIVE_DWELL_BASE;
327			value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
328			passive = min(value, passive);
329		}
330	}
331
332	return passive;
333}
334
335void iwl_init_scan_params(struct iwl_priv *priv)
336{
337	u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
338	if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ])
339		priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
340	if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
341		priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
342}
343
344int __must_check iwl_scan_initiate(struct iwl_priv *priv,
345				   struct ieee80211_vif *vif,
346				   enum iwl_scan_type scan_type,
347				   enum ieee80211_band band)
348{
349	int ret;
350
351	lockdep_assert_held(&priv->mutex);
352
353	cancel_delayed_work(&priv->scan_check);
354
355	if (!iwl_is_ready_rf(priv)) {
356		IWL_WARN(priv, "Request scan called when driver not ready.\n");
357		return -EIO;
358	}
359
360	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
361		IWL_DEBUG_SCAN(priv,
362			"Multiple concurrent scan requests in parallel.\n");
363		return -EBUSY;
364	}
365
366	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
367		IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n");
368		return -EBUSY;
369	}
370
371	IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
372			scan_type == IWL_SCAN_NORMAL ? "" :
373			scan_type == IWL_SCAN_OFFCH_TX ? "offchan TX " :
374			"internal short ");
375
376	set_bit(STATUS_SCANNING, &priv->status);
377	priv->scan_type = scan_type;
378	priv->scan_start = jiffies;
379	priv->scan_band = band;
380
381	ret = iwlagn_request_scan(priv, vif);
382	if (ret) {
383		clear_bit(STATUS_SCANNING, &priv->status);
384		priv->scan_type = IWL_SCAN_NORMAL;
385		return ret;
386	}
387
388	queue_delayed_work(priv->workqueue, &priv->scan_check,
389			   IWL_SCAN_CHECK_WATCHDOG);
390
391	return 0;
392}
393
394int iwl_mac_hw_scan(struct ieee80211_hw *hw,
395		    struct ieee80211_vif *vif,
396		    struct cfg80211_scan_request *req)
397{
398	struct iwl_priv *priv = hw->priv;
399	int ret;
400
401	IWL_DEBUG_MAC80211(priv, "enter\n");
402
403	if (req->n_channels == 0)
404		return -EINVAL;
405
406	mutex_lock(&priv->mutex);
407
408	/*
409	 * If an internal scan is in progress, just set
410	 * up the scan_request as per above.
411	 */
412	if (priv->scan_type != IWL_SCAN_NORMAL) {
413		IWL_DEBUG_SCAN(priv,
414			       "SCAN request during internal scan - defer\n");
415		priv->scan_request = req;
416		priv->scan_vif = vif;
417		ret = 0;
418	} else {
419		priv->scan_request = req;
420		priv->scan_vif = vif;
421		/*
422		 * mac80211 will only ask for one band at a time
423		 * so using channels[0] here is ok
424		 */
425		ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL,
426					req->channels[0]->band);
427		if (ret) {
428			priv->scan_request = NULL;
429			priv->scan_vif = NULL;
430		}
431	}
432
433	IWL_DEBUG_MAC80211(priv, "leave\n");
434
435	mutex_unlock(&priv->mutex);
436
437	return ret;
438}
439
440/*
441 * internal short scan, this function should only been called while associated.
442 * It will reset and tune the radio to prevent possible RF related problem
443 */
444void iwl_internal_short_hw_scan(struct iwl_priv *priv)
445{
446	queue_work(priv->workqueue, &priv->start_internal_scan);
447}
448
449static void iwl_bg_start_internal_scan(struct work_struct *work)
450{
451	struct iwl_priv *priv =
452		container_of(work, struct iwl_priv, start_internal_scan);
453
454	IWL_DEBUG_SCAN(priv, "Start internal scan\n");
455
456	mutex_lock(&priv->mutex);
457
458	if (priv->scan_type == IWL_SCAN_RADIO_RESET) {
459		IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
460		goto unlock;
461	}
462
463	if (test_bit(STATUS_SCANNING, &priv->status)) {
464		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
465		goto unlock;
466	}
467
468	if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band))
469		IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
470 unlock:
471	mutex_unlock(&priv->mutex);
472}
473
474static void iwl_bg_scan_check(struct work_struct *data)
475{
476	struct iwl_priv *priv =
477	    container_of(data, struct iwl_priv, scan_check.work);
478
479	IWL_DEBUG_SCAN(priv, "Scan check work\n");
480
481	/* Since we are here firmware does not finish scan and
482	 * most likely is in bad shape, so we don't bother to
483	 * send abort command, just force scan complete to mac80211 */
484	mutex_lock(&priv->mutex);
485	iwl_force_scan_end(priv);
486	mutex_unlock(&priv->mutex);
487}
488
489/**
490 * iwl_fill_probe_req - fill in all required fields and IE for probe request
491 */
492
493u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
494		       const u8 *ta, const u8 *ies, int ie_len, int left)
495{
496	int len = 0;
497	u8 *pos = NULL;
498
499	/* Make sure there is enough space for the probe request,
500	 * two mandatory IEs and the data */
501	left -= 24;
502	if (left < 0)
503		return 0;
504
505	frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
506	memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
507	memcpy(frame->sa, ta, ETH_ALEN);
508	memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
509	frame->seq_ctrl = 0;
510
511	len += 24;
512
513	/* ...next IE... */
514	pos = &frame->u.probe_req.variable[0];
515
516	/* fill in our indirect SSID IE */
517	left -= 2;
518	if (left < 0)
519		return 0;
520	*pos++ = WLAN_EID_SSID;
521	*pos++ = 0;
522
523	len += 2;
524
525	if (WARN_ON(left < ie_len))
526		return len;
527
528	if (ies && ie_len) {
529		memcpy(pos, ies, ie_len);
530		len += ie_len;
531	}
532
533	return (u16)len;
534}
535
536static void iwl_bg_abort_scan(struct work_struct *work)
537{
538	struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
539
540	IWL_DEBUG_SCAN(priv, "Abort scan work\n");
541
542	/* We keep scan_check work queued in case when firmware will not
543	 * report back scan completed notification */
544	mutex_lock(&priv->mutex);
545	iwl_scan_cancel_timeout(priv, 200);
546	mutex_unlock(&priv->mutex);
547}
548
549static void iwl_bg_scan_completed(struct work_struct *work)
550{
551	struct iwl_priv *priv =
552	    container_of(work, struct iwl_priv, scan_completed);
553	bool aborted;
554
555	IWL_DEBUG_SCAN(priv, "Completed scan.\n");
556
557	cancel_delayed_work(&priv->scan_check);
558
559	mutex_lock(&priv->mutex);
560
561	aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status);
562	if (aborted)
563		IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
564
565	if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) {
566		IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
567		goto out_settings;
568	}
569
570	if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->offchan_tx_skb) {
571		ieee80211_tx_status_irqsafe(priv->hw,
572					    priv->offchan_tx_skb);
573		priv->offchan_tx_skb = NULL;
574	}
575
576	if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
577		int err;
578
579		/* Check if mac80211 requested scan during our internal scan */
580		if (priv->scan_request == NULL)
581			goto out_complete;
582
583		/* If so request a new scan */
584		err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL,
585					priv->scan_request->channels[0]->band);
586		if (err) {
587			IWL_DEBUG_SCAN(priv,
588				"failed to initiate pending scan: %d\n", err);
589			aborted = true;
590			goto out_complete;
591		}
592
593		goto out;
594	}
595
596out_complete:
597	iwl_complete_scan(priv, aborted);
598
599out_settings:
600	/* Can we still talk to firmware ? */
601	if (!iwl_is_ready_rf(priv))
602		goto out;
603
604	iwlagn_post_scan(priv);
605
606out:
607	mutex_unlock(&priv->mutex);
608}
609
610void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
611{
612	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
613	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
614	INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
615	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
616}
617
618void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
619{
620	cancel_work_sync(&priv->start_internal_scan);
621	cancel_work_sync(&priv->abort_scan);
622	cancel_work_sync(&priv->scan_completed);
623
624	if (cancel_delayed_work_sync(&priv->scan_check)) {
625		mutex_lock(&priv->mutex);
626		iwl_force_scan_end(priv);
627		mutex_unlock(&priv->mutex);
628	}
629}