Skip to content

Commit 0242737

Browse files
Yicong Yangwilldeacon
authored andcommitted
perf/smmuv3: Enable HiSilicon Erratum 162001900 quirk for HIP08/09
Some HiSilicon SMMU PMCG suffers the erratum 162001900 that the PMU disable control sometimes fail to disable the counters. This will lead to error or inaccurate data since before we enable the counters the counter's still counting for the event used in last perf session. This patch tries to fix this by hardening the global disable process. Before disable the PMU, writing an invalid event type (0xffff) to focibly stop the counters. Correspondingly restore each events on pmu::pmu_enable(). Signed-off-by: Yicong Yang <yangyicong@hisilicon.com> Link: https://lore.kernel.org/r/20230814124012.58013-1-yangyicong@huawei.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent 90d6867 commit 0242737

4 files changed

Lines changed: 53 additions & 2 deletions

File tree

Documentation/arch/arm64/silicon-errata.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ stable kernels.
195195
+----------------+-----------------+-----------------+-----------------------------+
196196
| Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A |
197197
+----------------+-----------------+-----------------+-----------------------------+
198+
| Hisilicon | Hip08 SMMU PMCG | #162001900 | N/A |
199+
| | Hip09 SMMU PMCG | | |
200+
+----------------+-----------------+-----------------+-----------------------------+
198201
+----------------+-----------------+-----------------+-----------------------------+
199202
| Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
200203
+----------------+-----------------+-----------------+-----------------------------+

drivers/acpi/arm64/iort.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1711,7 +1711,10 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res,
17111711
static struct acpi_platform_list pmcg_plat_info[] __initdata = {
17121712
/* HiSilicon Hip08 Platform */
17131713
{"HISI ", "HIP08 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
1714-
"Erratum #162001800", IORT_SMMU_V3_PMCG_HISI_HIP08},
1714+
"Erratum #162001800, Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP08},
1715+
/* HiSilicon Hip09 Platform */
1716+
{"HISI ", "HIP09 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
1717+
"Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
17151718
{ }
17161719
};
17171720

drivers/perf/arm_smmuv3_pmu.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
#define SMMU_PMCG_PA_SHIFT 12
116116

117117
#define SMMU_PMCG_EVCNTR_RDONLY BIT(0)
118+
#define SMMU_PMCG_HARDEN_DISABLE BIT(1)
118119

119120
static int cpuhp_state_num;
120121

@@ -159,6 +160,20 @@ static inline void smmu_pmu_enable(struct pmu *pmu)
159160
writel(SMMU_PMCG_CR_ENABLE, smmu_pmu->reg_base + SMMU_PMCG_CR);
160161
}
161162

163+
static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu,
164+
struct perf_event *event, int idx);
165+
166+
static inline void smmu_pmu_enable_quirk_hip08_09(struct pmu *pmu)
167+
{
168+
struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
169+
unsigned int idx;
170+
171+
for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters)
172+
smmu_pmu_apply_event_filter(smmu_pmu, smmu_pmu->events[idx], idx);
173+
174+
smmu_pmu_enable(pmu);
175+
}
176+
162177
static inline void smmu_pmu_disable(struct pmu *pmu)
163178
{
164179
struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
@@ -167,6 +182,22 @@ static inline void smmu_pmu_disable(struct pmu *pmu)
167182
writel(0, smmu_pmu->reg_base + SMMU_PMCG_IRQ_CTRL);
168183
}
169184

185+
static inline void smmu_pmu_disable_quirk_hip08_09(struct pmu *pmu)
186+
{
187+
struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
188+
unsigned int idx;
189+
190+
/*
191+
* The global disable of PMU sometimes fail to stop the counting.
192+
* Harden this by writing an invalid event type to each used counter
193+
* to forcibly stop counting.
194+
*/
195+
for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters)
196+
writel(0xffff, smmu_pmu->reg_base + SMMU_PMCG_EVTYPER(idx));
197+
198+
smmu_pmu_disable(pmu);
199+
}
200+
170201
static inline void smmu_pmu_counter_set_value(struct smmu_pmu *smmu_pmu,
171202
u32 idx, u64 value)
172203
{
@@ -765,7 +796,10 @@ static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu)
765796
switch (model) {
766797
case IORT_SMMU_V3_PMCG_HISI_HIP08:
767798
/* HiSilicon Erratum 162001800 */
768-
smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY;
799+
smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY | SMMU_PMCG_HARDEN_DISABLE;
800+
break;
801+
case IORT_SMMU_V3_PMCG_HISI_HIP09:
802+
smmu_pmu->options |= SMMU_PMCG_HARDEN_DISABLE;
769803
break;
770804
}
771805

@@ -890,6 +924,16 @@ static int smmu_pmu_probe(struct platform_device *pdev)
890924
if (!dev->of_node)
891925
smmu_pmu_get_acpi_options(smmu_pmu);
892926

927+
/*
928+
* For platforms suffer this quirk, the PMU disable sometimes fails to
929+
* stop the counters. This will leads to inaccurate or error counting.
930+
* Forcibly disable the counters with these quirk handler.
931+
*/
932+
if (smmu_pmu->options & SMMU_PMCG_HARDEN_DISABLE) {
933+
smmu_pmu->pmu.pmu_enable = smmu_pmu_enable_quirk_hip08_09;
934+
smmu_pmu->pmu.pmu_disable = smmu_pmu_disable_quirk_hip08_09;
935+
}
936+
893937
/* Pick one CPU to be the preferred one to use */
894938
smmu_pmu->on_cpu = raw_smp_processor_id();
895939
WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu)));

include/linux/acpi_iort.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
*/
2222
#define IORT_SMMU_V3_PMCG_GENERIC 0x00000000 /* Generic SMMUv3 PMCG */
2323
#define IORT_SMMU_V3_PMCG_HISI_HIP08 0x00000001 /* HiSilicon HIP08 PMCG */
24+
#define IORT_SMMU_V3_PMCG_HISI_HIP09 0x00000002 /* HiSilicon HIP09 PMCG */
2425

2526
int iort_register_domain_token(int trans_id, phys_addr_t base,
2627
struct fwnode_handle *fw_node);

0 commit comments

Comments
 (0)