• OGAWA Hirofumi's avatar
    xhci: Fix race related to abort operation · 59185ef0
    OGAWA Hirofumi authored
    commit 1c111b6c upstream.
    
    Current abort operation has race.
    
        xhci_handle_command_timeout()
          xhci_abort_cmd_ring()
            xhci_write_64(CMD_RING_ABORT)
            xhci_handshake(5s)
    	  do {
    	    check CMD_RING_RUNNING
                udelay(1)
    					 ...
    					 COMP_CMD_ABORT event
    					 COMP_CMD_STOP event
    					 xhci_handle_stopped_cmd_ring()
    					   restart cmd_ring
                                               CMD_RING_RUNNING become 1 again
    	  } while ()
              return -ETIMEDOUT
            xhci_write_64(CMD_RING_ABORT)
            /* can abort random command */
    
    To do abort operation correctly, we have to wait both of COMP_CMD_STOP
    event and negation of CMD_RING_RUNNING.
    
    But like above, while timeout handler is waiting negation of
    CMD_RING_RUNNING, event handler can restart cmd_ring. So timeout
    handler never be notice negation of CMD_RING_RUNNING, and retry of
    CMD_RING_ABORT can abort random command (BTW, I guess retry of
    CMD_RING_ABORT was workaround of this race).
    
    To fix this race, this moves xhci_handle_stopped_cmd_ring() to
    xhci_abort_cmd_ring().  And timeout handler waits COMP_CMD_STOP event.
    
    At this point, timeout handler is owner of cmd_ring, and safely
    restart cmd_ring by using xhci_handle_stopped_cmd_ring().
    
    [FWIW, as bonus, this way would be easily extend to add CMD_RING_PAUSE
    operation]
    
    [locks edited as patch is rebased on other locking fixes -Mathias]
    Signed-off-by: default avatarOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
    Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    59185ef0
xhci-mem.c 77.2 KB