Skip to content

Commit 6148652

Browse files
James-A-ClarkSuzuki K Poulose
authored andcommitted
coresight: Enable and disable helper devices adjacent to the path
Currently CATU is the only helper device, and its enable and disable calls are hard coded. To allow more helper devices to be added in a generic way, remove these hard coded calls and just enable and disable all helper devices. This has to apply to helpers adjacent to the path, because they will never be in the path. CATU was already discovered in this way, so there is no change there. One change that is needed is for CATU to call back into ETR to allocate the buffer. Because the enable call was previously hard coded, it was done at a point where the buffer was already allocated, but this is no longer the case. Reviewed-by: Mike Leach <[email protected]> Signed-off-by: James Clark <[email protected]> Signed-off-by: Suzuki K Poulose <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 296b01f commit 6148652

File tree

6 files changed

+188
-55
lines changed

6 files changed

+188
-55
lines changed

drivers/hwtracing/coresight/coresight-catu.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -395,13 +395,18 @@ static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
395395
return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1);
396396
}
397397

398-
static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
398+
static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
399+
void *data)
399400
{
400401
int rc;
401402
u32 control, mode;
402-
struct etr_buf *etr_buf = data;
403+
struct etr_buf *etr_buf = NULL;
403404
struct device *dev = &drvdata->csdev->dev;
404405
struct coresight_device *csdev = drvdata->csdev;
406+
struct coresight_device *etrdev;
407+
union coresight_dev_subtype etr_subtype = {
408+
.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM
409+
};
405410

406411
if (catu_wait_for_ready(drvdata))
407412
dev_warn(dev, "Timeout while waiting for READY\n");
@@ -416,6 +421,13 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
416421
if (rc)
417422
return rc;
418423

424+
etrdev = coresight_find_input_type(
425+
csdev->pdata, CORESIGHT_DEV_TYPE_SINK, etr_subtype);
426+
if (etrdev) {
427+
etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, data);
428+
if (IS_ERR(etr_buf))
429+
return PTR_ERR(etr_buf);
430+
}
419431
control |= BIT(CATU_CONTROL_ENABLE);
420432

421433
if (etr_buf && etr_buf->mode == ETR_MODE_CATU) {
@@ -441,13 +453,14 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
441453
return 0;
442454
}
443455

444-
static int catu_enable(struct coresight_device *csdev, void *data)
456+
static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
457+
void *data)
445458
{
446459
int rc;
447460
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
448461

449462
CS_UNLOCK(catu_drvdata->base);
450-
rc = catu_enable_hw(catu_drvdata, data);
463+
rc = catu_enable_hw(catu_drvdata, mode, data);
451464
CS_LOCK(catu_drvdata->base);
452465
return rc;
453466
}

drivers/hwtracing/coresight/coresight-core.c

Lines changed: 150 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -403,8 +403,8 @@ static void coresight_disable_link(struct coresight_device *csdev,
403403
csdev->enable = false;
404404
}
405405

406-
static int coresight_enable_source(struct coresight_device *csdev,
407-
enum cs_mode mode)
406+
int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode,
407+
void *data)
408408
{
409409
int ret;
410410

@@ -413,7 +413,7 @@ static int coresight_enable_source(struct coresight_device *csdev,
413413
ret = coresight_control_assoc_ectdev(csdev, true);
414414
if (ret)
415415
return ret;
416-
ret = source_ops(csdev)->enable(csdev, NULL, mode);
416+
ret = source_ops(csdev)->enable(csdev, data, mode);
417417
if (ret) {
418418
coresight_control_assoc_ectdev(csdev, false);
419419
return ret;
@@ -426,25 +426,75 @@ static int coresight_enable_source(struct coresight_device *csdev,
426426

427427
return 0;
428428
}
429+
EXPORT_SYMBOL_GPL(coresight_enable_source);
430+
431+
static bool coresight_is_helper(struct coresight_device *csdev)
432+
{
433+
return csdev->type == CORESIGHT_DEV_TYPE_HELPER;
434+
}
435+
436+
static int coresight_enable_helper(struct coresight_device *csdev,
437+
enum cs_mode mode, void *data)
438+
{
439+
int ret;
440+
441+
if (!helper_ops(csdev)->enable)
442+
return 0;
443+
ret = helper_ops(csdev)->enable(csdev, mode, data);
444+
if (ret)
445+
return ret;
446+
447+
csdev->enable = true;
448+
return 0;
449+
}
450+
451+
static void coresight_disable_helper(struct coresight_device *csdev)
452+
{
453+
int ret;
454+
455+
if (!helper_ops(csdev)->disable)
456+
return;
457+
458+
ret = helper_ops(csdev)->disable(csdev, NULL);
459+
if (ret)
460+
return;
461+
csdev->enable = false;
462+
}
463+
464+
static void coresight_disable_helpers(struct coresight_device *csdev)
465+
{
466+
int i;
467+
struct coresight_device *helper;
468+
469+
for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
470+
helper = csdev->pdata->out_conns[i]->dest_dev;
471+
if (helper && coresight_is_helper(helper))
472+
coresight_disable_helper(helper);
473+
}
474+
}
429475

430476
/**
431477
* coresight_disable_source - Drop the reference count by 1 and disable
432478
* the device if there are no users left.
433479
*
434480
* @csdev: The coresight device to disable
481+
* @data: Opaque data to pass on to the disable function of the source device.
482+
* For example in perf mode this is a pointer to the struct perf_event.
435483
*
436484
* Returns true if the device has been disabled.
437485
*/
438-
static bool coresight_disable_source(struct coresight_device *csdev)
486+
bool coresight_disable_source(struct coresight_device *csdev, void *data)
439487
{
440488
if (atomic_dec_return(&csdev->refcnt) == 0) {
441489
if (source_ops(csdev)->disable)
442-
source_ops(csdev)->disable(csdev, NULL);
490+
source_ops(csdev)->disable(csdev, data);
443491
coresight_control_assoc_ectdev(csdev, false);
492+
coresight_disable_helpers(csdev);
444493
csdev->enable = false;
445494
}
446495
return !csdev->enable;
447496
}
497+
EXPORT_SYMBOL_GPL(coresight_disable_source);
448498

449499
/*
450500
* coresight_disable_path_from : Disable components in the given path beyond
@@ -495,6 +545,9 @@ static void coresight_disable_path_from(struct list_head *path,
495545
default:
496546
break;
497547
}
548+
549+
/* Disable all helpers adjacent along the path last */
550+
coresight_disable_helpers(csdev);
498551
}
499552
}
500553

@@ -504,9 +557,28 @@ void coresight_disable_path(struct list_head *path)
504557
}
505558
EXPORT_SYMBOL_GPL(coresight_disable_path);
506559

507-
int coresight_enable_path(struct list_head *path, enum cs_mode mode, void *sink_data)
560+
static int coresight_enable_helpers(struct coresight_device *csdev,
561+
enum cs_mode mode, void *data)
508562
{
563+
int i, ret = 0;
564+
struct coresight_device *helper;
565+
566+
for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
567+
helper = csdev->pdata->out_conns[i]->dest_dev;
568+
if (!helper || !coresight_is_helper(helper))
569+
continue;
570+
571+
ret = coresight_enable_helper(helper, mode, data);
572+
if (ret)
573+
return ret;
574+
}
509575

576+
return 0;
577+
}
578+
579+
int coresight_enable_path(struct list_head *path, enum cs_mode mode,
580+
void *sink_data)
581+
{
510582
int ret = 0;
511583
u32 type;
512584
struct coresight_node *nd;
@@ -516,6 +588,10 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode, void *sink_
516588
csdev = nd->csdev;
517589
type = csdev->type;
518590

591+
/* Enable all helpers adjacent to the path first */
592+
ret = coresight_enable_helpers(csdev, mode, sink_data);
593+
if (ret)
594+
goto err;
519595
/*
520596
* ETF devices are tricky... They can be a link or a sink,
521597
* depending on how they are configured. If an ETF has been
@@ -710,7 +786,7 @@ static int coresight_grab_device(struct coresight_device *csdev)
710786
struct coresight_device *child;
711787

712788
child = csdev->pdata->out_conns[i]->dest_dev;
713-
if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
789+
if (child && coresight_is_helper(child))
714790
if (!coresight_get_ref(child))
715791
goto err;
716792
}
@@ -721,7 +797,7 @@ static int coresight_grab_device(struct coresight_device *csdev)
721797
struct coresight_device *child;
722798

723799
child = csdev->pdata->out_conns[i]->dest_dev;
724-
if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
800+
if (child && coresight_is_helper(child))
725801
coresight_put_ref(child);
726802
}
727803
return -ENODEV;
@@ -740,7 +816,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
740816
struct coresight_device *child;
741817

742818
child = csdev->pdata->out_conns[i]->dest_dev;
743-
if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
819+
if (child && coresight_is_helper(child))
744820
coresight_put_ref(child);
745821
}
746822
}
@@ -1102,7 +1178,7 @@ int coresight_enable(struct coresight_device *csdev)
11021178
if (ret)
11031179
goto err_path;
11041180

1105-
ret = coresight_enable_source(csdev, CS_MODE_SYSFS);
1181+
ret = coresight_enable_source(csdev, CS_MODE_SYSFS, NULL);
11061182
if (ret)
11071183
goto err_source;
11081184

@@ -1159,7 +1235,7 @@ void coresight_disable(struct coresight_device *csdev)
11591235
if (ret)
11601236
goto out;
11611237

1162-
if (!csdev->enable || !coresight_disable_source(csdev))
1238+
if (!csdev->enable || !coresight_disable_source(csdev, NULL))
11631239
goto out;
11641240

11651241
switch (csdev->subtype.source_subtype) {
@@ -1644,6 +1720,69 @@ static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
16441720
return -ENOENT;
16451721
}
16461722

1723+
static bool coresight_compare_type(enum coresight_dev_type type_a,
1724+
union coresight_dev_subtype subtype_a,
1725+
enum coresight_dev_type type_b,
1726+
union coresight_dev_subtype subtype_b)
1727+
{
1728+
if (type_a != type_b)
1729+
return false;
1730+
1731+
switch (type_a) {
1732+
case CORESIGHT_DEV_TYPE_SINK:
1733+
return subtype_a.sink_subtype == subtype_b.sink_subtype;
1734+
case CORESIGHT_DEV_TYPE_LINK:
1735+
return subtype_a.link_subtype == subtype_b.link_subtype;
1736+
case CORESIGHT_DEV_TYPE_LINKSINK:
1737+
return subtype_a.link_subtype == subtype_b.link_subtype &&
1738+
subtype_a.sink_subtype == subtype_b.sink_subtype;
1739+
case CORESIGHT_DEV_TYPE_SOURCE:
1740+
return subtype_a.source_subtype == subtype_b.source_subtype;
1741+
case CORESIGHT_DEV_TYPE_HELPER:
1742+
return subtype_a.helper_subtype == subtype_b.helper_subtype;
1743+
default:
1744+
return false;
1745+
}
1746+
}
1747+
1748+
struct coresight_device *
1749+
coresight_find_input_type(struct coresight_platform_data *pdata,
1750+
enum coresight_dev_type type,
1751+
union coresight_dev_subtype subtype)
1752+
{
1753+
int i;
1754+
struct coresight_connection *conn;
1755+
1756+
for (i = 0; i < pdata->nr_inconns; ++i) {
1757+
conn = pdata->in_conns[i];
1758+
if (conn &&
1759+
coresight_compare_type(type, subtype, conn->src_dev->type,
1760+
conn->src_dev->subtype))
1761+
return conn->src_dev;
1762+
}
1763+
return NULL;
1764+
}
1765+
EXPORT_SYMBOL_GPL(coresight_find_input_type);
1766+
1767+
struct coresight_device *
1768+
coresight_find_output_type(struct coresight_platform_data *pdata,
1769+
enum coresight_dev_type type,
1770+
union coresight_dev_subtype subtype)
1771+
{
1772+
int i;
1773+
struct coresight_connection *conn;
1774+
1775+
for (i = 0; i < pdata->nr_outconns; ++i) {
1776+
conn = pdata->out_conns[i];
1777+
if (conn->dest_dev &&
1778+
coresight_compare_type(type, subtype, conn->dest_dev->type,
1779+
conn->dest_dev->subtype))
1780+
return conn->dest_dev;
1781+
}
1782+
return NULL;
1783+
}
1784+
EXPORT_SYMBOL_GPL(coresight_find_output_type);
1785+
16471786
bool coresight_loses_context_with_cpu(struct device *dev)
16481787
{
16491788
return fwnode_property_present(dev_fwnode(dev),

drivers/hwtracing/coresight/coresight-etm-perf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ static void etm_event_start(struct perf_event *event, int flags)
493493
goto fail_end_stop;
494494

495495
/* Finally enable the tracer */
496-
if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF))
496+
if (coresight_enable_source(csdev, CS_MODE_PERF, event))
497497
goto fail_disable_path;
498498

499499
/*
@@ -587,7 +587,7 @@ static void etm_event_stop(struct perf_event *event, int mode)
587587
return;
588588

589589
/* stop tracer */
590-
source_ops(csdev)->disable(csdev, event);
590+
coresight_disable_source(csdev, event);
591591

592592
/* tell the core */
593593
event->hw.state = PERF_HES_STOPPED;

drivers/hwtracing/coresight/coresight-priv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,5 +216,8 @@ void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev,
216216

217217
void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
218218
struct coresight_device *coresight_get_percpu_sink(int cpu);
219+
int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode,
220+
void *data);
221+
bool coresight_disable_source(struct coresight_device *csdev, void *data);
219222

220223
#endif

0 commit comments

Comments
 (0)