Commit 3ddad823 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman

USB: fix BUG: sleeping function called from invalid context at...

USB: fix BUG: sleeping function called from invalid context at /home/jeremy/hg/xen/paravirt/linux/drivers/usb/core/urb.c:524, in_atomic():1, irqs_disabled():0

Clearly there's a bug in
drivers/usb/serial/usb-serial.c:usb_serial_put().  It shouldn't call
kref_put() while holding a spinlock.
Signed-off-by: default avatarOliver Neukum <oneukum@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent f4244900
...@@ -60,19 +60,19 @@ static struct usb_driver usb_serial_driver = { ...@@ -60,19 +60,19 @@ static struct usb_driver usb_serial_driver = {
static int debug; static int debug;
static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */ static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
static spinlock_t table_lock; static DEFINE_MUTEX(table_lock);
static LIST_HEAD(usb_serial_driver_list); static LIST_HEAD(usb_serial_driver_list);
struct usb_serial *usb_serial_get_by_index(unsigned index) struct usb_serial *usb_serial_get_by_index(unsigned index)
{ {
struct usb_serial *serial; struct usb_serial *serial;
spin_lock(&table_lock); mutex_lock(&table_lock);
serial = serial_table[index]; serial = serial_table[index];
if (serial) if (serial)
kref_get(&serial->kref); kref_get(&serial->kref);
spin_unlock(&table_lock); mutex_unlock(&table_lock);
return serial; return serial;
} }
...@@ -84,7 +84,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po ...@@ -84,7 +84,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
dbg("%s %d", __FUNCTION__, num_ports); dbg("%s %d", __FUNCTION__, num_ports);
*minor = 0; *minor = 0;
spin_lock(&table_lock); mutex_lock(&table_lock);
for (i = 0; i < SERIAL_TTY_MINORS; ++i) { for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
if (serial_table[i]) if (serial_table[i])
continue; continue;
...@@ -106,10 +106,10 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po ...@@ -106,10 +106,10 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
serial_table[i] = serial; serial_table[i] = serial;
serial->port[j++]->number = i; serial->port[j++]->number = i;
} }
spin_unlock(&table_lock); mutex_unlock(&table_lock);
return serial; return serial;
} }
spin_unlock(&table_lock); mutex_unlock(&table_lock);
return NULL; return NULL;
} }
...@@ -172,9 +172,9 @@ static void destroy_serial(struct kref *kref) ...@@ -172,9 +172,9 @@ static void destroy_serial(struct kref *kref)
void usb_serial_put(struct usb_serial *serial) void usb_serial_put(struct usb_serial *serial)
{ {
spin_lock(&table_lock); mutex_lock(&table_lock);
kref_put(&serial->kref, destroy_serial); kref_put(&serial->kref, destroy_serial);
spin_unlock(&table_lock); mutex_unlock(&table_lock);
} }
/***************************************************************************** /*****************************************************************************
...@@ -1129,7 +1129,6 @@ static int __init usb_serial_init(void) ...@@ -1129,7 +1129,6 @@ static int __init usb_serial_init(void)
return -ENOMEM; return -ENOMEM;
/* Initialize our global data */ /* Initialize our global data */
spin_lock_init(&table_lock);
for (i = 0; i < SERIAL_TTY_MINORS; ++i) { for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
serial_table[i] = NULL; serial_table[i] = NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment