PERFORCE change 130743 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Wed Dec 12 14:36:17 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=130743
Change 130743 by hselasky at hselasky_laptop001 on 2007/12/12 22:36:05
This commit is related to USB device side support.
o In general: The code does the same like before
only that some functions have been refactored.
o Removed "usb_discover". It looked more and more
like an "sx_xlock" implementation, and it was
time to replace it by something simpler.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/usb.c#27 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/usb.c#27 (text+ko) ====
@@ -84,8 +84,6 @@
#define USB_UCRED
#endif
-uint8_t usb_driver_added_refcount = 1;
-
static uint8_t usb_post_init_called = 0;
static device_probe_t usb_probe;
@@ -93,7 +91,6 @@
static device_detach_t usb_detach;
static int usb_dummy_open(struct cdev *dev, int oflags, int devtype, struct thread *td);
-static void usb_discover(struct usbd_bus *bus);
static void usb_event_thread(struct usbd_bus *bus);
static void usb_create_event_thread(struct usbd_bus *bus);
static void usb_attach_sub(device_t dev, struct usbd_bus *bus);
@@ -142,84 +139,66 @@
}
/*------------------------------------------------------------------------*
- * usb_discover - explore the device tree from the root
+ * usb_event_thread - explore the device tree from the root
*------------------------------------------------------------------------*/
static void
-usb_discover(struct usbd_bus *bus)
+usb_event_thread(struct usbd_bus *bus)
{
- int32_t error;
+ int error;
PRINTFN(2, ("\n"));
- mtx_assert(&usb_global_lock, MA_OWNED);
+ while (1) {
- /*
- * check that only one thread is exploring at a time
- */
- while (bus->is_exploring) {
- bus->wait_explore = 1;
+ mtx_lock(&(bus->mtx));
+retry:
+ if (bus->needs.teardown) {
+ wakeup(&(bus->bdev));
+ mtx_unlock(&(bus->mtx));
+ break;
+ }
+ if ((bus->devices[USB_ROOT_HUB_ADDR] == NULL) ||
+ (bus->devices[USB_ROOT_HUB_ADDR]->hub == NULL) ||
+ (bus->needs.explore == 0)) {
- error = mtx_sleep(&bus->wait_explore, &usb_global_lock, 0,
- "usb wait explore", 0);
- }
+ if (bus->needs.sync) {
+ bus->needs.sync = 0;
+ wakeup(&(bus->needs));
+ }
+ bus->needs.wakeup = 1;
- bus->is_exploring = 1;
+ error = mtx_sleep(bus, &(bus->mtx),
+ 0, "usbevt", hz * 240);
- while (bus->devices[USB_START_ADDR] &&
- bus->devices[USB_START_ADDR]->hub &&
- bus->needs_explore &&
- (bus->wait_explore == 0)) {
- bus->needs_explore = 0;
+ PRINTFN(2, ("woken up\n"));
- /*
- * explore the hub (this call can sleep, exiting
- * usb_global_lock, which is actually Giant)
- */
- (bus->devices[USB_START_ADDR]->hub->explore)
- (bus->devices[USB_START_ADDR]);
- }
+ bus->needs.wakeup = 0;
+ goto retry;
+ }
+ bus->needs.explore = 0;
- bus->is_exploring = 0;
+ if (bus->needs.probe_attach) {
+ bus->needs.probe_attach = 0;
+ bus->driver_added_refcount++;
+ }
+ if (bus->driver_added_refcount == 0) {
+ /* avoid zero, hence that is memory default */
+ bus->driver_added_refcount = 1;
+ }
+ mtx_unlock(&(bus->mtx));
- if (bus->wait_explore) {
- bus->wait_explore = 0;
- wakeup(&bus->wait_explore);
- }
- return;
-}
-
-static void
-usb_event_thread(struct usbd_bus *bus)
-{
- int32_t error;
-
- mtx_lock(&usb_global_lock);
-
- while (1) {
- if (bus->devices[USB_START_ADDR] == 0) {
- break;
- }
- usb_discover(bus);
+ mtx_lock(&usb_global_lock);
/*
- * Check if a detach happened during discover:
+ * Explore the Root USB HUB (this call can sleep,
+ * exiting usb_global_lock, which is actually Giant)
*/
- if (bus->devices[USB_START_ADDR] == 0) {
- break;
- }
- error = mtx_sleep(&bus->needs_explore, &usb_global_lock,
- 0, "usbevt", hz * 60);
+ (bus->devices[USB_ROOT_HUB_ADDR]->hub->explore)
+ (bus->devices[USB_ROOT_HUB_ADDR]);
- PRINTFN(2, ("woke up\n"));
+ mtx_unlock(&usb_global_lock);
}
- bus->event_thread = NULL;
-
- /* in case parent is waiting for us to exit */
- wakeup(bus);
-
- mtx_unlock(&usb_global_lock);
-
PRINTF(("exit\n"));
usb_thread_exit(0);
@@ -227,54 +206,92 @@
return;
}
+/*------------------------------------------------------------------------*
+ * usb_needs_explore
+ *
+ * This functions is called when the USB event thread
+ * needs to be explored.
+ *------------------------------------------------------------------------*/
void
-usb_needs_explore(struct usbd_device *udev)
+usb_needs_explore(struct usbd_bus *bus, uint8_t what)
{
+ int err;
+
PRINTFN(2, ("\n"));
- mtx_lock(&usb_global_lock);
- udev->bus->needs_explore = 1;
- wakeup(&udev->bus->needs_explore);
- mtx_unlock(&usb_global_lock);
+ mtx_lock(&(bus->mtx));
+ if (bus->needs.wakeup) {
+ bus->needs.wakeup = 0;
+ wakeup(bus);
+ }
+ switch (what) {
+ case USB_BUS_EXPLORE_STOP:
+ bus->needs.teardown = 1;
+ err = mtx_sleep(&(bus->bdev), &(bus->mtx),
+ 0, "usbdrain", 0);
+ break;
+
+ case USB_BUS_EXPLORE_PROBE:
+ bus->needs.explore = 1;
+ bus->needs.probe_attach = 1;
+ break;
+
+ case USB_BUS_EXPLORE_SYNC:
+ bus->needs.sync = 1;
+ err = mtx_sleep(&(bus->needs), &(bus->mtx),
+ 0, "usbsync", 30 * hz);
+ break;
+
+ default:
+ /* just explore */
+ bus->needs.explore = 1;
+ break;
+ }
+ mtx_unlock(&(bus->mtx));
return;
}
+/*------------------------------------------------------------------------*
+ * usb_needs_probe_and_attach
+ *
+ * This function is called whenever a new driver is loaded and will
+ * cause that all USB busses are re-explored.
+ *------------------------------------------------------------------------*/
void
usb_needs_probe_and_attach(void)
{
struct usbd_bus *bus;
devclass_t dc;
device_t dev;
+ uint8_t what;
int max;
PRINTFN(2, ("\n"));
- mtx_lock(&usb_global_lock);
+ dc = devclass_find("usb");
+ if (dc == NULL) {
+ return;
+ }
+ /*
+ * Explore all USB busses in parallell.
+ */
- usb_driver_added_refcount++;
- if (usb_driver_added_refcount == 0) {
- /* avoid zero, hence that is memory default */
- usb_driver_added_refcount = 1;
+ what = USB_BUS_EXPLORE_PROBE;
+repeat:
+ max = devclass_get_maxunit(dc);
+ while (max >= 0) {
+ dev = devclass_get_device(dc, max);
+ if (dev) {
+ bus = device_get_softc(dev);
+ usb_needs_explore(bus, what);
+ }
+ max--;
}
- dc = devclass_find("usb");
- if (dc) {
- max = devclass_get_maxunit(dc);
- while (max >= 0) {
- dev = devclass_get_device(dc, max);
- if (dev) {
- bus = device_get_softc(dev);
-
- bus->needs_explore = 1;
- wakeup(&bus->needs_explore);
- }
- max--;
- }
- } else {
- printf("%s: \"usb\" devclass not present!\n",
- __FUNCTION__);
+ if (what == USB_BUS_EXPLORE_PROBE) {
+ what = USB_BUS_EXPLORE_SYNC;
+ goto repeat;
}
- mtx_unlock(&usb_global_lock);
return;
}
@@ -295,13 +312,14 @@
usb_probe(device_t dev)
{
PRINTF(("\n"));
- return (UMATCH_GENERIC);
+ return (0);
}
static void
usb_attach_sub(device_t dev, struct usbd_bus *bus)
{
dev_clone_fn usb_clone_ptr = &usb_clone;
+ struct usbd_device *child;
usbd_status_t err;
uint8_t speed;
@@ -335,33 +353,29 @@
return;
}
- err = usbd_new_device(bus->bdev, bus, NULL, 0, speed, 0, 0);
+ /* Allocate the Root USB device */
- if (!err) {
- err = usbd_probe_and_attach(bus->bdev, bus->devices[USB_START_ADDR]);
+ child = usbd_alloc_device(bus->bdev, bus, NULL, 0, 0, 1,
+ speed, USB_MODE_HOST);
+ if (child) {
+ err = usbd_probe_and_attach(child,
+ USB_IFACE_INDEX_ANY);
+ if (!err) {
+ if (!bus->devices[USB_ROOT_HUB_ADDR]->hub) {
+ err = USBD_NO_ROOT_HUB;
+ }
+ }
+ } else {
+ err = USBD_NOMEM;
}
- if (!err) {
- if (bus->devices[USB_START_ADDR]->hub == NULL) {
- device_printf(bus->bdev,
- "root device is not a hub\n");
- return;
- }
- /*
- * the USB bus is explored here so that devices,
- * for example the keyboard, can work during boot
- */
- /* make sure that the bus is explored */
- bus->needs_explore = 1;
-
- usb_discover(bus);
- } else {
- device_printf(bus->bdev, "root hub problem, error=%s\n",
+ if (err) {
+ device_printf(bus->bdev, "Root HUB problem, error=%s\n",
usbd_errstr(err));
}
+ /* Make sure that the USB BUS is explored */
+ bus->needs.explore = 1;
- usb_create_event_thread(bus);
-
snprintf(bus->usb_name, sizeof(bus->usb_name), "usb%u", device_get_unit(dev));
bus->usb_clone_tag = EVENTHANDLER_REGISTER(dev_clone, usb_clone_ptr, bus, 1000);
@@ -376,6 +390,10 @@
if (bus->usb_cdev == NULL) {
device_printf(dev, "Creating dummy device failed!\n");
}
+ /* create and start the event thread */
+
+ usb_create_event_thread(bus);
+
return;
}
@@ -408,22 +426,22 @@
dc = devclass_find("usb");
if (dc) {
- max = devclass_get_maxunit(dc);
- for (n = 0; n <= max; n++) {
+ max = devclass_get_maxunit(dc) + 1;
+ for (n = 0; n != max; n++) {
dev = devclass_get_device(dc, n);
if (dev) {
bus = device_get_softc(dev);
-
usb_attach_sub(dev, bus);
}
}
- } else {
- printf("%s: \"usb\" devclass not present!\n",
- __FUNCTION__);
}
usb_post_init_called = 1;
+ /* explore all USB busses in parallell */
+
+ usb_needs_probe_and_attach();
+
mtx_unlock(&usb_global_lock);
return;
@@ -435,38 +453,25 @@
usb_detach(device_t dev)
{
struct usbd_bus *bus = device_get_softc(dev);
- int32_t error;
+ struct usbd_device *udev = bus->devices[USB_ROOT_HUB_ADDR];
PRINTF(("start\n"));
+ /* get rid of explore thread */
+ usb_needs_explore(bus, USB_BUS_EXPLORE_STOP);
+
mtx_lock(&usb_global_lock);
- /* wait for any possible explore calls to finish */
- while (bus->is_exploring) {
- bus->wait_explore = 1;
-
- error = mtx_sleep(&bus->wait_explore, &usb_global_lock, 0,
- "usb wait explore", 0);
- }
-
/* detach children first */
bus_generic_detach(dev);
- if (bus->devices[USB_START_ADDR] != NULL) {
- /*
- * free device, but not sub-devices, hence they are freed by
- * the caller of this function
- */
- usbd_free_device(bus->devices[USB_START_ADDR], 0);
- }
- /* kill off event thread */
- if (bus->event_thread != NULL) {
- wakeup(&bus->needs_explore);
+ /*
+ * Free USB Root device, but not any sub-devices, hence they
+ * are freed by the caller of this function
+ */
+ usbd_detach_device(udev, USB_IFACE_INDEX_ANY, 0);
+ usbd_free_device(udev);
- error = mtx_sleep(bus, &usb_global_lock, 0, "usbdet", 0);
-
- PRINTF(("event thread dead\n"));
- }
mtx_unlock(&usb_global_lock);
mtx_lock(&bus->mtx);
@@ -723,7 +728,6 @@
{
struct usb_device_enumerate *ude = (void *)addr;
struct usbd_device *parent_hub;
- usb_port_status_t ps;
uint8_t old_addr;
uint8_t buf[8];
@@ -738,7 +742,7 @@
error = EINVAL;
goto ret002;
}
- error = usbreq_reset_port(parent_hub, NULL, &ps, udev->port_no);
+ error = usbreq_reset_port(parent_hub, NULL, udev->port_no);
if (error) {
error = ENXIO;
goto ret002;
More information about the p4-projects
mailing list