• Supriya Karanth's avatar
    usb: musb: Reselect index reg in interrupt context · 39287076
    Supriya Karanth authored
    musb INDEX register is getting modified/corrupted during temporary
    un-locking in a SMP system. Set this register with proper value
    after re-acquiring the lock
    
    Scenario:
    ---------
    CPU1 is handling a data transfer completion interrupt received for
    the CLASS1 EP
    CPU2 is handling a CLASS2 thread which is queuing data to musb for
    transfer
    
    Below is the error sequence:
    
             CPU1                   |             CPU2
    --------------------------------------------------------------------
    Data transfer completion inter- |
    rupt recieved.                  |
                                    |
    musb INDEX reg set to CLASS1 EP |
                                    |
    musb LOCK is acquired.          |
                                    |
                                    | CLASS2 thread queues data.
                                    |
                                    | CLASS2 thread tries to acquire musb
                                    | LOCK but lock is already taken by
                                    | CLASS1, so CLASS2 thread is
                                    | spinning.
                                    |
    From Interrupt Context musb     |
    giveback function is called     |
                                    |
    The giveback function releases  | CLASS2 thread now acquires LOCK
    LOCK                            |
                                    |
    ClASS1 Request's completion cal-| ClASS2 schedules the data transfer and
    lback is called                 | sets the MUSB INDEX to Class2 EP number
                                    |
    Interrupt handler for CLASS1 EP |
    tries to acquire LOCK and is    |
    spinning                        |
                                    |
    Interrupt for Class1 EP acquires| Class2 completes the scheduling etc and
    the MUSB LOCK                   | releases the musb LOCK
                                    |
    Interrupt for Class1 EP schedul-|
    es the next data transfer       |
    but musb INDEX register is still|
    set to CLASS2 EP                |
    
    Since the MUSB INDEX register is set to a different endpoint, we
    read and modify the wrong registers. Hence data transfer will not
    happen properly. This results in unpredictable behavior
    
    So, the MUSB INDEX register is set to proper value again when
    interrupt re-acquires the lock
    
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarSupriya Karanth <supriya.karanth@stericsson.com>
    Signed-off-by: default avatarPraveena Nadahally <praveen.nadahally@stericsson.com>
    Reviewed-by: default avatarsrinidhi kasagar <srinidhi.kasagar@stericsson.com>
    Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
    39287076
musb_gadget.c 58.7 KB