LCOV - code coverage report
Current view: top level - drivers/tty - tty_port.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 20 242 8.3 %
Date: 2023-04-06 08:38:28 Functions: 3 31 9.7 %

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

Generated by: LCOV version 1.14