diff options
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 0c4881d18cd5..8bc8337c99c4 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/list.h> | 30 | #include <linux/list.h> |
31 | #include <linux/smp_lock.h> | 31 | #include <linux/smp_lock.h> |
32 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
33 | #include <asm/semaphore.h> | ||
33 | #include <linux/usb.h> | 34 | #include <linux/usb.h> |
34 | #include "usb-serial.h" | 35 | #include "usb-serial.h" |
35 | #include "pl2303.h" | 36 | #include "pl2303.h" |
@@ -42,10 +43,10 @@ | |||
42 | 43 | ||
43 | /* Driver structure we register with the USB core */ | 44 | /* Driver structure we register with the USB core */ |
44 | static struct usb_driver usb_serial_driver = { | 45 | static struct usb_driver usb_serial_driver = { |
45 | .owner = THIS_MODULE, | ||
46 | .name = "usbserial", | 46 | .name = "usbserial", |
47 | .probe = usb_serial_probe, | 47 | .probe = usb_serial_probe, |
48 | .disconnect = usb_serial_disconnect, | 48 | .disconnect = usb_serial_disconnect, |
49 | .no_dynamic_id = 1, | ||
49 | }; | 50 | }; |
50 | 51 | ||
51 | /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead | 52 | /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead |
@@ -188,6 +189,11 @@ static int serial_open (struct tty_struct *tty, struct file * filp) | |||
188 | 189 | ||
189 | portNumber = tty->index - serial->minor; | 190 | portNumber = tty->index - serial->minor; |
190 | port = serial->port[portNumber]; | 191 | port = serial->port[portNumber]; |
192 | if (!port) | ||
193 | return -ENODEV; | ||
194 | |||
195 | if (down_interruptible(&port->sem)) | ||
196 | return -ERESTARTSYS; | ||
191 | 197 | ||
192 | ++port->open_count; | 198 | ++port->open_count; |
193 | 199 | ||
@@ -213,6 +219,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp) | |||
213 | goto bailout_module_put; | 219 | goto bailout_module_put; |
214 | } | 220 | } |
215 | 221 | ||
222 | up(&port->sem); | ||
216 | return 0; | 223 | return 0; |
217 | 224 | ||
218 | bailout_module_put: | 225 | bailout_module_put: |
@@ -220,6 +227,7 @@ bailout_module_put: | |||
220 | bailout_kref_put: | 227 | bailout_kref_put: |
221 | kref_put(&serial->kref, destroy_serial); | 228 | kref_put(&serial->kref, destroy_serial); |
222 | port->open_count = 0; | 229 | port->open_count = 0; |
230 | up(&port->sem); | ||
223 | return retval; | 231 | return retval; |
224 | } | 232 | } |
225 | 233 | ||
@@ -232,8 +240,10 @@ static void serial_close(struct tty_struct *tty, struct file * filp) | |||
232 | 240 | ||
233 | dbg("%s - port %d", __FUNCTION__, port->number); | 241 | dbg("%s - port %d", __FUNCTION__, port->number); |
234 | 242 | ||
243 | down(&port->sem); | ||
244 | |||
235 | if (port->open_count == 0) | 245 | if (port->open_count == 0) |
236 | return; | 246 | goto out; |
237 | 247 | ||
238 | --port->open_count; | 248 | --port->open_count; |
239 | if (port->open_count == 0) { | 249 | if (port->open_count == 0) { |
@@ -251,6 +261,9 @@ static void serial_close(struct tty_struct *tty, struct file * filp) | |||
251 | } | 261 | } |
252 | 262 | ||
253 | kref_put(&port->serial->kref, destroy_serial); | 263 | kref_put(&port->serial->kref, destroy_serial); |
264 | |||
265 | out: | ||
266 | up(&port->sem); | ||
254 | } | 267 | } |
255 | 268 | ||
256 | static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) | 269 | static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) |
@@ -258,6 +271,9 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int | |||
258 | struct usb_serial_port *port = tty->driver_data; | 271 | struct usb_serial_port *port = tty->driver_data; |
259 | int retval = -EINVAL; | 272 | int retval = -EINVAL; |
260 | 273 | ||
274 | if (!port) | ||
275 | goto exit; | ||
276 | |||
261 | dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); | 277 | dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); |
262 | 278 | ||
263 | if (!port->open_count) { | 279 | if (!port->open_count) { |
@@ -277,6 +293,9 @@ static int serial_write_room (struct tty_struct *tty) | |||
277 | struct usb_serial_port *port = tty->driver_data; | 293 | struct usb_serial_port *port = tty->driver_data; |
278 | int retval = -EINVAL; | 294 | int retval = -EINVAL; |
279 | 295 | ||
296 | if (!port) | ||
297 | goto exit; | ||
298 | |||
280 | dbg("%s - port %d", __FUNCTION__, port->number); | 299 | dbg("%s - port %d", __FUNCTION__, port->number); |
281 | 300 | ||
282 | if (!port->open_count) { | 301 | if (!port->open_count) { |
@@ -296,6 +315,9 @@ static int serial_chars_in_buffer (struct tty_struct *tty) | |||
296 | struct usb_serial_port *port = tty->driver_data; | 315 | struct usb_serial_port *port = tty->driver_data; |
297 | int retval = -EINVAL; | 316 | int retval = -EINVAL; |
298 | 317 | ||
318 | if (!port) | ||
319 | goto exit; | ||
320 | |||
299 | dbg("%s = port %d", __FUNCTION__, port->number); | 321 | dbg("%s = port %d", __FUNCTION__, port->number); |
300 | 322 | ||
301 | if (!port->open_count) { | 323 | if (!port->open_count) { |
@@ -314,6 +336,9 @@ static void serial_throttle (struct tty_struct * tty) | |||
314 | { | 336 | { |
315 | struct usb_serial_port *port = tty->driver_data; | 337 | struct usb_serial_port *port = tty->driver_data; |
316 | 338 | ||
339 | if (!port) | ||
340 | return; | ||
341 | |||
317 | dbg("%s - port %d", __FUNCTION__, port->number); | 342 | dbg("%s - port %d", __FUNCTION__, port->number); |
318 | 343 | ||
319 | if (!port->open_count) { | 344 | if (!port->open_count) { |
@@ -330,6 +355,9 @@ static void serial_unthrottle (struct tty_struct * tty) | |||
330 | { | 355 | { |
331 | struct usb_serial_port *port = tty->driver_data; | 356 | struct usb_serial_port *port = tty->driver_data; |
332 | 357 | ||
358 | if (!port) | ||
359 | return; | ||
360 | |||
333 | dbg("%s - port %d", __FUNCTION__, port->number); | 361 | dbg("%s - port %d", __FUNCTION__, port->number); |
334 | 362 | ||
335 | if (!port->open_count) { | 363 | if (!port->open_count) { |
@@ -347,6 +375,9 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in | |||
347 | struct usb_serial_port *port = tty->driver_data; | 375 | struct usb_serial_port *port = tty->driver_data; |
348 | int retval = -ENODEV; | 376 | int retval = -ENODEV; |
349 | 377 | ||
378 | if (!port) | ||
379 | goto exit; | ||
380 | |||
350 | dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd); | 381 | dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd); |
351 | 382 | ||
352 | if (!port->open_count) { | 383 | if (!port->open_count) { |
@@ -368,6 +399,9 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old) | |||
368 | { | 399 | { |
369 | struct usb_serial_port *port = tty->driver_data; | 400 | struct usb_serial_port *port = tty->driver_data; |
370 | 401 | ||
402 | if (!port) | ||
403 | return; | ||
404 | |||
371 | dbg("%s - port %d", __FUNCTION__, port->number); | 405 | dbg("%s - port %d", __FUNCTION__, port->number); |
372 | 406 | ||
373 | if (!port->open_count) { | 407 | if (!port->open_count) { |
@@ -384,6 +418,9 @@ static void serial_break (struct tty_struct *tty, int break_state) | |||
384 | { | 418 | { |
385 | struct usb_serial_port *port = tty->driver_data; | 419 | struct usb_serial_port *port = tty->driver_data; |
386 | 420 | ||
421 | if (!port) | ||
422 | return; | ||
423 | |||
387 | dbg("%s - port %d", __FUNCTION__, port->number); | 424 | dbg("%s - port %d", __FUNCTION__, port->number); |
388 | 425 | ||
389 | if (!port->open_count) { | 426 | if (!port->open_count) { |
@@ -445,6 +482,9 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file) | |||
445 | { | 482 | { |
446 | struct usb_serial_port *port = tty->driver_data; | 483 | struct usb_serial_port *port = tty->driver_data; |
447 | 484 | ||
485 | if (!port) | ||
486 | goto exit; | ||
487 | |||
448 | dbg("%s - port %d", __FUNCTION__, port->number); | 488 | dbg("%s - port %d", __FUNCTION__, port->number); |
449 | 489 | ||
450 | if (!port->open_count) { | 490 | if (!port->open_count) { |
@@ -464,6 +504,9 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file, | |||
464 | { | 504 | { |
465 | struct usb_serial_port *port = tty->driver_data; | 505 | struct usb_serial_port *port = tty->driver_data; |
466 | 506 | ||
507 | if (!port) | ||
508 | goto exit; | ||
509 | |||
467 | dbg("%s - port %d", __FUNCTION__, port->number); | 510 | dbg("%s - port %d", __FUNCTION__, port->number); |
468 | 511 | ||
469 | if (!port->open_count) { | 512 | if (!port->open_count) { |
@@ -742,6 +785,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
742 | port->number = i + serial->minor; | 785 | port->number = i + serial->minor; |
743 | port->serial = serial; | 786 | port->serial = serial; |
744 | spin_lock_init(&port->lock); | 787 | spin_lock_init(&port->lock); |
788 | sema_init(&port->sem, 1); | ||
745 | INIT_WORK(&port->work, usb_serial_port_softint, port); | 789 | INIT_WORK(&port->work, usb_serial_port_softint, port); |
746 | serial->port[i] = port; | 790 | serial->port[i] = port; |
747 | } | 791 | } |