summaryrefslogtreecommitdiffstats
path: root/drivers/hwtracing
diff options
context:
space:
mode:
authorMathieu Poirier <mathieu.poirier@linaro.org>2016-11-29 11:47:14 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-11-29 14:05:32 -0500
commitd52c9750f150111dc7f73e4036f6948b20c9f8c3 (patch)
tree2dcb69bd6d84668bf12797e456e3d063a76d1c92 /drivers/hwtracing
parenta39f841a5b5b2215f99ed6dd6f75b8e06807a810 (diff)
coresight: reset "enable_sink" flag when need be
When using coresight from the perf interface sinks are specified as part of the perf command line. As such the sink needs to be disabled once it has been acknowledged by the coresight framework. Otherwise the sink stays enabled, which may interfere with other sessions. This patch removes the sink selection check from the build path process and make it a function on it's own. The function is then used when operating from sysFS or perf to determine what sink has been selected. If operated from perf the status of the "enable_sink" flag is reset so that concurrent session can use a different sink. When used from sysFS the status of the flag is left untouched since users have full control. The implementation doesn't handle a scenario where a sink has been enabled from sysFS and another sink is selected from the perf command line as both modes of operation are mutually exclusive. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hwtracing')
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.c31
-rw-r--r--drivers/hwtracing/coresight/coresight-priv.h4
-rw-r--r--drivers/hwtracing/coresight/coresight.c74
3 files changed, 87 insertions, 22 deletions
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 2cd7c718198a..5a346fc8ce06 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -202,6 +202,21 @@ static void *etm_setup_aux(int event_cpu, void **pages,
202 if (!event_data) 202 if (!event_data)
203 return NULL; 203 return NULL;
204 204
205 /*
206 * In theory nothing prevent tracers in a trace session from being
207 * associated with different sinks, nor having a sink per tracer. But
208 * until we have HW with this kind of topology we need to assume tracers
209 * in a trace session are using the same sink. Therefore go through
210 * the coresight bus and pick the first enabled sink.
211 *
212 * When operated from sysFS users are responsible to enable the sink
213 * while from perf, the perf tools will do it based on the choice made
214 * on the cmd line. As such the "enable_sink" flag in sysFS is reset.
215 */
216 sink = coresight_get_enabled_sink(true);
217 if (!sink)
218 return NULL;
219
205 INIT_WORK(&event_data->work, free_event_data); 220 INIT_WORK(&event_data->work, free_event_data);
206 221
207 mask = &event_data->mask; 222 mask = &event_data->mask;
@@ -219,25 +234,11 @@ static void *etm_setup_aux(int event_cpu, void **pages,
219 * list of devices from source to sink that can be 234 * list of devices from source to sink that can be
220 * referenced later when the path is actually needed. 235 * referenced later when the path is actually needed.
221 */ 236 */
222 event_data->path[cpu] = coresight_build_path(csdev); 237 event_data->path[cpu] = coresight_build_path(csdev, sink);
223 if (IS_ERR(event_data->path[cpu])) 238 if (IS_ERR(event_data->path[cpu]))
224 goto err; 239 goto err;
225 } 240 }
226 241
227 /*
228 * In theory nothing prevent tracers in a trace session from being
229 * associated with different sinks, nor having a sink per tracer. But
230 * until we have HW with this kind of topology and a way to convey
231 * sink assignement from the perf cmd line we need to assume tracers
232 * in a trace session are using the same sink. Therefore pick the sink
233 * found at the end of the first available path.
234 */
235 cpu = cpumask_first(mask);
236 /* Grab the sink at the end of the path */
237 sink = coresight_get_sink(event_data->path[cpu]);
238 if (!sink)
239 goto err;
240
241 if (!sink_ops(sink)->alloc_buffer) 242 if (!sink_ops(sink)->alloc_buffer)
242 goto err; 243 goto err;
243 244
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 196a14be4b3d..ef9d8e93e3b2 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -111,7 +111,9 @@ static inline void CS_UNLOCK(void __iomem *addr)
111void coresight_disable_path(struct list_head *path); 111void coresight_disable_path(struct list_head *path);
112int coresight_enable_path(struct list_head *path, u32 mode); 112int coresight_enable_path(struct list_head *path, u32 mode);
113struct coresight_device *coresight_get_sink(struct list_head *path); 113struct coresight_device *coresight_get_sink(struct list_head *path);
114struct list_head *coresight_build_path(struct coresight_device *csdev); 114struct coresight_device *coresight_get_enabled_sink(bool reset);
115struct list_head *coresight_build_path(struct coresight_device *csdev,
116 struct coresight_device *sink);
115void coresight_release_path(struct list_head *path); 117void coresight_release_path(struct list_head *path);
116 118
117#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X 119#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 7bf00a0beb6f..0c37356e417c 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -368,6 +368,52 @@ struct coresight_device *coresight_get_sink(struct list_head *path)
368 return csdev; 368 return csdev;
369} 369}
370 370
371static int coresight_enabled_sink(struct device *dev, void *data)
372{
373 bool *reset = data;
374 struct coresight_device *csdev = to_coresight_device(dev);
375
376 if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
377 csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
378 csdev->activated) {
379 /*
380 * Now that we have a handle on the sink for this session,
381 * disable the sysFS "enable_sink" flag so that possible
382 * concurrent perf session that wish to use another sink don't
383 * trip on it. Doing so has no ramification for the current
384 * session.
385 */
386 if (*reset)
387 csdev->activated = false;
388
389 return 1;
390 }
391
392 return 0;
393}
394
395/**
396 * coresight_get_enabled_sink - returns the first enabled sink found on the bus
397 * @deactivate: Whether the 'enable_sink' flag should be reset
398 *
399 * When operated from perf the deactivate parameter should be set to 'true'.
400 * That way the "enabled_sink" flag of the sink that was selected can be reset,
401 * allowing for other concurrent perf sessions to choose a different sink.
402 *
403 * When operated from sysFS users have full control and as such the deactivate
404 * parameter should be set to 'false', hence mandating users to explicitly
405 * clear the flag.
406 */
407struct coresight_device *coresight_get_enabled_sink(bool deactivate)
408{
409 struct device *dev = NULL;
410
411 dev = bus_find_device(&coresight_bustype, NULL, &deactivate,
412 coresight_enabled_sink);
413
414 return dev ? to_coresight_device(dev) : NULL;
415}
416
371/** 417/**
372 * _coresight_build_path - recursively build a path from a @csdev to a sink. 418 * _coresight_build_path - recursively build a path from a @csdev to a sink.
373 * @csdev: The device to start from. 419 * @csdev: The device to start from.
@@ -380,6 +426,7 @@ struct coresight_device *coresight_get_sink(struct list_head *path)
380 * last one. 426 * last one.
381 */ 427 */
382static int _coresight_build_path(struct coresight_device *csdev, 428static int _coresight_build_path(struct coresight_device *csdev,
429 struct coresight_device *sink,
383 struct list_head *path) 430 struct list_head *path)
384{ 431{
385 int i; 432 int i;
@@ -387,15 +434,15 @@ static int _coresight_build_path(struct coresight_device *csdev,
387 struct coresight_node *node; 434 struct coresight_node *node;
388 435
389 /* An activated sink has been found. Enqueue the element */ 436 /* An activated sink has been found. Enqueue the element */
390 if ((csdev->type == CORESIGHT_DEV_TYPE_SINK || 437 if (csdev == sink)
391 csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && csdev->activated)
392 goto out; 438 goto out;
393 439
394 /* Not a sink - recursively explore each port found on this element */ 440 /* Not a sink - recursively explore each port found on this element */
395 for (i = 0; i < csdev->nr_outport; i++) { 441 for (i = 0; i < csdev->nr_outport; i++) {
396 struct coresight_device *child_dev = csdev->conns[i].child_dev; 442 struct coresight_device *child_dev = csdev->conns[i].child_dev;
397 443
398 if (child_dev && _coresight_build_path(child_dev, path) == 0) { 444 if (child_dev &&
445 _coresight_build_path(child_dev, sink, path) == 0) {
399 found = true; 446 found = true;
400 break; 447 break;
401 } 448 }
@@ -422,18 +469,22 @@ out:
422 return 0; 469 return 0;
423} 470}
424 471
425struct list_head *coresight_build_path(struct coresight_device *csdev) 472struct list_head *coresight_build_path(struct coresight_device *source,
473 struct coresight_device *sink)
426{ 474{
427 struct list_head *path; 475 struct list_head *path;
428 int rc; 476 int rc;
429 477
478 if (!sink)
479 return ERR_PTR(-EINVAL);
480
430 path = kzalloc(sizeof(struct list_head), GFP_KERNEL); 481 path = kzalloc(sizeof(struct list_head), GFP_KERNEL);
431 if (!path) 482 if (!path)
432 return ERR_PTR(-ENOMEM); 483 return ERR_PTR(-ENOMEM);
433 484
434 INIT_LIST_HEAD(path); 485 INIT_LIST_HEAD(path);
435 486
436 rc = _coresight_build_path(csdev, path); 487 rc = _coresight_build_path(source, sink, path);
437 if (rc) { 488 if (rc) {
438 kfree(path); 489 kfree(path);
439 return ERR_PTR(rc); 490 return ERR_PTR(rc);
@@ -497,6 +548,7 @@ static int coresight_validate_source(struct coresight_device *csdev,
497int coresight_enable(struct coresight_device *csdev) 548int coresight_enable(struct coresight_device *csdev)
498{ 549{
499 int cpu, ret = 0; 550 int cpu, ret = 0;
551 struct coresight_device *sink;
500 struct list_head *path; 552 struct list_head *path;
501 553
502 mutex_lock(&coresight_mutex); 554 mutex_lock(&coresight_mutex);
@@ -508,7 +560,17 @@ int coresight_enable(struct coresight_device *csdev)
508 if (csdev->enable) 560 if (csdev->enable)
509 goto out; 561 goto out;
510 562
511 path = coresight_build_path(csdev); 563 /*
564 * Search for a valid sink for this session but don't reset the
565 * "enable_sink" flag in sysFS. Users get to do that explicitly.
566 */
567 sink = coresight_get_enabled_sink(false);
568 if (!sink) {
569 ret = -EINVAL;
570 goto out;
571 }
572
573 path = coresight_build_path(csdev, sink);
512 if (IS_ERR(path)) { 574 if (IS_ERR(path)) {
513 pr_err("building path(s) failed\n"); 575 pr_err("building path(s) failed\n");
514 ret = PTR_ERR(path); 576 ret = PTR_ERR(path);