linux/drivers/tty/tty_port.c
<<
>>
Prefs
   1/*
   2 * Tty port functions
   3 */
   4
   5#include <linux/types.h>
   6#include <linux/errno.h>
   7#include <linux/tty.h>
   8#include <linux/tty_driver.h>
   9#include <linux/tty_flip.h>
  10#include <linux/serial.h>
  11#include <linux/timer.h>
  12#include <linux/string.h>
  13#include <linux/slab.h>
  14#include <linux/sched.h>
  15#include <linux/init.h>
  16#include <linux/wait.h>
  17#include <linux/bitops.h>
  18#include <linux/delay.h>
  19#include <linux/module.h>
  20
  21void tty_port_init(struct tty_port *port)
  22{
  23        memset(port, 0, sizeof(*port));
  24        tty_buffer_init(port);
  25        init_waitqueue_head(&port->open_wait);
  26        init_waitqueue_head(&port->close_wait);
  27        init_waitqueue_head(&port->delta_msr_wait);
  28        mutex_init(&port->mutex);
  29        mutex_init(&port->buf_mutex);
  30        spin_lock_init(&port->lock);
  31        port->close_delay = (50 * HZ) / 100;
  32        port->closing_wait = (3000 * HZ) / 100;
  33        kref_init(&port->kref);
  34}
  35EXPORT_SYMBOL(tty_port_init);
  36
  37/**
  38 * tty_port_link_device - link tty and tty_port
  39 * @port: tty_port of the device
  40 * @driver: tty_driver for this device
  41 * @index: index of the tty
  42 *
  43 * Provide the tty layer wit ha link from a tty (specified by @index) to a
  44 * tty_port (@port). Use this only if neither tty_port_register_device nor
  45 * tty_port_install is used in the driver. If used, this has to be called before
  46 * tty_register_driver.
  47 */
  48void tty_port_link_device(struct tty_port *port,
  49                struct tty_driver *driver, unsigned index)
  50{
  51        if (WARN_ON(index >= driver->num))
  52                return;
  53        driver->ports[index] = port;
  54}
  55EXPORT_SYMBOL_GPL(tty_port_link_device);
  56
  57/**
  58 * tty_port_register_device - register tty device
  59 * @port: tty_port of the device
  60 * @driver: tty_driver for this device
  61 * @index: index of the tty
  62 * @device: parent if exists, otherwise NULL
  63 *
  64 * It is the same as tty_register_device except the provided @port is linked to
  65 * a concrete tty specified by @index. Use this or tty_port_install (or both).
  66 * Call tty_port_link_device as a last resort.
  67 */
  68struct device *tty_port_register_device(struct tty_port *port,
  69                struct tty_driver *driver, unsigned index,
  70                struct device *device)
  71{
  72        tty_port_link_device(port, driver, index);
  73        return tty_register_device(driver, index, device);
  74}
  75EXPORT_SYMBOL_GPL(tty_port_register_device);
  76
  77/**
  78 * tty_port_register_device_attr - register tty device
  79 * @port: tty_port of the device
  80 * @driver: tty_driver for this device
  81 * @index: index of the tty
  82 * @device: parent if exists, otherwise NULL
  83 * @drvdata: Driver data to be set to device.
  84 * @attr_grp: Attribute group to be set on device.
  85 *
  86 * It is the same as tty_register_device_attr except the provided @port is
  87 * linked to a concrete tty specified by @index. Use this or tty_port_install
  88 * (or both). Call tty_port_link_device as a last resort.
  89 */
  90struct device *tty_port_register_device_attr(struct tty_port *port,
  91                struct tty_driver *driver, unsigned index,
  92                struct device *device, void *drvdata,
  93                const struct attribute_group **attr_grp)
  94{
  95        tty_port_link_device(port, driver, index);
  96        return tty_register_device_attr(driver, index, device, drvdata,
  97                        attr_grp);
  98}
  99EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
 100
 101int tty_port_alloc_xmit_buf(struct tty_port *port)
 102{
 103        /* We may sleep in get_zeroed_page() */
 104        mutex_lock(&port->buf_mutex);
 105        if (port->xmit_buf == NULL)
 106                port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
 107        mutex_unlock(&port->buf_mutex);
 108        if (port->xmit_buf == NULL)
 109                return -ENOMEM;
 110        return 0;
 111}
 112EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
 113
 114void tty_port_free_xmit_buf(struct tty_port *port)
 115{
 116        mutex_lock(&port->buf_mutex);
 117        if (port->xmit_buf != NULL) {
 118                free_page((unsigned long)port->xmit_buf);
 119                port->xmit_buf = NULL;
 120        }
 121        mutex_unlock(&port->buf_mutex);
 122}
 123EXPORT_SYMBOL(tty_port_free_xmit_buf);
 124
 125/**
 126 * tty_port_destroy -- destroy inited port
 127 * @port: tty port to be doestroyed
 128 *
 129 * When a port was initialized using tty_port_init, one has to destroy the
 130 * port by this function. Either indirectly by using tty_port refcounting
 131 * (tty_port_put) or directly if refcounting is not used.
 132 */
 133void tty_port_destroy(struct tty_port *port)
 134{
 135        cancel_work_sync(&port->buf.work);
 136        tty_buffer_free_all(port);
 137}
 138EXPORT_SYMBOL(tty_port_destroy);
 139
 140static void tty_port_destructor(struct kref *kref)
 141{
 142        struct tty_port *port = container_of(kref, struct tty_port, kref);
 143        if (port->xmit_buf)
 144                free_page((unsigned long)port->xmit_buf);
 145        tty_port_destroy(port);
 146        if (port->ops && port->ops->destruct)
 147                port->ops->destruct(port);
 148        else
 149                kfree(port);
 150}
 151
 152void tty_port_put(struct tty_port *port)
 153{
 154        if (port)
 155                kref_put(&port->kref, tty_port_destructor);
 156}
 157EXPORT_SYMBOL(tty_port_put);
 158
 159/**
 160 *      tty_port_tty_get        -       get a tty reference
 161 *      @port: tty port
 162 *
 163 *      Return a refcount protected tty instance or NULL if the port is not
 164 *      associated with a tty (eg due to close or hangup)
 165 */
 166
 167struct tty_struct *tty_port_tty_get(struct tty_port *port)
 168{
 169        unsigned long flags;
 170        struct tty_struct *tty;
 171
 172        spin_lock_irqsave(&port->lock, flags);
 173        tty = tty_kref_get(port->tty);
 174        spin_unlock_irqrestore(&port->lock, flags);
 175        return tty;
 176}
 177EXPORT_SYMBOL(tty_port_tty_get);
 178
 179/**
 180 *      tty_port_tty_set        -       set the tty of a port
 181 *      @port: tty port
 182 *      @tty: the tty
 183 *
 184 *      Associate the port and tty pair. Manages any internal refcounts.
 185 *      Pass NULL to deassociate a port
 186 */
 187
 188void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
 189{
 190        unsigned long flags;
 191
 192        spin_lock_irqsave(&port->lock, flags);
 193        if (port->tty)
 194                tty_kref_put(port->tty);
 195        port->tty = tty_kref_get(tty);
 196        spin_unlock_irqrestore(&port->lock, flags);
 197}
 198EXPORT_SYMBOL(tty_port_tty_set);
 199
 200static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
 201{
 202        mutex_lock(&port->mutex);
 203        if (port->console)
 204                goto out;
 205
 206        if (test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) {
 207                /*
 208                 * Drop DTR/RTS if HUPCL is set. This causes any attached
 209                 * modem to hang up the line.
 210                 */
 211                if (tty && C_HUPCL(tty))
 212                        tty_port_lower_dtr_rts(port);
 213
 214                if (port->ops->shutdown)
 215                        port->ops->shutdown(port);
 216        }
 217out:
 218        mutex_unlock(&port->mutex);
 219}
 220
 221/**
 222 *      tty_port_hangup         -       hangup helper
 223 *      @port: tty port
 224 *
 225 *      Perform port level tty hangup flag and count changes. Drop the tty
 226 *      reference.
 227 */
 228
 229void tty_port_hangup(struct tty_port *port)
 230{
 231        struct tty_struct *tty;
 232        unsigned long flags;
 233
 234        spin_lock_irqsave(&port->lock, flags);
 235        port->count = 0;
 236        port->flags &= ~ASYNC_NORMAL_ACTIVE;
 237        tty = port->tty;
 238        if (tty)
 239                set_bit(TTY_IO_ERROR, &tty->flags);
 240        port->tty = NULL;
 241        spin_unlock_irqrestore(&port->lock, flags);
 242        tty_port_shutdown(port, tty);
 243        tty_kref_put(tty);
 244        wake_up_interruptible(&port->open_wait);
 245        wake_up_interruptible(&port->delta_msr_wait);
 246}
 247EXPORT_SYMBOL(tty_port_hangup);
 248
 249/**
 250 * tty_port_tty_hangup - helper to hang up a tty
 251 *
 252 * @port: tty port
 253 * @check_clocal: hang only ttys with CLOCAL unset?
 254 */
 255void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
 256{
 257        struct tty_struct *tty = tty_port_tty_get(port);
 258
 259        if (tty && (!check_clocal || !C_CLOCAL(tty)))
 260                tty_hangup(tty);
 261        tty_kref_put(tty);
 262}
 263EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
 264
 265/**
 266 * tty_port_tty_wakeup - helper to wake up a tty
 267 *
 268 * @port: tty port
 269 */
 270void tty_port_tty_wakeup(struct tty_port *port)
 271{
 272        struct tty_struct *tty = tty_port_tty_get(port);
 273
 274        if (tty) {
 275                tty_wakeup(tty);
 276                tty_kref_put(tty);
 277        }
 278}
 279EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
 280
 281/**
 282 *      tty_port_carrier_raised -       carrier raised check
 283 *      @port: tty port
 284 *
 285 *      Wrapper for the carrier detect logic. For the moment this is used
 286 *      to hide some internal details. This will eventually become entirely
 287 *      internal to the tty port.
 288 */
 289
 290int tty_port_carrier_raised(struct tty_port *port)
 291{
 292        if (port->ops->carrier_raised == NULL)
 293                return 1;
 294        return port->ops->carrier_raised(port);
 295}
 296EXPORT_SYMBOL(tty_port_carrier_raised);
 297
 298/**
 299 *      tty_port_raise_dtr_rts  -       Raise DTR/RTS
 300 *      @port: tty port
 301 *
 302 *      Wrapper for the DTR/RTS raise logic. For the moment this is used
 303 *      to hide some internal details. This will eventually become entirely
 304 *      internal to the tty port.
 305 */
 306
 307void tty_port_raise_dtr_rts(struct tty_port *port)
 308{
 309        if (port->ops->dtr_rts)
 310                port->ops->dtr_rts(port, 1);
 311}
 312EXPORT_SYMBOL(tty_port_raise_dtr_rts);
 313
 314/**
 315 *      tty_port_lower_dtr_rts  -       Lower DTR/RTS
 316 *      @port: tty port
 317 *
 318 *      Wrapper for the DTR/RTS raise logic. For the moment this is used
 319 *      to hide some internal details. This will eventually become entirely
 320 *      internal to the tty port.
 321 */
 322
 323void tty_port_lower_dtr_rts(struct tty_port *port)
 324{
 325        if (port->ops->dtr_rts)
 326                port->ops->dtr_rts(port, 0);
 327}
 328EXPORT_SYMBOL(tty_port_lower_dtr_rts);
 329
 330/**
 331 *      tty_port_block_til_ready        -       Waiting logic for tty open
 332 *      @port: the tty port being opened
 333 *      @tty: the tty device being bound
 334 *      @filp: the file pointer of the opener
 335 *
 336 *      Implement the core POSIX/SuS tty behaviour when opening a tty device.
 337 *      Handles:
 338 *              - hangup (both before and during)
 339 *              - non blocking open
 340 *              - rts/dtr/dcd
 341 *              - signals
 342 *              - port flags and counts
 343 *
 344 *      The passed tty_port must implement the carrier_raised method if it can
 345 *      do carrier detect and the dtr_rts method if it supports software
 346 *      management of these lines. Note that the dtr/rts raise is done each
 347 *      iteration as a hangup may have previously dropped them while we wait.
 348 */
 349
 350int tty_port_block_til_ready(struct tty_port *port,
 351                                struct tty_struct *tty, struct file *filp)
 352{
 353        int do_clocal = 0, retval;
 354        unsigned long flags;
 355        DEFINE_WAIT(wait);
 356
 357        /* block if port is in the process of being closed */
 358        if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
 359                wait_event_interruptible_tty(tty, port->close_wait,
 360                                !(port->flags & ASYNC_CLOSING));
 361                if (port->flags & ASYNC_HUP_NOTIFY)
 362                        return -EAGAIN;
 363                else
 364                        return -ERESTARTSYS;
 365        }
 366
 367        /* if non-blocking mode is set we can pass directly to open unless
 368           the port has just hung up or is in another error state */
 369        if (tty->flags & (1 << TTY_IO_ERROR)) {
 370                port->flags |= ASYNC_NORMAL_ACTIVE;
 371                return 0;
 372        }
 373        if (filp->f_flags & O_NONBLOCK) {
 374                /* Indicate we are open */
 375                if (tty->termios.c_cflag & CBAUD)
 376                        tty_port_raise_dtr_rts(port);
 377                port->flags |= ASYNC_NORMAL_ACTIVE;
 378                return 0;
 379        }
 380
 381        if (C_CLOCAL(tty))
 382                do_clocal = 1;
 383
 384        /* Block waiting until we can proceed. We may need to wait for the
 385           carrier, but we must also wait for any close that is in progress
 386           before the next open may complete */
 387
 388        retval = 0;
 389
 390        /* The port lock protects the port counts */
 391        spin_lock_irqsave(&port->lock, flags);
 392        if (!tty_hung_up_p(filp))
 393                port->count--;
 394        port->blocked_open++;
 395        spin_unlock_irqrestore(&port->lock, flags);
 396
 397        while (1) {
 398                /* Indicate we are open */
 399                if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
 400                        tty_port_raise_dtr_rts(port);
 401
 402                prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
 403                /* Check for a hangup or uninitialised port.
 404                                                        Return accordingly */
 405                if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
 406                        if (port->flags & ASYNC_HUP_NOTIFY)
 407                                retval = -EAGAIN;
 408                        else
 409                                retval = -ERESTARTSYS;
 410                        break;
 411                }
 412                /*
 413                 * Probe the carrier. For devices with no carrier detect
 414                 * tty_port_carrier_raised will always return true.
 415                 * Never ask drivers if CLOCAL is set, this causes troubles
 416                 * on some hardware.
 417                 */
 418                if (!(port->flags & ASYNC_CLOSING) &&
 419                                (do_clocal || tty_port_carrier_raised(port)))
 420                        break;
 421                if (signal_pending(current)) {
 422                        retval = -ERESTARTSYS;
 423                        break;
 424                }
 425                tty_unlock(tty);
 426                schedule();
 427                tty_lock(tty);
 428        }
 429        finish_wait(&port->open_wait, &wait);
 430
 431        /* Update counts. A parallel hangup will have set count to zero and
 432           we must not mess that up further */
 433        spin_lock_irqsave(&port->lock, flags);
 434        if (!tty_hung_up_p(filp))
 435                port->count++;
 436        port->blocked_open--;
 437        if (retval == 0)
 438                port->flags |= ASYNC_NORMAL_ACTIVE;
 439        spin_unlock_irqrestore(&port->lock, flags);
 440        return retval;
 441}
 442EXPORT_SYMBOL(tty_port_block_til_ready);
 443
 444static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
 445{
 446        unsigned int bps = tty_get_baud_rate(tty);
 447        long timeout;
 448
 449        if (bps > 1200) {
 450                timeout = (HZ * 10 * port->drain_delay) / bps;
 451                timeout = max_t(long, timeout, HZ / 10);
 452        } else {
 453                timeout = 2 * HZ;
 454        }
 455        schedule_timeout_interruptible(timeout);
 456}
 457
 458int tty_port_close_start(struct tty_port *port,
 459                                struct tty_struct *tty, struct file *filp)
 460{
 461        unsigned long flags;
 462
 463        spin_lock_irqsave(&port->lock, flags);
 464        if (tty_hung_up_p(filp)) {
 465                spin_unlock_irqrestore(&port->lock, flags);
 466                return 0;
 467        }
 468
 469        if (tty->count == 1 && port->count != 1) {
 470                printk(KERN_WARNING
 471                    "tty_port_close_start: tty->count = 1 port count = %d.\n",
 472                                                                port->count);
 473                port->count = 1;
 474        }
 475        if (--port->count < 0) {
 476                printk(KERN_WARNING "tty_port_close_start: count = %d\n",
 477                                                                port->count);
 478                port->count = 0;
 479        }
 480
 481        if (port->count) {
 482                spin_unlock_irqrestore(&port->lock, flags);
 483                if (port->ops->drop)
 484                        port->ops->drop(port);
 485                return 0;
 486        }
 487        set_bit(ASYNCB_CLOSING, &port->flags);
 488        tty->closing = 1;
 489        spin_unlock_irqrestore(&port->lock, flags);
 490
 491        if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
 492                /* Don't block on a stalled port, just pull the chain */
 493                if (tty->flow_stopped)
 494                        tty_driver_flush_buffer(tty);
 495                if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 496                        tty_wait_until_sent_from_close(tty, port->closing_wait);
 497                if (port->drain_delay)
 498                        tty_port_drain_delay(port, tty);
 499        }
 500        /* Flush the ldisc buffering */
 501        tty_ldisc_flush(tty);
 502
 503        /* Don't call port->drop for the last reference. Callers will want
 504           to drop the last active reference in ->shutdown() or the tty
 505           shutdown path */
 506        return 1;
 507}
 508EXPORT_SYMBOL(tty_port_close_start);
 509
 510void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
 511{
 512        unsigned long flags;
 513
 514        spin_lock_irqsave(&port->lock, flags);
 515        tty->closing = 0;
 516
 517        if (port->blocked_open) {
 518                spin_unlock_irqrestore(&port->lock, flags);
 519                if (port->close_delay) {
 520                        msleep_interruptible(
 521                                jiffies_to_msecs(port->close_delay));
 522                }
 523                spin_lock_irqsave(&port->lock, flags);
 524                wake_up_interruptible(&port->open_wait);
 525        }
 526        port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
 527        wake_up_interruptible(&port->close_wait);
 528        spin_unlock_irqrestore(&port->lock, flags);
 529}
 530EXPORT_SYMBOL(tty_port_close_end);
 531
 532void tty_port_close(struct tty_port *port, struct tty_struct *tty,
 533                                                        struct file *filp)
 534{
 535        if (tty_port_close_start(port, tty, filp) == 0)
 536                return;
 537        tty_port_shutdown(port, tty);
 538        set_bit(TTY_IO_ERROR, &tty->flags);
 539        tty_port_close_end(port, tty);
 540        tty_port_tty_set(port, NULL);
 541}
 542EXPORT_SYMBOL(tty_port_close);
 543
 544/**
 545 * tty_port_install - generic tty->ops->install handler
 546 * @port: tty_port of the device
 547 * @driver: tty_driver for this device
 548 * @tty: tty to be installed
 549 *
 550 * It is the same as tty_standard_install except the provided @port is linked
 551 * to a concrete tty specified by @tty. Use this or tty_port_register_device
 552 * (or both). Call tty_port_link_device as a last resort.
 553 */
 554int tty_port_install(struct tty_port *port, struct tty_driver *driver,
 555                struct tty_struct *tty)
 556{
 557        tty->port = port;
 558        return tty_standard_install(driver, tty);
 559}
 560EXPORT_SYMBOL_GPL(tty_port_install);
 561
 562int tty_port_open(struct tty_port *port, struct tty_struct *tty,
 563                                                        struct file *filp)
 564{
 565        spin_lock_irq(&port->lock);
 566        if (!tty_hung_up_p(filp))
 567                ++port->count;
 568        spin_unlock_irq(&port->lock);
 569        tty_port_tty_set(port, tty);
 570
 571        /*
 572         * Do the device-specific open only if the hardware isn't
 573         * already initialized. Serialize open and shutdown using the
 574         * port mutex.
 575         */
 576
 577        mutex_lock(&port->mutex);
 578
 579        if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
 580                clear_bit(TTY_IO_ERROR, &tty->flags);
 581                if (port->ops->activate) {
 582                        int retval = port->ops->activate(port, tty);
 583                        if (retval) {
 584                                mutex_unlock(&port->mutex);
 585                                return retval;
 586                        }
 587                }
 588                set_bit(ASYNCB_INITIALIZED, &port->flags);
 589        }
 590        mutex_unlock(&port->mutex);
 591        return tty_port_block_til_ready(port, tty, filp);
 592}
 593
 594EXPORT_SYMBOL(tty_port_open);
 595
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.