aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuzuki K. Poulose <suzuki.poulose@arm.com>2015-05-26 05:53:12 -0400
committerArnd Bergmann <arnd@arndb.de>2015-05-29 10:43:49 -0400
commitab5b316d4b6d2f944ffcb4a742443207eda51cfb (patch)
tree56a32de739f28fc06c2fb5150aadbe0588afad95
parenta1a076d767f99209fe3ebd1fe394028620914ebe (diff)
arm-cci: Abstract out the PMU counter details
Adds the PMU model specific counters to the PMU model abstraction to make it easier to add a new PMU. The patch cleans up the naming convention used all over the code. e.g, CCI_PMU_MAX_HW_EVENTS => maximum number of events that can be counted at any time, which is in fact the maximum number of counters available. Change all such namings to use 'counters' instead of events. This patch also abstracts the following: 1) Size of a PMU event counter area. 2) Maximum number of programmable counters supported by the PMU model 3) Number of counters which counts fixed events (e.g, cycle counter on CCI-400). Also changes some of the static allocation of the data structures to dynamic, to accommodate the number of events supported by a PMU. Gets rid ofthe CCI_PMU_* defines for the model. All such data should be accessed via the model abstraction. Limits the number of counters to the maximum supported by the 'model'. Cc: Punit Agrawal <punit.agrawal@arm.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Will Deacon <will.deacon@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.c123
1 files changed, 93 insertions, 30 deletions
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 886a971aaddb..602bf64fc690 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -77,15 +77,17 @@ static const struct of_device_id arm_cci_matches[] = {
77 77
78#define CCI_PMU_OVRFLW_FLAG 1 78#define CCI_PMU_OVRFLW_FLAG 1
79 79
80#define CCI_PMU_CNTR_BASE(idx) ((idx) * SZ_4K) 80#define CCI_PMU_CNTR_SIZE(model) ((model)->cntr_size)
81 81#define CCI_PMU_CNTR_BASE(model, idx) ((idx) * CCI_PMU_CNTR_SIZE(model))
82#define CCI_PMU_CNTR_MASK ((1ULL << 32) -1) 82#define CCI_PMU_CNTR_MASK ((1ULL << 32) -1)
83#define CCI_PMU_CNTR_LAST(cci_pmu) (cci_pmu->num_cntrs - 1)
83 84
84#define CCI_PMU_EVENT_MASK 0xffUL 85#define CCI_PMU_EVENT_MASK 0xffUL
85#define CCI_PMU_EVENT_SOURCE(event) ((event >> 5) & 0x7) 86#define CCI_PMU_EVENT_SOURCE(event) ((event >> 5) & 0x7)
86#define CCI_PMU_EVENT_CODE(event) (event & 0x1f) 87#define CCI_PMU_EVENT_CODE(event) (event & 0x1f)
87 88
88#define CCI_PMU_MAX_HW_EVENTS 5 /* CCI PMU has 4 counters + 1 cycle counter */ 89#define CCI_PMU_MAX_HW_CNTRS(model) \
90 ((model)->num_hw_cntrs + (model)->fixed_hw_cntrs)
89 91
90/* Types of interfaces that can generate events */ 92/* Types of interfaces that can generate events */
91enum { 93enum {
@@ -100,13 +102,22 @@ struct event_range {
100}; 102};
101 103
102struct cci_pmu_hw_events { 104struct cci_pmu_hw_events {
103 struct perf_event *events[CCI_PMU_MAX_HW_EVENTS]; 105 struct perf_event **events;
104 unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)]; 106 unsigned long *used_mask;
105 raw_spinlock_t pmu_lock; 107 raw_spinlock_t pmu_lock;
106}; 108};
107 109
110/*
111 * struct cci_pmu_model:
112 * @fixed_hw_cntrs - Number of fixed event counters
113 * @num_hw_cntrs - Maximum number of programmable event counters
114 * @cntr_size - Size of an event counter mapping
115 */
108struct cci_pmu_model { 116struct cci_pmu_model {
109 char *name; 117 char *name;
118 u32 fixed_hw_cntrs;
119 u32 num_hw_cntrs;
120 u32 cntr_size;
110 struct event_range event_ranges[CCI_IF_MAX]; 121 struct event_range event_ranges[CCI_IF_MAX];
111}; 122};
112 123
@@ -116,12 +127,12 @@ struct cci_pmu {
116 void __iomem *base; 127 void __iomem *base;
117 struct pmu pmu; 128 struct pmu pmu;
118 int nr_irqs; 129 int nr_irqs;
119 int irqs[CCI_PMU_MAX_HW_EVENTS]; 130 int *irqs;
120 unsigned long active_irqs; 131 unsigned long active_irqs;
121 const struct cci_pmu_model *model; 132 const struct cci_pmu_model *model;
122 struct cci_pmu_hw_events hw_events; 133 struct cci_pmu_hw_events hw_events;
123 struct platform_device *plat_device; 134 struct platform_device *plat_device;
124 int num_events; 135 int num_cntrs;
125 atomic_t active_events; 136 atomic_t active_events;
126 struct mutex reserve_mutex; 137 struct mutex reserve_mutex;
127 struct notifier_block cpu_nb; 138 struct notifier_block cpu_nb;
@@ -155,7 +166,6 @@ enum cci400_perf_events {
155 166
156#define CCI_PMU_CYCLE_CNTR_IDX 0 167#define CCI_PMU_CYCLE_CNTR_IDX 0
157#define CCI_PMU_CNTR0_IDX 1 168#define CCI_PMU_CNTR0_IDX 1
158#define CCI_PMU_CNTR_LAST(cci_pmu) (CCI_PMU_CYCLE_CNTR_IDX + cci_pmu->num_events - 1)
159 169
160/* 170/*
161 * CCI PMU event id is an 8-bit value made of two parts - bits 7:5 for one of 8 171 * CCI PMU event id is an 8-bit value made of two parts - bits 7:5 for one of 8
@@ -235,20 +245,20 @@ static const struct cci_pmu_model *probe_cci_model(struct platform_device *pdev)
235 245
236static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx) 246static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
237{ 247{
238 return CCI_PMU_CYCLE_CNTR_IDX <= idx && 248 return 0 <= idx && idx <= CCI_PMU_CNTR_LAST(cci_pmu);
239 idx <= CCI_PMU_CNTR_LAST(cci_pmu);
240} 249}
241 250
242static u32 pmu_read_register(struct cci_pmu *cci_pmu, int idx, unsigned int offset) 251static u32 pmu_read_register(struct cci_pmu *cci_pmu, int idx, unsigned int offset)
243{ 252{
244 return readl_relaxed(cci_pmu->base + CCI_PMU_CNTR_BASE(idx) + offset); 253 return readl_relaxed(cci_pmu->base +
254 CCI_PMU_CNTR_BASE(cci_pmu->model, idx) + offset);
245} 255}
246 256
247static void pmu_write_register(struct cci_pmu *cci_pmu, u32 value, 257static void pmu_write_register(struct cci_pmu *cci_pmu, u32 value,
248 int idx, unsigned int offset) 258 int idx, unsigned int offset)
249{ 259{
250 return writel_relaxed(value, cci_pmu->base + 260 return writel_relaxed(value, cci_pmu->base +
251 CCI_PMU_CNTR_BASE(idx) + offset); 261 CCI_PMU_CNTR_BASE(cci_pmu->model, idx) + offset);
252} 262}
253 263
254static void pmu_disable_counter(struct cci_pmu *cci_pmu, int idx) 264static void pmu_disable_counter(struct cci_pmu *cci_pmu, int idx)
@@ -266,13 +276,14 @@ static void pmu_set_event(struct cci_pmu *cci_pmu, int idx, unsigned long event)
266 pmu_write_register(cci_pmu, event, idx, CCI_PMU_EVT_SEL); 276 pmu_write_register(cci_pmu, event, idx, CCI_PMU_EVT_SEL);
267} 277}
268 278
279/*
280 * Returns the number of programmable counters actually implemented
281 * by the cci
282 */
269static u32 pmu_get_max_counters(void) 283static u32 pmu_get_max_counters(void)
270{ 284{
271 u32 n_cnts = (readl_relaxed(cci_ctrl_base + CCI_PMCR) & 285 return (readl_relaxed(cci_ctrl_base + CCI_PMCR) &
272 CCI_PMCR_NCNT_MASK) >> CCI_PMCR_NCNT_SHIFT; 286 CCI_PMCR_NCNT_MASK) >> CCI_PMCR_NCNT_SHIFT;
273
274 /* add 1 for cycle counter */
275 return n_cnts + 1;
276} 287}
277 288
278static int pmu_get_event_idx(struct cci_pmu_hw_events *hw, struct perf_event *event) 289static int pmu_get_event_idx(struct cci_pmu_hw_events *hw, struct perf_event *event)
@@ -496,7 +507,7 @@ static void cci_pmu_enable(struct pmu *pmu)
496{ 507{
497 struct cci_pmu *cci_pmu = to_cci_pmu(pmu); 508 struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
498 struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events; 509 struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
499 int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_events); 510 int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_cntrs);
500 unsigned long flags; 511 unsigned long flags;
501 u32 val; 512 u32 val;
502 513
@@ -659,13 +670,16 @@ static int
659validate_group(struct perf_event *event) 670validate_group(struct perf_event *event)
660{ 671{
661 struct perf_event *sibling, *leader = event->group_leader; 672 struct perf_event *sibling, *leader = event->group_leader;
673 struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
674 unsigned long mask[BITS_TO_LONGS(cci_pmu->num_cntrs)];
662 struct cci_pmu_hw_events fake_pmu = { 675 struct cci_pmu_hw_events fake_pmu = {
663 /* 676 /*
664 * Initialise the fake PMU. We only need to populate the 677 * Initialise the fake PMU. We only need to populate the
665 * used_mask for the purposes of validation. 678 * used_mask for the purposes of validation.
666 */ 679 */
667 .used_mask = { 0 }, 680 .used_mask = mask,
668 }; 681 };
682 memset(mask, 0, BITS_TO_LONGS(cci_pmu->num_cntrs) * sizeof(unsigned long));
669 683
670 if (!validate_event(event->pmu, &fake_pmu, leader)) 684 if (!validate_event(event->pmu, &fake_pmu, leader))
671 return -EINVAL; 685 return -EINVAL;
@@ -819,6 +833,7 @@ static const struct attribute_group *pmu_attr_groups[] = {
819static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev) 833static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
820{ 834{
821 char *name = cci_pmu->model->name; 835 char *name = cci_pmu->model->name;
836 u32 num_cntrs;
822 837
823 pmu_cpumask_attr.var = cci_pmu; 838 pmu_cpumask_attr.var = cci_pmu;
824 cci_pmu->pmu = (struct pmu) { 839 cci_pmu->pmu = (struct pmu) {
@@ -836,7 +851,15 @@ static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
836 }; 851 };
837 852
838 cci_pmu->plat_device = pdev; 853 cci_pmu->plat_device = pdev;
839 cci_pmu->num_events = pmu_get_max_counters(); 854 num_cntrs = pmu_get_max_counters();
855 if (num_cntrs > cci_pmu->model->num_hw_cntrs) {
856 dev_warn(&pdev->dev,
857 "PMU implements more counters(%d) than supported by"
858 " the model(%d), truncated.",
859 num_cntrs, cci_pmu->model->num_hw_cntrs);
860 num_cntrs = cci_pmu->model->num_hw_cntrs;
861 }
862 cci_pmu->num_cntrs = num_cntrs + cci_pmu->model->fixed_hw_cntrs;
840 863
841 return perf_pmu_register(&cci_pmu->pmu, name, -1); 864 return perf_pmu_register(&cci_pmu->pmu, name, -1);
842} 865}
@@ -871,6 +894,9 @@ static int cci_pmu_cpu_notifier(struct notifier_block *self,
871static struct cci_pmu_model cci_pmu_models[] = { 894static struct cci_pmu_model cci_pmu_models[] = {
872 [CCI_REV_R0] = { 895 [CCI_REV_R0] = {
873 .name = "CCI_400", 896 .name = "CCI_400",
897 .fixed_hw_cntrs = 1, /* Cycle counter */
898 .num_hw_cntrs = 4,
899 .cntr_size = SZ_4K,
874 .event_ranges = { 900 .event_ranges = {
875 [CCI_IF_SLAVE] = { 901 [CCI_IF_SLAVE] = {
876 CCI_REV_R0_SLAVE_PORT_MIN_EV, 902 CCI_REV_R0_SLAVE_PORT_MIN_EV,
@@ -884,6 +910,9 @@ static struct cci_pmu_model cci_pmu_models[] = {
884 }, 910 },
885 [CCI_REV_R1] = { 911 [CCI_REV_R1] = {
886 .name = "CCI_400_r1", 912 .name = "CCI_400_r1",
913 .fixed_hw_cntrs = 1, /* Cycle counter */
914 .num_hw_cntrs = 4,
915 .cntr_size = SZ_4K,
887 .event_ranges = { 916 .event_ranges = {
888 [CCI_IF_SLAVE] = { 917 [CCI_IF_SLAVE] = {
889 CCI_REV_R1_SLAVE_PORT_MIN_EV, 918 CCI_REV_R1_SLAVE_PORT_MIN_EV,
@@ -938,35 +967,69 @@ static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
938 return false; 967 return false;
939} 968}
940 969
941static int cci_pmu_probe(struct platform_device *pdev) 970static struct cci_pmu *cci_pmu_alloc(struct platform_device *pdev)
942{ 971{
943 struct resource *res;
944 struct cci_pmu *cci_pmu; 972 struct cci_pmu *cci_pmu;
945 int i, ret, irq;
946 const struct cci_pmu_model *model; 973 const struct cci_pmu_model *model;
947 974
975 /*
976 * All allocations are devm_* hence we don't have to free
977 * them explicitly on an error, as it would end up in driver
978 * detach.
979 */
948 model = get_cci_model(pdev); 980 model = get_cci_model(pdev);
949 if (!model) { 981 if (!model) {
950 dev_warn(&pdev->dev, "CCI PMU version not supported\n"); 982 dev_warn(&pdev->dev, "CCI PMU version not supported\n");
951 return -ENODEV; 983 return ERR_PTR(-ENODEV);
952 } 984 }
953 985
954 cci_pmu = devm_kzalloc(&pdev->dev, sizeof(*cci_pmu), GFP_KERNEL); 986 cci_pmu = devm_kzalloc(&pdev->dev, sizeof(*cci_pmu), GFP_KERNEL);
955 if (!cci_pmu) 987 if (!cci_pmu)
956 return -ENOMEM; 988 return ERR_PTR(-ENOMEM);
957 989
958 cci_pmu->model = model; 990 cci_pmu->model = model;
991 cci_pmu->irqs = devm_kcalloc(&pdev->dev, CCI_PMU_MAX_HW_CNTRS(model),
992 sizeof(*cci_pmu->irqs), GFP_KERNEL);
993 if (!cci_pmu->irqs)
994 return ERR_PTR(-ENOMEM);
995 cci_pmu->hw_events.events = devm_kcalloc(&pdev->dev,
996 CCI_PMU_MAX_HW_CNTRS(model),
997 sizeof(*cci_pmu->hw_events.events),
998 GFP_KERNEL);
999 if (!cci_pmu->hw_events.events)
1000 return ERR_PTR(-ENOMEM);
1001 cci_pmu->hw_events.used_mask = devm_kcalloc(&pdev->dev,
1002 BITS_TO_LONGS(CCI_PMU_MAX_HW_CNTRS(model)),
1003 sizeof(*cci_pmu->hw_events.used_mask),
1004 GFP_KERNEL);
1005 if (!cci_pmu->hw_events.used_mask)
1006 return ERR_PTR(-ENOMEM);
1007
1008 return cci_pmu;
1009}
1010
1011
1012static int cci_pmu_probe(struct platform_device *pdev)
1013{
1014 struct resource *res;
1015 struct cci_pmu *cci_pmu;
1016 int i, ret, irq;
1017
1018 cci_pmu = cci_pmu_alloc(pdev);
1019 if (IS_ERR(cci_pmu))
1020 return PTR_ERR(cci_pmu);
1021
959 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1022 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
960 cci_pmu->base = devm_ioremap_resource(&pdev->dev, res); 1023 cci_pmu->base = devm_ioremap_resource(&pdev->dev, res);
961 if (IS_ERR(cci_pmu->base)) 1024 if (IS_ERR(cci_pmu->base))
962 return -ENOMEM; 1025 return -ENOMEM;
963 1026
964 /* 1027 /*
965 * CCI PMU has 5 overflow signals - one per counter; but some may be tied 1028 * CCI PMU has one overflow interrupt per counter; but some may be tied
966 * together to a common interrupt. 1029 * together to a common interrupt.
967 */ 1030 */
968 cci_pmu->nr_irqs = 0; 1031 cci_pmu->nr_irqs = 0;
969 for (i = 0; i < CCI_PMU_MAX_HW_EVENTS; i++) { 1032 for (i = 0; i < CCI_PMU_MAX_HW_CNTRS(cci_pmu->model); i++) {
970 irq = platform_get_irq(pdev, i); 1033 irq = platform_get_irq(pdev, i);
971 if (irq < 0) 1034 if (irq < 0)
972 break; 1035 break;
@@ -981,9 +1044,9 @@ static int cci_pmu_probe(struct platform_device *pdev)
981 * Ensure that the device tree has as many interrupts as the number 1044 * Ensure that the device tree has as many interrupts as the number
982 * of counters. 1045 * of counters.
983 */ 1046 */
984 if (i < CCI_PMU_MAX_HW_EVENTS) { 1047 if (i < CCI_PMU_MAX_HW_CNTRS(cci_pmu->model)) {
985 dev_warn(&pdev->dev, "In-correct number of interrupts: %d, should be %d\n", 1048 dev_warn(&pdev->dev, "In-correct number of interrupts: %d, should be %d\n",
986 i, CCI_PMU_MAX_HW_EVENTS); 1049 i, CCI_PMU_MAX_HW_CNTRS(cci_pmu->model));
987 return -EINVAL; 1050 return -EINVAL;
988 } 1051 }
989 1052