Commit 225785ae authored by Alan Stern's avatar Alan Stern Committed by Felipe Balbi

USB: f_mass_storage: improve memory barriers and synchronization

This patch reworks the way f_mass_storage.c handles memory barriers
and synchronization:

	The driver now uses a wait_queue instead of doing its own
	task-state manipulations (even though only one task will ever
	use the wait_queue).

	The thread_wakeup_needed variable is removed.  It was only a
	source of trouble; although it was what the driver tested to
	see whether it should wake up, what we really wanted to see
	was whether a USB transfer had completed.

	All the explicit memory barriers scattered throughout the
	driver are replaced by a few calls to smp_load_acquire() and
	smp_store_release().

	The inreq_busy and outreq_busy fields are removed.  In their
	place, the driver keeps track of the current I/O direction by
	splitting BUF_STATE_BUSY into two states: BUF_STATE_SENDING
	and BUF_STATE_RECEIVING.

	The buffer states are no longer protected by a lock.  Mutual
	exclusion isn't needed; the state is changed only by the
	driver's main thread when it owns the buffer, and only by the
	request completion routine when the gadget core owns the buffer.

	The do_write() and throw_away_data() routines were reorganized
	to make efficient use of the new sleeping mechanism.  This
	resulted in the removal of one indentation level in those
	routines, making the patch appear to be more more complicated
	than it really is.

	In a few places, the driver allowed itself to be frozen although
	it really shouldn't have (in the middle of executing a SCSI
	command).  Those places have been fixed.

	The logic in the exception handler for aborting transfers and
	waiting for them to stop has been simplified.
Tested-by: default avatarThinh Nguyen <thinhn@synopsys.com>
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent 78db441d
...@@ -133,9 +133,10 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun) ...@@ -133,9 +133,10 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
#define FSG_MAX_LUNS 16 #define FSG_MAX_LUNS 16
enum fsg_buffer_state { enum fsg_buffer_state {
BUF_STATE_SENDING = -2,
BUF_STATE_RECEIVING,
BUF_STATE_EMPTY = 0, BUF_STATE_EMPTY = 0,
BUF_STATE_FULL, BUF_STATE_FULL
BUF_STATE_BUSY
}; };
struct fsg_buffhd { struct fsg_buffhd {
...@@ -151,9 +152,7 @@ struct fsg_buffhd { ...@@ -151,9 +152,7 @@ struct fsg_buffhd {
unsigned int bulk_out_intended_length; unsigned int bulk_out_intended_length;
struct usb_request *inreq; struct usb_request *inreq;
int inreq_busy;
struct usb_request *outreq; struct usb_request *outreq;
int outreq_busy;
}; };
enum fsg_state { enum fsg_state {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment