diff options
| author | Linux Build Service Account <lnxbuild@quicinc.com> | 2017-12-17 08:28:55 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-12-17 08:28:54 -0800 |
| commit | b598eeb6bc8c5989c3ccc8acd59794596be461ce (patch) | |
| tree | 435727e7103fffdc03ff49c03f65dade3136f9af | |
| parent | 02a73d4553b036e9dd44b02a7ca874dc0555f86b (diff) | |
| parent | 85113f453fbba752e34910f204bb6dd4b7a19b4e (diff) | |
Merge "serial: msm_serial_hs: Allow system suspend when no client is active"
| -rw-r--r-- | drivers/tty/serial/msm_serial_hs.c | 71 |
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) |
