linux/drivers/usb/gadget
Thinh Nguyen 77f262550f usb: gadget: f_mass_storage: Serialize wake and sleep execution
commit dc9217b69d upstream.

f_mass_storage has a memorry barrier issue with the sleep and wake
functions that can cause a deadlock. This results in intermittent hangs
during MSC file transfer. The host will reset the device after receiving
no response to resume the transfer. This issue is seen when dwc3 is
processing 2 transfer-in-progress events at the same time, invoking
completion handlers for CSW and CBW. Also this issue occurs depending on
the system timing and latency.

To increase the chance to hit this issue, you can force dwc3 driver to
wait and process those 2 events at once by adding a small delay (~100us)
in dwc3_check_event_buf() whenever the request is for CSW and read the
event count again. Avoid debugging with printk and ftrace as extra
delays and memory barrier will mask this issue.

Scenario which can lead to failure:
-----------------------------------
1) The main thread sleeps and waits for the next command in
   get_next_command().
2) bulk_in_complete() wakes up main thread for CSW.
3) bulk_out_complete() tries to wake up the running main thread for CBW.
4) thread_wakeup_needed is not loaded with correct value in
   sleep_thread().
5) Main thread goes to sleep again.

The pattern is shown below. Note the 2 critical variables.
 * common->thread_wakeup_needed
 * bh->state

	CPU 0 (sleep_thread)		CPU 1 (wakeup_thread)
	==============================  ===============================

					bh->state = BH_STATE_FULL;
					smp_wmb();
	thread_wakeup_needed = 0;	thread_wakeup_needed = 1;
	smp_rmb();
	if (bh->state != BH_STATE_FULL)
		sleep again ...

As pointed out by Alan Stern, this is an R-pattern issue. The issue can
be seen when there are two wakeups in quick succession. The
thread_wakeup_needed can be overwritten in sleep_thread, and the read of
the bh->state maybe reordered before the write to thread_wakeup_needed.

This patch applies full memory barrier smp_mb() in both sleep_thread()
and wakeup_thread() to ensure the order which the thread_wakeup_needed
and bh->state are written and loaded.

However, a better solution in the future would be to use wait_queue
method that takes care of managing memory barrier between waker and
waiter.

Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
History 2017-09-15 18:29:54 +01:00
..
acm_ms.c usb: gadget: fix up some comments about CONFIG_USB_DEBUG 2013-12-20 09:51:24 -06:00
amd5536udc.c usb: delete non-required instances of include <linux/init.h> 2014-01-08 15:01:39 -08:00
amd5536udc.h usb: gadget: amd5536udc: remove unused structure member 2013-03-18 11:16:56 +02:00
at91_udc.c usb: gadget: at91_udc: move prepare clk into process context 2015-01-05 13:48:50 +00:00
at91_udc.h usb: gadget: at91_udc: add usb_clk for transition to common clk framework 2013-08-02 15:17:03 +03:00
atmel_usba_udc.c usb: gadget: udc: atmel: fix possible oops when unloading module 2015-01-22 16:33:25 +00:00
atmel_usba_udc.h usb: gadget: at91: using USBA_NR_DMAS for DMA channels 2014-02-19 13:47:12 -06:00
audio.c usb: gadget: remove usb_gadget_controller_number() 2012-09-10 16:43:24 +03:00
bcm63xx_udc.c usb: gadget: bcm63xx_udc: fix build failure on DMA channel code 2014-02-18 10:34:54 -06:00
cdc2.c usb: gadget: cdc2: fix conversion to new interface of f_ecm 2013-09-17 10:38:52 -05:00
composite.c usb: gadget: composite: Test get_alt() presence instead of set_alt() 2017-03-16 02:26:42 +00:00
config.c usb: gadget: always update HS/SS descriptors and create a copy of them 2012-10-31 15:09:44 +02:00
configfs.c usb: gadget: configfs: Fix interfaces array NULL-termination 2015-05-28 09:59:58 +01:00
configfs.h usb: gadget: OS descriptors: provide interface directory names 2014-06-19 10:06:48 -05:00
dbgp.c usb: gadget: allocate & giveback serial ports instead hard code them 2013-01-21 20:52:43 +02:00
dummy_hcd.c USB: gadget: dummy_hcd: fix hub-descriptor removable fields 2017-09-15 18:29:41 +01:00
epautoconf.c usb: delete non-required instances of include <linux/init.h> 2014-01-08 15:01:39 -08:00
ether.c usb: gadget: ether: put_usb_function on unbind 2013-07-25 20:35:23 +03:00
f_acm.c ACM gadget: fix endianness in notifications 2017-07-18 18:40:18 +01:00
f_ecm.c usb: gadget: f_ecm: remove compatibility layer 2013-12-12 13:43:36 -06:00
f_eem.c usb: gadget: f_eem: Staticize eem_alloc 2013-09-17 11:06:50 -05:00
f_fs.c usb: gadget: function: f_fs: pass companion descriptor along 2017-07-18 18:40:07 +01:00
f_hid.c usb: gadget: f_hid: Use spinlock instead of mutex 2017-06-05 21:16:57 +01:00
f_loopback.c usb: gadget: f_loopback: Fix sparse warning 2013-12-17 13:17:42 -06:00
f_mass_storage.c usb: gadget: f_mass_storage: Serialize wake and sleep execution 2017-09-15 18:29:54 +01:00
f_mass_storage.h usb: gadget: f_mass_storage: remove compatibility layer 2013-10-10 10:24:53 -05:00
f_midi.c usb: gadget: define free_ep_req as universal function 2017-06-05 21:16:57 +01:00
f_ncm.c usb: gadget: f_ncm: Fix sparse warning 2013-12-17 13:17:43 -06:00
f_obex.c usb: gadget: f_obex: Fix sparse warning 2013-12-17 13:17:43 -06:00
f_phonet.c usb: gadget: function: phonet: balance usb_ep_disable calls 2015-03-23 15:17:57 +00:00
f_rndis.c usb: gadget: f_rndis: fix interface id for OS descriptors 2014-10-05 13:40:57 -07:00
f_serial.c usb: gadget: f_serial: Fix sparse warning 2013-12-17 13:17:44 -06:00
f_sourcesink.c usb: gadget: define free_ep_req as universal function 2017-06-05 21:16:57 +01:00
f_subset.c usb: gadget: f_subset: replace PTR_RET with PTR_ERR_OR_ZERO 2014-04-21 14:07:29 -05:00
f_uac1.c usb: gadget: f_uac1: Staticize local functions 2013-08-09 16:34:19 +03:00
f_uac2.c usb: gadget: avoid exposing kernel stack 2016-08-22 22:38:12 +01:00
f_uvc.c usb: gadget: f_uvc: Fix SuperSpeed companion descriptor's wBytesPerInterval 2017-07-18 18:40:21 +01:00
f_uvc.h usb: gadget: uvc: Fix coding style issues introduced by SS support 2013-03-18 11:18:18 +02:00
fotg210-udc.c usb: gadget: fotg210-udc: remove unnecessary OOM messages 2014-05-14 09:23:27 -05:00
fotg210.h usb: gadget: add Faraday fotg210_udc driver 2013-06-10 17:58:11 +03:00
fsl_mxc_udc.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
fsl_qe_udc.c usb: gadget: fsl_qe_udc: signedness bug in qe_get_frame() 2016-11-20 01:17:15 +00:00
fsl_qe_udc.h usb: gadget: Complete fsl qe/udc driver conversion 2012-06-12 13:32:29 +03:00
fsl_udc_core.c usb: patches for v3.16 merge window 2014-05-23 11:28:21 +09:00
fsl_usb2_udc.h usb: gadget: fsl_mxc_udc: replace MX35_IO_ADDRESS to ioremap 2013-01-18 14:08:21 +02:00
functions.c usb: gadget: add a forward pointer from usb_function to its "instance" 2013-01-21 20:52:46 +02:00
fusb300_udc.c usb: gadget: fusb300_udc: remove unnecessary OOM messages 2014-05-14 09:23:28 -05:00
fusb300_udc.h usb: gadget: fusb300_udc: add FUSB300_EPSET0_STL_CLR for clearing EP0 stall 2013-04-02 16:57:24 +03:00
g_ffs.c usb: gadget: g_ffs: convert to new interface of f_fs 2013-12-12 13:43:39 -06:00
g_zero.h usb: gadget: define free_ep_req as universal function 2017-06-05 21:16:57 +01:00
gadget_chips.h usb: gadget: remove usb_gadget_controller_number() 2012-09-10 16:43:24 +03:00
gmidi.c usb: gadget: consider link speed for bMaxPower 2013-01-10 12:38:52 +02:00
goku_udc.c usb: delete non-required instances of include <linux/init.h> 2014-01-08 15:01:39 -08:00
goku_udc.h usb: gadget: goku_udc: let udc-core manage gadget->dev 2013-03-18 11:16:45 +02:00
gr_udc.c usb: gadget: gr_udc: Fix check for invalid number of microframes 2014-06-27 10:53:07 -05:00
gr_udc.h usb: gadget: Add UDC driver for Aeroflex Gaisler GRUSBDC 2013-12-23 19:26:13 -06:00
hid.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
inode.c USB: gadgetfs: fix checks of wTotalLength in config descriptors 2017-03-16 02:26:43 +00:00
Kconfig usb: pch_udc: usb gadget device support for Intel Quark X1000 2014-10-30 09:40:10 -07:00
lpc32xx_udc.c Merge branch 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm 2014-04-05 13:20:43 -07:00
m66592-udc.c usb: gadget: m66592-udc: forever loop in set_feature() 2015-09-30 13:20:38 +01:00
m66592-udc.h usb: gadget: m66592-udc: convert to udc_start/udc_stop 2013-01-24 21:11:29 +02:00
Makefile usb: dwc2/s3c-hsotg: move s3c-hsotg into dwc2 directory 2014-04-24 13:12:43 -07:00
mass_storage.c usb: gadget: mass_storage: convert to new interface of f_mass_storage 2013-10-10 10:24:10 -05:00
multi.c usb: gadget: fix up some comments about CONFIG_USB_DEBUG 2013-12-20 09:51:24 -06:00
mv_u3d.h usb: gadget: mv: Add USB 3.0 device driver for Marvell PXA2128 chip. 2012-06-22 13:08:21 +03:00
mv_u3d_core.c usb: gadget: mv_u3d_core: remove unnecessary OOM messages 2014-05-14 09:23:29 -05:00
mv_udc.h usb: gadget: mv_udc_core: remove unused clock 2013-04-02 11:42:45 +03:00
mv_udc_core.c usb: gadget: mv_udc_core: fix phy_regs I/O memory leak 2015-08-12 09:48:30 +01:00
ncm.c usb: gadget: ncm: convert to new function interface 2013-06-10 17:12:52 +03:00
ndis.h usb/net: rndis: break out <linux/rndis.h> defines 2012-05-12 15:02:22 -04:00
net2272.c usb: gadget: add "maxpacket_limit" field to struct usb_ep 2013-12-17 13:17:41 -06:00
net2272.h USB: net2272: driver for PLX NET2272 USB device controller 2011-06-06 16:47:27 -07:00
net2280.c Revert "usb: gadget: net2280: Add support for PLX USB338X" 2014-05-28 11:35:41 -07:00
net2280.h Revert "usb: gadget: net2280: Add support for PLX USB338X" 2014-05-28 11:35:41 -07:00
nokia.c usb: gadget: nokia: fix error recovery path for optional functions 2013-12-17 13:17:41 -06:00
omap_udc.c usb: delete non-required instances of include <linux/init.h> 2014-01-08 15:01:39 -08:00
omap_udc.h usb: gadget: Update omap_udc to use usb_endpoint_descriptor inside the struct usb_ep 2012-05-04 15:52:57 +03:00
pch_udc.c usb: pch_udc: usb gadget device support for Intel Quark X1000 2014-10-30 09:40:10 -07:00
printer.c usb: gadget: printer: enqueue printer's response for setup request 2015-05-04 16:06:38 +01:00
pxa25x_udc.c usb: delete non-required instances of include <linux/init.h> 2014-01-08 15:01:39 -08:00
pxa25x_udc.h usb: gadget: pxa25x_udc: convert to udc_start/udc_stop 2013-01-24 21:11:31 +02:00
pxa27x_udc.c usb: gadget: pxa27x: fix suspend callback 2016-01-11 10:50:15 +00:00
pxa27x_udc.h usb: gadget: pxa27x_udc: convert to udc_start/udc_stop 2013-01-24 21:11:31 +02:00
r8a66597-udc.c usb: gadget: r8a66597-udc: remove unnecessary OOM messages 2014-05-14 09:23:29 -05:00
r8a66597-udc.h gadget/r8a66597: remove conditional compilation of clk code 2012-07-30 17:25:12 -07:00
rndis.c usb: patches for v3.16 merge window 2014-05-23 11:28:21 +09:00
rndis.h usb: gadget: rndis: init & exit rndis at module load/unload 2013-06-10 17:58:09 +03:00
s3c-hsudc.c usb: gadget: s3c-hsudc: remove unused label 2014-02-18 10:52:53 -06:00
s3c2410_udc.c usb: gadget: s3c2410_udc: don't use pr_debug return value 2014-05-14 09:23:31 -05:00
s3c2410_udc.h usb: gadget: s3c2410: convert to udc_start/udc_stop 2013-01-24 21:11:32 +02:00
serial.c usb: gadget: serial: convert to new interface of f_obex 2013-04-03 14:43:36 +03:00
storage_common.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2014-06-12 10:30:18 -07:00
storage_common.h usb: gadget: mass storage: fix return of delayed status 2013-11-25 10:56:33 -06:00
tcm_usb_gadget.c Merge branch 'locking-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into next 2014-06-03 12:57:53 -07:00
tcm_usb_gadget.h usb: gadget: make sure each gadget is using same index for Product, Serial,… 2012-09-10 16:13:00 +03:00
u_ecm.h usb: gadget: f_ecm: add configfs support 2013-06-10 17:27:54 +03:00
u_eem.h usb: gadget: f_eem: add configfs support 2013-06-10 17:58:00 +03:00
u_ether.c usb: gadget: u_ether: remove interrupt throttling 2017-02-23 03:54:27 +00:00
u_ether.h usb: gadget: f_rndis: remove compatibility layer 2013-12-12 13:43:37 -06:00
u_ether_configfs.h usb: gadget: add helpers for configfs support for USB Ethernet 2013-06-10 17:15:43 +03:00
u_f.c usb: gadget: define free_ep_req as universal function 2017-06-05 21:16:57 +01:00
u_f.h usb: gadget: define free_ep_req as universal function 2017-06-05 21:16:57 +01:00
u_fs.h usb: gadget: f_fs: Add flags to descriptors block 2014-03-05 14:40:11 -06:00
u_gether.h usb: gadget: f_subset: add configfs support 2013-06-10 17:58:08 +03:00
u_ncm.h usb: gadget: f_ncm: add configfs support 2013-06-10 17:15:02 +03:00
u_os_desc.h usb: gadget: OS Feature Descriptors support 2014-05-14 09:38:16 -05:00
u_phonet.h usb: gadget: f_phonet: remove compatibility layer 2013-06-10 17:31:55 +03:00
u_rndis.h usb: gadget: f_rndis: OS descriptors support 2014-05-14 09:38:58 -05:00
u_serial.c tty: Fix low_latency BUG 2014-02-28 16:31:00 -08:00
u_serial.h usb: gadget: nokia: use function framework for ACM 2013-04-03 14:43:20 +03:00
u_uac1.c usb: gadget: u_uac1: add __user annotation 2013-08-09 16:34:13 +03:00
u_uac1.h usb: gadget: Rename audio function to uac1 2012-02-15 10:09:48 +02:00
udc-core.c usb: gadget: udc: core: don't starve DMA resources 2016-11-20 01:17:17 +00:00
usbstring.c usb: delete non-required instances of include <linux/init.h> 2014-01-08 15:01:39 -08:00
uvc.h [media] f_uvc: add v4l2_device and replace parent with v4l2_dev 2013-06-21 11:04:47 -03:00
uvc_queue.c usb: gadget: uvc: Set the vb2 queue timestamp flags 2014-05-15 11:07:56 -05:00
uvc_queue.h usb: gadget/uvc: Port UVC webcam gadget to use videobuf2 framework 2013-04-02 11:42:48 +03:00
uvc_v4l2.c usb: gadget/uvc: Add support for 'get_unmapped_area' for MMUless architectures 2013-04-02 11:42:49 +03:00
uvc_video.c usb: gadget: composite: always set ep->mult to a sensible value 2017-03-16 02:26:17 +00:00
webcam.c usb: gadget: consider link speed for bMaxPower 2013-01-10 12:38:52 +02:00
zero.c usb: gadget: zero: Fix SuperSpeed enumeration for alternate setting 1 2014-04-16 10:11:45 -05:00