]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
perf/marvell: Refactor to extract PMU operations
authorGowthami Thiagarajan <gthiagarajan@marvell.com>
Fri, 8 Nov 2024 04:06:16 +0000 (09:36 +0530)
committerWill Deacon <will@kernel.org>
Mon, 9 Dec 2024 15:57:34 +0000 (15:57 +0000)
Introduce a refactor to the Marvell DDR PMU driver to extract
PMU operations ("pmu ops") from the existing driver.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@Huawei.com>
Signed-off-by: Gowthami Thiagarajan <gthiagarajan@marvell.com>
Link: https://lore.kernel.org/r/20241108040619.753343-3-gthiagarajan@marvell.com
Signed-off-by: Will Deacon <will@kernel.org>
drivers/perf/marvell_cn10k_ddr_pmu.c

index d375ea40add75a7ddd13c41b4b43def5a89a5a96..ffdb642fada92a80dd817961f9259988cfe30919 100644 (file)
@@ -127,6 +127,7 @@ struct cn10k_ddr_pmu {
        struct pmu pmu;
        void __iomem *base;
        const struct ddr_pmu_platform_data *p_data;
+       const struct ddr_pmu_ops *ops;
        unsigned int cpu;
        struct  device *dev;
        int active_events;
@@ -135,6 +136,16 @@ 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 {
@@ -375,6 +386,7 @@ 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 = pmu->ops;
        u32 reg;
        u64 val;
 
@@ -394,21 +406,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 +
-                                   p_data->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 +
-                              p_data->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);
        }
 }
 
@@ -464,6 +465,7 @@ 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 = pmu->ops;
        struct hw_perf_event *hwc = &event->hw;
        u8 config = event->attr.config;
        int counter, ret;
@@ -492,11 +494,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 + p_data->cnt_freerun_ctrl);
+                       ops->clear_write_freerun_counter(pmu);
        }
 
        hwc->state |= PERF_HES_STOPPED;
@@ -578,9 +578,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->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->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->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->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->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->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 = pmu->ops;
        struct perf_event *event;
        struct hw_perf_event *hwc;
        u64 prev_count, new_count;
@@ -620,9 +674,7 @@ static irqreturn_t cn10k_ddr_pmu_overflow_handler(struct cn10k_ddr_pmu *pmu)
                value = cn10k_ddr_perf_read_counter(pmu, i);
                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);
                }
        }
 
@@ -661,6 +713,14 @@ 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,
+};
+
 #if defined(CONFIG_ACPI) || defined(CONFIG_OF)
 static const struct ddr_pmu_platform_data cn10k_ddr_pmu_pdata = {
        .counter_overflow_val =  BIT_ULL(48),
@@ -713,6 +773,7 @@ static int cn10k_ddr_perf_probe(struct platform_device *pdev)
        is_cn10k = ddr_pmu->p_data->is_cn10k;
 
        if (is_cn10k) {
+               ddr_pmu->ops = &ddr_pmu_ops;
                /* Setup the PMU counter to work in manual mode */
                writeq_relaxed(OP_MODE_CTRL_VAL_MANUAL, ddr_pmu->base +
                               ddr_pmu->p_data->cnt_op_mode_ctrl);