usb: gadget: serial: fix re-ordering of tx data
authorPhilip Oberstaller <Philip.Oberstaller@septentrio.com>
Fri, 27 Mar 2015 16:42:18 +0000 (17:42 +0100)
committerFelipe Balbi <balbi@ti.com>
Mon, 27 Apr 2015 19:44:29 +0000 (14:44 -0500)
commit3e9d3d2efc677b501b12512cab5adb4f32a0673a
tree99374f697bbd56447003e3f42d9cbf8baafcd0c5
parentf286d487e9283a42a8844659bb5552b3f1bf6a7d
usb: gadget: serial: fix re-ordering of tx data

When a single thread is sending out data over the gadget serial port,
gs_start_tx() will be called both from the sender context and from the
write completion. Since the port lock is released before the packet is
queued, the order in which the URBs are submitted is not guaranteed.
E.g.

  sending thread                      completion (interrupt)

  gs_write()
    LOCK
                                      gs_write_complete()
                                        LOCK (wait)
    gs_start_tx()
      req1 = list_entry(pool->next)
      UNLOCK
                                        LOCK (acquired)
                                        gs_start_tx()
                                          req2 = list_entry(pool->next)
                                          UNLOCK
                                          usb_ep_queue(req2)
      usb_ep_queue(req1)

I.e., req2 is submitted before req1 but it contains the data that
comes after req1.

To reproduce, use SMP with sending thread and completion pinned to
different CPUs, or use PREEMPT_RT, and add the following delay just
before the call to usb_ep_queue():

if (port->write_started > 0 && !list_empty(pool))
udelay(1000);

To work around this problem, make sure that only one thread is running
through the gs_start_tx() loop with an extra flag write_busy. Since
gs_start_tx() is always called with the port lock held, no further
synchronisation is needed. The original caller will continue through
the loop when the request was successfully submitted.

Signed-off-by: Philip Oberstaller <Philip.Oberstaller@septentrio.com>
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/gadget/function/u_serial.c