linux/drivers/usb/gadget/function
Thinh Nguyen dc9217b69d usb: gadget: f_mass_storage: Serialize wake and sleep execution
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.

Cc: <stable@vger.kernel.org>
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>
2017-06-02 12:44:08 +03:00
..
f_acm.c usb: gadget: acm: fix endianness in notifications 2017-03-22 11:20:52 +02:00
f_ecm.c
f_eem.c usb: gadget: prevent potenial null pointer dereference on skb->len 2016-09-06 10:44:03 +03:00
f_fs.c usb: gadget: f_fs: avoid out of bounds access on comp_desc 2017-05-16 14:11:04 +03:00
f_hid.c usb: gadget: f_hid: fix: Don't access hidg->req without spinlock held 2017-03-22 11:21:10 +02:00
f_loopback.c usb: gadget: remove variable ret and remove unnecessary if statement 2016-09-09 13:38:37 +03:00
f_mass_storage.c usb: gadget: f_mass_storage: Serialize wake and sleep execution 2017-06-02 12:44:08 +03:00
f_mass_storage.h usb: gadget: Add per-lun inquiry string 2016-08-25 12:13:13 +03:00
f_midi.c usb: gadget: remove useless parameter in alloc_ep_req() 2016-08-25 12:13:19 +03:00
f_ncm.c drivers: add explicit interrupt.h includes 2017-03-30 11:05:34 -07:00
f_obex.c
f_phonet.c net: use core MTU range checking in misc drivers 2016-10-20 14:51:10 -04:00
f_printer.c usb: gadget: printer: Remove pnp_string static buffer 2017-01-24 11:04:08 +02:00
f_rndis.c usb: gadget: function: f_rndis: socket buffer may be NULL 2016-08-22 10:45:12 +03:00
f_serial.c
f_sourcesink.c usb: gadget: remove useless parameter in alloc_ep_req() 2016-08-25 12:13:19 +03:00
f_subset.c
f_tcm.c usb: gadget: Correct usb EP argument for BOT status request 2017-03-30 01:36:50 -07:00
f_uac1.c
f_uac2.c usb: gadget: uac2: add req_number as parameter 2017-01-24 11:04:21 +02:00
f_uvc.c usb: gadget: f_uvc: Sanity check wMaxPacketSize for SuperSpeed 2017-03-22 11:21:09 +02:00
f_uvc.h
g_zero.h
Makefile
ndis.h
rndis.c usb: gadget: Fix checkpatch error for braces 2016-11-18 13:54:41 +02:00
rndis.h usb: gadget: Fix checkpatch error for braces 2016-11-18 13:54:41 +02:00
storage_common.c usb: gadget: Add per-lun inquiry string 2016-08-25 12:13:13 +03:00
storage_common.h usb: gadget: Add per-lun inquiry string 2016-08-25 12:13:13 +03:00
tcm.h
u_ecm.h
u_eem.h
u_ether_configfs.h usb: gadget: ether: Add \n to each attribute of ethernet functions 2017-01-24 11:04:07 +02:00
u_ether.c usb: gadget: u_ether: conditionally align transfer size 2017-04-11 10:58:21 +03:00
u_ether.h usb: gadget: u_ether: add a flag to avoid skb_reserve() calling 2016-08-31 10:06:03 +03:00
u_fs.h usb: changes for v4.12 2017-04-11 16:47:26 +02:00
u_gether.h
u_hid.h
u_midi.h
u_ncm.h
u_phonet.h
u_printer.h usb: gadget: printer: Remove pnp_string static buffer 2017-01-24 11:04:08 +02:00
u_rndis.h
u_serial.c usb: gadget: gserial: check if console kthread exists 2017-05-16 14:11:04 +03:00
u_serial.h
u_tcm.h
u_uac1.c
u_uac1.h
u_uac2.h usb: gadget: uac2: add req_number as parameter 2017-01-24 11:04:21 +02:00
u_uvc.h
uvc_configfs.c usb: gadget: uvc: Missing files for configfs interface 2017-04-11 10:57:59 +03:00
uvc_configfs.h
uvc_queue.c
uvc_queue.h
uvc_v4l2.c usb: gadget: Fix checkpatch error for braces 2016-11-18 13:54:41 +02:00
uvc_v4l2.h
uvc_video.c usb: gadget: composite: always set ep->mult to a sensible value 2016-10-31 11:15:33 +02:00
uvc_video.h
uvc.h usb: gadget: Fix checkpatch error for braces 2016-11-18 13:54:41 +02:00