Date: Wed, 12 Dec 2007 22:36:16 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 130743 for review Message-ID: <200712122236.lBCMaGgr077010@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=130743 Change 130743 by hselasky@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712122236.lBCMaGgr077010>