• Sergey Senozhatsky's avatar
    serial: 8250: change lock order in serial8250_do_startup() · 205d300a
    Sergey Senozhatsky authored
    We have a number of "uart.port->desc.lock vs desc.lock->uart.port"
    lockdep reports coming from 8250 driver; this causes a bit of trouble
    to people, so let's fix it.
    
    The problem is reverse lock order in two different call paths:
    
    chain #1:
    
     serial8250_do_startup()
      spin_lock_irqsave(&port->lock);
       disable_irq_nosync(port->irq);
        raw_spin_lock_irqsave(&desc->lock)
    
    chain #2:
    
      __report_bad_irq()
       raw_spin_lock_irqsave(&desc->lock)
        for_each_action_of_desc()
         printk()
          spin_lock_irqsave(&port->lock);
    
    Fix this by changing the order of locks in serial8250_do_startup():
     do disable_irq_nosync() first, which grabs desc->lock, and grab
     uart->port after that, so that chain #1 and chain #2 have same lock
     order.
    
    Full lockdep splat:
    
     ======================================================
     WARNING: possible circular locking dependency detected
     5.4.39 #55 Not tainted
     ======================================================
    
     swapper/0/0 is trying to acquire lock:
     ffffffffab65b6c0 (console_owner){-...}, at: console_lock_spinning_enable+0x31/0x57
    
     but task is already holding lock:
     ffff88810a8e34c0 (&irq_desc_lock_class){-.-.}, at: __report_bad_irq+0x5b/0xba
    
     which lock already depends on the new lock.
    
     the existing dependency chain (in reverse order) is:
    
     -> #2 (&irq_desc_lock_class){-.-.}:
            _raw_spin_lock_irqsave+0x61/0x8d
            __irq_get_desc_lock+0x65/0x89
            __disable_irq_nosync+0x3b/0x93
            serial8250_do_startup+0x451/0x75c
            uart_startup+0x1b4/0x2ff
            uart_port_activate+0x73/0xa0
            tty_port_open+0xae/0x10a
            uart_open+0x1b/0x26
            tty_open+0x24d/0x3a0
            chrdev_open+0xd5/0x1cc
            do_dentry_open+0x299/0x3c8
            path_openat+0x434/0x1100
            do_filp_open+0x9b/0x10a
            do_sys_open+0x15f/0x3d7
            kernel_init_freeable+0x157/0x1dd
            kernel_init+0xe/0x105
            ret_from_fork+0x27/0x50
    
     -> #1 (&port_lock_key){-.-.}:
            _raw_spin_lock_irqsave+0x61/0x8d
            serial8250_console_write+0xa7/0x2a0
            console_unlock+0x3b7/0x528
            vprintk_emit+0x111/0x17f
            printk+0x59/0x73
            register_console+0x336/0x3a4
            uart_add_one_port+0x51b/0x5be
            serial8250_register_8250_port+0x454/0x55e
            dw8250_probe+0x4dc/0x5b9
            platform_drv_probe+0x67/0x8b
            really_probe+0x14a/0x422
            driver_probe_device+0x66/0x130
            device_driver_attach+0x42/0x5b
            __driver_attach+0xca/0x139
            bus_for_each_dev+0x97/0xc9
            bus_add_driver+0x12b/0x228
            driver_register+0x64/0xed
            do_one_initcall+0x20c/0x4a6
            do_initcall_level+0xb5/0xc5
            do_basic_setup+0x4c/0x58
            kernel_init_freeable+0x13f/0x1dd
            kernel_init+0xe/0x105
            ret_from_fork+0x27/0x50
    
     -> #0 (console_owner){-...}:
            __lock_acquire+0x118d/0x2714
            lock_acquire+0x203/0x258
            console_lock_spinning_enable+0x51/0x57
            console_unlock+0x25d/0x528
            vprintk_emit+0x111/0x17f
            printk+0x59/0x73
            __report_bad_irq+0xa3/0xba
            note_interrupt+0x19a/0x1d6
            handle_irq_event_percpu+0x57/0x79
            handle_irq_event+0x36/0x55
            handle_fasteoi_irq+0xc2/0x18a
            do_IRQ+0xb3/0x157
            ret_from_intr+0x0/0x1d
            cpuidle_enter_state+0x12f/0x1fd
            cpuidle_enter+0x2e/0x3d
            do_idle+0x1ce/0x2ce
            cpu_startup_entry+0x1d/0x1f
            start_kernel+0x406/0x46a
            secondary_startup_64+0xa4/0xb0
    
     other info that might help us debug this:
    
     Chain exists of:
       console_owner --> &port_lock_key --> &irq_desc_lock_class
    
      Possible unsafe locking scenario:
    
            CPU0                    CPU1
            ----                    ----
       lock(&irq_desc_lock_class);
                                    lock(&port_lock_key);
                                    lock(&irq_desc_lock_class);
       lock(console_owner);
    
      *** DEADLOCK ***
    
     2 locks held by swapper/0/0:
      #0: ffff88810a8e34c0 (&irq_desc_lock_class){-.-.}, at: __report_bad_irq+0x5b/0xba
      #1: ffffffffab65b5c0 (console_lock){+.+.}, at: console_trylock_spinning+0x20/0x181
    
     stack backtrace:
     CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.39 #55
     Hardware name: XXXXXX
     Call Trace:
      <IRQ>
      dump_stack+0xbf/0x133
      ? print_circular_bug+0xd6/0xe9
      check_noncircular+0x1b9/0x1c3
      __lock_acquire+0x118d/0x2714
      lock_acquire+0x203/0x258
      ? console_lock_spinning_enable+0x31/0x57
      console_lock_spinning_enable+0x51/0x57
      ? console_lock_spinning_enable+0x31/0x57
      console_unlock+0x25d/0x528
      ? console_trylock+0x18/0x4e
      vprintk_emit+0x111/0x17f
      ? lock_acquire+0x203/0x258
      printk+0x59/0x73
      __report_bad_irq+0xa3/0xba
      note_interrupt+0x19a/0x1d6
      handle_irq_event_percpu+0x57/0x79
      handle_irq_event+0x36/0x55
      handle_fasteoi_irq+0xc2/0x18a
      do_IRQ+0xb3/0x157
      common_interrupt+0xf/0xf
      </IRQ>
    Signed-off-by: default avatarSergey Senozhatsky <sergey.senozhatsky@gmail.com>
    Fixes: 768aec0b ("serial: 8250: fix shared interrupts issues with SMP and RT kernels")
    Reported-by: default avatarGuenter Roeck <linux@roeck-us.net>
    Reported-by: default avatarRaul Rangel <rrangel@google.com>
    BugLink: https://bugs.chromium.org/p/chromium/issues/detail?id=1114800
    Link: https://lore.kernel.org/lkml/CAHQZ30BnfX+gxjPm1DUd5psOTqbyDh4EJE=2=VAMW_VDafctkA@mail.gmail.com/T/#uReviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
    Reviewed-by: default avatarGuenter Roeck <linux@roeck-us.net>
    Tested-by: default avatarGuenter Roeck <linux@roeck-us.net>
    Cc: stable <stable@vger.kernel.org>
    Link: https://lore.kernel.org/r/20200817022646.1484638-1-sergey.senozhatsky@gmail.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    205d300a
8250_port.c 85 KB