Hi,

the hub driver depends on GFP_ATOMIC not failing for correct
functioning. Here's a patch that handles it with a workqueue.

        Regards
                Oliver

Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
-----

--- a/drivers/usb/core/hub.c    2007-02-28 15:04:45.000000000 +0100
+++ b/drivers/usb/core/hub.c    2007-03-01 10:30:25.000000000 +0100
@@ -71,6 +71,7 @@
        unsigned                has_indicators:1;
        u8                      indicator[USB_MAXCHILDREN];
        struct delayed_work     leds;
+       struct delayed_work     low_mem_work;
 };
 
 
@@ -208,6 +209,24 @@
                        status);
 }
 
+#define USB_HUB_LOWMEM_DELAY 2*HZ
+
+static void low_mem_work(struct work_struct *work)
+{
+       struct usb_hub          *hub =
+               container_of(work, struct usb_hub, low_mem_work.work);
+       int r;
+
+       r = usb_submit_urb(hub->urb, GFP_KERNEL);
+       if (r < 0) {
+               if (r == -ENOMEM)
+                       schedule_delayed_work(&hub->low_mem_work,
+                               USB_HUB_LOWMEM_DELAY);
+               else
+                       dev_err (hub->intfdev, "resubmit --> %d\n", r);
+       }
+}
+
 #define        LED_CYCLE_PERIOD        ((2*HZ)/3)
 
 static void led_work (struct work_struct *work)
@@ -381,6 +400,8 @@
        if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0
                        && status != -ENODEV && status != -EPERM)
                dev_err (hub->intfdev, "resubmit --> %d\n", status);
+       if (status == -ENOMEM)
+               schedule_delayed_work(&hub->low_mem_work, USB_HUB_LOWMEM_DELAY);
 }
 
 /* USB 2.0 spec Section 11.24.2.3 */
@@ -508,6 +529,7 @@
 
        /* (blocking) stop khubd and related activity */
        usb_kill_urb(hub->urb);
+       cancel_delayed_work(&hub->low_mem_work);
        if (hub->has_indicators)
                cancel_delayed_work(&hub->leds);
        if (hub->has_indicators || hub->tt.hub)
@@ -936,6 +958,7 @@
        hub->intfdev = &intf->dev;
        hub->hdev = hdev;
        INIT_DELAYED_WORK(&hub->leds, led_work);
+       INIT_DELAYED_WORK(&hub->low_mem_work, low_mem_work);
 
        usb_set_intfdata (intf, hub);
        intf->needs_remote_wakeup = 1;

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