aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bus/arm-ccn.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bus/arm-ccn.c')
-rw-r--r--drivers/bus/arm-ccn.c270
1 files changed, 214 insertions, 56 deletions
diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c
index aaa0f2a87118..7d9879e166cf 100644
--- a/drivers/bus/arm-ccn.c
+++ b/drivers/bus/arm-ccn.c
@@ -166,13 +166,17 @@ struct arm_ccn_dt {
166 166
167 struct hrtimer hrtimer; 167 struct hrtimer hrtimer;
168 168
169 cpumask_t cpu;
170 struct notifier_block cpu_nb;
171
169 struct pmu pmu; 172 struct pmu pmu;
170}; 173};
171 174
172struct arm_ccn { 175struct arm_ccn {
173 struct device *dev; 176 struct device *dev;
174 void __iomem *base; 177 void __iomem *base;
175 unsigned irq_used:1; 178 unsigned int irq;
179
176 unsigned sbas_present:1; 180 unsigned sbas_present:1;
177 unsigned sbsx_present:1; 181 unsigned sbsx_present:1;
178 182
@@ -212,7 +216,7 @@ static int arm_ccn_node_to_xp_port(int node)
212 216
213static void arm_ccn_pmu_config_set(u64 *config, u32 node_xp, u32 type, u32 port) 217static void arm_ccn_pmu_config_set(u64 *config, u32 node_xp, u32 type, u32 port)
214{ 218{
215 *config &= ~((0xff << 0) | (0xff << 8) | (0xff << 24)); 219 *config &= ~((0xff << 0) | (0xff << 8) | (0x3 << 24));
216 *config |= (node_xp << 0) | (type << 8) | (port << 24); 220 *config |= (node_xp << 0) | (type << 8) | (port << 24);
217} 221}
218 222
@@ -336,6 +340,23 @@ static ssize_t arm_ccn_pmu_event_show(struct device *dev,
336 if (event->mask) 340 if (event->mask)
337 res += snprintf(buf + res, PAGE_SIZE - res, ",mask=0x%x", 341 res += snprintf(buf + res, PAGE_SIZE - res, ",mask=0x%x",
338 event->mask); 342 event->mask);
343
344 /* Arguments required by an event */
345 switch (event->type) {
346 case CCN_TYPE_CYCLES:
347 break;
348 case CCN_TYPE_XP:
349 res += snprintf(buf + res, PAGE_SIZE - res,
350 ",xp=?,port=?,vc=?,dir=?");
351 if (event->event == CCN_EVENT_WATCHPOINT)
352 res += snprintf(buf + res, PAGE_SIZE - res,
353 ",cmp_l=?,cmp_h=?,mask=?");
354 break;
355 default:
356 res += snprintf(buf + res, PAGE_SIZE - res, ",node=?");
357 break;
358 }
359
339 res += snprintf(buf + res, PAGE_SIZE - res, "\n"); 360 res += snprintf(buf + res, PAGE_SIZE - res, "\n");
340 361
341 return res; 362 return res;
@@ -521,6 +542,25 @@ static struct attribute_group arm_ccn_pmu_cmp_mask_attr_group = {
521 .attrs = arm_ccn_pmu_cmp_mask_attrs, 542 .attrs = arm_ccn_pmu_cmp_mask_attrs,
522}; 543};
523 544
545static ssize_t arm_ccn_pmu_cpumask_show(struct device *dev,
546 struct device_attribute *attr, char *buf)
547{
548 struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
549
550 return cpumap_print_to_pagebuf(true, buf, &ccn->dt.cpu);
551}
552
553static struct device_attribute arm_ccn_pmu_cpumask_attr =
554 __ATTR(cpumask, S_IRUGO, arm_ccn_pmu_cpumask_show, NULL);
555
556static struct attribute *arm_ccn_pmu_cpumask_attrs[] = {
557 &arm_ccn_pmu_cpumask_attr.attr,
558 NULL,
559};
560
561static struct attribute_group arm_ccn_pmu_cpumask_attr_group = {
562 .attrs = arm_ccn_pmu_cpumask_attrs,
563};
524 564
525/* 565/*
526 * Default poll period is 10ms, which is way over the top anyway, 566 * Default poll period is 10ms, which is way over the top anyway,
@@ -542,6 +582,7 @@ static const struct attribute_group *arm_ccn_pmu_attr_groups[] = {
542 &arm_ccn_pmu_events_attr_group, 582 &arm_ccn_pmu_events_attr_group,
543 &arm_ccn_pmu_format_attr_group, 583 &arm_ccn_pmu_format_attr_group,
544 &arm_ccn_pmu_cmp_mask_attr_group, 584 &arm_ccn_pmu_cmp_mask_attr_group,
585 &arm_ccn_pmu_cpumask_attr_group,
545 NULL 586 NULL
546}; 587};
547 588
@@ -587,7 +628,65 @@ static int arm_ccn_pmu_type_eq(u32 a, u32 b)
587 return 0; 628 return 0;
588} 629}
589 630
590static void arm_ccn_pmu_event_destroy(struct perf_event *event) 631static int arm_ccn_pmu_event_alloc(struct perf_event *event)
632{
633 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
634 struct hw_perf_event *hw = &event->hw;
635 u32 node_xp, type, event_id;
636 struct arm_ccn_component *source;
637 int bit;
638
639 node_xp = CCN_CONFIG_NODE(event->attr.config);
640 type = CCN_CONFIG_TYPE(event->attr.config);
641 event_id = CCN_CONFIG_EVENT(event->attr.config);
642
643 /* Allocate the cycle counter */
644 if (type == CCN_TYPE_CYCLES) {
645 if (test_and_set_bit(CCN_IDX_PMU_CYCLE_COUNTER,
646 ccn->dt.pmu_counters_mask))
647 return -EAGAIN;
648
649 hw->idx = CCN_IDX_PMU_CYCLE_COUNTER;
650 ccn->dt.pmu_counters[CCN_IDX_PMU_CYCLE_COUNTER].event = event;
651
652 return 0;
653 }
654
655 /* Allocate an event counter */
656 hw->idx = arm_ccn_pmu_alloc_bit(ccn->dt.pmu_counters_mask,
657 CCN_NUM_PMU_EVENT_COUNTERS);
658 if (hw->idx < 0) {
659 dev_dbg(ccn->dev, "No more counters available!\n");
660 return -EAGAIN;
661 }
662
663 if (type == CCN_TYPE_XP)
664 source = &ccn->xp[node_xp];
665 else
666 source = &ccn->node[node_xp];
667 ccn->dt.pmu_counters[hw->idx].source = source;
668
669 /* Allocate an event source or a watchpoint */
670 if (type == CCN_TYPE_XP && event_id == CCN_EVENT_WATCHPOINT)
671 bit = arm_ccn_pmu_alloc_bit(source->xp.dt_cmp_mask,
672 CCN_NUM_XP_WATCHPOINTS);
673 else
674 bit = arm_ccn_pmu_alloc_bit(source->pmu_events_mask,
675 CCN_NUM_PMU_EVENTS);
676 if (bit < 0) {
677 dev_dbg(ccn->dev, "No more event sources/watchpoints on node/XP %d!\n",
678 node_xp);
679 clear_bit(hw->idx, ccn->dt.pmu_counters_mask);
680 return -EAGAIN;
681 }
682 hw->config_base = bit;
683
684 ccn->dt.pmu_counters[hw->idx].event = event;
685
686 return 0;
687}
688
689static void arm_ccn_pmu_event_release(struct perf_event *event)
591{ 690{
592 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); 691 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
593 struct hw_perf_event *hw = &event->hw; 692 struct hw_perf_event *hw = &event->hw;
@@ -616,15 +715,14 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
616 struct arm_ccn *ccn; 715 struct arm_ccn *ccn;
617 struct hw_perf_event *hw = &event->hw; 716 struct hw_perf_event *hw = &event->hw;
618 u32 node_xp, type, event_id; 717 u32 node_xp, type, event_id;
619 int valid, bit; 718 int valid;
620 struct arm_ccn_component *source;
621 int i; 719 int i;
720 struct perf_event *sibling;
622 721
623 if (event->attr.type != event->pmu->type) 722 if (event->attr.type != event->pmu->type)
624 return -ENOENT; 723 return -ENOENT;
625 724
626 ccn = pmu_to_arm_ccn(event->pmu); 725 ccn = pmu_to_arm_ccn(event->pmu);
627 event->destroy = arm_ccn_pmu_event_destroy;
628 726
629 if (hw->sample_period) { 727 if (hw->sample_period) {
630 dev_warn(ccn->dev, "Sampling not supported!\n"); 728 dev_warn(ccn->dev, "Sampling not supported!\n");
@@ -642,6 +740,16 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
642 dev_warn(ccn->dev, "Can't provide per-task data!\n"); 740 dev_warn(ccn->dev, "Can't provide per-task data!\n");
643 return -EOPNOTSUPP; 741 return -EOPNOTSUPP;
644 } 742 }
743 /*
744 * Many perf core operations (eg. events rotation) operate on a
745 * single CPU context. This is obvious for CPU PMUs, where one
746 * expects the same sets of events being observed on all CPUs,
747 * but can lead to issues for off-core PMUs, like CCN, where each
748 * event could be theoretically assigned to a different CPU. To
749 * mitigate this, we enforce CPU assignment to one, selected
750 * processor (the one described in the "cpumask" attribute).
751 */
752 event->cpu = cpumask_first(&ccn->dt.cpu);
645 753
646 node_xp = CCN_CONFIG_NODE(event->attr.config); 754 node_xp = CCN_CONFIG_NODE(event->attr.config);
647 type = CCN_CONFIG_TYPE(event->attr.config); 755 type = CCN_CONFIG_TYPE(event->attr.config);
@@ -711,48 +819,20 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
711 node_xp, type, port); 819 node_xp, type, port);
712 } 820 }
713 821
714 /* Allocate the cycle counter */ 822 /*
715 if (type == CCN_TYPE_CYCLES) { 823 * We must NOT create groups containing mixed PMUs, although software
716 if (test_and_set_bit(CCN_IDX_PMU_CYCLE_COUNTER, 824 * events are acceptable (for example to create a CCN group
717 ccn->dt.pmu_counters_mask)) 825 * periodically read when a hrtimer aka cpu-clock leader triggers).
718 return -EAGAIN; 826 */
719 827 if (event->group_leader->pmu != event->pmu &&
720 hw->idx = CCN_IDX_PMU_CYCLE_COUNTER; 828 !is_software_event(event->group_leader))
721 ccn->dt.pmu_counters[CCN_IDX_PMU_CYCLE_COUNTER].event = event; 829 return -EINVAL;
722
723 return 0;
724 }
725
726 /* Allocate an event counter */
727 hw->idx = arm_ccn_pmu_alloc_bit(ccn->dt.pmu_counters_mask,
728 CCN_NUM_PMU_EVENT_COUNTERS);
729 if (hw->idx < 0) {
730 dev_warn(ccn->dev, "No more counters available!\n");
731 return -EAGAIN;
732 }
733
734 if (type == CCN_TYPE_XP)
735 source = &ccn->xp[node_xp];
736 else
737 source = &ccn->node[node_xp];
738 ccn->dt.pmu_counters[hw->idx].source = source;
739
740 /* Allocate an event source or a watchpoint */
741 if (type == CCN_TYPE_XP && event_id == CCN_EVENT_WATCHPOINT)
742 bit = arm_ccn_pmu_alloc_bit(source->xp.dt_cmp_mask,
743 CCN_NUM_XP_WATCHPOINTS);
744 else
745 bit = arm_ccn_pmu_alloc_bit(source->pmu_events_mask,
746 CCN_NUM_PMU_EVENTS);
747 if (bit < 0) {
748 dev_warn(ccn->dev, "No more event sources/watchpoints on node/XP %d!\n",
749 node_xp);
750 clear_bit(hw->idx, ccn->dt.pmu_counters_mask);
751 return -EAGAIN;
752 }
753 hw->config_base = bit;
754 830
755 ccn->dt.pmu_counters[hw->idx].event = event; 831 list_for_each_entry(sibling, &event->group_leader->sibling_list,
832 group_entry)
833 if (sibling->pmu != event->pmu &&
834 !is_software_event(sibling))
835 return -EINVAL;
756 836
757 return 0; 837 return 0;
758} 838}
@@ -835,9 +915,14 @@ static void arm_ccn_pmu_event_start(struct perf_event *event, int flags)
835 arm_ccn_pmu_read_counter(ccn, hw->idx)); 915 arm_ccn_pmu_read_counter(ccn, hw->idx));
836 hw->state = 0; 916 hw->state = 0;
837 917
838 if (!ccn->irq_used) 918 /*
919 * Pin the timer, so that the overflows are handled by the chosen
920 * event->cpu (this is the same one as presented in "cpumask"
921 * attribute).
922 */
923 if (!ccn->irq)
839 hrtimer_start(&ccn->dt.hrtimer, arm_ccn_pmu_timer_period(), 924 hrtimer_start(&ccn->dt.hrtimer, arm_ccn_pmu_timer_period(),
840 HRTIMER_MODE_REL); 925 HRTIMER_MODE_REL_PINNED);
841 926
842 /* Set the DT bus input, engaging the counter */ 927 /* Set the DT bus input, engaging the counter */
843 arm_ccn_pmu_xp_dt_config(event, 1); 928 arm_ccn_pmu_xp_dt_config(event, 1);
@@ -852,7 +937,7 @@ static void arm_ccn_pmu_event_stop(struct perf_event *event, int flags)
852 /* Disable counting, setting the DT bus to pass-through mode */ 937 /* Disable counting, setting the DT bus to pass-through mode */
853 arm_ccn_pmu_xp_dt_config(event, 0); 938 arm_ccn_pmu_xp_dt_config(event, 0);
854 939
855 if (!ccn->irq_used) 940 if (!ccn->irq)
856 hrtimer_cancel(&ccn->dt.hrtimer); 941 hrtimer_cancel(&ccn->dt.hrtimer);
857 942
858 /* Let the DT bus drain */ 943 /* Let the DT bus drain */
@@ -1014,8 +1099,13 @@ static void arm_ccn_pmu_event_config(struct perf_event *event)
1014 1099
1015static int arm_ccn_pmu_event_add(struct perf_event *event, int flags) 1100static int arm_ccn_pmu_event_add(struct perf_event *event, int flags)
1016{ 1101{
1102 int err;
1017 struct hw_perf_event *hw = &event->hw; 1103 struct hw_perf_event *hw = &event->hw;
1018 1104
1105 err = arm_ccn_pmu_event_alloc(event);
1106 if (err)
1107 return err;
1108
1019 arm_ccn_pmu_event_config(event); 1109 arm_ccn_pmu_event_config(event);
1020 1110
1021 hw->state = PERF_HES_STOPPED; 1111 hw->state = PERF_HES_STOPPED;
@@ -1029,6 +1119,8 @@ static int arm_ccn_pmu_event_add(struct perf_event *event, int flags)
1029static void arm_ccn_pmu_event_del(struct perf_event *event, int flags) 1119static void arm_ccn_pmu_event_del(struct perf_event *event, int flags)
1030{ 1120{
1031 arm_ccn_pmu_event_stop(event, PERF_EF_UPDATE); 1121 arm_ccn_pmu_event_stop(event, PERF_EF_UPDATE);
1122
1123 arm_ccn_pmu_event_release(event);
1032} 1124}
1033 1125
1034static void arm_ccn_pmu_event_read(struct perf_event *event) 1126static void arm_ccn_pmu_event_read(struct perf_event *event)
@@ -1079,12 +1171,39 @@ static enum hrtimer_restart arm_ccn_pmu_timer_handler(struct hrtimer *hrtimer)
1079} 1171}
1080 1172
1081 1173
1174static int arm_ccn_pmu_cpu_notifier(struct notifier_block *nb,
1175 unsigned long action, void *hcpu)
1176{
1177 struct arm_ccn_dt *dt = container_of(nb, struct arm_ccn_dt, cpu_nb);
1178 struct arm_ccn *ccn = container_of(dt, struct arm_ccn, dt);
1179 unsigned int cpu = (long)hcpu; /* for (long) see kernel/cpu.c */
1180 unsigned int target;
1181
1182 switch (action & ~CPU_TASKS_FROZEN) {
1183 case CPU_DOWN_PREPARE:
1184 if (!cpumask_test_and_clear_cpu(cpu, &dt->cpu))
1185 break;
1186 target = cpumask_any_but(cpu_online_mask, cpu);
1187 if (target < 0)
1188 break;
1189 perf_pmu_migrate_context(&dt->pmu, cpu, target);
1190 cpumask_set_cpu(target, &dt->cpu);
1191 WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
1192 default:
1193 break;
1194 }
1195
1196 return NOTIFY_OK;
1197}
1198
1199
1082static DEFINE_IDA(arm_ccn_pmu_ida); 1200static DEFINE_IDA(arm_ccn_pmu_ida);
1083 1201
1084static int arm_ccn_pmu_init(struct arm_ccn *ccn) 1202static int arm_ccn_pmu_init(struct arm_ccn *ccn)
1085{ 1203{
1086 int i; 1204 int i;
1087 char *name; 1205 char *name;
1206 int err;
1088 1207
1089 /* Initialize DT subsystem */ 1208 /* Initialize DT subsystem */
1090 ccn->dt.base = ccn->base + CCN_REGION_SIZE; 1209 ccn->dt.base = ccn->base + CCN_REGION_SIZE;
@@ -1136,20 +1255,58 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn)
1136 }; 1255 };
1137 1256
1138 /* No overflow interrupt? Have to use a timer instead. */ 1257 /* No overflow interrupt? Have to use a timer instead. */
1139 if (!ccn->irq_used) { 1258 if (!ccn->irq) {
1140 dev_info(ccn->dev, "No access to interrupts, using timer.\n"); 1259 dev_info(ccn->dev, "No access to interrupts, using timer.\n");
1141 hrtimer_init(&ccn->dt.hrtimer, CLOCK_MONOTONIC, 1260 hrtimer_init(&ccn->dt.hrtimer, CLOCK_MONOTONIC,
1142 HRTIMER_MODE_REL); 1261 HRTIMER_MODE_REL);
1143 ccn->dt.hrtimer.function = arm_ccn_pmu_timer_handler; 1262 ccn->dt.hrtimer.function = arm_ccn_pmu_timer_handler;
1144 } 1263 }
1145 1264
1146 return perf_pmu_register(&ccn->dt.pmu, name, -1); 1265 /* Pick one CPU which we will use to collect data from CCN... */
1266 cpumask_set_cpu(smp_processor_id(), &ccn->dt.cpu);
1267
1268 /*
1269 * ... and change the selection when it goes offline. Priority is
1270 * picked to have a chance to migrate events before perf is notified.
1271 */
1272 ccn->dt.cpu_nb.notifier_call = arm_ccn_pmu_cpu_notifier;
1273 ccn->dt.cpu_nb.priority = CPU_PRI_PERF + 1,
1274 err = register_cpu_notifier(&ccn->dt.cpu_nb);
1275 if (err)
1276 goto error_cpu_notifier;
1277
1278 /* Also make sure that the overflow interrupt is handled by this CPU */
1279 if (ccn->irq) {
1280 err = irq_set_affinity(ccn->irq, &ccn->dt.cpu);
1281 if (err) {
1282 dev_err(ccn->dev, "Failed to set interrupt affinity!\n");
1283 goto error_set_affinity;
1284 }
1285 }
1286
1287 err = perf_pmu_register(&ccn->dt.pmu, name, -1);
1288 if (err)
1289 goto error_pmu_register;
1290
1291 return 0;
1292
1293error_pmu_register:
1294error_set_affinity:
1295 unregister_cpu_notifier(&ccn->dt.cpu_nb);
1296error_cpu_notifier:
1297 ida_simple_remove(&arm_ccn_pmu_ida, ccn->dt.id);
1298 for (i = 0; i < ccn->num_xps; i++)
1299 writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
1300 writel(0, ccn->dt.base + CCN_DT_PMCR);
1301 return err;
1147} 1302}
1148 1303
1149static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn) 1304static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn)
1150{ 1305{
1151 int i; 1306 int i;
1152 1307
1308 irq_set_affinity(ccn->irq, cpu_possible_mask);
1309 unregister_cpu_notifier(&ccn->dt.cpu_nb);
1153 for (i = 0; i < ccn->num_xps; i++) 1310 for (i = 0; i < ccn->num_xps; i++)
1154 writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL); 1311 writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
1155 writel(0, ccn->dt.base + CCN_DT_PMCR); 1312 writel(0, ccn->dt.base + CCN_DT_PMCR);
@@ -1285,6 +1442,7 @@ static int arm_ccn_probe(struct platform_device *pdev)
1285{ 1442{
1286 struct arm_ccn *ccn; 1443 struct arm_ccn *ccn;
1287 struct resource *res; 1444 struct resource *res;
1445 unsigned int irq;
1288 int err; 1446 int err;
1289 1447
1290 ccn = devm_kzalloc(&pdev->dev, sizeof(*ccn), GFP_KERNEL); 1448 ccn = devm_kzalloc(&pdev->dev, sizeof(*ccn), GFP_KERNEL);
@@ -1309,6 +1467,7 @@ static int arm_ccn_probe(struct platform_device *pdev)
1309 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1467 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1310 if (!res) 1468 if (!res)
1311 return -EINVAL; 1469 return -EINVAL;
1470 irq = res->start;
1312 1471
1313 /* Check if we can use the interrupt */ 1472 /* Check if we can use the interrupt */
1314 writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLE, 1473 writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLE,
@@ -1318,13 +1477,12 @@ static int arm_ccn_probe(struct platform_device *pdev)
1318 /* Can set 'disable' bits, so can acknowledge interrupts */ 1477 /* Can set 'disable' bits, so can acknowledge interrupts */
1319 writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__ENABLE, 1478 writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__ENABLE,
1320 ccn->base + CCN_MN_ERRINT_STATUS); 1479 ccn->base + CCN_MN_ERRINT_STATUS);
1321 err = devm_request_irq(ccn->dev, res->start, 1480 err = devm_request_irq(ccn->dev, irq, arm_ccn_irq_handler, 0,
1322 arm_ccn_irq_handler, 0, dev_name(ccn->dev), 1481 dev_name(ccn->dev), ccn);
1323 ccn);
1324 if (err) 1482 if (err)
1325 return err; 1483 return err;
1326 1484
1327 ccn->irq_used = 1; 1485 ccn->irq = irq;
1328 } 1486 }
1329 1487
1330 1488