On Thu, 12 Jan 2006 17:19:02 -0500 (EST), Alan Stern <[EMAIL PROTECTED]> wrote:

> There was a mistake in my patch, an == that should have been !=.

You are not the first and not the last to be trapped by a function
returning a boolean instead of an error code. I approach this problem
with two things. First, I use != and == for error codes, and use
direct tests for error codes (so you'll never catch me writing
 !(p = kmalloc(len, gfp)) ). Second, I do not add new functions
returning booleans in kernel code.

> Here's the updated patch.

Looks good to me. I would not allocate the work struct, seems too much
trouble for an equivalent of seven pointers in size. Also, it is wrong
to submit URBs with GFP_KERNEL while holding a spinlock. I'm surprised
it didn't keel over with might_sleep()...

The hid_open is an oddball. The hiddev does not check its result, so
we should never return an error. Maybe it should be fixed elsewhere,
but for the purposes of this patch it better be made to return zero.
The whole system is weird. Observe how the disconnect causes forceful
closes. I'm amazed this works... Better not strain it too much.

Attached are changes I propose on top of the patch. Alan, your call.

-- Pete

diff -urp -X dontdiff linux-2.6.16-rc1-hid-stern/drivers/usb/input/hid-core.c 
linux-2.6.16-rc1-hid-stern-f1/drivers/usb/input/hid-core.c
--- linux-2.6.16-rc1-hid-stern/drivers/usb/input/hid-core.c     2006-01-24 
16:43:46.000000000 -0800
+++ linux-2.6.16-rc1-hid-stern-f1/drivers/usb/input/hid-core.c  2006-01-24 
17:18:13.000000000 -0800
@@ -926,11 +926,12 @@ static int hid_start_in(struct hid_devic
        spin_lock_irqsave(&hid->inlock, flags);
        if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) &&
                        !test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) {
+               spin_unlock_irqrestore(&hid->inlock, flags);
                rc = usb_submit_urb(hid->urbin, mem_flags);
                if (rc != 0)
                        clear_bit(HID_IN_RUNNING, &hid->iofl);
-       }
-       spin_unlock_irqrestore(&hid->inlock, flags);
+       } else
+               spin_unlock_irqrestore(&hid->inlock, flags);
        return rc;
 }
 
@@ -957,15 +958,13 @@ static void hid_reset(void *_hid)
                if (rc_lock)
                        usb_unlock_device(hid->dev);
        }
-       kfree(hid->reset_work);
        clear_bit(HID_RESET_PENDING, &hid->iofl);
 
        if (rc == 0) {
                hid->retry_delay = 0;
                if (hid_start_in(hid, GFP_KERNEL))
                        hid_io_error(hid);
-       } else if (rc != -ENODEV && rc != -EHOSTUNREACH &&
-                       rc != -EINTR)
+       } else if (rc != -ENODEV && rc != -EHOSTUNREACH && rc != -EINTR)
                err("can't reset device, %s-%s/input%d, status %d",
                                hid->dev->bus->bus_name,
                                hid->dev->devpath,
@@ -994,20 +993,13 @@ static void hid_io_error(struct hid_devi
 
                /* Retries failed, so do a port reset */
                if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
-                       hid->reset_work = kmalloc(sizeof(struct work_struct),
-                                       GFP_ATOMIC);
-                       if (hid->reset_work) {
-                               INIT_WORK(hid->reset_work, hid_reset, hid);
-                               if (schedule_work(hid->reset_work) != 0)
-                                       goto done;
-                               kfree(hid->reset_work);
-                       }
+                       if (schedule_work(&hid->reset_work))
+                               goto done;
                        clear_bit(HID_RESET_PENDING, &hid->iofl);
                }
        }
 
-       mod_timer(&hid->io_retry,
-                       jiffies + msecs_to_jiffies(hid->retry_delay));
+       mod_timer(&hid->io_retry, jiffies + msecs_to_jiffies(hid->retry_delay));
 done:
        spin_unlock_irqrestore(&hid->inlock, flags);
 }
@@ -1378,8 +1370,8 @@ static int hid_get_class_descriptor(stru
 int hid_open(struct hid_device *hid)
 {
        ++hid->open;
-       if (hid_start_in(hid, GFP_KERNEL) != 0)
-               return -EIO;
+       if (hid_start_in(hid, GFP_KERNEL))
+               hid_io_error(hid);
        return 0;
 }
 
@@ -1892,6 +1884,7 @@ static struct hid_device *usb_hid_config
 
        init_waitqueue_head(&hid->wait);
 
+       INIT_WORK(&hid->reset_work, hid_reset, hid);
        setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid);
 
        spin_lock_init(&hid->inlock);
diff -urp -X dontdiff linux-2.6.16-rc1-hid-stern/drivers/usb/input/hid.h 
linux-2.6.16-rc1-hid-stern-f1/drivers/usb/input/hid.h
--- linux-2.6.16-rc1-hid-stern/drivers/usb/input/hid.h  2006-01-24 
16:43:46.000000000 -0800
+++ linux-2.6.16-rc1-hid-stern-f1/drivers/usb/input/hid.h       2006-01-24 
17:12:02.000000000 -0800
@@ -400,7 +400,7 @@ struct hid_device {                                         
        /* device repo
        struct timer_list io_retry;                                     /* 
Retry timer */
        unsigned long stop_retry;                                       /* Time 
to give up, in jiffies */
        unsigned int retry_delay;                                       /* 
Delay length in ms */
-       struct work_struct *reset_work;                                 /* Task 
context for resets */
+       struct work_struct reset_work;                                  /* Task 
context for resets */
 
        unsigned int bufsize;                                           /* URB 
buffer size */
 


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642
_______________________________________________
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