diff options
Diffstat (limited to 'drivers/tty/tty_port.c')
| -rw-r--r-- | drivers/tty/tty_port.c | 94 |
1 files changed, 88 insertions, 6 deletions
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index bf6e238146ae..d7bdd8d0c23f 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c | |||
| @@ -33,6 +33,70 @@ void tty_port_init(struct tty_port *port) | |||
| 33 | } | 33 | } |
| 34 | EXPORT_SYMBOL(tty_port_init); | 34 | EXPORT_SYMBOL(tty_port_init); |
| 35 | 35 | ||
| 36 | /** | ||
| 37 | * tty_port_link_device - link tty and tty_port | ||
| 38 | * @port: tty_port of the device | ||
| 39 | * @driver: tty_driver for this device | ||
| 40 | * @index: index of the tty | ||
| 41 | * | ||
| 42 | * Provide the tty layer wit ha link from a tty (specified by @index) to a | ||
| 43 | * tty_port (@port). Use this only if neither tty_port_register_device nor | ||
| 44 | * tty_port_install is used in the driver. If used, this has to be called before | ||
| 45 | * tty_register_driver. | ||
| 46 | */ | ||
| 47 | void tty_port_link_device(struct tty_port *port, | ||
| 48 | struct tty_driver *driver, unsigned index) | ||
| 49 | { | ||
| 50 | if (WARN_ON(index >= driver->num)) | ||
| 51 | return; | ||
| 52 | driver->ports[index] = port; | ||
| 53 | } | ||
| 54 | EXPORT_SYMBOL_GPL(tty_port_link_device); | ||
| 55 | |||
| 56 | /** | ||
| 57 | * tty_port_register_device - register tty device | ||
| 58 | * @port: tty_port of the device | ||
| 59 | * @driver: tty_driver for this device | ||
| 60 | * @index: index of the tty | ||
| 61 | * @device: parent if exists, otherwise NULL | ||
| 62 | * | ||
| 63 | * It is the same as tty_register_device except the provided @port is linked to | ||
| 64 | * a concrete tty specified by @index. Use this or tty_port_install (or both). | ||
| 65 | * Call tty_port_link_device as a last resort. | ||
| 66 | */ | ||
| 67 | struct device *tty_port_register_device(struct tty_port *port, | ||
| 68 | struct tty_driver *driver, unsigned index, | ||
| 69 | struct device *device) | ||
| 70 | { | ||
| 71 | tty_port_link_device(port, driver, index); | ||
| 72 | return tty_register_device(driver, index, device); | ||
| 73 | } | ||
| 74 | EXPORT_SYMBOL_GPL(tty_port_register_device); | ||
| 75 | |||
| 76 | /** | ||
| 77 | * tty_port_register_device_attr - register tty device | ||
| 78 | * @port: tty_port of the device | ||
| 79 | * @driver: tty_driver for this device | ||
| 80 | * @index: index of the tty | ||
| 81 | * @device: parent if exists, otherwise NULL | ||
| 82 | * @drvdata: Driver data to be set to device. | ||
| 83 | * @attr_grp: Attribute group to be set on device. | ||
| 84 | * | ||
| 85 | * It is the same as tty_register_device_attr except the provided @port is | ||
| 86 | * linked to a concrete tty specified by @index. Use this or tty_port_install | ||
| 87 | * (or both). Call tty_port_link_device as a last resort. | ||
| 88 | */ | ||
| 89 | struct device *tty_port_register_device_attr(struct tty_port *port, | ||
| 90 | struct tty_driver *driver, unsigned index, | ||
| 91 | struct device *device, void *drvdata, | ||
| 92 | const struct attribute_group **attr_grp) | ||
| 93 | { | ||
| 94 | tty_port_link_device(port, driver, index); | ||
| 95 | return tty_register_device_attr(driver, index, device, drvdata, | ||
| 96 | attr_grp); | ||
| 97 | } | ||
| 98 | EXPORT_SYMBOL_GPL(tty_port_register_device_attr); | ||
| 99 | |||
| 36 | int tty_port_alloc_xmit_buf(struct tty_port *port) | 100 | int tty_port_alloc_xmit_buf(struct tty_port *port) |
| 37 | { | 101 | { |
| 38 | /* We may sleep in get_zeroed_page() */ | 102 | /* We may sleep in get_zeroed_page() */ |
| @@ -230,7 +294,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 230 | 294 | ||
| 231 | /* block if port is in the process of being closed */ | 295 | /* block if port is in the process of being closed */ |
| 232 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { | 296 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
| 233 | wait_event_interruptible_tty(port->close_wait, | 297 | wait_event_interruptible_tty(tty, port->close_wait, |
| 234 | !(port->flags & ASYNC_CLOSING)); | 298 | !(port->flags & ASYNC_CLOSING)); |
| 235 | if (port->flags & ASYNC_HUP_NOTIFY) | 299 | if (port->flags & ASYNC_HUP_NOTIFY) |
| 236 | return -EAGAIN; | 300 | return -EAGAIN; |
| @@ -246,7 +310,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 246 | } | 310 | } |
| 247 | if (filp->f_flags & O_NONBLOCK) { | 311 | if (filp->f_flags & O_NONBLOCK) { |
| 248 | /* Indicate we are open */ | 312 | /* Indicate we are open */ |
| 249 | if (tty->termios->c_cflag & CBAUD) | 313 | if (tty->termios.c_cflag & CBAUD) |
| 250 | tty_port_raise_dtr_rts(port); | 314 | tty_port_raise_dtr_rts(port); |
| 251 | port->flags |= ASYNC_NORMAL_ACTIVE; | 315 | port->flags |= ASYNC_NORMAL_ACTIVE; |
| 252 | return 0; | 316 | return 0; |
| @@ -270,7 +334,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 270 | 334 | ||
| 271 | while (1) { | 335 | while (1) { |
| 272 | /* Indicate we are open */ | 336 | /* Indicate we are open */ |
| 273 | if (tty->termios->c_cflag & CBAUD) | 337 | if (tty->termios.c_cflag & CBAUD) |
| 274 | tty_port_raise_dtr_rts(port); | 338 | tty_port_raise_dtr_rts(port); |
| 275 | 339 | ||
| 276 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); | 340 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); |
| @@ -296,9 +360,9 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 296 | retval = -ERESTARTSYS; | 360 | retval = -ERESTARTSYS; |
| 297 | break; | 361 | break; |
| 298 | } | 362 | } |
| 299 | tty_unlock(); | 363 | tty_unlock(tty); |
| 300 | schedule(); | 364 | schedule(); |
| 301 | tty_lock(); | 365 | tty_lock(tty); |
| 302 | } | 366 | } |
| 303 | finish_wait(&port->open_wait, &wait); | 367 | finish_wait(&port->open_wait, &wait); |
| 304 | 368 | ||
| @@ -369,7 +433,7 @@ int tty_port_close_start(struct tty_port *port, | |||
| 369 | 433 | ||
| 370 | /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to | 434 | /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to |
| 371 | hang up the line */ | 435 | hang up the line */ |
| 372 | if (tty->termios->c_cflag & HUPCL) | 436 | if (tty->termios.c_cflag & HUPCL) |
| 373 | tty_port_lower_dtr_rts(port); | 437 | tty_port_lower_dtr_rts(port); |
| 374 | 438 | ||
| 375 | /* Don't call port->drop for the last reference. Callers will want | 439 | /* Don't call port->drop for the last reference. Callers will want |
| @@ -413,6 +477,24 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty, | |||
| 413 | } | 477 | } |
| 414 | EXPORT_SYMBOL(tty_port_close); | 478 | EXPORT_SYMBOL(tty_port_close); |
| 415 | 479 | ||
| 480 | /** | ||
| 481 | * tty_port_install - generic tty->ops->install handler | ||
| 482 | * @port: tty_port of the device | ||
| 483 | * @driver: tty_driver for this device | ||
| 484 | * @tty: tty to be installed | ||
| 485 | * | ||
| 486 | * It is the same as tty_standard_install except the provided @port is linked | ||
| 487 | * to a concrete tty specified by @tty. Use this or tty_port_register_device | ||
| 488 | * (or both). Call tty_port_link_device as a last resort. | ||
| 489 | */ | ||
| 490 | int tty_port_install(struct tty_port *port, struct tty_driver *driver, | ||
| 491 | struct tty_struct *tty) | ||
| 492 | { | ||
| 493 | tty->port = port; | ||
| 494 | return tty_standard_install(driver, tty); | ||
| 495 | } | ||
| 496 | EXPORT_SYMBOL_GPL(tty_port_install); | ||
| 497 | |||
| 416 | int tty_port_open(struct tty_port *port, struct tty_struct *tty, | 498 | int tty_port_open(struct tty_port *port, struct tty_struct *tty, |
| 417 | struct file *filp) | 499 | struct file *filp) |
| 418 | { | 500 | { |
