• D
    pch_uart: Add eg20t_port lock field, avoid recursive spinlocks · fe89def7
    Darren Hart 提交于
    pch_uart_interrupt() takes priv->port.lock which leads to two recursive
    spinlock calls if low_latency==1 or CONFIG_PREEMPT_RT_FULL=y (one
    otherwise):
    
    pch_uart_interrupt
      spin_lock_irqsave(priv->port.lock, flags)
      case PCH_UART_IID_RDR_TO (data ready)
      handle_rx_to
        push_rx
          tty_port_tty_get
            spin_lock_irqsave(&port->lock, flags) <--- already hold this lock
            ...
          tty_flip_buffer_push
            ...
            flush_to_ldisc
              spin_lock_irqsave(&tty->buf.lock)
                spin_lock_irqsave(&tty->buf.lock)
                disc->ops->receive_buf(tty, char_buf)
                  n_tty_receive_buf
                    tty->ops->flush_chars()
                    uart_flush_chars
                      uart_start
                        spin_lock_irqsave(&port->lock) <--- already hold this lock
    
    Avoid this by using a dedicated lock to protect the eg20t_port structure
    and IO access to its membase. This is more consistent with the 8250
    driver.  Ensure priv->lock is always take prior to priv->port.lock when
    taken at the same time.
    
    V2: Remove inadvertent whitespace change.
    V3: Account for oops_in_progress for the private lock in
        pch_console_write().
    
    Note: Like the 8250 driver, if a printk is introduced anywhere inside
          the pch_console_write() critical section, the kernel will hang
          on a recursive spinlock on the private lock. The oops case is
          handled by using a trylock in the oops_in_progress case.
    Signed-off-by: NDarren Hart <dvhart@linux.intel.com>
    CC: Tomoya MORINAGA <tomoya.rohm@gmail.com>
    CC: Feng Tang <feng.tang@intel.com>
    CC: Alexander Stein <alexander.stein@systec-electronic.com>
    Acked-by: NAlan Cox <alan@linux.intel.com>
    Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    fe89def7
pch_uart.c 47.6 KB