aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuzuki K Poulose <suzuki.poulose@arm.com>2018-09-20 15:18:03 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-09-25 14:09:18 -0400
commitb9866bb16882e89b57e2dc826114316357263fb7 (patch)
treed24736cd28364ae42366b0da723963d3ec425bf3
parente7753f3937610633a540f2be81be87531f96ff04 (diff)
coresight: Handle failures in enabling a trace path
coresight_enable_path() enables the components in a trace path from a given source to a sink, excluding the source. The operation is performed in the reverse order; the sink first and then backwards in the list. However, if we encounter an error in enabling any of the component, we simply disable all the components in the given path irrespective of whether we enabled some of the components in the enable iteration. This could interfere with another trace session if one of the link devices is turned off (e.g, TMC-ETF). So, we need to make sure that we only disable those components which were actually enabled from the iteration. This patch achieves the same by refactoring the coresight_disable_path to accept a "node" to start from in the forward order, which can then be used from the error path of coresight_enable_path(). With this change, we don't issue a disable call back for a component which didn't get enabled. This change of behavior triggers a bug in coresight_enable_link(), where we leave the refcount on the device and will prevent the device from being enabled forever. So, we also drop the refcount in the coresight_enable_link() if the operation failed. Also, with the refactoring, we always start after the first node (which is the "SOURCE" device) for disabling the entire path. This implies, we must not find a "SOURCE" in the middle of the path. Hence, added a WARN_ON() to make sure the paths we get are sane, rather than simply ignoring them. Cc: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/hwtracing/coresight/coresight.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index e73ca6af4765..f4f50753cf75 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -187,8 +187,10 @@ static int coresight_enable_link(struct coresight_device *csdev,
187 if (atomic_inc_return(&csdev->refcnt[refport]) == 1) { 187 if (atomic_inc_return(&csdev->refcnt[refport]) == 1) {
188 if (link_ops(csdev)->enable) { 188 if (link_ops(csdev)->enable) {
189 ret = link_ops(csdev)->enable(csdev, inport, outport); 189 ret = link_ops(csdev)->enable(csdev, inport, outport);
190 if (ret) 190 if (ret) {
191 atomic_dec(&csdev->refcnt[refport]);
191 return ret; 192 return ret;
193 }
192 } 194 }
193 } 195 }
194 196
@@ -277,13 +279,21 @@ static bool coresight_disable_source(struct coresight_device *csdev)
277 return !csdev->enable; 279 return !csdev->enable;
278} 280}
279 281
280void coresight_disable_path(struct list_head *path) 282/*
283 * coresight_disable_path_from : Disable components in the given path beyond
284 * @nd in the list. If @nd is NULL, all the components, except the SOURCE are
285 * disabled.
286 */
287static void coresight_disable_path_from(struct list_head *path,
288 struct coresight_node *nd)
281{ 289{
282 u32 type; 290 u32 type;
283 struct coresight_node *nd;
284 struct coresight_device *csdev, *parent, *child; 291 struct coresight_device *csdev, *parent, *child;
285 292
286 list_for_each_entry(nd, path, link) { 293 if (!nd)
294 nd = list_first_entry(path, struct coresight_node, link);
295
296 list_for_each_entry_continue(nd, path, link) {
287 csdev = nd->csdev; 297 csdev = nd->csdev;
288 type = csdev->type; 298 type = csdev->type;
289 299
@@ -303,7 +313,12 @@ void coresight_disable_path(struct list_head *path)
303 coresight_disable_sink(csdev); 313 coresight_disable_sink(csdev);
304 break; 314 break;
305 case CORESIGHT_DEV_TYPE_SOURCE: 315 case CORESIGHT_DEV_TYPE_SOURCE:
306 /* sources are disabled from either sysFS or Perf */ 316 /*
317 * We skip the first node in the path assuming that it
318 * is the source. So we don't expect a source device in
319 * the middle of a path.
320 */
321 WARN_ON(1);
307 break; 322 break;
308 case CORESIGHT_DEV_TYPE_LINK: 323 case CORESIGHT_DEV_TYPE_LINK:
309 parent = list_prev_entry(nd, link)->csdev; 324 parent = list_prev_entry(nd, link)->csdev;
@@ -316,6 +331,11 @@ void coresight_disable_path(struct list_head *path)
316 } 331 }
317} 332}
318 333
334void coresight_disable_path(struct list_head *path)
335{
336 coresight_disable_path_from(path, NULL);
337}
338
319int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data) 339int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data)
320{ 340{
321 341
@@ -369,7 +389,7 @@ int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data)
369out: 389out:
370 return ret; 390 return ret;
371err: 391err:
372 coresight_disable_path(path); 392 coresight_disable_path_from(path, nd);
373 goto out; 393 goto out;
374} 394}
375 395