| From 1edcdf2f87e3daebe7299f5d403dca6ad621aaa9 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 16 Sep 2020 13:17:35 -0600 |
| Subject: coresight: Make sysfs functional on topologies with per core sink |
| |
| From: Linu Cherian <lcherian@marvell.com> |
| |
| [ Upstream commit 6d578258b955fc8888e1bbd9a8fefe7b10065a84 ] |
| |
| Coresight driver assumes sink is common across all the ETMs, |
| and tries to build a path between ETM and the first enabled |
| sink found using bus based search. This breaks sysFS usage |
| on implementations that has multiple per core sinks in |
| enabled state. |
| |
| To fix this, coresight_get_enabled_sink API is updated to |
| do a connection based search starting from the given source, |
| instead of bus based search. |
| With sink selection using sysfs depecrated for perf interface, |
| provision for reset is removed as well in this API. |
| |
| Signed-off-by: Linu Cherian <lcherian@marvell.com> |
| [Fixed indentation problem and removed obsolete comment] |
| Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> |
| Link: https://lore.kernel.org/r/20200916191737.4001561-15-mathieu.poirier@linaro.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/hwtracing/coresight/coresight-priv.h | 3 +- |
| drivers/hwtracing/coresight/coresight.c | 62 +++++++++----------- |
| 2 files changed, 29 insertions(+), 36 deletions(-) |
| |
| diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h |
| index f2dc625ea5856..5fe773c4d6cc5 100644 |
| --- a/drivers/hwtracing/coresight/coresight-priv.h |
| +++ b/drivers/hwtracing/coresight/coresight-priv.h |
| @@ -148,7 +148,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 *source); |
| struct coresight_device *coresight_get_sink_by_id(u32 id); |
| struct coresight_device * |
| coresight_find_default_sink(struct coresight_device *csdev); |
| diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c |
| index cdcb1917216fd..fd46216669449 100644 |
| --- a/drivers/hwtracing/coresight/coresight.c |
| +++ b/drivers/hwtracing/coresight/coresight.c |
| @@ -540,50 +540,46 @@ struct coresight_device *coresight_get_sink(struct list_head *path) |
| return csdev; |
| } |
| |
| -static int coresight_enabled_sink(struct device *dev, const void *data) |
| +static struct coresight_device * |
| +coresight_find_enabled_sink(struct coresight_device *csdev) |
| { |
| - const bool *reset = data; |
| - struct coresight_device *csdev = to_coresight_device(dev); |
| + int i; |
| + struct coresight_device *sink; |
| |
| if ((csdev->type == CORESIGHT_DEV_TYPE_SINK || |
| csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && |
| - csdev->activated) { |
| - /* |
| - * Now that we have a handle on the sink for this session, |
| - * disable the sysFS "enable_sink" flag so that possible |
| - * concurrent perf session that wish to use another sink don't |
| - * trip on it. Doing so has no ramification for the current |
| - * session. |
| - */ |
| - if (*reset) |
| - csdev->activated = false; |
| + csdev->activated) |
| + return csdev; |
| |
| - return 1; |
| + /* |
| + * Recursively explore each port found on this element. |
| + */ |
| + for (i = 0; i < csdev->pdata->nr_outport; i++) { |
| + struct coresight_device *child_dev; |
| + |
| + child_dev = csdev->pdata->conns[i].child_dev; |
| + if (child_dev) |
| + sink = coresight_find_enabled_sink(child_dev); |
| + if (sink) |
| + return sink; |
| } |
| |
| - return 0; |
| + return NULL; |
| } |
| |
| /** |
| - * coresight_get_enabled_sink - returns the first enabled sink found on the bus |
| - * @deactivate: Whether the 'enable_sink' flag should be reset |
| - * |
| - * When operated from perf the deactivate parameter should be set to 'true'. |
| - * That way the "enabled_sink" flag of the sink that was selected can be reset, |
| - * allowing for other concurrent perf sessions to choose a different sink. |
| + * coresight_get_enabled_sink - returns the first enabled sink using |
| + * connection based search starting from the source reference |
| * |
| - * When operated from sysFS users have full control and as such the deactivate |
| - * parameter should be set to 'false', hence mandating users to explicitly |
| - * clear the flag. |
| + * @source: Coresight source device reference |
| */ |
| -struct coresight_device *coresight_get_enabled_sink(bool deactivate) |
| +struct coresight_device * |
| +coresight_get_enabled_sink(struct coresight_device *source) |
| { |
| - struct device *dev = NULL; |
| - |
| - dev = bus_find_device(&coresight_bustype, NULL, &deactivate, |
| - coresight_enabled_sink); |
| + if (!source) |
| + return NULL; |
| |
| - return dev ? to_coresight_device(dev) : NULL; |
| + return coresight_find_enabled_sink(source); |
| } |
| |
| static int coresight_sink_by_id(struct device *dev, const void *data) |
| @@ -988,11 +984,7 @@ int coresight_enable(struct coresight_device *csdev) |
| goto out; |
| } |
| |
| - /* |
| - * 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); |
| if (!sink) { |
| ret = -EINVAL; |
| goto out; |
| -- |
| 2.27.0 |
| |