aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuzuki K. Poulose <suzuki.poulose@arm.com>2015-05-26 05:53:16 -0400
committerArnd Bergmann <arnd@arndb.de>2015-05-29 10:43:52 -0400
commite14cfad3fef6f1d0a968aca639481139747ffcde (patch)
tree6d6689ddaa0ac38e2055466e7ec4e634275597cd
parenta95791efa72a08d3824713a75235d0407c0715dc (diff)
arm-cci: Add aliases for PMU events
Each CCI model have different event/source codes and formats. This patch exports this information via the sysfs, which includes the aliases for the events. The aliases are listed by 'perf list', helping the users to specify the name of the event instead of the binary config values. Each event alias must accompany the 'source' code except for the following cases : 1) CCI-400 - cycles event, doesn't relate to an interface. 2) CCI-500 - Global events to the CCI. (Fixed source code = 0xf) Each CCI model provides two sets of attributes(format and event), which are dynamically populated before registering the PMU, to allow for the appropriate information. Cc: Punit Agrawal <punit.agrawal@arm.com> Cc: Will Deacon <will.deacon@arm.com> Cc: Pawel Moll <pawel.moll@arm.com> Cc: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com> Acked-by: Punit Agrawal <punit.agrawal@arm.com> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--drivers/bus/arm-cci.c296
1 files changed, 295 insertions, 1 deletions
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 1475eafbd25c..577cc4bf6a9d 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -121,6 +121,10 @@ struct cci_pmu_model {
121 u32 fixed_hw_cntrs; 121 u32 fixed_hw_cntrs;
122 u32 num_hw_cntrs; 122 u32 num_hw_cntrs;
123 u32 cntr_size; 123 u32 cntr_size;
124 u64 nformat_attrs;
125 u64 nevent_attrs;
126 struct dev_ext_attribute *format_attrs;
127 struct dev_ext_attribute *event_attrs;
124 struct event_range event_ranges[CCI_IF_MAX]; 128 struct event_range event_ranges[CCI_IF_MAX];
125 int (*validate_hw_event)(struct cci_pmu *, unsigned long); 129 int (*validate_hw_event)(struct cci_pmu *, unsigned long);
126 int (*get_event_idx)(struct cci_pmu *, struct cci_pmu_hw_events *, unsigned long); 130 int (*get_event_idx)(struct cci_pmu *, struct cci_pmu_hw_events *, unsigned long);
@@ -157,6 +161,19 @@ enum cci_models {
157 CCI_MODEL_MAX 161 CCI_MODEL_MAX
158}; 162};
159 163
164static ssize_t cci_pmu_format_show(struct device *dev,
165 struct device_attribute *attr, char *buf);
166static ssize_t cci_pmu_event_show(struct device *dev,
167 struct device_attribute *attr, char *buf);
168
169#define CCI_EXT_ATTR_ENTRY(_name, _func, _config) \
170 { __ATTR(_name, S_IRUGO, _func, NULL), (void *)_config }
171
172#define CCI_FORMAT_EXT_ATTR_ENTRY(_name, _config) \
173 CCI_EXT_ATTR_ENTRY(_name, cci_pmu_format_show, (char *)_config)
174#define CCI_EVENT_EXT_ATTR_ENTRY(_name, _config) \
175 CCI_EXT_ATTR_ENTRY(_name, cci_pmu_event_show, (unsigned long)_config)
176
160/* CCI400 PMU Specific definitions */ 177/* CCI400 PMU Specific definitions */
161 178
162#ifdef CONFIG_ARM_CCI400_PMU 179#ifdef CONFIG_ARM_CCI400_PMU
@@ -218,6 +235,106 @@ enum cci400_perf_events {
218#define CCI400_R1_MASTER_PORT_MIN_EV 0x00 235#define CCI400_R1_MASTER_PORT_MIN_EV 0x00
219#define CCI400_R1_MASTER_PORT_MAX_EV 0x11 236#define CCI400_R1_MASTER_PORT_MAX_EV 0x11
220 237
238#define CCI400_CYCLE_EVENT_EXT_ATTR_ENTRY(_name, _config) \
239 CCI_EXT_ATTR_ENTRY(_name, cci400_pmu_cycle_event_show, \
240 (unsigned long)_config)
241
242static ssize_t cci400_pmu_cycle_event_show(struct device *dev,
243 struct device_attribute *attr, char *buf);
244
245static struct dev_ext_attribute cci400_pmu_format_attrs[] = {
246 CCI_FORMAT_EXT_ATTR_ENTRY(event, "config:0-4"),
247 CCI_FORMAT_EXT_ATTR_ENTRY(source, "config:5-7"),
248};
249
250static struct dev_ext_attribute cci400_r0_pmu_event_attrs[] = {
251 /* Slave events */
252 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_any, 0x0),
253 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_device, 0x01),
254 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_normal_or_nonshareable, 0x2),
255 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_inner_or_outershareable, 0x3),
256 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_cache_maintenance, 0x4),
257 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_mem_barrier, 0x5),
258 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_sync_barrier, 0x6),
259 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_dvm_msg, 0x7),
260 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_dvm_msg_sync, 0x8),
261 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_stall_tt_full, 0x9),
262 CCI_EVENT_EXT_ATTR_ENTRY(si_r_data_last_hs_snoop, 0xA),
263 CCI_EVENT_EXT_ATTR_ENTRY(si_r_data_stall_rvalids_h_rready_l, 0xB),
264 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_any, 0xC),
265 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_device, 0xD),
266 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_normal_or_nonshareable, 0xE),
267 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_inner_or_outershare_wback_wclean, 0xF),
268 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_write_unique, 0x10),
269 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_write_line_unique, 0x11),
270 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_evict, 0x12),
271 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_stall_tt_full, 0x13),
272 /* Master events */
273 CCI_EVENT_EXT_ATTR_ENTRY(mi_retry_speculative_fetch, 0x14),
274 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_addr_hazard, 0x15),
275 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_id_hazard, 0x16),
276 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_tt_full, 0x17),
277 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_barrier_hazard, 0x18),
278 CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_barrier_hazard, 0x19),
279 CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_tt_full, 0x1A),
280 /* Special event for cycles counter */
281 CCI400_CYCLE_EVENT_EXT_ATTR_ENTRY(cycles, 0xff),
282};
283
284static struct dev_ext_attribute cci400_r1_pmu_event_attrs[] = {
285 /* Slave events */
286 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_any, 0x0),
287 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_device, 0x01),
288 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_normal_or_nonshareable, 0x2),
289 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_inner_or_outershareable, 0x3),
290 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_cache_maintenance, 0x4),
291 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_mem_barrier, 0x5),
292 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_sync_barrier, 0x6),
293 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_dvm_msg, 0x7),
294 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_dvm_msg_sync, 0x8),
295 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_stall_tt_full, 0x9),
296 CCI_EVENT_EXT_ATTR_ENTRY(si_r_data_last_hs_snoop, 0xA),
297 CCI_EVENT_EXT_ATTR_ENTRY(si_r_data_stall_rvalids_h_rready_l, 0xB),
298 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_any, 0xC),
299 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_device, 0xD),
300 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_normal_or_nonshareable, 0xE),
301 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_inner_or_outershare_wback_wclean, 0xF),
302 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_write_unique, 0x10),
303 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_write_line_unique, 0x11),
304 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_evict, 0x12),
305 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_stall_tt_full, 0x13),
306 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_stall_slave_id_hazard, 0x14),
307 /* Master events */
308 CCI_EVENT_EXT_ATTR_ENTRY(mi_retry_speculative_fetch, 0x0),
309 CCI_EVENT_EXT_ATTR_ENTRY(mi_stall_cycle_addr_hazard, 0x1),
310 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_master_id_hazard, 0x2),
311 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_hi_prio_rtq_full, 0x3),
312 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_barrier_hazard, 0x4),
313 CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_barrier_hazard, 0x5),
314 CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_wtq_full, 0x6),
315 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_low_prio_rtq_full, 0x7),
316 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_mid_prio_rtq_full, 0x8),
317 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_qvn_vn0, 0x9),
318 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_qvn_vn1, 0xA),
319 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_qvn_vn2, 0xB),
320 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_qvn_vn3, 0xC),
321 CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_qvn_vn0, 0xD),
322 CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_qvn_vn1, 0xE),
323 CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_qvn_vn2, 0xF),
324 CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_qvn_vn3, 0x10),
325 CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_unique_or_line_unique_addr_hazard, 0x11),
326 /* Special event for cycles counter */
327 CCI400_CYCLE_EVENT_EXT_ATTR_ENTRY(cycles, 0xff),
328};
329
330static ssize_t cci400_pmu_cycle_event_show(struct device *dev,
331 struct device_attribute *attr, char *buf)
332{
333 struct dev_ext_attribute *eattr = container_of(attr,
334 struct dev_ext_attribute, attr);
335 return snprintf(buf, PAGE_SIZE, "config=0x%lx\n", (unsigned long)eattr->var);
336}
337
221static int cci400_get_event_idx(struct cci_pmu *cci_pmu, 338static int cci400_get_event_idx(struct cci_pmu *cci_pmu,
222 struct cci_pmu_hw_events *hw, 339 struct cci_pmu_hw_events *hw,
223 unsigned long cci_event) 340 unsigned long cci_event)
@@ -355,6 +472,92 @@ static inline struct cci_pmu_model *probe_cci_model(struct platform_device *pdev
355#define CCI500_GLOBAL_PORT_MIN_EV 0x00 472#define CCI500_GLOBAL_PORT_MIN_EV 0x00
356#define CCI500_GLOBAL_PORT_MAX_EV 0x0f 473#define CCI500_GLOBAL_PORT_MAX_EV 0x0f
357 474
475
476#define CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(_name, _config) \
477 CCI_EXT_ATTR_ENTRY(_name, cci500_pmu_global_event_show, \
478 (unsigned long) _config)
479
480static ssize_t cci500_pmu_global_event_show(struct device *dev,
481 struct device_attribute *attr, char *buf);
482
483static struct dev_ext_attribute cci500_pmu_format_attrs[] = {
484 CCI_FORMAT_EXT_ATTR_ENTRY(event, "config:0-4"),
485 CCI_FORMAT_EXT_ATTR_ENTRY(source, "config:5-8"),
486};
487
488static struct dev_ext_attribute cci500_pmu_event_attrs[] = {
489 /* Slave events */
490 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_arvalid, 0x0),
491 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_dev, 0x1),
492 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_nonshareable, 0x2),
493 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_shareable_non_alloc, 0x3),
494 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_shareable_alloc, 0x4),
495 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_invalidate, 0x5),
496 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_cache_maint, 0x6),
497 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_dvm_msg, 0x7),
498 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_rval, 0x8),
499 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_rlast_snoop, 0x9),
500 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_awalid, 0xA),
501 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_dev, 0xB),
502 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_non_shareable, 0xC),
503 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_share_wb, 0xD),
504 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_share_wlu, 0xE),
505 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_share_wunique, 0xF),
506 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_evict, 0x10),
507 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_wrevict, 0x11),
508 CCI_EVENT_EXT_ATTR_ENTRY(si_w_data_beat, 0x12),
509 CCI_EVENT_EXT_ATTR_ENTRY(si_srq_acvalid, 0x13),
510 CCI_EVENT_EXT_ATTR_ENTRY(si_srq_read, 0x14),
511 CCI_EVENT_EXT_ATTR_ENTRY(si_srq_clean, 0x15),
512 CCI_EVENT_EXT_ATTR_ENTRY(si_srq_data_transfer_low, 0x16),
513 CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_stall_arvalid, 0x17),
514 CCI_EVENT_EXT_ATTR_ENTRY(si_r_data_stall, 0x18),
515 CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_stall, 0x19),
516 CCI_EVENT_EXT_ATTR_ENTRY(si_w_data_stall, 0x1A),
517 CCI_EVENT_EXT_ATTR_ENTRY(si_w_resp_stall, 0x1B),
518 CCI_EVENT_EXT_ATTR_ENTRY(si_srq_stall, 0x1C),
519 CCI_EVENT_EXT_ATTR_ENTRY(si_s_data_stall, 0x1D),
520 CCI_EVENT_EXT_ATTR_ENTRY(si_rq_stall_ot_limit, 0x1E),
521 CCI_EVENT_EXT_ATTR_ENTRY(si_r_stall_arbit, 0x1F),
522
523 /* Master events */
524 CCI_EVENT_EXT_ATTR_ENTRY(mi_r_data_beat_any, 0x0),
525 CCI_EVENT_EXT_ATTR_ENTRY(mi_w_data_beat_any, 0x1),
526 CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall, 0x2),
527 CCI_EVENT_EXT_ATTR_ENTRY(mi_r_data_stall, 0x3),
528 CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall, 0x4),
529 CCI_EVENT_EXT_ATTR_ENTRY(mi_w_data_stall, 0x5),
530 CCI_EVENT_EXT_ATTR_ENTRY(mi_w_resp_stall, 0x6),
531
532 /* Global events */
533 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_0_1, 0x0),
534 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_2_3, 0x1),
535 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_4_5, 0x2),
536 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_6_7, 0x3),
537 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_0_1, 0x4),
538 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_2_3, 0x5),
539 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_4_5, 0x6),
540 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_6_7, 0x7),
541 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_back_invalidation, 0x8),
542 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_stall_alloc_busy, 0x9),
543 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_stall_tt_full, 0xA),
544 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_wrq, 0xB),
545 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_cd_hs, 0xC),
546 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_rq_stall_addr_hazard, 0xD),
547 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snopp_rq_stall_tt_full, 0xE),
548 CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_rq_tzmp1_prot, 0xF),
549};
550
551static ssize_t cci500_pmu_global_event_show(struct device *dev,
552 struct device_attribute *attr, char *buf)
553{
554 struct dev_ext_attribute *eattr = container_of(attr,
555 struct dev_ext_attribute, attr);
556 /* Global events have single fixed source code */
557 return snprintf(buf, PAGE_SIZE, "event=0x%lx,source=0x%x\n",
558 (unsigned long)eattr->var, CCI500_PORT_GLOBAL);
559}
560
358static int cci500_validate_hw_event(struct cci_pmu *cci_pmu, 561static int cci500_validate_hw_event(struct cci_pmu *cci_pmu,
359 unsigned long hw_event) 562 unsigned long hw_event)
360{ 563{
@@ -398,6 +601,24 @@ static int cci500_validate_hw_event(struct cci_pmu *cci_pmu,
398} 601}
399#endif /* CONFIG_ARM_CCI500_PMU */ 602#endif /* CONFIG_ARM_CCI500_PMU */
400 603
604static ssize_t cci_pmu_format_show(struct device *dev,
605 struct device_attribute *attr, char *buf)
606{
607 struct dev_ext_attribute *eattr = container_of(attr,
608 struct dev_ext_attribute, attr);
609 return snprintf(buf, PAGE_SIZE, "%s\n", (char *)eattr->var);
610}
611
612static ssize_t cci_pmu_event_show(struct device *dev,
613 struct device_attribute *attr, char *buf)
614{
615 struct dev_ext_attribute *eattr = container_of(attr,
616 struct dev_ext_attribute, attr);
617 /* source parameter is mandatory for normal PMU events */
618 return snprintf(buf, PAGE_SIZE, "source=?,event=0x%lx\n",
619 (unsigned long)eattr->var);
620}
621
401static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx) 622static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
402{ 623{
403 return 0 <= idx && idx <= CCI_PMU_CNTR_LAST(cci_pmu); 624 return 0 <= idx && idx <= CCI_PMU_CNTR_LAST(cci_pmu);
@@ -980,17 +1201,78 @@ static struct attribute_group pmu_attr_group = {
980 .attrs = pmu_attrs, 1201 .attrs = pmu_attrs,
981}; 1202};
982 1203
1204static struct attribute_group pmu_format_attr_group = {
1205 .name = "format",
1206 .attrs = NULL, /* Filled in cci_pmu_init_attrs */
1207};
1208
1209static struct attribute_group pmu_event_attr_group = {
1210 .name = "events",
1211 .attrs = NULL, /* Filled in cci_pmu_init_attrs */
1212};
1213
983static const struct attribute_group *pmu_attr_groups[] = { 1214static const struct attribute_group *pmu_attr_groups[] = {
984 &pmu_attr_group, 1215 &pmu_attr_group,
1216 &pmu_format_attr_group,
1217 &pmu_event_attr_group,
985 NULL 1218 NULL
986}; 1219};
987 1220
1221static struct attribute **alloc_attrs(struct platform_device *pdev,
1222 int n, struct dev_ext_attribute *source)
1223{
1224 int i;
1225 struct attribute **attrs;
1226
1227 /* Alloc n + 1 (for terminating NULL) */
1228 attrs = devm_kcalloc(&pdev->dev, n + 1, sizeof(struct attribute *),
1229 GFP_KERNEL);
1230 if (!attrs)
1231 return attrs;
1232 for(i = 0; i < n; i++)
1233 attrs[i] = &source[i].attr.attr;
1234 return attrs;
1235}
1236
1237static int cci_pmu_init_attrs(struct cci_pmu *cci_pmu, struct platform_device *pdev)
1238{
1239 const struct cci_pmu_model *model = cci_pmu->model;
1240 struct attribute **attrs;
1241
1242 /*
1243 * All allocations below are managed, hence doesn't need to be
1244 * free'd explicitly in case of an error.
1245 */
1246
1247 if (model->nevent_attrs) {
1248 attrs = alloc_attrs(pdev, model->nevent_attrs,
1249 model->event_attrs);
1250 if (!attrs)
1251 return -ENOMEM;
1252 pmu_event_attr_group.attrs = attrs;
1253 }
1254 if (model->nformat_attrs) {
1255 attrs = alloc_attrs(pdev, model->nformat_attrs,
1256 model->format_attrs);
1257 if (!attrs)
1258 return -ENOMEM;
1259 pmu_format_attr_group.attrs = attrs;
1260 }
1261 pmu_cpumask_attr.var = cci_pmu;
1262
1263 return 0;
1264}
1265
988static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev) 1266static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
989{ 1267{
990 char *name = cci_pmu->model->name; 1268 char *name = cci_pmu->model->name;
991 u32 num_cntrs; 1269 u32 num_cntrs;
1270 int rc;
1271
1272 rc = cci_pmu_init_attrs(cci_pmu, pdev);
1273 if (rc)
1274 return rc;
992 1275
993 pmu_cpumask_attr.var = cci_pmu;
994 cci_pmu->pmu = (struct pmu) { 1276 cci_pmu->pmu = (struct pmu) {
995 .name = cci_pmu->model->name, 1277 .name = cci_pmu->model->name,
996 .task_ctx_nr = perf_invalid_context, 1278 .task_ctx_nr = perf_invalid_context,
@@ -1053,6 +1335,10 @@ static struct cci_pmu_model cci_pmu_models[] = {
1053 .fixed_hw_cntrs = 1, /* Cycle counter */ 1335 .fixed_hw_cntrs = 1, /* Cycle counter */
1054 .num_hw_cntrs = 4, 1336 .num_hw_cntrs = 4,
1055 .cntr_size = SZ_4K, 1337 .cntr_size = SZ_4K,
1338 .format_attrs = cci400_pmu_format_attrs,
1339 .nformat_attrs = ARRAY_SIZE(cci400_pmu_format_attrs),
1340 .event_attrs = cci400_r0_pmu_event_attrs,
1341 .nevent_attrs = ARRAY_SIZE(cci400_r0_pmu_event_attrs),
1056 .event_ranges = { 1342 .event_ranges = {
1057 [CCI_IF_SLAVE] = { 1343 [CCI_IF_SLAVE] = {
1058 CCI400_R0_SLAVE_PORT_MIN_EV, 1344 CCI400_R0_SLAVE_PORT_MIN_EV,
@@ -1071,6 +1357,10 @@ static struct cci_pmu_model cci_pmu_models[] = {
1071 .fixed_hw_cntrs = 1, /* Cycle counter */ 1357 .fixed_hw_cntrs = 1, /* Cycle counter */
1072 .num_hw_cntrs = 4, 1358 .num_hw_cntrs = 4,
1073 .cntr_size = SZ_4K, 1359 .cntr_size = SZ_4K,
1360 .format_attrs = cci400_pmu_format_attrs,
1361 .nformat_attrs = ARRAY_SIZE(cci400_pmu_format_attrs),
1362 .event_attrs = cci400_r1_pmu_event_attrs,
1363 .nevent_attrs = ARRAY_SIZE(cci400_r1_pmu_event_attrs),
1074 .event_ranges = { 1364 .event_ranges = {
1075 [CCI_IF_SLAVE] = { 1365 [CCI_IF_SLAVE] = {
1076 CCI400_R1_SLAVE_PORT_MIN_EV, 1366 CCI400_R1_SLAVE_PORT_MIN_EV,
@@ -1091,6 +1381,10 @@ static struct cci_pmu_model cci_pmu_models[] = {
1091 .fixed_hw_cntrs = 0, 1381 .fixed_hw_cntrs = 0,
1092 .num_hw_cntrs = 8, 1382 .num_hw_cntrs = 8,
1093 .cntr_size = SZ_64K, 1383 .cntr_size = SZ_64K,
1384 .format_attrs = cci500_pmu_format_attrs,
1385 .nformat_attrs = ARRAY_SIZE(cci500_pmu_format_attrs),
1386 .event_attrs = cci500_pmu_event_attrs,
1387 .nevent_attrs = ARRAY_SIZE(cci500_pmu_event_attrs),
1094 .event_ranges = { 1388 .event_ranges = {
1095 [CCI_IF_SLAVE] = { 1389 [CCI_IF_SLAVE] = {
1096 CCI500_SLAVE_PORT_MIN_EV, 1390 CCI500_SLAVE_PORT_MIN_EV,