summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-mem.c
diff options
context:
space:
mode:
authorRodrigo Vivi <rodrigo.vivi@intel.com>2024-04-02 08:17:13 -0400
committerRodrigo Vivi <rodrigo.vivi@intel.com>2024-04-02 08:17:13 -0400
commit5add703f6acad1c63f8a532b6de56e50d548e904 (patch)
treebe39a82716119cd8b7cf7e2734baf8cd9a80ceb7 /drivers/spi/spi-mem.c
parent71cdfa8cad300caa7afcbba09776bbc8dcfa9e39 (diff)
parent39cd87c4eb2b893354f3b850f916353f2658ae6f (diff)
Merge drm/drm-next into drm-intel-next
Catching up on 6.9-rc2 Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Diffstat (limited to 'drivers/spi/spi-mem.c')
-rw-r--r--drivers/spi/spi-mem.c49
1 files changed, 48 insertions, 1 deletions
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index 2dc8ceb85374..17b8baf749e6 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -297,6 +297,49 @@ static void spi_mem_access_end(struct spi_mem *mem)
pm_runtime_put(ctlr->dev.parent);
}
+static void spi_mem_add_op_stats(struct spi_statistics __percpu *pcpu_stats,
+ const struct spi_mem_op *op, int exec_op_ret)
+{
+ struct spi_statistics *stats;
+ u64 len, l2len;
+
+ get_cpu();
+ stats = this_cpu_ptr(pcpu_stats);
+ u64_stats_update_begin(&stats->syncp);
+
+ /*
+ * We do not have the concept of messages or transfers. Let's consider
+ * that one operation is equivalent to one message and one transfer.
+ */
+ u64_stats_inc(&stats->messages);
+ u64_stats_inc(&stats->transfers);
+
+ /* Use the sum of all lengths as bytes count and histogram value. */
+ len = op->cmd.nbytes + op->addr.nbytes;
+ len += op->dummy.nbytes + op->data.nbytes;
+ u64_stats_add(&stats->bytes, len);
+ l2len = min(fls(len), SPI_STATISTICS_HISTO_SIZE) - 1;
+ u64_stats_inc(&stats->transfer_bytes_histo[l2len]);
+
+ /* Only account for data bytes as transferred bytes. */
+ if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
+ u64_stats_add(&stats->bytes_tx, op->data.nbytes);
+ if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN)
+ u64_stats_add(&stats->bytes_rx, op->data.nbytes);
+
+ /*
+ * A timeout is not an error, following the same behavior as
+ * spi_transfer_one_message().
+ */
+ if (exec_op_ret == -ETIMEDOUT)
+ u64_stats_inc(&stats->timedout);
+ else if (exec_op_ret)
+ u64_stats_inc(&stats->errors);
+
+ u64_stats_update_end(&stats->syncp);
+ put_cpu();
+}
+
/**
* spi_mem_exec_op() - Execute a memory operation
* @mem: the SPI memory
@@ -339,8 +382,12 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
* read path) and expect the core to use the regular SPI
* interface in other cases.
*/
- if (!ret || ret != -ENOTSUPP || ret != -EOPNOTSUPP)
+ if (!ret || (ret != -ENOTSUPP && ret != -EOPNOTSUPP)) {
+ spi_mem_add_op_stats(ctlr->pcpu_statistics, op, ret);
+ spi_mem_add_op_stats(mem->spi->pcpu_statistics, op, ret);
+
return ret;
+ }
}
tmpbufsize = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;