diff mbox series

[v2] drivers/perf: hisi: Enable HiSilicon Erratum 162700402 quirk for HIP09

Message ID 20240227125231.53127-1-hejunhao3@huawei.com (mailing list archive)
State New, archived
Headers show
Series [v2] drivers/perf: hisi: Enable HiSilicon Erratum 162700402 quirk for HIP09 | expand

Commit Message

Junhao He Feb. 27, 2024, 12:52 p.m. UTC
HiSilicon UC PMU v2 suffers the erratum 162700402 that the PMU counter
cannot be set due to the lack of clock under power saving mode. This will
lead to error or inaccurate counts. The clock can be enabled by the PMU
global enabling control.

This patch tries to fix this by set the UC PMU enable before set event
period to turn on the clock, and then restore the UC PMU configuration.
The counter register can hold its value without a clock.

Signed-off-by: Junhao He <hejunhao3@huawei.com>
---

Changes since V1:
- Updated the comment regarding the quirk function.
- Extract write counter normal to a helper function.
Link: https://lore.kernel.org/all/20240207094245.34195-1-hejunhao3@huawei.com/

 drivers/perf/hisilicon/hisi_uncore_uc_pmu.c | 42 ++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

Comments

Yicong Yang Feb. 29, 2024, 11:12 a.m. UTC | #1
On 2024/2/27 20:52, Junhao He wrote:
> HiSilicon UC PMU v2 suffers the erratum 162700402 that the PMU counter
> cannot be set due to the lack of clock under power saving mode. This will
> lead to error or inaccurate counts. The clock can be enabled by the PMU
> global enabling control.
> 
> This patch tries to fix this by set the UC PMU enable before set event
> period to turn on the clock, and then restore the UC PMU configuration.
> The counter register can hold its value without a clock.
> 
> Signed-off-by: Junhao He <hejunhao3@huawei.com>
> ---
> 
> Changes since V1:
> - Updated the comment regarding the quirk function.
> - Extract write counter normal to a helper function.
> Link: https://lore.kernel.org/all/20240207094245.34195-1-hejunhao3@huawei.com/
> 

This version looks clearer to me,

Reviewed-by: Yicong Yang <yangyicong@hisilicon.com>

>  drivers/perf/hisilicon/hisi_uncore_uc_pmu.c | 42 ++++++++++++++++++++-
>  1 file changed, 41 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
> index 636fb79647c8..481dcc9e8fbf 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
> @@ -287,12 +287,52 @@ static u64 hisi_uc_pmu_read_counter(struct hisi_pmu *uc_pmu,
>  	return readq(uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx));
>  }
>  
> -static void hisi_uc_pmu_write_counter(struct hisi_pmu *uc_pmu,
> +static bool hisi_uc_pmu_get_glb_en_state(struct hisi_pmu *uc_pmu)
> +{
> +	u32 val;
> +
> +	val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
> +	return !!FIELD_GET(HISI_UC_EVENT_GLB_EN, val);
> +}
> +
> +static void hisi_uc_pmu_write_counter_normal(struct hisi_pmu *uc_pmu,
>  				      struct hw_perf_event *hwc, u64 val)
>  {
>  	writeq(val, uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx));
>  }
>  
> +static void hisi_uc_pmu_write_counter_quirk_v2(struct hisi_pmu *uc_pmu,
> +				      struct hw_perf_event *hwc, u64 val)
> +{
> +	hisi_uc_pmu_start_counters(uc_pmu);
> +	hisi_uc_pmu_write_counter_normal(uc_pmu, hwc, val);
> +	hisi_uc_pmu_stop_counters(uc_pmu);
> +}
> +
> +static void hisi_uc_pmu_write_counter(struct hisi_pmu *uc_pmu,
> +				      struct hw_perf_event *hwc, u64 val)
> +{
> +	bool enable = hisi_uc_pmu_get_glb_en_state(uc_pmu);
> +	bool erratum = uc_pmu->identifier == HISI_PMU_V2;
> +
> +	/*
> +	 * HiSilicon UC PMU v2 suffers the erratum 162700402 that the
> +	 * PMU counter cannot be set due to the lack of clock under power
> +	 * saving mode. This will lead to error or inaccurate counts.
> +	 * The clock can be enabled by the PMU global enabling control.
> +	 * The irq handler and pmu_start() will call the function to set
> +	 * period. If the function under irq context, the PMU has been
> +	 * enabled therefore we set counter directly. Other situations
> +	 * the PMU is disabled, we need to enable it to turn on the
> +	 * counter clock to set period, and then restore PMU enable
> +	 * status, the counter can hold its value without a clock.
> +	 */
> +	if (enable || !erratum)
> +		hisi_uc_pmu_write_counter_normal(uc_pmu, hwc, val);
> +	else
> +		hisi_uc_pmu_write_counter_quirk_v2(uc_pmu, hwc, val);
> +}
> +
>  static void hisi_uc_pmu_enable_counter_int(struct hisi_pmu *uc_pmu,
>  					   struct hw_perf_event *hwc)
>  {
>
Will Deacon March 4, 2024, 3:17 p.m. UTC | #2
On Tue, 27 Feb 2024 20:52:31 +0800, Junhao He wrote:
> HiSilicon UC PMU v2 suffers the erratum 162700402 that the PMU counter
> cannot be set due to the lack of clock under power saving mode. This will
> lead to error or inaccurate counts. The clock can be enabled by the PMU
> global enabling control.
> 
> This patch tries to fix this by set the UC PMU enable before set event
> period to turn on the clock, and then restore the UC PMU configuration.
> The counter register can hold its value without a clock.
> 
> [...]

Applied to will (for-next/perf), thanks!

[1/1] drivers/perf: hisi: Enable HiSilicon Erratum 162700402 quirk for HIP09
      https://git.kernel.org/will/c/e10b6976f6b9

Cheers,
diff mbox series

Patch

diff --git a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
index 636fb79647c8..481dcc9e8fbf 100644
--- a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
@@ -287,12 +287,52 @@  static u64 hisi_uc_pmu_read_counter(struct hisi_pmu *uc_pmu,
 	return readq(uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx));
 }
 
-static void hisi_uc_pmu_write_counter(struct hisi_pmu *uc_pmu,
+static bool hisi_uc_pmu_get_glb_en_state(struct hisi_pmu *uc_pmu)
+{
+	u32 val;
+
+	val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
+	return !!FIELD_GET(HISI_UC_EVENT_GLB_EN, val);
+}
+
+static void hisi_uc_pmu_write_counter_normal(struct hisi_pmu *uc_pmu,
 				      struct hw_perf_event *hwc, u64 val)
 {
 	writeq(val, uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx));
 }
 
+static void hisi_uc_pmu_write_counter_quirk_v2(struct hisi_pmu *uc_pmu,
+				      struct hw_perf_event *hwc, u64 val)
+{
+	hisi_uc_pmu_start_counters(uc_pmu);
+	hisi_uc_pmu_write_counter_normal(uc_pmu, hwc, val);
+	hisi_uc_pmu_stop_counters(uc_pmu);
+}
+
+static void hisi_uc_pmu_write_counter(struct hisi_pmu *uc_pmu,
+				      struct hw_perf_event *hwc, u64 val)
+{
+	bool enable = hisi_uc_pmu_get_glb_en_state(uc_pmu);
+	bool erratum = uc_pmu->identifier == HISI_PMU_V2;
+
+	/*
+	 * HiSilicon UC PMU v2 suffers the erratum 162700402 that the
+	 * PMU counter cannot be set due to the lack of clock under power
+	 * saving mode. This will lead to error or inaccurate counts.
+	 * The clock can be enabled by the PMU global enabling control.
+	 * The irq handler and pmu_start() will call the function to set
+	 * period. If the function under irq context, the PMU has been
+	 * enabled therefore we set counter directly. Other situations
+	 * the PMU is disabled, we need to enable it to turn on the
+	 * counter clock to set period, and then restore PMU enable
+	 * status, the counter can hold its value without a clock.
+	 */
+	if (enable || !erratum)
+		hisi_uc_pmu_write_counter_normal(uc_pmu, hwc, val);
+	else
+		hisi_uc_pmu_write_counter_quirk_v2(uc_pmu, hwc, val);
+}
+
 static void hisi_uc_pmu_enable_counter_int(struct hisi_pmu *uc_pmu,
 					   struct hw_perf_event *hwc)
 {