lkml.org 
[lkml]   [2007]   [Jul]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
SubjectRe: [linux-usb-devel] 2.6.22+: 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
Date

> 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.

Yes, these functions need to sleep.
Does this work?

Regards
Oliver
---
--- a/drivers/usb/serial/usb-serial.c 2007-07-23 08:47:35.000000000 +0200
+++ b/drivers/usb/serial/usb-serial.c 2007-07-24 09:33:15.000000000 +0200
@@ -60,19 +60,19 @@ static struct usb_driver usb_serial_driv

static int debug;
static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
-static spinlock_t table_lock;
+DEFINE_MUTEX(table_lock);
static LIST_HEAD(usb_serial_driver_list);

struct usb_serial *usb_serial_get_by_index(unsigned index)
{
struct usb_serial *serial;

- spin_lock(&table_lock);
+ mutex_lock(&table_lock);
serial = serial_table[index];

if (serial)
kref_get(&serial->kref);
- spin_unlock(&table_lock);
+ mutex_unlock(&table_lock);
return serial;
}

@@ -84,7 +84,7 @@ static struct usb_serial *get_free_seria
dbg("%s %d", __FUNCTION__, num_ports);

*minor = 0;
- spin_lock(&table_lock);
+ mutex_lock(&table_lock);
for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
if (serial_table[i])
continue;
@@ -106,10 +106,10 @@ static struct usb_serial *get_free_seria
serial_table[i] = serial;
serial->port[j++]->number = i;
}
- spin_unlock(&table_lock);
+ mutex_unlock(&table_lock);
return serial;
}
- spin_unlock(&table_lock);
+ mutex_unlock(&table_lock);
return NULL;
}

@@ -172,9 +172,9 @@ static void destroy_serial(struct kref *

void usb_serial_put(struct usb_serial *serial)
{
- spin_lock(&table_lock);
+ mutex_lock(&table_lock);
kref_put(&serial->kref, destroy_serial);
- spin_unlock(&table_lock);
+ mutex_unlock(&table_lock);
}

/*****************************************************************************
@@ -1128,7 +1128,6 @@ static int __init usb_serial_init(void)
return -ENOMEM;

/* Initialize our global data */
- spin_lock_init(&table_lock);
for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
serial_table[i] = NULL;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2007-07-24 10:09    [from the cache]
©2003-2014 Jasper Spaans. Advertise on this site