summaryrefslogtreecommitdiff
path: root/drivers/tty
diff options
context:
space:
mode:
authorMukesh Kumar Savaliya <msavaliy@codeaurora.org>2017-09-25 19:56:12 +0530
committerMukesh Kumar Savaliya <msavaliy@codeaurora.org>2017-10-12 14:41:45 +0530
commit33b0678405a3dbdffe09e56ff576682d46d47c0d (patch)
treed14e9494d56d9c44bc26dece3ecabf6e1b6863d2 /drivers/tty
parent34f1071c18f56ceae77aa761578c639d59e67265 (diff)
serial: msm_serial_hs: Do not accept Rx Data till the Rx pipe connect
In a resume path, sometimes RX is resetted and keep the RX BAM engine enabled which actually makes RX to start accepting data when Flow control is not disabled. 1. Keep the flow control disabled till the RX engine is fully enabled. 2. Use atomic variable to prevent race between startup and resume path. 3. Revert stop_rx changes, as we should not vote for the clock there. 4. Revert suspend time wakeup interrupt enable as clocks are ON and it can cause extra 0xFD injects in case of noise. Change-Id: I5fe84b8d9f5118803e72974db3e6637c44b9c482 Signed-off-by: Mukesh Kumar Savaliya <msavaliy@codeaurora.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/msm_serial_hs.c49
1 files changed, 21 insertions, 28 deletions
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 416006a3384c..c2c9b9361d64 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -218,7 +218,7 @@ struct msm_hs_wakeup {
};
struct msm_hs_port {
- bool startup_locked;
+ atomic_t startup_locked;
struct uart_port uport;
unsigned long imr_reg; /* shadow value of UARTDM_IMR */
struct clk *clk;
@@ -649,7 +649,6 @@ static int msm_serial_loopback_enable_set(void *data, u64 val)
unsigned long flags;
int ret = 0;
- msm_uport->startup_locked = true;
msm_hs_resource_vote(msm_uport);
if (val) {
@@ -669,7 +668,6 @@ static int msm_serial_loopback_enable_set(void *data, u64 val)
}
/* Calling CLOCK API. Hence mb() requires here. */
mb();
- msm_uport->startup_locked = false;
msm_hs_resource_unvote(msm_uport);
return 0;
}
@@ -681,13 +679,11 @@ static int msm_serial_loopback_enable_get(void *data, u64 *val)
unsigned long flags;
int ret = 0;
- msm_uport->startup_locked = true;
msm_hs_resource_vote(msm_uport);
spin_lock_irqsave(&uport->lock, flags);
ret = msm_hs_read(&msm_uport->uport, UART_DM_MR2);
spin_unlock_irqrestore(&uport->lock, flags);
- msm_uport->startup_locked = false;
msm_hs_resource_unvote(msm_uport);
@@ -1372,12 +1368,9 @@ static void msm_hs_stop_rx_locked(struct uart_port *uport)
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
if (msm_uport->pm_state != MSM_HS_PM_ACTIVE) {
- MSM_HS_WARN("%s(): Clocks are off\n", __func__);
- /* Make sure resource_on doesn't get called */
- if (msm_hs_clk_bus_vote(msm_uport))
- MSM_HS_ERR("%s:Failed clock vote\n", __func__);
- msm_hs_disable_rx(uport);
- msm_hs_clk_bus_unvote(msm_uport);
+ MSM_HS_WARN("%s(): Clocks are off, Rx still active\n",
+ __func__);
+ return;
} else
msm_hs_disable_rx(uport);
@@ -1421,7 +1414,7 @@ void tx_timeout_handler(unsigned long arg)
if (UARTDM_ISR_CURRENT_CTS_BMSK & isr)
MSM_HS_WARN("%s(): CTS Disabled, ISR 0x%x", __func__, isr);
dump_uart_hs_registers(msm_uport);
- /* Stop further loging */
+ /* Stop further logging */
MSM_HS_ERR("%s(): Stop IPC logging\n", __func__);
}
@@ -1868,12 +1861,6 @@ static void msm_hs_start_tx_locked(struct uart_port *uport)
struct msm_hs_tx *tx = &msm_uport->tx;
unsigned int isr;
- if (msm_uport->startup_locked) {
- MSM_HS_DBG("%s(): No Tx Request, startup_locked=%d\n",
- __func__, msm_uport->startup_locked);
- return;
- }
-
/* Bail if transfer in progress */
if (tx->flush < FLUSH_STOP || tx->dma_in_flight) {
MSM_HS_INFO("%s(): retry, flush %d, dma_in_flight %d\n",
@@ -1881,9 +1868,12 @@ static void msm_hs_start_tx_locked(struct uart_port *uport)
if (msm_uport->pm_state == MSM_HS_PM_ACTIVE) {
isr = msm_hs_read(uport, UART_DM_ISR);
- if (UARTDM_ISR_CURRENT_CTS_BMSK & isr)
- MSM_HS_DBG("%s():CTS 1: Peer is Busy, ISR 0x%x",
- __func__, isr);
+ if (UARTDM_ISR_CURRENT_CTS_BMSK & isr) {
+ MSM_HS_DBG("%s():CTS 1: Peer is Busy\n",
+ __func__);
+ MSM_HS_DBG("%s():ISR 0x%x\n",
+ __func__, isr);
+ }
} else
MSM_HS_WARN("%s(): Clocks are off\n", __func__);
@@ -2364,11 +2354,11 @@ void msm_hs_resource_on(struct msm_hs_port *msm_uport)
unsigned int data;
unsigned long flags;
- if (msm_uport->startup_locked) {
- MSM_HS_WARN("%s(): startup_locked=%d\n",
- __func__, msm_uport->startup_locked);
+ if (atomic_read(&msm_uport->startup_locked)) {
+ MSM_HS_DBG("%s(): Port open in progress\n", __func__);
return;
}
+ msm_hs_disable_flow_control(uport, false);
if (msm_uport->rx.flush == FLUSH_SHUTDOWN ||
msm_uport->rx.flush == FLUSH_STOP) {
@@ -2387,6 +2377,8 @@ void msm_hs_resource_on(struct msm_hs_port *msm_uport)
spin_unlock_irqrestore(&uport->lock, flags);
}
msm_hs_spsconnect_tx(msm_uport);
+
+ msm_hs_enable_flow_control(uport, false);
}
/* Request to turn off uart clock once pending TX is flushed */
@@ -2679,7 +2671,7 @@ static int msm_hs_startup(struct uart_port *uport)
struct sps_pipe *sps_pipe_handle_tx = tx->cons.pipe_handle;
struct sps_pipe *sps_pipe_handle_rx = rx->prod.pipe_handle;
- msm_uport->startup_locked = true;
+ atomic_set(&msm_uport->startup_locked, 1);
rfr_level = uport->fifosize;
if (rfr_level > 16)
rfr_level -= 16;
@@ -2809,7 +2801,7 @@ static int msm_hs_startup(struct uart_port *uport)
atomic_set(&msm_uport->client_req_state, 0);
LOG_USR_MSG(msm_uport->ipc_msm_hs_pwr_ctxt,
"%s: Client_Count 0\n", __func__);
- msm_uport->startup_locked = false;
+ atomic_set(&msm_uport->startup_locked, 0);
msm_hs_start_rx_locked(uport);
spin_unlock_irqrestore(&uport->lock, flags);
@@ -2826,6 +2818,7 @@ unconfig_uart_gpios:
free_uart_irq:
free_irq(uport->irq, msm_uport);
unvote_exit:
+ atomic_set(&msm_uport->startup_locked, 0);
msm_hs_resource_unvote(msm_uport);
MSM_HS_ERR("%s(): Error return\n", __func__);
return ret;
@@ -3238,8 +3231,6 @@ static void msm_hs_pm_suspend(struct device *dev)
msm_uport->pm_state = MSM_HS_PM_SUSPENDED;
msm_hs_resource_off(msm_uport);
obs_manage_irq(msm_uport, false);
- if (!atomic_read(&msm_uport->client_req_state))
- enable_wakeup_interrupt(msm_uport);
msm_hs_clk_bus_unvote(msm_uport);
/* For OBS, don't use wakeup interrupt, set gpio to suspended state */
@@ -3251,6 +3242,8 @@ static void msm_hs_pm_suspend(struct device *dev)
__func__);
}
+ if (!atomic_read(&msm_uport->client_req_state))
+ enable_wakeup_interrupt(msm_uport);
LOG_USR_MSG(msm_uport->ipc_msm_hs_pwr_ctxt,
"%s: PM State Suspended client_count %d\n", __func__,
client_count);