diff --git a/drivers/spi/q2spi-gsi.c b/drivers/spi/q2spi-gsi.c index 1e233c97d07c..0af382331462 100644 --- a/drivers/spi/q2spi-gsi.c +++ b/drivers/spi/q2spi-gsi.c @@ -130,6 +130,7 @@ static void q2spi_check_m_irq_err_status(struct q2spi_geni *q2spi, u32 cb_status Q2SPI_DEBUG(q2spi, "%s Q2SPI_CHEKSUM_FAIL\n", __func__); if (status & Q2SPI_START_SEQ_TIMEOUT) { q2spi->is_start_seq_fail = true; + complete_all(&q2spi->wait_comp_start_fail); Q2SPI_DEBUG(q2spi, "%s Q2SPI_START_SEQ_TIMEOUT\n", __func__); } if (status & Q2SPI_STOP_SEQ_TIMEOUT) @@ -495,15 +496,15 @@ int check_gsi_transfer_completion_db_rx(struct q2spi_geni *q2spi) int check_gsi_transfer_completion(struct q2spi_geni *q2spi) { int i = 0, ret = 0; - unsigned long timeout = 0, xfer_timeout = 0; + unsigned long timeleft = 0, xfer_timeout = 0; xfer_timeout = XFER_TIMEOUT_OFFSET; Q2SPI_DEBUG(q2spi, "%s tx_eot:%d rx_eot:%d\n", __func__, q2spi->gsi->num_tx_eot, q2spi->gsi->num_rx_eot); for (i = 0 ; i < q2spi->gsi->num_tx_eot; i++) { - timeout = + timeleft = wait_for_completion_timeout(&q2spi->tx_cb, msecs_to_jiffies(xfer_timeout)); - if (!timeout) { + if (!timeleft) { Q2SPI_DEBUG(q2spi, "%s PID:%d Tx[%d] timeout\n", __func__, current->pid, i); ret = -ETIMEDOUT; goto err_gsi_geni_transfer; @@ -513,9 +514,9 @@ int check_gsi_transfer_completion(struct q2spi_geni *q2spi) } for (i = 0 ; i < q2spi->gsi->num_rx_eot; i++) { - timeout = + timeleft = wait_for_completion_timeout(&q2spi->rx_cb, msecs_to_jiffies(xfer_timeout)); - if (!timeout) { + if (!timeleft) { Q2SPI_DEBUG(q2spi, "%s PID:%d Rx[%d] timeout\n", __func__, current->pid, i); ret = -ETIMEDOUT; goto err_gsi_geni_transfer; @@ -524,11 +525,15 @@ int check_gsi_transfer_completion(struct q2spi_geni *q2spi) } } err_gsi_geni_transfer: - if (q2spi->gsi->qup_gsi_err || !timeout) { + if (q2spi->gsi->qup_gsi_err || !timeleft) { ret = -ETIMEDOUT; Q2SPI_DEBUG(q2spi, "%s Err QUP Gsi Error\n", __func__); q2spi->gsi->qup_gsi_err = false; q2spi->setup_config0 = false; + /* Block on TX completion callback for start sequence failure */ + wait_for_completion_interruptible_timeout + (&q2spi->wait_comp_start_fail, + msecs_to_jiffies(TIMEOUT_MSECONDS)); if (!q2spi->is_start_seq_fail) gpi_q2spi_terminate_all(q2spi->gsi->tx_c); } diff --git a/drivers/spi/q2spi-msm-geni.c b/drivers/spi/q2spi-msm-geni.c index a5cb66cd941c..4b64d1c66d91 100644 --- a/drivers/spi/q2spi-msm-geni.c +++ b/drivers/spi/q2spi-msm-geni.c @@ -2267,7 +2267,9 @@ static ssize_t q2spi_transfer(struct file *filp, const char __user *buf, size_t pm_runtime_set_suspended(q2spi->dev); goto err; } + q2spi->is_start_seq_fail = false; + reinit_completion(&q2spi->wait_comp_start_fail); Q2SPI_DEBUG(q2spi, "%s PM after get_sync count:%d\n", __func__, atomic_read(&q2spi->dev->power.usage_count)); q2spi_wait_for_doorbell_setup_ready(q2spi); @@ -2286,6 +2288,7 @@ static ssize_t q2spi_transfer(struct file *filp, const char __user *buf, size_t ret = -ENOMEM; goto err; } + Q2SPI_DEBUG(q2spi, "%s flow_id:%d\n", __func__, flow_id); ret = q2spi_transfer_with_retries(q2spi, q2spi_req, cur_q2spi_pkt, len, flow_id, user_buf); Q2SPI_DEBUG(q2spi, "%s transfer_with_retries ret:%d\n", __func__, ret); @@ -4421,6 +4424,7 @@ static int q2spi_geni_probe(struct platform_device *pdev) atomic_set(&q2spi->sma_rd_pending, 0); init_completion(&q2spi->sma_wr_comp); init_completion(&q2spi->sma_rd_comp); + init_completion(&q2spi->wait_comp_start_fail); /* Pre allocate buffers for transfers */ ret = q2spi_pre_alloc_buffers(q2spi); diff --git a/drivers/spi/q2spi-msm.h b/drivers/spi/q2spi-msm.h index 83cf08b298da..e0b4db019da5 100644 --- a/drivers/spi/q2spi-msm.h +++ b/drivers/spi/q2spi-msm.h @@ -529,6 +529,7 @@ struct q2spi_dma_transfer { * @q2spi_sleep_cmd_enable: reflects start sending the sleep command to slave * @q2spi_cr_hdr_err: reflects CR Header incorrect in CR Header * @is_start_seq_fail: start sequence fail due to slave not responding + * @wait_comp_start_fail: completion for transfer callback during start sequence failure */ struct q2spi_geni { struct device *wrapper_dev; @@ -636,6 +637,7 @@ struct q2spi_geni { bool q2spi_sleep_cmd_enable; bool q2spi_cr_hdr_err; bool is_start_seq_fail; + struct completion wait_comp_start_fail; }; /**