Hi,

I did the dirty deed. Could you please tell me which quirky devices
you know of? I am afraid this list needs to be populated and there
are outstanding regressions in Adrian's list.

        Regards
                Oliver

--

--- a/include/linux/usb.h       2007-01-18 13:15:25.000000000 +0100
+++ b/include/linux/usb.h       2007-01-19 12:12:07.000000000 +0100
@@ -387,6 +387,7 @@
        struct usb_device *children[USB_MAXCHILDREN];
 
        int pm_usage_cnt;               /* usage counter for autosuspend */
+       int pm_quirks;                  /* quirks of power management */
 #ifdef CONFIG_PM
        struct delayed_work autosuspend; /* for delayed autosuspends */
        struct mutex pm_mutex;          /* protects PM operations */
@@ -1460,3 +1461,6 @@
 #endif  /* __KERNEL__ */
 
 #endif
+
+/* Power management quirks */
+#define USB_PM_DISCONNECT      1 /* devices which disconnect when resuming */
--- a/drivers/usb/core/hub.c    2007-01-17 14:26:17.000000000 +0100
+++ b/drivers/usb/core/hub.c    2007-01-19 12:31:08.000000000 +0100
@@ -31,6 +31,7 @@
 #include "usb.h"
 #include "hcd.h"
 #include "hub.h"
+#include "autosuspend_quirks.h"
 
 struct usb_hub {
        struct device           *intfdev;       /* the "interface" device */
@@ -1263,6 +1264,33 @@
 static int __usb_port_suspend(struct usb_device *, int port1);
 #endif
 
+#ifdef CONFIG_USB_SUSPEND
+
+static int usb_autosuspend_search_quirk(u16 vendor, u16 product, u16 version)
+{
+       const struct pm_blacklist *blentry = pm_blacklist;
+
+       while (blentry->idVendor) {
+               if (blentry->idVendor == vendor &&
+                       blentry->idProduct == product &&
+                       blentry->bcdVersionMin <= version &&
+                       blentry->bcdVersionMax >= version)
+                               return blentry->quirks;
+               blentry++;
+       }
+
+       return 0;
+}
+
+#else
+
+static int usb_autosuspend_search_quirk(u16 vendor, u16 product, u16 version)
+{
+       return 0;
+}
+
+#endif /* CONFIG_USB_SUSPEND */
+
 static int __usb_new_device(void *void_data)
 {
        struct usb_device *udev = void_data;
@@ -1359,6 +1387,12 @@
        }
 #endif
 
+       /* Determine power management quirks */
+       udev->pm_quirks = usb_autosuspend_search_quirk(
+               le16_to_cpu(udev->descriptor.idVendor),
+               le16_to_cpu(udev->descriptor.idProduct),
+               le16_to_cpu(udev->descriptor.bcdDevice));
+       dev_dbg(&udev->dev, "USB power management quirks: %d\n", 
udev->pm_quirks);
        /* Register the device.  The device driver is responsible
         * for adding the device files to usbfs and sysfs and for
         * configuring the device.
--- /dev/null   2006-05-02 08:46:16.000000000 +0200
+++ b/drivers/usb/core/autosuspend_quirks.h     2007-01-19 12:29:44.000000000 
+0100
@@ -0,0 +1,20 @@
+/*
+ * This is a list of USB devices which are quirky with respect
+ * to power management. Keep this list ordered by
+ * 1. Vendor
+ * 2. Product
+ * 3. Version, the most specific first
+ */
+
+
+static const struct pm_blacklist {
+       u16     idVendor; /* vendor id of the quirky device */
+       u16     idProduct; /* product id of the quirky device */
+       u16     bcdVersionMin; /* minimum version id of the afflicted devices */
+       u16     bcdVersionMax; /* maximum version id of the afflicted devices */
+       int     quirks; /* the actual qirks, several to be joined with binary 
or */
+} pm_blacklist[] = {
+       /* Elsa MicroLink 56k (V.250) */
+       {0x05cc, 0x2267, 0x0100, 0x0100, USB_PM_DISCONNECT},
+       {0, 0, 0, 0, 0} /* keep this last */
+};
--- a/drivers/usb/core/driver.c 2007-01-18 13:13:22.000000000 +0100
+++ b/drivers/usb/core/driver.c 2007-01-19 12:04:46.000000000 +0100
@@ -952,7 +952,7 @@
         * Also fail if any interfaces require remote wakeup but it
         * isn't available. */
        udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
-       if (udev->pm_usage_cnt > 0)
+       if (udev->pm_usage_cnt > 0 || udev->pm_quirks & USB_PM_DISCONNECT)
                return -EBUSY;
        if (udev->actconfig) {
                for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {

-------------------------------------------------------------------------
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