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..40671fa 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