aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/usb-serial.c
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2007-07-24 09:13:42 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-30 16:27:46 -0400
commit3ddad8232c3802f7a602d1ea24938a8067114479 (patch)
treeba648621b4c4df0846e222c6c81843bca6077b55 /drivers/usb/serial/usb-serial.c
parentf42449003114cc17cda0458c14f2deadfadf9f63 (diff)
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: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r--drivers/usb/serial/usb-serial.c17
1 files changed, 8 insertions, 9 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 5e1cf78c7786..9bf01a5efc84 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -60,19 +60,19 @@ static struct usb_driver usb_serial_driver = {
60 60
61static int debug; 61static int debug;
62static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */ 62static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
63static spinlock_t table_lock; 63static DEFINE_MUTEX(table_lock);
64static LIST_HEAD(usb_serial_driver_list); 64static LIST_HEAD(usb_serial_driver_list);
65 65
66struct usb_serial *usb_serial_get_by_index(unsigned index) 66struct usb_serial *usb_serial_get_by_index(unsigned index)
67{ 67{
68 struct usb_serial *serial; 68 struct usb_serial *serial;
69 69
70 spin_lock(&table_lock); 70 mutex_lock(&table_lock);
71 serial = serial_table[index]; 71 serial = serial_table[index];
72 72
73 if (serial) 73 if (serial)
74 kref_get(&serial->kref); 74 kref_get(&serial->kref);
75 spin_unlock(&table_lock); 75 mutex_unlock(&table_lock);
76 return serial; 76 return serial;
77} 77}
78 78
@@ -84,7 +84,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
84 dbg("%s %d", __FUNCTION__, num_ports); 84 dbg("%s %d", __FUNCTION__, num_ports);
85 85
86 *minor = 0; 86 *minor = 0;
87 spin_lock(&table_lock); 87 mutex_lock(&table_lock);
88 for (i = 0; i < SERIAL_TTY_MINORS; ++i) { 88 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
89 if (serial_table[i]) 89 if (serial_table[i])
90 continue; 90 continue;
@@ -106,10 +106,10 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
106 serial_table[i] = serial; 106 serial_table[i] = serial;
107 serial->port[j++]->number = i; 107 serial->port[j++]->number = i;
108 } 108 }
109 spin_unlock(&table_lock); 109 mutex_unlock(&table_lock);
110 return serial; 110 return serial;
111 } 111 }
112 spin_unlock(&table_lock); 112 mutex_unlock(&table_lock);
113 return NULL; 113 return NULL;
114} 114}
115 115
@@ -172,9 +172,9 @@ static void destroy_serial(struct kref *kref)
172 172
173void usb_serial_put(struct usb_serial *serial) 173void usb_serial_put(struct usb_serial *serial)
174{ 174{
175 spin_lock(&table_lock); 175 mutex_lock(&table_lock);
176 kref_put(&serial->kref, destroy_serial); 176 kref_put(&serial->kref, destroy_serial);
177 spin_unlock(&table_lock); 177 mutex_unlock(&table_lock);
178} 178}
179 179
180/***************************************************************************** 180/*****************************************************************************
@@ -1129,7 +1129,6 @@ static int __init usb_serial_init(void)
1129 return -ENOMEM; 1129 return -ENOMEM;
1130 1130
1131 /* Initialize our global data */ 1131 /* Initialize our global data */
1132 spin_lock_init(&table_lock);
1133 for (i = 0; i < SERIAL_TTY_MINORS; ++i) { 1132 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
1134 serial_table[i] = NULL; 1133 serial_table[i] = NULL;
1135 } 1134 }