Skip to content

Commit daecd33

Browse files
Yicong Yangwilldeacon
authored andcommitted
drivers/perf: hisi_pcie: Record hardware counts correctly
Currently we set the period and record it as the initial value of the counter without checking it's set to the hardware successfully or not. However the counter maybe unwritable if the target event is unsupported by the device. In such case we will pass user a wrong count: [start counts when setting the period] hwc->prev_count = 0x8000000000000000 device.counter_value = 0 // the counter is not set as the period [when user reads the counter] event->count = device.counter_value - hwc->prev_count = 0x8000000000000000 // wrong. should be 0. Fix this by record the hardware counter counts correctly when setting the period. Fixes: 8404b0f ("drivers/perf: hisi: Add driver for HiSilicon PCIe PMU") Signed-off-by: Yicong Yang <yangyicong@hisilicon.com> Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Link: https://lore.kernel.org/r/20240829090332.28756-2-yangyicong@huawei.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent 5e9629d commit daecd33

1 file changed

Lines changed: 14 additions & 0 deletions

File tree

drivers/perf/hisilicon/hisi_pcie_pmu.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,10 +452,24 @@ static void hisi_pcie_pmu_set_period(struct perf_event *event)
452452
struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu);
453453
struct hw_perf_event *hwc = &event->hw;
454454
int idx = hwc->idx;
455+
u64 orig_cnt, cnt;
456+
457+
orig_cnt = hisi_pcie_pmu_read_counter(event);
455458

456459
local64_set(&hwc->prev_count, HISI_PCIE_INIT_VAL);
457460
hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_CNT, idx, HISI_PCIE_INIT_VAL);
458461
hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EXT_CNT, idx, HISI_PCIE_INIT_VAL);
462+
463+
/*
464+
* The counter maybe unwritable if the target event is unsupported.
465+
* Check this by comparing the counts after setting the period. If
466+
* the counts stay unchanged after setting the period then update
467+
* the hwc->prev_count correctly. Otherwise the final counts user
468+
* get maybe totally wrong.
469+
*/
470+
cnt = hisi_pcie_pmu_read_counter(event);
471+
if (orig_cnt == cnt)
472+
local64_set(&hwc->prev_count, cnt);
459473
}
460474

461475
static void hisi_pcie_pmu_enable_counter(struct hisi_pcie_pmu *pcie_pmu, struct hw_perf_event *hwc)

0 commit comments

Comments
 (0)