LCOV - code coverage report
Current view: top level - drivers/tty - tty_port.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 117 256 45.7 %
Date: 2021-04-22 12:43:58 Functions: 16 30 53.3 %

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

Generated by: LCOV version 1.14