From: Logan Gunthorpe <logang@deltatee.com>
To: dmaengine@vger.kernel.org, Vinod Koul <vkoul@kernel.org>
Cc: "Frank Li" <Frank.li@nxp.com>,
"Christoph Hellwig" <hch@infradead.org>,
"Christophe Jaillet" <christophe.jaillet@wanadoo.fr>,
"Dave Jiang" <dave.jiang@intel.com>,
"Thomas Weißschuh" <linux@weissschuh.net>,
"Kelvin Cao" <kelvin.cao@microchip.com>,
"Logan Gunthorpe" <logang@deltatee.com>
Subject: [PATCH v1 4/5] dmaengine: switchtec-dma: Add pmon sysfs attributes
Date: Tue, 7 Jul 2026 10:20:44 -0600 [thread overview]
Message-ID: <20260707162045.23910-5-logang@deltatee.com> (raw)
In-Reply-To: <20260707162045.23910-1-logang@deltatee.com>
Switchtec hardware exposes some performance monitor registers which
can be used to monitor various statistics of the hardware.
Expose these as a sysfs interface under the switchtec group in a
pmon sub-group.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
drivers/dma/switchtec_dma.c | 199 ++++++++++++++++++++++++++++++++++++
1 file changed, 199 insertions(+)
diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
index 4841134bd7b8..2ac43eb58995 100644
--- a/drivers/dma/switchtec_dma.c
+++ b/drivers/dma/switchtec_dma.c
@@ -12,6 +12,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/iopoll.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include "dmaengine.h"
@@ -91,6 +92,12 @@ struct chan_hw_regs {
#define SE_BUF_LEN_MASK GENMASK_U32(20, 12)
#define SE_THRESH_MASK GENMASK_U32(31, 23)
+#define SWITCHTEC_LAT_SE_FETCH BIT(0)
+#define SWITCHTEC_LAT_VDM BIT(1)
+#define SWITCHTEC_LAT_RD_IMM BIT(2)
+#define SWITCHTEC_LAT_FW_NP BIT(3)
+#define SWITCHTEC_LAT_SE_PROCESS BIT(4)
+
#define SWITCHTEC_CHAN_ENABLE BIT(1)
struct chan_fw_regs {
@@ -1156,8 +1163,200 @@ static struct attribute_group switchtec_config_group = {
.attrs = switchtec_config_attrs,
};
+#define pmon_show(chan, page, field, reader) ({ \
+ struct switchtec_dma_chan *__swdma_chan = \
+ container_of((chan), struct switchtec_dma_chan, dma_chan); \
+ struct chan_fw_regs __iomem *__chan_fw = __swdma_chan->mmio_chan_fw; \
+ u64 __pmon_val = 0; \
+ int __pmon_ret = 0; \
+ \
+ rcu_read_lock(); \
+ if (!rcu_dereference(__swdma_chan->swdma_dev->pdev)) { \
+ __pmon_ret = -ENODEV; \
+ } else { \
+ __pmon_val = reader(&__chan_fw->field); \
+ __pmon_ret = sysfs_emit((page), "0x%llx\n", __pmon_val); \
+ } \
+ rcu_read_unlock(); \
+ __pmon_ret; \
+})
+
+static ssize_t se_count_show(struct dma_chan *chan, char *page)
+{
+ return pmon_show(chan, page, perf_fetched_se_cnt_lo, lo_hi_readq);
+}
+static struct dma_chan_sysfs_entry se_count_attr = __ATTR_RO(se_count);
+
+static ssize_t byte_count_show(struct dma_chan *chan, char *page)
+{
+ return pmon_show(chan, page, perf_byte_cnt_lo, lo_hi_readq);
+}
+static struct dma_chan_sysfs_entry byte_count_attr = __ATTR_RO(byte_count);
+
+static ssize_t se_pending_show(struct dma_chan *chan, char *page)
+{
+ return pmon_show(chan, page, perf_se_pending, readw);
+}
+static struct dma_chan_sysfs_entry se_pending_attr = __ATTR_RO(se_pending);
+
+static ssize_t se_buf_empty_show(struct dma_chan *chan, char *page)
+{
+ return pmon_show(chan, page, perf_se_buf_empty, readw);
+}
+static struct dma_chan_sysfs_entry se_buf_empty_attr = __ATTR_RO(se_buf_empty);
+
+static ssize_t chan_idle_show(struct dma_chan *chan, char *page)
+{
+ return pmon_show(chan, page, perf_chan_idle, readl);
+}
+static struct dma_chan_sysfs_entry chan_idle_attr = __ATTR_RO(chan_idle);
+
+static ssize_t latency_max_show(struct dma_chan *chan, char *page)
+{
+ return pmon_show(chan, page, perf_lat_max, readl);
+}
+static struct dma_chan_sysfs_entry latency_max_attr = __ATTR_RO(latency_max);
+
+static ssize_t latency_min_show(struct dma_chan *chan, char *page)
+{
+ return pmon_show(chan, page, perf_lat_min, readl);
+}
+static struct dma_chan_sysfs_entry latency_min_attr = __ATTR_RO(latency_min);
+
+static ssize_t latency_last_show(struct dma_chan *chan, char *page)
+{
+ return pmon_show(chan, page, perf_lat_last, readl);
+}
+static struct dma_chan_sysfs_entry latency_last_attr = __ATTR_RO(latency_last);
+
+static ssize_t latency_selector_show(struct dma_chan *chan, char *page)
+{
+ struct switchtec_dma_chan *swdma_chan =
+ container_of(chan, struct switchtec_dma_chan, dma_chan);
+ struct chan_fw_regs __iomem *chan_fw = swdma_chan->mmio_chan_fw;
+ u32 lat = 0;
+
+ rcu_read_lock();
+ if (!rcu_dereference(swdma_chan->swdma_dev->pdev)) {
+ rcu_read_unlock();
+ return -ENODEV;
+ }
+
+ lat = readl(&chan_fw->perf_latency_selector);
+ rcu_read_unlock();
+
+ strcat(page, "To select a latency type, write the type number (1 ~ 5) to latency_selector\n\n");
+
+ strcat(page, "Latency Types:\n");
+ strcat(page, "(1) SE Fetch latency");
+ if (lat & SWITCHTEC_LAT_SE_FETCH)
+ strcat(page, " (*)\n");
+ else
+ strcat(page, "\n");
+
+ strcat(page, "(2) VDM latency");
+ if (lat & SWITCHTEC_LAT_VDM)
+ strcat(page, " (*)\n");
+ else
+ strcat(page, "\n");
+
+ strcat(page, "(3) Read Immediate latency");
+ if (lat & SWITCHTEC_LAT_RD_IMM)
+ strcat(page, " (*)\n");
+ else
+ strcat(page, "\n");
+
+ strcat(page, "(4) SE Processing latency");
+ if (lat & SWITCHTEC_LAT_SE_PROCESS)
+ strcat(page, " (*)\n");
+ else
+ strcat(page, "\n");
+
+ strcat(page, "(5) FW NP TLP latency");
+ if (lat & SWITCHTEC_LAT_FW_NP)
+ strcat(page, " (*)\n");
+ else
+ strcat(page, "\n");
+
+ strcat(page, "\n");
+
+ return strlen(page);
+}
+
+static ssize_t latency_selector_store(struct dma_chan *chan, const char *page,
+ size_t count)
+{
+ struct switchtec_dma_chan *swdma_chan =
+ container_of(chan, struct switchtec_dma_chan, dma_chan);
+ struct chan_fw_regs __iomem *chan_fw = swdma_chan->mmio_chan_fw;
+ ssize_t ret = count;
+ int lat_type;
+
+ if (kstrtoint(page, 0, &lat_type) < 0)
+ return -EINVAL;
+
+ switch (lat_type) {
+ case 1:
+ lat_type = SWITCHTEC_LAT_SE_FETCH;
+ break;
+ case 2:
+ lat_type = SWITCHTEC_LAT_VDM;
+ break;
+ case 3:
+ lat_type = SWITCHTEC_LAT_RD_IMM;
+ break;
+ case 4:
+ lat_type = SWITCHTEC_LAT_SE_PROCESS;
+ break;
+ case 5:
+ lat_type = SWITCHTEC_LAT_FW_NP;
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ rcu_read_lock();
+ if (!rcu_dereference(swdma_chan->swdma_dev->pdev)) {
+ ret = -ENODEV;
+ goto err_unlock;
+ }
+
+ if (chan->client_count) {
+ ret = -EBUSY;
+ goto err_unlock;
+ }
+
+ writel(lat_type, &chan_fw->perf_latency_selector);
+
+err_unlock:
+ rcu_read_unlock();
+
+ return ret;
+}
+static struct dma_chan_sysfs_entry
+latency_selector_attr = __ATTR_RW(latency_selector);
+
+static struct attribute *switchtec_pmon_attrs[] = {
+ &se_count_attr.attr,
+ &byte_count_attr.attr,
+ &se_pending_attr.attr,
+ &se_buf_empty_attr.attr,
+ &chan_idle_attr.attr,
+ &latency_max_attr.attr,
+ &latency_min_attr.attr,
+ &latency_last_attr.attr,
+ &latency_selector_attr.attr,
+ NULL,
+};
+
+static struct attribute_group switchtec_pmon_group = {
+ .name = "pmon",
+ .attrs = switchtec_pmon_attrs,
+};
+
static const struct attribute_group *switchtec_groups[] = {
&switchtec_config_group,
+ &switchtec_pmon_group,
NULL,
};
--
2.47.3
next prev parent reply other threads:[~2026-07-07 16:21 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-07 16:20 [PATCH v1 0/5] Add sysfs interface to switchtec-dma Logan Gunthorpe
2026-07-07 16:20 ` [PATCH v1 1/5] dmaengine: add support for custom per-channel sysfs attributes Logan Gunthorpe
2026-07-07 16:54 ` sashiko-bot
2026-07-07 16:20 ` [PATCH v1 2/5] dmaengine: ioatdma: use common channel sysfs attribute creation Logan Gunthorpe
2026-07-07 16:48 ` Dave Jiang
2026-07-07 16:59 ` sashiko-bot
2026-07-07 16:20 ` [PATCH v1 3/5] dmaengine: switchtec-dma: Add config sysfs attributes Logan Gunthorpe
2026-07-07 16:55 ` sashiko-bot
2026-07-07 16:20 ` Logan Gunthorpe [this message]
2026-07-07 16:58 ` [PATCH v1 4/5] dmaengine: switchtec-dma: Add pmon " sashiko-bot
2026-07-07 16:20 ` [PATCH v1 5/5] dmaengine: switchtec-dma: Add PCI1008 device ID Logan Gunthorpe
2026-07-07 16:53 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260707162045.23910-5-logang@deltatee.com \
--to=logang@deltatee.com \
--cc=Frank.li@nxp.com \
--cc=christophe.jaillet@wanadoo.fr \
--cc=dave.jiang@intel.com \
--cc=dmaengine@vger.kernel.org \
--cc=hch@infradead.org \
--cc=kelvin.cao@microchip.com \
--cc=linux@weissschuh.net \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.