diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2014-02-08 09:39:10 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2014-02-08 09:39:10 -0800 |
commit | ebe31ae5a823d1628dd68961b72c92c900c240db (patch) | |
tree | 5df70a37390e4b813f44488fd6f5b419ed4bb009 /drivers/tty | |
parent | f1910e55c883aded4effc5ee7f658635e4e01aa4 (diff) | |
parent | 6b1a422ae8b5d725b3786ded2abfd96ad064200f (diff) |
Merge "msm_serial_hs: Race Condition during Baud Rate Configuration"
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/msm_serial_hs.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index 9e922d1ab4e7..e486d727e5cc 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c @@ -141,7 +141,7 @@ enum flush_reason { FLUSH_NONE, FLUSH_DATA_READY, FLUSH_DATA_INVALID, /* values after this indicate invalid data */ - FLUSH_IGNORE = FLUSH_DATA_INVALID, + FLUSH_IGNORE, FLUSH_STOP, FLUSH_SHUTDOWN, }; @@ -206,6 +206,7 @@ struct msm_hs_rx { struct tasklet_struct tlet; struct msm_hs_sps_ep_conn_data prod; bool rx_cmd_queued; + bool rx_cmd_exec; }; enum buffer_states { NONE_PENDING = 0x0, @@ -1252,7 +1253,7 @@ static void msm_hs_set_termios(struct uart_port *uport, if (msm_uport->rx.flush == FLUSH_NONE) { wake_lock(&msm_uport->rx.wake_lock); - msm_uport->rx.flush = FLUSH_IGNORE; + msm_uport->rx.flush = FLUSH_DATA_INVALID; /* * Before using dmov APIs make sure that * previous writel are completed. Hence @@ -1269,6 +1270,7 @@ static void msm_hs_set_termios(struct uart_port *uport, MSM_HS_ERR("%s(): sps_disconnect failed\n", __func__); msm_hs_spsconnect_rx(uport); + msm_uport->rx.flush = FLUSH_IGNORE; msm_serial_hs_rx_tlet((unsigned long) &rx->tlet); } else { msm_uport->rx_discard_flush_issued = true; @@ -1376,7 +1378,7 @@ static void msm_hs_stop_rx_locked(struct uart_port *uport) unsigned int data; MSM_HS_DBG("In %s():\n", __func__); - if (msm_uport->clk_state == MSM_HS_CLK_ON) { + if (msm_uport->clk_state != MSM_HS_CLK_OFF) { /* disable dlink */ data = msm_hs_read(uport, UART_DM_DMEN); if (is_blsp_uart(msm_uport)) @@ -1507,6 +1509,12 @@ static void msm_hs_start_rx_locked(struct uart_port *uport) MSM_HS_WARN("%s: Failed.Clocks are OFF\n", __func__); return; } + if (rx->rx_cmd_exec) { + MSM_HS_DBG("%s: Rx Cmd got executed, wait for rx_tlet\n", + __func__); + rx->flush = FLUSH_IGNORE; + return; + } msm_uport->rx.buffer_pending = 0; if (buffer_pending) MSM_HS_ERR("Error: rx started in buffer state =%x", @@ -1634,6 +1642,7 @@ static void msm_serial_hs_rx_tlet(unsigned long tlet_ptr) rx = &msm_uport->rx; msm_uport->rx.rx_cmd_queued = false; + msm_uport->rx.rx_cmd_exec = false; status = msm_hs_read(uport, UART_DM_SR); @@ -1903,6 +1912,7 @@ static void msm_hs_sps_rx_callback(struct sps_event_notify *notify) if (msm_uport->rx.flush == FLUSH_NONE) { spin_lock_irqsave(&uport->lock, flags); msm_uport->rx_count_callback = notify->data.transfer.iovec.size; + msm_uport->rx.rx_cmd_exec = true; spin_unlock_irqrestore(&uport->lock, flags); tasklet_schedule(&msm_uport->rx.tlet); } @@ -2697,6 +2707,7 @@ static int msm_hs_startup(struct uart_port *uport) /* Initialize the tx */ tx->tx_ready_int_en = 0; tx->dma_in_flight = 0; + rx->rx_cmd_exec = false; msm_uport->tty_flush_receive = false; MSM_HS_DBG("%s: Setting tty_flush_receive to false\n", __func__); |