q2spi-msm-geni: Ensure Channel errors handled sequentially after START sequence fail
When slave is in sleep q2spi host transfer will fail with GSI start sequence failure. In this scenario two events reported from GSI channel error and TX dma completion event 0x22. Since GSI reports these events separately if start sequence fail is not processed before channel error gpi_q2spi_terminate_all is called twice and leading to GSI failures. Ensure Channel errors in GSI recover path are handled sequentially only after START sequence fail is processed. Change-Id: Ie85528b6354241153330c403ba026c5006d5c78e Signed-off-by: Chandana Kishori Chiluveru <quic_cchiluve@quicinc.com>
This commit is contained in:
parent
7f32770218
commit
4219aa4a08
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user