This is a note to let you know that I've just added the patch titled

     Subject: [PATCH] USB: create new workqueue thread for USB autosuspend

to my gregkh-2.6 tree.  Its filename is

     usb-create-new-workqueue-thread-for-usb-autosuspend.patch

This tree can be found at 
    http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/


>From [EMAIL PROTECTED] Tue Sep 19 07:14:32 2006
Date: Tue, 19 Sep 2006 10:14:07 -0400 (EDT)
From: Alan Stern <[EMAIL PROTECTED]>
To: Greg KH <[EMAIL PROTECTED]>
cc: USB development list <linux-usb-devel@lists.sourceforge.net>
Subject: [PATCH] USB: create new workqueue thread for USB autosuspend
Message-ID: <[EMAIL PROTECTED]>

This patch (as787) creates a new workqueue thread to handle delayed
USB autosuspend requests.  Previously the code used keventd.  However
it turns out that the hub driver's suspend routine calls
flush_scheduled_work(), making it a poor candidate for running in
keventd (the call immediately deadlocks).  The solution is to use a
new thread instead of keventd.

Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>


---
 drivers/usb/core/driver.c |   11 ++++++-----
 drivers/usb/core/usb.c    |   42 +++++++++++++++++++++++++++++++++++++++---
 drivers/usb/core/usb.h    |    1 +
 3 files changed, 46 insertions(+), 8 deletions(-)

--- gregkh-2.6.orig/drivers/usb/core/driver.c
+++ gregkh-2.6/drivers/usb/core/driver.c
@@ -24,6 +24,7 @@
 
 #include <linux/device.h>
 #include <linux/usb.h>
+#include <linux/workqueue.h>
 #include "hcd.h"
 #include "usb.h"
 
@@ -1135,7 +1136,7 @@ void usb_autosuspend_device(struct usb_d
        mutex_lock_nested(&udev->pm_mutex, udev->level);
        udev->pm_usage_cnt -= dec_usage_cnt;
        if (udev->pm_usage_cnt <= 0)
-               schedule_delayed_work(&udev->autosuspend,
+               queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
                                USB_AUTOSUSPEND_DELAY);
        mutex_unlock(&udev->pm_mutex);
        // dev_dbg(&udev->dev, "%s: cnt %d\n",
@@ -1219,10 +1220,10 @@ void usb_autopm_put_interface(struct usb
        struct usb_device       *udev = interface_to_usbdev(intf);
 
        mutex_lock_nested(&udev->pm_mutex, udev->level);
-       if (intf->condition != USB_INTERFACE_UNBOUND) {
-               if (--intf->pm_usage_cnt <= 0)
-                       schedule_delayed_work(&udev->autosuspend,
-                                       USB_AUTOSUSPEND_DELAY);
+       if (intf->condition != USB_INTERFACE_UNBOUND &&
+                       --intf->pm_usage_cnt <= 0) {
+               queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+                               USB_AUTOSUSPEND_DELAY);
        }
        mutex_unlock(&udev->pm_mutex);
        // dev_dbg(&intf->dev, "%s: cnt %d\n",
--- gregkh-2.6.orig/drivers/usb/core/usb.c
+++ gregkh-2.6/drivers/usb/core/usb.c
@@ -33,6 +33,7 @@
 #include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #include <asm/io.h>
 #include <asm/scatterlist.h>
@@ -47,6 +48,8 @@ const char *usbcore_name = "usbcore";
 
 static int nousb;      /* Disable USB when built into kernel image */
 
+struct workqueue_struct *ksuspend_usb_wq;      /* For autosuspend */
+
 
 /**
  * usb_ifnum_to_if - get the interface object with a given interface number
@@ -170,9 +173,9 @@ static void usb_release_dev(struct devic
 
        udev = to_usb_device(dev);
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_USB_SUSPEND
        cancel_delayed_work(&udev->autosuspend);
-       flush_scheduled_work();
+       flush_workqueue(ksuspend_usb_wq);
 #endif
        usb_destroy_configuration(udev);
        usb_put_hcd(bus_to_hcd(udev->bus));
@@ -184,6 +187,28 @@ static void usb_release_dev(struct devic
 
 #ifdef CONFIG_PM
 
+static int ksuspend_usb_init(void)
+{
+       ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd");
+       if (!ksuspend_usb_wq)
+               return -ENOMEM;
+       return 0;
+}
+
+static void ksuspend_usb_cleanup(void)
+{
+       destroy_workqueue(ksuspend_usb_wq);
+}
+
+#else
+
+#define ksuspend_usb_init()    0
+#define ksuspend_usb_cleanup() do {} while (0)
+
+#endif
+
+#ifdef CONFIG_USB_SUSPEND
+
 /* usb_autosuspend_work - callback routine to autosuspend a USB device */
 static void usb_autosuspend_work(void *_udev)
 {
@@ -195,6 +220,11 @@ static void usb_autosuspend_work(void *_
        mutex_unlock(&udev->pm_mutex);
 }
 
+#else
+
+static void usb_autosuspend_work(void *_udev)
+{}
+
 #endif
 
 /**
@@ -976,9 +1006,12 @@ static int __init usb_init(void)
                return 0;
        }
 
+       retval = ksuspend_usb_init();
+       if (retval)
+               goto out;
        retval = bus_register(&usb_bus_type);
        if (retval) 
-               goto out;
+               goto bus_register_failed;
        retval = usb_host_init();
        if (retval)
                goto host_init_failed;
@@ -1014,6 +1047,8 @@ major_init_failed:
        usb_host_cleanup();
 host_init_failed:
        bus_unregister(&usb_bus_type);
+bus_register_failed:
+       ksuspend_usb_cleanup();
 out:
        return retval;
 }
@@ -1035,6 +1070,7 @@ static void __exit usb_exit(void)
        usb_hub_cleanup();
        usb_host_cleanup();
        bus_unregister(&usb_bus_type);
+       ksuspend_usb_cleanup();
 }
 
 subsys_initcall(usb_init);
--- gregkh-2.6.orig/drivers/usb/core/usb.h
+++ gregkh-2.6/drivers/usb/core/usb.h
@@ -62,6 +62,7 @@ extern int usb_autoresume_device(struct 
 
 #endif
 
+extern struct workqueue_struct *ksuspend_usb_wq;
 extern struct bus_type usb_bus_type;
 extern struct usb_device_driver usb_generic_driver;
 


Patches currently in gregkh-2.6 which might be from [EMAIL PROTECTED] are

usb/usbcore-add-usb_device_driver-definition.patch
usb/usbcore-track-whether-interfaces-are-suspended.patch
usb/usbcore-add-configuration_string-to-attribute-group.patch
usb/usbcore-rename-usb_suspend_device-to-usb_port_suspend.patch
usb/usbcore-move-code-among-source-files.patch
usb/usb-pl2303-remove-80-columns-limit-violations-in-pl2303-driver.patch
usb/usb-usbtouchscreen-version-0.4.patch
usb/usbcore-khubd-and-busy-port-handling.patch
usb/usbcore-make-hcd_endpoint_disable-wait-for-queue-to-drain.patch
usb/usb-skeleton-don-t-submit-urbs-after-disconnection.patch
usb/usbcore-fix-up-device-and-power-state-tests.patch
usb/usbcore-make-usb_generic-a-usb_device_driver.patch
usb/usbcore-resume-device-resume-recursion.patch
usb/usbcore-set-device-and-power-states-properly.patch
usb/usbcore-split-suspend-resume-for-device-and-interfaces.patch
usb/usbcore-suspending-devices-with-no-driver.patch
usb/usbfs-detect-device-unregistration.patch
usb/usbfs-private-mutex-for-open-release-and-remove.patch
usb/hub-driver-improve-use-of-ifdef.patch
usb/usb-properly-unregister-reboot-notifier-in-case-of-failure-in-ehci-hcd.patch
usb/wusb-hub-recognizes-wusb-ports.patch
usb/uhci-increase-resume-detect-off-delay.patch
usb/wusb-handle-wusb-device-ep0-speed-settings.patch
usb/wusb-pretty-print-new-devices.patch
usb/usb-remove-struct-usb_operations.patch
usb/usb-deal-with-broken-config-descriptors.patch
usb/usb-storage-fix-for-ufi-lun-detection.patch
usb/usbcore-add-autosuspend-autoresume-infrastructure.patch
usb/usb-usb-hub-driver-improve-use-of-ifdef-fix.patch
usb/usbcore-help-drivers-to-change-device-configs.patch
usb/usb-replace-kernel_thread-with-kthread_run-in-libusual.c.patch
usb/usbcore-add-flag-for-whether-a-host-controller-uses-dma.patch
usb/usbcore-store-each-usb_device-s-level-in-the-tree.patch
usb/usbcore-trim-down-usb_bus-structure.patch
usb/usbcore-non-hub-specific-uses-of-autosuspend.patch
usb/usbcore-remove-usb_suspend_root_hub.patch
usb/usbmon-don-t-call-mon_dmapeek-if-dma-isn-t-being-used.patch
usb/usb-unusual_devs-entry-for-lacie-dvd-rw.patch
usb/usb-fix-root-hub-resume-when-config_usb_suspend-is-not-set.patch
usb/usb-force-root-hub-resume-after-power-loss.patch
usb/ohci-add-auto-stop-support.patch
usb/usb-allow-both-root-hub-interrupts-and-polling.patch
usb/usb-create-new-workqueue-thread-for-usb-autosuspend.patch
usb/usb-dummy-hcd-fix-warn-unused-result-messages.patch
usb/usb-fix-autosuspend-when-config_pm-isn-t-set.patch
usb/usb-fixes-kerneldoc-errors-in-usbcore-auto-patch.patch
usb/usb-g_file_storage-fix-ignoring-return-value-warnings.patch
usb/usb-g_file_storage-set-sense-info-valid-bit-only-when-needed.patch
usb/ohci-remove-existing-autosuspend-code.patch

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to