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