diff options
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 105 |
1 files changed, 31 insertions, 74 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index bd3fa7ff15b1..3873660d8217 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -247,96 +247,66 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | |||
247 | return retval; | 247 | return retval; |
248 | } | 248 | } |
249 | 249 | ||
250 | static int serial_open(struct tty_struct *tty, struct file *filp) | 250 | static int serial_activate(struct tty_port *tport, struct tty_struct *tty) |
251 | { | 251 | { |
252 | struct usb_serial_port *port = tty->driver_data; | 252 | struct usb_serial_port *port = |
253 | container_of(tport, struct usb_serial_port, port); | ||
253 | struct usb_serial *serial = port->serial; | 254 | struct usb_serial *serial = port->serial; |
254 | int retval; | 255 | int retval; |
255 | 256 | ||
256 | dbg("%s - port %d", __func__, port->number); | 257 | mutex_lock(&serial->disc_mutex); |
257 | 258 | if (serial->disconnected) | |
258 | spin_lock_irq(&port->port.lock); | 259 | retval = -ENODEV; |
259 | if (!tty_hung_up_p(filp)) | 260 | else |
260 | ++port->port.count; | 261 | retval = port->serial->type->open(tty, port); |
261 | spin_unlock_irq(&port->port.lock); | 262 | mutex_unlock(&serial->disc_mutex); |
262 | tty_port_tty_set(&port->port, tty); | 263 | return retval; |
264 | } | ||
263 | 265 | ||
264 | /* Do the device-specific open only if the hardware isn't | 266 | static int serial_open(struct tty_struct *tty, struct file *filp) |
265 | * already initialized. | 267 | { |
266 | */ | 268 | struct usb_serial_port *port = tty->driver_data; |
267 | if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) { | ||
268 | if (mutex_lock_interruptible(&port->mutex)) | ||
269 | return -ERESTARTSYS; | ||
270 | mutex_lock(&serial->disc_mutex); | ||
271 | if (serial->disconnected) | ||
272 | retval = -ENODEV; | ||
273 | else | ||
274 | retval = port->serial->type->open(tty, port); | ||
275 | mutex_unlock(&serial->disc_mutex); | ||
276 | mutex_unlock(&port->mutex); | ||
277 | if (retval) | ||
278 | return retval; | ||
279 | set_bit(ASYNCB_INITIALIZED, &port->port.flags); | ||
280 | } | ||
281 | 269 | ||
282 | /* Now do the correct tty layer semantics */ | 270 | dbg("%s - port %d", __func__, port->number); |
283 | retval = tty_port_block_til_ready(&port->port, tty, filp); | 271 | return tty_port_open(&port->port, tty, filp); |
284 | return retval; | ||
285 | } | 272 | } |
286 | 273 | ||
287 | /** | 274 | /** |
288 | * serial_down - shut down hardware | 275 | * serial_down - shut down hardware |
289 | * @port: port to shut down | 276 | * @tport: tty port to shut down |
290 | * | 277 | * |
291 | * Shut down a USB serial port unless it is the console. We never | 278 | * Shut down a USB serial port unless it is the console. We never |
292 | * shut down the console hardware as it will always be in use. | 279 | * shut down the console hardware as it will always be in use. Serialized |
280 | * against activate by the tport mutex and kept to matching open/close pairs | ||
281 | * of calls by the ASYNCB_INITIALIZED flag. | ||
293 | */ | 282 | */ |
294 | static void serial_down(struct usb_serial_port *port) | 283 | static void serial_down(struct tty_port *tport) |
295 | { | 284 | { |
285 | struct usb_serial_port *port = | ||
286 | container_of(tport, struct usb_serial_port, port); | ||
296 | struct usb_serial_driver *drv = port->serial->type; | 287 | struct usb_serial_driver *drv = port->serial->type; |
297 | |||
298 | /* | 288 | /* |
299 | * The console is magical. Do not hang up the console hardware | 289 | * The console is magical. Do not hang up the console hardware |
300 | * or there will be tears. | 290 | * or there will be tears. |
301 | */ | 291 | */ |
302 | if (port->console) | 292 | if (port->console) |
303 | return; | 293 | return; |
304 | |||
305 | /* Don't call the close method if the hardware hasn't been | ||
306 | * initialized. | ||
307 | */ | ||
308 | if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags)) | ||
309 | return; | ||
310 | |||
311 | mutex_lock(&port->mutex); | ||
312 | if (drv->close) | 294 | if (drv->close) |
313 | drv->close(port); | 295 | drv->close(port); |
314 | mutex_unlock(&port->mutex); | ||
315 | } | 296 | } |
316 | 297 | ||
317 | static void serial_hangup(struct tty_struct *tty) | 298 | static void serial_hangup(struct tty_struct *tty) |
318 | { | 299 | { |
319 | struct usb_serial_port *port = tty->driver_data; | 300 | struct usb_serial_port *port = tty->driver_data; |
320 | |||
321 | dbg("%s - port %d", __func__, port->number); | 301 | dbg("%s - port %d", __func__, port->number); |
322 | |||
323 | serial_down(port); | ||
324 | tty_port_hangup(&port->port); | 302 | tty_port_hangup(&port->port); |
325 | } | 303 | } |
326 | 304 | ||
327 | static void serial_close(struct tty_struct *tty, struct file *filp) | 305 | static void serial_close(struct tty_struct *tty, struct file *filp) |
328 | { | 306 | { |
329 | struct usb_serial_port *port = tty->driver_data; | 307 | struct usb_serial_port *port = tty->driver_data; |
330 | |||
331 | dbg("%s - port %d", __func__, port->number); | 308 | dbg("%s - port %d", __func__, port->number); |
332 | 309 | tty_port_close(&port->port, tty, filp); | |
333 | if (tty_hung_up_p(filp)) | ||
334 | return; | ||
335 | if (tty_port_close_start(&port->port, tty, filp) == 0) | ||
336 | return; | ||
337 | serial_down(port); | ||
338 | tty_port_close_end(&port->port, tty); | ||
339 | tty_port_tty_set(&port->port, NULL); | ||
340 | } | 310 | } |
341 | 311 | ||
342 | /** | 312 | /** |
@@ -388,10 +358,6 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf, | |||
388 | 358 | ||
389 | dbg("%s - port %d, %d byte(s)", __func__, port->number, count); | 359 | dbg("%s - port %d, %d byte(s)", __func__, port->number, count); |
390 | 360 | ||
391 | /* count is managed under the mutex lock for the tty so cannot | ||
392 | drop to zero until after the last close completes */ | ||
393 | WARN_ON(!port->port.count); | ||
394 | |||
395 | /* pass on to the driver specific version of this function */ | 361 | /* pass on to the driver specific version of this function */ |
396 | retval = port->serial->type->write(tty, port, buf, count); | 362 | retval = port->serial->type->write(tty, port, buf, count); |
397 | 363 | ||
@@ -403,7 +369,6 @@ static int serial_write_room(struct tty_struct *tty) | |||
403 | { | 369 | { |
404 | struct usb_serial_port *port = tty->driver_data; | 370 | struct usb_serial_port *port = tty->driver_data; |
405 | dbg("%s - port %d", __func__, port->number); | 371 | dbg("%s - port %d", __func__, port->number); |
406 | WARN_ON(!port->port.count); | ||
407 | /* pass on to the driver specific version of this function */ | 372 | /* pass on to the driver specific version of this function */ |
408 | return port->serial->type->write_room(tty); | 373 | return port->serial->type->write_room(tty); |
409 | } | 374 | } |
@@ -411,7 +376,7 @@ static int serial_write_room(struct tty_struct *tty) | |||
411 | static int serial_chars_in_buffer(struct tty_struct *tty) | 376 | static int serial_chars_in_buffer(struct tty_struct *tty) |
412 | { | 377 | { |
413 | struct usb_serial_port *port = tty->driver_data; | 378 | struct usb_serial_port *port = tty->driver_data; |
414 | dbg("%s = port %d", __func__, port->number); | 379 | dbg("%s - port %d", __func__, port->number); |
415 | 380 | ||
416 | /* if the device was unplugged then any remaining characters | 381 | /* if the device was unplugged then any remaining characters |
417 | fell out of the connector ;) */ | 382 | fell out of the connector ;) */ |
@@ -426,7 +391,6 @@ static void serial_throttle(struct tty_struct *tty) | |||
426 | struct usb_serial_port *port = tty->driver_data; | 391 | struct usb_serial_port *port = tty->driver_data; |
427 | dbg("%s - port %d", __func__, port->number); | 392 | dbg("%s - port %d", __func__, port->number); |
428 | 393 | ||
429 | WARN_ON(!port->port.count); | ||
430 | /* pass on to the driver specific version of this function */ | 394 | /* pass on to the driver specific version of this function */ |
431 | if (port->serial->type->throttle) | 395 | if (port->serial->type->throttle) |
432 | port->serial->type->throttle(tty); | 396 | port->serial->type->throttle(tty); |
@@ -437,7 +401,6 @@ static void serial_unthrottle(struct tty_struct *tty) | |||
437 | struct usb_serial_port *port = tty->driver_data; | 401 | struct usb_serial_port *port = tty->driver_data; |
438 | dbg("%s - port %d", __func__, port->number); | 402 | dbg("%s - port %d", __func__, port->number); |
439 | 403 | ||
440 | WARN_ON(!port->port.count); | ||
441 | /* pass on to the driver specific version of this function */ | 404 | /* pass on to the driver specific version of this function */ |
442 | if (port->serial->type->unthrottle) | 405 | if (port->serial->type->unthrottle) |
443 | port->serial->type->unthrottle(tty); | 406 | port->serial->type->unthrottle(tty); |
@@ -451,8 +414,6 @@ static int serial_ioctl(struct tty_struct *tty, struct file *file, | |||
451 | 414 | ||
452 | dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); | 415 | dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); |
453 | 416 | ||
454 | WARN_ON(!port->port.count); | ||
455 | |||
456 | /* pass on to the driver specific version of this function | 417 | /* pass on to the driver specific version of this function |
457 | if it is available */ | 418 | if it is available */ |
458 | if (port->serial->type->ioctl) { | 419 | if (port->serial->type->ioctl) { |
@@ -467,7 +428,6 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
467 | struct usb_serial_port *port = tty->driver_data; | 428 | struct usb_serial_port *port = tty->driver_data; |
468 | dbg("%s - port %d", __func__, port->number); | 429 | dbg("%s - port %d", __func__, port->number); |
469 | 430 | ||
470 | WARN_ON(!port->port.count); | ||
471 | /* pass on to the driver specific version of this function | 431 | /* pass on to the driver specific version of this function |
472 | if it is available */ | 432 | if it is available */ |
473 | if (port->serial->type->set_termios) | 433 | if (port->serial->type->set_termios) |
@@ -482,7 +442,6 @@ static int serial_break(struct tty_struct *tty, int break_state) | |||
482 | 442 | ||
483 | dbg("%s - port %d", __func__, port->number); | 443 | dbg("%s - port %d", __func__, port->number); |
484 | 444 | ||
485 | WARN_ON(!port->port.count); | ||
486 | /* pass on to the driver specific version of this function | 445 | /* pass on to the driver specific version of this function |
487 | if it is available */ | 446 | if it is available */ |
488 | if (port->serial->type->break_ctl) | 447 | if (port->serial->type->break_ctl) |
@@ -543,7 +502,6 @@ static int serial_tiocmget(struct tty_struct *tty, struct file *file) | |||
543 | 502 | ||
544 | dbg("%s - port %d", __func__, port->number); | 503 | dbg("%s - port %d", __func__, port->number); |
545 | 504 | ||
546 | WARN_ON(!port->port.count); | ||
547 | if (port->serial->type->tiocmget) | 505 | if (port->serial->type->tiocmget) |
548 | return port->serial->type->tiocmget(tty, file); | 506 | return port->serial->type->tiocmget(tty, file); |
549 | return -EINVAL; | 507 | return -EINVAL; |
@@ -556,7 +514,6 @@ static int serial_tiocmset(struct tty_struct *tty, struct file *file, | |||
556 | 514 | ||
557 | dbg("%s - port %d", __func__, port->number); | 515 | dbg("%s - port %d", __func__, port->number); |
558 | 516 | ||
559 | WARN_ON(!port->port.count); | ||
560 | if (port->serial->type->tiocmset) | 517 | if (port->serial->type->tiocmset) |
561 | return port->serial->type->tiocmset(tty, file, set, clear); | 518 | return port->serial->type->tiocmset(tty, file, set, clear); |
562 | return -EINVAL; | 519 | return -EINVAL; |
@@ -625,8 +582,7 @@ static void port_release(struct device *dev) | |||
625 | usb_free_urb(port->write_urb); | 582 | usb_free_urb(port->write_urb); |
626 | usb_free_urb(port->interrupt_in_urb); | 583 | usb_free_urb(port->interrupt_in_urb); |
627 | usb_free_urb(port->interrupt_out_urb); | 584 | usb_free_urb(port->interrupt_out_urb); |
628 | if (!IS_ERR(port->write_fifo) && port->write_fifo) | 585 | kfifo_free(&port->write_fifo); |
629 | kfifo_free(port->write_fifo); | ||
630 | kfree(port->bulk_in_buffer); | 586 | kfree(port->bulk_in_buffer); |
631 | kfree(port->bulk_out_buffer); | 587 | kfree(port->bulk_out_buffer); |
632 | kfree(port->interrupt_in_buffer); | 588 | kfree(port->interrupt_in_buffer); |
@@ -725,6 +681,8 @@ static void serial_dtr_rts(struct tty_port *port, int on) | |||
725 | static const struct tty_port_operations serial_port_ops = { | 681 | static const struct tty_port_operations serial_port_ops = { |
726 | .carrier_raised = serial_carrier_raised, | 682 | .carrier_raised = serial_carrier_raised, |
727 | .dtr_rts = serial_dtr_rts, | 683 | .dtr_rts = serial_dtr_rts, |
684 | .activate = serial_activate, | ||
685 | .shutdown = serial_down, | ||
728 | }; | 686 | }; |
729 | 687 | ||
730 | int usb_serial_probe(struct usb_interface *interface, | 688 | int usb_serial_probe(struct usb_interface *interface, |
@@ -923,7 +881,8 @@ int usb_serial_probe(struct usb_interface *interface, | |||
923 | port->port.ops = &serial_port_ops; | 881 | port->port.ops = &serial_port_ops; |
924 | port->serial = serial; | 882 | port->serial = serial; |
925 | spin_lock_init(&port->lock); | 883 | spin_lock_init(&port->lock); |
926 | mutex_init(&port->mutex); | 884 | /* Keep this for private driver use for the moment but |
885 | should probably go away */ | ||
927 | INIT_WORK(&port->work, usb_serial_port_work); | 886 | INIT_WORK(&port->work, usb_serial_port_work); |
928 | serial->port[i] = port; | 887 | serial->port[i] = port; |
929 | port->dev.parent = &interface->dev; | 888 | port->dev.parent = &interface->dev; |
@@ -966,9 +925,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
966 | dev_err(&interface->dev, "No free urbs available\n"); | 925 | dev_err(&interface->dev, "No free urbs available\n"); |
967 | goto probe_error; | 926 | goto probe_error; |
968 | } | 927 | } |
969 | port->write_fifo = kfifo_alloc(PAGE_SIZE, GFP_KERNEL, | 928 | if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) |
970 | &port->lock); | ||
971 | if (IS_ERR(port->write_fifo)) | ||
972 | goto probe_error; | 929 | goto probe_error; |
973 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 930 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); |
974 | port->bulk_out_size = buffer_size; | 931 | port->bulk_out_size = buffer_size; |