coresight: Updates for Linux v7.1

CoreSight self hosted tracing subsystem updates for Linux v7.1, includes:
 
  - Fix unregistration related issues
  - Clean up CTI power management and sysfs code
  - Miscellaneous fixes
  - MAINTAINERS: Add Leo Yan as Reviewer
  - MAINTAINERS: Update Mike's email address
 
 Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEuFy0byloRoXZHaWBxcXRZPKyBqEFAmnWh6cACgkQxcXRZPKy
 BqF55hAAmnd6RQRNhbTukjORsP/LENV5F7OWZuEI4y8OxbwBkTPA3gnZCNNEURqQ
 J2pymcabYzxZJ6wwXFOYpJH1ZM78cIhW6u0LugXb844c85k4G/K7t44ENYz0VKuL
 aBF4rzRfng4TprLIZQvYq/ND/tP4MGJ/3Il+IVcrCF+XSFj056N7VlrI5vKCjNgM
 JzfHCYNi4NiqXUzdECbzTjdEejg1eAe8xeIuNb7FSvfJ21a8iy2toGYtHmaecnNg
 Eir4CB1ZclQlyrQLEEjH22sTnjxBJRPXtkvTpUDTuIipGzzEZHdN7a9cWH5sNFxh
 VWCqI3PXs6/S6FBaCzjY3rL7qcAPCblPO5CkXajMlvj7+d7TDJL4jtB7BitNe1rY
 x/OR3J8fmsJMhxKKAlYnKPMMXlum50DzhPJvl4JUXd5EJnTLIkG6Z6vajCQm2diR
 WpI/ADee4mk3k9fhEfkiM7mXfKfmvId4/2W3p2dKDk3w8yl0htcuSIo6M3HgIi7w
 Ffedjh2+NM7f/8Gwn5AqORV1besCmCyIVs8alCHC9oegUSm/Kzxcf4K34THIeMub
 aejRbUU0QJtH2tVUPg6OD5owIwEJ5dZrGVKr5jtTP6s9W1G0MNX3EWsKvMixDjUw
 Tc6cM3jcGvmeqBOGlEVbBKmn17WPcnNa1bQZ6RfYyx6mtYf3b5A=
 =6zJ9
 -----END PGP SIGNATURE-----

Merge tag 'coresight-next-v7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux into char-misc-next

Suzuki writes:

coresight: Updates for Linux v7.1

CoreSight self hosted tracing subsystem updates for Linux v7.1, includes:

 - Fix unregistration related issues
 - Clean up CTI power management and sysfs code
 - Miscellaneous fixes
 - MAINTAINERS: Add Leo Yan as Reviewer
 - MAINTAINERS: Update Mike's email address

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

* tag 'coresight-next-v7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux: (25 commits)
  coresight: tpdm: fix invalid MMIO access issue
  coresight: tpdm: add traceid_show for checking traceid
  coresight: platform: check the availability of the endpoint before parse
  coresight: cti: fix the check condition in inout_sel_store
  MAINTAINERS: coresight: Add Leo Yan as Reviewer
  coresight: cti: Properly handle negative offsets in cti_reg32_{show|store}()
  coresight: cti: Remove hw_enabled flag
  coresight: cti: Remove hw_powered flag
  coresight: cti: Rename cti_active() to cti_is_active()
  coresight: cti: Remove CPU power management code
  coresight: cti: Access ASICCTL only when implemented
  coresight: cti: Fix register reads
  coresight: cti: Make spinlock usage consistent
  drivers/hwtracing/coresight: remove unneeded variable in tmc_crashdata_release()
  MAINTAINERS: Change e-mail address for reviewer
  coresight: ctcu: fix the spin_bug
  coresight: Unify bus unregistration via coresight_unregister()
  coresight: Do not mix success path with failure handling
  coresight: Move sink validation into etm_perf_add_symlink_sink()
  coresight: Refactor sysfs connection group cleanup
  ...
This commit is contained in:
Greg Kroah-Hartman 2026-04-09 09:21:13 +02:00
commit 1c0220a615
25 changed files with 364 additions and 509 deletions

View File

@ -576,6 +576,7 @@ Michel Lespinasse <michel@lespinasse.org> <walken@google.com>
Michel Lespinasse <michel@lespinasse.org> <walken@zoy.org>
Mickaël Salaün <mic@digikod.net> <mic@linux.microsoft.com>
Miguel Ojeda <ojeda@kernel.org> <miguel.ojeda.sandonis@gmail.com>
Mike Leach <mike.leach@arm.com> <mike.leach@linaro.org>
Mike Rapoport <rppt@kernel.org> <mike@compulab.co.il>
Mike Rapoport <rppt@kernel.org> <mike.rapoport@gmail.com>
Mike Rapoport <rppt@kernel.org> <rppt@linux.ibm.com>

View File

@ -278,3 +278,13 @@ Date: Aug 2025
KernelVersion 6.18
Contact: Mao Jinlong <quic_jinlmao@quicinc.com>
Description: (Read) Show hardware context information of device.
What: /sys/bus/coresight/devices/<tpdm-name>/traceid
Date: March 2026
KernelVersion: 7.1
Contact: Jie Gan <jie.gan@oss.qualcomm.com>
Description:
(R) Show the trace ID that will appear in the trace stream
coming from this TPDM. The trace ID is inherited from the
connected TPDA device and is fixed for the lifetime of the
device. Returns -EINVAL if the device has not been enabled yet.

View File

@ -2725,8 +2725,9 @@ N: digicolor
ARM/CORESIGHT FRAMEWORK AND DRIVERS
M: Suzuki K Poulose <suzuki.poulose@arm.com>
R: Mike Leach <mike.leach@linaro.org>
R: Mike Leach <mike.leach@arm.com>
R: James Clark <james.clark@linaro.org>
R: Leo Yan <leo.yan@arm.com>
L: coresight@lists.linaro.org (moderated for non-subscribers)
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@ -20734,7 +20735,7 @@ PERFORMANCE EVENTS TOOLING ARM64
R: John Garry <john.g.garry@oracle.com>
R: Will Deacon <will@kernel.org>
R: James Clark <james.clark@linaro.org>
R: Mike Leach <mike.leach@linaro.org>
R: Mike Leach <mike.leach@arm.com>
R: Leo Yan <leo.yan@linux.dev>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Supported

View File

@ -30,8 +30,6 @@
#define catu_dbg(x, ...) do {} while (0)
#endif
DEFINE_CORESIGHT_DEVLIST(catu_devs, "catu");
struct catu_etr_buf {
struct tmc_sg_table *catu_table;
dma_addr_t sladdr;
@ -530,7 +528,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
if (ret)
return ret;
catu_desc.name = coresight_alloc_device_name(&catu_devs, dev);
catu_desc.name = coresight_alloc_device_name("catu", dev);
if (!catu_desc.name)
return -ENOMEM;

View File

@ -53,6 +53,9 @@ struct coresight_node {
const u32 coresight_barrier_pkt[4] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
EXPORT_SYMBOL_GPL(coresight_barrier_pkt);
/* List maintains the device index */
static LIST_HEAD(coresight_dev_idx_list);
static const struct cti_assoc_op *cti_assoc_ops;
void coresight_set_cti_ops(const struct cti_assoc_op *cti_op)
@ -1149,7 +1152,6 @@ static int coresight_clear_filter_source(struct device *dev, void *data)
return 0;
}
/* coresight_remove_conns - Remove other device's references to this device */
static void coresight_remove_conns(struct coresight_device *csdev)
{
int i, j;
@ -1159,10 +1161,6 @@ static void coresight_remove_conns(struct coresight_device *csdev)
bus_for_each_dev(&coresight_bustype, NULL, csdev,
coresight_clear_filter_source);
/*
* Remove the input connection references from the destination device
* for each output connection.
*/
for (i = 0; i < csdev->pdata->nr_outconns; i++) {
conn = csdev->pdata->out_conns[i];
if (conn->filter_src_fwnode) {
@ -1173,6 +1171,13 @@ static void coresight_remove_conns(struct coresight_device *csdev)
if (!conn->dest_dev)
continue;
/* Remove sysfs links for the output connection */
coresight_remove_links(csdev, conn);
/*
* Remove the input connection references from the destination
* device for each output connection.
*/
for (j = 0; j < conn->dest_dev->pdata->nr_inconns; ++j)
if (conn->dest_dev->pdata->in_conns[j] == conn) {
conn->dest_dev->pdata->in_conns[j] = NULL;
@ -1195,6 +1200,8 @@ static void coresight_remove_conns(struct coresight_device *csdev)
coresight_remove_links(conn->src_dev, conn);
conn->dest_dev = NULL;
}
coresight_remove_conns_sysfs_group(csdev);
}
/**
@ -1295,17 +1302,13 @@ void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset)
* coresight_release_platform_data: Release references to the devices connected
* to the output port of this device.
*/
void coresight_release_platform_data(struct coresight_device *csdev,
struct device *dev,
void coresight_release_platform_data(struct device *dev,
struct coresight_platform_data *pdata)
{
int i;
struct coresight_connection **conns = pdata->out_conns;
for (i = 0; i < pdata->nr_outconns; i++) {
/* If we have made the links, remove them now */
if (csdev && conns[i]->dest_dev)
coresight_remove_links(csdev, conns[i]);
/*
* Drop the refcount and clear the handle as this device
* is going away
@ -1317,8 +1320,6 @@ void coresight_release_platform_data(struct coresight_device *csdev,
devm_kfree(dev, pdata->out_conns);
devm_kfree(dev, pdata->in_conns);
devm_kfree(dev, pdata);
if (csdev)
coresight_remove_conns_sysfs_group(csdev);
}
struct coresight_device *coresight_register(struct coresight_desc *desc)
@ -1346,12 +1347,6 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
csdev->dev.parent = desc->dev;
csdev->dev.release = coresight_device_release;
csdev->dev.bus = &coresight_bustype;
/*
* Hold the reference to our parent device. This will be
* dropped only in coresight_device_release().
*/
csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev));
dev_set_name(&csdev->dev, "%s", desc->name);
if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
@ -1363,6 +1358,14 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
goto err_out;
}
}
/*
* Hold the reference to our parent device. This will be
* dropped only in coresight_device_release().
*/
csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev));
dev_set_name(&csdev->dev, "%s", desc->name);
/*
* Make sure the device registration and the connection fixup
* are synchronised, so that we don't see uninitialised devices
@ -1380,37 +1383,30 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
goto out_unlock;
}
if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
sink_ops(csdev)->alloc_buffer) {
ret = etm_perf_add_symlink_sink(csdev);
if (ret) {
device_unregister(&csdev->dev);
/*
* As with the above, all resources are free'd
* explicitly via coresight_device_release() triggered
* from put_device(), which is in turn called from
* function device_unregister().
*/
goto out_unlock;
}
}
/* Device is now registered */
registered = true;
ret = etm_perf_add_symlink_sink(csdev);
if (ret && ret != -EOPNOTSUPP)
goto out_unlock;
ret = coresight_create_conns_sysfs_group(csdev);
if (!ret)
ret = coresight_fixup_orphan_conns(csdev);
if (ret)
goto out_unlock;
ret = coresight_fixup_orphan_conns(csdev);
if (ret)
goto out_unlock;
mutex_unlock(&coresight_mutex);
if (cti_assoc_ops && cti_assoc_ops->add)
cti_assoc_ops->add(csdev);
return csdev;
out_unlock:
mutex_unlock(&coresight_mutex);
/* Success */
if (!ret) {
if (cti_assoc_ops && cti_assoc_ops->add)
cti_assoc_ops->add(csdev);
return csdev;
}
/* Unregister the device if needed */
if (registered) {
@ -1419,41 +1415,76 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
}
err_out:
/* Cleanup the connection information */
coresight_release_platform_data(NULL, desc->dev, desc->pdata);
coresight_release_platform_data(desc->dev, desc->pdata);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(coresight_register);
void coresight_unregister(struct coresight_device *csdev)
{
etm_perf_del_symlink_sink(csdev);
/* Remove references of that device in the topology */
if (cti_assoc_ops && cti_assoc_ops->remove)
cti_assoc_ops->remove(csdev);
mutex_lock(&coresight_mutex);
etm_perf_del_symlink_sink(csdev);
coresight_remove_conns(csdev);
coresight_clear_default_sink(csdev);
coresight_release_platform_data(csdev, csdev->dev.parent, csdev->pdata);
coresight_release_platform_data(csdev->dev.parent, csdev->pdata);
device_unregister(&csdev->dev);
mutex_unlock(&coresight_mutex);
}
EXPORT_SYMBOL_GPL(coresight_unregister);
/*
* coresight_search_device_idx - Search the fwnode handle of a device
* in the given dev_idx list. Must be called with the coresight_mutex held.
*
* Returns the index of the entry, when found. Otherwise, -ENOENT.
*/
static int coresight_search_device_idx(struct coresight_dev_list *dict,
struct fwnode_handle *fwnode)
static struct coresight_dev_list *
coresight_allocate_device_list(const char *prefix)
{
int i;
struct coresight_dev_list *list;
for (i = 0; i < dict->nr_idx; i++)
if (dict->fwnode_list[i] == fwnode)
return i;
return -ENOENT;
/* Check if have already allocated */
list_for_each_entry(list, &coresight_dev_idx_list, node) {
if (!strcmp(list->pfx, prefix))
return list;
}
list = kzalloc(sizeof(*list), GFP_KERNEL);
if (!list)
return NULL;
list->pfx = kstrdup(prefix, GFP_KERNEL);
if (!list->pfx) {
kfree(list);
return NULL;
}
list_add(&list->node, &coresight_dev_idx_list);
return list;
}
static int coresight_allocate_device_idx(struct coresight_dev_list *list,
struct device *dev)
{
struct fwnode_handle **fwnode_list;
struct fwnode_handle *fwnode = dev_fwnode(dev);
int idx;
for (idx = 0; idx < list->nr_idx; idx++)
if (list->fwnode_list[idx] == fwnode)
return idx;
/* Make space for the new entry */
idx = list->nr_idx;
fwnode_list = krealloc_array(list->fwnode_list,
idx + 1, sizeof(*list->fwnode_list),
GFP_KERNEL);
if (!fwnode_list)
return -ENOMEM;
fwnode_list[idx] = fwnode;
list->fwnode_list = fwnode_list;
list->nr_idx = idx + 1;
return idx;
}
static bool coresight_compare_type(enum coresight_dev_type type_a,
@ -1527,45 +1558,63 @@ bool coresight_loses_context_with_cpu(struct device *dev)
EXPORT_SYMBOL_GPL(coresight_loses_context_with_cpu);
/*
* coresight_alloc_device_name - Get an index for a given device in the
* device index list specific to a driver. An index is allocated for a
* device and is tracked with the fwnode_handle to prevent allocating
* coresight_alloc_device_name - Get an index for a given device in the list
* specific to a driver (presented by the prefix string). An index is allocated
* for a device and is tracked with the fwnode_handle to prevent allocating
* duplicate indices for the same device (e.g, if we defer probing of
* a device due to dependencies), in case the index is requested again.
*/
char *coresight_alloc_device_name(struct coresight_dev_list *dict,
struct device *dev)
char *coresight_alloc_device_name(const char *prefix, struct device *dev)
{
int idx;
struct coresight_dev_list *list;
char *name = NULL;
struct fwnode_handle **list;
int idx;
mutex_lock(&coresight_mutex);
idx = coresight_search_device_idx(dict, dev_fwnode(dev));
if (idx < 0) {
/* Make space for the new entry */
idx = dict->nr_idx;
list = krealloc_array(dict->fwnode_list,
idx + 1, sizeof(*dict->fwnode_list),
GFP_KERNEL);
if (ZERO_OR_NULL_PTR(list)) {
idx = -ENOMEM;
goto done;
}
list = coresight_allocate_device_list(prefix);
if (!list)
goto done;
list[idx] = dev_fwnode(dev);
dict->fwnode_list = list;
dict->nr_idx = idx + 1;
}
idx = coresight_allocate_device_idx(list, dev);
name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", dict->pfx, idx);
/*
* If index allocation fails, the device list is not released here;
* it is instead freed later by coresight_release_device_list() when
* the coresight_core module is unloaded.
*/
if (idx < 0)
goto done;
name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", list->pfx, idx);
done:
mutex_unlock(&coresight_mutex);
return name;
}
EXPORT_SYMBOL_GPL(coresight_alloc_device_name);
static void coresight_release_device_list(void)
{
struct coresight_dev_list *list, *next;
int i;
/*
* Here is no need to take coresight_mutex; this is during core module
* unloading, no race condition with other modules.
*/
list_for_each_entry_safe(list, next, &coresight_dev_idx_list, node) {
for (i = 0; i < list->nr_idx; i++)
list->fwnode_list[i] = NULL;
list->nr_idx = 0;
list_del(&list->node);
kfree(list->pfx);
kfree(list->fwnode_list);
kfree(list);
}
}
const struct bus_type coresight_bustype = {
.name = "coresight",
};
@ -1639,6 +1688,7 @@ static void __exit coresight_exit(void)
&coresight_notifier);
etm_perf_exit();
bus_unregister(&coresight_bustype);
coresight_release_device_list();
}
module_init(coresight_init);

View File

@ -19,8 +19,6 @@
#include "coresight-ctcu.h"
#include "coresight-priv.h"
DEFINE_CORESIGHT_DEVLIST(ctcu_devs, "ctcu");
#define ctcu_writel(drvdata, val, offset) __raw_writel((val), drvdata->base + offset)
#define ctcu_readl(drvdata, offset) __raw_readl(drvdata->base + offset)
@ -187,7 +185,7 @@ static int ctcu_probe(struct platform_device *pdev)
void __iomem *base;
int i, ret;
desc.name = coresight_alloc_device_name(&ctcu_devs, dev);
desc.name = coresight_alloc_device_name("ctcu", dev);
if (!desc.name)
return -ENOMEM;
@ -228,6 +226,7 @@ static int ctcu_probe(struct platform_device *pdev)
desc.dev = dev;
desc.ops = &ctcu_ops;
desc.access = CSDEV_ACCESS_IOMEM(base);
raw_spin_lock_init(&drvdata->spin_lock);
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev))

View File

@ -42,21 +42,6 @@ static DEFINE_MUTEX(ect_mutex);
#define csdev_to_cti_drvdata(csdev) \
dev_get_drvdata(csdev->dev.parent)
/* power management handling */
static int nr_cti_cpu;
/* quick lookup list for CPU bound CTIs when power handling */
static struct cti_drvdata *cti_cpu_drvdata[NR_CPUS];
/*
* CTI naming. CTI bound to cores will have the name cti_cpu<N> where
* N is the CPU ID. System CTIs will have the name cti_sys<I> where I
* is an index allocated by order of discovery.
*
* CTI device name list - for CTI not bound to cores.
*/
DEFINE_CORESIGHT_DEVLIST(cti_sys_devs, "cti_sys");
/* write set of regs to hardware - call with spinlock claimed */
void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
{
@ -77,7 +62,8 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
/* other regs */
writel_relaxed(config->ctigate, drvdata->base + CTIGATE);
writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
if (config->asicctl_impl)
writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET);
/* re-enable CTI */
@ -90,60 +76,24 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
static int cti_enable_hw(struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
unsigned long flags;
int rc = 0;
int rc;
raw_spin_lock_irqsave(&drvdata->spinlock, flags);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* no need to do anything if enabled or unpowered*/
if (config->hw_enabled || !config->hw_powered)
/* no need to do anything if enabled */
if (cti_is_active(config))
goto cti_state_unchanged;
/* claim the device */
rc = coresight_claim_device(drvdata->csdev);
if (rc)
goto cti_err_not_enabled;
return rc;
cti_write_all_hw_regs(drvdata);
config->hw_enabled = true;
drvdata->config.enable_req_count++;
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
return rc;
cti_state_unchanged:
drvdata->config.enable_req_count++;
/* cannot enable due to error */
cti_err_not_enabled:
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
return rc;
}
/* re-enable CTI on CPU when using CPU hotplug */
static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
raw_spin_lock(&drvdata->spinlock);
config->hw_powered = true;
/* no need to do anything if no enable request */
if (!drvdata->config.enable_req_count)
goto cti_hp_not_enabled;
/* try to claim the device */
if (coresight_claim_device(drvdata->csdev))
goto cti_hp_not_enabled;
cti_write_all_hw_regs(drvdata);
config->hw_enabled = true;
raw_spin_unlock(&drvdata->spinlock);
return;
/* did not re-enable due to no claim / no request */
cti_hp_not_enabled:
raw_spin_unlock(&drvdata->spinlock);
return 0;
}
/* disable hardware */
@ -151,39 +101,36 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev;
int ret = 0;
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* don't allow negative refcounts, return an error */
if (!drvdata->config.enable_req_count) {
ret = -EINVAL;
goto cti_not_disabled;
}
if (!cti_is_active(config))
return -EINVAL;
/* check refcount - disable on 0 */
if (--drvdata->config.enable_req_count > 0)
goto cti_not_disabled;
/* no need to do anything if disabled or cpu unpowered */
if (!config->hw_enabled || !config->hw_powered)
goto cti_not_disabled;
return 0;
CS_UNLOCK(drvdata->base);
/* disable CTI */
writel_relaxed(0, drvdata->base + CTICONTROL);
config->hw_enabled = false;
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
raw_spin_unlock(&drvdata->spinlock);
return ret;
return 0;
}
/* not disabled this call */
cti_not_disabled:
raw_spin_unlock(&drvdata->spinlock);
return ret;
u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset)
{
int val;
CS_UNLOCK(drvdata->base);
val = readl_relaxed(drvdata->base + offset);
CS_LOCK(drvdata->base);
return val;
}
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value)
@ -198,11 +145,11 @@ void cti_write_intack(struct device *dev, u32 ackval)
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* write if enabled */
if (cti_active(config))
if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIINTACK, ackval);
raw_spin_unlock(&drvdata->spinlock);
}
/*
@ -240,6 +187,8 @@ static void cti_set_default_config(struct device *dev,
config->trig_filter_enable = true;
config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);
config->enable_req_count = 0;
config->asicctl_impl = !!FIELD_GET(GENMASK(4, 0), devid);
}
/*
@ -369,7 +318,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) :
CTIOUTEN(trigger_idx));
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* read - modify write - the trigger / channel enable value */
reg_value = direction == CTI_TRIG_IN ? config->ctiinen[trigger_idx] :
@ -386,9 +335,9 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
config->ctiouten[trigger_idx] = reg_value;
/* write through if enabled */
if (cti_active(config))
if (cti_is_active(config))
cti_write_single_reg(drvdata, reg_offset, reg_value);
raw_spin_unlock(&drvdata->spinlock);
return 0;
}
@ -406,7 +355,8 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
chan_bitmask = BIT(channel_idx);
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
reg_value = config->ctigate;
switch (op) {
case CTI_GATE_CHAN_ENABLE:
@ -423,10 +373,10 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
}
if (err == 0) {
config->ctigate = reg_value;
if (cti_active(config))
if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIGATE, reg_value);
}
raw_spin_unlock(&drvdata->spinlock);
return err;
}
@ -445,7 +395,8 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
chan_bitmask = BIT(channel_idx);
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
reg_value = config->ctiappset;
switch (op) {
case CTI_CHAN_SET:
@ -471,9 +422,8 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
break;
}
if ((err == 0) && cti_active(config))
if ((err == 0) && cti_is_active(config))
cti_write_single_reg(drvdata, reg_offset, reg_value);
raw_spin_unlock(&drvdata->spinlock);
return err;
}
@ -658,146 +608,6 @@ static void cti_remove_conn_xrefs(struct cti_drvdata *drvdata)
}
}
/** cti PM callbacks **/
static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
void *v)
{
struct cti_drvdata *drvdata;
struct coresight_device *csdev;
unsigned int cpu = smp_processor_id();
int notify_res = NOTIFY_OK;
if (!cti_cpu_drvdata[cpu])
return NOTIFY_OK;
drvdata = cti_cpu_drvdata[cpu];
csdev = drvdata->csdev;
if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu))
return NOTIFY_BAD;
raw_spin_lock(&drvdata->spinlock);
switch (cmd) {
case CPU_PM_ENTER:
/* CTI regs all static - we have a copy & nothing to save */
drvdata->config.hw_powered = false;
if (drvdata->config.hw_enabled)
coresight_disclaim_device(csdev);
break;
case CPU_PM_ENTER_FAILED:
drvdata->config.hw_powered = true;
if (drvdata->config.hw_enabled) {
if (coresight_claim_device(csdev))
drvdata->config.hw_enabled = false;
}
break;
case CPU_PM_EXIT:
/* write hardware registers to re-enable. */
drvdata->config.hw_powered = true;
drvdata->config.hw_enabled = false;
/* check enable reference count to enable HW */
if (drvdata->config.enable_req_count) {
/* check we can claim the device as we re-power */
if (coresight_claim_device(csdev))
goto cti_notify_exit;
drvdata->config.hw_enabled = true;
cti_write_all_hw_regs(drvdata);
}
break;
default:
notify_res = NOTIFY_DONE;
break;
}
cti_notify_exit:
raw_spin_unlock(&drvdata->spinlock);
return notify_res;
}
static struct notifier_block cti_cpu_pm_nb = {
.notifier_call = cti_cpu_pm_notify,
};
/* CPU HP handlers */
static int cti_starting_cpu(unsigned int cpu)
{
struct cti_drvdata *drvdata = cti_cpu_drvdata[cpu];
if (!drvdata)
return 0;
cti_cpuhp_enable_hw(drvdata);
return 0;
}
static int cti_dying_cpu(unsigned int cpu)
{
struct cti_drvdata *drvdata = cti_cpu_drvdata[cpu];
if (!drvdata)
return 0;
raw_spin_lock(&drvdata->spinlock);
drvdata->config.hw_powered = false;
if (drvdata->config.hw_enabled)
coresight_disclaim_device(drvdata->csdev);
raw_spin_unlock(&drvdata->spinlock);
return 0;
}
static int cti_pm_setup(struct cti_drvdata *drvdata)
{
int ret;
if (drvdata->ctidev.cpu == -1)
return 0;
if (nr_cti_cpu)
goto done;
cpus_read_lock();
ret = cpuhp_setup_state_nocalls_cpuslocked(
CPUHP_AP_ARM_CORESIGHT_CTI_STARTING,
"arm/coresight_cti:starting",
cti_starting_cpu, cti_dying_cpu);
if (ret) {
cpus_read_unlock();
return ret;
}
ret = cpu_pm_register_notifier(&cti_cpu_pm_nb);
cpus_read_unlock();
if (ret) {
cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_CTI_STARTING);
return ret;
}
done:
nr_cti_cpu++;
cti_cpu_drvdata[drvdata->ctidev.cpu] = drvdata;
return 0;
}
/* release PM registrations */
static void cti_pm_release(struct cti_drvdata *drvdata)
{
if (drvdata->ctidev.cpu == -1)
return;
cti_cpu_drvdata[drvdata->ctidev.cpu] = NULL;
if (--nr_cti_cpu == 0) {
cpu_pm_unregister_notifier(&cti_cpu_pm_nb);
cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_CTI_STARTING);
}
}
/** cti ect operations **/
int cti_enable(struct coresight_device *csdev, enum cs_mode mode,
struct coresight_path *path)
@ -823,17 +633,13 @@ static const struct coresight_ops cti_ops = {
.helper_ops = &cti_ops_ect,
};
/*
* Free up CTI specific resources
* called by dev->release, need to call down to underlying csdev release.
*/
static void cti_device_release(struct device *dev)
static void cti_remove(struct amba_device *adev)
{
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_drvdata *drvdata = dev_get_drvdata(&adev->dev);
struct cti_drvdata *ect_item, *ect_tmp;
mutex_lock(&ect_mutex);
cti_pm_release(drvdata);
cti_remove_conn_xrefs(drvdata);
/* remove from the list */
list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
@ -844,17 +650,6 @@ static void cti_device_release(struct device *dev)
}
mutex_unlock(&ect_mutex);
if (drvdata->csdev_release)
drvdata->csdev_release(dev);
}
static void cti_remove(struct amba_device *adev)
{
struct cti_drvdata *drvdata = dev_get_drvdata(&adev->dev);
mutex_lock(&ect_mutex);
cti_remove_conn_xrefs(drvdata);
mutex_unlock(&ect_mutex);
coresight_unregister(drvdata->csdev);
}
@ -900,29 +695,27 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(pdata);
}
/* default to powered - could change on PM notifications */
drvdata->config.hw_powered = true;
/* set up device name - will depend if cpu bound or otherwise */
/*
* Set up device name - will depend if cpu bound or otherwise.
*
* CTI bound to cores will have the name cti_cpu<N> where N is th
* eCPU ID. System CTIs will have the name cti_sys<I> where I is an
* index allocated by order of discovery.
*/
if (drvdata->ctidev.cpu >= 0)
cti_desc.name = devm_kasprintf(dev, GFP_KERNEL, "cti_cpu%d",
drvdata->ctidev.cpu);
else
cti_desc.name = coresight_alloc_device_name(&cti_sys_devs, dev);
cti_desc.name = coresight_alloc_device_name("cti_sys", dev);
if (!cti_desc.name)
return -ENOMEM;
/* setup CPU power management handling for CPU bound CTI devices. */
ret = cti_pm_setup(drvdata);
if (ret)
return ret;
/* create dynamic attributes for connections */
ret = cti_create_cons_sysfs(dev, drvdata);
if (ret) {
dev_err(dev, "%s: create dynamic sysfs entries failed\n",
cti_desc.name);
goto pm_release;
return ret;
}
/* set up coresight component description */
@ -935,10 +728,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
coresight_clear_self_claim_tag(&cti_desc.access);
drvdata->csdev = coresight_register(&cti_desc);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);
goto pm_release;
}
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
/* add to list of CTI devices */
mutex_lock(&ect_mutex);
@ -947,18 +738,10 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
cti_update_conn_xrefs(drvdata);
mutex_unlock(&ect_mutex);
/* set up release chain */
drvdata->csdev_release = drvdata->csdev->dev.release;
drvdata->csdev->dev.release = cti_device_release;
/* all done - dec pm refcount */
pm_runtime_put(&adev->dev);
dev_info(&drvdata->csdev->dev, "CTI initialized\n");
return 0;
pm_release:
cti_pm_release(drvdata);
return ret;
}
static struct amba_cs_uci_id uci_id_cti[] = {

View File

@ -81,19 +81,12 @@ static ssize_t enable_show(struct device *dev,
char *buf)
{
int enable_req;
bool enabled, powered;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
raw_spin_lock(&drvdata->spinlock);
enable_req = drvdata->config.enable_req_count;
powered = drvdata->config.hw_powered;
enabled = drvdata->config.hw_enabled;
raw_spin_unlock(&drvdata->spinlock);
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
enable_req = cti_is_active(&drvdata->config);
if (powered)
return sprintf(buf, "%d\n", enabled);
else
return sprintf(buf, "%d\n", !!enable_req);
return sprintf(buf, "%d\n", !!enable_req);
}
static ssize_t enable_store(struct device *dev,
@ -131,12 +124,7 @@ static ssize_t powered_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bool powered;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
raw_spin_lock(&drvdata->spinlock);
powered = drvdata->config.hw_powered;
raw_spin_unlock(&drvdata->spinlock);
bool powered = pm_runtime_active(dev->parent);
return sprintf(buf, "%d\n", powered);
}
@ -181,10 +169,10 @@ static ssize_t coresight_cti_reg_show(struct device *dev,
u32 val = 0;
pm_runtime_get_sync(dev->parent);
raw_spin_lock(&drvdata->spinlock);
if (drvdata->config.hw_powered)
val = readl_relaxed(drvdata->base + cti_attr->off);
raw_spin_unlock(&drvdata->spinlock);
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
val = cti_read_single_reg(drvdata, cti_attr->off);
pm_runtime_put_sync(dev->parent);
return sysfs_emit(buf, "0x%x\n", val);
}
@ -202,10 +190,10 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
return -EINVAL;
pm_runtime_get_sync(dev->parent);
raw_spin_lock(&drvdata->spinlock);
if (drvdata->config.hw_powered)
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
cti_write_single_reg(drvdata, cti_attr->off, val);
raw_spin_unlock(&drvdata->spinlock);
pm_runtime_put_sync(dev->parent);
return size;
}
@ -264,17 +252,19 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf,
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
raw_spin_lock(&drvdata->spinlock);
if ((reg_offset >= 0) && cti_active(config)) {
CS_UNLOCK(drvdata->base);
val = readl_relaxed(drvdata->base + reg_offset);
if (pcached_val)
*pcached_val = val;
CS_LOCK(drvdata->base);
} else if (pcached_val) {
val = *pcached_val;
if (reg_offset < 0)
return -EINVAL;
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
if (cti_is_active(config)) {
val = cti_read_single_reg(drvdata, reg_offset);
if (pcached_val)
*pcached_val = val;
} else if (pcached_val) {
val = *pcached_val;
}
}
raw_spin_unlock(&drvdata->spinlock);
return sprintf(buf, "%#x\n", val);
}
@ -293,15 +283,19 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
raw_spin_lock(&drvdata->spinlock);
/* local store */
if (pcached_val)
*pcached_val = (u32)val;
if (reg_offset < 0)
return -EINVAL;
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
/* local store */
if (pcached_val)
*pcached_val = (u32)val;
/* write through if offset and enabled */
if (cti_is_active(config))
cti_write_single_reg(drvdata, reg_offset, val);
}
/* write through if offset and enabled */
if ((reg_offset >= 0) && cti_active(config))
cti_write_single_reg(drvdata, reg_offset, val);
raw_spin_unlock(&drvdata->spinlock);
return size;
}
@ -343,15 +337,16 @@ static ssize_t inout_sel_store(struct device *dev,
{
unsigned long val;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val > (CTIINOUTEN_MAX - 1))
if (val >= config->nr_trig_max)
return -EINVAL;
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
drvdata->config.ctiinout_sel = val;
raw_spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(inout_sel);
@ -364,10 +359,11 @@ static ssize_t inen_show(struct device *dev,
int index;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
raw_spin_lock(&drvdata->spinlock);
index = drvdata->config.ctiinout_sel;
val = drvdata->config.ctiinen[index];
raw_spin_unlock(&drvdata->spinlock);
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
index = drvdata->config.ctiinout_sel;
val = drvdata->config.ctiinen[index];
}
return sprintf(buf, "%#lx\n", val);
}
@ -383,14 +379,15 @@ static ssize_t inen_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
index = config->ctiinout_sel;
config->ctiinen[index] = val;
/* write through if enabled */
if (cti_active(config))
if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIINEN(index), val);
raw_spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(inen);
@ -403,10 +400,11 @@ static ssize_t outen_show(struct device *dev,
int index;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
raw_spin_lock(&drvdata->spinlock);
index = drvdata->config.ctiinout_sel;
val = drvdata->config.ctiouten[index];
raw_spin_unlock(&drvdata->spinlock);
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
index = drvdata->config.ctiinout_sel;
val = drvdata->config.ctiouten[index];
}
return sprintf(buf, "%#lx\n", val);
}
@ -422,14 +420,15 @@ static ssize_t outen_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
index = config->ctiinout_sel;
config->ctiouten[index] = val;
/* write through if enabled */
if (cti_active(config))
if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIOUTEN(index), val);
raw_spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(outen);
@ -463,15 +462,15 @@ static ssize_t appclear_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* a 1'b1 in appclr clears down the same bit in appset*/
config->ctiappset &= ~val;
/* write through if enabled */
if (cti_active(config))
if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIAPPCLEAR, val);
raw_spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_WO(appclear);
@ -487,12 +486,12 @@ static ssize_t apppulse_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* write through if enabled */
if (cti_active(config))
if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIAPPPULSE, val);
raw_spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_WO(apppulse);
@ -530,6 +529,18 @@ static struct attribute *coresight_cti_regs_attrs[] = {
NULL,
};
static umode_t coresight_cti_regs_is_visible(struct kobject *kobj,
struct attribute *attr, int idx)
{
struct device *dev = kobj_to_dev(kobj);
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
if (attr == &dev_attr_asicctl.attr && !drvdata->config.asicctl_impl)
return 0;
return attr->mode;
}
/* CTI channel x-trigger programming */
static int
cti_trig_op_parse(struct device *dev, enum cti_chan_op op,
@ -681,9 +692,9 @@ static ssize_t trig_filter_enable_show(struct device *dev,
u32 val;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
raw_spin_lock(&drvdata->spinlock);
val = drvdata->config.trig_filter_enable;
raw_spin_unlock(&drvdata->spinlock);
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
val = drvdata->config.trig_filter_enable;
return sprintf(buf, "%d\n", val);
}
@ -697,9 +708,9 @@ static ssize_t trig_filter_enable_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
drvdata->config.trig_filter_enable = !!val;
raw_spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(trig_filter_enable);
@ -728,7 +739,7 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* clear the CTI trigger / channel programming registers */
for (i = 0; i < config->nr_trig_max; i++) {
@ -744,10 +755,9 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
config->xtrig_rchan_sel = 0;
/* if enabled then write through */
if (cti_active(config))
if (cti_is_active(config))
cti_write_all_hw_regs(drvdata);
raw_spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_WO(chan_xtrigs_reset);
@ -768,9 +778,9 @@ static ssize_t chan_xtrigs_sel_store(struct device *dev,
if (val > (drvdata->config.nr_ctm_channels - 1))
return -EINVAL;
raw_spin_lock(&drvdata->spinlock);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
drvdata->config.xtrig_rchan_sel = val;
raw_spin_unlock(&drvdata->spinlock);
return size;
}
@ -781,9 +791,8 @@ static ssize_t chan_xtrigs_sel_show(struct device *dev,
unsigned long val;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
raw_spin_lock(&drvdata->spinlock);
val = drvdata->config.xtrig_rchan_sel;
raw_spin_unlock(&drvdata->spinlock);
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
val = drvdata->config.xtrig_rchan_sel;
return sprintf(buf, "%ld\n", val);
}
@ -838,12 +847,12 @@ static ssize_t print_chan_list(struct device *dev,
unsigned long inuse_bits = 0, chan_mask;
/* scan regs to get bitmap of channels in use. */
raw_spin_lock(&drvdata->spinlock);
for (i = 0; i < config->nr_trig_max; i++) {
inuse_bits |= config->ctiinen[i];
inuse_bits |= config->ctiouten[i];
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
for (i = 0; i < config->nr_trig_max; i++) {
inuse_bits |= config->ctiinen[i];
inuse_bits |= config->ctiouten[i];
}
}
raw_spin_unlock(&drvdata->spinlock);
/* inverse bits if printing free channels */
if (!inuse)
@ -1169,6 +1178,7 @@ static const struct attribute_group coresight_cti_mgmt_group = {
static const struct attribute_group coresight_cti_regs_group = {
.attrs = coresight_cti_regs_attrs,
.is_visible = coresight_cti_regs_is_visible,
.name = "regs",
};

View File

@ -119,9 +119,8 @@ struct cti_device {
* @nr_trig_max: Max number of trigger signals implemented on device.
* (max of trig_in or trig_out) - from ID register.
* @nr_ctm_channels: number of available CTM channels - from ID register.
* @asicctl_impl: true if asicctl is implemented.
* @enable_req_count: CTI is enabled alongside >=1 associated devices.
* @hw_enabled: true if hw is currently enabled.
* @hw_powered: true if associated cpu powered on, or no cpu.
* @trig_in_use: bitfield of in triggers registered as in use.
* @trig_out_use: bitfield of out triggers registered as in use.
* @trig_out_filter: bitfield of out triggers that are blocked if filter
@ -140,11 +139,10 @@ struct cti_config {
/* hardware description */
int nr_ctm_channels;
int nr_trig_max;
bool asicctl_impl;
/* cti enable control */
int enable_req_count;
bool hw_enabled;
bool hw_powered;
/* registered triggers and filtering */
u32 trig_in_use;
@ -170,7 +168,6 @@ struct cti_config {
* @spinlock: Control data access to one at a time.
* @config: Configuration data for this CTI device.
* @node: List entry of this device in the list of CTI devices.
* @csdev_release: release function for underlying coresight_device.
*/
struct cti_drvdata {
void __iomem *base;
@ -179,7 +176,6 @@ struct cti_drvdata {
raw_spinlock_t spinlock;
struct cti_config config;
struct list_head node;
void (*csdev_release)(struct device *dev);
};
/*
@ -222,6 +218,7 @@ int cti_disable(struct coresight_device *csdev, struct coresight_path *path);
void cti_write_all_hw_regs(struct cti_drvdata *drvdata);
void cti_write_intack(struct device *dev, u32 ackval);
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset);
int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
enum cti_trig_dir direction, u32 channel_idx,
u32 trigger_idx);
@ -234,10 +231,10 @@ struct coresight_platform_data *
coresight_cti_get_platform_data(struct device *dev);
const char *cti_plat_get_node_name(struct fwnode_handle *fwnode);
/* cti powered and enabled */
static inline bool cti_active(struct cti_config *cfg)
/* Check if a cti device is enabled */
static inline bool cti_is_active(struct cti_config *cfg)
{
return cfg->hw_powered && cfg->hw_enabled;
return !!cfg->enable_req_count;
}
#endif /* _CORESIGHT_CORESIGHT_CTI_H */

View File

@ -19,9 +19,6 @@ struct dummy_drvdata {
u8 traceid;
};
DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source");
DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink");
static int dummy_source_enable(struct coresight_device *csdev,
struct perf_event *event, enum cs_mode mode,
__maybe_unused struct coresight_path *path)
@ -126,7 +123,7 @@ static int dummy_probe(struct platform_device *pdev)
if (of_device_is_compatible(node, "arm,coresight-dummy-source")) {
desc.name = coresight_alloc_device_name(&source_devs, dev);
desc.name = coresight_alloc_device_name("dummy_source", dev);
if (!desc.name)
return -ENOMEM;
@ -155,7 +152,7 @@ static int dummy_probe(struct platform_device *pdev)
drvdata->traceid = (u8)trace_id;
} else if (of_device_is_compatible(node, "arm,coresight-dummy-sink")) {
desc.name = coresight_alloc_device_name(&sink_devs, dev);
desc.name = coresight_alloc_device_name("dummy_sink", dev);
if (!desc.name)
return -ENOMEM;

View File

@ -63,8 +63,6 @@
#define ETB_FFSR_BIT 1
#define ETB_FRAME_SIZE_WORDS 4
DEFINE_CORESIGHT_DEVLIST(etb_devs, "etb");
/**
* struct etb_drvdata - specifics associated to an ETB component
* @base: memory mapped base address for this component.
@ -722,7 +720,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
struct resource *res = &adev->res;
struct coresight_desc desc = { 0 };
desc.name = coresight_alloc_device_name(&etb_devs, dev);
desc.name = coresight_alloc_device_name("etb", dev);
if (!desc.name)
return -ENOMEM;

View File

@ -902,7 +902,10 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev)
if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
return -EINVAL;
return -EOPNOTSUPP;
if (!sink_ops(csdev)->alloc_buffer)
return -EOPNOTSUPP;
if (csdev->ea != NULL)
return -EINVAL;

View File

@ -30,8 +30,6 @@
#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT)
#define FUNNEL_ENSx_MASK 0xff
DEFINE_CORESIGHT_DEVLIST(funnel_devs, "funnel");
/**
* struct funnel_drvdata - specifics associated to a funnel component
* @base: memory mapped base address for this component.
@ -223,7 +221,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
of_device_is_compatible(dev->of_node, "arm,coresight-funnel"))
dev_warn_once(dev, "Uses OBSOLETE CoreSight funnel binding\n");
desc.name = coresight_alloc_device_name(&funnel_devs, dev);
desc.name = coresight_alloc_device_name("funnel", dev);
if (!desc.name)
return -ENOMEM;

View File

@ -220,6 +220,8 @@ static int of_coresight_parse_endpoint(struct device *dev,
rparent = of_coresight_get_port_parent(rep);
if (!rparent)
break;
if (!of_device_is_available(rparent))
break;
if (of_graph_parse_endpoint(rep, &rendpoint))
break;
@ -849,7 +851,7 @@ coresight_get_platform_data(struct device *dev)
error:
if (!IS_ERR_OR_NULL(pdata))
/* Cleanup the connection information */
coresight_release_platform_data(NULL, dev, pdata);
coresight_release_platform_data(dev, pdata);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(coresight_get_platform_data);

View File

@ -239,8 +239,7 @@ static inline void *coresight_get_uci_data_from_amba(const struct amba_id *table
return NULL;
}
void coresight_release_platform_data(struct coresight_device *csdev,
struct device *dev,
void coresight_release_platform_data(struct device *dev,
struct coresight_platform_data *pdata);
struct coresight_device *
coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode);

View File

@ -24,8 +24,6 @@
#define REPLICATOR_IDFILTER0 0x000
#define REPLICATOR_IDFILTER1 0x004
DEFINE_CORESIGHT_DEVLIST(replicator_devs, "replicator");
/**
* struct replicator_drvdata - specifics associated to a replicator component
* @base: memory mapped base address for this component. Also indicates
@ -230,7 +228,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
dev_warn_once(dev,
"Uses OBSOLETE CoreSight replicator binding\n");
desc.name = coresight_alloc_device_name(&replicator_devs, dev);
desc.name = coresight_alloc_device_name("replicator", dev);
if (!desc.name)
return -ENOMEM;

View File

@ -110,8 +110,6 @@ struct channel_space {
unsigned long *guaranteed;
};
DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm");
/**
* struct stm_drvdata - specifics associated to an STM component
* @base: memory mapped base address for this component.
@ -834,7 +832,7 @@ static int __stm_probe(struct device *dev, struct resource *res)
struct resource ch_res;
struct coresight_desc desc = { 0 };
desc.name = coresight_alloc_device_name(&stm_devs, dev);
desc.name = coresight_alloc_device_name("stm", dev);
if (!desc.name)
return -ENOMEM;

View File

@ -32,10 +32,6 @@
#include "coresight-priv.h"
#include "coresight-tmc.h"
DEFINE_CORESIGHT_DEVLIST(etb_devs, "tmc_etb");
DEFINE_CORESIGHT_DEVLIST(etf_devs, "tmc_etf");
DEFINE_CORESIGHT_DEVLIST(etr_devs, "tmc_etr");
int tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
{
struct coresight_device *csdev = drvdata->csdev;
@ -401,7 +397,6 @@ static ssize_t tmc_crashdata_read(struct file *file, char __user *data,
static int tmc_crashdata_release(struct inode *inode, struct file *file)
{
int ret = 0;
unsigned long flags;
struct tmc_resrv_buf *rbuf;
struct tmc_drvdata *drvdata = container_of(file->private_data,
@ -414,7 +409,7 @@ static int tmc_crashdata_release(struct inode *inode, struct file *file)
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
dev_dbg(&drvdata->csdev->dev, "%s: released\n", __func__);
return ret;
return 0;
}
static const struct file_operations tmc_crashdata_fops = {
@ -777,7 +772,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
struct coresight_platform_data *pdata = NULL;
struct tmc_drvdata *drvdata;
struct coresight_desc desc = { 0 };
struct coresight_dev_list *dev_list = NULL;
const char *dev_list = NULL;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
@ -827,7 +822,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
desc.type = CORESIGHT_DEV_TYPE_SINK;
desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
desc.ops = &tmc_etb_cs_ops;
dev_list = &etb_devs;
dev_list = "tmc_etb";
break;
case TMC_CONFIG_TYPE_ETR:
desc.groups = coresight_etr_groups;
@ -839,7 +834,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
goto out;
idr_init(&drvdata->idr);
mutex_init(&drvdata->idr_mutex);
dev_list = &etr_devs;
dev_list = "tmc_etr";
break;
case TMC_CONFIG_TYPE_ETF:
desc.groups = coresight_etf_groups;
@ -847,7 +842,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
desc.ops = &tmc_etf_cs_ops;
dev_list = &etf_devs;
dev_list = "tmc_etf";
break;
default:
pr_err("%s: Unsupported TMC config\n", desc.name);

View File

@ -47,8 +47,6 @@ struct trace_noc_drvdata {
int atid;
};
DEFINE_CORESIGHT_DEVLIST(trace_noc_devs, "traceNoc");
static void trace_noc_enable_hw(struct trace_noc_drvdata *drvdata)
{
u32 val;
@ -191,7 +189,7 @@ static int _tnoc_probe(struct device *dev, struct resource *res)
struct coresight_desc desc = { 0 };
int ret;
desc.name = coresight_alloc_device_name(&trace_noc_devs, dev);
desc.name = coresight_alloc_device_name("traceNoc", dev);
if (!desc.name)
return -ENOMEM;

View File

@ -20,8 +20,6 @@
#include "coresight-trace-id.h"
#include "coresight-tpdm.h"
DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
static void tpda_clear_element_size(struct coresight_device *csdev)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@ -585,7 +583,7 @@ static int tpda_probe(struct amba_device *adev, const struct amba_id *id)
if (ret)
return ret;
desc.name = coresight_alloc_device_name(&tpda_devs, dev);
desc.name = coresight_alloc_device_name("tpda", dev);
if (!desc.name)
return -ENOMEM;
desc.type = CORESIGHT_DEV_TYPE_LINK;

View File

@ -19,8 +19,6 @@
#include "coresight-priv.h"
#include "coresight-tpdm.h"
DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm");
static bool tpdm_has_dsb_dataset(struct tpdm_drvdata *drvdata)
{
return (drvdata->datasets & TPDM_PIDR0_DS_DSB);
@ -483,7 +481,7 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata)
static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
enum cs_mode mode,
__maybe_unused struct coresight_path *path)
struct coresight_path *path)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@ -499,6 +497,7 @@ static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
}
__tpdm_enable(drvdata);
drvdata->traceid = path->trace_id;
drvdata->enable = true;
spin_unlock(&drvdata->spinlock);
@ -695,6 +694,29 @@ static struct attribute_group tpdm_attr_grp = {
.attrs = tpdm_attrs,
};
static ssize_t traceid_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
unsigned long val;
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
val = drvdata->traceid;
if (!val)
return -EINVAL;
return sysfs_emit(buf, "%#lx\n", val);
}
static DEVICE_ATTR_RO(traceid);
static struct attribute *traceid_attrs[] = {
&dev_attr_traceid.attr,
NULL,
};
static struct attribute_group traceid_attr_grp = {
.attrs = traceid_attrs,
};
static ssize_t dsb_mode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@ -1369,6 +1391,12 @@ static const struct attribute_group *tpdm_attr_grps[] = {
&tpdm_cmb_patt_grp,
&tpdm_cmb_msr_grp,
&tpdm_mcmb_attr_grp,
&traceid_attr_grp,
NULL,
};
static const struct attribute_group *static_tpdm_attr_grps[] = {
&traceid_attr_grp,
NULL,
};
@ -1402,6 +1430,7 @@ static int tpdm_probe(struct device *dev, struct resource *res)
if (ret)
return ret;
desc.access = CSDEV_ACCESS_IOMEM(base);
if (tpdm_has_dsb_dataset(drvdata))
of_property_read_u32(drvdata->dev->of_node,
"qcom,dsb-msrs-num", &drvdata->dsb_msr_num);
@ -1416,7 +1445,7 @@ static int tpdm_probe(struct device *dev, struct resource *res)
}
/* Set up coresight component description */
desc.name = coresight_alloc_device_name(&tpdm_devs, dev);
desc.name = coresight_alloc_device_name("tpdm", dev);
if (!desc.name)
return -ENOMEM;
desc.type = CORESIGHT_DEV_TYPE_SOURCE;
@ -1424,9 +1453,10 @@ static int tpdm_probe(struct device *dev, struct resource *res)
desc.ops = &tpdm_cs_ops;
desc.pdata = dev->platform_data;
desc.dev = dev;
desc.access = CSDEV_ACCESS_IOMEM(base);
if (res)
desc.groups = tpdm_attr_grps;
else
desc.groups = static_tpdm_attr_grps;
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);

View File

@ -300,6 +300,7 @@ struct cmb_dataset {
* @cmb Specifics associated to TPDM CMB.
* @dsb_msr_num Number of MSR supported by DSB TPDM
* @cmb_msr_num Number of MSR supported by CMB TPDM
* @traceid Trace ID of the path.
*/
struct tpdm_drvdata {
@ -313,6 +314,7 @@ struct tpdm_drvdata {
struct cmb_dataset *cmb;
u32 dsb_msr_num;
u32 cmb_msr_num;
u8 traceid;
};
/* Enumerate members of various datasets */

View File

@ -49,8 +49,6 @@
#define FFCR_FON_MAN BIT(6)
#define FFCR_STOP_FI BIT(12)
DEFINE_CORESIGHT_DEVLIST(tpiu_devs, "tpiu");
/*
* @base: memory mapped base address for this component.
* @atclk: optional clock for the core parts of the TPIU.
@ -134,7 +132,7 @@ static int __tpiu_probe(struct device *dev, struct resource *res)
struct coresight_desc desc = { 0 };
int ret;
desc.name = coresight_alloc_device_name(&tpiu_devs, dev);
desc.name = coresight_alloc_device_name("tpiu", dev);
if (!desc.name)
return -ENOMEM;

View File

@ -17,8 +17,6 @@
#include "coresight-priv.h"
#include "ultrasoc-smb.h"
DEFINE_CORESIGHT_DEVLIST(sink_devs, "ultra_smb");
#define ULTRASOC_SMB_DSM_UUID "82ae1283-7f6a-4cbe-aa06-53e8fb24db18"
static bool smb_buffer_not_empty(struct smb_drv_data *drvdata)
@ -478,7 +476,7 @@ static int smb_register_sink(struct platform_device *pdev,
desc.pdata = pdata;
desc.dev = &pdev->dev;
desc.groups = smb_sink_groups;
desc.name = coresight_alloc_device_name(&sink_devs, &pdev->dev);
desc.name = coresight_alloc_device_name("ultra_smb", &pdev->dev);
if (!desc.name) {
dev_err(&pdev->dev, "Failed to alloc coresight device name");
return -ENOMEM;

View File

@ -306,24 +306,19 @@ struct coresight_device {
* coresight_dev_list - Mapping for devices to "name" index for device
* names.
*
* @node: Node on the global device index list.
* @nr_idx: Number of entries already allocated.
* @pfx: Prefix pattern for device name.
* @fwnode_list: Array of fwnode_handles associated with each allocated
* index, upto nr_idx entries.
*/
struct coresight_dev_list {
struct list_head node;
int nr_idx;
const char *pfx;
char *pfx;
struct fwnode_handle **fwnode_list;
};
#define DEFINE_CORESIGHT_DEVLIST(var, dev_pfx) \
static struct coresight_dev_list (var) = { \
.pfx = dev_pfx, \
.nr_idx = 0, \
.fwnode_list = NULL, \
}
#define to_coresight_device(d) container_of(d, struct coresight_device, dev)
/**
@ -663,8 +658,7 @@ void coresight_clear_self_claim_tag(struct csdev_access *csa);
void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
void coresight_disclaim_device(struct coresight_device *csdev);
void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
char *coresight_alloc_device_name(struct coresight_dev_list *devs,
struct device *dev);
char *coresight_alloc_device_name(const char *prefix, struct device *dev);
bool coresight_loses_context_with_cpu(struct device *dev);