Loading drivers/hwtracing/coresight/coresight-etm-perf.c +3 −1 Original line number Diff line number Diff line Loading @@ -120,6 +120,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 @@ -135,8 +136,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 +5 −2 Original line number Diff line number Diff line /* Copyright (c) 2011-2012, 2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2012, 2016-2017, The Linux Foundation. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -134,8 +135,10 @@ static inline bool coresight_authstatus_enabled(void __iomem *addr) void coresight_disable_path(struct list_head *path); int coresight_enable_path(struct list_head *path, u32 mode); struct coresight_device *coresight_get_sink(struct list_head *path); struct coresight_device *coresight_get_source(struct list_head *path); struct list_head *coresight_build_path(struct coresight_device *csdev); void coresight_release_path(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 +62 −53 Original line number Diff line number Diff line /* Copyright (c) 2012, The Linux Foundation. All rights reserved. /* Copyright (c) 2012, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -39,19 +39,17 @@ struct coresight_node { struct list_head link; }; /* * 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); static int coresight_id_match(struct device *dev, void *data) { Loading Loading @@ -152,6 +150,7 @@ static void coresight_disable_sink(struct coresight_device *csdev) if (sink_ops(csdev)->disable) { sink_ops(csdev)->disable(csdev); csdev->enable = false; csdev->activated = false; } } } Loading Loading @@ -353,6 +352,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 @@ -446,14 +459,23 @@ struct list_head *coresight_build_path(struct coresight_device *csdev) * 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 @@ -494,9 +516,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 list_head *path; mutex_lock(&coresight_mutex); Loading @@ -523,25 +561,9 @@ int coresight_enable(struct coresight_device *csdev) if (ret) goto err_source; switch (csdev->subtype.source_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 @@ -551,15 +573,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 @@ -570,24 +591,12 @@ void coresight_disable(struct coresight_device *csdev) if (!csdev->enable) 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_source(csdev); 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 +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2012, 2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012, 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -175,6 +175,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 @@ -120,6 +120,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 @@ -135,8 +136,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 +5 −2 Original line number Diff line number Diff line /* Copyright (c) 2011-2012, 2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2012, 2016-2017, The Linux Foundation. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -134,8 +135,10 @@ static inline bool coresight_authstatus_enabled(void __iomem *addr) void coresight_disable_path(struct list_head *path); int coresight_enable_path(struct list_head *path, u32 mode); struct coresight_device *coresight_get_sink(struct list_head *path); struct coresight_device *coresight_get_source(struct list_head *path); struct list_head *coresight_build_path(struct coresight_device *csdev); void coresight_release_path(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 +62 −53 Original line number Diff line number Diff line /* Copyright (c) 2012, The Linux Foundation. All rights reserved. /* Copyright (c) 2012, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -39,19 +39,17 @@ struct coresight_node { struct list_head link; }; /* * 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); static int coresight_id_match(struct device *dev, void *data) { Loading Loading @@ -152,6 +150,7 @@ static void coresight_disable_sink(struct coresight_device *csdev) if (sink_ops(csdev)->disable) { sink_ops(csdev)->disable(csdev); csdev->enable = false; csdev->activated = false; } } } Loading Loading @@ -353,6 +352,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 @@ -446,14 +459,23 @@ struct list_head *coresight_build_path(struct coresight_device *csdev) * 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 @@ -494,9 +516,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 list_head *path; mutex_lock(&coresight_mutex); Loading @@ -523,25 +561,9 @@ int coresight_enable(struct coresight_device *csdev) if (ret) goto err_source; switch (csdev->subtype.source_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 @@ -551,15 +573,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 @@ -570,24 +591,12 @@ void coresight_disable(struct coresight_device *csdev) if (!csdev->enable) 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_source(csdev); 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 +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2012, 2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012, 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -175,6 +175,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