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