Skip to content

Commit 177af82

Browse files
mikel-armbbgregkh
authored andcommitted
coresight: cti: Enable CTI associated with devices
The CoreSight subsystem enables a path of devices from source to sink. Any CTI devices associated with the path devices must be enabled at the same time. This patch adds an associated coresight_device element to the main coresight device structure, and uses this to create associations between the CTI and other devices based on the device tree data. The associated device element is used to enable CTI in conjunction with the path elements. CTI devices are reference counted so where a single CTI is associated with multiple elements on the path, it will be enabled on the first associated device enable, and disabled with the last associated device disable. Signed-off-by: Mike Leach <mike.leach@linaro.org> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Link: https://lore.kernel.org/r/20200320165303.13681-9-mathieu.poirier@linaro.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent a561477 commit 177af82

File tree

5 files changed

+208
-5
lines changed

5 files changed

+208
-5
lines changed

drivers/hwtracing/coresight/coresight-cti.c

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Author: Mike Leach <mike.leach@linaro.org>
55
*/
66

7+
#include <linux/property.h>
78
#include "coresight-cti.h"
89

910
/**
@@ -441,6 +442,127 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
441442
return err;
442443
}
443444

445+
/*
446+
* Look for a matching connection device name in the list of connections.
447+
* If found then swap in the csdev name, set trig con association pointer
448+
* and return found.
449+
*/
450+
static bool
451+
cti_match_fixup_csdev(struct cti_device *ctidev, const char *node_name,
452+
struct coresight_device *csdev)
453+
{
454+
struct cti_trig_con *tc;
455+
456+
list_for_each_entry(tc, &ctidev->trig_cons, node) {
457+
if (tc->con_dev_name) {
458+
if (!strcmp(node_name, tc->con_dev_name)) {
459+
/* match: so swap in csdev name & dev */
460+
tc->con_dev_name = dev_name(&csdev->dev);
461+
tc->con_dev = csdev;
462+
return true;
463+
}
464+
}
465+
}
466+
return false;
467+
}
468+
469+
/*
470+
* Search the cti list to add an associated CTI into the supplied CS device
471+
* This will set the association if CTI declared before the CS device.
472+
* (called from coresight_register() with coresight_mutex locked).
473+
*/
474+
void cti_add_assoc_to_csdev(struct coresight_device *csdev)
475+
{
476+
struct cti_drvdata *ect_item;
477+
struct cti_device *ctidev;
478+
const char *node_name = NULL;
479+
480+
/* protect the list */
481+
mutex_lock(&ect_mutex);
482+
483+
/* exit if current is an ECT device.*/
484+
if ((csdev->type == CORESIGHT_DEV_TYPE_ECT) || list_empty(&ect_net))
485+
goto cti_add_done;
486+
487+
/* if we didn't find the csdev previously we used the fwnode name */
488+
node_name = cti_plat_get_node_name(dev_fwnode(csdev->dev.parent));
489+
if (!node_name)
490+
goto cti_add_done;
491+
492+
/* for each CTI in list... */
493+
list_for_each_entry(ect_item, &ect_net, node) {
494+
ctidev = &ect_item->ctidev;
495+
if (cti_match_fixup_csdev(ctidev, node_name, csdev)) {
496+
/*
497+
* if we found a matching csdev then update the ECT
498+
* association pointer for the device with this CTI.
499+
*/
500+
csdev->ect_dev = ect_item->csdev;
501+
break;
502+
}
503+
}
504+
cti_add_done:
505+
mutex_unlock(&ect_mutex);
506+
}
507+
EXPORT_SYMBOL_GPL(cti_add_assoc_to_csdev);
508+
509+
/*
510+
* Removing the associated devices is easier.
511+
* A CTI will not have a value for csdev->ect_dev.
512+
*/
513+
void cti_remove_assoc_from_csdev(struct coresight_device *csdev)
514+
{
515+
struct cti_drvdata *ctidrv;
516+
struct cti_trig_con *tc;
517+
struct cti_device *ctidev;
518+
519+
mutex_lock(&ect_mutex);
520+
if (csdev->ect_dev) {
521+
ctidrv = csdev_to_cti_drvdata(csdev->ect_dev);
522+
ctidev = &ctidrv->ctidev;
523+
list_for_each_entry(tc, &ctidev->trig_cons, node) {
524+
if (tc->con_dev == csdev->ect_dev) {
525+
tc->con_dev = NULL;
526+
break;
527+
}
528+
}
529+
csdev->ect_dev = NULL;
530+
}
531+
mutex_unlock(&ect_mutex);
532+
}
533+
EXPORT_SYMBOL_GPL(cti_remove_assoc_from_csdev);
534+
535+
/*
536+
* Update the cross references where the associated device was found
537+
* while we were building the connection info. This will occur if the
538+
* assoc device was registered before the CTI.
539+
*/
540+
static void cti_update_conn_xrefs(struct cti_drvdata *drvdata)
541+
{
542+
struct cti_trig_con *tc;
543+
struct cti_device *ctidev = &drvdata->ctidev;
544+
545+
list_for_each_entry(tc, &ctidev->trig_cons, node) {
546+
if (tc->con_dev)
547+
/* set tc->con_dev->ect_dev */
548+
coresight_set_assoc_ectdev_mutex(tc->con_dev,
549+
drvdata->csdev);
550+
}
551+
}
552+
553+
static void cti_remove_conn_xrefs(struct cti_drvdata *drvdata)
554+
{
555+
struct cti_trig_con *tc;
556+
struct cti_device *ctidev = &drvdata->ctidev;
557+
558+
list_for_each_entry(tc, &ctidev->trig_cons, node) {
559+
if (tc->con_dev) {
560+
coresight_set_assoc_ectdev_mutex(tc->con_dev,
561+
NULL);
562+
}
563+
}
564+
}
565+
444566
/** cti ect operations **/
445567
int cti_enable(struct coresight_device *csdev)
446568
{
@@ -475,6 +597,7 @@ static void cti_device_release(struct device *dev)
475597
struct cti_drvdata *ect_item, *ect_tmp;
476598

477599
mutex_lock(&ect_mutex);
600+
cti_remove_conn_xrefs(drvdata);
478601

479602
/* remove from the list */
480603
list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
@@ -566,6 +689,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
566689
/* add to list of CTI devices */
567690
mutex_lock(&ect_mutex);
568691
list_add(&drvdata->node, &ect_net);
692+
/* set any cross references */
693+
cti_update_conn_xrefs(drvdata);
569694
mutex_unlock(&ect_mutex);
570695

571696
/* set up release chain */

drivers/hwtracing/coresight/coresight-cti.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
216216
u32 channel_idx);
217217
struct coresight_platform_data *
218218
coresight_cti_get_platform_data(struct device *dev);
219+
const char *cti_plat_get_node_name(struct fwnode_handle *fwnode);
219220

220221
/* cti powered and enabled */
221222
static inline bool cti_active(struct cti_config *cfg)

drivers/hwtracing/coresight/coresight-priv.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,16 @@ static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
162162
static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
163163
#endif
164164

165+
#ifdef CONFIG_CORESIGHT_CTI
166+
extern void cti_add_assoc_to_csdev(struct coresight_device *csdev);
167+
extern void cti_remove_assoc_from_csdev(struct coresight_device *csdev);
168+
169+
#else
170+
static inline void cti_add_assoc_to_csdev(struct coresight_device *csdev) {}
171+
static inline void
172+
cti_remove_assoc_from_csdev(struct coresight_device *csdev) {}
173+
#endif
174+
165175
/*
166176
* Macros and inline functions to handle CoreSight UCI data and driver
167177
* private data in AMBA ID table entries, and extract data values.
@@ -204,5 +214,7 @@ static inline void *coresight_get_uci_data(const struct amba_id *id)
204214
void coresight_release_platform_data(struct coresight_platform_data *pdata);
205215
struct coresight_device *
206216
coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode);
217+
void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev,
218+
struct coresight_device *ect_csdev);
207219

208220
#endif

drivers/hwtracing/coresight/coresight.c

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,44 @@ void coresight_disclaim_device(void __iomem *base)
216216
CS_LOCK(base);
217217
}
218218

219+
/* enable or disable an associated CTI device of the supplied CS device */
220+
static int
221+
coresight_control_assoc_ectdev(struct coresight_device *csdev, bool enable)
222+
{
223+
int ect_ret = 0;
224+
struct coresight_device *ect_csdev = csdev->ect_dev;
225+
226+
if (!ect_csdev)
227+
return 0;
228+
229+
if (enable) {
230+
if (ect_ops(ect_csdev)->enable)
231+
ect_ret = ect_ops(ect_csdev)->enable(ect_csdev);
232+
} else {
233+
if (ect_ops(ect_csdev)->disable)
234+
ect_ret = ect_ops(ect_csdev)->disable(ect_csdev);
235+
}
236+
237+
/* output warning if ECT enable is preventing trace operation */
238+
if (ect_ret)
239+
dev_info(&csdev->dev, "Associated ECT device (%s) %s failed\n",
240+
dev_name(&ect_csdev->dev),
241+
enable ? "enable" : "disable");
242+
return ect_ret;
243+
}
244+
245+
/*
246+
* Set the associated ect / cti device while holding the coresight_mutex
247+
* to avoid a race with coresight_enable that may try to use this value.
248+
*/
249+
void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev,
250+
struct coresight_device *ect_csdev)
251+
{
252+
mutex_lock(&coresight_mutex);
253+
csdev->ect_dev = ect_csdev;
254+
mutex_unlock(&coresight_mutex);
255+
}
256+
219257
static int coresight_enable_sink(struct coresight_device *csdev,
220258
u32 mode, void *data)
221259
{
@@ -228,9 +266,14 @@ static int coresight_enable_sink(struct coresight_device *csdev,
228266
if (!sink_ops(csdev)->enable)
229267
return -EINVAL;
230268

231-
ret = sink_ops(csdev)->enable(csdev, mode, data);
269+
ret = coresight_control_assoc_ectdev(csdev, true);
232270
if (ret)
233271
return ret;
272+
ret = sink_ops(csdev)->enable(csdev, mode, data);
273+
if (ret) {
274+
coresight_control_assoc_ectdev(csdev, false);
275+
return ret;
276+
}
234277
csdev->enable = true;
235278

236279
return 0;
@@ -246,6 +289,7 @@ static void coresight_disable_sink(struct coresight_device *csdev)
246289
ret = sink_ops(csdev)->disable(csdev);
247290
if (ret)
248291
return;
292+
coresight_control_assoc_ectdev(csdev, false);
249293
csdev->enable = false;
250294
}
251295

@@ -269,8 +313,15 @@ static int coresight_enable_link(struct coresight_device *csdev,
269313
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && outport < 0)
270314
return outport;
271315

272-
if (link_ops(csdev)->enable)
273-
ret = link_ops(csdev)->enable(csdev, inport, outport);
316+
if (link_ops(csdev)->enable) {
317+
ret = coresight_control_assoc_ectdev(csdev, true);
318+
if (!ret) {
319+
ret = link_ops(csdev)->enable(csdev, inport, outport);
320+
if (ret)
321+
coresight_control_assoc_ectdev(csdev, false);
322+
}
323+
}
324+
274325
if (!ret)
275326
csdev->enable = true;
276327

@@ -300,8 +351,10 @@ static void coresight_disable_link(struct coresight_device *csdev,
300351
nr_conns = 1;
301352
}
302353

303-
if (link_ops(csdev)->disable)
354+
if (link_ops(csdev)->disable) {
304355
link_ops(csdev)->disable(csdev, inport, outport);
356+
coresight_control_assoc_ectdev(csdev, false);
357+
}
305358

306359
for (i = 0; i < nr_conns; i++)
307360
if (atomic_read(&csdev->refcnt[i]) != 0)
@@ -322,9 +375,14 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
322375

323376
if (!csdev->enable) {
324377
if (source_ops(csdev)->enable) {
325-
ret = source_ops(csdev)->enable(csdev, NULL, mode);
378+
ret = coresight_control_assoc_ectdev(csdev, true);
326379
if (ret)
327380
return ret;
381+
ret = source_ops(csdev)->enable(csdev, NULL, mode);
382+
if (ret) {
383+
coresight_control_assoc_ectdev(csdev, false);
384+
return ret;
385+
};
328386
}
329387
csdev->enable = true;
330388
}
@@ -347,6 +405,7 @@ static bool coresight_disable_source(struct coresight_device *csdev)
347405
if (atomic_dec_return(csdev->refcnt) == 0) {
348406
if (source_ops(csdev)->disable)
349407
source_ops(csdev)->disable(csdev, NULL);
408+
coresight_control_assoc_ectdev(csdev, false);
350409
csdev->enable = false;
351410
}
352411
return !csdev->enable;
@@ -964,6 +1023,7 @@ static void coresight_device_release(struct device *dev)
9641023
{
9651024
struct coresight_device *csdev = to_coresight_device(dev);
9661025

1026+
cti_remove_assoc_from_csdev(csdev);
9671027
fwnode_handle_put(csdev->dev.fwnode);
9681028
kfree(csdev->refcnt);
9691029
kfree(csdev);
@@ -1246,6 +1306,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
12461306

12471307
coresight_fixup_device_conns(csdev);
12481308
coresight_fixup_orphan_conns(csdev);
1309+
cti_add_assoc_to_csdev(csdev);
12491310

12501311
mutex_unlock(&coresight_mutex);
12511312

include/linux/coresight.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ struct coresight_connection {
163163
* activated but not yet enabled. Enabling for a _sink_
164164
* appens when a source has been selected for that it.
165165
* @ea: Device attribute for sink representation under PMU directory.
166+
* @ect_dev: Associated cross trigger device. Not part of the trace data
167+
* path or connections.
166168
*/
167169
struct coresight_device {
168170
struct coresight_platform_data *pdata;
@@ -176,6 +178,8 @@ struct coresight_device {
176178
/* sink specific fields */
177179
bool activated; /* true only if a sink is part of a path */
178180
struct dev_ext_attribute *ea;
181+
/* cross trigger handling */
182+
struct coresight_device *ect_dev;
179183
};
180184

181185
/*

0 commit comments

Comments
 (0)