Skip to content

Commit 4ff6039

Browse files
Yuanfang ZhangSuzuki K Poulose
authored andcommitted
coresight-etm4x: add isb() before reading the TRCSTATR
As recommended by section 4.3.7 ("Synchronization when using system instructions to progrom the trace unit") of ARM IHI 0064H.b, the self-hosted trace analyzer must perform a Context synchronization event between writing to the TRCPRGCTLR and reading the TRCSTATR. Additionally, add an ISB between the each read of TRCSTATR on coresight_timeout() when using system instructions to program the trace unit. Fixes: 1ab3bb9 ("coresight: etm4x: Add necessary synchronization for sysreg access") Signed-off-by: Yuanfang Zhang <[email protected]> Signed-off-by: Suzuki K Poulose <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent cade8a8 commit 4ff6039

File tree

3 files changed

+62
-10
lines changed

3 files changed

+62
-10
lines changed

drivers/hwtracing/coresight/coresight-core.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,18 +1093,20 @@ static void coresight_remove_conns(struct coresight_device *csdev)
10931093
}
10941094

10951095
/**
1096-
* coresight_timeout - loop until a bit has changed to a specific register
1097-
* state.
1096+
* coresight_timeout_action - loop until a bit has changed to a specific register
1097+
* state, with a callback after every trial.
10981098
* @csa: coresight device access for the device
10991099
* @offset: Offset of the register from the base of the device.
11001100
* @position: the position of the bit of interest.
11011101
* @value: the value the bit should have.
1102+
* @cb: Call back after each trial.
11021103
*
11031104
* Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
11041105
* TIMEOUT_US has elapsed, which ever happens first.
11051106
*/
1106-
int coresight_timeout(struct csdev_access *csa, u32 offset,
1107-
int position, int value)
1107+
int coresight_timeout_action(struct csdev_access *csa, u32 offset,
1108+
int position, int value,
1109+
coresight_timeout_cb_t cb)
11081110
{
11091111
int i;
11101112
u32 val;
@@ -1120,7 +1122,8 @@ int coresight_timeout(struct csdev_access *csa, u32 offset,
11201122
if (!(val & BIT(position)))
11211123
return 0;
11221124
}
1123-
1125+
if (cb)
1126+
cb(csa, offset, position, value);
11241127
/*
11251128
* Delay is arbitrary - the specification doesn't say how long
11261129
* we are expected to wait. Extra check required to make sure
@@ -1132,6 +1135,13 @@ int coresight_timeout(struct csdev_access *csa, u32 offset,
11321135

11331136
return -EAGAIN;
11341137
}
1138+
EXPORT_SYMBOL_GPL(coresight_timeout_action);
1139+
1140+
int coresight_timeout(struct csdev_access *csa, u32 offset,
1141+
int position, int value)
1142+
{
1143+
return coresight_timeout_action(csa, offset, position, value, NULL);
1144+
}
11351145
EXPORT_SYMBOL_GPL(coresight_timeout);
11361146

11371147
u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset)

drivers/hwtracing/coresight/coresight-etm4x-core.c

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,29 @@ static void etm4_check_arch_features(struct etmv4_drvdata *drvdata,
427427
}
428428
#endif /* CONFIG_ETM4X_IMPDEF_FEATURE */
429429

430+
static void etm4x_sys_ins_barrier(struct csdev_access *csa, u32 offset, int pos, int val)
431+
{
432+
if (!csa->io_mem)
433+
isb();
434+
}
435+
436+
/*
437+
* etm4x_wait_status: Poll for TRCSTATR.<pos> == <val>. While using system
438+
* instruction to access the trace unit, each access must be separated by a
439+
* synchronization barrier. See ARM IHI0064H.b section "4.3.7 Synchronization of
440+
* register updates", for system instructions section, in "Notes":
441+
*
442+
* "In particular, whenever disabling or enabling the trace unit, a poll of
443+
* TRCSTATR needs explicit synchronization between each read of TRCSTATR"
444+
*/
445+
static int etm4x_wait_status(struct csdev_access *csa, int pos, int val)
446+
{
447+
if (!csa->io_mem)
448+
return coresight_timeout_action(csa, TRCSTATR, pos, val,
449+
etm4x_sys_ins_barrier);
450+
return coresight_timeout(csa, TRCSTATR, pos, val);
451+
}
452+
430453
static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
431454
{
432455
int i, rc;
@@ -458,7 +481,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
458481
isb();
459482

460483
/* wait for TRCSTATR.IDLE to go up */
461-
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
484+
if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 1))
462485
dev_err(etm_dev,
463486
"timeout while waiting for Idle Trace Status\n");
464487
if (drvdata->nr_pe)
@@ -551,7 +574,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
551574
isb();
552575

553576
/* wait for TRCSTATR.IDLE to go back down to '0' */
554-
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
577+
if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 0))
555578
dev_err(etm_dev,
556579
"timeout while waiting for Idle Trace Status\n");
557580

@@ -940,10 +963,25 @@ static void etm4_disable_hw(void *info)
940963
tsb_csync();
941964
etm4x_relaxed_write32(csa, control, TRCPRGCTLR);
942965

966+
/*
967+
* As recommended by section 4.3.7 ("Synchronization when using system
968+
* instructions to progrom the trace unit") of ARM IHI 0064H.b, the
969+
* self-hosted trace analyzer must perform a Context synchronization
970+
* event between writing to the TRCPRGCTLR and reading the TRCSTATR.
971+
*/
972+
if (!csa->io_mem)
973+
isb();
974+
943975
/* wait for TRCSTATR.PMSTABLE to go to '1' */
944-
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
976+
if (etm4x_wait_status(csa, TRCSTATR_PMSTABLE_BIT, 1))
945977
dev_err(etm_dev,
946978
"timeout while waiting for PM stable Trace Status\n");
979+
/*
980+
* As recommended by section 4.3.7 (Synchronization of register updates)
981+
* of ARM IHI 0064H.b.
982+
*/
983+
isb();
984+
947985
/* read the status of the single shot comparators */
948986
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
949987
config->ss_status[i] =
@@ -1745,7 +1783,7 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
17451783
etm4_os_lock(drvdata);
17461784

17471785
/* wait for TRCSTATR.PMSTABLE to go up */
1748-
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) {
1786+
if (etm4x_wait_status(csa, TRCSTATR_PMSTABLE_BIT, 1)) {
17491787
dev_err(etm_dev,
17501788
"timeout while waiting for PM Stable Status\n");
17511789
etm4_os_unlock(drvdata);
@@ -1836,7 +1874,7 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
18361874
state->trcpdcr = etm4x_read32(csa, TRCPDCR);
18371875

18381876
/* wait for TRCSTATR.IDLE to go up */
1839-
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) {
1877+
if (etm4x_wait_status(csa, TRCSTATR_PMSTABLE_BIT, 1)) {
18401878
dev_err(etm_dev,
18411879
"timeout while waiting for Idle Trace Status\n");
18421880
etm4_os_unlock(drvdata);

include/linux/coresight.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,10 @@ extern int coresight_enable_sysfs(struct coresight_device *csdev);
661661
extern void coresight_disable_sysfs(struct coresight_device *csdev);
662662
extern int coresight_timeout(struct csdev_access *csa, u32 offset,
663663
int position, int value);
664+
typedef void (*coresight_timeout_cb_t) (struct csdev_access *, u32, int, int);
665+
extern int coresight_timeout_action(struct csdev_access *csa, u32 offset,
666+
int position, int value,
667+
coresight_timeout_cb_t cb);
664668

665669
extern int coresight_claim_device(struct coresight_device *csdev);
666670
extern int coresight_claim_device_unlocked(struct coresight_device *csdev);

0 commit comments

Comments
 (0)