diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 807416b75ecc..a7351f9f3659 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -584,11 +584,13 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) 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; + if (drvdata->enable) { + /* 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 */ @@ -627,11 +629,13 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) spin_lock_irqsave(&drvdata->spinlock, flags); - /* 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) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return -EINVAL; + if (drvdata->enable) { + /* 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) { + spin_unlock_irqrestore(&drvdata->spinlock, flags); + return -EINVAL; + } } /* Re-enable the TMC if need be */ diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 625882bc8b08..94eb30a35488 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1179,6 +1179,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) drvdata->mode = CS_MODE_SYSFS; atomic_inc(csdev->refcnt); } + drvdata->enable = true; out: spin_unlock_irqrestore(&drvdata->spinlock, flags); @@ -1653,6 +1654,11 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev) spin_unlock_irqrestore(&drvdata->spinlock, flags); + /* Free memory outside the spinlock if need be */ + if (drvdata->etr_buf) { + tmc_etr_free_sysfs_buf(drvdata->etr_buf); + drvdata->etr_buf = NULL; + } dev_dbg(&csdev->dev, "TMC-ETR disabled\n"); return 0; } diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 6db954ed1b7d..75cb4e5fa295 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2012,2017,2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2012,2017-2019 The Linux Foundation. All rights reserved. * * Description: CoreSight Trace Memory Controller driver */ @@ -62,11 +62,13 @@ void tmc_flush_and_stop(struct tmc_drvdata *drvdata) void tmc_enable_hw(struct tmc_drvdata *drvdata) { + drvdata->enable = true; writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL); } void tmc_disable_hw(struct tmc_drvdata *drvdata) { + drvdata->enable = false; writel_relaxed(0x0, drvdata->base + TMC_CTL); } @@ -102,6 +104,9 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata) { int ret = 0; + if (!drvdata->enable) + return -EPERM; + switch (drvdata->config_type) { case TMC_CONFIG_TYPE_ETB: case TMC_CONFIG_TYPE_ETF: @@ -330,16 +335,20 @@ static ssize_t buffer_size_store(struct device *dev, unsigned long val; struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); + if (drvdata->enable) { + pr_err("ETR is in use, disable it to change the mem_size\n"); + return -EINVAL; + } /* Only permitted for TMC-ETRs */ if (drvdata->config_type != TMC_CONFIG_TYPE_ETR) return -EPERM; - ret = kstrtoul(buf, 0, &val); if (ret) return ret; /* The buffer size should be page aligned */ if (val & (PAGE_SIZE - 1)) return -EINVAL; + drvdata->size = val; return size; } diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index 0a360ed8275c..dfe1a45e9ea1 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -209,6 +209,7 @@ struct tmc_drvdata { struct etr_buf *perf_buf; struct coresight_csr *csr; const char *csr_name; + bool enable; }; struct etr_buf_operations { diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index cbdd26ebaabb..06bcad51e1ac 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2012, 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012, 2017-2019 The Linux Foundation. All rights reserved. */ #include @@ -263,6 +263,7 @@ static void coresight_disable_sink(struct coresight_device *csdev) if (ret) return; csdev->activated = false; + csdev->enable = false; } static int coresight_enable_link(struct coresight_device *csdev, @@ -962,6 +963,7 @@ static ssize_t enable_source_store(struct device *dev, if (ret) return ret; } else { + atomic_set(csdev->refcnt, 1); coresight_disable(csdev); }