1184610Salfred/* $FreeBSD$ */
2184610Salfred/*-
3184610Salfred * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
4184610Salfred *
5184610Salfred * Redistribution and use in source and binary forms, with or without
6184610Salfred * modification, are permitted provided that the following conditions
7184610Salfred * are met:
8184610Salfred * 1. Redistributions of source code must retain the above copyright
9184610Salfred *    notice, this list of conditions and the following disclaimer.
10184610Salfred * 2. Redistributions in binary form must reproduce the above copyright
11184610Salfred *    notice, this list of conditions and the following disclaimer in the
12184610Salfred *    documentation and/or other materials provided with the distribution.
13184610Salfred *
14184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17184610Salfred * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24184610Salfred * SUCH DAMAGE.
25184610Salfred */
26184610Salfred
27205005Sthompsa#include "opt_ddb.h"
28205005Sthompsa
29194677Sthompsa#include <sys/stdint.h>
30194677Sthompsa#include <sys/stddef.h>
31194677Sthompsa#include <sys/param.h>
32194677Sthompsa#include <sys/queue.h>
33194677Sthompsa#include <sys/types.h>
34194677Sthompsa#include <sys/systm.h>
35194677Sthompsa#include <sys/kernel.h>
36194677Sthompsa#include <sys/bus.h>
37194677Sthompsa#include <sys/module.h>
38194677Sthompsa#include <sys/lock.h>
39194677Sthompsa#include <sys/mutex.h>
40194677Sthompsa#include <sys/condvar.h>
41194677Sthompsa#include <sys/sysctl.h>
42194677Sthompsa#include <sys/sx.h>
43194677Sthompsa#include <sys/unistd.h>
44194677Sthompsa#include <sys/callout.h>
45194677Sthompsa#include <sys/malloc.h>
46194677Sthompsa#include <sys/priv.h>
47194677Sthompsa
48188942Sthompsa#include <dev/usb/usb.h>
49194677Sthompsa#include <dev/usb/usbdi.h>
50184610Salfred
51194228Sthompsa#define	USB_DEBUG_VAR usb_ctrl_debug
52184610Salfred
53188942Sthompsa#include <dev/usb/usb_core.h>
54188942Sthompsa#include <dev/usb/usb_debug.h>
55188942Sthompsa#include <dev/usb/usb_process.h>
56188942Sthompsa#include <dev/usb/usb_busdma.h>
57188942Sthompsa#include <dev/usb/usb_dynamic.h>
58188942Sthompsa#include <dev/usb/usb_device.h>
59188942Sthompsa#include <dev/usb/usb_hub.h>
60184610Salfred
61188942Sthompsa#include <dev/usb/usb_controller.h>
62188942Sthompsa#include <dev/usb/usb_bus.h>
63215649Sweongyo#include <dev/usb/usb_pf.h>
64229096Shselasky#include "usb_if.h"
65184610Salfred
66190754Sthompsa/* function prototypes  */
67184610Salfred
68194228Sthompsastatic device_probe_t usb_probe;
69194228Sthompsastatic device_attach_t usb_attach;
70194228Sthompsastatic device_detach_t usb_detach;
71229096Shselaskystatic device_suspend_t usb_suspend;
72229096Shselaskystatic device_resume_t usb_resume;
73229096Shselaskystatic device_shutdown_t usb_shutdown;
74184610Salfred
75194228Sthompsastatic void	usb_attach_sub(device_t, struct usb_bus *);
76184610Salfred
77184610Salfred/* static variables */
78184610Salfred
79194677Sthompsa#ifdef USB_DEBUG
80194228Sthompsastatic int usb_ctrl_debug = 0;
81184610Salfred
82248085Smariusstatic SYSCTL_NODE(_hw_usb, OID_AUTO, ctrl, CTLFLAG_RW, 0, "USB controller");
83194228SthompsaSYSCTL_INT(_hw_usb_ctrl, OID_AUTO, debug, CTLFLAG_RW, &usb_ctrl_debug, 0,
84184610Salfred    "Debug level");
85184610Salfred#endif
86184610Salfred
87195965Salfredstatic int usb_no_boot_wait = 0;
88195965SalfredTUNABLE_INT("hw.usb.no_boot_wait", &usb_no_boot_wait);
89242775ShselaskySYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RD|CTLFLAG_TUN, &usb_no_boot_wait, 0,
90229100Shselasky    "No USB device enumerate waiting at boot.");
91195965Salfred
92232870Shselaskystatic int usb_no_suspend_wait = 0;
93232870ShselaskyTUNABLE_INT("hw.usb.no_suspend_wait", &usb_no_suspend_wait);
94232870ShselaskySYSCTL_INT(_hw_usb, OID_AUTO, no_suspend_wait, CTLFLAG_RW|CTLFLAG_TUN,
95232870Shselasky    &usb_no_suspend_wait, 0, "No USB device waiting at system suspend.");
96232870Shselasky
97229100Shselaskystatic int usb_no_shutdown_wait = 0;
98229100ShselaskyTUNABLE_INT("hw.usb.no_shutdown_wait", &usb_no_shutdown_wait);
99232870ShselaskySYSCTL_INT(_hw_usb, OID_AUTO, no_shutdown_wait, CTLFLAG_RW|CTLFLAG_TUN,
100232870Shselasky    &usb_no_shutdown_wait, 0, "No USB device waiting at system shutdown.");
101229100Shselasky
102194228Sthompsastatic devclass_t usb_devclass;
103184610Salfred
104194228Sthompsastatic device_method_t usb_methods[] = {
105194228Sthompsa	DEVMETHOD(device_probe, usb_probe),
106194228Sthompsa	DEVMETHOD(device_attach, usb_attach),
107194228Sthompsa	DEVMETHOD(device_detach, usb_detach),
108229096Shselasky	DEVMETHOD(device_suspend, usb_suspend),
109229096Shselasky	DEVMETHOD(device_resume, usb_resume),
110229096Shselasky	DEVMETHOD(device_shutdown, usb_shutdown),
111184610Salfred	{0, 0}
112184610Salfred};
113184610Salfred
114194228Sthompsastatic driver_t usb_driver = {
115184610Salfred	.name = "usbus",
116194228Sthompsa	.methods = usb_methods,
117184610Salfred	.size = 0,
118184610Salfred};
119184610Salfred
120213426Shselasky/* Host Only Drivers */
121194228SthompsaDRIVER_MODULE(usbus, ohci, usb_driver, usb_devclass, 0, 0);
122194228SthompsaDRIVER_MODULE(usbus, uhci, usb_driver, usb_devclass, 0, 0);
123194228SthompsaDRIVER_MODULE(usbus, ehci, usb_driver, usb_devclass, 0, 0);
124213435ShselaskyDRIVER_MODULE(usbus, xhci, usb_driver, usb_devclass, 0, 0);
125213426Shselasky
126213426Shselasky/* Device Only Drivers */
127194228SthompsaDRIVER_MODULE(usbus, at91_udp, usb_driver, usb_devclass, 0, 0);
128213426ShselaskyDRIVER_MODULE(usbus, musbotg, usb_driver, usb_devclass, 0, 0);
129194228SthompsaDRIVER_MODULE(usbus, uss820, usb_driver, usb_devclass, 0, 0);
130184610Salfred
131184610Salfred/*------------------------------------------------------------------------*
132194228Sthompsa *	usb_probe
133184610Salfred *
134184610Salfred * This function is called from "{ehci,ohci,uhci}_pci_attach()".
135184610Salfred *------------------------------------------------------------------------*/
136184610Salfredstatic int
137194228Sthompsausb_probe(device_t dev)
138184610Salfred{
139184610Salfred	DPRINTF("\n");
140184610Salfred	return (0);
141184610Salfred}
142184610Salfred
143213425Shselaskystatic void
144213425Shselaskyusb_root_mount_rel(struct usb_bus *bus)
145213425Shselasky{
146213425Shselasky	if (bus->bus_roothold != NULL) {
147213425Shselasky		DPRINTF("Releasing root mount hold %p\n", bus->bus_roothold);
148213425Shselasky		root_mount_rel(bus->bus_roothold);
149213425Shselasky		bus->bus_roothold = NULL;
150213425Shselasky	}
151213425Shselasky}
152213425Shselasky
153184610Salfred/*------------------------------------------------------------------------*
154194228Sthompsa *	usb_attach
155184610Salfred *------------------------------------------------------------------------*/
156184610Salfredstatic int
157194228Sthompsausb_attach(device_t dev)
158184610Salfred{
159192984Sthompsa	struct usb_bus *bus = device_get_ivars(dev);
160184610Salfred
161184610Salfred	DPRINTF("\n");
162184610Salfred
163184610Salfred	if (bus == NULL) {
164199816Sthompsa		device_printf(dev, "USB device has no ivars\n");
165184610Salfred		return (ENXIO);
166184610Salfred	}
167188907Sthompsa
168195965Salfred	if (usb_no_boot_wait == 0) {
169195965Salfred		/* delay vfs_mountroot until the bus is explored */
170195965Salfred		bus->bus_roothold = root_mount_hold(device_get_nameunit(dev));
171195965Salfred	}
172188907Sthompsa
173196488Salfred	usb_attach_sub(dev, bus);
174196488Salfred
175184610Salfred	return (0);			/* return success */
176184610Salfred}
177184610Salfred
178184610Salfred/*------------------------------------------------------------------------*
179194228Sthompsa *	usb_detach
180184610Salfred *------------------------------------------------------------------------*/
181184610Salfredstatic int
182194228Sthompsausb_detach(device_t dev)
183184610Salfred{
184192984Sthompsa	struct usb_bus *bus = device_get_softc(dev);
185184610Salfred
186184610Salfred	DPRINTF("\n");
187184610Salfred
188184610Salfred	if (bus == NULL) {
189184610Salfred		/* was never setup properly */
190184610Salfred		return (0);
191184610Salfred	}
192186730Salfred	/* Stop power watchdog */
193194228Sthompsa	usb_callout_drain(&bus->power_wdog);
194186730Salfred
195184610Salfred	/* Let the USB explore process detach all devices. */
196213425Shselasky	usb_root_mount_rel(bus);
197184610Salfred
198184824Sthompsa	USB_BUS_LOCK(bus);
199229096Shselasky
200229096Shselasky	/* Queue detach job */
201229096Shselasky	usb_proc_msignal(&bus->explore_proc,
202229096Shselasky	    &bus->detach_msg[0], &bus->detach_msg[1]);
203229096Shselasky
204184610Salfred	/* Wait for detach to complete */
205194228Sthompsa	usb_proc_mwait(&bus->explore_proc,
206184610Salfred	    &bus->detach_msg[0], &bus->detach_msg[1]);
207184610Salfred
208184824Sthompsa	USB_BUS_UNLOCK(bus);
209184610Salfred
210187174Sthompsa	/* Get rid of USB callback processes */
211187174Sthompsa
212194228Sthompsa	usb_proc_free(&bus->giant_callback_proc);
213194228Sthompsa	usb_proc_free(&bus->non_giant_callback_proc);
214187174Sthompsa
215184610Salfred	/* Get rid of USB explore process */
216184610Salfred
217194228Sthompsa	usb_proc_free(&bus->explore_proc);
218184610Salfred
219191400Sthompsa	/* Get rid of control transfer process */
220191400Sthompsa
221194228Sthompsa	usb_proc_free(&bus->control_xfer_proc);
222191400Sthompsa
223217558Shselasky#if USB_HAVE_PF
224215812Sweongyo	usbpf_detach(bus);
225217558Shselasky#endif
226184610Salfred	return (0);
227184610Salfred}
228184610Salfred
229184610Salfred/*------------------------------------------------------------------------*
230229096Shselasky *	usb_suspend
231229096Shselasky *------------------------------------------------------------------------*/
232229096Shselaskystatic int
233229096Shselaskyusb_suspend(device_t dev)
234229096Shselasky{
235229096Shselasky	struct usb_bus *bus = device_get_softc(dev);
236229096Shselasky
237229096Shselasky	DPRINTF("\n");
238229096Shselasky
239229096Shselasky	if (bus == NULL) {
240229096Shselasky		/* was never setup properly */
241229096Shselasky		return (0);
242229096Shselasky	}
243229096Shselasky
244229096Shselasky	USB_BUS_LOCK(bus);
245229096Shselasky	usb_proc_msignal(&bus->explore_proc,
246229096Shselasky	    &bus->suspend_msg[0], &bus->suspend_msg[1]);
247232870Shselasky	if (usb_no_suspend_wait == 0) {
248232870Shselasky		/* wait for suspend callback to be executed */
249232870Shselasky		usb_proc_mwait(&bus->explore_proc,
250232870Shselasky		    &bus->suspend_msg[0], &bus->suspend_msg[1]);
251232870Shselasky	}
252229096Shselasky	USB_BUS_UNLOCK(bus);
253229096Shselasky
254229096Shselasky	return (0);
255229096Shselasky}
256229096Shselasky
257229096Shselasky/*------------------------------------------------------------------------*
258229096Shselasky *	usb_resume
259229096Shselasky *------------------------------------------------------------------------*/
260229096Shselaskystatic int
261229096Shselaskyusb_resume(device_t dev)
262229096Shselasky{
263229096Shselasky	struct usb_bus *bus = device_get_softc(dev);
264229096Shselasky
265229096Shselasky	DPRINTF("\n");
266229096Shselasky
267229096Shselasky	if (bus == NULL) {
268229096Shselasky		/* was never setup properly */
269229096Shselasky		return (0);
270229096Shselasky	}
271229096Shselasky
272229096Shselasky	USB_BUS_LOCK(bus);
273229096Shselasky	usb_proc_msignal(&bus->explore_proc,
274229096Shselasky	    &bus->resume_msg[0], &bus->resume_msg[1]);
275229096Shselasky	USB_BUS_UNLOCK(bus);
276229096Shselasky
277229096Shselasky	return (0);
278229096Shselasky}
279229096Shselasky
280229096Shselasky/*------------------------------------------------------------------------*
281259602Shselasky *	usb_bus_reset_async_locked
282259602Shselasky *------------------------------------------------------------------------*/
283259602Shselaskyvoid
284259602Shselaskyusb_bus_reset_async_locked(struct usb_bus *bus)
285259602Shselasky{
286259602Shselasky	USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
287259602Shselasky
288259602Shselasky	DPRINTF("\n");
289259602Shselasky
290259602Shselasky	if (bus->reset_msg[0].hdr.pm_qentry.tqe_prev != NULL ||
291259602Shselasky	    bus->reset_msg[1].hdr.pm_qentry.tqe_prev != NULL) {
292259602Shselasky		DPRINTF("Reset already pending\n");
293259602Shselasky		return;
294259602Shselasky	}
295259602Shselasky
296259602Shselasky	device_printf(bus->parent, "Resetting controller\n");
297259602Shselasky
298259602Shselasky	usb_proc_msignal(&bus->explore_proc,
299259602Shselasky	    &bus->reset_msg[0], &bus->reset_msg[1]);
300259602Shselasky}
301259602Shselasky
302259602Shselasky/*------------------------------------------------------------------------*
303229096Shselasky *	usb_shutdown
304229096Shselasky *------------------------------------------------------------------------*/
305229096Shselaskystatic int
306229096Shselaskyusb_shutdown(device_t dev)
307229096Shselasky{
308229096Shselasky	struct usb_bus *bus = device_get_softc(dev);
309229096Shselasky
310229096Shselasky	DPRINTF("\n");
311229096Shselasky
312229096Shselasky	if (bus == NULL) {
313229096Shselasky		/* was never setup properly */
314229096Shselasky		return (0);
315229096Shselasky	}
316229096Shselasky
317229100Shselasky	device_printf(bus->bdev, "Controller shutdown\n");
318229100Shselasky
319229096Shselasky	USB_BUS_LOCK(bus);
320229096Shselasky	usb_proc_msignal(&bus->explore_proc,
321229096Shselasky	    &bus->shutdown_msg[0], &bus->shutdown_msg[1]);
322229100Shselasky	if (usb_no_shutdown_wait == 0) {
323229100Shselasky		/* wait for shutdown callback to be executed */
324229100Shselasky		usb_proc_mwait(&bus->explore_proc,
325229100Shselasky		    &bus->shutdown_msg[0], &bus->shutdown_msg[1]);
326229100Shselasky	}
327229096Shselasky	USB_BUS_UNLOCK(bus);
328229096Shselasky
329229100Shselasky	device_printf(bus->bdev, "Controller shutdown complete\n");
330229100Shselasky
331229096Shselasky	return (0);
332229096Shselasky}
333229096Shselasky
334229096Shselasky/*------------------------------------------------------------------------*
335194228Sthompsa *	usb_bus_explore
336184610Salfred *
337184610Salfred * This function is used to explore the device tree from the root.
338184610Salfred *------------------------------------------------------------------------*/
339184610Salfredstatic void
340194228Sthompsausb_bus_explore(struct usb_proc_msg *pm)
341184610Salfred{
342192984Sthompsa	struct usb_bus *bus;
343192984Sthompsa	struct usb_device *udev;
344184610Salfred
345192984Sthompsa	bus = ((struct usb_bus_msg *)pm)->bus;
346184610Salfred	udev = bus->devices[USB_ROOT_HUB_ADDR];
347184610Salfred
348229096Shselasky	if (bus->no_explore != 0)
349229096Shselasky		return;
350229096Shselasky
351267350Shselasky	if (udev != NULL) {
352267350Shselasky		USB_BUS_UNLOCK(bus);
353267350Shselasky		uhub_explore_handle_re_enumerate(udev);
354267350Shselasky		USB_BUS_LOCK(bus);
355267350Shselasky	}
356184610Salfred
357267350Shselasky	if (udev != NULL && udev->hub != NULL) {
358267350Shselasky
359184610Salfred		if (bus->do_probe) {
360184610Salfred			bus->do_probe = 0;
361184610Salfred			bus->driver_added_refcount++;
362184610Salfred		}
363184610Salfred		if (bus->driver_added_refcount == 0) {
364184610Salfred			/* avoid zero, hence that is memory default */
365184610Salfred			bus->driver_added_refcount = 1;
366184610Salfred		}
367196488Salfred
368205005Sthompsa#ifdef DDB
369196488Salfred		/*
370196488Salfred		 * The following three lines of code are only here to
371196488Salfred		 * recover from DDB:
372196488Salfred		 */
373196488Salfred		usb_proc_rewakeup(&bus->control_xfer_proc);
374196488Salfred		usb_proc_rewakeup(&bus->giant_callback_proc);
375196488Salfred		usb_proc_rewakeup(&bus->non_giant_callback_proc);
376205005Sthompsa#endif
377196488Salfred
378184824Sthompsa		USB_BUS_UNLOCK(bus);
379184610Salfred
380208013Sthompsa#if USB_HAVE_POWERD
381184610Salfred		/*
382186730Salfred		 * First update the USB power state!
383186730Salfred		 */
384194228Sthompsa		usb_bus_powerd(bus);
385208013Sthompsa#endif
386196488Salfred		 /* Explore the Root USB HUB. */
387196403Sjhb		(udev->hub->explore) (udev);
388184824Sthompsa		USB_BUS_LOCK(bus);
389184610Salfred	}
390213425Shselasky	usb_root_mount_rel(bus);
391184610Salfred}
392184610Salfred
393184610Salfred/*------------------------------------------------------------------------*
394194228Sthompsa *	usb_bus_detach
395184610Salfred *
396184610Salfred * This function is used to detach the device tree from the root.
397184610Salfred *------------------------------------------------------------------------*/
398184610Salfredstatic void
399194228Sthompsausb_bus_detach(struct usb_proc_msg *pm)
400184610Salfred{
401192984Sthompsa	struct usb_bus *bus;
402192984Sthompsa	struct usb_device *udev;
403184610Salfred	device_t dev;
404184610Salfred
405192984Sthompsa	bus = ((struct usb_bus_msg *)pm)->bus;
406184610Salfred	udev = bus->devices[USB_ROOT_HUB_ADDR];
407184610Salfred	dev = bus->bdev;
408184610Salfred	/* clear the softc */
409184610Salfred	device_set_softc(dev, NULL);
410184824Sthompsa	USB_BUS_UNLOCK(bus);
411184610Salfred
412196488Salfred	/* detach children first */
413196403Sjhb	mtx_lock(&Giant);
414184610Salfred	bus_generic_detach(dev);
415196488Salfred	mtx_unlock(&Giant);
416184610Salfred
417184610Salfred	/*
418197553Sthompsa	 * Free USB device and all subdevices, if any.
419184610Salfred	 */
420197553Sthompsa	usb_free_device(udev, 0);
421184610Salfred
422184824Sthompsa	USB_BUS_LOCK(bus);
423184610Salfred	/* clear bdev variable last */
424184610Salfred	bus->bdev = NULL;
425184610Salfred}
426184610Salfred
427229096Shselasky/*------------------------------------------------------------------------*
428229096Shselasky *	usb_bus_suspend
429229096Shselasky *
430259602Shselasky * This function is used to suspend the USB controller.
431229096Shselasky *------------------------------------------------------------------------*/
432186730Salfredstatic void
433229096Shselaskyusb_bus_suspend(struct usb_proc_msg *pm)
434229096Shselasky{
435229096Shselasky	struct usb_bus *bus;
436229096Shselasky	struct usb_device *udev;
437229096Shselasky	usb_error_t err;
438247090Shselasky	uint8_t do_unlock;
439229096Shselasky
440259602Shselasky	DPRINTF("\n");
441259602Shselasky
442229096Shselasky	bus = ((struct usb_bus_msg *)pm)->bus;
443229096Shselasky	udev = bus->devices[USB_ROOT_HUB_ADDR];
444229096Shselasky
445229096Shselasky	if (udev == NULL || bus->bdev == NULL)
446229096Shselasky		return;
447229096Shselasky
448229100Shselasky	USB_BUS_UNLOCK(bus);
449229100Shselasky
450232870Shselasky	/*
451232870Shselasky	 * We use the shutdown event here because the suspend and
452232870Shselasky	 * resume events are reserved for the USB port suspend and
453232870Shselasky	 * resume. The USB system suspend is implemented like full
454232870Shselasky	 * shutdown and all connected USB devices will be disconnected
455232870Shselasky	 * subsequently. At resume all USB devices will be
456232870Shselasky	 * re-connected again.
457232870Shselasky	 */
458232870Shselasky
459229096Shselasky	bus_generic_shutdown(bus->bdev);
460229096Shselasky
461247090Shselasky	do_unlock = usbd_enum_lock(udev);
462229096Shselasky
463229096Shselasky	err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX);
464229096Shselasky	if (err)
465229096Shselasky		device_printf(bus->bdev, "Could not unconfigure root HUB\n");
466229096Shselasky
467229096Shselasky	USB_BUS_LOCK(bus);
468229096Shselasky	bus->hw_power_state = 0;
469229096Shselasky	bus->no_explore = 1;
470229096Shselasky	USB_BUS_UNLOCK(bus);
471229096Shselasky
472229096Shselasky	if (bus->methods->set_hw_power != NULL)
473229096Shselasky		(bus->methods->set_hw_power) (bus);
474229096Shselasky
475229096Shselasky	if (bus->methods->set_hw_power_sleep != NULL)
476229096Shselasky		(bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SUSPEND);
477229096Shselasky
478247090Shselasky	if (do_unlock)
479247090Shselasky		usbd_enum_unlock(udev);
480229100Shselasky
481229100Shselasky	USB_BUS_LOCK(bus);
482229096Shselasky}
483229096Shselasky
484229096Shselasky/*------------------------------------------------------------------------*
485229096Shselasky *	usb_bus_resume
486229096Shselasky *
487259602Shselasky * This function is used to resume the USB controller.
488229096Shselasky *------------------------------------------------------------------------*/
489229096Shselaskystatic void
490229096Shselaskyusb_bus_resume(struct usb_proc_msg *pm)
491229096Shselasky{
492229096Shselasky	struct usb_bus *bus;
493229096Shselasky	struct usb_device *udev;
494229096Shselasky	usb_error_t err;
495247090Shselasky	uint8_t do_unlock;
496229096Shselasky
497259602Shselasky	DPRINTF("\n");
498259602Shselasky
499229096Shselasky	bus = ((struct usb_bus_msg *)pm)->bus;
500229096Shselasky	udev = bus->devices[USB_ROOT_HUB_ADDR];
501229096Shselasky
502229096Shselasky	if (udev == NULL || bus->bdev == NULL)
503229096Shselasky		return;
504229096Shselasky
505229100Shselasky	USB_BUS_UNLOCK(bus);
506229100Shselasky
507247090Shselasky	do_unlock = usbd_enum_lock(udev);
508229096Shselasky#if 0
509229096Shselasky	DEVMETHOD(usb_take_controller, NULL);	/* dummy */
510229096Shselasky#endif
511229096Shselasky	USB_TAKE_CONTROLLER(device_get_parent(bus->bdev));
512229096Shselasky
513229096Shselasky	USB_BUS_LOCK(bus);
514229096Shselasky 	bus->hw_power_state =
515229096Shselasky	  USB_HW_POWER_CONTROL |
516229096Shselasky	  USB_HW_POWER_BULK |
517229096Shselasky	  USB_HW_POWER_INTERRUPT |
518229096Shselasky	  USB_HW_POWER_ISOC |
519229096Shselasky	  USB_HW_POWER_NON_ROOT_HUB;
520229096Shselasky	bus->no_explore = 0;
521229096Shselasky	USB_BUS_UNLOCK(bus);
522229096Shselasky
523229096Shselasky	if (bus->methods->set_hw_power_sleep != NULL)
524229096Shselasky		(bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_RESUME);
525229096Shselasky
526229096Shselasky	if (bus->methods->set_hw_power != NULL)
527229096Shselasky		(bus->methods->set_hw_power) (bus);
528229096Shselasky
529229369Shselasky	/* restore USB configuration to index 0 */
530229096Shselasky	err = usbd_set_config_index(udev, 0);
531229096Shselasky	if (err)
532229096Shselasky		device_printf(bus->bdev, "Could not configure root HUB\n");
533229096Shselasky
534229369Shselasky	/* probe and attach */
535229369Shselasky	err = usb_probe_and_attach(udev, USB_IFACE_INDEX_ANY);
536229369Shselasky	if (err) {
537229369Shselasky		device_printf(bus->bdev, "Could not probe and "
538229369Shselasky		    "attach root HUB\n");
539229369Shselasky	}
540229369Shselasky
541247090Shselasky	if (do_unlock)
542247090Shselasky		usbd_enum_unlock(udev);
543229100Shselasky
544229100Shselasky	USB_BUS_LOCK(bus);
545229096Shselasky}
546229096Shselasky
547229096Shselasky/*------------------------------------------------------------------------*
548259602Shselasky *	usb_bus_reset
549259602Shselasky *
550259602Shselasky * This function is used to reset the USB controller.
551259602Shselasky *------------------------------------------------------------------------*/
552259602Shselaskystatic void
553259602Shselaskyusb_bus_reset(struct usb_proc_msg *pm)
554259602Shselasky{
555259602Shselasky	struct usb_bus *bus;
556259602Shselasky
557259602Shselasky	DPRINTF("\n");
558259602Shselasky
559259602Shselasky	bus = ((struct usb_bus_msg *)pm)->bus;
560259602Shselasky
561259602Shselasky	if (bus->bdev == NULL || bus->no_explore != 0)
562259602Shselasky		return;
563259602Shselasky
564259602Shselasky	/* a suspend and resume will reset the USB controller */
565259602Shselasky	usb_bus_suspend(pm);
566259602Shselasky	usb_bus_resume(pm);
567259602Shselasky}
568259602Shselasky
569259602Shselasky/*------------------------------------------------------------------------*
570229096Shselasky *	usb_bus_shutdown
571229096Shselasky *
572259602Shselasky * This function is used to shutdown the USB controller.
573229096Shselasky *------------------------------------------------------------------------*/
574229096Shselaskystatic void
575229096Shselaskyusb_bus_shutdown(struct usb_proc_msg *pm)
576229096Shselasky{
577229096Shselasky	struct usb_bus *bus;
578229096Shselasky	struct usb_device *udev;
579229096Shselasky	usb_error_t err;
580247090Shselasky	uint8_t do_unlock;
581229096Shselasky
582229096Shselasky	bus = ((struct usb_bus_msg *)pm)->bus;
583229096Shselasky	udev = bus->devices[USB_ROOT_HUB_ADDR];
584229096Shselasky
585229096Shselasky	if (udev == NULL || bus->bdev == NULL)
586229096Shselasky		return;
587229096Shselasky
588229100Shselasky	USB_BUS_UNLOCK(bus);
589229100Shselasky
590229096Shselasky	bus_generic_shutdown(bus->bdev);
591229096Shselasky
592247090Shselasky	do_unlock = usbd_enum_lock(udev);
593229096Shselasky
594229096Shselasky	err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX);
595229096Shselasky	if (err)
596229096Shselasky		device_printf(bus->bdev, "Could not unconfigure root HUB\n");
597229096Shselasky
598229096Shselasky	USB_BUS_LOCK(bus);
599229096Shselasky	bus->hw_power_state = 0;
600229096Shselasky	bus->no_explore = 1;
601229096Shselasky	USB_BUS_UNLOCK(bus);
602229096Shselasky
603229096Shselasky	if (bus->methods->set_hw_power != NULL)
604229096Shselasky		(bus->methods->set_hw_power) (bus);
605229096Shselasky
606229096Shselasky	if (bus->methods->set_hw_power_sleep != NULL)
607229096Shselasky		(bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SHUTDOWN);
608229096Shselasky
609247090Shselasky	if (do_unlock)
610247090Shselasky		usbd_enum_unlock(udev);
611229100Shselasky
612229100Shselasky	USB_BUS_LOCK(bus);
613229096Shselasky}
614229096Shselasky
615229096Shselaskystatic void
616194228Sthompsausb_power_wdog(void *arg)
617186730Salfred{
618192984Sthompsa	struct usb_bus *bus = arg;
619186730Salfred
620186730Salfred	USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
621186730Salfred
622194228Sthompsa	usb_callout_reset(&bus->power_wdog,
623194228Sthompsa	    4 * hz, usb_power_wdog, arg);
624186730Salfred
625205005Sthompsa#ifdef DDB
626196488Salfred	/*
627196488Salfred	 * The following line of code is only here to recover from
628196488Salfred	 * DDB:
629196488Salfred	 */
630196488Salfred	usb_proc_rewakeup(&bus->explore_proc);	/* recover from DDB */
631205005Sthompsa#endif
632196488Salfred
633208013Sthompsa#if USB_HAVE_POWERD
634186730Salfred	USB_BUS_UNLOCK(bus);
635186730Salfred
636194228Sthompsa	usb_bus_power_update(bus);
637186730Salfred
638190724Sthompsa	USB_BUS_LOCK(bus);
639208013Sthompsa#endif
640186730Salfred}
641186730Salfred
642184610Salfred/*------------------------------------------------------------------------*
643194228Sthompsa *	usb_bus_attach
644184610Salfred *
645186730Salfred * This function attaches USB in context of the explore thread.
646184610Salfred *------------------------------------------------------------------------*/
647184610Salfredstatic void
648194228Sthompsausb_bus_attach(struct usb_proc_msg *pm)
649184610Salfred{
650192984Sthompsa	struct usb_bus *bus;
651192984Sthompsa	struct usb_device *child;
652186730Salfred	device_t dev;
653193045Sthompsa	usb_error_t err;
654192500Sthompsa	enum usb_dev_speed speed;
655184610Salfred
656192984Sthompsa	bus = ((struct usb_bus_msg *)pm)->bus;
657186730Salfred	dev = bus->bdev;
658186730Salfred
659184610Salfred	DPRINTF("\n");
660184610Salfred
661184610Salfred	switch (bus->usbrev) {
662184610Salfred	case USB_REV_1_0:
663184610Salfred		speed = USB_SPEED_FULL;
664184610Salfred		device_printf(bus->bdev, "12Mbps Full Speed USB v1.0\n");
665184610Salfred		break;
666184610Salfred
667184610Salfred	case USB_REV_1_1:
668184610Salfred		speed = USB_SPEED_FULL;
669184610Salfred		device_printf(bus->bdev, "12Mbps Full Speed USB v1.1\n");
670184610Salfred		break;
671184610Salfred
672184610Salfred	case USB_REV_2_0:
673184610Salfred		speed = USB_SPEED_HIGH;
674184610Salfred		device_printf(bus->bdev, "480Mbps High Speed USB v2.0\n");
675184610Salfred		break;
676184610Salfred
677184610Salfred	case USB_REV_2_5:
678184610Salfred		speed = USB_SPEED_VARIABLE;
679184610Salfred		device_printf(bus->bdev, "480Mbps Wireless USB v2.5\n");
680184610Salfred		break;
681184610Salfred
682213435Shselasky	case USB_REV_3_0:
683213435Shselasky		speed = USB_SPEED_SUPER;
684219048Shselasky		device_printf(bus->bdev, "5.0Gbps Super Speed USB v3.0\n");
685213435Shselasky		break;
686213435Shselasky
687184610Salfred	default:
688199816Sthompsa		device_printf(bus->bdev, "Unsupported USB revision\n");
689213425Shselasky		usb_root_mount_rel(bus);
690184610Salfred		return;
691184610Salfred	}
692184610Salfred
693190734Sthompsa	/* default power_mask value */
694190734Sthompsa	bus->hw_power_state =
695190734Sthompsa	  USB_HW_POWER_CONTROL |
696190734Sthompsa	  USB_HW_POWER_BULK |
697190734Sthompsa	  USB_HW_POWER_INTERRUPT |
698190734Sthompsa	  USB_HW_POWER_ISOC |
699190734Sthompsa	  USB_HW_POWER_NON_ROOT_HUB;
700190734Sthompsa
701229096Shselasky	USB_BUS_UNLOCK(bus);
702229096Shselasky
703190734Sthompsa	/* make sure power is set at least once */
704190734Sthompsa
705190734Sthompsa	if (bus->methods->set_hw_power != NULL) {
706190734Sthompsa		(bus->methods->set_hw_power) (bus);
707190734Sthompsa	}
708190734Sthompsa
709229096Shselasky	/* allocate the Root USB device */
710184610Salfred
711194228Sthompsa	child = usb_alloc_device(bus->bdev, bus, NULL, 0, 0, 1,
712184610Salfred	    speed, USB_MODE_HOST);
713184610Salfred	if (child) {
714194228Sthompsa		err = usb_probe_and_attach(child,
715184610Salfred		    USB_IFACE_INDEX_ANY);
716184610Salfred		if (!err) {
717189676Sthompsa			if ((bus->devices[USB_ROOT_HUB_ADDR] == NULL) ||
718189676Sthompsa			    (bus->devices[USB_ROOT_HUB_ADDR]->hub == NULL)) {
719184610Salfred				err = USB_ERR_NO_ROOT_HUB;
720184610Salfred			}
721184610Salfred		}
722184610Salfred	} else {
723184610Salfred		err = USB_ERR_NOMEM;
724184610Salfred	}
725184610Salfred
726186730Salfred	USB_BUS_LOCK(bus);
727186730Salfred
728184610Salfred	if (err) {
729184610Salfred		device_printf(bus->bdev, "Root HUB problem, error=%s\n",
730194228Sthompsa		    usbd_errstr(err));
731213425Shselasky		usb_root_mount_rel(bus);
732184610Salfred	}
733186730Salfred
734186730Salfred	/* set softc - we are ready */
735186730Salfred	device_set_softc(dev, bus);
736186730Salfred
737190724Sthompsa	/* start watchdog */
738194228Sthompsa	usb_power_wdog(bus);
739186730Salfred}
740186730Salfred
741186730Salfred/*------------------------------------------------------------------------*
742194228Sthompsa *	usb_attach_sub
743186730Salfred *
744196488Salfred * This function creates a thread which runs the USB attach code.
745186730Salfred *------------------------------------------------------------------------*/
746186730Salfredstatic void
747194228Sthompsausb_attach_sub(device_t dev, struct usb_bus *bus)
748186730Salfred{
749188409Sthompsa	const char *pname = device_get_nameunit(dev);
750188409Sthompsa
751196488Salfred	mtx_lock(&Giant);
752196488Salfred	if (usb_devclass_ptr == NULL)
753196488Salfred		usb_devclass_ptr = devclass_find("usbus");
754196488Salfred	mtx_unlock(&Giant);
755196488Salfred
756217558Shselasky#if USB_HAVE_PF
757215812Sweongyo	usbpf_attach(bus);
758217558Shselasky#endif
759184610Salfred	/* Initialise USB process messages */
760194228Sthompsa	bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore;
761184610Salfred	bus->explore_msg[0].bus = bus;
762194228Sthompsa	bus->explore_msg[1].hdr.pm_callback = &usb_bus_explore;
763184610Salfred	bus->explore_msg[1].bus = bus;
764184610Salfred
765194228Sthompsa	bus->detach_msg[0].hdr.pm_callback = &usb_bus_detach;
766184610Salfred	bus->detach_msg[0].bus = bus;
767194228Sthompsa	bus->detach_msg[1].hdr.pm_callback = &usb_bus_detach;
768184610Salfred	bus->detach_msg[1].bus = bus;
769184610Salfred
770194228Sthompsa	bus->attach_msg[0].hdr.pm_callback = &usb_bus_attach;
771186730Salfred	bus->attach_msg[0].bus = bus;
772194228Sthompsa	bus->attach_msg[1].hdr.pm_callback = &usb_bus_attach;
773186730Salfred	bus->attach_msg[1].bus = bus;
774186730Salfred
775229096Shselasky	bus->suspend_msg[0].hdr.pm_callback = &usb_bus_suspend;
776229096Shselasky	bus->suspend_msg[0].bus = bus;
777229096Shselasky	bus->suspend_msg[1].hdr.pm_callback = &usb_bus_suspend;
778229096Shselasky	bus->suspend_msg[1].bus = bus;
779229096Shselasky
780229096Shselasky	bus->resume_msg[0].hdr.pm_callback = &usb_bus_resume;
781229096Shselasky	bus->resume_msg[0].bus = bus;
782229096Shselasky	bus->resume_msg[1].hdr.pm_callback = &usb_bus_resume;
783229096Shselasky	bus->resume_msg[1].bus = bus;
784229096Shselasky
785259602Shselasky	bus->reset_msg[0].hdr.pm_callback = &usb_bus_reset;
786259602Shselasky	bus->reset_msg[0].bus = bus;
787259602Shselasky	bus->reset_msg[1].hdr.pm_callback = &usb_bus_reset;
788259602Shselasky	bus->reset_msg[1].bus = bus;
789259602Shselasky
790229096Shselasky	bus->shutdown_msg[0].hdr.pm_callback = &usb_bus_shutdown;
791229096Shselasky	bus->shutdown_msg[0].bus = bus;
792229096Shselasky	bus->shutdown_msg[1].hdr.pm_callback = &usb_bus_shutdown;
793229096Shselasky	bus->shutdown_msg[1].bus = bus;
794229096Shselasky
795190735Sthompsa	/* Create USB explore and callback processes */
796187172Sthompsa
797194228Sthompsa	if (usb_proc_create(&bus->giant_callback_proc,
798188409Sthompsa	    &bus->bus_mtx, pname, USB_PRI_MED)) {
799218475Shselasky		device_printf(dev, "WARNING: Creation of USB Giant "
800187174Sthompsa		    "callback process failed.\n");
801194228Sthompsa	} else if (usb_proc_create(&bus->non_giant_callback_proc,
802188409Sthompsa	    &bus->bus_mtx, pname, USB_PRI_HIGH)) {
803218475Shselasky		device_printf(dev, "WARNING: Creation of USB non-Giant "
804187174Sthompsa		    "callback process failed.\n");
805194228Sthompsa	} else if (usb_proc_create(&bus->explore_proc,
806188409Sthompsa	    &bus->bus_mtx, pname, USB_PRI_MED)) {
807218475Shselasky		device_printf(dev, "WARNING: Creation of USB explore "
808187172Sthompsa		    "process failed.\n");
809194228Sthompsa	} else if (usb_proc_create(&bus->control_xfer_proc,
810191400Sthompsa	    &bus->bus_mtx, pname, USB_PRI_MED)) {
811218475Shselasky		device_printf(dev, "WARNING: Creation of USB control transfer "
812191400Sthompsa		    "process failed.\n");
813186730Salfred	} else {
814186730Salfred		/* Get final attach going */
815186730Salfred		USB_BUS_LOCK(bus);
816229096Shselasky		usb_proc_msignal(&bus->explore_proc,
817229096Shselasky		    &bus->attach_msg[0], &bus->attach_msg[1]);
818186730Salfred		USB_BUS_UNLOCK(bus);
819184610Salfred
820196488Salfred		/* Do initial explore */
821196488Salfred		usb_needs_explore(bus, 1);
822184610Salfred	}
823184610Salfred}
824184610Salfred
825194228SthompsaSYSUNINIT(usb_bus_unload, SI_SUB_KLD, SI_ORDER_ANY, usb_bus_unload, NULL);
826184610Salfred
827184610Salfred/*------------------------------------------------------------------------*
828194228Sthompsa *	usb_bus_mem_flush_all_cb
829184610Salfred *------------------------------------------------------------------------*/
830190180Sthompsa#if USB_HAVE_BUSDMA
831184610Salfredstatic void
832194228Sthompsausb_bus_mem_flush_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
833193074Sthompsa    struct usb_page *pg, usb_size_t size, usb_size_t align)
834184610Salfred{
835194228Sthompsa	usb_pc_cpu_flush(pc);
836184610Salfred}
837190180Sthompsa#endif
838184610Salfred
839184610Salfred/*------------------------------------------------------------------------*
840194228Sthompsa *	usb_bus_mem_flush_all - factored out code
841184610Salfred *------------------------------------------------------------------------*/
842190180Sthompsa#if USB_HAVE_BUSDMA
843184610Salfredvoid
844194228Sthompsausb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb)
845184610Salfred{
846184610Salfred	if (cb) {
847194228Sthompsa		cb(bus, &usb_bus_mem_flush_all_cb);
848184610Salfred	}
849184610Salfred}
850190180Sthompsa#endif
851184610Salfred
852184610Salfred/*------------------------------------------------------------------------*
853194228Sthompsa *	usb_bus_mem_alloc_all_cb
854184610Salfred *------------------------------------------------------------------------*/
855190180Sthompsa#if USB_HAVE_BUSDMA
856184610Salfredstatic void
857194228Sthompsausb_bus_mem_alloc_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
858193074Sthompsa    struct usb_page *pg, usb_size_t size, usb_size_t align)
859184610Salfred{
860184610Salfred	/* need to initialize the page cache */
861184610Salfred	pc->tag_parent = bus->dma_parent_tag;
862184610Salfred
863194228Sthompsa	if (usb_pc_alloc_mem(pc, pg, size, align)) {
864184610Salfred		bus->alloc_failed = 1;
865184610Salfred	}
866184610Salfred}
867190180Sthompsa#endif
868184610Salfred
869184610Salfred/*------------------------------------------------------------------------*
870194228Sthompsa *	usb_bus_mem_alloc_all - factored out code
871184610Salfred *
872184610Salfred * Returns:
873184610Salfred *    0: Success
874184610Salfred * Else: Failure
875184610Salfred *------------------------------------------------------------------------*/
876184610Salfreduint8_t
877194228Sthompsausb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat,
878193045Sthompsa    usb_bus_mem_cb_t *cb)
879184610Salfred{
880184610Salfred	bus->alloc_failed = 0;
881184610Salfred
882186439Sthompsa	mtx_init(&bus->bus_mtx, device_get_nameunit(bus->parent),
883184610Salfred	    NULL, MTX_DEF | MTX_RECURSE);
884184610Salfred
885194228Sthompsa	usb_callout_init_mtx(&bus->power_wdog,
886190724Sthompsa	    &bus->bus_mtx, 0);
887186730Salfred
888184610Salfred	TAILQ_INIT(&bus->intr_q.head);
889184610Salfred
890190180Sthompsa#if USB_HAVE_BUSDMA
891194228Sthompsa	usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
892190180Sthompsa	    dmat, &bus->bus_mtx, NULL, 32, USB_BUS_DMA_TAG_MAX);
893190180Sthompsa#endif
894187170Sthompsa	if ((bus->devices_max > USB_MAX_DEVICES) ||
895187170Sthompsa	    (bus->devices_max < USB_MIN_DEVICES) ||
896187170Sthompsa	    (bus->devices == NULL)) {
897187170Sthompsa		DPRINTFN(0, "Devices field has not been "
898199816Sthompsa		    "initialised properly\n");
899187170Sthompsa		bus->alloc_failed = 1;		/* failure */
900187170Sthompsa	}
901190180Sthompsa#if USB_HAVE_BUSDMA
902184610Salfred	if (cb) {
903194228Sthompsa		cb(bus, &usb_bus_mem_alloc_all_cb);
904184610Salfred	}
905190180Sthompsa#endif
906184610Salfred	if (bus->alloc_failed) {
907194228Sthompsa		usb_bus_mem_free_all(bus, cb);
908184610Salfred	}
909184610Salfred	return (bus->alloc_failed);
910184610Salfred}
911184610Salfred
912184610Salfred/*------------------------------------------------------------------------*
913194228Sthompsa *	usb_bus_mem_free_all_cb
914184610Salfred *------------------------------------------------------------------------*/
915190180Sthompsa#if USB_HAVE_BUSDMA
916184610Salfredstatic void
917194228Sthompsausb_bus_mem_free_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
918193074Sthompsa    struct usb_page *pg, usb_size_t size, usb_size_t align)
919184610Salfred{
920194228Sthompsa	usb_pc_free_mem(pc);
921184610Salfred}
922190180Sthompsa#endif
923184610Salfred
924184610Salfred/*------------------------------------------------------------------------*
925194228Sthompsa *	usb_bus_mem_free_all - factored out code
926184610Salfred *------------------------------------------------------------------------*/
927184610Salfredvoid
928194228Sthompsausb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb)
929184610Salfred{
930190180Sthompsa#if USB_HAVE_BUSDMA
931184610Salfred	if (cb) {
932194228Sthompsa		cb(bus, &usb_bus_mem_free_all_cb);
933184610Salfred	}
934194228Sthompsa	usb_dma_tag_unsetup(bus->dma_parent_tag);
935190180Sthompsa#endif
936184610Salfred
937184824Sthompsa	mtx_destroy(&bus->bus_mtx);
938184610Salfred}
939250560Shselasky
940250560Shselasky/* convenience wrappers */
941250560Shselaskyvoid
942250560Shselaskyusb_proc_explore_mwait(struct usb_device *udev, void *pm1, void *pm2)
943250560Shselasky{
944250560Shselasky	usb_proc_mwait(&udev->bus->explore_proc, pm1, pm2);
945250560Shselasky}
946250560Shselasky
947250560Shselaskyvoid	*
948250560Shselaskyusb_proc_explore_msignal(struct usb_device *udev, void *pm1, void *pm2)
949250560Shselasky{
950250560Shselasky	return (usb_proc_msignal(&udev->bus->explore_proc, pm1, pm2));
951250560Shselasky}
952250560Shselasky
953250560Shselaskyvoid
954250560Shselaskyusb_proc_explore_lock(struct usb_device *udev)
955250560Shselasky{
956250560Shselasky	USB_BUS_LOCK(udev->bus);
957250560Shselasky}
958250560Shselasky
959250560Shselaskyvoid
960250560Shselaskyusb_proc_explore_unlock(struct usb_device *udev)
961250560Shselasky{
962250560Shselasky	USB_BUS_UNLOCK(udev->bus);
963250560Shselasky}
964