From c825bab0cef8b90bab8b63eb5686b8c8eb22e798 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Mon, 19 Mar 2012 15:20:57 +0800 Subject: usb: storage: fix lockdep warning inside usb_stor_pre_reset(v2) This patch fixes one lockdep warning[1] inside usb_stor_pre_reset. If the current configuration includes multiple mass storage interfaces, the 'AA' lockdep warning will be triggered since the lock class of 'us->dev_mutex' is acquired two times in .reset path. It isn't a real deadlock, so just take the lockdep_set_class annotation to remove the warning. [1], lockdep warning log :[ INFO: possible recursive locking detected ] :3.3.0-0.rc5.git3.1.fc17.x86_64 #1 Tainted: G W :--------------------------------------------- :usb-storage/14846 is trying to acquire lock: : (&(us->dev_mutex)){+.+.+.}, at: [] usb_stor_pre_reset+0x1c/0x20 [usb_storage] :but task is already holding lock: : (&(us->dev_mutex)){+.+.+.}, at: [] usb_stor_pre_reset+0x1c/0x20 [usb_storage] :other info that might help us debug this: : Possible unsafe locking scenario: : CPU0 : ---- : lock(&(us->dev_mutex)); : lock(&(us->dev_mutex)); : *** DEADLOCK *** : May be due to missing lock nesting notation :2 locks held by usb-storage/14846: : #0: (&__lockdep_no_validate__){......}, at: [] usb_lock_device_for_reset+0x95/0x100 : #1: (&(us->dev_mutex)){+.+.+.}, at: [] usb_stor_pre_reset+0x1c/0x20 [usb_storage] :stack backtrace: :Pid: 14846, comm: usb-storage Tainted: G W 3.3.0-0.rc5.git3.1.fc17.x86_64 #1 :Call Trace: : [] __lock_acquire+0x168f/0x1bb0 : [] ? native_sched_clock+0x13/0x80 : [] ? sched_clock+0x9/0x10 : [] ? sched_clock+0x9/0x10 : [] ? sched_clock_local+0x25/0xa0 : [] lock_acquire+0xa1/0x1e0 : [] ? usb_stor_pre_reset+0x1c/0x20 [usb_storage] : [] mutex_lock_nested+0x76/0x3a0 : [] ? usb_stor_pre_reset+0x1c/0x20 [usb_storage] : [] ? usb_stor_pre_reset+0x1c/0x20 [usb_storage] : [] usb_stor_pre_reset+0x1c/0x20 [usb_storage] : [] usb_reset_device+0x7d/0x190 : [] usb_stor_port_reset+0x7c/0x80 [usb_storage] : [] usb_stor_invoke_transport+0x94/0x560 [usb_storage] : [] ? mark_held_locks+0xb2/0x130 : [] ? _raw_spin_unlock_irq+0x30/0x50 : [] usb_stor_transparent_scsi_command+0xe/0x10 [usb_storage] : [] usb_stor_control_thread+0x173/0x280 [usb_storage] : [] ? fill_inquiry_response+0x20/0x20 [usb_storage] : [] kthread+0xb7/0xc0 : [] kernel_thread_helper+0x4/0x10 : [] ? retint_restore_args+0x13/0x13 : [] ? kthread_worker_fn+0x1a0/0x1a0 : [] ? gs_change+0x13/0x13 Reported-By: Dave Jones Signed-off-by: Ming Lei Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/usb.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index c18538e4a6db..2653e73db623 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -132,6 +132,35 @@ static struct us_unusual_dev for_dynamic_ids = #undef COMPLIANT_DEV #undef USUAL_DEV +#ifdef CONFIG_LOCKDEP + +static struct lock_class_key us_interface_key[USB_MAXINTERFACES]; + +static void us_set_lock_class(struct mutex *mutex, + struct usb_interface *intf) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_host_config *config = udev->actconfig; + int i; + + for (i = 0; i < config->desc.bNumInterfaces; i++) { + if (config->interface[i] == intf) + break; + } + + BUG_ON(i == config->desc.bNumInterfaces); + + lockdep_set_class(mutex, &us_interface_key[i]); +} + +#else + +static void us_set_lock_class(struct mutex *mutex, + struct usb_interface *intf) +{ +} + +#endif #ifdef CONFIG_PM /* Minimal support for suspend and resume */ @@ -895,6 +924,7 @@ int usb_stor_probe1(struct us_data **pus, *pus = us = host_to_us(host); memset(us, 0, sizeof(struct us_data)); mutex_init(&(us->dev_mutex)); + us_set_lock_class(&us->dev_mutex, intf); init_completion(&us->cmnd_ready); init_completion(&(us->notify)); init_waitqueue_head(&us->delay_wait); -- cgit v1.2.1