• Thomas Gleixner's avatar
    usb: musb: Ensure that cppi41 timer gets armed on premature DMA TX irq · c58d80f5
    Thomas Gleixner authored
    Some TI chips raise the DMA complete interrupt before the actual
    transfer has been completed. The code tries to busy wait for a few
    microseconds and if that fails it arms an hrtimer to recheck. So far
    so good, but that has the following issue:
    CPU 0					CPU1
    DMA interrupt
      if (premature_irq(RQ1))
        if (!hrtimer_active(timer))
    hrtimer expires
      timer->state = CALLBACK_RUNNING;
          if (requests_pending())
    					DMA interrupt
    					  if (premature_irq(RQ2))
    					    if (!hrtimer_active(timer))
      timer->state = INACTIVE;
    The premature interrupt of request2 on CPU1 does not arm the timer and
    therefor the request completion never happens because it checks for
    !hrtimer_active(). hrtimer_active() evaluates:
      timer->state != HRTIMER_STATE_INACTIVE
    which of course evaluates to true in the above case as timer->state is
    That's clearly documented:
     * A timer is active, when it is enqueued into the rbtree or the
     * callback function is running or it's in the state of being migrated
     * to another cpu.
    But that's not what the code wants to check. The code wants to check
    whether the timer is queued, i.e. whether its armed and waiting for
    We have a helper function for this: hrtimer_is_queued(). This
      timer->state & HRTIMER_STATE_QUEUED
    So in the above case this evaluates to false and therefor forces the
    DMA interrupt on CPU1 to call hrtimer_start().
    Use hrtimer_is_queued() instead of hrtimer_active() and evrything is
    Reported-by: default avatarTorben Hohn <torbenh@linutronix.de>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
musb_cppi41.c 19.3 KB