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: Thinh Nguyen <thinhn@synopsys.com> Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>