From 50a212ec906f7524620675f0c57357691c26c81f Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 16 Oct 2024 01:20:19 +0000
Subject: [PATCH] 修改GPIO导出默认初始值
---
kernel/drivers/hwtracing/coresight/coresight-tmc-etf.c | 116 +++++++++++++++++++++++++++++++++++++--------------------
1 files changed, 75 insertions(+), 41 deletions(-)
diff --git a/kernel/drivers/hwtracing/coresight/coresight-tmc-etf.c b/kernel/drivers/hwtracing/coresight/coresight-tmc-etf.c
index f0b31c5..e9c2b07 100644
--- a/kernel/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/kernel/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -37,7 +37,7 @@
static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
{
- int rc = coresight_claim_device(drvdata->base);
+ int rc = coresight_claim_device(drvdata->csdev);
if (rc)
return rc;
@@ -50,23 +50,20 @@
{
char *bufp;
u32 read_data, lost;
- int i;
/* Check if the buffer wrapped around. */
lost = readl_relaxed(drvdata->base + TMC_STS) & TMC_STS_FULL;
bufp = drvdata->buf;
drvdata->len = 0;
while (1) {
- for (i = 0; i < drvdata->memwidth; i++) {
- read_data = readl_relaxed(drvdata->base + TMC_RRD);
- if (read_data == 0xFFFFFFFF)
- goto done;
- memcpy(bufp, &read_data, 4);
- bufp += 4;
- drvdata->len += 4;
- }
+ read_data = readl_relaxed(drvdata->base + TMC_RRD);
+ if (read_data == 0xFFFFFFFF)
+ break;
+ memcpy(bufp, &read_data, 4);
+ bufp += 4;
+ drvdata->len += 4;
}
-done:
+
if (lost)
coresight_insert_barrier_packet(drvdata->buf);
return;
@@ -90,8 +87,8 @@
static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
{
- coresight_disclaim_device(drvdata->base);
__tmc_etb_disable_hw(drvdata);
+ coresight_disclaim_device(drvdata->csdev);
}
static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
@@ -112,7 +109,7 @@
static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
{
- int rc = coresight_claim_device(drvdata->base);
+ int rc = coresight_claim_device(drvdata->csdev);
if (rc)
return rc;
@@ -123,11 +120,13 @@
static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
{
+ struct coresight_device *csdev = drvdata->csdev;
+
CS_UNLOCK(drvdata->base);
tmc_flush_and_stop(drvdata);
tmc_disable_hw(drvdata);
- coresight_disclaim_device_unlocked(drvdata->base);
+ coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
}
@@ -226,9 +225,11 @@
static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
{
int ret = 0;
+ pid_t pid;
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct perf_output_handle *handle = data;
+ struct cs_buffers *buf = etm_perf_sink_config(handle);
spin_lock_irqsave(&drvdata->spinlock, flags);
do {
@@ -236,18 +237,39 @@
if (drvdata->reading)
break;
/*
- * In Perf mode there can be only one writer per sink. There
- * is also no need to continue if the ETB/ETF is already
- * operated from sysFS.
+ * No need to continue if the ETB/ETF is already operated
+ * from sysFS.
*/
- if (drvdata->mode != CS_MODE_DISABLED)
+ if (drvdata->mode == CS_MODE_SYSFS) {
+ ret = -EBUSY;
break;
+ }
+
+ /* Get a handle on the pid of the process to monitor */
+ pid = buf->pid;
+
+ if (drvdata->pid != -1 && drvdata->pid != pid) {
+ ret = -EBUSY;
+ break;
+ }
ret = tmc_set_etf_buffer(csdev, handle);
if (ret)
break;
+
+ /*
+ * No HW configuration is needed if the sink is already in
+ * use for this session.
+ */
+ if (drvdata->pid == pid) {
+ atomic_inc(csdev->refcnt);
+ break;
+ }
+
ret = tmc_etb_enable_hw(drvdata);
if (!ret) {
+ /* Associate with monitored process. */
+ drvdata->pid = pid;
drvdata->mode = CS_MODE_PERF;
atomic_inc(csdev->refcnt);
}
@@ -261,7 +283,6 @@
u32 mode, void *data)
{
int ret;
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
switch (mode) {
case CS_MODE_SYSFS:
@@ -279,7 +300,7 @@
if (ret)
return ret;
- dev_dbg(drvdata->dev, "TMC-ETB/ETF enabled\n");
+ dev_dbg(&csdev->dev, "TMC-ETB/ETF enabled\n");
return 0;
}
@@ -303,11 +324,13 @@
/* Complain if we (somehow) got out of sync */
WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED);
tmc_etb_disable_hw(drvdata);
+ /* Dissociate from monitored process. */
+ drvdata->pid = -1;
drvdata->mode = CS_MODE_DISABLED;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
- dev_dbg(drvdata->dev, "TMC-ETB/ETF disabled\n");
+ dev_dbg(&csdev->dev, "TMC-ETB/ETF disabled\n");
return 0;
}
@@ -337,7 +360,7 @@
spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (first_enable)
- dev_dbg(drvdata->dev, "TMC-ETF enabled\n");
+ dev_dbg(&csdev->dev, "TMC-ETF enabled\n");
return ret;
}
@@ -362,23 +385,24 @@
spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (last_disable)
- dev_dbg(drvdata->dev, "TMC-ETF disabled\n");
+ dev_dbg(&csdev->dev, "TMC-ETF disabled\n");
}
static void *tmc_alloc_etf_buffer(struct coresight_device *csdev,
struct perf_event *event, void **pages,
int nr_pages, bool overwrite)
{
- int node, cpu = event->cpu;
+ int node;
struct cs_buffers *buf;
- node = (cpu == -1) ? NUMA_NO_NODE : cpu_to_node(cpu);
+ node = (event->cpu == -1) ? NUMA_NO_NODE : cpu_to_node(event->cpu);
/* Allocate memory structure for interaction with Perf */
buf = kzalloc_node(sizeof(struct cs_buffers), GFP_KERNEL, node);
if (!buf)
return NULL;
+ buf->pid = task_pid_nr(event->owner);
buf->snapshot = overwrite;
buf->nr_pages = nr_pages;
buf->data_pages = pages;
@@ -404,7 +428,7 @@
return -EINVAL;
/* wrap head around to the amount of space we have */
- head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1);
+ head = handle->head & (((unsigned long)buf->nr_pages << PAGE_SHIFT) - 1);
/* find the page to write to */
buf->cur = head / PAGE_SIZE;
@@ -427,7 +451,7 @@
u32 *buf_ptr;
u64 read_ptr, write_ptr;
u32 status;
- unsigned long offset, to_read, flags;
+ unsigned long offset, to_read = 0, flags;
struct cs_buffers *buf = sink_config;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -439,6 +463,11 @@
return 0;
spin_lock_irqsave(&drvdata->spinlock, flags);
+
+ /* Don't do anything if another tracer is using this sink */
+ if (atomic_read(csdev->refcnt) != 1)
+ goto out;
+
CS_UNLOCK(drvdata->base);
tmc_flush_and_stop(drvdata);
@@ -494,7 +523,7 @@
cur = buf->cur;
offset = buf->offset;
- barrier = barrier_pkt;
+ barrier = coresight_barrier_pkt;
/* for every byte to read */
for (i = 0; i < to_read; i += 4) {
@@ -515,12 +544,17 @@
}
}
- /* In snapshot mode we have to update the head */
- if (buf->snapshot) {
- handle->head = (cur * PAGE_SIZE) + offset;
- to_read = buf->nr_pages << PAGE_SHIFT;
- }
+ /*
+ * In snapshot mode we simply increment the head by the number of byte
+ * that were written. User space function cs_etm_find_snapshot() will
+ * figure out how many bytes to get from the AUX buffer based on the
+ * position of the head.
+ */
+ if (buf->snapshot)
+ handle->head += to_read;
+
CS_LOCK(drvdata->base);
+out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return to_read;
@@ -566,13 +600,6 @@
goto out;
}
- /* There is no point in reading a TMC in HW FIFO mode */
- mode = readl_relaxed(drvdata->base + TMC_MODE);
- if (mode != TMC_MODE_CIRCULAR_BUFFER) {
- ret = -EINVAL;
- goto out;
- }
-
/* Don't interfere if operated from Perf */
if (drvdata->mode == CS_MODE_PERF) {
ret = -EINVAL;
@@ -586,8 +613,15 @@
}
/* Disable the TMC if need be */
- if (drvdata->mode == CS_MODE_SYSFS)
+ if (drvdata->mode == CS_MODE_SYSFS) {
+ /* There is no point in reading a TMC in HW FIFO mode */
+ mode = readl_relaxed(drvdata->base + TMC_MODE);
+ if (mode != TMC_MODE_CIRCULAR_BUFFER) {
+ ret = -EINVAL;
+ goto out;
+ }
__tmc_etb_disable_hw(drvdata);
+ }
drvdata->reading = true;
out:
--
Gitblit v1.6.2