diff options
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
| -rw-r--r-- | drivers/usb/serial/usb-serial.c | 83 |
1 files changed, 28 insertions, 55 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index bd3fa7ff15b1..4543f359be75 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 | /** |
| @@ -725,6 +695,8 @@ static void serial_dtr_rts(struct tty_port *port, int on) | |||
| 725 | static const struct tty_port_operations serial_port_ops = { | 695 | static const struct tty_port_operations serial_port_ops = { |
| 726 | .carrier_raised = serial_carrier_raised, | 696 | .carrier_raised = serial_carrier_raised, |
| 727 | .dtr_rts = serial_dtr_rts, | 697 | .dtr_rts = serial_dtr_rts, |
| 698 | .activate = serial_activate, | ||
| 699 | .shutdown = serial_down, | ||
| 728 | }; | 700 | }; |
| 729 | 701 | ||
| 730 | int usb_serial_probe(struct usb_interface *interface, | 702 | int usb_serial_probe(struct usb_interface *interface, |
| @@ -923,7 +895,8 @@ int usb_serial_probe(struct usb_interface *interface, | |||
| 923 | port->port.ops = &serial_port_ops; | 895 | port->port.ops = &serial_port_ops; |
| 924 | port->serial = serial; | 896 | port->serial = serial; |
| 925 | spin_lock_init(&port->lock); | 897 | spin_lock_init(&port->lock); |
| 926 | mutex_init(&port->mutex); | 898 | /* Keep this for private driver use for the moment but |
| 899 | should probably go away */ | ||
| 927 | INIT_WORK(&port->work, usb_serial_port_work); | 900 | INIT_WORK(&port->work, usb_serial_port_work); |
| 928 | serial->port[i] = port; | 901 | serial->port[i] = port; |
| 929 | port->dev.parent = &interface->dev; | 902 | port->dev.parent = &interface->dev; |
