aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/usb-serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r--drivers/usb/serial/usb-serial.c48
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 */
44static struct usb_driver usb_serial_driver = { 45static 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
218bailout_module_put: 225bailout_module_put:
@@ -220,6 +227,7 @@ bailout_module_put:
220bailout_kref_put: 227bailout_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
265out:
266 up(&port->sem);
254} 267}
255 268
256static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) 269static 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 }