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:
Chandana Kishori Chiluveru 2024-08-27 23:04:40 -07:00
parent 7f32770218
commit 4219aa4a08
3 changed files with 17 additions and 6 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
};
/**