summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPraveen Talari <praveen.talari@oss.qualcomm.com>2026-07-29 20:43:26 +0530
committerMark Brown <broonie@kernel.org>2026-07-29 21:41:31 +0100
commit607b41c1e0fe68bcc1b09cd544a4e2af43b20dea (patch)
treec06b3dd9306c653465008ebb58008b682dc3d7c7
parentf40e7ab049f4ba588619336886c1867127d9499f (diff)
downloadlinux-next-607b41c1e0fe68bcc1b09cd544a4e2af43b20dea.tar.gz
linux-next-607b41c1e0fe68bcc1b09cd544a4e2af43b20dea.zip
spi: qcom-geni: add GENI SE registers trace event on error paths
The GENI SPI driver reports various transfer failures such as command timeouts, DMA reset timeouts, DMA transaction errors, and unexpected interrupt conditions. However, diagnosing the root cause of these failures is difficult as the hardware state is not captured when the error occurs. Add trace_geni_se_regs() calls at critical SPI error handling paths to automatically capture GENI serial engine debug registers when failures are detected. This includes: - M_CMD abort/cancel timeout - DMA TX/RX FSM reset timeout - DMA transaction failures and pending residue conditions - Unexpected interrupt error status - Premature transfer completion with pending TX/RX data Dumping the SE debug registers at the time of failure provides additional hardware context and significantly improves post-mortem analysis of SPI transfer issues without affecting normal operation. Acked-by: Mukesh Kumar Savaliya <mukesh.savaliya@oss.qualcomm.com> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com> Link: https://patch.msgid.link/20260729-add-tracepoints-for-se-reg-dump-v4-2-08bbd63b0ed2@oss.qualcomm.com Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-geni-qcom.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 26e723cfea61..2c657cd990b4 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2017-2018, The Linux foundation. All rights reserved.
+#include <trace/events/qcom_geni_se.h>
+
#define CREATE_TRACE_POINTS
#include <trace/events/qcom_geni_spi.h>
@@ -184,6 +186,7 @@ static void handle_se_timeout(struct spi_controller *spi)
time_left = wait_for_completion_timeout(&mas->abort_done, HZ);
if (!time_left) {
dev_err(mas->dev, "Failed to cancel/abort m_cmd\n");
+ trace_geni_se_regs(se);
/*
* No need for a lock since SPI core has a lock and we never
@@ -201,8 +204,10 @@ reset_if_dma:
writel(1, se->base + SE_DMA_TX_FSM_RST);
spin_unlock_irq(&mas->lock);
time_left = wait_for_completion_timeout(&mas->tx_reset_done, HZ);
- if (!time_left)
+ if (!time_left) {
dev_err(mas->dev, "DMA TX RESET failed\n");
+ trace_geni_se_regs(se);
+ }
}
if (xfer->rx_buf) {
spin_lock_irq(&mas->lock);
@@ -210,8 +215,10 @@ reset_if_dma:
writel(1, se->base + SE_DMA_RX_FSM_RST);
spin_unlock_irq(&mas->lock);
time_left = wait_for_completion_timeout(&mas->rx_reset_done, HZ);
- if (!time_left)
+ if (!time_left) {
dev_err(mas->dev, "DMA RX RESET failed\n");
+ trace_geni_se_regs(se);
+ }
}
} else {
/*
@@ -382,10 +389,12 @@ static void
spi_gsi_callback_result(void *cb, const struct dmaengine_result *result)
{
struct spi_controller *spi = cb;
+ struct spi_geni_master *mas = spi_controller_get_devdata(spi);
spi->cur_msg->status = -EIO;
if (result->result != DMA_TRANS_NOERROR) {
dev_err(&spi->dev, "DMA txn failed: %d\n", result->result);
+ trace_geni_se_regs(&mas->se);
spi_finalize_current_transfer(spi);
return;
}
@@ -395,6 +404,7 @@ spi_gsi_callback_result(void *cb, const struct dmaengine_result *result)
dev_dbg(&spi->dev, "DMA txn completed\n");
} else {
dev_err(&spi->dev, "DMA xfer has pending: %d\n", result->residue);
+ trace_geni_se_regs(&mas->se);
}
spi_finalize_current_transfer(spi);
@@ -941,8 +951,10 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
if (m_irq & (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |
M_RX_FIFO_RD_ERR_EN | M_RX_FIFO_WR_ERR_EN |
- M_TX_FIFO_RD_ERR_EN | M_TX_FIFO_WR_ERR_EN))
+ M_TX_FIFO_RD_ERR_EN | M_TX_FIFO_WR_ERR_EN)) {
dev_warn(mas->dev, "Unexpected IRQ err status %#010x\n", m_irq);
+ trace_geni_se_regs(se);
+ }
spin_lock(&mas->lock);
@@ -971,13 +983,16 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
* weren't written correctly.
*/
if (mas->tx_rem_bytes) {
+ trace_geni_se_regs(se);
writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
dev_err(mas->dev, "Premature done. tx_rem = %d bpw%d\n",
mas->tx_rem_bytes, mas->cur_bits_per_word);
}
- if (mas->rx_rem_bytes)
+ if (mas->rx_rem_bytes) {
dev_err(mas->dev, "Premature done. rx_rem = %d bpw%d\n",
mas->rx_rem_bytes, mas->cur_bits_per_word);
+ trace_geni_se_regs(se);
+ }
} else {
complete(&mas->cs_done);
}