Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+8 −9
Original line number Diff line number Diff line
@@ -60,19 +60,19 @@ static struct usb_driver usb_serial_driver = {

static int debug;
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);

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_serial (struct usb_serial *serial, int num_po
	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_serial (struct usb_serial *serial, int num_po
			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 *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);
}

/*****************************************************************************
@@ -1129,7 +1129,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;
	}