Loading drivers/hwtracing/coresight/coresight-etm-perf.c +3 −1 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ static void free_event_data(struct work_struct *work) cpumask_t *mask; struct etm_event_data *event_data; struct coresight_device *sink; struct coresight_device *source; event_data = container_of(work, struct etm_event_data, work); mask = &event_data->mask; Loading @@ -126,8 +127,9 @@ static void free_event_data(struct work_struct *work) } for_each_cpu(cpu, mask) { source = coresight_get_source(event_data->path[cpu]); if (!(IS_ERR_OR_NULL(event_data->path[cpu]))) coresight_release_path(event_data->path[cpu]); coresight_release_path(source, event_data->path[cpu]); } kfree(event_data->path); Loading drivers/hwtracing/coresight/coresight-priv.h +3 −1 Original line number Diff line number Diff line Loading @@ -143,7 +143,9 @@ struct coresight_device *coresight_get_sink(struct list_head *path); struct coresight_device *coresight_get_enabled_sink(bool reset); struct list_head *coresight_build_path(struct coresight_device *csdev, struct coresight_device *sink); void coresight_release_path(struct list_head *path); struct coresight_device *coresight_get_source(struct list_head *path); void coresight_release_path(struct coresight_device *csdev, struct list_head *path); #ifdef CONFIG_CORESIGHT_SOURCE_ETM3X extern int etm_readl_cp14(u32 off, unsigned int *val); Loading drivers/hwtracing/coresight/coresight.c +61 −53 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2012, The Linux Foundation. All rights reserved. * Copyright (c) 2012, 2017, The Linux Foundation. All rights reserved. */ #include <linux/kernel.h> Loading Loading @@ -33,18 +33,16 @@ struct coresight_node { }; /* * When operating Coresight drivers from the sysFS interface, only a single * path can exist from a tracer (associated to a CPU) to a sink. * struct coresight_path - path from source to sink * @path: Address of path list. * @link: hook to the list. */ static DEFINE_PER_CPU(struct list_head *, tracer_path); struct coresight_path { struct list_head *path; struct list_head link; }; /* * As of this writing only a single STM can be found in CS topologies. Since * there is no way to know if we'll ever see more and what kind of * configuration they will enact, for the time being only define a single path * for STM. */ static struct list_head *stm_path; static LIST_HEAD(cs_active_paths); /* * When losing synchronisation a new barrier packet needs to be inserted at the Loading Loading @@ -151,7 +149,7 @@ static void coresight_disable_sink(struct coresight_device *csdev) if (atomic_dec_return(csdev->refcnt) == 0) { if (sink_ops(csdev)->disable) { sink_ops(csdev)->disable(csdev); csdev->enable = false; csdev->activated = false; } } } Loading Loading @@ -364,6 +362,20 @@ int coresight_enable_path(struct list_head *path, u32 mode) goto out; } struct coresight_device *coresight_get_source(struct list_head *path) { struct coresight_device *csdev; if (!path) return NULL; csdev = list_first_entry(path, struct coresight_node, link)->csdev; if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) return NULL; return csdev; } struct coresight_device *coresight_get_sink(struct list_head *path) { struct coresight_device *csdev; Loading Loading @@ -543,15 +555,24 @@ struct list_head *coresight_build_path(struct coresight_device *source, /** * coresight_release_path - release a previously built path. * @path: the path to release. * Remove coresight path entry from source device * * Go through all the elements of a path and 1) removed it from the list and * 2) free the memory allocated for each node. */ void coresight_release_path(struct list_head *path) void coresight_release_path(struct coresight_device *csdev, struct list_head *path) { struct coresight_device *csdev; struct coresight_node *nd, *next; if (csdev != NULL && csdev->node != NULL) { /* Remove path entry from source device */ list_del(&csdev->node->link); kfree(csdev->node); csdev->node = NULL; } /* Free the path */ list_for_each_entry_safe(nd, next, path, link) { csdev = nd->csdev; Loading Loading @@ -592,9 +613,25 @@ static int coresight_validate_source(struct coresight_device *csdev, return 0; } int coresight_store_path(struct coresight_device *csdev, struct list_head *path) { struct coresight_path *node; node = kzalloc(sizeof(struct coresight_path), GFP_KERNEL); if (!node) return -ENOMEM; node->path = path; list_add(&node->link, &cs_active_paths); csdev->node = node; return 0; } int coresight_enable(struct coresight_device *csdev) { int cpu, ret = 0; int ret = 0; struct coresight_device *sink; struct list_head *path; enum coresight_dev_subtype_source subtype; Loading Loading @@ -643,25 +680,9 @@ int coresight_enable(struct coresight_device *csdev) if (ret) goto err_source; switch (subtype) { case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: /* * When working from sysFS it is important to keep track * of the paths that were created so that they can be * undone in 'coresight_disable()'. Since there can only * be a single session per tracer (when working from sysFS) * a per-cpu variable will do just fine. */ cpu = source_ops(csdev)->cpu_id(csdev); per_cpu(tracer_path, cpu) = path; break; case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: stm_path = path; break; default: /* We can't be here */ break; } ret = coresight_store_path(csdev, path); if (ret) goto err_source; out: mutex_unlock(&coresight_mutex); Loading @@ -671,15 +692,14 @@ int coresight_enable(struct coresight_device *csdev) coresight_disable_path(path); err_path: coresight_release_path(path); coresight_release_path(csdev, path); goto out; } EXPORT_SYMBOL_GPL(coresight_enable); void coresight_disable(struct coresight_device *csdev) { int cpu, ret; struct list_head *path = NULL; int ret; mutex_lock(&coresight_mutex); Loading @@ -690,23 +710,11 @@ void coresight_disable(struct coresight_device *csdev) if (!csdev->enable || !coresight_disable_source(csdev)) goto out; switch (csdev->subtype.source_subtype) { case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: cpu = source_ops(csdev)->cpu_id(csdev); path = per_cpu(tracer_path, cpu); per_cpu(tracer_path, cpu) = NULL; break; case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: path = stm_path; stm_path = NULL; break; default: /* We can't be here */ break; } if (csdev->node == NULL) goto out; coresight_disable_path(path); coresight_release_path(path); coresight_disable_path(csdev->node->path); coresight_release_path(csdev, csdev->node->path); out: mutex_unlock(&coresight_mutex); Loading include/linux/coresight.h +1 −0 Original line number Diff line number Diff line Loading @@ -171,6 +171,7 @@ struct coresight_device { const struct coresight_ops *ops; struct device dev; atomic_t *refcnt; struct coresight_path *node; bool orphan; bool enable; /* true only if configured as part of a path */ bool activated; /* true only if a sink is part of a path */ Loading Loading
drivers/hwtracing/coresight/coresight-etm-perf.c +3 −1 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ static void free_event_data(struct work_struct *work) cpumask_t *mask; struct etm_event_data *event_data; struct coresight_device *sink; struct coresight_device *source; event_data = container_of(work, struct etm_event_data, work); mask = &event_data->mask; Loading @@ -126,8 +127,9 @@ static void free_event_data(struct work_struct *work) } for_each_cpu(cpu, mask) { source = coresight_get_source(event_data->path[cpu]); if (!(IS_ERR_OR_NULL(event_data->path[cpu]))) coresight_release_path(event_data->path[cpu]); coresight_release_path(source, event_data->path[cpu]); } kfree(event_data->path); Loading
drivers/hwtracing/coresight/coresight-priv.h +3 −1 Original line number Diff line number Diff line Loading @@ -143,7 +143,9 @@ struct coresight_device *coresight_get_sink(struct list_head *path); struct coresight_device *coresight_get_enabled_sink(bool reset); struct list_head *coresight_build_path(struct coresight_device *csdev, struct coresight_device *sink); void coresight_release_path(struct list_head *path); struct coresight_device *coresight_get_source(struct list_head *path); void coresight_release_path(struct coresight_device *csdev, struct list_head *path); #ifdef CONFIG_CORESIGHT_SOURCE_ETM3X extern int etm_readl_cp14(u32 off, unsigned int *val); Loading
drivers/hwtracing/coresight/coresight.c +61 −53 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2012, The Linux Foundation. All rights reserved. * Copyright (c) 2012, 2017, The Linux Foundation. All rights reserved. */ #include <linux/kernel.h> Loading Loading @@ -33,18 +33,16 @@ struct coresight_node { }; /* * When operating Coresight drivers from the sysFS interface, only a single * path can exist from a tracer (associated to a CPU) to a sink. * struct coresight_path - path from source to sink * @path: Address of path list. * @link: hook to the list. */ static DEFINE_PER_CPU(struct list_head *, tracer_path); struct coresight_path { struct list_head *path; struct list_head link; }; /* * As of this writing only a single STM can be found in CS topologies. Since * there is no way to know if we'll ever see more and what kind of * configuration they will enact, for the time being only define a single path * for STM. */ static struct list_head *stm_path; static LIST_HEAD(cs_active_paths); /* * When losing synchronisation a new barrier packet needs to be inserted at the Loading Loading @@ -151,7 +149,7 @@ static void coresight_disable_sink(struct coresight_device *csdev) if (atomic_dec_return(csdev->refcnt) == 0) { if (sink_ops(csdev)->disable) { sink_ops(csdev)->disable(csdev); csdev->enable = false; csdev->activated = false; } } } Loading Loading @@ -364,6 +362,20 @@ int coresight_enable_path(struct list_head *path, u32 mode) goto out; } struct coresight_device *coresight_get_source(struct list_head *path) { struct coresight_device *csdev; if (!path) return NULL; csdev = list_first_entry(path, struct coresight_node, link)->csdev; if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) return NULL; return csdev; } struct coresight_device *coresight_get_sink(struct list_head *path) { struct coresight_device *csdev; Loading Loading @@ -543,15 +555,24 @@ struct list_head *coresight_build_path(struct coresight_device *source, /** * coresight_release_path - release a previously built path. * @path: the path to release. * Remove coresight path entry from source device * * Go through all the elements of a path and 1) removed it from the list and * 2) free the memory allocated for each node. */ void coresight_release_path(struct list_head *path) void coresight_release_path(struct coresight_device *csdev, struct list_head *path) { struct coresight_device *csdev; struct coresight_node *nd, *next; if (csdev != NULL && csdev->node != NULL) { /* Remove path entry from source device */ list_del(&csdev->node->link); kfree(csdev->node); csdev->node = NULL; } /* Free the path */ list_for_each_entry_safe(nd, next, path, link) { csdev = nd->csdev; Loading Loading @@ -592,9 +613,25 @@ static int coresight_validate_source(struct coresight_device *csdev, return 0; } int coresight_store_path(struct coresight_device *csdev, struct list_head *path) { struct coresight_path *node; node = kzalloc(sizeof(struct coresight_path), GFP_KERNEL); if (!node) return -ENOMEM; node->path = path; list_add(&node->link, &cs_active_paths); csdev->node = node; return 0; } int coresight_enable(struct coresight_device *csdev) { int cpu, ret = 0; int ret = 0; struct coresight_device *sink; struct list_head *path; enum coresight_dev_subtype_source subtype; Loading Loading @@ -643,25 +680,9 @@ int coresight_enable(struct coresight_device *csdev) if (ret) goto err_source; switch (subtype) { case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: /* * When working from sysFS it is important to keep track * of the paths that were created so that they can be * undone in 'coresight_disable()'. Since there can only * be a single session per tracer (when working from sysFS) * a per-cpu variable will do just fine. */ cpu = source_ops(csdev)->cpu_id(csdev); per_cpu(tracer_path, cpu) = path; break; case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: stm_path = path; break; default: /* We can't be here */ break; } ret = coresight_store_path(csdev, path); if (ret) goto err_source; out: mutex_unlock(&coresight_mutex); Loading @@ -671,15 +692,14 @@ int coresight_enable(struct coresight_device *csdev) coresight_disable_path(path); err_path: coresight_release_path(path); coresight_release_path(csdev, path); goto out; } EXPORT_SYMBOL_GPL(coresight_enable); void coresight_disable(struct coresight_device *csdev) { int cpu, ret; struct list_head *path = NULL; int ret; mutex_lock(&coresight_mutex); Loading @@ -690,23 +710,11 @@ void coresight_disable(struct coresight_device *csdev) if (!csdev->enable || !coresight_disable_source(csdev)) goto out; switch (csdev->subtype.source_subtype) { case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: cpu = source_ops(csdev)->cpu_id(csdev); path = per_cpu(tracer_path, cpu); per_cpu(tracer_path, cpu) = NULL; break; case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: path = stm_path; stm_path = NULL; break; default: /* We can't be here */ break; } if (csdev->node == NULL) goto out; coresight_disable_path(path); coresight_release_path(path); coresight_disable_path(csdev->node->path); coresight_release_path(csdev, csdev->node->path); out: mutex_unlock(&coresight_mutex); Loading
include/linux/coresight.h +1 −0 Original line number Diff line number Diff line Loading @@ -171,6 +171,7 @@ struct coresight_device { const struct coresight_ops *ops; struct device dev; atomic_t *refcnt; struct coresight_path *node; bool orphan; bool enable; /* true only if configured as part of a path */ bool activated; /* true only if a sink is part of a path */ Loading