On Tue, Jul 23, 2013 at 04:30:29AM -0500, Josef Schimke wrote:
> wrt that:
> 1.  Am I on the right track thinking like that?
> 2.  Does the USB stuff in the kernel already have a way to test this?
> 3.  If not, I'm really stumped about how I can do this, so any advice
> would be great.  :p
> 
> Aside from that - in hid_start_in(), would it have been better if I'd
> used goto and a label instead of breaking from the for loop?  I wouldn't
> have to test if (rc == 0) to clear that HID_NO_BANDWIDTH bit that way,
> but it seemed more messy.

I'd recommend just always using 2 interrupt urbs, it can't hurt other
devices / host controllers if it's always there.

> diff -uprN -X linux-3.10-vanilla/Documentation/dontdiff 
> linux-3.10-vanilla/drivers/hid/usbhid/hid-core.c 
> linux-3.10-dev/drivers/hid/usbhid/hid-core.c
> --- linux-3.10-vanilla/drivers/hid/usbhid/hid-core.c  2013-06-30 
> 17:13:29.000000000 -0500
> +++ linux-3.10-dev/drivers/hid/usbhid/hid-core.c      2013-07-22 
> 16:00:24.785950521 -0500
> @@ -80,20 +80,26 @@ static int hid_start_in(struct hid_devic
>       unsigned long flags;
>       int rc = 0;
>       struct usbhid_device *usbhid = hid->driver_data;
> +     int i;
>  
>       spin_lock_irqsave(&usbhid->lock, flags);
>       if (hid->open > 0 &&
>                       !test_bit(HID_DISCONNECTED, &usbhid->iofl) &&
>                       !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
>                       !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
> -             rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
> -             if (rc != 0) {
> -                     clear_bit(HID_IN_RUNNING, &usbhid->iofl);
> -                     if (rc == -ENOSPC)
> -                             set_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
> -             } else {
> -                     clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
> +             for (i = 0; i < usbhid->n_inurbs; i++) {
> +                     rc = usb_submit_urb(usbhid->inurbs[i], GFP_ATOMIC);
> +                     if (rc != 0) {
> +                             clear_bit(HID_IN_RUNNING, &usbhid->iofl);
> +                             if (rc == -ENOSPC)
> +                                     set_bit(HID_NO_BANDWIDTH, 
> &usbhid->iofl);
> +
> +                             break;
> +                     }
>               }
> +
> +             if (rc == 0)
> +                     clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
>       }
>       spin_unlock_irqrestore(&usbhid->lock, flags);
>       return rc;
> @@ -120,7 +126,7 @@ static void hid_reset(struct work_struct
>  
>       if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) {
>               dev_dbg(&usbhid->intf->dev, "clear halt\n");
> -             rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe);
> +             rc = usb_clear_halt(hid_to_usb_dev(hid), 
> usbhid->inurbs[0]->pipe);
>               clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
>               hid_start_in(hid);
>       }
> @@ -780,6 +786,7 @@ done:
>  void usbhid_close(struct hid_device *hid)
>  {
>       struct usbhid_device *usbhid = hid->driver_data;
> +     int i;
>  
>       mutex_lock(&hid_open_mut);
>  
> @@ -791,7 +798,10 @@ void usbhid_close(struct hid_device *hid
>       if (!--hid->open) {
>               spin_unlock_irq(&usbhid->lock);
>               hid_cancel_delayed_stuff(usbhid);
> -             usb_kill_urb(usbhid->urbin);
> +
> +             for (i = 0; i < usbhid->n_inurbs; i++)
> +                     usb_kill_urb(usbhid->inurbs[i]);
> +
>               usbhid->intf->needs_remote_wakeup = 0;
>       } else {
>               spin_unlock_irq(&usbhid->lock);
> @@ -1087,6 +1097,7 @@ static int usbhid_start(struct hid_devic
>       struct usb_device *dev = interface_to_usbdev(intf);
>       struct usbhid_device *usbhid = hid->driver_data;
>       unsigned int n, insize = 0;
> +     int i;
>       int ret;
>  
>       clear_bit(HID_DISCONNECTED, &usbhid->iofl);
> @@ -1133,16 +1144,33 @@ static int usbhid_start(struct hid_devic
>                       interval = hid_mousepoll_interval;
>  
>               ret = -ENOMEM;
> +
> +             /*
> +              * Some controllers need more than one input URB to prevent 
> data from being lost
> +              * while processing a prior completed URB.
> +              */
> +             usbhid->n_inurbs = 2;
> +
> +             if (usbhid->inurbs)
> +                     continue;
> +
> +             usbhid->inurbs = kmalloc(usbhid->n_inurbs * sizeof(struct urb 
> *), GFP_KERNEL);

A hint, run your patch through scripts/checkpatch.pl so that people
don't complain about coding style issues next time :)

I can't see anything really wrong with this, care to resend it with a
signed-off-by: line so that Jiri can apply it (if he agrees with it?)

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to