aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwtracing
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwtracing')
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x-sysfs.c21
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x.c1
-rw-r--r--drivers/hwtracing/coresight/coresight-priv.h3
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-etf.c29
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-etr.c80
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc.c21
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc.h99
-rw-r--r--drivers/hwtracing/coresight/coresight.c25
-rw-r--r--drivers/hwtracing/intel_th/core.c36
-rw-r--r--drivers/hwtracing/intel_th/gth.c3
-rw-r--r--drivers/hwtracing/intel_th/intel_th.h2
-rw-r--r--drivers/hwtracing/intel_th/msu.c6
-rw-r--r--drivers/hwtracing/intel_th/pci.c50
-rw-r--r--drivers/hwtracing/intel_th/sth.c4
-rw-r--r--drivers/hwtracing/stm/p_sys-t.c6
-rw-r--r--drivers/hwtracing/stm/policy.c4
17 files changed, 334 insertions, 58 deletions
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 1ef098ff27c3..6558dd7652a5 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -223,7 +223,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
id = (u32)event->attr.config2;
sink = coresight_get_sink_by_id(id);
} else {
- sink = coresight_get_enabled_sink(true);
+ sink = coresight_get_enabled_sink(NULL, true);
}
if (!sink)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index a0365e23678e..f5fb1e7a9c17 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -655,10 +655,13 @@ static ssize_t cyc_threshold_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
+
+ /* mask off max threshold before checking min value */
+ val &= ETM_CYC_THRESHOLD_MASK;
if (val < drvdata->ccitmin)
return -EINVAL;
- config->ccctlr = val & ETM_CYC_THRESHOLD_MASK;
+ config->ccctlr = val;
return size;
}
static DEVICE_ATTR_RW(cyc_threshold);
@@ -689,14 +692,16 @@ static ssize_t bb_ctrl_store(struct device *dev,
return -EINVAL;
if (!drvdata->nr_addr_cmp)
return -EINVAL;
+
/*
- * Bit[7:0] selects which address range comparator is used for
- * branch broadcast control.
+ * Bit[8] controls include(1) / exclude(0), bits[0-7] select
+ * individual range comparators. If include then at least 1
+ * range must be selected.
*/
- if (BMVAL(val, 0, 7) > drvdata->nr_addr_cmp)
+ if ((val & BIT(8)) && (BMVAL(val, 0, 7) == 0))
return -EINVAL;
- config->bb_ctrl = val;
+ config->bb_ctrl = val & GENMASK(8, 0);
return size;
}
static DEVICE_ATTR_RW(bb_ctrl);
@@ -1329,8 +1334,8 @@ static ssize_t seq_event_store(struct device *dev,
spin_lock(&drvdata->spinlock);
idx = config->seq_idx;
- /* RST, bits[7:0] */
- config->seq_ctrl[idx] = val & 0xFF;
+ /* Seq control has two masks B[15:8] F[7:0] */
+ config->seq_ctrl[idx] = val & 0xFFFF;
spin_unlock(&drvdata->spinlock);
return size;
}
@@ -1585,7 +1590,7 @@ static ssize_t res_ctrl_store(struct device *dev,
if (idx % 2 != 0)
/* PAIRINV, bit[21] */
val &= ~BIT(21);
- config->res_ctrl[idx] = val;
+ config->res_ctrl[idx] = val & GENMASK(21, 0);
spin_unlock(&drvdata->spinlock);
return size;
}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 27e047ebb0ba..af4dfa955f7d 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -1202,6 +1202,7 @@ static const struct amba_id etm4_ids[] = {
CS_AMBA_ID(0x000bb95a), /* Cortex-A72 */
CS_AMBA_ID(0x000bb959), /* Cortex-A73 */
CS_AMBA_UCI_ID(0x000bb9da, uci_id_etm4), /* Cortex-A35 */
+ CS_AMBA_ID(0x000cc210), /* Marvell-OcteonTx-CN9xxx */
{},
};
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index e0684d06e9ee..83325b0f86f0 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -147,7 +147,8 @@ static inline void coresight_write_reg_pair(void __iomem *addr, u64 val,
void coresight_disable_path(struct list_head *path);
int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data);
struct coresight_device *coresight_get_sink(struct list_head *path);
-struct coresight_device *coresight_get_enabled_sink(bool reset);
+struct coresight_device *coresight_get_enabled_sink(struct coresight_device *cs,
+ bool reset);
struct coresight_device *coresight_get_sink_by_id(u32 id);
struct list_head *coresight_build_path(struct coresight_device *csdev,
struct coresight_device *sink);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 8de109de171f..e43e9ef0617c 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -592,13 +592,6 @@ 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;
- }
-
/* Don't interfere if operated from Perf */
if (drvdata->mode == CS_MODE_PERF) {
ret = -EINVAL;
@@ -612,8 +605,15 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
}
/* 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:
@@ -635,15 +635,14 @@ 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;
- }
-
/* Re-enable the TMC if need be */
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) {
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return -EINVAL;
+ }
/*
* The trace run will continue with the same allocated trace
* buffer. As such zero-out the buffer so that we don't end
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 9f293b9dce8c..1ed2ea51f222 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -16,6 +16,7 @@
#include <linux/vmalloc.h>
#include "coresight-catu.h"
#include "coresight-etm-perf.h"
+#include <linux/arm-smccc.h>
#include "coresight-priv.h"
#include "coresight-tmc.h"
@@ -590,6 +591,9 @@ static int tmc_etr_alloc_flat_buf(struct tmc_drvdata *drvdata,
void **pages)
{
struct etr_flat_buf *flat_buf;
+ dma_addr_t s_paddr = 0;
+ int buff_sec_mapped = 0;
+ int ret;
/* We cannot reuse existing pages for flat buf */
if (pages)
@@ -606,12 +610,44 @@ static int tmc_etr_alloc_flat_buf(struct tmc_drvdata *drvdata,
return -ENOMEM;
}
+ if (!(drvdata->etr_options & CORESIGHT_OPTS_SECURE_BUFF))
+ goto skip_secure_buffer;
+
+ /* Register driver allocated dma buffer for necessary
+ * mapping in the secure world
+ */
+ if (tmc_register_drvbuf(drvdata, flat_buf->daddr, etr_buf->size)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ buff_sec_mapped = 1;
+
+ /* Allocate secure trace buffer */
+ if (tmc_alloc_secbuf(drvdata, etr_buf->size, &s_paddr)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+skip_secure_buffer:
flat_buf->size = etr_buf->size;
flat_buf->dev = drvdata->dev;
etr_buf->hwaddr = flat_buf->daddr;
+ etr_buf->s_paddr= s_paddr;
etr_buf->mode = ETR_MODE_FLAT;
etr_buf->private = flat_buf;
return 0;
+
+err:
+ kfree(flat_buf);
+ dma_free_coherent(drvdata->dev, etr_buf->size, flat_buf->vaddr,
+ flat_buf->daddr);
+ if (buff_sec_mapped)
+ tmc_unregister_drvbuf(drvdata, flat_buf->daddr,
+ etr_buf->size);
+ if (s_paddr)
+ tmc_free_secbuf(drvdata, s_paddr, etr_buf->size);
+
+ return ret;
}
static void tmc_etr_free_flat_buf(struct etr_buf *etr_buf)
@@ -937,10 +973,17 @@ static void __tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
CS_UNLOCK(drvdata->base);
+ if (drvdata->etr_options & CORESIGHT_OPTS_RESET_CTL_REG)
+ tmc_disable_hw(drvdata);
+
/* Wait for TMCSReady bit to be set */
tmc_wait_for_tmcready(drvdata);
writel_relaxed(etr_buf->size / 4, drvdata->base + TMC_RSZ);
+ if (drvdata && CORESIGHT_OPTS_BUFFSIZE_8BX)
+ writel_relaxed(etr_buf->size / 8, drvdata->base + TMC_RSZ);
+ else
+ writel_relaxed(etr_buf->size / 4, drvdata->base + TMC_RSZ);
writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
@@ -957,7 +1000,10 @@ static void __tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
axictl |= TMC_AXICTL_SCT_GAT_MODE;
writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
- tmc_write_dba(drvdata, etr_buf->hwaddr);
+ if (drvdata->etr_options & CORESIGHT_OPTS_SECURE_BUFF)
+ tmc_write_dba(drvdata, etr_buf->s_paddr);
+ else
+ tmc_write_dba(drvdata, etr_buf->hwaddr);
/*
* If the TMC pointers must be programmed before the session,
* we have to set it properly (i.e, RRP/RWP to base address and
@@ -965,7 +1011,10 @@ static void __tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
*/
if (tmc_etr_has_cap(drvdata, TMC_ETR_SAVE_RESTORE)) {
tmc_write_rrp(drvdata, etr_buf->hwaddr);
- tmc_write_rwp(drvdata, etr_buf->hwaddr);
+ if (drvdata->etr_options & CORESIGHT_OPTS_SECURE_BUFF)
+ tmc_write_rwp(drvdata, etr_buf->s_paddr);
+ else
+ tmc_write_rwp(drvdata, etr_buf->hwaddr);
sts = readl_relaxed(drvdata->base + TMC_STS) & ~TMC_STS_FULL;
writel_relaxed(sts, drvdata->base + TMC_STS);
}
@@ -1476,7 +1525,7 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
goto out;
}
- if (WARN_ON(drvdata->perf_data != etr_perf)) {
+ if (WARN_ON(drvdata->perf_buf != etr_buf)) {
lost = true;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
goto out;
@@ -1488,8 +1537,6 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
tmc_sync_etr_buf(drvdata);
CS_LOCK(drvdata->base);
- /* Reset perf specific data */
- drvdata->perf_data = NULL;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
size = etr_buf->len;
@@ -1543,7 +1590,6 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
}
etr_perf->head = PERF_IDX2OFF(handle->head, etr_perf);
- drvdata->perf_data = etr_perf;
/*
* No HW configuration is needed if the sink is already in
@@ -1559,6 +1605,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
/* Associate with monitored process. */
drvdata->pid = pid;
drvdata->mode = CS_MODE_PERF;
+ drvdata->perf_buf = etr_perf->etr_buf;
atomic_inc(csdev->refcnt);
}
@@ -1604,6 +1651,8 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
/* Dissociate from monitored process. */
drvdata->pid = -1;
drvdata->mode = CS_MODE_DISABLED;
+ /* Reset perf specific data */
+ drvdata->perf_buf = NULL;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -1696,3 +1745,22 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
return 0;
}
+
+int tmc_copy_secure_buffer(struct tmc_drvdata *drvdata,
+ char *bufp, size_t len)
+{
+ struct arm_smccc_res res;
+ uint64_t offset;
+ char *vaddr;
+ struct etr_buf *etr_buf = drvdata->etr_buf;
+
+ tmc_etr_buf_get_data(etr_buf, 0, 0, &vaddr);
+ offset = bufp - vaddr;
+
+ arm_smccc_smc(OCTEONTX_TRC_COPY_TO_DRVBUF, etr_buf->hwaddr + offset,
+ etr_buf->s_paddr + offset, len, 0, 0, 0, 0, &res);
+ if (res.a0 != SMCCC_RET_SUCCESS)
+ return -EFAULT;
+
+ return 0;
+}
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 3f718729d741..17759762abdc 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -151,6 +151,10 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
if (actual <= 0)
return 0;
+ if ((drvdata->etr_options & CORESIGHT_OPTS_SECURE_BUFF) &&
+ tmc_copy_secure_buffer(drvdata, bufp, len))
+ return -EFAULT;
+
if (copy_to_user(data, bufp, actual)) {
dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
return -EFAULT;
@@ -419,11 +423,21 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
spin_lock_init(&drvdata->spinlock);
+ drvdata->cpu = pdata ? pdata->cpu : 0;
+
+ /* Enable options for Silicon issues */
+ if (id->id == OCTEONTX_CN9XXX_ETR)
+ drvdata->etr_options = CORESIGHT_OPTS_BUFFSIZE_8BX |
+ CORESIGHT_OPTS_SECURE_BUFF |
+ CORESIGHT_OPTS_RESET_CTL_REG;
+
devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
drvdata->config_type = BMVAL(devid, 6, 7);
drvdata->memwidth = tmc_get_memwidth(devid);
/* This device is not associated with a session */
drvdata->pid = -1;
+ drvdata->formatter_en = !(readl_relaxed(drvdata->base + TMC_FFSR) &
+ TMC_FFSR_FT_NOT_PRESENT);
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
if (np)
@@ -432,6 +446,11 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
&drvdata->size);
if (ret)
drvdata->size = SZ_1M;
+
+ /* Cache locked buffer */
+ if (np)
+ drvdata->cache_lock_en = of_property_read_bool(np,
+ "cache-lock");
} else {
drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
}
@@ -494,6 +513,8 @@ static const struct amba_id tmc_ids[] = {
CS_AMBA_ID(0x000bb9e9),
/* Coresight SoC 600 TMC-ETF */
CS_AMBA_ID(0x000bb9ea),
+ /* Marvell OcteonTx CN9xxx */
+ CS_AMBA_ID_DATA(OCTEONTX_CN9XXX_ETR, (unsigned long)OCTEONTX_CN9XXX_ETR_CAPS),
{ 0, 0},
};
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 503f1b3a3741..46118e93f1a9 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -12,6 +12,7 @@
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/refcount.h>
+#include <linux/arm-smccc.h>
#define TMC_RSZ 0x004
#define TMC_STS 0x00c
@@ -73,6 +74,9 @@
#define TMC_AXICTL_AXCACHE_OS (0xf << 2)
#define TMC_AXICTL_ARCACHE_OS (0xf << 16)
+/* TMC_FFSR - 0x300 */
+#define TMC_FFSR_FT_NOT_PRESENT BIT(4)
+
/* TMC_FFCR - 0x304 */
#define TMC_FFCR_FLUSHMAN_BIT 6
#define TMC_FFCR_EN_FMT BIT(0)
@@ -126,6 +130,33 @@ enum tmc_mem_intf_width {
#define CORESIGHT_SOC_600_ETR_CAPS \
(TMC_ETR_SAVE_RESTORE | TMC_ETR_AXI_ARCACHE)
+/* Marvell OcteonTx CN9xxx TMC-ETR unadvertised capabilities */
+#define OCTEONTX_CN9XXX_ETR_CAPS \
+ (TMC_ETR_SAVE_RESTORE)
+
+/* Marvell OcteonTx CN9xxx device */
+#define OCTEONTX_CN9XXX_ETR 0x000cc213
+
+/* Marvell OcteonTx CN9xxx HW issues */
+#define CORESIGHT_OPTS_BUFFSIZE_8BX (0x1U << 0) /* 8 byte size multiplier */
+#define CORESIGHT_OPTS_SECURE_BUFF (0x1U << 1) /* Trace buffer is Secure */
+#define CORESIGHT_OPTS_RESET_CTL_REG (0x1U << 2) /* Reset CTL on reset */
+
+/* SMC call ids for managing the secure trace buffer */
+
+/* Args: x1 - size, x2 - cpu, x3 - llc lock flag
+ * Returns: x0 - status, x1 - secure buffer address
+ */
+#define OCTEONTX_TRC_ALLOC_SBUF 0xc2000c05
+/* Args: x1 - non secure buffer address, x2 - size */
+#define OCTEONTX_TRC_REGISTER_DRVBUF 0xc2000c06
+/* Args: x1 - dst(non secure), x2 - src(secure), x3 - size */
+#define OCTEONTX_TRC_COPY_TO_DRVBUF 0xc2000c07
+/* Args: x1 - secure buffer address, x2 - size */
+#define OCTEONTX_TRC_FREE_SBUF 0xc2000c08
+/* Args: x1 - non secure buffer address, x2 - size */
+#define OCTEONTX_TRC_UNREGISTER_DRVBUF 0xc2000c09
+
enum etr_mode {
ETR_MODE_FLAT, /* Uses contiguous flat buffer */
ETR_MODE_ETR_SG, /* Uses in-built TMC ETR SG mechanism */
@@ -141,6 +172,7 @@ struct etr_buf_operations;
* @full : Trace data overflow
* @size : Size of the buffer.
* @hwaddr : Address to be programmed in the TMC:DBA{LO,HI}
+ * @s_paddr : Secure trace buffer
* @offset : Offset of the trace data in the buffer for consumption.
* @len : Available trace data @buf (may round up to the beginning).
* @ops : ETR buffer operations for the mode.
@@ -152,6 +184,7 @@ struct etr_buf {
bool full;
ssize_t size;
dma_addr_t hwaddr;
+ dma_addr_t s_paddr;
unsigned long offset;
s64 len;
const struct etr_buf_operations *ops;
@@ -164,13 +197,14 @@ struct etr_buf {
* @dev: the device entity associated to this component.
* @csdev: component vitals needed by the framework.
* @miscdev: specifics to handle "/dev/xyz.tmc" entry.
- * @spinlock: only one at a time pls.
- * @pid: Process ID of the process being monitored by the session
+ * @spinlock: only one at a time pls. * @pid: Process ID of the process being monitored by the session
* that is using this component.
* @buf: Snapshot of the trace data for ETF/ETB.
* @etr_buf: details of buffer used in TMC-ETR
* @len: size of the available trace for ETF/ETB.
* @size: trace buffer size for this TMC (common for all modes).
+ * @formatter_en: Formatter enable/disable status
+ * @cache_lock_en: Cache lock status
* @mode: how this TMC is being used.
* @config_type: TMC variant, must be of type @tmc_config_type.
* @memwidth: width of the memory interface databus, in bytes.
@@ -179,8 +213,10 @@ struct etr_buf {
* device configuration register (DEVID)
* @idr: Holds etr_bufs allocated for this ETR.
* @idr_mutex: Access serialisation for idr.
- * @perf_data: PERF buffer for ETR.
- * @sysfs_data: SYSFS buffer for ETR.
+ * @sysfs_buf: SYSFS buffer for ETR.
+ * @perf_buf: PERF buffer for ETR.
+ * @etr_options: Bitmask of options to manage Silicon issues
+ * @cpu: CPU id this component is associated with
*/
struct tmc_drvdata {
void __iomem *base;
@@ -194,6 +230,8 @@ struct tmc_drvdata {
char *buf; /* TMC ETB */
struct etr_buf *etr_buf; /* TMC ETR */
};
+ bool formatter_en;
+ bool cache_lock_en;
u32 len;
u32 size;
u32 mode;
@@ -205,6 +243,9 @@ struct tmc_drvdata {
struct mutex idr_mutex;
struct etr_buf *sysfs_buf;
void *perf_data;
+ u32 etr_options;
+ int cpu;
+ struct etr_buf *perf_buf;
};
struct etr_buf_operations {
@@ -322,4 +363,54 @@ tmc_sg_table_buf_size(struct tmc_sg_table *sg_table)
struct coresight_device *tmc_etr_get_catu_device(struct tmc_drvdata *drvdata);
+static inline int tmc_alloc_secbuf(struct tmc_drvdata *drvdata,
+ size_t len, dma_addr_t *s_paddr)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(OCTEONTX_TRC_ALLOC_SBUF, len, drvdata->cpu,
+ drvdata->cache_lock_en, 0, 0, 0, 0, &res);
+ if (res.a0 != SMCCC_RET_SUCCESS)
+ return -EFAULT;
+
+ *s_paddr = res.a1;
+ return 0;
+}
+
+static inline int tmc_free_secbuf(struct tmc_drvdata *drvdata,
+ dma_addr_t s_paddr, size_t len)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(OCTEONTX_TRC_FREE_SBUF, s_paddr, len,
+ 0, 0, 0, 0, 0, &res);
+ return 0;
+}
+
+static inline int tmc_register_drvbuf(struct tmc_drvdata *drvdata,
+ dma_addr_t paddr, size_t len)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(OCTEONTX_TRC_REGISTER_DRVBUF, paddr, len,
+ 0, 0, 0, 0, 0, &res);
+ if (res.a0 != SMCCC_RET_SUCCESS)
+ return -EFAULT;
+
+ return 0;
+}
+
+static inline int tmc_unregister_drvbuf(struct tmc_drvdata *drvdata,
+ dma_addr_t paddr, size_t len)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(OCTEONTX_TRC_UNREGISTER_DRVBUF, paddr, len,
+ 0, 0, 0, 0, 0, &res);
+ return 0;
+
+}
+
+int tmc_copy_secure_buffer(struct tmc_drvdata *drvdata,
+ char *bufp, size_t len);
#endif
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 4b130281236a..1fbf7e125b23 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -524,6 +524,7 @@ static int coresight_enabled_sink(struct device *dev, void *data)
/**
* coresight_get_enabled_sink - returns the first enabled sink found on the bus
+ * In case the child port is a single source ETR, returns the child port as sink
* @deactivate: Whether the 'enable_sink' flag should be reset
*
* When operated from perf the deactivate parameter should be set to 'true'.
@@ -534,10 +535,30 @@ static int coresight_enabled_sink(struct device *dev, void *data)
* parameter should be set to 'false', hence mandating users to explicitly
* clear the flag.
*/
-struct coresight_device *coresight_get_enabled_sink(bool deactivate)
+struct coresight_device *coresight_get_enabled_sink(struct coresight_device *s,
+ bool deactivate)
{
+ struct coresight_device *child;
struct device *dev = NULL;
+ if (s == NULL)
+ goto skip_single_source;
+
+ /* If the connected port is an ETR with single trace source,
+ * nothing to search further.
+ */
+ child = s->conns[0].child_dev;
+ if (s->nr_outport == 1 &&
+ child->type == CORESIGHT_DEV_TYPE_SINK &&
+ child->subtype.sink_subtype == CORESIGHT_DEV_SUBTYPE_SINK_BUFFER &&
+ child->nr_inport == 1 &&
+ child->activated) {
+ if (deactivate)
+ child->activated = false;
+ return child;
+ }
+
+skip_single_source:
dev = bus_find_device(&coresight_bustype, NULL, &deactivate,
coresight_enabled_sink);
@@ -782,7 +803,7 @@ int coresight_enable(struct coresight_device *csdev)
* Search for a valid sink for this session but don't reset the
* "enable_sink" flag in sysFS. Users get to do that explicitly.
*/
- sink = coresight_get_enabled_sink(false);
+ sink = coresight_get_enabled_sink(csdev, false);
if (!sink) {
ret = -EINVAL;
goto out;
diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index 033dce563c99..9ea1d8f54465 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -649,10 +649,8 @@ intel_th_subdevice_alloc(struct intel_th *th,
}
err = intel_th_device_add_resources(thdev, res, subdev->nres);
- if (err) {
- put_device(&thdev->dev);
+ if (err)
goto fail_put_device;
- }
if (subdev->type == INTEL_TH_OUTPUT) {
if (subdev->mknode)
@@ -667,10 +665,8 @@ intel_th_subdevice_alloc(struct intel_th *th,
}
err = device_add(&thdev->dev);
- if (err) {
- put_device(&thdev->dev);
+ if (err)
goto fail_free_res;
- }
/* need switch driver to be loaded to enumerate the rest */
if (subdev->type == INTEL_TH_SWITCH && !req) {
@@ -847,9 +843,6 @@ static irqreturn_t intel_th_irq(int irq, void *data)
ret |= d->irq(th->thdev[i]);
}
- if (ret == IRQ_NONE)
- pr_warn_ratelimited("nobody cared for irq\n");
-
return ret;
}
@@ -900,6 +893,7 @@ intel_th_alloc(struct device *dev, struct intel_th_drvdata *drvdata,
if (th->irq == -1)
th->irq = devres[r].start;
+ th->num_irqs++;
break;
default:
dev_warn(dev, "Unknown resource type %lx\n",
@@ -953,6 +947,9 @@ void intel_th_free(struct intel_th *th)
th->num_thdevs = 0;
+ for (i = 0; i < th->num_irqs; i++)
+ devm_free_irq(th->dev, th->irq + i, th);
+
pm_runtime_get_sync(th->dev);
pm_runtime_forbid(th->dev);
@@ -1033,15 +1030,30 @@ int intel_th_set_output(struct intel_th_device *thdev,
{
struct intel_th_device *hub = to_intel_th_hub(thdev);
struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
+ int ret;
/* In host mode, this is up to the external debugger, do nothing. */
if (hub->host_mode)
return 0;
- if (!hubdrv->set_output)
- return -ENOTSUPP;
+ /*
+ * hub is instantiated together with the source device that
+ * calls here, so guaranteed to be present.
+ */
+ hubdrv = to_intel_th_driver(hub->dev.driver);
+ if (!hubdrv || !try_module_get(hubdrv->driver.owner))
+ return -EINVAL;
+
+ if (!hubdrv->set_output) {
+ ret = -ENOTSUPP;
+ goto out;
+ }
- return hubdrv->set_output(hub, master);
+ ret = hubdrv->set_output(hub, master);
+
+out:
+ module_put(hubdrv->driver.owner);
+ return ret;
}
EXPORT_SYMBOL_GPL(intel_th_set_output);
diff --git a/drivers/hwtracing/intel_th/gth.c b/drivers/hwtracing/intel_th/gth.c
index fa9d34af87ac..f72803a02391 100644
--- a/drivers/hwtracing/intel_th/gth.c
+++ b/drivers/hwtracing/intel_th/gth.c
@@ -626,6 +626,9 @@ static void intel_th_gth_switch(struct intel_th_device *thdev,
if (!count)
dev_dbg(&thdev->dev, "timeout waiting for CTS Trigger\n");
+ /* De-assert the trigger */
+ iowrite32(0, gth->base + REG_CTS_CTL);
+
intel_th_gth_stop(gth, output, false);
intel_th_gth_start(gth, output);
}
diff --git a/drivers/hwtracing/intel_th/intel_th.h b/drivers/hwtracing/intel_th/intel_th.h
index 0df480072b6c..6f4f5486fe6d 100644
--- a/drivers/hwtracing/intel_th/intel_th.h
+++ b/drivers/hwtracing/intel_th/intel_th.h
@@ -261,6 +261,7 @@ enum th_mmio_idx {
* @num_thdevs: number of devices in the @thdev array
* @num_resources: number of resources in the @resource array
* @irq: irq number
+ * @num_irqs: number of IRQs is use
* @id: this Intel TH controller's device ID in the system
* @major: device node major for output devices
*/
@@ -277,6 +278,7 @@ struct intel_th {
unsigned int num_thdevs;
unsigned int num_resources;
int irq;
+ int num_irqs;
int id;
int major;
diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c
index cfd48c81b9d9..e73ed7ac0cea 100644
--- a/drivers/hwtracing/intel_th/msu.c
+++ b/drivers/hwtracing/intel_th/msu.c
@@ -535,7 +535,7 @@ static int msc_configure(struct msc *msc)
lockdep_assert_held(&msc->buf_mutex);
if (msc->mode > MSC_MODE_MULTI)
- return -ENOTSUPP;
+ return -EINVAL;
if (msc->mode == MSC_MODE_MULTI)
msc_buffer_clear_hw_header(msc);
@@ -1029,7 +1029,7 @@ static int msc_buffer_alloc(struct msc *msc, unsigned long *nr_pages,
} else if (msc->mode == MSC_MODE_MULTI) {
ret = msc_buffer_multi_alloc(msc, nr_pages, nr_wins);
} else {
- ret = -ENOTSUPP;
+ ret = -EINVAL;
}
if (!ret) {
@@ -1252,7 +1252,7 @@ static ssize_t intel_th_msc_read(struct file *file, char __user *buf,
if (ret >= 0)
*ppos = iter->offset;
} else {
- ret = -ENOTSUPP;
+ ret = -EINVAL;
}
put_count:
diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
index 91dfeba62485..0d26484d6795 100644
--- a/drivers/hwtracing/intel_th/pci.c
+++ b/drivers/hwtracing/intel_th/pci.c
@@ -200,15 +200,65 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
{
+ /* Comet Lake PCH */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x06a6),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
+ {
+ /* Comet Lake PCH-V */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa3a6),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
+ {
/* Ice Lake NNPI */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x45c5),
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
{
+ /* Ice Lake CPU */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8a29),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
+ {
+ /* Tiger Lake CPU */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9a33),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
+ {
/* Tiger Lake PCH */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa0a6),
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
+ {
+ /* Tiger Lake PCH-H */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x43a6),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
+ {
+ /* Jasper Lake PCH */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4da6),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
+ {
+ /* Jasper Lake CPU */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4e29),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
+ {
+ /* Elkhart Lake CPU */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4529),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
+ {
+ /* Elkhart Lake */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4b26),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
+ {
+ /* Emmitsburg PCH */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1bcc),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
{ 0 },
};
diff --git a/drivers/hwtracing/intel_th/sth.c b/drivers/hwtracing/intel_th/sth.c
index 3a1f4e650378..a1529f571491 100644
--- a/drivers/hwtracing/intel_th/sth.c
+++ b/drivers/hwtracing/intel_th/sth.c
@@ -161,9 +161,7 @@ static int sth_stm_link(struct stm_data *stm_data, unsigned int master,
{
struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
- intel_th_set_output(to_intel_th_device(sth->dev), master);
-
- return 0;
+ return intel_th_set_output(to_intel_th_device(sth->dev), master);
}
static int intel_th_sw_init(struct sth_device *sth)
diff --git a/drivers/hwtracing/stm/p_sys-t.c b/drivers/hwtracing/stm/p_sys-t.c
index b178a5495b67..360b5c03df95 100644
--- a/drivers/hwtracing/stm/p_sys-t.c
+++ b/drivers/hwtracing/stm/p_sys-t.c
@@ -238,7 +238,7 @@ static struct configfs_attribute *sys_t_policy_attrs[] = {
static inline bool sys_t_need_ts(struct sys_t_output *op)
{
if (op->node.ts_interval &&
- time_after(op->ts_jiffies + op->node.ts_interval, jiffies)) {
+ time_after(jiffies, op->ts_jiffies + op->node.ts_interval)) {
op->ts_jiffies = jiffies;
return true;
@@ -250,8 +250,8 @@ static inline bool sys_t_need_ts(struct sys_t_output *op)
static bool sys_t_need_clock_sync(struct sys_t_output *op)
{
if (op->node.clocksync_interval &&
- time_after(op->clocksync_jiffies + op->node.clocksync_interval,
- jiffies)) {
+ time_after(jiffies,
+ op->clocksync_jiffies + op->node.clocksync_interval)) {
op->clocksync_jiffies = jiffies;
return true;
diff --git a/drivers/hwtracing/stm/policy.c b/drivers/hwtracing/stm/policy.c
index 4b9e44b227d8..4f932a419752 100644
--- a/drivers/hwtracing/stm/policy.c
+++ b/drivers/hwtracing/stm/policy.c
@@ -345,7 +345,11 @@ void stp_policy_unbind(struct stp_policy *policy)
stm->policy = NULL;
policy->stm = NULL;
+ /*
+ * Drop the reference on the protocol driver and lose the link.
+ */
stm_put_protocol(stm->pdrv);
+ stm->pdrv = NULL;
stm_put_device(stm);
}