(http://linux.derkeiler.com/Mailing-Lists/Kernel/2006-09/msg07416.html) (http://lkml.org/lkml/2006/10/4/399) (merged into input tree) (merged into mainline) This patch fixes the following two lockdep warnings. The first one has already been discussed at http://lkml.org/lkml/2006/7/6/191 - however the substitution mutex_lock() for mutex_lock_nested() inside the ps2_command() is not enough (which already is in mainline) - as this is purely recursive situation (the same line of code acquires the lock twice), the SINGLE_DEPTH_NESTING doesn't help (as the lock is even in such case the same class). This patch relies on existence of spin_lock_irqsave_nested(), which I provide in another patch. Signed-off-by: Jiri Kosina ============================================= [ INFO: possible recursive locking detected ] 2.6.18-rc6-mm2-dirty #4 --------------------------------------------- kseriod/140 is trying to acquire lock: (&ps2dev->cmd_mutex/1){--..}, at: [] ps2_command+0x5b/0x3a0 but task is already holding lock: (&ps2dev->cmd_mutex/1){--..}, at: [] ps2_command+0x5b/0x3a0 other info that might help us debug this: 4 locks held by kseriod/140: #0: (serio_mutex){--..}, at: [] mutex_lock+0x25/0x30 #1: (&serio->drv_mutex){--..}, at: [] mutex_lock+0x25/0x30 #2: (psmouse_mutex){--..}, at: [] mutex_lock+0x25/0x30 #3: (&ps2dev->cmd_mutex/1){--..}, at: [] ps2_command+0x5b/0x3a0 stack backtrace: [] dump_trace+0x225/0x240 [] show_trace_log_lvl+0x30/0x50 [] show_trace+0x28/0x30 [] dump_stack+0x22/0x30 [] print_deadlock_bug+0xc0/0xd0 [] check_deadlock+0x72/0x80 [] __lock_acquire+0x43d/0x990 [] lock_acquire+0x68/0x80 [] mutex_lock_nested+0x93/0x2e0 [] ps2_command+0x5b/0x3a0 [] psmouse_sliced_command+0x2d/0x90 [] synaptics_pt_write+0x2f/0x70 [] ps2_sendbyte+0x86/0x130 [] ps2_command+0xd4/0x3a0 [] psmouse_probe+0x29/0xa0 [] psmouse_connect+0x122/0x270 [] serio_connect_driver+0x2c/0x50 [] serio_driver_probe+0x24/0x30 [] really_probe+0xc9/0xf0 [] driver_probe_device+0x63/0xe0 [] __device_attach+0x18/0x20 [] bus_for_each_drv+0x57/0x80 [] device_attach+0x71/0x90 [] bus_attach_device+0x23/0x50 [] device_add+0x219/0x390 [] serio_add_port+0x51/0x100 [] serio_handle_event+0x78/0xa0 [] serio_thread+0x23/0x110 [] kthread+0xa5/0xf0 [] kernel_thread_helper+0x7/0x14 and the second one: ============================================= [ INFO: possible recursive locking detected ] 2.6.18-rc6-mm2-dirty #7 --------------------------------------------- swapper/0 is trying to acquire lock: (&serio->lock){++..}, at: [] serio_interrupt+0x20/0x60 but task is already holding lock: (&serio->lock){++..}, at: [] serio_interrupt+0x20/0x60 other info that might help us debug this: 1 lock held by swapper/0: #0: (&serio->lock){++..}, at: [] serio_interrupt+0x20/0x60 stack backtrace: [] dump_trace+0x225/0x240 [] show_trace_log_lvl+0x30/0x50 [] show_trace+0x28/0x30 [] dump_stack+0x22/0x30 [] print_deadlock_bug+0xc0/0xd0 [] check_deadlock+0x72/0x80 [] __lock_acquire+0x43d/0x990 [] lock_acquire+0x68/0x80 [] _spin_lock_irqsave+0x4d/0x70 [] serio_interrupt+0x20/0x60 [] synaptics_pass_pt_packet+0x44/0xd0 [] synaptics_process_byte+0xba/0xd0 [] psmouse_handle_byte+0x1a/0x110 [] psmouse_interrupt+0xaa/0x2e0 [] __serio_interrupt+0x3a/0x70 [] serio_interrupt+0x42/0x60 [] i8042_interrupt+0x10e/0x240 [] handle_IRQ_event+0x31/0x80 [] handle_level_irq+0x8e/0x120 [] do_IRQ+0x5a/0xb0 [] common_interrupt+0x2e/0x34 [] acpi_processor_idle+0x1e8/0x31b [] cpu_idle+0x95/0xa0 [] rest_init+0x44/0x50 [] start_kernel+0x1cd/0x220 diff -rup linux-2.6.18-rc6-mm2.orig/drivers/input/serio/libps2.c linux-2.6.18-rc6-mm2/drivers/input/serio/libps2.c --- linux-2.6.18-rc6-mm2.orig/drivers/input/serio/libps2.c 2006-09-04 04:19:48.000000000 +0200 +++ linux-2.6.18-rc6-mm2/drivers/input/serio/libps2.c 2006-09-14 16:16:06.000000000 +0200 @@ -182,7 +182,7 @@ int ps2_command(struct ps2dev *ps2dev, u return -1; } - mutex_lock_nested(&ps2dev->cmd_mutex, SINGLE_DEPTH_NESTING); + mutex_lock_nested(&ps2dev->cmd_mutex, ps2dev->serio->depth); serio_pause_rx(ps2dev->serio); ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; diff -rup linux-2.6.18-rc6-mm2.orig/drivers/input/serio/serio.c linux-2.6.18-rc6-mm2/drivers/input/serio/serio.c --- linux-2.6.18-rc6-mm2.orig/drivers/input/serio/serio.c 2006-09-04 04:19:48.000000000 +0200 +++ linux-2.6.18-rc6-mm2/drivers/input/serio/serio.c 2006-09-14 16:16:00.000000000 +0200 @@ -553,9 +553,11 @@ static void serio_add_port(struct serio if (serio->parent) { serio_pause_rx(serio->parent); serio->parent->child = serio; + serio->depth = serio->parent->depth + 1; serio_continue_rx(serio->parent); - } - + } else + serio->depth = 0; + list_add_tail(&serio->node, &serio_list); if (serio->start) serio->start(serio); @@ -916,7 +918,7 @@ irqreturn_t serio_interrupt(struct serio unsigned long flags; irqreturn_t ret = IRQ_NONE; - spin_lock_irqsave(&serio->lock, flags); + spin_lock_irqsave_nested(&serio->lock, flags, serio->depth); if (likely(serio->drv)) { ret = serio->drv->interrupt(serio, data, dfl, regs); diff -rup linux-2.6.18-rc6-mm2.orig/include/linux/serio.h linux-2.6.18-rc6-mm2/include/linux/serio.h --- linux-2.6.18-rc6-mm2.orig/include/linux/serio.h 2006-09-14 16:20:56.000000000 +0200 +++ linux-2.6.18-rc6-mm2/include/linux/serio.h 2006-09-14 15:15:41.000000000 +0200 @@ -41,6 +41,7 @@ struct serio { void (*stop)(struct serio *); struct serio *parent, *child; + unsigned int depth; /* level of nesting in parent-child hierarichy of serios */ struct serio_driver *drv; /* accessed from interrupt, must be protected by serio->lock and serio->sem */ struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */