[PATCHv2] Input: xpad - Fix double URB submission races

2015-08-10 Thread Laura Abbott
The xpad driver has several races with respect to URB submission which
make it easy to end up with submission while active:

[ cut here ]
WARNING: CPU: 3 PID: 3563 at drivers/usb/core/urb.c:339
usb_submit_urb+0x2ad/0x5a0()
URB 8804078ac240 submitted while active
Modules linked in: fuse xt_CHECKSUM ipt_MASQUERADE nf_nat_masquerade_ipv4 tun
nf_conntrack_netbios_ns nf_conntrack_broadcast ip6t_rpfilter ip6t_REJECT
nf_reject_ipv6 xt_conntrack ebtable_nat ebtable_broute bridge ebtable_filter
ebtables ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6
ip6table_mangle ip6table_security ip6table_raw ip6table_filter ip6_tables
iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack
iptable_mangle iptable_security iptable_raw bnep xpadsnd_hda_codec_realtek
snd_hda_codec_hdmi snd_hda_codec_generic snd_hda_intel snd_hda_codec
snd_hda_core snd_hwdep snd_seq intel_rapl iosf_mbi snd_seq_device
x86_pkg_temp_thermal coretemp snd_pcm kvm uvcvideo iTCO_wdt iTCO_vendor_support
iwlwifi videobuf2_vmalloc videobuf2_core videobuf2_memops
v4l2_common btusb videodev btrtl btbcm thinkpad_acpi snd_timer btintel
mei_me rtsx_pci_ms cfg80211 bluetooth pcspkr mei media memstick joydev snd
tpm_tis shpchp ie31200_edac i2c_i801 tpm lpc_ich edac_core nfsd rfkill wmi
soundcore auth_rpcgss nfs_acl lockd grace sunrpc binfmt_misc dm_crypt i915 8021q
garp stp llc mrp i2c_algo_bit drm_kms_helper drm rtsx_pci_sdmmc mmc_core e1000e
crct10dif_pclmul crc32_pclmul crc32c_intel rtsx_pci ghash_clmulni_intel
ptp serio_raw pps_core mfd_core video
CPU: 3 PID: 3563 Comm: led_test.sh Not tainted 4.2.0-rc4-xpad+ #14
Hardware name: LENOVO 20BFS0EC00/20BFS0EC00, BIOS GMET62WW (2.10 )
03/19/2014
 17a45bc6 8800c9a0fbd8 81758a11
 8800c9a0fc30 8800c9a0fc18 8109b656
0002 8804078ac240 00d0 8800c9806d60
Call Trace:
[] dump_stack+0x45/0x57
[] warn_slowpath_common+0x86/0xc0
[] warn_slowpath_fmt+0x55/0x70
[] ? do_truncate+0x88/0xc0
[] usb_submit_urb+0x2ad/0x5a0
[] ? mntput+0x24/0x40
[] ? terminate_walk+0xc7/0xe0
[] xpad_send_led_command+0xc7/0x110 [xpad]
[] xpad_led_set+0x15/0x20 [xpad]
[] led_set_brightness+0x88/0xc0
[] brightness_store+0x7e/0xc0
[] dev_attr_store+0x18/0x30
[] sysfs_kf_write+0x37/0x40
[] kernfs_fop_write+0x11d/0x170
[] __vfs_write+0x37/0x100
[] ? __sb_start_write+0x58/0x110
[] ? security_file_permission+0x3d/0xc0
[] vfs_write+0xa6/0x1a0
[] ? filp_close+0x5a/0x80
[] SyS_write+0x55/0xc0
[] entry_SYSCALL_64_fastpath+0x12/0x71
---[ end trace f573b768c94a66d6 ]---

This is easily reproducible with

while true; do
for i in $(seq 0 5); do
echo $i > /sys/class/leds/xpad0/subsystem/xpad0/brightness
done
done

xpad_send_led_command attempts to protect against races by locking
around usb_submit_urb. This is not sufficent since usb_submit_urb
is asynchronous; the urb is considered to be in use until the callback
(xpad_irq_out) returns appropriately. Additionally, there is no
protection at all in xpad_play_effect which uses the same urb. Fix this
by creating a queue for urb submission. This will serialize requests to
ensure only one is submitted at a time.

Signed-off-by: Laura Abbott 
---
v2: Created a proper queue for events instead of just dropping them
---
 drivers/input/joystick/xpad.c | 273 ++
 1 file changed, 194 insertions(+), 79 deletions(-)

diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index f8850f9..e94cc49 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -100,6 +100,9 @@
 #define XTYPE_XBOXONE 3
 #define XTYPE_UNKNOWN 4
 
+#define OUT_IRQ_SUBMITTED  0
+#define OUT_IRQ_QUEUE_EMPTY1
+
 static bool dpad_to_buttons;
 module_param(dpad_to_buttons, bool, S_IRUGO);
 MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for 
unknown pads");
@@ -334,7 +337,9 @@ struct usb_xpad {
struct urb *irq_out;/* urb for interrupt out report */
unsigned char *odata;   /* output data */
dma_addr_t odata_dma;
-   struct mutex odata_mutex;
+   unsigned long odata_flags;
+   spinlock_t queue_lock;
+   struct list_head odata_queue;   /* queue of commands */
 
 #if defined(CONFIG_JOYSTICK_XPAD_LEDS)
struct xpad_led *led;
@@ -347,6 +352,94 @@ struct usb_xpad {
unsigned long led_no;   /* led to lit on xbox360 controllers */
 };
 
+struct xpad_queue_item {
+   char odata[XPAD_PKT_LEN];
+   int transfer_length;
+   struct list_head entry;
+};
+
+static void __xpad_remove_urb(struct usb_xpad *xpad, struct xpad_queue_item 
*item)
+{
+   list_del(&item->entry);
+   kfree(item);
+}
+
+/*
+ * This function must be called with the queue lock held
+ *
+ * returns
+ *  0 - urb successfully submitted
+ *  OUT_IRQ_QUEUE_EMPTY - queue was empty
+ *  negative - error submittin

Re: [PATCHv2] Input: xpad - Fix double URB submission races

2015-08-24 Thread Laura Abbott

On 08/21/2015 09:50 AM, Dmitry Torokhov wrote:

Hi Laura,

On Mon, Aug 10, 2015 at 05:26:12PM -0700, Laura Abbott wrote:

v2: Created a proper queue for events instead of just dropping them


How long does it take for the queue to exhaust your memory if you keep
bombarding the driver with requests?



My script which changes the LEDs as fast as possible ran for 7+ hours on
my machine with 16GB of RAM without exhausting all of it. This is also a
very extreme case as almost any kind of delay between sending
commands will drain the queue.
 

I do not think you need a queue. I believe the nature of LEDs and rumble
force feedback effect is such that you can discard all requests but the
latest that arrived between the moment you submitted a request to the
device and the moment you are ready submit a new one.


So your suggestion is to only keep a single item in the queue?



Thanks.



Thanks,
Laura
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCHv2] Input: xpad - Fix double URB submission races

2015-08-26 Thread Dmitry Torokhov
On Mon, Aug 24, 2015 at 9:22 PM, Laura Abbott  wrote:
> On 08/21/2015 09:50 AM, Dmitry Torokhov wrote:
>>
>> Hi Laura,
>>
>> On Mon, Aug 10, 2015 at 05:26:12PM -0700, Laura Abbott wrote:
>>>
>>> v2: Created a proper queue for events instead of just dropping them
>>
>>
>> How long does it take for the queue to exhaust your memory if you keep
>> bombarding the driver with requests?
>>
>
> My script which changes the LEDs as fast as possible ran for 7+ hours on
> my machine with 16GB of RAM without exhausting all of it. This is also a
> very extreme case as almost any kind of delay between sending
> commands will drain the queue.

Hmm, that means the device is able to process requests pretty fast;
I'm impressed.

>
>>
>> I do not think you need a queue. I believe the nature of LEDs and rumble
>> force feedback effect is such that you can discard all requests but the
>> latest that arrived between the moment you submitted a request to the
>> device and the moment you are ready submit a new one.
>
>
> So your suggestion is to only keep a single item in the queue?

That would not be a queue anymore, but essentially yes. Store pending
brightness and FF effect in the driver structure and simply replace it
with the latest requests until the device is ready to process next
request. You need to take care alternating serving LED vs FF requests
to make sure one does not starve another.

Thanks!

-- 
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCHv2] Input: xpad - Fix double URB submission races

2015-08-21 Thread Dmitry Torokhov
Hi Laura,

On Mon, Aug 10, 2015 at 05:26:12PM -0700, Laura Abbott wrote:
> v2: Created a proper queue for events instead of just dropping them

How long does it take for the queue to exhaust your memory if you keep
bombarding the driver with requests?

I do not think you need a queue. I believe the nature of LEDs and rumble
force feedback effect is such that you can discard all requests but the
latest that arrived between the moment you submitted a request to the
device and the moment you are ready submit a new one.

Thanks.

-- 
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/