From: Zhang Yanmin <yanmin.zh...@intel.com>

Wake up ldisc device before calling its driver to access the device.

Signed-off-by: Zhang Yanmin <yanmin.zh...@intel.com>
---
 drivers/tty/n_gsm.c | 40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 2c34c32..f887df6 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -62,6 +62,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/gsmmux.h>
+#include <linux/pm_runtime.h>
 
 static int debug;
 module_param(debug, int, 0600);
@@ -555,6 +556,27 @@ static int gsm_stuff_frame(const u8 *input, u8 *output, 
int len)
        return olen;
 }
 
+static int pm_runtime_get_sync_tty(struct tty_struct *tty)
+{
+       int ret = 0;
+
+       /* Wakeup parent as tty itself doesn't enable runtime */
+       if (tty->dev->parent)
+               ret = pm_runtime_get_sync(tty->dev->parent);
+
+       return ret;
+}
+
+static int pm_runtime_put_tty(struct tty_struct *tty)
+{
+       int ret = 0;
+
+       if (tty->dev->parent)
+               ret = pm_runtime_put(tty->dev->parent);
+
+       return ret;
+}
+
 /**
  *     gsm_send        -       send a control frame
  *     @gsm: our GSM mux
@@ -1511,7 +1533,9 @@ static void gsm_dlci_begin_open(struct gsm_dlci *dlci)
                return;
        dlci->retries = gsm->n2;
        dlci->state = DLCI_OPENING;
+       pm_runtime_get_sync_tty(gsm->tty);
        gsm_command(dlci->gsm, dlci->addr, SABM|PF);
+       pm_runtime_put_tty(gsm->tty);
        mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100);
 }
 
@@ -1533,7 +1557,9 @@ static void gsm_dlci_begin_close(struct gsm_dlci *dlci)
                return;
        dlci->retries = gsm->n2;
        dlci->state = DLCI_CLOSING;
+       pm_runtime_get_sync_tty(gsm->tty);
        gsm_command(dlci->gsm, dlci->addr, DISC|PF);
+       pm_runtime_put_tty(gsm->tty);
        mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100);
 }
 
@@ -2286,7 +2312,9 @@ static void gsmld_receive_buf(struct tty_struct *tty, 
const unsigned char *cp,
                        flags = *f++;
                switch (flags) {
                case TTY_NORMAL:
+                       pm_runtime_get_sync_tty(gsm->tty);
                        gsm->receive(gsm, *dp);
+                       pm_runtime_put_tty(gsm->tty);
                        break;
                case TTY_OVERRUN:
                case TTY_BREAK:
@@ -2957,6 +2985,7 @@ static int gsmtty_open(struct tty_struct *tty, struct 
file *filp)
 {
        struct gsm_dlci *dlci = tty->driver_data;
        struct tty_port *port = &dlci->port;
+       int ret;
 
        port->count++;
        tty_port_tty_set(port, tty);
@@ -2968,7 +2997,11 @@ static int gsmtty_open(struct tty_struct *tty, struct 
file *filp)
        /* Start sending off SABM messages */
        gsm_dlci_begin_open(dlci);
        /* And wait for virtual carrier */
-       return tty_port_block_til_ready(port, tty, filp);
+       pm_runtime_get_sync_tty(dlci->gsm->tty);
+       ret = tty_port_block_til_ready(port, tty, filp);
+       pm_runtime_put_tty(dlci->gsm->tty);
+
+       return ret;
 }
 
 static void gsmtty_close(struct tty_struct *tty, struct file *filp)
@@ -2986,11 +3019,14 @@ static void gsmtty_close(struct tty_struct *tty, struct 
file *filp)
        gsm = dlci->gsm;
        if (tty_port_close_start(&dlci->port, tty, filp) == 0)
                return;
+       pm_runtime_get_sync_tty(gsm->tty);
        gsm_dlci_begin_close(dlci);
        if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) {
                if (C_HUPCL(tty))
                        tty_port_lower_dtr_rts(&dlci->port);
        }
+       pm_runtime_put_tty(gsm->tty);
+
        tty_port_close_end(&dlci->port, tty);
        tty_port_tty_set(&dlci->port, NULL);
        return;
@@ -3012,10 +3048,12 @@ static int gsmtty_write(struct tty_struct *tty, const 
unsigned char *buf,
        struct gsm_dlci *dlci = tty->driver_data;
        if (dlci->state == DLCI_CLOSED)
                return -EINVAL;
+       pm_runtime_get_sync_tty(dlci->gsm->tty);
        /* Stuff the bytes into the fifo queue */
        sent = kfifo_in_locked(dlci->fifo, buf, len, &dlci->lock);
        /* Need to kick the channel */
        gsm_dlci_data_kick(dlci);
+       pm_runtime_put_tty(dlci->gsm->tty);
        return sent;
 }
 
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to