summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/serial/msm_serial_hs.c71
1 files changed, 41 insertions, 30 deletions
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index c2c9b9361d64..5da2f1406546 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -258,6 +258,7 @@ struct msm_hs_port {
atomic_t client_count;
bool obs; /* out of band sleep flag */
atomic_t client_req_state;
+ int sys_suspend_noirq_cnt;
void *ipc_msm_hs_log_ctxt;
void *ipc_msm_hs_pwr_ctxt;
int ipc_debug_mask;
@@ -395,8 +396,6 @@ static void msm_hs_resource_unvote(struct msm_hs_port *msm_uport)
{
struct uart_port *uport = &(msm_uport->uport);
int rc = atomic_read(&msm_uport->resource_count);
- struct msm_hs_tx *tx = &msm_uport->tx;
- struct msm_hs_rx *rx = &msm_uport->rx;
MSM_HS_DBG("%s(): power usage count %d", __func__, rc);
if (rc <= 0) {
@@ -405,15 +404,8 @@ static void msm_hs_resource_unvote(struct msm_hs_port *msm_uport)
return;
}
atomic_dec(&msm_uport->resource_count);
-
- if (pm_runtime_enabled(uport->dev)) {
- pm_runtime_mark_last_busy(uport->dev);
- pm_runtime_put_autosuspend(uport->dev);
- } else {
- MSM_HS_DBG("%s():tx.flush:%d,in_flight:%d,rx.flush:%d\n",
- __func__, tx->flush, tx->dma_in_flight, rx->flush);
- msm_hs_pm_suspend(uport->dev);
- }
+ pm_runtime_mark_last_busy(uport->dev);
+ pm_runtime_put_autosuspend(uport->dev);
}
/* Vote for resources before accessing them */
@@ -1390,8 +1382,9 @@ static void msm_hs_disconnect_rx(struct uart_port *uport)
if (msm_uport->rx.flush == FLUSH_NONE)
msm_uport->rx.flush = FLUSH_STOP;
- if (sps_is_pipe_empty(sps_pipe_handle, &prod_empty)) {
- MSM_HS_WARN("%s():Pipe Not Empty, ret=%d, flush=%d\n",
+ if (!sps_is_pipe_empty(sps_pipe_handle, &prod_empty)) {
+ if (prod_empty == false)
+ MSM_HS_WARN("%s():Pipe Not Empty, prod=%d, flush=%d\n",
__func__, prod_empty, msm_uport->rx.flush);
}
disconnect_rx_endpoint(msm_uport);
@@ -3295,6 +3288,7 @@ static int msm_hs_pm_resume(struct device *dev)
LOG_USR_MSG(msm_uport->ipc_msm_hs_pwr_ctxt,
"%s:PM State:Active client_count %d\n", __func__, client_count);
exit_pm_resume:
+ msm_uport->sys_suspend_noirq_cnt = 0;
mutex_unlock(&msm_uport->mtx);
return ret;
}
@@ -3304,14 +3298,11 @@ static int msm_hs_pm_sys_suspend_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct msm_hs_port *msm_uport = get_matching_hs_port(pdev);
- enum msm_hs_pm_state prev_pwr_state;
int clk_cnt, client_count, ret = 0;
if (IS_ERR_OR_NULL(msm_uport))
return -ENODEV;
-
mutex_lock(&msm_uport->mtx);
-
/*
* If there is an active clk request or an impending userspace request
* fail the suspend callback.
@@ -3319,19 +3310,40 @@ static int msm_hs_pm_sys_suspend_noirq(struct device *dev)
clk_cnt = atomic_read(&msm_uport->resource_count);
client_count = atomic_read(&msm_uport->client_count);
if (msm_uport->pm_state == MSM_HS_PM_ACTIVE) {
- MSM_HS_WARN("%s:Fail Suspend.clk_cnt:%d,clnt_count:%d\n",
- __func__, clk_cnt, client_count);
- ret = -EBUSY;
- goto exit_suspend_noirq;
+ if (clk_cnt == 0 && client_count == 0)
+ msm_uport->sys_suspend_noirq_cnt++;
+ /*Serve force suspend post autosuspend timer expires
+ */
+ if (msm_uport->sys_suspend_noirq_cnt >= 2) {
+ msm_uport->pm_state = MSM_HS_PM_SYS_SUSPENDED;
+ msm_uport->sys_suspend_noirq_cnt = 0;
+ mutex_unlock(&msm_uport->mtx);
+
+ msm_hs_pm_suspend(dev);
+ /*
+ * Synchronize RT-pm and system-pm, RT-PM thinks that
+ * we are active. The three calls below let the RT-PM
+ * know that we are suspended already without calling
+ * suspend callback
+ */
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+ pm_runtime_enable(dev);
+
+ /*To Balance out exit time Mutex unlock */
+ mutex_lock(&msm_uport->mtx);
+ } else {
+ ret = -EBUSY;
+ }
}
-
- prev_pwr_state = msm_uport->pm_state;
- msm_uport->pm_state = MSM_HS_PM_SYS_SUSPENDED;
- LOG_USR_MSG(msm_uport->ipc_msm_hs_pwr_ctxt,
- "%s:PM State:Sys-Suspended client_count %d\n", __func__,
- client_count);
-exit_suspend_noirq:
mutex_unlock(&msm_uport->mtx);
+ if (ret)
+ MSM_HS_WARN("%s:Fail Suspend.clk_cnt:%d,clnt_count:%d\n",
+ __func__, clk_cnt, client_count);
+ else
+ LOG_USR_MSG(msm_uport->ipc_msm_hs_pwr_ctxt,
+ "%s:PM State:Sys-Suspended client_count %d\n",
+ __func__, client_count);
return ret;
};
@@ -3817,11 +3829,10 @@ static void msm_hs_shutdown(struct uart_port *uport)
if (atomic_read(&msm_uport->client_count)) {
MSM_HS_WARN("%s: Client vote on, forcing to 0\n", __func__);
atomic_set(&msm_uport->client_count, 0);
- LOG_USR_MSG(msm_uport->ipc_msm_hs_pwr_ctxt,
- "%s: Client_Count 0\n", __func__);
}
msm_hs_unconfig_uart_gpios(uport);
- MSM_HS_INFO("%s:UART port closed successfully\n", __func__);
+ LOG_USR_MSG(msm_uport->ipc_msm_hs_pwr_ctxt,
+ "%s:UART port closed, Client_Count 0\n", __func__);
}
static void __exit msm_serial_hs_exit(void)