On Mon, 10 Dec 2012 05:24:02 -0800 Chris Moeller <kode54@xxxxxxxxx> wrote: > On Mon, 10 Dec 2012 04:43:54 -0800 > Chris Moeller <kode54@xxxxxxxxx> wrote: > > > On Mon, 10 Dec 2012 02:58:25 -0800 > > Chris Moeller <kode54@xxxxxxxxx> wrote: > > > > > On Sun, 2 Dec 2012 23:43:18 -0800 > > > Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx> wrote: > > > > > > > On Fri, Nov 30, 2012 at 08:13:29PM -0800, Chris Moeller wrote: > > > > > On Fri, 30 Nov 2012 14:30:23 -0800 > > > > > Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx> wrote: > > > > > > > > > > > Hi Chris, > > > > > > > > > > > > On Friday, November 30, 2012 01:54:06 PM Chris Moeller > > > > > > wrote: > > > > > > > I've submitted versions of this with prior patch sets, and > > > > > > > this part was never accepted, possibly because it depended > > > > > > > on other patches to work, or possibly because it wasn't so > > > > > > > cleanly organized. This time, I've split the LED setting > > > > > > > command off into its own static function, then call that > > > > > > > on controller connect and optionally on LED setting > > > > > > > commands. The static function does not include any > > > > > > > locking, because locking inside the function which > > > > > > > receives the incoming packets deadlocks the driver, and > > > > > > > does not appear to be necessary anyway. > > > > > > > > > > > > > > It also removes all traces of the original bulk out > > > > > > > function which was designed for the purpose of setting > > > > > > > the LED status on connect, as I found that it actually > > > > > > > does not work at all. It appears to try to send the data, > > > > > > > but nothing actually happens to the controller LEDs. > > > > > > > > > > > > Attached is a reply I sent to on 7/4/11 to which you > > > > > > unfortunately never responded. The issue is that of force > > > > > > feedback (rumble) and LED share the same URB then access to > > > > > > that URB should be arbitrated. The attached message > > > > > > contains a patch that attempts to implement that > > > > > > arbitration, could you please try it out and see what > > > > > > changes are needed to make it work? > > > > > > > > > > > > Thanks. > > > > > > > > > > > > > > > > So sorry I missed your reply. That's what I get for filtering > > > > > the mailing list messages past my inbox, then never following > > > > > up on my filter/folder set for replies to my own messages. I > > > > > recall you mentioned that potential race condition when I > > > > > first submitted, but I forgot to do anything about it. I'm > > > > > glad at least one of us has our stuff together. It seems to > > > > > work just fine, but there may be a force feedback issue with > > > > > the following test program, where it leaves the effect playing > > > > > indefinitely after the program terminates, and then the > > > > > controller itself ceases to respond until the module is > > > > > removed and reloaded. > > > > > > > > Just to confirm, you see this problem only with the patch being > > > > discussed and do not see it without it, right? > > > > > > > > > > Yeah, the problem only happens with this patch. Here's a silly > > > mess which fixes it. If you can think of a better way to handle > > > pending commands outside of the IRQ, be my guest. The problem > > > seems to be that it doesn't like sending further commands from > > > inside the output irq callback, so further commands are not sent, > > > and the spinlock is left locked or something. So it seems that it > > > needs to be such that the callback merely signals when the packet > > > has completed sending, and the actual queue must be handled > > > outside of the irq, and somehow kindly wait for the irq to > > > complete for each command. Unless, you know, there's some other > > > way to queue up multiple commands without waiting on each one to > > > complete. I know bulk out doesn't work for the LED setting > > > command, at least. Anyway, here goes. > > > > Disregard this patch, it locks up frequently. I'm working on > > something else instead. > > Okay, this one seems to work. LED setting doesn't lock up like the old > mutex regulated LED setting mode, and I can successfully power off and > on the controller while that previously posted test program is still > running on the event device, without the LED setting clobbering the > rumble packets, and vice versa. > > --- > diff -urpN a/drivers/input/joystick/xpad.c > b/drivers/input/joystick/xpad.c --- > a/drivers/input/joystick/xpad.c 2012-12-10 03:59:14.407669714 > -0800 +++ b/drivers/input/joystick/xpad.c 2012-12-10 > 05:13:22.835479280 -0800 @@ -259,19 +259,17 @@ struct usb_xpad > { struct usb_interface *intf; /* usb interface */ > int pad_present; > + int interface_number; > > struct urb *irq_in; /* urb for interrupt in > report */ unsigned char *idata; /* input data */ > dma_addr_t idata_dma; > > - struct urb *bulk_out; > - unsigned char *bdata; > - > #if defined(CONFIG_JOYSTICK_XPAD_FF) || > defined(CONFIG_JOYSTICK_XPAD_LEDS) struct urb > *irq_out; /* urb for interrupt out report */ unsigned > char *odata; /* output data */ dma_addr_t odata_dma; > - struct mutex odata_mutex; > + spinlock_t odata_lock; > #endif > > #if defined(CONFIG_JOYSTICK_XPAD_LEDS) > @@ -441,13 +439,15 @@ static void xpad360_process_packet(struc > * > */ > > +static void xpad_send_led_command(struct usb_xpad *xpad, int > command); + > static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, > unsigned char *data) { > /* Presence change */ > if (data[0] & 0x08) { > if (data[1] & 0x80) { > xpad->pad_present = 1; > - usb_submit_urb(xpad->bulk_out, GFP_ATOMIC); > + xpad_send_led_command(xpad, 16); > } else > xpad->pad_present = 0; > } > @@ -502,29 +502,6 @@ exit: > __func__, retval); > } > > -static void xpad_bulk_out(struct urb *urb) > -{ > - struct usb_xpad *xpad = urb->context; > - struct device *dev = &xpad->intf->dev; > - > - switch (urb->status) { > - case 0: > - /* success */ > - break; > - case -ECONNRESET: > - case -ENOENT: > - case -ESHUTDOWN: > - /* this urb is terminated, clean up */ > - dev_dbg(dev, "%s - urb shutting down with status: > %d\n", > - __func__, urb->status); > - break; > - default: > - dev_dbg(dev, "%s - nonzero urb status received: > %d\n", > - __func__, urb->status); > - } > -} > - > -#if defined(CONFIG_JOYSTICK_XPAD_FF) || > defined(CONFIG_JOYSTICK_XPAD_LEDS) static void xpad_irq_out(struct > urb *urb) { > struct usb_xpad *xpad = urb->context; > @@ -574,7 +551,7 @@ static int xpad_init_output(struct usb_i > goto fail1; > } > > - mutex_init(&xpad->odata_mutex); > + spin_lock_init(&xpad->odata_lock); > > xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL); > if (!xpad->irq_out) { > @@ -610,15 +587,12 @@ static void xpad_deinit_output(struct us > xpad->odata, xpad->odata_dma); > } > } > -#else > -static int xpad_init_output(struct usb_interface *intf, struct > usb_xpad *xpad) { return 0; } -static void xpad_deinit_output(struct > usb_xpad *xpad) {} -static void xpad_stop_output(struct usb_xpad > *xpad) {} -#endif > > #ifdef CONFIG_JOYSTICK_XPAD_FF > static int xpad_play_effect(struct input_dev *dev, void *data, > struct ff_effect *effect) { > + int retval; > + unsigned long flags; > struct usb_xpad *xpad = input_get_drvdata(dev); > > if (effect->type == FF_RUMBLE) { > @@ -628,6 +602,7 @@ static int xpad_play_effect(struct input > switch (xpad->xtype) { > > case XTYPE_XBOX: > + spin_lock_irqsave(&xpad->odata_lock, flags); > xpad->odata[0] = 0x00; > xpad->odata[1] = 0x06; > xpad->odata[2] = 0x00; > @@ -636,9 +611,13 @@ static int xpad_play_effect(struct input > xpad->odata[5] = weak / 256; /* right > actuator */ xpad->irq_out->transfer_buffer_length = 6; > > - return usb_submit_urb(xpad->irq_out, > GFP_ATOMIC); > + retval = usb_submit_urb(xpad->irq_out, > GFP_ATOMIC); > + spin_unlock_irqrestore(&xpad->odata_lock, > flags); + > + return retval; > > case XTYPE_XBOX360: > + spin_lock_irqsave(&xpad->odata_lock, flags); > xpad->odata[0] = 0x00; > xpad->odata[1] = 0x08; > xpad->odata[2] = 0x00; > @@ -649,9 +628,13 @@ static int xpad_play_effect(struct input > xpad->odata[7] = 0x00; > xpad->irq_out->transfer_buffer_length = 8; > > - return usb_submit_urb(xpad->irq_out, > GFP_ATOMIC); > + retval = usb_submit_urb(xpad->irq_out, > GFP_ATOMIC); > + spin_unlock_irqrestore(&xpad->odata_lock, > flags); + > + return retval; > > case XTYPE_XBOX360W: > + spin_lock_irqsave(&xpad->odata_lock, flags); > xpad->odata[0] = 0x00; > xpad->odata[1] = 0x01; > xpad->odata[2] = 0x0F; > @@ -666,7 +649,10 @@ static int xpad_play_effect(struct input > xpad->odata[11] = 0x00; > xpad->irq_out->transfer_buffer_length = 12; > > - return usb_submit_urb(xpad->irq_out, > GFP_ATOMIC); > + retval = usb_submit_urb(xpad->irq_out, > GFP_ATOMIC); > + spin_unlock_irqrestore(&xpad->odata_lock, > flags); + > + return retval; > > default: > dev_dbg(&xpad->dev->dev, > @@ -693,6 +679,43 @@ static int xpad_init_ff(struct usb_xpad > static int xpad_init_ff(struct usb_xpad *xpad) { return 0; } > #endif > > +static void xpad_send_led_command(struct usb_xpad *xpad, int command) > +{ > + unsigned long flags; > + if (xpad->xtype == XTYPE_XBOX360) { > + if (command >= 0 && command < 14) { > + spin_lock_irqsave(&xpad->odata_lock, flags); > + xpad->odata[0] = 0x01; > + xpad->odata[1] = 0x03; > + xpad->odata[2] = command; > + xpad->irq_out->transfer_buffer_length = 3; > + usb_submit_urb(xpad->irq_out, GFP_KERNEL); > + spin_unlock_irqrestore(&xpad->odata_lock, > flags); > + } > + } else if (xpad->xtype == XTYPE_XBOX360W) { > + if (command >= 0 && command < 17) { > + if (command == 16) > + command = 0x02 + > xpad->interface_number; > + spin_lock_irqsave(&xpad->odata_lock, flags); > + xpad->odata[0] = 0x00; > + xpad->odata[1] = 0x00; > + xpad->odata[2] = 0x08; > + xpad->odata[3] = 0x40 + command; > + xpad->odata[4] = 0x00; > + xpad->odata[5] = 0x00; > + xpad->odata[6] = 0x00; > + xpad->odata[7] = 0x00; > + xpad->odata[8] = 0x00; > + xpad->odata[9] = 0x00; > + xpad->odata[10] = 0x00; > + xpad->odata[11] = 0x00; > + xpad->irq_out->transfer_buffer_length = 12; > + usb_submit_urb(xpad->irq_out, GFP_KERNEL); > + spin_unlock_irqrestore(&xpad->odata_lock, > flags); > + } > + } > +} > + > #if defined(CONFIG_JOYSTICK_XPAD_LEDS) > #include <linux/leds.h> > > @@ -702,19 +725,6 @@ struct xpad_led { > struct usb_xpad *xpad; > }; > > -static void xpad_send_led_command(struct usb_xpad *xpad, int command) > -{ > - if (command >= 0 && command < 14) { > - mutex_lock(&xpad->odata_mutex); > - xpad->odata[0] = 0x01; > - xpad->odata[1] = 0x03; > - xpad->odata[2] = command; > - xpad->irq_out->transfer_buffer_length = 3; > - usb_submit_urb(xpad->irq_out, GFP_KERNEL); > - mutex_unlock(&xpad->odata_mutex); > - } > -} > - > static void xpad_led_set(struct led_classdev *led_cdev, > enum led_brightness value) > { > @@ -732,7 +742,7 @@ static int xpad_led_probe(struct usb_xpa > struct led_classdev *led_cdev; > int error; > > - if (xpad->xtype != XTYPE_XBOX360) > + if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != > XTYPE_XBOX360W) return 0; > > xpad->led = led = kzalloc(sizeof(struct xpad_led), > GFP_KERNEL); @@ -758,7 +768,8 @@ static int xpad_led_probe(struct > usb_xpa /* > * Light up the segment corresponding to controller number > */ > - xpad_send_led_command(xpad, (led_no % 4) + 2); > + if (xpad->xtype == XTYPE_XBOX360) > + xpad_send_led_command(xpad, (led_no % 4) + 2); > > return 0; > } > @@ -960,42 +971,7 @@ static int xpad_probe(struct usb_interfa > usb_set_intfdata(intf, xpad); > > if (xpad->xtype == XTYPE_XBOX360W) { > - /* > - * Setup the message to set the LEDs on the > - * controller when it shows up > - */ > - xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL); > - if (!xpad->bulk_out) { > - error = -ENOMEM; > - goto fail7; > - } > - > - xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL); > - if (!xpad->bdata) { > - error = -ENOMEM; > - goto fail8; > - } > - > - xpad->bdata[2] = 0x08; > - switch (intf->cur_altsetting->desc.bInterfaceNumber) > { > - case 0: > - xpad->bdata[3] = 0x42; > - break; > - case 2: > - xpad->bdata[3] = 0x43; > - break; > - case 4: > - xpad->bdata[3] = 0x44; > - break; > - case 6: > - xpad->bdata[3] = 0x45; > - } > - > - ep_irq_in = &intf->cur_altsetting->endpoint[1].desc; > - usb_fill_bulk_urb(xpad->bulk_out, udev, > - usb_sndbulkpipe(udev, > ep_irq_in->bEndpointAddress), > - xpad->bdata, XPAD_PKT_LEN, > xpad_bulk_out, xpad); - > + xpad->interface_number = > intf->cur_altsetting->desc.bInterfaceNumber / 2; /* > * Submit the int URB immediately rather than > waiting for open > * because we get status messages from the device > whether @@ -1006,13 +982,11 @@ static int xpad_probe(struct > usb_interfa xpad->irq_in->dev = xpad->udev; > error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); > if (error) > - goto fail9; > + goto fail7; > } > > return 0; > > - fail9: kfree(xpad->bdata); > - fail8: usb_free_urb(xpad->bulk_out); > fail7: input_unregister_device(input_dev); > input_dev = NULL; > fail6: xpad_led_disconnect(xpad); > @@ -1036,8 +1010,6 @@ static void xpad_disconnect(struct usb_i > xpad_deinit_output(xpad); > > if (xpad->xtype == XTYPE_XBOX360W) { > - usb_kill_urb(xpad->bulk_out); > - usb_free_urb(xpad->bulk_out); > usb_kill_urb(xpad->irq_in); > } > > @@ -1045,9 +1017,6 @@ static void xpad_disconnect(struct usb_i > usb_free_coherent(xpad->udev, XPAD_PKT_LEN, > xpad->idata, xpad->idata_dma); > > - kfree(xpad->bdata); > - kfree(xpad); > - > usb_set_intfdata(intf, NULL); > } > Has anything been done regarding this patch yet? I'm not seeing a whole lot of activity on this front. -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html