Skip to content

Commit 6de0298

Browse files
rmurphy-armwilldeacon
authored andcommitted
perf/arm_cspmu: Generalise event filtering
The notion of a single u32 filter value for any event doesn't scale well when the potential architectural scope is already two 64-bit values, and implementations may add custom stuff on the side too. Rather than try to thread arbitrary filter data through the common path, let's just make the set_ev_filter op self-contained in terms of parsing and configuring any and all filtering for the given event - splitting out a distinct op for cycles events which inherently differ - and let implementations override the whole thing if they want to do something different. This already allows the Ampere code to stop looking a bit hacky. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Reviewed-by: James Clark <james.clark@linaro.org> Reviewed-by: Ilkka Koskinen <ilkka@os.amperecomputing.com> Link: https://lore.kernel.org/r/c0cd4d4c12566dbf1b062ccd60241b3e0639f4cc.1741190362.git.robin.murphy@arm.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent 862f7ad commit 6de0298

File tree

4 files changed

+42
-40
lines changed

4 files changed

+42
-40
lines changed

drivers/perf/arm_cspmu/ampere_cspmu.c

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -132,32 +132,20 @@ ampere_cspmu_get_name(const struct arm_cspmu *cspmu)
132132
return ctx->name;
133133
}
134134

135-
static u32 ampere_cspmu_event_filter(const struct perf_event *event)
135+
static void ampere_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
136+
const struct perf_event *event)
136137
{
137138
/*
138-
* PMEVFILTR or PMCCFILTR aren't used in Ampere SoC PMU but are marked
139-
* as RES0. Make sure, PMCCFILTR is written zero.
139+
* PMCCFILTR is RES0, so this is just a dummy callback to override
140+
* the default implementation and avoid writing to it.
140141
*/
141-
return 0;
142142
}
143143

144144
static void ampere_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
145-
struct hw_perf_event *hwc,
146-
u32 filter)
145+
const struct perf_event *event)
147146
{
148-
struct perf_event *event;
149-
unsigned int idx;
150147
u32 threshold, rank, bank;
151148

152-
/*
153-
* At this point, all the events have the same filter settings.
154-
* Therefore, take the first event and use its configuration.
155-
*/
156-
idx = find_first_bit(cspmu->hw_events.used_ctrs,
157-
cspmu->cycle_counter_logical_idx);
158-
159-
event = cspmu->hw_events.events[idx];
160-
161149
threshold = get_threshold(event);
162150
rank = get_rank(event);
163151
bank = get_bank(event);
@@ -233,7 +221,7 @@ static int ampere_cspmu_init_ops(struct arm_cspmu *cspmu)
233221

234222
cspmu->impl.ctx = ctx;
235223

236-
impl_ops->event_filter = ampere_cspmu_event_filter;
224+
impl_ops->set_cc_filter = ampere_cspmu_set_cc_filter;
237225
impl_ops->set_ev_filter = ampere_cspmu_set_ev_filter;
238226
impl_ops->validate_event = ampere_cspmu_validate_event;
239227
impl_ops->get_name = ampere_cspmu_get_name;

drivers/perf/arm_cspmu/arm_cspmu.c

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ static unsigned long arm_cspmu_cpuhp_state;
6666
static DEFINE_MUTEX(arm_cspmu_lock);
6767

6868
static void arm_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
69-
struct hw_perf_event *hwc, u32 filter);
69+
const struct perf_event *event);
70+
static void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
71+
const struct perf_event *event);
7072

7173
static struct acpi_apmt_node *arm_cspmu_apmt_node(struct device *dev)
7274
{
@@ -205,11 +207,6 @@ static bool arm_cspmu_is_cycle_counter_event(const struct perf_event *event)
205207
return (event->attr.config == ARM_CSPMU_EVT_CYCLES_DEFAULT);
206208
}
207209

208-
static u32 arm_cspmu_event_filter(const struct perf_event *event)
209-
{
210-
return event->attr.config1 & ARM_CSPMU_FILTER_MASK;
211-
}
212-
213210
static ssize_t arm_cspmu_identifier_show(struct device *dev,
214211
struct device_attribute *attr,
215212
char *page)
@@ -371,7 +368,7 @@ static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
371368
DEFAULT_IMPL_OP(get_name),
372369
DEFAULT_IMPL_OP(is_cycle_counter_event),
373370
DEFAULT_IMPL_OP(event_type),
374-
DEFAULT_IMPL_OP(event_filter),
371+
DEFAULT_IMPL_OP(set_cc_filter),
375372
DEFAULT_IMPL_OP(set_ev_filter),
376373
DEFAULT_IMPL_OP(event_attr_is_visible),
377374
};
@@ -767,40 +764,38 @@ static inline void arm_cspmu_set_event(struct arm_cspmu *cspmu,
767764
}
768765

769766
static void arm_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
770-
struct hw_perf_event *hwc,
771-
u32 filter)
767+
const struct perf_event *event)
772768
{
769+
u32 filter = event->attr.config1 & ARM_CSPMU_FILTER_MASK;
773770
u32 offset = PMEVFILTR + (4 * hwc->idx);
774771

775772
writel(filter, cspmu->base0 + offset);
776773
}
777774

778-
static inline void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu, u32 filter)
775+
static void arm_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
776+
const struct perf_event *event)
779777
{
780-
u32 offset = PMCCFILTR;
778+
u32 filter = event->attr.config1 & ARM_CSPMU_FILTER_MASK;
781779

782-
writel(filter, cspmu->base0 + offset);
780+
writel(filter, cspmu->base0 + PMCCFILTR);
783781
}
784782

785783
static void arm_cspmu_start(struct perf_event *event, int pmu_flags)
786784
{
787785
struct arm_cspmu *cspmu = to_arm_cspmu(event->pmu);
788786
struct hw_perf_event *hwc = &event->hw;
789-
u32 filter;
790787

791788
/* We always reprogram the counter */
792789
if (pmu_flags & PERF_EF_RELOAD)
793790
WARN_ON(!(hwc->state & PERF_HES_UPTODATE));
794791

795792
arm_cspmu_set_event_period(event);
796793

797-
filter = cspmu->impl.ops.event_filter(event);
798-
799794
if (event->hw.extra_reg.idx == cspmu->cycle_counter_logical_idx) {
800-
arm_cspmu_set_cc_filter(cspmu, filter);
795+
cspmu->impl.ops.set_cc_filter(cspmu, event);
801796
} else {
802797
arm_cspmu_set_event(cspmu, hwc);
803-
cspmu->impl.ops.set_ev_filter(cspmu, hwc, filter);
798+
cspmu->impl.ops.set_ev_filter(cspmu, event);
804799
}
805800

806801
hwc->state = 0;

drivers/perf/arm_cspmu/arm_cspmu.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,11 @@ struct arm_cspmu_impl_ops {
149149
bool (*is_cycle_counter_event)(const struct perf_event *event);
150150
/* Decode event type/id from configs */
151151
u32 (*event_type)(const struct perf_event *event);
152-
/* Decode filter value from configs */
153-
u32 (*event_filter)(const struct perf_event *event);
154-
/* Set event filter */
152+
/* Set event filters */
153+
void (*set_cc_filter)(struct arm_cspmu *cspmu,
154+
const struct perf_event *event);
155155
void (*set_ev_filter)(struct arm_cspmu *cspmu,
156-
struct hw_perf_event *hwc, u32 filter);
156+
const struct perf_event *event);
157157
/* Implementation specific event validation */
158158
int (*validate_event)(struct arm_cspmu *cspmu,
159159
struct perf_event *event);

drivers/perf/arm_cspmu/nvidia_cspmu.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,24 @@ static u32 nv_cspmu_event_filter(const struct perf_event *event)
183183
return filter_val;
184184
}
185185

186+
static void nv_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
187+
const struct perf_event *event)
188+
{
189+
u32 filter = nv_cspmu_event_filter(event);
190+
u32 offset = PMEVFILTR + (4 * event->hw.idx);
191+
192+
writel(filter, cspmu->base0 + offset);
193+
}
194+
195+
static void nv_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
196+
const struct perf_event *event)
197+
{
198+
u32 filter = nv_cspmu_event_filter(event);
199+
200+
writel(filter, cspmu->base0 + PMCCFILTR);
201+
}
202+
203+
186204
enum nv_cspmu_name_fmt {
187205
NAME_FMT_GENERIC,
188206
NAME_FMT_SOCKET
@@ -322,7 +340,8 @@ static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
322340
cspmu->impl.ctx = ctx;
323341

324342
/* NVIDIA specific callbacks. */
325-
impl_ops->event_filter = nv_cspmu_event_filter;
343+
impl_ops->set_cc_filter = nv_cspmu_set_cc_filter;
344+
impl_ops->set_ev_filter = nv_cspmu_set_ev_filter;
326345
impl_ops->get_event_attrs = nv_cspmu_get_event_attrs;
327346
impl_ops->get_format_attrs = nv_cspmu_get_format_attrs;
328347
impl_ops->get_name = nv_cspmu_get_name;

0 commit comments

Comments
 (0)