LCOV - code coverage report
Current view: top level - drivers/tty - tty_port.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 20 234 8.5 %
Date: 2022-12-09 01:23:36 Functions: 3 30 10.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Tty port functions
       4             :  */
       5             : 
       6             : #include <linux/types.h>
       7             : #include <linux/errno.h>
       8             : #include <linux/tty.h>
       9             : #include <linux/tty_driver.h>
      10             : #include <linux/tty_flip.h>
      11             : #include <linux/serial.h>
      12             : #include <linux/timer.h>
      13             : #include <linux/string.h>
      14             : #include <linux/slab.h>
      15             : #include <linux/sched/signal.h>
      16             : #include <linux/wait.h>
      17             : #include <linux/bitops.h>
      18             : #include <linux/delay.h>
      19             : #include <linux/module.h>
      20             : #include <linux/serdev.h>
      21             : #include "tty.h"
      22             : 
      23           0 : static int tty_port_default_receive_buf(struct tty_port *port,
      24             :                                         const unsigned char *p,
      25             :                                         const unsigned char *f, size_t count)
      26             : {
      27             :         int ret;
      28             :         struct tty_struct *tty;
      29             :         struct tty_ldisc *disc;
      30             : 
      31           0 :         tty = READ_ONCE(port->itty);
      32           0 :         if (!tty)
      33             :                 return 0;
      34             : 
      35           0 :         disc = tty_ldisc_ref(tty);
      36           0 :         if (!disc)
      37             :                 return 0;
      38             : 
      39           0 :         ret = tty_ldisc_receive_buf(disc, p, (char *)f, count);
      40             : 
      41           0 :         tty_ldisc_deref(disc);
      42             : 
      43           0 :         return ret;
      44             : }
      45             : 
      46           0 : static void tty_port_default_wakeup(struct tty_port *port)
      47             : {
      48           0 :         struct tty_struct *tty = tty_port_tty_get(port);
      49             : 
      50           0 :         if (tty) {
      51           0 :                 tty_wakeup(tty);
      52           0 :                 tty_kref_put(tty);
      53             :         }
      54           0 : }
      55             : 
      56             : const struct tty_port_client_operations tty_port_default_client_ops = {
      57             :         .receive_buf = tty_port_default_receive_buf,
      58             :         .write_wakeup = tty_port_default_wakeup,
      59             : };
      60             : EXPORT_SYMBOL_GPL(tty_port_default_client_ops);
      61             : 
      62             : /**
      63             :  * tty_port_init -- initialize tty_port
      64             :  * @port: tty_port to initialize
      65             :  *
      66             :  * Initializes the state of struct tty_port. When a port was initialized using
      67             :  * this function, one has to destroy the port by tty_port_destroy(). Either
      68             :  * indirectly by using &tty_port refcounting (tty_port_put()) or directly if
      69             :  * refcounting is not used.
      70             :  */
      71          16 : void tty_port_init(struct tty_port *port)
      72             : {
      73          16 :         memset(port, 0, sizeof(*port));
      74          16 :         tty_buffer_init(port);
      75          16 :         init_waitqueue_head(&port->open_wait);
      76          16 :         init_waitqueue_head(&port->delta_msr_wait);
      77          16 :         mutex_init(&port->mutex);
      78          16 :         mutex_init(&port->buf_mutex);
      79          16 :         spin_lock_init(&port->lock);
      80          16 :         port->close_delay = (50 * HZ) / 100;
      81          16 :         port->closing_wait = (3000 * HZ) / 100;
      82          16 :         port->client_ops = &tty_port_default_client_ops;
      83          32 :         kref_init(&port->kref);
      84          16 : }
      85             : EXPORT_SYMBOL(tty_port_init);
      86             : 
      87             : /**
      88             :  * tty_port_link_device - link tty and tty_port
      89             :  * @port: tty_port of the device
      90             :  * @driver: tty_driver for this device
      91             :  * @index: index of the tty
      92             :  *
      93             :  * Provide the tty layer with a link from a tty (specified by @index) to a
      94             :  * tty_port (@port). Use this only if neither tty_port_register_device() nor
      95             :  * tty_port_install() is used in the driver. If used, this has to be called
      96             :  * before tty_register_driver().
      97             :  */
      98           1 : void tty_port_link_device(struct tty_port *port,
      99             :                 struct tty_driver *driver, unsigned index)
     100             : {
     101           1 :         if (WARN_ON(index >= driver->num))
     102             :                 return;
     103           1 :         driver->ports[index] = port;
     104             : }
     105             : EXPORT_SYMBOL_GPL(tty_port_link_device);
     106             : 
     107             : /**
     108             :  * tty_port_register_device - register tty device
     109             :  * @port: tty_port of the device
     110             :  * @driver: tty_driver for this device
     111             :  * @index: index of the tty
     112             :  * @device: parent if exists, otherwise NULL
     113             :  *
     114             :  * It is the same as tty_register_device() except the provided @port is linked
     115             :  * to a concrete tty specified by @index. Use this or tty_port_install() (or
     116             :  * both). Call tty_port_link_device() as a last resort.
     117             :  */
     118           1 : struct device *tty_port_register_device(struct tty_port *port,
     119             :                 struct tty_driver *driver, unsigned index,
     120             :                 struct device *device)
     121             : {
     122           1 :         return tty_port_register_device_attr(port, driver, index, device, NULL, NULL);
     123             : }
     124             : EXPORT_SYMBOL_GPL(tty_port_register_device);
     125             : 
     126             : /**
     127             :  * tty_port_register_device_attr - register tty device
     128             :  * @port: tty_port of the device
     129             :  * @driver: tty_driver for this device
     130             :  * @index: index of the tty
     131             :  * @device: parent if exists, otherwise NULL
     132             :  * @drvdata: Driver data to be set to device.
     133             :  * @attr_grp: Attribute group to be set on device.
     134             :  *
     135             :  * It is the same as tty_register_device_attr() except the provided @port is
     136             :  * linked to a concrete tty specified by @index. Use this or tty_port_install()
     137             :  * (or both). Call tty_port_link_device() as a last resort.
     138             :  */
     139           0 : struct device *tty_port_register_device_attr(struct tty_port *port,
     140             :                 struct tty_driver *driver, unsigned index,
     141             :                 struct device *device, void *drvdata,
     142             :                 const struct attribute_group **attr_grp)
     143             : {
     144           1 :         tty_port_link_device(port, driver, index);
     145           1 :         return tty_register_device_attr(driver, index, device, drvdata,
     146             :                         attr_grp);
     147             : }
     148             : EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
     149             : 
     150             : /**
     151             :  * tty_port_register_device_attr_serdev - register tty or serdev device
     152             :  * @port: tty_port of the device
     153             :  * @driver: tty_driver for this device
     154             :  * @index: index of the tty
     155             :  * @device: parent if exists, otherwise NULL
     156             :  * @drvdata: driver data for the device
     157             :  * @attr_grp: attribute group for the device
     158             :  *
     159             :  * Register a serdev or tty device depending on if the parent device has any
     160             :  * defined serdev clients or not.
     161             :  */
     162           0 : struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
     163             :                 struct tty_driver *driver, unsigned index,
     164             :                 struct device *device, void *drvdata,
     165             :                 const struct attribute_group **attr_grp)
     166             : {
     167             :         struct device *dev;
     168             : 
     169           0 :         tty_port_link_device(port, driver, index);
     170             : 
     171           0 :         dev = serdev_tty_port_register(port, device, driver, index);
     172           0 :         if (PTR_ERR(dev) != -ENODEV) {
     173             :                 /* Skip creating cdev if we registered a serdev device */
     174             :                 return dev;
     175             :         }
     176             : 
     177           0 :         return tty_register_device_attr(driver, index, device, drvdata,
     178             :                         attr_grp);
     179             : }
     180             : EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev);
     181             : 
     182             : /**
     183             :  * tty_port_register_device_serdev - register tty or serdev device
     184             :  * @port: tty_port of the device
     185             :  * @driver: tty_driver for this device
     186             :  * @index: index of the tty
     187             :  * @device: parent if exists, otherwise NULL
     188             :  *
     189             :  * Register a serdev or tty device depending on if the parent device has any
     190             :  * defined serdev clients or not.
     191             :  */
     192           0 : struct device *tty_port_register_device_serdev(struct tty_port *port,
     193             :                 struct tty_driver *driver, unsigned index,
     194             :                 struct device *device)
     195             : {
     196           0 :         return tty_port_register_device_attr_serdev(port, driver, index,
     197             :                         device, NULL, NULL);
     198             : }
     199             : EXPORT_SYMBOL_GPL(tty_port_register_device_serdev);
     200             : 
     201             : /**
     202             :  * tty_port_unregister_device - deregister a tty or serdev device
     203             :  * @port: tty_port of the device
     204             :  * @driver: tty_driver for this device
     205             :  * @index: index of the tty
     206             :  *
     207             :  * If a tty or serdev device is registered with a call to
     208             :  * tty_port_register_device_serdev() then this function must be called when
     209             :  * the device is gone.
     210             :  */
     211           0 : void tty_port_unregister_device(struct tty_port *port,
     212             :                 struct tty_driver *driver, unsigned index)
     213             : {
     214             :         int ret;
     215             : 
     216           0 :         ret = serdev_tty_port_unregister(port);
     217             :         if (ret == 0)
     218             :                 return;
     219             : 
     220           0 :         tty_unregister_device(driver, index);
     221             : }
     222             : EXPORT_SYMBOL_GPL(tty_port_unregister_device);
     223             : 
     224           0 : int tty_port_alloc_xmit_buf(struct tty_port *port)
     225             : {
     226             :         /* We may sleep in get_zeroed_page() */
     227           0 :         mutex_lock(&port->buf_mutex);
     228           0 :         if (port->xmit_buf == NULL) {
     229           0 :                 port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
     230           0 :                 if (port->xmit_buf)
     231           0 :                         kfifo_init(&port->xmit_fifo, port->xmit_buf, PAGE_SIZE);
     232             :         }
     233           0 :         mutex_unlock(&port->buf_mutex);
     234           0 :         if (port->xmit_buf == NULL)
     235             :                 return -ENOMEM;
     236           0 :         return 0;
     237             : }
     238             : EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
     239             : 
     240           0 : void tty_port_free_xmit_buf(struct tty_port *port)
     241             : {
     242           0 :         mutex_lock(&port->buf_mutex);
     243           0 :         free_page((unsigned long)port->xmit_buf);
     244           0 :         port->xmit_buf = NULL;
     245           0 :         INIT_KFIFO(port->xmit_fifo);
     246           0 :         mutex_unlock(&port->buf_mutex);
     247           0 : }
     248             : EXPORT_SYMBOL(tty_port_free_xmit_buf);
     249             : 
     250             : /**
     251             :  * tty_port_destroy -- destroy inited port
     252             :  * @port: tty port to be destroyed
     253             :  *
     254             :  * When a port was initialized using tty_port_init(), one has to destroy the
     255             :  * port by this function. Either indirectly by using &tty_port refcounting
     256             :  * (tty_port_put()) or directly if refcounting is not used.
     257             :  */
     258           0 : void tty_port_destroy(struct tty_port *port)
     259             : {
     260           0 :         tty_buffer_cancel_work(port);
     261           0 :         tty_buffer_free_all(port);
     262           0 : }
     263             : EXPORT_SYMBOL(tty_port_destroy);
     264             : 
     265           0 : static void tty_port_destructor(struct kref *kref)
     266             : {
     267           0 :         struct tty_port *port = container_of(kref, struct tty_port, kref);
     268             : 
     269             :         /* check if last port ref was dropped before tty release */
     270           0 :         if (WARN_ON(port->itty))
     271             :                 return;
     272           0 :         free_page((unsigned long)port->xmit_buf);
     273           0 :         tty_port_destroy(port);
     274           0 :         if (port->ops && port->ops->destruct)
     275           0 :                 port->ops->destruct(port);
     276             :         else
     277           0 :                 kfree(port);
     278             : }
     279             : 
     280             : /**
     281             :  * tty_port_put -- drop a reference to tty_port
     282             :  * @port: port to drop a reference of (can be NULL)
     283             :  *
     284             :  * The final put will destroy and free up the @port using
     285             :  * @port->ops->destruct() hook, or using kfree() if not provided.
     286             :  */
     287           0 : void tty_port_put(struct tty_port *port)
     288             : {
     289           0 :         if (port)
     290           0 :                 kref_put(&port->kref, tty_port_destructor);
     291           0 : }
     292             : EXPORT_SYMBOL(tty_port_put);
     293             : 
     294             : /**
     295             :  * tty_port_tty_get     -       get a tty reference
     296             :  * @port: tty port
     297             :  *
     298             :  * Return a refcount protected tty instance or %NULL if the port is not
     299             :  * associated with a tty (eg due to close or hangup).
     300             :  */
     301           0 : struct tty_struct *tty_port_tty_get(struct tty_port *port)
     302             : {
     303             :         unsigned long flags;
     304             :         struct tty_struct *tty;
     305             : 
     306           0 :         spin_lock_irqsave(&port->lock, flags);
     307           0 :         tty = tty_kref_get(port->tty);
     308           0 :         spin_unlock_irqrestore(&port->lock, flags);
     309           0 :         return tty;
     310             : }
     311             : EXPORT_SYMBOL(tty_port_tty_get);
     312             : 
     313             : /**
     314             :  * tty_port_tty_set     -       set the tty of a port
     315             :  * @port: tty port
     316             :  * @tty: the tty
     317             :  *
     318             :  * Associate the port and tty pair. Manages any internal refcounts. Pass %NULL
     319             :  * to deassociate a port.
     320             :  */
     321           0 : void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
     322             : {
     323             :         unsigned long flags;
     324             : 
     325           0 :         spin_lock_irqsave(&port->lock, flags);
     326           0 :         tty_kref_put(port->tty);
     327           0 :         port->tty = tty_kref_get(tty);
     328           0 :         spin_unlock_irqrestore(&port->lock, flags);
     329           0 : }
     330             : EXPORT_SYMBOL(tty_port_tty_set);
     331             : 
     332             : /**
     333             :  * tty_port_shutdown - internal helper to shutdown the device
     334             :  * @port: tty port to be shut down
     335             :  * @tty: the associated tty
     336             :  *
     337             :  * It is used by tty_port_hangup() and tty_port_close(). Its task is to
     338             :  * shutdown the device if it was initialized (note consoles remain
     339             :  * functioning). It lowers DTR/RTS (if @tty has HUPCL set) and invokes
     340             :  * @port->ops->shutdown().
     341             :  */
     342           0 : static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
     343             : {
     344           0 :         mutex_lock(&port->mutex);
     345           0 :         if (port->console)
     346             :                 goto out;
     347             : 
     348           0 :         if (tty_port_initialized(port)) {
     349           0 :                 tty_port_set_initialized(port, 0);
     350             :                 /*
     351             :                  * Drop DTR/RTS if HUPCL is set. This causes any attached
     352             :                  * modem to hang up the line.
     353             :                  */
     354           0 :                 if (tty && C_HUPCL(tty))
     355             :                         tty_port_lower_dtr_rts(port);
     356             : 
     357           0 :                 if (port->ops->shutdown)
     358           0 :                         port->ops->shutdown(port);
     359             :         }
     360             : out:
     361           0 :         mutex_unlock(&port->mutex);
     362           0 : }
     363             : 
     364             : /**
     365             :  * tty_port_hangup              -       hangup helper
     366             :  * @port: tty port
     367             :  *
     368             :  * Perform port level tty hangup flag and count changes. Drop the tty
     369             :  * reference.
     370             :  *
     371             :  * Caller holds tty lock.
     372             :  */
     373           0 : void tty_port_hangup(struct tty_port *port)
     374             : {
     375             :         struct tty_struct *tty;
     376             :         unsigned long flags;
     377             : 
     378           0 :         spin_lock_irqsave(&port->lock, flags);
     379           0 :         port->count = 0;
     380           0 :         tty = port->tty;
     381           0 :         if (tty)
     382           0 :                 set_bit(TTY_IO_ERROR, &tty->flags);
     383           0 :         port->tty = NULL;
     384           0 :         spin_unlock_irqrestore(&port->lock, flags);
     385           0 :         tty_port_set_active(port, 0);
     386           0 :         tty_port_shutdown(port, tty);
     387           0 :         tty_kref_put(tty);
     388           0 :         wake_up_interruptible(&port->open_wait);
     389           0 :         wake_up_interruptible(&port->delta_msr_wait);
     390           0 : }
     391             : EXPORT_SYMBOL(tty_port_hangup);
     392             : 
     393             : /**
     394             :  * tty_port_tty_hangup - helper to hang up a tty
     395             :  * @port: tty port
     396             :  * @check_clocal: hang only ttys with %CLOCAL unset?
     397             :  */
     398           0 : void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
     399             : {
     400           0 :         struct tty_struct *tty = tty_port_tty_get(port);
     401             : 
     402           0 :         if (tty && (!check_clocal || !C_CLOCAL(tty)))
     403           0 :                 tty_hangup(tty);
     404           0 :         tty_kref_put(tty);
     405           0 : }
     406             : EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
     407             : 
     408             : /**
     409             :  * tty_port_tty_wakeup - helper to wake up a tty
     410             :  * @port: tty port
     411             :  */
     412           0 : void tty_port_tty_wakeup(struct tty_port *port)
     413             : {
     414           0 :         port->client_ops->write_wakeup(port);
     415           0 : }
     416             : EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
     417             : 
     418             : /**
     419             :  * tty_port_carrier_raised      -       carrier raised check
     420             :  * @port: tty port
     421             :  *
     422             :  * Wrapper for the carrier detect logic. For the moment this is used
     423             :  * to hide some internal details. This will eventually become entirely
     424             :  * internal to the tty port.
     425             :  */
     426           0 : int tty_port_carrier_raised(struct tty_port *port)
     427             : {
     428           0 :         if (port->ops->carrier_raised == NULL)
     429             :                 return 1;
     430           0 :         return port->ops->carrier_raised(port);
     431             : }
     432             : EXPORT_SYMBOL(tty_port_carrier_raised);
     433             : 
     434             : /**
     435             :  * tty_port_raise_dtr_rts       -       Raise DTR/RTS
     436             :  * @port: tty port
     437             :  *
     438             :  * Wrapper for the DTR/RTS raise logic. For the moment this is used to hide
     439             :  * some internal details. This will eventually become entirely internal to the
     440             :  * tty port.
     441             :  */
     442           0 : void tty_port_raise_dtr_rts(struct tty_port *port)
     443             : {
     444           0 :         if (port->ops->dtr_rts)
     445           0 :                 port->ops->dtr_rts(port, 1);
     446           0 : }
     447             : EXPORT_SYMBOL(tty_port_raise_dtr_rts);
     448             : 
     449             : /**
     450             :  * tty_port_lower_dtr_rts       -       Lower DTR/RTS
     451             :  * @port: tty port
     452             :  *
     453             :  * Wrapper for the DTR/RTS raise logic. For the moment this is used to hide
     454             :  * some internal details. This will eventually become entirely internal to the
     455             :  * tty port.
     456             :  */
     457           0 : void tty_port_lower_dtr_rts(struct tty_port *port)
     458             : {
     459           0 :         if (port->ops->dtr_rts)
     460           0 :                 port->ops->dtr_rts(port, 0);
     461           0 : }
     462             : EXPORT_SYMBOL(tty_port_lower_dtr_rts);
     463             : 
     464             : /**
     465             :  * tty_port_block_til_ready     -       Waiting logic for tty open
     466             :  * @port: the tty port being opened
     467             :  * @tty: the tty device being bound
     468             :  * @filp: the file pointer of the opener or %NULL
     469             :  *
     470             :  * Implement the core POSIX/SuS tty behaviour when opening a tty device.
     471             :  * Handles:
     472             :  *
     473             :  *      - hangup (both before and during)
     474             :  *      - non blocking open
     475             :  *      - rts/dtr/dcd
     476             :  *      - signals
     477             :  *      - port flags and counts
     478             :  *
     479             :  * The passed @port must implement the @port->ops->carrier_raised method if it
     480             :  * can do carrier detect and the @port->ops->dtr_rts method if it supports
     481             :  * software management of these lines. Note that the dtr/rts raise is done each
     482             :  * iteration as a hangup may have previously dropped them while we wait.
     483             :  *
     484             :  * Caller holds tty lock.
     485             :  *
     486             :  * Note: May drop and reacquire tty lock when blocking, so @tty and @port may
     487             :  * have changed state (eg., may have been hung up).
     488             :  */
     489           0 : int tty_port_block_til_ready(struct tty_port *port,
     490             :                                 struct tty_struct *tty, struct file *filp)
     491             : {
     492           0 :         int do_clocal = 0, retval;
     493             :         unsigned long flags;
     494           0 :         DEFINE_WAIT(wait);
     495             : 
     496             :         /* if non-blocking mode is set we can pass directly to open unless
     497             :          * the port has just hung up or is in another error state.
     498             :          */
     499           0 :         if (tty_io_error(tty)) {
     500           0 :                 tty_port_set_active(port, 1);
     501           0 :                 return 0;
     502             :         }
     503           0 :         if (filp == NULL || (filp->f_flags & O_NONBLOCK)) {
     504             :                 /* Indicate we are open */
     505           0 :                 if (C_BAUD(tty))
     506             :                         tty_port_raise_dtr_rts(port);
     507           0 :                 tty_port_set_active(port, 1);
     508           0 :                 return 0;
     509             :         }
     510             : 
     511           0 :         if (C_CLOCAL(tty))
     512           0 :                 do_clocal = 1;
     513             : 
     514             :         /* Block waiting until we can proceed. We may need to wait for the
     515             :          * carrier, but we must also wait for any close that is in progress
     516             :          * before the next open may complete.
     517             :          */
     518             : 
     519           0 :         retval = 0;
     520             : 
     521             :         /* The port lock protects the port counts */
     522           0 :         spin_lock_irqsave(&port->lock, flags);
     523           0 :         port->count--;
     524           0 :         port->blocked_open++;
     525           0 :         spin_unlock_irqrestore(&port->lock, flags);
     526             : 
     527             :         while (1) {
     528             :                 /* Indicate we are open */
     529           0 :                 if (C_BAUD(tty) && tty_port_initialized(port))
     530             :                         tty_port_raise_dtr_rts(port);
     531             : 
     532           0 :                 prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
     533             :                 /* Check for a hangup or uninitialised port.
     534             :                  * Return accordingly.
     535             :                  */
     536           0 :                 if (tty_hung_up_p(filp) || !tty_port_initialized(port)) {
     537           0 :                         if (port->flags & ASYNC_HUP_NOTIFY)
     538             :                                 retval = -EAGAIN;
     539             :                         else
     540           0 :                                 retval = -ERESTARTSYS;
     541             :                         break;
     542             :                 }
     543             :                 /*
     544             :                  * Probe the carrier. For devices with no carrier detect
     545             :                  * tty_port_carrier_raised will always return true.
     546             :                  * Never ask drivers if CLOCAL is set, this causes troubles
     547             :                  * on some hardware.
     548             :                  */
     549           0 :                 if (do_clocal || tty_port_carrier_raised(port))
     550             :                         break;
     551           0 :                 if (signal_pending(current)) {
     552             :                         retval = -ERESTARTSYS;
     553             :                         break;
     554             :                 }
     555           0 :                 tty_unlock(tty);
     556           0 :                 schedule();
     557           0 :                 tty_lock(tty);
     558             :         }
     559           0 :         finish_wait(&port->open_wait, &wait);
     560             : 
     561             :         /* Update counts. A parallel hangup will have set count to zero and
     562             :          * we must not mess that up further.
     563             :          */
     564           0 :         spin_lock_irqsave(&port->lock, flags);
     565           0 :         if (!tty_hung_up_p(filp))
     566           0 :                 port->count++;
     567           0 :         port->blocked_open--;
     568           0 :         spin_unlock_irqrestore(&port->lock, flags);
     569           0 :         if (retval == 0)
     570             :                 tty_port_set_active(port, 1);
     571             :         return retval;
     572             : }
     573             : EXPORT_SYMBOL(tty_port_block_til_ready);
     574             : 
     575           0 : static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
     576             : {
     577           0 :         unsigned int bps = tty_get_baud_rate(tty);
     578             :         long timeout;
     579             : 
     580           0 :         if (bps > 1200) {
     581           0 :                 timeout = (HZ * 10 * port->drain_delay) / bps;
     582           0 :                 timeout = max_t(long, timeout, HZ / 10);
     583             :         } else {
     584             :                 timeout = 2 * HZ;
     585             :         }
     586           0 :         schedule_timeout_interruptible(timeout);
     587           0 : }
     588             : 
     589             : /**
     590             :  * tty_port_close_start - helper for tty->ops->close, part 1/2
     591             :  * @port: tty_port of the device
     592             :  * @tty: tty being closed
     593             :  * @filp: passed file pointer
     594             :  *
     595             :  * Decrements and checks open count. Flushes the port if this is the last
     596             :  * close. That means, dropping the data from the outpu buffer on the device and
     597             :  * waiting for sending logic to finish. The rest of close handling is performed
     598             :  * in tty_port_close_end().
     599             :  *
     600             :  * Locking: Caller holds tty lock.
     601             :  *
     602             :  * Return: 1 if this is the last close, otherwise 0
     603             :  */
     604           0 : int tty_port_close_start(struct tty_port *port,
     605             :                                 struct tty_struct *tty, struct file *filp)
     606             : {
     607             :         unsigned long flags;
     608             : 
     609           0 :         if (tty_hung_up_p(filp))
     610             :                 return 0;
     611             : 
     612           0 :         spin_lock_irqsave(&port->lock, flags);
     613           0 :         if (tty->count == 1 && port->count != 1) {
     614           0 :                 tty_warn(tty, "%s: tty->count = 1 port count = %d\n", __func__,
     615             :                          port->count);
     616           0 :                 port->count = 1;
     617             :         }
     618           0 :         if (--port->count < 0) {
     619           0 :                 tty_warn(tty, "%s: bad port count (%d)\n", __func__,
     620             :                          port->count);
     621           0 :                 port->count = 0;
     622             :         }
     623             : 
     624           0 :         if (port->count) {
     625           0 :                 spin_unlock_irqrestore(&port->lock, flags);
     626           0 :                 return 0;
     627             :         }
     628           0 :         spin_unlock_irqrestore(&port->lock, flags);
     629             : 
     630           0 :         tty->closing = 1;
     631             : 
     632           0 :         if (tty_port_initialized(port)) {
     633             :                 /* Don't block on a stalled port, just pull the chain */
     634           0 :                 if (tty->flow.tco_stopped)
     635           0 :                         tty_driver_flush_buffer(tty);
     636           0 :                 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
     637           0 :                         tty_wait_until_sent(tty, port->closing_wait);
     638           0 :                 if (port->drain_delay)
     639           0 :                         tty_port_drain_delay(port, tty);
     640             :         }
     641             :         /* Flush the ldisc buffering */
     642           0 :         tty_ldisc_flush(tty);
     643             : 
     644             :         /* Report to caller this is the last port reference */
     645           0 :         return 1;
     646             : }
     647             : EXPORT_SYMBOL(tty_port_close_start);
     648             : 
     649             : /**
     650             :  * tty_port_close_end - helper for tty->ops->close, part 2/2
     651             :  * @port: tty_port of the device
     652             :  * @tty: tty being closed
     653             :  *
     654             :  * This is a continuation of the first part: tty_port_close_start(). This
     655             :  * should be called after turning off the device. It flushes the data from the
     656             :  * line discipline and delays the close by @port->close_delay.
     657             :  *
     658             :  * Locking: Caller holds tty lock.
     659             :  */
     660           0 : void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
     661             : {
     662             :         unsigned long flags;
     663             : 
     664           0 :         tty_ldisc_flush(tty);
     665           0 :         tty->closing = 0;
     666             : 
     667           0 :         spin_lock_irqsave(&port->lock, flags);
     668             : 
     669           0 :         if (port->blocked_open) {
     670           0 :                 spin_unlock_irqrestore(&port->lock, flags);
     671           0 :                 if (port->close_delay)
     672           0 :                         msleep_interruptible(jiffies_to_msecs(port->close_delay));
     673           0 :                 spin_lock_irqsave(&port->lock, flags);
     674           0 :                 wake_up_interruptible(&port->open_wait);
     675             :         }
     676           0 :         spin_unlock_irqrestore(&port->lock, flags);
     677           0 :         tty_port_set_active(port, 0);
     678           0 : }
     679             : EXPORT_SYMBOL(tty_port_close_end);
     680             : 
     681             : /**
     682             :  * tty_port_close - generic tty->ops->close handler
     683             :  * @port: tty_port of the device
     684             :  * @tty: tty being closed
     685             :  * @filp: passed file pointer
     686             :  *
     687             :  * It is a generic helper to be used in driver's @tty->ops->close. It wraps a
     688             :  * sequence of tty_port_close_start(), tty_port_shutdown(), and
     689             :  * tty_port_close_end(). The latter two are called only if this is the last
     690             :  * close. See the respective functions for the details.
     691             :  *
     692             :  * Locking: Caller holds tty lock
     693             :  */
     694           0 : void tty_port_close(struct tty_port *port, struct tty_struct *tty,
     695             :                                                         struct file *filp)
     696             : {
     697           0 :         if (tty_port_close_start(port, tty, filp) == 0)
     698             :                 return;
     699           0 :         tty_port_shutdown(port, tty);
     700           0 :         if (!port->console)
     701           0 :                 set_bit(TTY_IO_ERROR, &tty->flags);
     702           0 :         tty_port_close_end(port, tty);
     703           0 :         tty_port_tty_set(port, NULL);
     704             : }
     705             : EXPORT_SYMBOL(tty_port_close);
     706             : 
     707             : /**
     708             :  * tty_port_install - generic tty->ops->install handler
     709             :  * @port: tty_port of the device
     710             :  * @driver: tty_driver for this device
     711             :  * @tty: tty to be installed
     712             :  *
     713             :  * It is the same as tty_standard_install() except the provided @port is linked
     714             :  * to a concrete tty specified by @tty. Use this or tty_port_register_device()
     715             :  * (or both). Call tty_port_link_device() as a last resort.
     716             :  */
     717           0 : int tty_port_install(struct tty_port *port, struct tty_driver *driver,
     718             :                 struct tty_struct *tty)
     719             : {
     720           0 :         tty->port = port;
     721           0 :         return tty_standard_install(driver, tty);
     722             : }
     723             : EXPORT_SYMBOL_GPL(tty_port_install);
     724             : 
     725             : /**
     726             :  * tty_port_open - generic tty->ops->open handler
     727             :  * @port: tty_port of the device
     728             :  * @tty: tty to be opened
     729             :  * @filp: passed file pointer
     730             :  *
     731             :  * It is a generic helper to be used in driver's @tty->ops->open. It activates
     732             :  * the devices using @port->ops->activate if not active already. And waits for
     733             :  * the device to be ready using tty_port_block_til_ready() (e.g.  raises
     734             :  * DTR/CTS and waits for carrier).
     735             :  *
     736             :  * Note that @port->ops->shutdown is not called when @port->ops->activate
     737             :  * returns an error (on the contrary, @tty->ops->close is).
     738             :  *
     739             :  * Locking: Caller holds tty lock.
     740             :  *
     741             :  * Note: may drop and reacquire tty lock (in tty_port_block_til_ready()) so
     742             :  * @tty and @port may have changed state (eg., may be hung up now).
     743             :  */
     744           0 : int tty_port_open(struct tty_port *port, struct tty_struct *tty,
     745             :                                                         struct file *filp)
     746             : {
     747           0 :         spin_lock_irq(&port->lock);
     748           0 :         ++port->count;
     749           0 :         spin_unlock_irq(&port->lock);
     750           0 :         tty_port_tty_set(port, tty);
     751             : 
     752             :         /*
     753             :          * Do the device-specific open only if the hardware isn't
     754             :          * already initialized. Serialize open and shutdown using the
     755             :          * port mutex.
     756             :          */
     757             : 
     758           0 :         mutex_lock(&port->mutex);
     759             : 
     760           0 :         if (!tty_port_initialized(port)) {
     761           0 :                 clear_bit(TTY_IO_ERROR, &tty->flags);
     762           0 :                 if (port->ops->activate) {
     763           0 :                         int retval = port->ops->activate(port, tty);
     764             : 
     765           0 :                         if (retval) {
     766           0 :                                 mutex_unlock(&port->mutex);
     767           0 :                                 return retval;
     768             :                         }
     769             :                 }
     770             :                 tty_port_set_initialized(port, 1);
     771             :         }
     772           0 :         mutex_unlock(&port->mutex);
     773           0 :         return tty_port_block_til_ready(port, tty, filp);
     774             : }
     775             : EXPORT_SYMBOL(tty_port_open);

Generated by: LCOV version 1.14