[RFC PATCH 5/6] riscv: perf: introduce DT mechanism

Zong Li zong.li at sifive.com
Mon Jun 29 02:26:45 EDT 2020


On Mon, Jun 29, 2020 at 12:37 PM Anup Patel <anup at brainfault.org> wrote:
>
> On Mon, Jun 29, 2020 at 8:49 AM Zong Li <zong.li at sifive.com> wrote:
> >
> > Each architecture is responsible for mapping generic hardware and cache
> > events to their own specific encoding of hardware events. For each
> > architecture, it also have to distinguish the defination of hardware
> > events of different platforms of each vendor. We use DT file to describe
> > platform-specific information to make our perf implementation more
> > generic and common.
> >
> > Signed-off-by: Zong Li <zong.li at sifive.com>
> > ---
> >  arch/riscv/include/asm/perf_event.h |  55 ++----
> >  arch/riscv/kernel/perf_event.c      | 273 +++++++++++++---------------
> >  2 files changed, 139 insertions(+), 189 deletions(-)
> >
> > diff --git a/arch/riscv/include/asm/perf_event.h b/arch/riscv/include/asm/perf_event.h
> > index 41d515a1f331..e95d3bbaae3e 100644
> > --- a/arch/riscv/include/asm/perf_event.h
> > +++ b/arch/riscv/include/asm/perf_event.h
> > @@ -17,6 +17,8 @@
> >  #define RISCV_EVENT_COUNTERS   29
> >  #define RISCV_TOTAL_COUNTERS   (RISCV_BASE_COUNTERS + RISCV_EVENT_COUNTERS)
> >
> > +#define RISCV_DEFAULT_WIDTH_COUNTER    64
> > +
> >  /*
> >   * According to the spec, an implementation can support counter up to
> >   * mhpmcounter31, but many high-end processors has at most 6 general
> > @@ -33,9 +35,21 @@
> >
> >  #define RISCV_PMU_HPMCOUNTER_FIRST     3
> >  #define RISCV_PMU_HPMCOUNTER_LAST                                      \
> > -       (RISCV_PMU_HPMCOUNTER_FIRST + riscv_pmu->num_counters - 1)
> > +       (RISCV_PMU_HPMCOUNTER_FIRST + riscv_pmu.num_event_cntr - 1)
> > +
> > +#define RISCV_OP_UNSUPP                        (-EOPNOTSUPP)
> > +
> > +#define RISCV_MAP_ALL_UNSUPPORTED                                      \
> > +       [0 ... PERF_COUNT_HW_MAX - 1] = RISCV_OP_UNSUPP
> >
> > -#define RISCV_OP_UNSUPP                (-EOPNOTSUPP)
> > +#define C(x) PERF_COUNT_HW_CACHE_##x
> > +
> > +#define RISCV_CACHE_MAP_ALL_UNSUPPORTED                                        \
> > +[0 ... C(MAX) - 1] = {                                                 \
> > +       [0 ... C(OP_MAX) - 1] = {                                       \
> > +               [0 ... C(RESULT_MAX) - 1] = RISCV_OP_UNSUPP,            \
> > +       },                                                              \
> > +}
> >
> >  /* Hardware cache event encoding */
> >  #define PERF_HW_CACHE_TYPE             0
> > @@ -65,43 +79,6 @@
> >  #define CSR_MHPMEVENT7 0x327
> >  #define CSR_MHPMEVENT8 0x328
> >
> > -struct cpu_hw_events {
> > -       /* # currently enabled events*/
> > -       int                     n_events;
> > -       /* currently enabled events */
> > -       struct perf_event       *events[RISCV_EVENT_COUNTERS];
> > -       /* bitmap of used event counters */
> > -       unsigned long           used_cntr_mask;
> > -       /* vendor-defined PMU data */
> > -       void                    *platform;
> > -};
> > -
> > -struct riscv_pmu {
> > -       struct pmu      *pmu;
> > -
> > -       /* generic hw/cache events table */
> > -       const int       *hw_events;
> > -       const int       (*cache_events)[PERF_COUNT_HW_CACHE_MAX]
> > -                                      [PERF_COUNT_HW_CACHE_OP_MAX]
> > -                                      [PERF_COUNT_HW_CACHE_RESULT_MAX];
> > -       /* method used to map hw/cache events */
> > -       int             (*map_hw_event)(u64 config);
> > -       int             (*map_cache_event)(u64 config);
> > -
> > -       /* max generic hw events in map */
> > -       int             max_events;
> > -       /* number total counters, 2(base) + x(general) */
> > -       int             num_counters;
> > -       /* the width of the counter */
> > -       int             counter_width;
> > -
> > -       /* vendor-defined PMU features */
> > -       void            *platform;
> > -
> > -       irqreturn_t     (*handle_irq)(int irq_num, void *dev);
> > -       int             irq;
> > -};
> > -
> >  #endif
> >  #ifdef CONFIG_PERF_EVENTS
> >  #define perf_arch_bpf_user_pt_regs(regs) (struct user_regs_struct *)regs
> > diff --git a/arch/riscv/kernel/perf_event.c b/arch/riscv/kernel/perf_event.c
> > index 0cfcd6f1e57b..3bdfbe4efd5c 100644
> > --- a/arch/riscv/kernel/perf_event.c
> > +++ b/arch/riscv/kernel/perf_event.c
> > @@ -9,6 +9,7 @@
> >   * Copyright (C) 2009 Google, Inc., Stephane Eranian
> >   * Copyright 2014 Tilera Corporation. All Rights Reserved.
> >   * Copyright (C) 2018 Andes Technology Corporation
> > + * Copyright (C) 2020 SiFive
> >   *
> >   * Perf_events support for RISC-V platforms.
> >   *
> > @@ -30,113 +31,55 @@
> >  #include <linux/perf_event.h>
> >  #include <linux/atomic.h>
> >  #include <linux/of.h>
> > +#include <asm/csr.h>
> >  #include <asm/perf_event.h>
> >
> > -static const struct riscv_pmu *riscv_pmu __read_mostly;
> > +static struct riscv_pmu {
> > +       struct pmu      *pmu;
> > +
> > +       /* number of event counters */
> > +       int             num_event_cntr;
> > +
> > +       /* the width of base counters */
> > +       int             width_base_cntr;
> > +
> > +       /* the width of event counters */
> > +       int             width_event_cntr;
> > +
> > +       irqreturn_t     (*handle_irq)(int irq_num, void *dev);
> > +
> > +       int             irq;
> > +} riscv_pmu;
> > +
> > +struct cpu_hw_events {
> > +       /* # currently enabled events*/
> > +       int                     n_events;
> > +
> > +       /* currently enabled events */
> > +       struct perf_event       *events[RISCV_EVENT_COUNTERS];
> > +
> > +       /* bitmap of used event counters */
> > +       unsigned long           used_cntr_mask;
> > +};
> > +
> >  static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
> >
> >  /*
> >   * Hardware & cache maps and their methods
> >   */
> >
> > -static const int riscv_hw_event_map[] = {
> > -       [PERF_COUNT_HW_CPU_CYCLES]              = RISCV_PMU_CYCLE,
> > -       [PERF_COUNT_HW_INSTRUCTIONS]            = RISCV_PMU_INSTRET,
> > -       [PERF_COUNT_HW_CACHE_REFERENCES]        = RISCV_OP_UNSUPP,
> > -       [PERF_COUNT_HW_CACHE_MISSES]            = RISCV_OP_UNSUPP,
> > -       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = RISCV_OP_UNSUPP,
> > -       [PERF_COUNT_HW_BRANCH_MISSES]           = RISCV_OP_UNSUPP,
> > -       [PERF_COUNT_HW_BUS_CYCLES]              = RISCV_OP_UNSUPP,
> > +static int riscv_hw_event_map[PERF_COUNT_HW_MAX] = {
> > +       RISCV_MAP_ALL_UNSUPPORTED,
> > +
> > +       /* Specify base pmu, even if they aren't present in DT file */
> > +       [PERF_COUNT_HW_CPU_CYCLES]      = RISCV_PMU_CYCLE,
> > +       [PERF_COUNT_HW_INSTRUCTIONS]    = RISCV_PMU_INSTRET,
> >  };
> >
> > -#define C(x) PERF_COUNT_HW_CACHE_##x
> > -static const int riscv_cache_event_map[PERF_COUNT_HW_CACHE_MAX]
> > -[PERF_COUNT_HW_CACHE_OP_MAX]
> > -[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
> > -       [C(L1D)] = {
> > -               [C(OP_READ)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_WRITE)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_PREFETCH)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -       },
> > -       [C(L1I)] = {
> > -               [C(OP_READ)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_WRITE)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_PREFETCH)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -       },
> > -       [C(LL)] = {
> > -               [C(OP_READ)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_WRITE)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_PREFETCH)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -       },
> > -       [C(DTLB)] = {
> > -               [C(OP_READ)] = {
> > -                       [C(RESULT_ACCESS)] =  RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] =  RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_WRITE)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_PREFETCH)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -       },
> > -       [C(ITLB)] = {
> > -               [C(OP_READ)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_WRITE)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_PREFETCH)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -       },
> > -       [C(BPU)] = {
> > -               [C(OP_READ)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_WRITE)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -               [C(OP_PREFETCH)] = {
> > -                       [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
> > -                       [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
> > -               },
> > -       },
> > +static int riscv_cache_event_map[PERF_COUNT_HW_CACHE_MAX]
> > +                               [PERF_COUNT_HW_CACHE_OP_MAX]
> > +                               [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
> > +       RISCV_CACHE_MAP_ALL_UNSUPPORTED,
> >  };
> >
> >  /*
> > @@ -154,6 +97,17 @@ static inline int is_event_counter(int idx)
> >                 idx <= RISCV_PMU_HPMCOUNTER_LAST);
> >  }
> >
> > +static inline int get_counter_width(int idx)
> > +{
> > +       if (is_base_counter(idx))
> > +               return riscv_pmu.width_base_cntr;
> > +
> > +       if (is_event_counter(idx))
> > +               return riscv_pmu.width_event_cntr;
> > +
> > +       return 0;
> > +}
> > +
> >  static inline int get_available_counter(struct perf_event *event)
> >  {
> >         struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
> > @@ -188,10 +142,14 @@ static inline int get_available_counter(struct perf_event *event)
> >   */
> >  static int riscv_map_hw_event(u64 config)
> >  {
> > -       if (config >= riscv_pmu->max_events)
> > +       int ret;
> > +
> > +       if (config >= PERF_COUNT_HW_MAX)
> >                 return -EINVAL;
> >
> > -       return riscv_pmu->hw_events[config];
> > +       ret = riscv_hw_event_map[config];
> > +
> > +       return ret == RISCV_OP_UNSUPP ? -ENOENT : ret;
> >  }
> >
> >  /*
> > @@ -355,7 +313,7 @@ static void riscv_pmu_read(struct perf_event *event)
> >          * delta is the value to update the counter we maintain in the kernel.
> >          */
> >         delta = (new_raw_count - prev_raw_count) &
> > -               ((1ULL << riscv_pmu->counter_width) - 1);
> > +               ((1ULL << get_counter_width(idx)) - 1);
> >
> >         local64_add(delta, &event->count);
> >         /*
> > @@ -386,7 +344,7 @@ static void riscv_pmu_stop(struct perf_event *event, int flags)
> >         hwc->state |= PERF_HES_STOPPED;
> >
> >         if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
> > -               riscv_pmu->pmu->read(event);
> > +               riscv_pmu_read(event);
> >                 hwc->state |= PERF_HES_UPTODATE;
> >         }
> >  }
> > @@ -429,7 +387,7 @@ static int riscv_pmu_add(struct perf_event *event, int flags)
> >         struct hw_perf_event *hwc = &event->hw;
> >         int count_idx;
> >
> > -       if (cpuc->n_events == riscv_pmu->num_counters)
> > +       if (cpuc->n_events == riscv_pmu.num_event_cntr)
> >                 return -ENOSPC;
> >
> >         count_idx = get_available_counter(event);
> > @@ -437,13 +395,13 @@ static int riscv_pmu_add(struct perf_event *event, int flags)
> >                 return -ENOSPC;
> >
> >         cpuc->n_events++;
> > +
> >         hwc->idx = count_idx;
> > -       cpuc->events[hwc->idx] = event;
> >
> >         hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
> >
> >         if (flags & PERF_EF_START)
> > -               riscv_pmu->pmu->start(event, PERF_EF_RELOAD);
> > +               riscv_pmu_start(event, PERF_EF_RELOAD);
> >
> >         return 0;
> >  }
> > @@ -459,8 +417,8 @@ static void riscv_pmu_del(struct perf_event *event, int flags)
> >         cpuc->n_events--;
> >         __clear_bit(hwc->idx, &cpuc->used_cntr_mask);
> >
> > -       cpuc->events[hwc->idx] = NULL;
> > -       riscv_pmu->pmu->stop(event, PERF_EF_UPDATE);
> > +       riscv_pmu_stop(event, PERF_EF_UPDATE);
> > +
> >         perf_event_update_userpage(event);
> >  }
> >
> > @@ -470,7 +428,7 @@ static void riscv_pmu_del(struct perf_event *event, int flags)
> >
> >  static DEFINE_MUTEX(pmc_reserve_mutex);
> >
> > -static irqreturn_t riscv_base_pmu_handle_irq(int irq_num, void *dev)
> > +static irqreturn_t riscv_pmu_handle_irq(int irq_num, void *dev)
> >  {
> >         return IRQ_NONE;
> >  }
> > @@ -480,8 +438,8 @@ static int reserve_pmc_hardware(void)
> >         int err = 0;
> >
> >         mutex_lock(&pmc_reserve_mutex);
> > -       if (riscv_pmu->irq >= 0 && riscv_pmu->handle_irq) {
> > -               err = request_irq(riscv_pmu->irq, riscv_pmu->handle_irq,
> > +       if (riscv_pmu.irq >= 0 && riscv_pmu.handle_irq) {
> > +               err = request_irq(riscv_pmu.irq, riscv_pmu.handle_irq,
> >                                   IRQF_PERCPU, "riscv-base-perf", NULL);
> >         }
> >         mutex_unlock(&pmc_reserve_mutex);
> > @@ -492,8 +450,8 @@ static int reserve_pmc_hardware(void)
> >  static void release_pmc_hardware(void)
> >  {
> >         mutex_lock(&pmc_reserve_mutex);
> > -       if (riscv_pmu->irq >= 0)
> > -               free_irq(riscv_pmu->irq, NULL);
> > +       if (riscv_pmu.irq >= 0)
> > +               free_irq(riscv_pmu.irq, NULL);
> >         mutex_unlock(&pmc_reserve_mutex);
> >  }
> >
> > @@ -529,10 +487,10 @@ static int riscv_event_init(struct perf_event *event)
> >
> >         switch (event->attr.type) {
> >         case PERF_TYPE_HARDWARE:
> > -               code = riscv_pmu->map_hw_event(attr->config);
> > +               code = riscv_map_hw_event(attr->config);
> >                 break;
> >         case PERF_TYPE_HW_CACHE:
> > -               code = riscv_pmu->map_cache_event(attr->config);
> > +               code = riscv_map_cache_event(attr->config);
> >                 break;
> >         case PERF_TYPE_RAW:
> >                 code = attr->config;
> > @@ -555,9 +513,6 @@ static int riscv_event_init(struct perf_event *event)
> >         /*
> >          * idx is set to -1 because the index of a general event should not be
> >          * decided until binding to some counter in pmu->add().
> > -        *
> > -        * But since we don't have such support, later in pmu->add(), we just
> > -        * use hwc->config as the index instead.
> >          */
> >         hwc->config_base = config_base;
> >         hwc->config = code;
> > @@ -570,52 +525,70 @@ static int riscv_event_init(struct perf_event *event)
> >   * Initialization
> >   */
> >
> > -static struct pmu min_pmu = {
> > -       .name           = "riscv-base",
> > -       .event_init     = riscv_event_init,
> > -       .add            = riscv_pmu_add,
> > -       .del            = riscv_pmu_del,
> > -       .start          = riscv_pmu_start,
> > -       .stop           = riscv_pmu_stop,
> > -       .read           = riscv_pmu_read,
> > -};
> > +static struct riscv_pmu riscv_pmu = {
> > +       .pmu = &(struct pmu) {
> > +               .name           = "riscv-pmu",
> > +               .event_init     = riscv_event_init,
> > +               .add            = riscv_pmu_add,
> > +               .del            = riscv_pmu_del,
> > +               .start          = riscv_pmu_start,
> > +               .stop           = riscv_pmu_stop,
> > +               .read           = riscv_pmu_read,
> > +       },
> >
> > -static const struct riscv_pmu riscv_base_pmu = {
> > -       .pmu = &min_pmu,
> > -       .max_events = ARRAY_SIZE(riscv_hw_event_map),
> > -       .map_hw_event = riscv_map_hw_event,
> > -       .hw_events = riscv_hw_event_map,
> > -       .map_cache_event = riscv_map_cache_event,
> > -       .cache_events = &riscv_cache_event_map,
> > -       .counter_width = 63,
> > -       .num_counters = RISCV_BASE_COUNTERS + 0,
> > -       .handle_irq = &riscv_base_pmu_handle_irq,
> > +       .num_event_cntr = 0,
> > +       .width_event_cntr = RISCV_DEFAULT_WIDTH_COUNTER,
> > +       .width_base_cntr = RISCV_DEFAULT_WIDTH_COUNTER,
> >
> > +       .handle_irq = &riscv_pmu_handle_irq,
> >         /* This means this PMU has no IRQ. */
> >         .irq = -1,
> >  };
> >
> > -static const struct of_device_id riscv_pmu_of_ids[] = {
> > -       {.compatible = "riscv,base-pmu",        .data = &riscv_base_pmu},
> > -       { /* sentinel value */ }
> > -};
> > +static int __init init_riscv_pmu(struct device_node *node)
> > +{
> > +       int num_events, key, value, i;
> > +
> > +       of_property_read_u32(node, "riscv,width-base-cntr", &riscv_pmu.width_base_cntr);
> > +
> > +       of_property_read_u32(node, "riscv,width-event-cntr", &riscv_pmu.width_event_cntr);
> > +
> > +       of_property_read_u32(node, "riscv,n-event-cntr", &riscv_pmu.num_event_cntr);
> > +       if (riscv_pmu.num_event_cntr > RISCV_EVENT_COUNTERS)
> > +               riscv_pmu.num_event_cntr = RISCV_EVENT_COUNTERS;
> > +
> > +       num_events = of_property_count_u32_elems(node, "riscv,hw-event-map");
> > +       if (num_events > 0 && num_events % 2 == 0)
> > +               for (i = 0; i < num_events;) {
> > +                       of_property_read_u32_index(node, "riscv,hw-event-map", i++, &key);
> > +                       of_property_read_u32_index(node, "riscv,hw-event-map", i++, &value);
> > +                       riscv_hw_event_map[key] = value;
> > +               }
> > +
> > +       num_events = of_property_count_u32_elems(node, "riscv,hw-cache-event-map");
> > +       if (num_events > 0 && num_events % 2 == 0)
> > +               for (i = 0; i < num_events;) {
> > +                       of_property_read_u32_index(node, "riscv,hw-cache-event-map", i++, &key);
> > +                       of_property_read_u32_index(node, "riscv,hw-cache-event-map", i++, &value);
> > +                       riscv_cache_event_map
> > +                               [(key >> PERF_HW_CACHE_TYPE) & PERF_HW_CACHE_MASK]
> > +                               [(key >> PERF_HW_CACHE_OP) & PERF_HW_CACHE_MASK]
> > +                               [(key >> PERF_HW_CACHE_RESULT) & PERF_HW_CACHE_MASK] = value;
> > +               }
> > +
> > +       return 0;
> > +}
> >
> >  static int __init init_hw_perf_events(void)
> >  {
> > -       struct device_node *node = of_find_node_by_type(NULL, "pmu");
> > -       const struct of_device_id *of_id;
> > +       struct device_node *node = of_find_compatible_node(NULL, NULL, "riscv,pmu");
> >
> > -       riscv_pmu = &riscv_base_pmu;
> > +       if (node)
> > +               init_riscv_pmu(node);
> >
> > -       if (node) {
> > -               of_id = of_match_node(riscv_pmu_of_ids, node);
> > -
> > -               if (of_id)
> > -                       riscv_pmu = of_id->data;
> > -               of_node_put(node);
> > -       }
> > +       /* Even if there is no pmu node in DT, we reach here for base PMU. */
> > +       perf_pmu_register(riscv_pmu.pmu, "cpu", PERF_TYPE_RAW);
> >
> > -       perf_pmu_register(riscv_pmu->pmu, "cpu", PERF_TYPE_RAW);
> >         return 0;
> >  }
> >  arch_initcall(init_hw_perf_events);
>
> Why does this have to arch_initcall() ??
> Why can't we just probe this like a regular DT based driver ??
>
> This driver needs total re-write because it has to be a platform driver.
> Even the names of counters are not registered. The implementation
> specific counter names should come from DT property.
>

We have some discussion in the cover letter, let us talk about in one place. :)

> Regards,
> Anup
>
> > --
> > 2.27.0
> >



More information about the linux-riscv mailing list