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        }
 263}
 264EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
 265
 266/**
 267 * tty_port_tty_wakeup - helper to wake up a tty
 268 *
 269 * @port: tty port
 270 */
 271void tty_port_tty_wakeup(struct tty_port *port)
 272{
 273        struct tty_struct *tty = tty_port_tty_get(port);
 274
 275        if (tty) {
 276                tty_wakeup(tty);
 277                tty_kref_put(tty);
 278        }
 279}
 280EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
 281
 282/**
 283 *      tty_port_carrier_raised -       carrier raised check
 284 *      @port: tty port
 285 *
 286 *      Wrapper for the carrier detect logic. For the moment this is used
 287 *      to hide some internal details. This will eventually become entirely
 288 *      internal to the tty port.
 289 */
 290
 291int tty_port_carrier_raised(struct tty_port *port)
 292{
 293        if (port->ops->carrier_raised == NULL)
 294                return 1;
 295        return port->ops->carrier_raised(port);
 296}
 297EXPORT_SYMBOL(tty_port_carrier_raised);
 298
 299/**
 300 *      tty_port_raise_dtr_rts  -       Raise DTR/RTS
 301 *      @port: tty port
 302 *
 303 *      Wrapper for the DTR/RTS raise logic. For the moment this is used
 304 *      to hide some internal details. This will eventually become entirely
 305 *      internal to the tty port.
 306 */
 307
 308void tty_port_raise_dtr_rts(struct tty_port *port)
 309{
 310        if (port->ops->dtr_rts)
 311                port->ops->dtr_rts(port, 1);
 312}
 313EXPORT_SYMBOL(tty_port_raise_dtr_rts);
 314
 315/**
 316 *      tty_port_lower_dtr_rts  -       Lower DTR/RTS
 317 *      @port: tty port
 318 *
 319 *      Wrapper for the DTR/RTS raise logic. For the moment this is used
 320 *      to hide some internal details. This will eventually become entirely
 321 *      internal to the tty port.
 322 */
 323
 324void tty_port_lower_dtr_rts(struct tty_port *port)
 325{
 326        if (port->ops->dtr_rts)
 327                port->ops->dtr_rts(port, 0);
 328}
 329EXPORT_SYMBOL(tty_port_lower_dtr_rts);
 330
 331/**
 332 *      tty_port_block_til_ready        -       Waiting logic for tty open
 333 *      @port: the tty port being opened
 334 *      @tty: the tty device being bound
 335 *      @filp: the file pointer of the opener
 336 *
 337 *      Implement the core POSIX/SuS tty behaviour when opening a tty device.
 338 *      Handles:
 339 *              - hangup (both before and during)
 340 *              - non blocking open
 341 *              - rts/dtr/dcd
 342 *              - signals
 343 *              - port flags and counts
 344 *
 345 *      The passed tty_port must implement the carrier_raised method if it can
 346 *      do carrier detect and the dtr_rts method if it supports software
 347 *      management of these lines. Note that the dtr/rts raise is done each
 348 *      iteration as a hangup may have previously dropped them while we wait.
 349 */
 350
 351int tty_port_block_til_ready(struct tty_port *port,
 352                                struct tty_struct *tty, struct file *filp)
 353{
 354        int do_clocal = 0, retval;
 355        unsigned long flags;
 356        DEFINE_WAIT(wait);
 357
 358        /* block if port is in the process of being closed */
 359        if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
 360                wait_event_interruptible_tty(tty, port->close_wait,
 361                                !(port->flags & ASYNC_CLOSING));
 362                if (port->flags & ASYNC_HUP_NOTIFY)
 363                        return -EAGAIN;
 364                else
 365                        return -ERESTARTSYS;
 366        }
 367
 368        /* if non-blocking mode is set we can pass directly to open unless
 369           the port has just hung up or is in another error state */
 370        if (tty->flags & (1 << TTY_IO_ERROR)) {
 371                port->flags |= ASYNC_NORMAL_ACTIVE;
 372                return 0;
 373        }
 374        if (filp->f_flags & O_NONBLOCK) {
 375                /* Indicate we are open */
 376                if (tty->termios.c_cflag & CBAUD)
 377                        tty_port_raise_dtr_rts(port);
 378                port->flags |= ASYNC_NORMAL_ACTIVE;
 379                return 0;
 380        }
 381
 382        if (C_CLOCAL(tty))
 383                do_clocal = 1;
 384
 385        /* Block waiting until we can proceed. We may need to wait for the
 386           carrier, but we must also wait for any close that is in progress
 387           before the next open may complete */
 388
 389        retval = 0;
 390
 391        /* The port lock protects the port counts */
 392        spin_lock_irqsave(&port->lock, flags);
 393        if (!tty_hung_up_p(filp))
 394                port->count--;
 395        port->blocked_open++;
 396        spin_unlock_irqrestore(&port->lock, flags);
 397
 398        while (1) {
 399                /* Indicate we are open */
 400                if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
 401                        tty_port_raise_dtr_rts(port);
 402
 403                prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
 404                /* Check for a hangup or uninitialised port.
 405                                                        Return accordingly */
 406                if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
 407                        if (port->flags & ASYNC_HUP_NOTIFY)
 408                                retval = -EAGAIN;
 409                        else
 410                                retval = -ERESTARTSYS;
 411                        break;
 412                }
 413                /*
 414                 * Probe the carrier. For devices with no carrier detect
 415                 * tty_port_carrier_raised will always return true.
 416                 * Never ask drivers if CLOCAL is set, this causes troubles
 417                 * on some hardware.
 418                 */
 419                if (!(port->flags & ASYNC_CLOSING) &&
 420                                (do_clocal || tty_port_carrier_raised(port)))
 421                        break;
 422                if (signal_pending(current)) {
 423                        retval = -ERESTARTSYS;
 424                        break;
 425                }
 426                tty_unlock(tty);
 427                schedule();
 428                tty_lock(tty);
 429        }
 430        finish_wait(&port->open_wait, &wait);
 431
 432        /* Update counts. A parallel hangup will have set count to zero and
 433           we must not mess that up further */
 434        spin_lock_irqsave(&port->lock, flags);
 435        if (!tty_hung_up_p(filp))
 436                port->count++;
 437        port->blocked_open--;
 438        if (retval == 0)
 439                port->flags |= ASYNC_NORMAL_ACTIVE;
 440        spin_unlock_irqrestore(&port->lock, flags);
 441        return retval;
 442}
 443EXPORT_SYMBOL(tty_port_block_til_ready);
 444
 445static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
 446{
 447        unsigned int bps = tty_get_baud_rate(tty);
 448        long timeout;
 449
 450        if (bps > 1200) {
 451                timeout = (HZ * 10 * port->drain_delay) / bps;
 452                timeout = max_t(long, timeout, HZ / 10);
 453        } else {
 454                timeout = 2 * HZ;
 455        }
 456        schedule_timeout_interruptible(timeout);
 457}
 458
 459int tty_port_close_start(struct tty_port *port,
 460                                struct tty_struct *tty, struct file *filp)
 461{
 462        unsigned long flags;
 463
 464        spin_lock_irqsave(&port->lock, flags);
 465        if (tty_hung_up_p(filp)) {
 466                spin_unlock_irqrestore(&port->lock, flags);
 467                return 0;
 468        }
 469
 470        if (tty->count == 1 && port->count != 1) {
 471                printk(KERN_WARNING
 472                    "tty_port_close_start: tty->count = 1 port count = %d.\n",
 473                                                                port->count);
 474                port->count = 1;
 475        }
 476        if (--port->count < 0) {
 477                printk(KERN_WARNING "tty_port_close_start: count = %d\n",
 478                                                                port->count);
 479                port->count = 0;
 480        }
 481
 482        if (port->count) {
 483                spin_unlock_irqrestore(&port->lock, flags);
 484                if (port->ops->drop)
 485                        port->ops->drop(port);
 486                return 0;
 487        }
 488        set_bit(ASYNCB_CLOSING, &port->flags);
 489        tty->closing = 1;
 490        spin_unlock_irqrestore(&port->lock, flags);
 491
 492        if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
 493                /* Don't block on a stalled port, just pull the chain */
 494                if (tty->flow_stopped)
 495                        tty_driver_flush_buffer(tty);
 496                if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 497                        tty_wait_until_sent_from_close(tty, port->closing_wait);
 498                if (port->drain_delay)
 499                        tty_port_drain_delay(port, tty);
 500        }
 501        /* Flush the ldisc buffering */
 502        tty_ldisc_flush(tty);
 503
 504        /* Don't call port->drop for the last reference. Callers will want
 505           to drop the last active reference in ->shutdown() or the tty
 506           shutdown path */
 507        return 1;
 508}
 509EXPORT_SYMBOL(tty_port_close_start);
 510
 511void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
 512{
 513        unsigned long flags;
 514
 515        spin_lock_irqsave(&port->lock, flags);
 516        tty->closing = 0;
 517
 518        if (port->blocked_open) {
 519                spin_unlock_irqrestore(&port->lock, flags);
 520                if (port->close_delay) {
 521                        msleep_interruptible(
 522                                jiffies_to_msecs(port->close_delay));
 523                }
 524                spin_lock_irqsave(&port->lock, flags);
 525                wake_up_interruptible(&port->open_wait);
 526        }
 527        port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
 528        wake_up_interruptible(&port->close_wait);
 529        spin_unlock_irqrestore(&port->lock, flags);
 530}
 531EXPORT_SYMBOL(tty_port_close_end);
 532
 533void tty_port_close(struct tty_port *port, struct tty_struct *tty,
 534                                                        struct file *filp)
 535{
 536        if (tty_port_close_start(port, tty, filp) == 0)
 537                return;
 538        tty_port_shutdown(port, tty);
 539        set_bit(TTY_IO_ERROR, &tty->flags);
 540        tty_port_close_end(port, tty);
 541        tty_port_tty_set(port, NULL);
 542}
 543EXPORT_SYMBOL(tty_port_close);
 544
 545/**
 546 * tty_port_install - generic tty->ops->install handler
 547 * @port: tty_port of the device
 548 * @driver: tty_driver for this device
 549 * @tty: tty to be installed
 550 *
 551 * It is the same as tty_standard_install except the provided @port is linked
 552 * to a concrete tty specified by @tty. Use this or tty_port_register_device
 553 * (or both). Call tty_port_link_device as a last resort.
 554 */
 555int tty_port_install(struct tty_port *port, struct tty_driver *driver,
 556                struct tty_struct *tty)
 557{
 558        tty->port = port;
 559        return tty_standard_install(driver, tty);
 560}
 561EXPORT_SYMBOL_GPL(tty_port_install);
 562
 563int tty_port_open(struct tty_port *port, struct tty_struct *tty,
 564                                                        struct file *filp)
 565{
 566        spin_lock_irq(&port->lock);
 567        if (!tty_hung_up_p(filp))
 568                ++port->count;
 569        spin_unlock_irq(&port->lock);
 570        tty_port_tty_set(port, tty);
 571
 572        /*
 573         * Do the device-specific open only if the hardware isn't
 574         * already initialized. Serialize open and shutdown using the
 575         * port mutex.
 576         */
 577
 578        mutex_lock(&port->mutex);
 579
 580        if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
 581                clear_bit(TTY_IO_ERROR, &tty->flags);
 582                if (port->ops->activate) {
 583                        int retval = port->ops->activate(port, tty);
 584                        if (retval) {
 585                                mutex_unlock(&port->mutex);
 586                                return retval;
 587                        }
 588                }
 589                set_bit(ASYNCB_INITIALIZED, &port->flags);
 590        }
 591        mutex_unlock(&port->mutex);
 592        return tty_port_block_til_ready(port, tty, filp);
 593}
 594
 595EXPORT_SYMBOL(tty_port_open);
 596
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.