Messages in this thread Patch in this message | | | Date | Tue, 26 May 2015 10:20:34 +0800 | From | "Zhang, Yanmin" <> | Subject | [PATCH 3/3] n_gsm: wake up ldisc tty before using it |
| |
Wake up ldisc device before calling its driver to access the device.
Signed-off-by: Zhang Yanmin <yanmin.zhang@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
| |