[RESEND PATCH v4 1/3] perf/marvell: Refactor to extract platform data
Gowthami Thiagarajan
gthiagarajan at marvell.com
Fri Apr 19 03:43:33 PDT 2024
Hi,
The patches are updated as per the comments received. Do you have any feedback on this version?
Thanks,
Gowthami
> -----Original Message-----
> From: Gowthami Thiagarajan <gthiagarajan at marvell.com>
> Sent: Wednesday, March 27, 2024 12:49 PM
> To: will at kernel.org; mark.rutland at arm.com; linux-arm-kernel at lists.infradead.org; linux-
> kernel at vger.kernel.org
> Cc: Sunil Kovvuri Goutham <sgoutham at marvell.com>; Bharat Bhushan <bbhushan2 at marvell.com>; George
> Cherian <gcherian at marvell.com>; Gowthami Thiagarajan <gthiagarajan at marvell.com>
> Subject: [RESEND PATCH v4 1/3] perf/marvell: Refactor to extract platform data
>
> This commit introduces a refactor to the Marvell driver
> code, specifically targeting the extraction of platform data
> (referred to as "pdata") from the existing driver. The purpose of
> this refactor is to prepare for the upcoming support of the next
> version of the Performance Monitoring Unit (PMU) in this
> driver.
>
> No functional changes are introduced in this refactor. Its sole
> purpose is to improve code organization and pave the way for
> future enhancements to the driver.
>
> Signed-off-by: Gowthami Thiagarajan <gthiagarajan at marvell.com>
> ---
> drivers/perf/marvell_cn10k_ddr_pmu.c | 282 ++++++++++++++++++++-------
> 1 file changed, 210 insertions(+), 72 deletions(-)
>
> diff --git a/drivers/perf/marvell_cn10k_ddr_pmu.c b/drivers/perf/marvell_cn10k_ddr_pmu.c
> index 524ba82bfce2..d6485c4cf30f 100644
> --- a/drivers/perf/marvell_cn10k_ddr_pmu.c
> +++ b/drivers/perf/marvell_cn10k_ddr_pmu.c
> @@ -1,7 +1,8 @@
> // SPDX-License-Identifier: GPL-2.0
> -/* Marvell CN10K DRAM Subsystem (DSS) Performance Monitor Driver
> +/*
> + * Marvell CN10K DRAM Subsystem (DSS) Performance Monitor Driver
> *
> - * Copyright (C) 2021 Marvell.
> + * Copyright (C) 2024 Marvell.
> */
>
> #include <linux/init.h>
> @@ -14,24 +15,24 @@
> #include <linux/platform_device.h>
>
> /* Performance Counters Operating Mode Control Registers */
> -#define DDRC_PERF_CNT_OP_MODE_CTRL 0x8020
> -#define OP_MODE_CTRL_VAL_MANNUAL 0x1
> +#define CN10K_DDRC_PERF_CNT_OP_MODE_CTRL 0x8020
> +#define OP_MODE_CTRL_VAL_MANUAL 0x1
>
> /* Performance Counters Start Operation Control Registers */
> -#define DDRC_PERF_CNT_START_OP_CTRL 0x8028
> +#define CN10K_DDRC_PERF_CNT_START_OP_CTRL 0x8028
> #define START_OP_CTRL_VAL_START 0x1ULL
> #define START_OP_CTRL_VAL_ACTIVE 0x2
>
> /* Performance Counters End Operation Control Registers */
> -#define DDRC_PERF_CNT_END_OP_CTRL 0x8030
> +#define CN10K_DDRC_PERF_CNT_END_OP_CTRL 0x8030
> #define END_OP_CTRL_VAL_END 0x1ULL
>
> /* Performance Counters End Status Registers */
> -#define DDRC_PERF_CNT_END_STATUS 0x8038
> +#define CN10K_DDRC_PERF_CNT_END_STATUS 0x8038
> #define END_STATUS_VAL_END_TIMER_MODE_END 0x1
>
> /* Performance Counters Configuration Registers */
> -#define DDRC_PERF_CFG_BASE 0x8040
> +#define CN10K_DDRC_PERF_CFG_BASE 0x8040
>
> /* 8 Generic event counter + 2 fixed event counters */
> #define DDRC_PERF_NUM_GEN_COUNTERS 8
> @@ -42,17 +43,19 @@
> DDRC_PERF_NUM_FIX_COUNTERS)
>
> /* Generic event counter registers */
> -#define DDRC_PERF_CFG(n) (DDRC_PERF_CFG_BASE + 8 * (n))
> +#define DDRC_PERF_CFG(base, n) ((base) + 8 * (n))
> #define EVENT_ENABLE BIT_ULL(63)
>
> /* Two dedicated event counters for DDR reads and writes */
> #define EVENT_DDR_READS 101
> #define EVENT_DDR_WRITES 100
>
> +#define DDRC_PERF_REG(base, n) ((base) + 8 * (n))
> /*
> * programmable events IDs in programmable event counters.
> * DO NOT change these event-id numbers, they are used to
> * program event bitmap in h/w.
> + *
> */
> #define EVENT_OP_IS_ZQLATCH 55
> #define EVENT_OP_IS_ZQSTART 54
> @@ -63,8 +66,8 @@
> #define EVENT_VISIBLE_WIN_LIMIT_REACHED_RD 49
> #define EVENT_BSM_STARVATION 48
> #define EVENT_BSM_ALLOC 47
> -#define EVENT_LPR_REQ_WITH_NOCREDIT 46
> -#define EVENT_HPR_REQ_WITH_NOCREDIT 45
> +#define EVENT_RETRY_FIFO_FULL_OR_LPR_REQ_NOCRED 46
> +#define EVENT_DFI_OR_HPR_REQ_NOCRED 45
> #define EVENT_OP_IS_ZQCS 44
> #define EVENT_OP_IS_ZQCL 43
> #define EVENT_OP_IS_LOAD_MODE 42
> @@ -102,28 +105,38 @@
> #define EVENT_HIF_RD_OR_WR 1
>
> /* Event counter value registers */
> -#define DDRC_PERF_CNT_VALUE_BASE 0x8080
> -#define DDRC_PERF_CNT_VALUE(n) (DDRC_PERF_CNT_VALUE_BASE + 8 * (n))
> +#define CN10K_DDRC_PERF_CNT_VALUE_BASE 0x8080
>
> /* Fixed event counter enable/disable register */
> -#define DDRC_PERF_CNT_FREERUN_EN 0x80C0
> +#define CN10K_DDRC_PERF_CNT_FREERUN_EN 0x80C0
> #define DDRC_PERF_FREERUN_WRITE_EN 0x1
> #define DDRC_PERF_FREERUN_READ_EN 0x2
>
> /* Fixed event counter control register */
> -#define DDRC_PERF_CNT_FREERUN_CTRL 0x80C8
> +#define CN10K_DDRC_PERF_CNT_FREERUN_CTRL 0x80C8
> #define DDRC_FREERUN_WRITE_CNT_CLR 0x1
> #define DDRC_FREERUN_READ_CNT_CLR 0x2
>
> -/* Fixed event counter value register */
> -#define DDRC_PERF_CNT_VALUE_WR_OP 0x80D0
> -#define DDRC_PERF_CNT_VALUE_RD_OP 0x80D8
> #define DDRC_PERF_CNT_VALUE_OVERFLOW BIT_ULL(48)
> #define DDRC_PERF_CNT_MAX_VALUE GENMASK_ULL(48, 0)
>
> +/* Fixed event counter value register */
> +#define CN10K_DDRC_PERF_CNT_VALUE_WR_OP 0x80D0
> +#define CN10K_DDRC_PERF_CNT_VALUE_RD_OP 0x80D8
> +
> +enum mrvl_ddr_pmu_version {
> + DDR_PMU_V1 = 1,
> +};
> +
> +struct ddr_pmu_data {
> + int id;
> +};
> +
> struct cn10k_ddr_pmu {
> struct pmu pmu;
> void __iomem *base;
> + const struct ddr_pmu_platform_data *p_data;
> + int version;
> unsigned int cpu;
> struct device *dev;
> int active_events;
> @@ -132,8 +145,35 @@ struct cn10k_ddr_pmu {
> struct hlist_node node;
> };
>
> +struct ddr_pmu_ops {
> + void (*enable_read_freerun_counter)(struct cn10k_ddr_pmu *pmu,
> + bool enable);
> + void (*enable_write_freerun_counter)(struct cn10k_ddr_pmu *pmu,
> + bool enable);
> + void (*clear_read_freerun_counter)(struct cn10k_ddr_pmu *pmu);
> + void (*clear_write_freerun_counter)(struct cn10k_ddr_pmu *pmu);
> + void (*pmu_overflow_handler)(struct cn10k_ddr_pmu *pmu, int evt_idx);
> +};
> +
> #define to_cn10k_ddr_pmu(p) container_of(p, struct cn10k_ddr_pmu, pmu)
>
> +struct ddr_pmu_platform_data {
> + u64 counter_overflow_val;
> + u64 counter_max_val;
> + u64 ddrc_perf_cnt_base;
> + u64 ddrc_perf_cfg_base;
> + u64 ddrc_perf_cnt_op_mode_ctrl;
> + u64 ddrc_perf_cnt_start_op_ctrl;
> + u64 ddrc_perf_cnt_end_op_ctrl;
> + u64 ddrc_perf_cnt_end_status;
> + u64 ddrc_perf_cnt_freerun_en;
> + u64 ddrc_perf_cnt_freerun_ctrl;
> + u64 ddrc_perf_cnt_freerun_clr;
> + u64 ddrc_perf_cnt_value_wr_op;
> + u64 ddrc_perf_cnt_value_rd_op;
> + const struct ddr_pmu_ops *ops;
> +};
> +
> static ssize_t cn10k_ddr_pmu_event_show(struct device *dev,
> struct device_attribute *attr,
> char *page)
> @@ -189,9 +229,9 @@ static struct attribute *cn10k_ddr_perf_events_attrs[] = {
> CN10K_DDR_PMU_EVENT_ATTR(ddr_zqcl, EVENT_OP_IS_ZQCL),
> CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_wr_access, EVENT_OP_IS_ZQCS),
> CN10K_DDR_PMU_EVENT_ATTR(ddr_hpr_req_with_nocredit,
> - EVENT_HPR_REQ_WITH_NOCREDIT),
> + EVENT_DFI_OR_HPR_REQ_NOCRED),
> CN10K_DDR_PMU_EVENT_ATTR(ddr_lpr_req_with_nocredit,
> - EVENT_LPR_REQ_WITH_NOCREDIT),
> + EVENT_RETRY_FIFO_FULL_OR_LPR_REQ_NOCRED),
> CN10K_DDR_PMU_EVENT_ATTR(ddr_bsm_alloc, EVENT_BSM_ALLOC),
> CN10K_DDR_PMU_EVENT_ATTR(ddr_bsm_starvation, EVENT_BSM_STARVATION),
> CN10K_DDR_PMU_EVENT_ATTR(ddr_win_limit_reached_rd,
> @@ -266,7 +306,8 @@ static ktime_t cn10k_ddr_pmu_timer_period(void)
> return ms_to_ktime((u64)cn10k_ddr_pmu_poll_period_sec * USEC_PER_SEC);
> }
>
> -static int ddr_perf_get_event_bitmap(int eventid, u64 *event_bitmap)
> +static int ddr_perf_get_event_bitmap(int eventid, u64 *event_bitmap,
> + struct cn10k_ddr_pmu *ddr_pmu)
> {
> switch (eventid) {
> case EVENT_HIF_RD_OR_WR ... EVENT_WAW_HAZARD:
> @@ -354,6 +395,8 @@ static int cn10k_ddr_perf_event_init(struct perf_event *event)
> static void cn10k_ddr_perf_counter_enable(struct cn10k_ddr_pmu *pmu,
> int counter, bool enable)
> {
> + const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> + const struct ddr_pmu_ops *ops = p_data->ops;
> u32 reg;
> u64 val;
>
> @@ -363,7 +406,7 @@ static void cn10k_ddr_perf_counter_enable(struct cn10k_ddr_pmu *pmu,
> }
>
> if (counter < DDRC_PERF_NUM_GEN_COUNTERS) {
> - reg = DDRC_PERF_CFG(counter);
> + reg = DDRC_PERF_CFG(p_data->ddrc_perf_cfg_base, counter);
> val = readq_relaxed(pmu->base + reg);
>
> if (enable)
> @@ -373,19 +416,10 @@ static void cn10k_ddr_perf_counter_enable(struct cn10k_ddr_pmu *pmu,
>
> writeq_relaxed(val, pmu->base + reg);
> } else {
> - val = readq_relaxed(pmu->base + DDRC_PERF_CNT_FREERUN_EN);
> - if (enable) {
> - if (counter == DDRC_PERF_READ_COUNTER_IDX)
> - val |= DDRC_PERF_FREERUN_READ_EN;
> - else
> - val |= DDRC_PERF_FREERUN_WRITE_EN;
> - } else {
> - if (counter == DDRC_PERF_READ_COUNTER_IDX)
> - val &= ~DDRC_PERF_FREERUN_READ_EN;
> - else
> - val &= ~DDRC_PERF_FREERUN_WRITE_EN;
> - }
> - writeq_relaxed(val, pmu->base + DDRC_PERF_CNT_FREERUN_EN);
> + if (counter == DDRC_PERF_READ_COUNTER_IDX)
> + ops->enable_read_freerun_counter(pmu, enable);
> + else
> + ops->enable_write_freerun_counter(pmu, enable);
> }
> }
>
> @@ -393,13 +427,18 @@ static u64 cn10k_ddr_perf_read_counter(struct cn10k_ddr_pmu *pmu, int counter)
> {
> u64 val;
>
> + const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> +
> if (counter == DDRC_PERF_READ_COUNTER_IDX)
> - return readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE_RD_OP);
> + return readq_relaxed(pmu->base +
> + p_data->ddrc_perf_cnt_value_rd_op);
>
> if (counter == DDRC_PERF_WRITE_COUNTER_IDX)
> - return readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE_WR_OP);
> + return readq_relaxed(pmu->base +
> + p_data->ddrc_perf_cnt_value_wr_op);
>
> - val = readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE(counter));
> + val = readq_relaxed(pmu->base +
> + DDRC_PERF_REG(p_data->ddrc_perf_cnt_base, counter));
> return val;
> }
>
> @@ -407,6 +446,7 @@ static void cn10k_ddr_perf_event_update(struct perf_event *event)
> {
> struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
> struct hw_perf_event *hwc = &event->hw;
> + const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> u64 prev_count, new_count, mask;
>
> do {
> @@ -414,7 +454,7 @@ static void cn10k_ddr_perf_event_update(struct perf_event *event)
> new_count = cn10k_ddr_perf_read_counter(pmu, hwc->idx);
> } while (local64_xchg(&hwc->prev_count, new_count) != prev_count);
>
> - mask = DDRC_PERF_CNT_MAX_VALUE;
> + mask = p_data->counter_max_val;
>
> local64_add((new_count - prev_count) & mask, &event->count);
> }
> @@ -435,6 +475,8 @@ static void cn10k_ddr_perf_event_start(struct perf_event *event, int flags)
> static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags)
> {
> struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
> + const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> + const struct ddr_pmu_ops *ops = p_data->ops;
> struct hw_perf_event *hwc = &event->hw;
> u8 config = event->attr.config;
> int counter, ret;
> @@ -454,8 +496,8 @@ static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags)
>
> if (counter < DDRC_PERF_NUM_GEN_COUNTERS) {
> /* Generic counters, configure event id */
> - reg_offset = DDRC_PERF_CFG(counter);
> - ret = ddr_perf_get_event_bitmap(config, &val);
> + reg_offset = DDRC_PERF_CFG(p_data->ddrc_perf_cfg_base, counter);
> + ret = ddr_perf_get_event_bitmap(config, &val, pmu);
> if (ret)
> return ret;
>
> @@ -463,11 +505,9 @@ static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags)
> } else {
> /* fixed event counter, clear counter value */
> if (counter == DDRC_PERF_READ_COUNTER_IDX)
> - val = DDRC_FREERUN_READ_CNT_CLR;
> + ops->clear_read_freerun_counter(pmu);
> else
> - val = DDRC_FREERUN_WRITE_CNT_CLR;
> -
> - writeq_relaxed(val, pmu->base + DDRC_PERF_CNT_FREERUN_CTRL);
> + ops->clear_write_freerun_counter(pmu);
> }
>
> hwc->state |= PERF_HES_STOPPED;
> @@ -512,17 +552,19 @@ static void cn10k_ddr_perf_event_del(struct perf_event *event, int flags)
> static void cn10k_ddr_perf_pmu_enable(struct pmu *pmu)
> {
> struct cn10k_ddr_pmu *ddr_pmu = to_cn10k_ddr_pmu(pmu);
> + const struct ddr_pmu_platform_data *p_data = ddr_pmu->p_data;
>
> writeq_relaxed(START_OP_CTRL_VAL_START, ddr_pmu->base +
> - DDRC_PERF_CNT_START_OP_CTRL);
> + p_data->ddrc_perf_cnt_start_op_ctrl);
> }
>
> static void cn10k_ddr_perf_pmu_disable(struct pmu *pmu)
> {
> struct cn10k_ddr_pmu *ddr_pmu = to_cn10k_ddr_pmu(pmu);
> + const struct ddr_pmu_platform_data *p_data = ddr_pmu->p_data;
>
> writeq_relaxed(END_OP_CTRL_VAL_END, ddr_pmu->base +
> - DDRC_PERF_CNT_END_OP_CTRL);
> + p_data->ddrc_perf_cnt_end_op_ctrl);
> }
>
> static void cn10k_ddr_perf_event_update_all(struct cn10k_ddr_pmu *pmu)
> @@ -547,8 +589,63 @@ static void cn10k_ddr_perf_event_update_all(struct cn10k_ddr_pmu *pmu)
> }
> }
>
> +static void ddr_pmu_enable_read_freerun(struct cn10k_ddr_pmu *pmu, bool enable)
> +{
> + const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> + u64 val;
> +
> + val = readq_relaxed(pmu->base + p_data->ddrc_perf_cnt_freerun_en);
> + if (enable)
> + val |= DDRC_PERF_FREERUN_READ_EN;
> + else
> + val &= ~DDRC_PERF_FREERUN_READ_EN;
> +
> + writeq_relaxed(val, pmu->base + p_data->ddrc_perf_cnt_freerun_en);
> +}
> +
> +static void ddr_pmu_enable_write_freerun(struct cn10k_ddr_pmu *pmu, bool enable)
> +{
> + const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> + u64 val;
> +
> + val = readq_relaxed(pmu->base + p_data->ddrc_perf_cnt_freerun_en);
> + if (enable)
> + val |= DDRC_PERF_FREERUN_WRITE_EN;
> + else
> + val &= ~DDRC_PERF_FREERUN_WRITE_EN;
> +
> + writeq_relaxed(val, pmu->base + p_data->ddrc_perf_cnt_freerun_en);
> +}
> +
> +static void ddr_pmu_read_clear_freerun(struct cn10k_ddr_pmu *pmu)
> +{
> + const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> + u64 val;
> +
> + val = DDRC_FREERUN_READ_CNT_CLR;
> + writeq_relaxed(val, pmu->base + p_data->ddrc_perf_cnt_freerun_ctrl);
> +}
> +
> +static void ddr_pmu_write_clear_freerun(struct cn10k_ddr_pmu *pmu)
> +{
> + const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> + u64 val;
> +
> + val = DDRC_FREERUN_WRITE_CNT_CLR;
> + writeq_relaxed(val, pmu->base + p_data->ddrc_perf_cnt_freerun_ctrl);
> +}
> +
> +static void ddr_pmu_overflow_hander(struct cn10k_ddr_pmu *pmu, int evt_idx)
> +{
> + cn10k_ddr_perf_event_update_all(pmu);
> + cn10k_ddr_perf_pmu_disable(&pmu->pmu);
> + cn10k_ddr_perf_pmu_enable(&pmu->pmu);
> +}
> +
> static irqreturn_t cn10k_ddr_pmu_overflow_handler(struct cn10k_ddr_pmu *pmu)
> {
> + const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> + const struct ddr_pmu_ops *ops = p_data->ops;
> struct perf_event *event;
> struct hw_perf_event *hwc;
> u64 prev_count, new_count;
> @@ -586,11 +683,9 @@ static irqreturn_t cn10k_ddr_pmu_overflow_handler(struct cn10k_ddr_pmu *pmu)
> continue;
>
> value = cn10k_ddr_perf_read_counter(pmu, i);
> - if (value == DDRC_PERF_CNT_MAX_VALUE) {
> + if (value == p_data->counter_max_val) {
> pr_info("Counter-(%d) reached max value\n", i);
> - cn10k_ddr_perf_event_update_all(pmu);
> - cn10k_ddr_perf_pmu_disable(&pmu->pmu);
> - cn10k_ddr_perf_pmu_enable(&pmu->pmu);
> + ops->pmu_overflow_handler(pmu, i);
> }
> }
>
> @@ -629,13 +724,44 @@ static int cn10k_ddr_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
> return 0;
> }
>
> +static const struct ddr_pmu_ops ddr_pmu_ops = {
> + .enable_read_freerun_counter = ddr_pmu_enable_read_freerun,
> + .enable_write_freerun_counter = ddr_pmu_enable_write_freerun,
> + .clear_read_freerun_counter = ddr_pmu_read_clear_freerun,
> + .clear_write_freerun_counter = ddr_pmu_write_clear_freerun,
> + .pmu_overflow_handler = ddr_pmu_overflow_hander,
> +};
> +
> +static const struct ddr_pmu_platform_data cn10k_ddr_pmu_pdata = {
> + .counter_overflow_val = BIT_ULL(48),
> + .counter_max_val = GENMASK_ULL(48, 0),
> + .ddrc_perf_cnt_base = CN10K_DDRC_PERF_CNT_VALUE_BASE,
> + .ddrc_perf_cfg_base = CN10K_DDRC_PERF_CFG_BASE,
> + .ddrc_perf_cnt_op_mode_ctrl = CN10K_DDRC_PERF_CNT_OP_MODE_CTRL,
> + .ddrc_perf_cnt_start_op_ctrl = CN10K_DDRC_PERF_CNT_START_OP_CTRL,
> + .ddrc_perf_cnt_end_op_ctrl = CN10K_DDRC_PERF_CNT_END_OP_CTRL,
> + .ddrc_perf_cnt_end_status = CN10K_DDRC_PERF_CNT_END_STATUS,
> + .ddrc_perf_cnt_freerun_en = CN10K_DDRC_PERF_CNT_FREERUN_EN,
> + .ddrc_perf_cnt_freerun_ctrl = CN10K_DDRC_PERF_CNT_FREERUN_CTRL,
> + .ddrc_perf_cnt_freerun_clr = 0,
> + .ddrc_perf_cnt_value_wr_op = CN10K_DDRC_PERF_CNT_VALUE_WR_OP,
> + .ddrc_perf_cnt_value_rd_op = CN10K_DDRC_PERF_CNT_VALUE_RD_OP,
> + .ops = &ddr_pmu_ops,
> +};
> +
> +static const struct ddr_pmu_data ddr_pmu_data = {
> + .id = DDR_PMU_V1,
> +};
> +
> static int cn10k_ddr_perf_probe(struct platform_device *pdev)
> {
> + const struct ddr_pmu_data *dev_data;
> struct cn10k_ddr_pmu *ddr_pmu;
> struct resource *res;
> void __iomem *base;
> char *name;
> int ret;
> + int version;
>
> ddr_pmu = devm_kzalloc(&pdev->dev, sizeof(*ddr_pmu), GFP_KERNEL);
> if (!ddr_pmu)
> @@ -644,30 +770,42 @@ static int cn10k_ddr_perf_probe(struct platform_device *pdev)
> ddr_pmu->dev = &pdev->dev;
> platform_set_drvdata(pdev, ddr_pmu);
>
> + dev_data = device_get_match_data(&pdev->dev);
> + if (!dev_data) {
> + dev_err(&pdev->dev, "Error: No device match data found\n");
> + return -ENODEV;
> + }
> + version = dev_data->id;
> + ddr_pmu->version = version;
> +
> base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
> if (IS_ERR(base))
> return PTR_ERR(base);
>
> ddr_pmu->base = base;
>
> - /* Setup the PMU counter to work in manual mode */
> - writeq_relaxed(OP_MODE_CTRL_VAL_MANNUAL, ddr_pmu->base +
> - DDRC_PERF_CNT_OP_MODE_CTRL);
> -
> - ddr_pmu->pmu = (struct pmu) {
> - .module = THIS_MODULE,
> - .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
> - .task_ctx_nr = perf_invalid_context,
> - .attr_groups = cn10k_attr_groups,
> - .event_init = cn10k_ddr_perf_event_init,
> - .add = cn10k_ddr_perf_event_add,
> - .del = cn10k_ddr_perf_event_del,
> - .start = cn10k_ddr_perf_event_start,
> - .stop = cn10k_ddr_perf_event_stop,
> - .read = cn10k_ddr_perf_event_update,
> - .pmu_enable = cn10k_ddr_perf_pmu_enable,
> - .pmu_disable = cn10k_ddr_perf_pmu_disable,
> - };
> + if (version == DDR_PMU_V1) {
> + /* Setup the PMU counter to work in manual mode */
> + writeq_relaxed(OP_MODE_CTRL_VAL_MANUAL, ddr_pmu->base +
> + (ddr_pmu->p_data->ddrc_perf_cnt_op_mode_ctrl));
> +
> + ddr_pmu->pmu = (struct pmu) {
> + .module = THIS_MODULE,
> + .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
> + .task_ctx_nr = perf_invalid_context,
> + .attr_groups = cn10k_attr_groups,
> + .event_init = cn10k_ddr_perf_event_init,
> + .add = cn10k_ddr_perf_event_add,
> + .del = cn10k_ddr_perf_event_del,
> + .start = cn10k_ddr_perf_event_start,
> + .stop = cn10k_ddr_perf_event_stop,
> + .read = cn10k_ddr_perf_event_update,
> + .pmu_enable = cn10k_ddr_perf_pmu_enable,
> + .pmu_disable = cn10k_ddr_perf_pmu_disable,
> + };
> +
> + ddr_pmu->p_data = &cn10k_ddr_pmu_pdata;
> + }
>
> /* Choose this cpu to collect perf data */
> ddr_pmu->cpu = raw_smp_processor_id();
> @@ -688,7 +826,7 @@ static int cn10k_ddr_perf_probe(struct platform_device *pdev)
> if (ret)
> goto error;
>
> - pr_info("CN10K DDR PMU Driver for ddrc@%llx\n", res->start);
> + pr_info("DDR PMU Driver for ddrc@%llx\n", res->start);
> return 0;
> error:
> cpuhp_state_remove_instance_nocalls(
> @@ -711,7 +849,7 @@ static int cn10k_ddr_perf_remove(struct platform_device *pdev)
>
> #ifdef CONFIG_OF
> static const struct of_device_id cn10k_ddr_pmu_of_match[] = {
> - { .compatible = "marvell,cn10k-ddr-pmu", },
> + { .compatible = "marvell,cn10k-ddr-pmu", .data = &ddr_pmu_data},
> { },
> };
> MODULE_DEVICE_TABLE(of, cn10k_ddr_pmu_of_match);
> @@ -719,7 +857,7 @@ MODULE_DEVICE_TABLE(of, cn10k_ddr_pmu_of_match);
>
> #ifdef CONFIG_ACPI
> static const struct acpi_device_id cn10k_ddr_pmu_acpi_match[] = {
> - {"MRVL000A", 0},
> + {"MRVL000A", (kernel_ulong_t)&ddr_pmu_data},
> {},
> };
> MODULE_DEVICE_TABLE(acpi, cn10k_ddr_pmu_acpi_match);
> --
> 2.25.1
More information about the linux-arm-kernel
mailing list