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        tty_buffer_free_all(port);
 136}
 137EXPORT_SYMBOL(tty_port_destroy);
 138
 139static void tty_port_destructor(struct kref *kref)
 140{
 141        struct tty_port *port = container_of(kref, struct tty_port, kref);
 142        if (port->xmit_buf)
 143                free_page((unsigned long)port->xmit_buf);
 144        tty_port_destroy(port);
 145        if (port->ops && port->ops->destruct)
 146                port->ops->destruct(port);
 147        else
 148                kfree(port);
 149}
 150
 151void tty_port_put(struct tty_port *port)
 152{
 153        if (port)
 154                kref_put(&port->kref, tty_port_destructor);
 155}
 156EXPORT_SYMBOL(tty_port_put);
 157
 158/**
 159 *      tty_port_tty_get        -       get a tty reference
 160 *      @port: tty port
 161 *
 162 *      Return a refcount protected tty instance or NULL if the port is not
 163 *      associated with a tty (eg due to close or hangup)
 164 */
 165
 166struct tty_struct *tty_port_tty_get(struct tty_port *port)
 167{
 168        unsigned long flags;
 169        struct tty_struct *tty;
 170
 171        spin_lock_irqsave(&port->lock, flags);
 172        tty = tty_kref_get(port->tty);
 173        spin_unlock_irqrestore(&port->lock, flags);
 174        return tty;
 175}
 176EXPORT_SYMBOL(tty_port_tty_get);
 177
 178/**
 179 *      tty_port_tty_set        -       set the tty of a port
 180 *      @port: tty port
 181 *      @tty: the tty
 182 *
 183 *      Associate the port and tty pair. Manages any internal refcounts.
 184 *      Pass NULL to deassociate a port
 185 */
 186
 187void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
 188{
 189        unsigned long flags;
 190
 191        spin_lock_irqsave(&port->lock, flags);
 192        if (port->tty)
 193                tty_kref_put(port->tty);
 194        port->tty = tty_kref_get(tty);
 195        spin_unlock_irqrestore(&port->lock, flags);
 196}
 197EXPORT_SYMBOL(tty_port_tty_set);
 198
 199static void tty_port_shutdown(struct tty_port *port)
 200{
 201        mutex_lock(&port->mutex);
 202        if (port->ops->shutdown && !port->console &&
 203                test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
 204                        port->ops->shutdown(port);
 205        mutex_unlock(&port->mutex);
 206}
 207
 208/**
 209 *      tty_port_hangup         -       hangup helper
 210 *      @port: tty port
 211 *
 212 *      Perform port level tty hangup flag and count changes. Drop the tty
 213 *      reference.
 214 */
 215
 216void tty_port_hangup(struct tty_port *port)
 217{
 218        unsigned long flags;
 219
 220        spin_lock_irqsave(&port->lock, flags);
 221        port->count = 0;
 222        port->flags &= ~ASYNC_NORMAL_ACTIVE;
 223        if (port->tty) {
 224                set_bit(TTY_IO_ERROR, &port->tty->flags);
 225                tty_kref_put(port->tty);
 226        }
 227        port->tty = NULL;
 228        spin_unlock_irqrestore(&port->lock, flags);
 229        wake_up_interruptible(&port->open_wait);
 230        wake_up_interruptible(&port->delta_msr_wait);
 231        tty_port_shutdown(port);
 232}
 233EXPORT_SYMBOL(tty_port_hangup);
 234
 235/**
 236 *      tty_port_carrier_raised -       carrier raised check
 237 *      @port: tty port
 238 *
 239 *      Wrapper for the carrier detect logic. For the moment this is used
 240 *      to hide some internal details. This will eventually become entirely
 241 *      internal to the tty port.
 242 */
 243
 244int tty_port_carrier_raised(struct tty_port *port)
 245{
 246        if (port->ops->carrier_raised == NULL)
 247                return 1;
 248        return port->ops->carrier_raised(port);
 249}
 250EXPORT_SYMBOL(tty_port_carrier_raised);
 251
 252/**
 253 *      tty_port_raise_dtr_rts  -       Raise DTR/RTS
 254 *      @port: tty port
 255 *
 256 *      Wrapper for the DTR/RTS raise logic. For the moment this is used
 257 *      to hide some internal details. This will eventually become entirely
 258 *      internal to the tty port.
 259 */
 260
 261void tty_port_raise_dtr_rts(struct tty_port *port)
 262{
 263        if (port->ops->dtr_rts)
 264                port->ops->dtr_rts(port, 1);
 265}
 266EXPORT_SYMBOL(tty_port_raise_dtr_rts);
 267
 268/**
 269 *      tty_port_lower_dtr_rts  -       Lower DTR/RTS
 270 *      @port: tty port
 271 *
 272 *      Wrapper for the DTR/RTS raise logic. For the moment this is used
 273 *      to hide some internal details. This will eventually become entirely
 274 *      internal to the tty port.
 275 */
 276
 277void tty_port_lower_dtr_rts(struct tty_port *port)
 278{
 279        if (port->ops->dtr_rts)
 280                port->ops->dtr_rts(port, 0);
 281}
 282EXPORT_SYMBOL(tty_port_lower_dtr_rts);
 283
 284/**
 285 *      tty_port_block_til_ready        -       Waiting logic for tty open
 286 *      @port: the tty port being opened
 287 *      @tty: the tty device being bound
 288 *      @filp: the file pointer of the opener
 289 *
 290 *      Implement the core POSIX/SuS tty behaviour when opening a tty device.
 291 *      Handles:
 292 *              - hangup (both before and during)
 293 *              - non blocking open
 294 *              - rts/dtr/dcd
 295 *              - signals
 296 *              - port flags and counts
 297 *
 298 *      The passed tty_port must implement the carrier_raised method if it can
 299 *      do carrier detect and the dtr_rts method if it supports software
 300 *      management of these lines. Note that the dtr/rts raise is done each
 301 *      iteration as a hangup may have previously dropped them while we wait.
 302 */
 303
 304int tty_port_block_til_ready(struct tty_port *port,
 305                                struct tty_struct *tty, struct file *filp)
 306{
 307        int do_clocal = 0, retval;
 308        unsigned long flags;
 309        DEFINE_WAIT(wait);
 310
 311        /* block if port is in the process of being closed */
 312        if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
 313                wait_event_interruptible_tty(tty, port->close_wait,
 314                                !(port->flags & ASYNC_CLOSING));
 315                if (port->flags & ASYNC_HUP_NOTIFY)
 316                        return -EAGAIN;
 317                else
 318                        return -ERESTARTSYS;
 319        }
 320
 321        /* if non-blocking mode is set we can pass directly to open unless
 322           the port has just hung up or is in another error state */
 323        if (tty->flags & (1 << TTY_IO_ERROR)) {
 324                port->flags |= ASYNC_NORMAL_ACTIVE;
 325                return 0;
 326        }
 327        if (filp->f_flags & O_NONBLOCK) {
 328                /* Indicate we are open */
 329                if (tty->termios.c_cflag & CBAUD)
 330                        tty_port_raise_dtr_rts(port);
 331                port->flags |= ASYNC_NORMAL_ACTIVE;
 332                return 0;
 333        }
 334
 335        if (C_CLOCAL(tty))
 336                do_clocal = 1;
 337
 338        /* Block waiting until we can proceed. We may need to wait for the
 339           carrier, but we must also wait for any close that is in progress
 340           before the next open may complete */
 341
 342        retval = 0;
 343
 344        /* The port lock protects the port counts */
 345        spin_lock_irqsave(&port->lock, flags);
 346        if (!tty_hung_up_p(filp))
 347                port->count--;
 348        port->blocked_open++;
 349        spin_unlock_irqrestore(&port->lock, flags);
 350
 351        while (1) {
 352                /* Indicate we are open */
 353                if (tty->termios.c_cflag & CBAUD)
 354                        tty_port_raise_dtr_rts(port);
 355
 356                prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
 357                /* Check for a hangup or uninitialised port.
 358                                                        Return accordingly */
 359                if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
 360                        if (port->flags & ASYNC_HUP_NOTIFY)
 361                                retval = -EAGAIN;
 362                        else
 363                                retval = -ERESTARTSYS;
 364                        break;
 365                }
 366                /*
 367                 * Probe the carrier. For devices with no carrier detect
 368                 * tty_port_carrier_raised will always return true.
 369                 * Never ask drivers if CLOCAL is set, this causes troubles
 370                 * on some hardware.
 371                 */
 372                if (!(port->flags & ASYNC_CLOSING) &&
 373                                (do_clocal || tty_port_carrier_raised(port)))
 374                        break;
 375                if (signal_pending(current)) {
 376                        retval = -ERESTARTSYS;
 377                        break;
 378                }
 379                tty_unlock(tty);
 380                schedule();
 381                tty_lock(tty);
 382        }
 383        finish_wait(&port->open_wait, &wait);
 384
 385        /* Update counts. A parallel hangup will have set count to zero and
 386           we must not mess that up further */
 387        spin_lock_irqsave(&port->lock, flags);
 388        if (!tty_hung_up_p(filp))
 389                port->count++;
 390        port->blocked_open--;
 391        if (retval == 0)
 392                port->flags |= ASYNC_NORMAL_ACTIVE;
 393        spin_unlock_irqrestore(&port->lock, flags);
 394        return retval;
 395}
 396EXPORT_SYMBOL(tty_port_block_til_ready);
 397
 398int tty_port_close_start(struct tty_port *port,
 399                                struct tty_struct *tty, struct file *filp)
 400{
 401        unsigned long flags;
 402
 403        spin_lock_irqsave(&port->lock, flags);
 404        if (tty_hung_up_p(filp)) {
 405                spin_unlock_irqrestore(&port->lock, flags);
 406                return 0;
 407        }
 408
 409        if (tty->count == 1 && port->count != 1) {
 410                printk(KERN_WARNING
 411                    "tty_port_close_start: tty->count = 1 port count = %d.\n",
 412                                                                port->count);
 413                port->count = 1;
 414        }
 415        if (--port->count < 0) {
 416                printk(KERN_WARNING "tty_port_close_start: count = %d\n",
 417                                                                port->count);
 418                port->count = 0;
 419        }
 420
 421        if (port->count) {
 422                spin_unlock_irqrestore(&port->lock, flags);
 423                if (port->ops->drop)
 424                        port->ops->drop(port);
 425                return 0;
 426        }
 427        set_bit(ASYNCB_CLOSING, &port->flags);
 428        tty->closing = 1;
 429        spin_unlock_irqrestore(&port->lock, flags);
 430        /* Don't block on a stalled port, just pull the chain */
 431        if (tty->flow_stopped)
 432                tty_driver_flush_buffer(tty);
 433        if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
 434                        port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 435                tty_wait_until_sent_from_close(tty, port->closing_wait);
 436        if (port->drain_delay) {
 437                unsigned int bps = tty_get_baud_rate(tty);
 438                long timeout;
 439
 440                if (bps > 1200)
 441                        timeout = max_t(long,
 442                                (HZ * 10 * port->drain_delay) / bps, HZ / 10);
 443                else
 444                        timeout = 2 * HZ;
 445                schedule_timeout_interruptible(timeout);
 446        }
 447        /* Flush the ldisc buffering */
 448        tty_ldisc_flush(tty);
 449
 450        /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
 451           hang up the line */
 452        if (tty->termios.c_cflag & HUPCL)
 453                tty_port_lower_dtr_rts(port);
 454
 455        /* Don't call port->drop for the last reference. Callers will want
 456           to drop the last active reference in ->shutdown() or the tty
 457           shutdown path */
 458        return 1;
 459}
 460EXPORT_SYMBOL(tty_port_close_start);
 461
 462void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
 463{
 464        unsigned long flags;
 465
 466        spin_lock_irqsave(&port->lock, flags);
 467        tty->closing = 0;
 468
 469        if (port->blocked_open) {
 470                spin_unlock_irqrestore(&port->lock, flags);
 471                if (port->close_delay) {
 472                        msleep_interruptible(
 473                                jiffies_to_msecs(port->close_delay));
 474                }
 475                spin_lock_irqsave(&port->lock, flags);
 476                wake_up_interruptible(&port->open_wait);
 477        }
 478        port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
 479        wake_up_interruptible(&port->close_wait);
 480        spin_unlock_irqrestore(&port->lock, flags);
 481}
 482EXPORT_SYMBOL(tty_port_close_end);
 483
 484void tty_port_close(struct tty_port *port, struct tty_struct *tty,
 485                                                        struct file *filp)
 486{
 487        if (tty_port_close_start(port, tty, filp) == 0)
 488                return;
 489        tty_port_shutdown(port);
 490        set_bit(TTY_IO_ERROR, &tty->flags);
 491        tty_port_close_end(port, tty);
 492        tty_port_tty_set(port, NULL);
 493}
 494EXPORT_SYMBOL(tty_port_close);
 495
 496/**
 497 * tty_port_install - generic tty->ops->install handler
 498 * @port: tty_port of the device
 499 * @driver: tty_driver for this device
 500 * @tty: tty to be installed
 501 *
 502 * It is the same as tty_standard_install except the provided @port is linked
 503 * to a concrete tty specified by @tty. Use this or tty_port_register_device
 504 * (or both). Call tty_port_link_device as a last resort.
 505 */
 506int tty_port_install(struct tty_port *port, struct tty_driver *driver,
 507                struct tty_struct *tty)
 508{
 509        tty->port = port;
 510        return tty_standard_install(driver, tty);
 511}
 512EXPORT_SYMBOL_GPL(tty_port_install);
 513
 514int tty_port_open(struct tty_port *port, struct tty_struct *tty,
 515                                                        struct file *filp)
 516{
 517        spin_lock_irq(&port->lock);
 518        if (!tty_hung_up_p(filp))
 519                ++port->count;
 520        spin_unlock_irq(&port->lock);
 521        tty_port_tty_set(port, tty);
 522
 523        /*
 524         * Do the device-specific open only if the hardware isn't
 525         * already initialized. Serialize open and shutdown using the
 526         * port mutex.
 527         */
 528
 529        mutex_lock(&port->mutex);
 530
 531        if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
 532                clear_bit(TTY_IO_ERROR, &tty->flags);
 533                if (port->ops->activate) {
 534                        int retval = port->ops->activate(port, tty);
 535                        if (retval) {
 536                                mutex_unlock(&port->mutex);
 537                                return retval;
 538                        }
 539                }
 540                set_bit(ASYNCB_INITIALIZED, &port->flags);
 541        }
 542        mutex_unlock(&port->mutex);
 543        return tty_port_block_til_ready(port, tty, filp);
 544}
 545
 546EXPORT_SYMBOL(tty_port_open);
 547
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.