From: will.deacon@arm.com (Will Deacon)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions
Date: Tue, 17 Mar 2015 18:49:20 +0000 [thread overview]
Message-ID: <20150317184918.GD8399@arm.com> (raw)
In-Reply-To: <1426000735-14375-3-git-send-email-suzuki.poulose@arm.com>
On Tue, Mar 10, 2015 at 03:18:52PM +0000, Suzuki K. Poulose wrote:
> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
>
> CCI400 has different event specifications for PMU, for revsion
> 0 and revision 1. As of now, we check the revision every single
> time before using the parameters for the PMU. This patch abstracts
> the details of the pmu models in a struct (cci_pmu_model) and
> stores the information in cci_pmu at initialisation time, avoiding
> multiple probe operations.
>
> Changes since V2:
> - Cleanup event validation(pmu_validate_hw_event). Get rid of
> helper functions:
> pmu_is_valid_slave_event
> pmu_is_valid_master_event
>
> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
> ---
Looks good to me:
Reviewed-by: Will Deacon <will.deacon@arm.com>
Will
> drivers/bus/arm-cci.c | 141 ++++++++++++++++++++++++++++---------------------
> 1 file changed, 81 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
> index ea39fc2..f88383e 100644
> --- a/drivers/bus/arm-cci.c
> +++ b/drivers/bus/arm-cci.c
> @@ -79,19 +79,38 @@ static const struct of_device_id arm_cci_matches[] = {
>
> #define CCI_PMU_MAX_HW_EVENTS 5 /* CCI PMU has 4 counters + 1 cycle counter */
>
> +/* Types of interfaces that can generate events */
> +enum {
> + CCI_IF_SLAVE,
> + CCI_IF_MASTER,
> + CCI_IF_MAX,
> +};
> +
> +struct event_range {
> + u32 min;
> + u32 max;
> +};
> +
> struct cci_pmu_hw_events {
> struct perf_event *events[CCI_PMU_MAX_HW_EVENTS];
> unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)];
> raw_spinlock_t pmu_lock;
> };
>
> +struct cci_pmu_model {
> + char *name;
> + struct event_range event_ranges[CCI_IF_MAX];
> +};
> +
> +static struct cci_pmu_model cci_pmu_models[];
> +
> struct cci_pmu {
> void __iomem *base;
> struct pmu pmu;
> int nr_irqs;
> int irqs[CCI_PMU_MAX_HW_EVENTS];
> unsigned long active_irqs;
> - struct pmu_port_event_ranges *port_ranges;
> + const struct cci_pmu_model *model;
> struct cci_pmu_hw_events hw_events;
> struct platform_device *plat_device;
> int num_events;
> @@ -152,53 +171,11 @@ enum cci400_perf_events {
> #define CCI_REV_R1_MASTER_PORT_MIN_EV 0x00
> #define CCI_REV_R1_MASTER_PORT_MAX_EV 0x11
>
> -struct pmu_port_event_ranges {
> - u8 slave_min;
> - u8 slave_max;
> - u8 master_min;
> - u8 master_max;
> -};
> -
> -static struct pmu_port_event_ranges port_event_range[] = {
> - [CCI_REV_R0] = {
> - .slave_min = CCI_REV_R0_SLAVE_PORT_MIN_EV,
> - .slave_max = CCI_REV_R0_SLAVE_PORT_MAX_EV,
> - .master_min = CCI_REV_R0_MASTER_PORT_MIN_EV,
> - .master_max = CCI_REV_R0_MASTER_PORT_MAX_EV,
> - },
> - [CCI_REV_R1] = {
> - .slave_min = CCI_REV_R1_SLAVE_PORT_MIN_EV,
> - .slave_max = CCI_REV_R1_SLAVE_PORT_MAX_EV,
> - .master_min = CCI_REV_R1_MASTER_PORT_MIN_EV,
> - .master_max = CCI_REV_R1_MASTER_PORT_MAX_EV,
> - },
> -};
> -
> -/*
> - * Export different PMU names for the different revisions so userspace knows
> - * because the event ids are different
> - */
> -static char *const pmu_names[] = {
> - [CCI_REV_R0] = "CCI_400",
> - [CCI_REV_R1] = "CCI_400_r1",
> -};
> -
> -static int pmu_is_valid_slave_event(u8 ev_code)
> -{
> - return pmu->port_ranges->slave_min <= ev_code &&
> - ev_code <= pmu->port_ranges->slave_max;
> -}
> -
> -static int pmu_is_valid_master_event(u8 ev_code)
> -{
> - return pmu->port_ranges->master_min <= ev_code &&
> - ev_code <= pmu->port_ranges->master_max;
> -}
> -
> static int pmu_validate_hw_event(u8 hw_event)
> {
> u8 ev_source = CCI_PMU_EVENT_SOURCE(hw_event);
> u8 ev_code = CCI_PMU_EVENT_CODE(hw_event);
> + int if_type;
>
> switch (ev_source) {
> case CCI_PORT_S0:
> @@ -207,18 +184,22 @@ static int pmu_validate_hw_event(u8 hw_event)
> case CCI_PORT_S3:
> case CCI_PORT_S4:
> /* Slave Interface */
> - if (pmu_is_valid_slave_event(ev_code))
> - return hw_event;
> + if_type = CCI_IF_SLAVE;
> break;
> case CCI_PORT_M0:
> case CCI_PORT_M1:
> case CCI_PORT_M2:
> /* Master Interface */
> - if (pmu_is_valid_master_event(ev_code))
> - return hw_event;
> + if_type = CCI_IF_MASTER;
> break;
> + default:
> + return -ENOENT;
> }
>
> + if (ev_code >= pmu->model->event_ranges[if_type].min &&
> + ev_code <= pmu->model->event_ranges[if_type].max)
> + return hw_event;
> +
> return -ENOENT;
> }
>
> @@ -234,11 +215,9 @@ static int probe_cci_revision(void)
> return CCI_REV_R1;
> }
>
> -static struct pmu_port_event_ranges *port_range_by_rev(void)
> +static const struct cci_pmu_model *probe_cci_model(struct platform_device *pdev)
> {
> - int rev = probe_cci_revision();
> -
> - return &port_event_range[rev];
> + return &cci_pmu_models[probe_cci_revision()];
> }
>
> static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
> @@ -807,9 +786,9 @@ static const struct attribute_group *pmu_attr_groups[] = {
>
> static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
> {
> - char *name = pmu_names[probe_cci_revision()];
> + char *name = cci_pmu->model->name;
> cci_pmu->pmu = (struct pmu) {
> - .name = pmu_names[probe_cci_revision()],
> + .name = cci_pmu->model->name,
> .task_ctx_nr = perf_invalid_context,
> .pmu_enable = cci_pmu_enable,
> .pmu_disable = cci_pmu_disable,
> @@ -862,6 +841,35 @@ static struct notifier_block cci_pmu_cpu_nb = {
> .priority = CPU_PRI_PERF + 1,
> };
>
> +static struct cci_pmu_model cci_pmu_models[] = {
> + [CCI_REV_R0] = {
> + .name = "CCI_400",
> + .event_ranges = {
> + [CCI_IF_SLAVE] = {
> + CCI_REV_R0_SLAVE_PORT_MIN_EV,
> + CCI_REV_R0_SLAVE_PORT_MAX_EV,
> + },
> + [CCI_IF_MASTER] = {
> + CCI_REV_R0_MASTER_PORT_MIN_EV,
> + CCI_REV_R0_MASTER_PORT_MAX_EV,
> + },
> + },
> + },
> + [CCI_REV_R1] = {
> + .name = "CCI_400_r1",
> + .event_ranges = {
> + [CCI_IF_SLAVE] = {
> + CCI_REV_R1_SLAVE_PORT_MIN_EV,
> + CCI_REV_R1_SLAVE_PORT_MAX_EV,
> + },
> + [CCI_IF_MASTER] = {
> + CCI_REV_R1_MASTER_PORT_MIN_EV,
> + CCI_REV_R1_MASTER_PORT_MAX_EV,
> + },
> + },
> + },
> +};
> +
> static const struct of_device_id arm_cci_pmu_matches[] = {
> {
> .compatible = "arm,cci-400-pmu",
> @@ -869,6 +877,16 @@ static const struct of_device_id arm_cci_pmu_matches[] = {
> {},
> };
>
> +static inline const struct cci_pmu_model *get_cci_model(struct platform_device *pdev)
> +{
> + const struct of_device_id *match = of_match_node(arm_cci_pmu_matches,
> + pdev->dev.of_node);
> + if (!match)
> + return NULL;
> +
> + return probe_cci_model(pdev);
> +}
> +
> static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
> {
> int i;
> @@ -884,11 +902,19 @@ static int cci_pmu_probe(struct platform_device *pdev)
> {
> struct resource *res;
> int i, ret, irq;
> + const struct cci_pmu_model *model;
> +
> + model = get_cci_model(pdev);
> + if (!model) {
> + dev_warn(&pdev->dev, "CCI PMU version not supported\n");
> + return -ENODEV;
> + }
>
> pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
> if (!pmu)
> return -ENOMEM;
>
> + pmu->model = model;
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> pmu->base = devm_ioremap_resource(&pdev->dev, res);
> if (IS_ERR(pmu->base))
> @@ -920,12 +946,6 @@ static int cci_pmu_probe(struct platform_device *pdev)
> return -EINVAL;
> }
>
> - pmu->port_ranges = port_range_by_rev();
> - if (!pmu->port_ranges) {
> - dev_warn(&pdev->dev, "CCI PMU version not supported\n");
> - return -EINVAL;
> - }
> -
> raw_spin_lock_init(&pmu->hw_events.pmu_lock);
> mutex_init(&pmu->reserve_mutex);
> atomic_set(&pmu->active_events, 0);
> @@ -939,6 +959,7 @@ static int cci_pmu_probe(struct platform_device *pdev)
> if (ret)
> return ret;
>
> + pr_info("ARM %s PMU driver probed", pmu->model->name);
> return 0;
> }
>
> --
> 1.7.9.5
>
WARNING: multiple messages have this Message-ID (diff)
From: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
To: "Suzuki K. Poulose" <suzuki.poulose-5wv7dgnIgG8@public.gmane.org>
Cc: "linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org"
<linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>,
Nicolas Pitre <nico-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
Bartlomiej Zolnierkiewicz
<b.zolnierkie-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>,
Kukjin Kim <kgene-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
Abhilash Kesavan
<a.kesavan-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>,
Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>,
"devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org"
<devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
"linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org"
<linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
Liviu Dudau <Liviu.Dudau-5wv7dgnIgG8@public.gmane.org>,
Lorenzo Pieralisi
<Lorenzo.Pieralisi-5wv7dgnIgG8@public.gmane.org>,
Olof Johansson <olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org>,
Pawel Moll <Pawel.Moll-5wv7dgnIgG8@public.gmane.org>,
Punit Agrawal <Punit.Agrawal-5wv7dgnIgG8@public.gmane.org>,
Sudeep Holla <Sudeep.Holla-5wv7dgnIgG8@public.gmane.org>,
Catalin Marinas <Catalin.Marinas-5wv7dgnIgG8@public.gmane.org>
Subject: Re: [PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions
Date: Tue, 17 Mar 2015 18:49:20 +0000 [thread overview]
Message-ID: <20150317184918.GD8399@arm.com> (raw)
In-Reply-To: <1426000735-14375-3-git-send-email-suzuki.poulose-5wv7dgnIgG8@public.gmane.org>
On Tue, Mar 10, 2015 at 03:18:52PM +0000, Suzuki K. Poulose wrote:
> From: "Suzuki K. Poulose" <suzuki.poulose-5wv7dgnIgG8@public.gmane.org>
>
> CCI400 has different event specifications for PMU, for revsion
> 0 and revision 1. As of now, we check the revision every single
> time before using the parameters for the PMU. This patch abstracts
> the details of the pmu models in a struct (cci_pmu_model) and
> stores the information in cci_pmu at initialisation time, avoiding
> multiple probe operations.
>
> Changes since V2:
> - Cleanup event validation(pmu_validate_hw_event). Get rid of
> helper functions:
> pmu_is_valid_slave_event
> pmu_is_valid_master_event
>
> Signed-off-by: Suzuki K. Poulose <suzuki.poulose-5wv7dgnIgG8@public.gmane.org>
> ---
Looks good to me:
Reviewed-by: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
Will
> drivers/bus/arm-cci.c | 141 ++++++++++++++++++++++++++++---------------------
> 1 file changed, 81 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
> index ea39fc2..f88383e 100644
> --- a/drivers/bus/arm-cci.c
> +++ b/drivers/bus/arm-cci.c
> @@ -79,19 +79,38 @@ static const struct of_device_id arm_cci_matches[] = {
>
> #define CCI_PMU_MAX_HW_EVENTS 5 /* CCI PMU has 4 counters + 1 cycle counter */
>
> +/* Types of interfaces that can generate events */
> +enum {
> + CCI_IF_SLAVE,
> + CCI_IF_MASTER,
> + CCI_IF_MAX,
> +};
> +
> +struct event_range {
> + u32 min;
> + u32 max;
> +};
> +
> struct cci_pmu_hw_events {
> struct perf_event *events[CCI_PMU_MAX_HW_EVENTS];
> unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)];
> raw_spinlock_t pmu_lock;
> };
>
> +struct cci_pmu_model {
> + char *name;
> + struct event_range event_ranges[CCI_IF_MAX];
> +};
> +
> +static struct cci_pmu_model cci_pmu_models[];
> +
> struct cci_pmu {
> void __iomem *base;
> struct pmu pmu;
> int nr_irqs;
> int irqs[CCI_PMU_MAX_HW_EVENTS];
> unsigned long active_irqs;
> - struct pmu_port_event_ranges *port_ranges;
> + const struct cci_pmu_model *model;
> struct cci_pmu_hw_events hw_events;
> struct platform_device *plat_device;
> int num_events;
> @@ -152,53 +171,11 @@ enum cci400_perf_events {
> #define CCI_REV_R1_MASTER_PORT_MIN_EV 0x00
> #define CCI_REV_R1_MASTER_PORT_MAX_EV 0x11
>
> -struct pmu_port_event_ranges {
> - u8 slave_min;
> - u8 slave_max;
> - u8 master_min;
> - u8 master_max;
> -};
> -
> -static struct pmu_port_event_ranges port_event_range[] = {
> - [CCI_REV_R0] = {
> - .slave_min = CCI_REV_R0_SLAVE_PORT_MIN_EV,
> - .slave_max = CCI_REV_R0_SLAVE_PORT_MAX_EV,
> - .master_min = CCI_REV_R0_MASTER_PORT_MIN_EV,
> - .master_max = CCI_REV_R0_MASTER_PORT_MAX_EV,
> - },
> - [CCI_REV_R1] = {
> - .slave_min = CCI_REV_R1_SLAVE_PORT_MIN_EV,
> - .slave_max = CCI_REV_R1_SLAVE_PORT_MAX_EV,
> - .master_min = CCI_REV_R1_MASTER_PORT_MIN_EV,
> - .master_max = CCI_REV_R1_MASTER_PORT_MAX_EV,
> - },
> -};
> -
> -/*
> - * Export different PMU names for the different revisions so userspace knows
> - * because the event ids are different
> - */
> -static char *const pmu_names[] = {
> - [CCI_REV_R0] = "CCI_400",
> - [CCI_REV_R1] = "CCI_400_r1",
> -};
> -
> -static int pmu_is_valid_slave_event(u8 ev_code)
> -{
> - return pmu->port_ranges->slave_min <= ev_code &&
> - ev_code <= pmu->port_ranges->slave_max;
> -}
> -
> -static int pmu_is_valid_master_event(u8 ev_code)
> -{
> - return pmu->port_ranges->master_min <= ev_code &&
> - ev_code <= pmu->port_ranges->master_max;
> -}
> -
> static int pmu_validate_hw_event(u8 hw_event)
> {
> u8 ev_source = CCI_PMU_EVENT_SOURCE(hw_event);
> u8 ev_code = CCI_PMU_EVENT_CODE(hw_event);
> + int if_type;
>
> switch (ev_source) {
> case CCI_PORT_S0:
> @@ -207,18 +184,22 @@ static int pmu_validate_hw_event(u8 hw_event)
> case CCI_PORT_S3:
> case CCI_PORT_S4:
> /* Slave Interface */
> - if (pmu_is_valid_slave_event(ev_code))
> - return hw_event;
> + if_type = CCI_IF_SLAVE;
> break;
> case CCI_PORT_M0:
> case CCI_PORT_M1:
> case CCI_PORT_M2:
> /* Master Interface */
> - if (pmu_is_valid_master_event(ev_code))
> - return hw_event;
> + if_type = CCI_IF_MASTER;
> break;
> + default:
> + return -ENOENT;
> }
>
> + if (ev_code >= pmu->model->event_ranges[if_type].min &&
> + ev_code <= pmu->model->event_ranges[if_type].max)
> + return hw_event;
> +
> return -ENOENT;
> }
>
> @@ -234,11 +215,9 @@ static int probe_cci_revision(void)
> return CCI_REV_R1;
> }
>
> -static struct pmu_port_event_ranges *port_range_by_rev(void)
> +static const struct cci_pmu_model *probe_cci_model(struct platform_device *pdev)
> {
> - int rev = probe_cci_revision();
> -
> - return &port_event_range[rev];
> + return &cci_pmu_models[probe_cci_revision()];
> }
>
> static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
> @@ -807,9 +786,9 @@ static const struct attribute_group *pmu_attr_groups[] = {
>
> static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
> {
> - char *name = pmu_names[probe_cci_revision()];
> + char *name = cci_pmu->model->name;
> cci_pmu->pmu = (struct pmu) {
> - .name = pmu_names[probe_cci_revision()],
> + .name = cci_pmu->model->name,
> .task_ctx_nr = perf_invalid_context,
> .pmu_enable = cci_pmu_enable,
> .pmu_disable = cci_pmu_disable,
> @@ -862,6 +841,35 @@ static struct notifier_block cci_pmu_cpu_nb = {
> .priority = CPU_PRI_PERF + 1,
> };
>
> +static struct cci_pmu_model cci_pmu_models[] = {
> + [CCI_REV_R0] = {
> + .name = "CCI_400",
> + .event_ranges = {
> + [CCI_IF_SLAVE] = {
> + CCI_REV_R0_SLAVE_PORT_MIN_EV,
> + CCI_REV_R0_SLAVE_PORT_MAX_EV,
> + },
> + [CCI_IF_MASTER] = {
> + CCI_REV_R0_MASTER_PORT_MIN_EV,
> + CCI_REV_R0_MASTER_PORT_MAX_EV,
> + },
> + },
> + },
> + [CCI_REV_R1] = {
> + .name = "CCI_400_r1",
> + .event_ranges = {
> + [CCI_IF_SLAVE] = {
> + CCI_REV_R1_SLAVE_PORT_MIN_EV,
> + CCI_REV_R1_SLAVE_PORT_MAX_EV,
> + },
> + [CCI_IF_MASTER] = {
> + CCI_REV_R1_MASTER_PORT_MIN_EV,
> + CCI_REV_R1_MASTER_PORT_MAX_EV,
> + },
> + },
> + },
> +};
> +
> static const struct of_device_id arm_cci_pmu_matches[] = {
> {
> .compatible = "arm,cci-400-pmu",
> @@ -869,6 +877,16 @@ static const struct of_device_id arm_cci_pmu_matches[] = {
> {},
> };
>
> +static inline const struct cci_pmu_model *get_cci_model(struct platform_device *pdev)
> +{
> + const struct of_device_id *match = of_match_node(arm_cci_pmu_matches,
> + pdev->dev.of_node);
> + if (!match)
> + return NULL;
> +
> + return probe_cci_model(pdev);
> +}
> +
> static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
> {
> int i;
> @@ -884,11 +902,19 @@ static int cci_pmu_probe(struct platform_device *pdev)
> {
> struct resource *res;
> int i, ret, irq;
> + const struct cci_pmu_model *model;
> +
> + model = get_cci_model(pdev);
> + if (!model) {
> + dev_warn(&pdev->dev, "CCI PMU version not supported\n");
> + return -ENODEV;
> + }
>
> pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
> if (!pmu)
> return -ENOMEM;
>
> + pmu->model = model;
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> pmu->base = devm_ioremap_resource(&pdev->dev, res);
> if (IS_ERR(pmu->base))
> @@ -920,12 +946,6 @@ static int cci_pmu_probe(struct platform_device *pdev)
> return -EINVAL;
> }
>
> - pmu->port_ranges = port_range_by_rev();
> - if (!pmu->port_ranges) {
> - dev_warn(&pdev->dev, "CCI PMU version not supported\n");
> - return -EINVAL;
> - }
> -
> raw_spin_lock_init(&pmu->hw_events.pmu_lock);
> mutex_init(&pmu->reserve_mutex);
> atomic_set(&pmu->active_events, 0);
> @@ -939,6 +959,7 @@ static int cci_pmu_probe(struct platform_device *pdev)
> if (ret)
> return ret;
>
> + pr_info("ARM %s PMU driver probed", pmu->model->name);
> return 0;
> }
>
> --
> 1.7.9.5
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: Will Deacon <will.deacon@arm.com>
To: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
Cc: "linux-arm-kernel@lists.infradead.org"
<linux-arm-kernel@lists.infradead.org>,
Nicolas Pitre <nico@linaro.org>,
Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>,
Kukjin Kim <kgene@kernel.org>,
Abhilash Kesavan <a.kesavan@samsung.com>,
Arnd Bergmann <arnd@arndb.de>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
Liviu Dudau <Liviu.Dudau@arm.com>,
Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>,
Olof Johansson <olof@lixom.net>, Pawel Moll <Pawel.Moll@arm.com>,
Punit Agrawal <Punit.Agrawal@arm.com>,
Sudeep Holla <Sudeep.Holla@arm.com>,
Catalin Marinas <Catalin.Marinas@arm.com>
Subject: Re: [PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions
Date: Tue, 17 Mar 2015 18:49:20 +0000 [thread overview]
Message-ID: <20150317184918.GD8399@arm.com> (raw)
In-Reply-To: <1426000735-14375-3-git-send-email-suzuki.poulose@arm.com>
On Tue, Mar 10, 2015 at 03:18:52PM +0000, Suzuki K. Poulose wrote:
> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
>
> CCI400 has different event specifications for PMU, for revsion
> 0 and revision 1. As of now, we check the revision every single
> time before using the parameters for the PMU. This patch abstracts
> the details of the pmu models in a struct (cci_pmu_model) and
> stores the information in cci_pmu at initialisation time, avoiding
> multiple probe operations.
>
> Changes since V2:
> - Cleanup event validation(pmu_validate_hw_event). Get rid of
> helper functions:
> pmu_is_valid_slave_event
> pmu_is_valid_master_event
>
> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
> ---
Looks good to me:
Reviewed-by: Will Deacon <will.deacon@arm.com>
Will
> drivers/bus/arm-cci.c | 141 ++++++++++++++++++++++++++++---------------------
> 1 file changed, 81 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
> index ea39fc2..f88383e 100644
> --- a/drivers/bus/arm-cci.c
> +++ b/drivers/bus/arm-cci.c
> @@ -79,19 +79,38 @@ static const struct of_device_id arm_cci_matches[] = {
>
> #define CCI_PMU_MAX_HW_EVENTS 5 /* CCI PMU has 4 counters + 1 cycle counter */
>
> +/* Types of interfaces that can generate events */
> +enum {
> + CCI_IF_SLAVE,
> + CCI_IF_MASTER,
> + CCI_IF_MAX,
> +};
> +
> +struct event_range {
> + u32 min;
> + u32 max;
> +};
> +
> struct cci_pmu_hw_events {
> struct perf_event *events[CCI_PMU_MAX_HW_EVENTS];
> unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)];
> raw_spinlock_t pmu_lock;
> };
>
> +struct cci_pmu_model {
> + char *name;
> + struct event_range event_ranges[CCI_IF_MAX];
> +};
> +
> +static struct cci_pmu_model cci_pmu_models[];
> +
> struct cci_pmu {
> void __iomem *base;
> struct pmu pmu;
> int nr_irqs;
> int irqs[CCI_PMU_MAX_HW_EVENTS];
> unsigned long active_irqs;
> - struct pmu_port_event_ranges *port_ranges;
> + const struct cci_pmu_model *model;
> struct cci_pmu_hw_events hw_events;
> struct platform_device *plat_device;
> int num_events;
> @@ -152,53 +171,11 @@ enum cci400_perf_events {
> #define CCI_REV_R1_MASTER_PORT_MIN_EV 0x00
> #define CCI_REV_R1_MASTER_PORT_MAX_EV 0x11
>
> -struct pmu_port_event_ranges {
> - u8 slave_min;
> - u8 slave_max;
> - u8 master_min;
> - u8 master_max;
> -};
> -
> -static struct pmu_port_event_ranges port_event_range[] = {
> - [CCI_REV_R0] = {
> - .slave_min = CCI_REV_R0_SLAVE_PORT_MIN_EV,
> - .slave_max = CCI_REV_R0_SLAVE_PORT_MAX_EV,
> - .master_min = CCI_REV_R0_MASTER_PORT_MIN_EV,
> - .master_max = CCI_REV_R0_MASTER_PORT_MAX_EV,
> - },
> - [CCI_REV_R1] = {
> - .slave_min = CCI_REV_R1_SLAVE_PORT_MIN_EV,
> - .slave_max = CCI_REV_R1_SLAVE_PORT_MAX_EV,
> - .master_min = CCI_REV_R1_MASTER_PORT_MIN_EV,
> - .master_max = CCI_REV_R1_MASTER_PORT_MAX_EV,
> - },
> -};
> -
> -/*
> - * Export different PMU names for the different revisions so userspace knows
> - * because the event ids are different
> - */
> -static char *const pmu_names[] = {
> - [CCI_REV_R0] = "CCI_400",
> - [CCI_REV_R1] = "CCI_400_r1",
> -};
> -
> -static int pmu_is_valid_slave_event(u8 ev_code)
> -{
> - return pmu->port_ranges->slave_min <= ev_code &&
> - ev_code <= pmu->port_ranges->slave_max;
> -}
> -
> -static int pmu_is_valid_master_event(u8 ev_code)
> -{
> - return pmu->port_ranges->master_min <= ev_code &&
> - ev_code <= pmu->port_ranges->master_max;
> -}
> -
> static int pmu_validate_hw_event(u8 hw_event)
> {
> u8 ev_source = CCI_PMU_EVENT_SOURCE(hw_event);
> u8 ev_code = CCI_PMU_EVENT_CODE(hw_event);
> + int if_type;
>
> switch (ev_source) {
> case CCI_PORT_S0:
> @@ -207,18 +184,22 @@ static int pmu_validate_hw_event(u8 hw_event)
> case CCI_PORT_S3:
> case CCI_PORT_S4:
> /* Slave Interface */
> - if (pmu_is_valid_slave_event(ev_code))
> - return hw_event;
> + if_type = CCI_IF_SLAVE;
> break;
> case CCI_PORT_M0:
> case CCI_PORT_M1:
> case CCI_PORT_M2:
> /* Master Interface */
> - if (pmu_is_valid_master_event(ev_code))
> - return hw_event;
> + if_type = CCI_IF_MASTER;
> break;
> + default:
> + return -ENOENT;
> }
>
> + if (ev_code >= pmu->model->event_ranges[if_type].min &&
> + ev_code <= pmu->model->event_ranges[if_type].max)
> + return hw_event;
> +
> return -ENOENT;
> }
>
> @@ -234,11 +215,9 @@ static int probe_cci_revision(void)
> return CCI_REV_R1;
> }
>
> -static struct pmu_port_event_ranges *port_range_by_rev(void)
> +static const struct cci_pmu_model *probe_cci_model(struct platform_device *pdev)
> {
> - int rev = probe_cci_revision();
> -
> - return &port_event_range[rev];
> + return &cci_pmu_models[probe_cci_revision()];
> }
>
> static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
> @@ -807,9 +786,9 @@ static const struct attribute_group *pmu_attr_groups[] = {
>
> static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
> {
> - char *name = pmu_names[probe_cci_revision()];
> + char *name = cci_pmu->model->name;
> cci_pmu->pmu = (struct pmu) {
> - .name = pmu_names[probe_cci_revision()],
> + .name = cci_pmu->model->name,
> .task_ctx_nr = perf_invalid_context,
> .pmu_enable = cci_pmu_enable,
> .pmu_disable = cci_pmu_disable,
> @@ -862,6 +841,35 @@ static struct notifier_block cci_pmu_cpu_nb = {
> .priority = CPU_PRI_PERF + 1,
> };
>
> +static struct cci_pmu_model cci_pmu_models[] = {
> + [CCI_REV_R0] = {
> + .name = "CCI_400",
> + .event_ranges = {
> + [CCI_IF_SLAVE] = {
> + CCI_REV_R0_SLAVE_PORT_MIN_EV,
> + CCI_REV_R0_SLAVE_PORT_MAX_EV,
> + },
> + [CCI_IF_MASTER] = {
> + CCI_REV_R0_MASTER_PORT_MIN_EV,
> + CCI_REV_R0_MASTER_PORT_MAX_EV,
> + },
> + },
> + },
> + [CCI_REV_R1] = {
> + .name = "CCI_400_r1",
> + .event_ranges = {
> + [CCI_IF_SLAVE] = {
> + CCI_REV_R1_SLAVE_PORT_MIN_EV,
> + CCI_REV_R1_SLAVE_PORT_MAX_EV,
> + },
> + [CCI_IF_MASTER] = {
> + CCI_REV_R1_MASTER_PORT_MIN_EV,
> + CCI_REV_R1_MASTER_PORT_MAX_EV,
> + },
> + },
> + },
> +};
> +
> static const struct of_device_id arm_cci_pmu_matches[] = {
> {
> .compatible = "arm,cci-400-pmu",
> @@ -869,6 +877,16 @@ static const struct of_device_id arm_cci_pmu_matches[] = {
> {},
> };
>
> +static inline const struct cci_pmu_model *get_cci_model(struct platform_device *pdev)
> +{
> + const struct of_device_id *match = of_match_node(arm_cci_pmu_matches,
> + pdev->dev.of_node);
> + if (!match)
> + return NULL;
> +
> + return probe_cci_model(pdev);
> +}
> +
> static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
> {
> int i;
> @@ -884,11 +902,19 @@ static int cci_pmu_probe(struct platform_device *pdev)
> {
> struct resource *res;
> int i, ret, irq;
> + const struct cci_pmu_model *model;
> +
> + model = get_cci_model(pdev);
> + if (!model) {
> + dev_warn(&pdev->dev, "CCI PMU version not supported\n");
> + return -ENODEV;
> + }
>
> pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
> if (!pmu)
> return -ENOMEM;
>
> + pmu->model = model;
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> pmu->base = devm_ioremap_resource(&pdev->dev, res);
> if (IS_ERR(pmu->base))
> @@ -920,12 +946,6 @@ static int cci_pmu_probe(struct platform_device *pdev)
> return -EINVAL;
> }
>
> - pmu->port_ranges = port_range_by_rev();
> - if (!pmu->port_ranges) {
> - dev_warn(&pdev->dev, "CCI PMU version not supported\n");
> - return -EINVAL;
> - }
> -
> raw_spin_lock_init(&pmu->hw_events.pmu_lock);
> mutex_init(&pmu->reserve_mutex);
> atomic_set(&pmu->active_events, 0);
> @@ -939,6 +959,7 @@ static int cci_pmu_probe(struct platform_device *pdev)
> if (ret)
> return ret;
>
> + pr_info("ARM %s PMU driver probed", pmu->model->name);
> return 0;
> }
>
> --
> 1.7.9.5
>
next prev parent reply other threads:[~2015-03-17 18:49 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-10 15:18 [PATCHv3 0/5] arm-cci400: PMU monitoring support on ARM64 Suzuki K. Poulose
2015-03-10 15:18 ` Suzuki K. Poulose
2015-03-10 15:18 ` Suzuki K. Poulose
2015-03-10 15:18 ` [PATCH 1/5] arm-cci: Rearrange code for splitting PMU vs driver code Suzuki K. Poulose
2015-03-10 15:18 ` Suzuki K. Poulose
2015-03-10 15:18 ` [PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions Suzuki K. Poulose
2015-03-10 15:18 ` Suzuki K. Poulose
2015-03-10 15:18 ` Suzuki K. Poulose
2015-03-17 18:49 ` Will Deacon [this message]
2015-03-17 18:49 ` Will Deacon
2015-03-17 18:49 ` Will Deacon
2015-03-10 15:18 ` [PATCH 3/5] arm-cci: Get rid of secure transactions for PMU driver Suzuki K. Poulose
2015-03-10 15:18 ` Suzuki K. Poulose
2015-03-10 15:18 ` Suzuki K. Poulose
2015-03-17 9:51 ` [UPDATED] " Suzuki K. Poulose
2015-03-17 9:51 ` Suzuki K. Poulose
2015-03-19 17:25 ` Mark Rutland
2015-03-19 17:25 ` Mark Rutland
2015-03-19 17:32 ` Mark Rutland
2015-03-19 17:32 ` Mark Rutland
2015-03-19 17:32 ` Mark Rutland
2015-03-19 17:38 ` Sudeep Holla
2015-03-19 17:38 ` Sudeep Holla
2015-03-19 17:52 ` Suzuki K. Poulose
2015-03-19 17:52 ` Suzuki K. Poulose
2015-03-19 17:54 ` Mark Rutland
2015-03-19 17:54 ` Mark Rutland
2015-03-19 17:54 ` Mark Rutland
2015-03-10 15:18 ` [PATCH 4/5] arm-cci: Split the code for PMU vs driver support Suzuki K. Poulose
2015-03-10 15:18 ` Suzuki K. Poulose
2015-03-10 16:24 ` Sudeep Holla
2015-03-10 16:24 ` Sudeep Holla
2015-03-10 16:24 ` Sudeep Holla
2015-03-10 15:18 ` [PATCH 5/5] arm-cci: Fix CCI PMU event validation Suzuki K. Poulose
2015-03-10 15:18 ` Suzuki K. Poulose
2015-03-17 18:52 ` Will Deacon
2015-03-17 18:52 ` Will Deacon
2015-03-17 18:52 ` Will Deacon
2015-03-10 16:09 ` [PATCHv3 0/5] arm-cci400: PMU monitoring support on ARM64 Nicolas Pitre
2015-03-10 16:09 ` Nicolas Pitre
2015-03-10 16:09 ` Nicolas Pitre
2015-03-10 16:11 ` Suzuki K. Poulose
2015-03-10 16:11 ` Suzuki K. Poulose
2015-03-10 16:21 ` Sudeep Holla
2015-03-10 16:21 ` Sudeep Holla
2015-03-10 16:24 ` Suzuki K. Poulose
2015-03-10 16:24 ` Suzuki K. Poulose
2015-03-11 11:40 ` Punit Agrawal
2015-03-11 11:40 ` Punit Agrawal
2015-03-11 11:40 ` Punit Agrawal
2015-03-17 18:54 ` Will Deacon
2015-03-17 18:54 ` Will Deacon
2015-03-18 10:09 ` Suzuki K. Poulose
2015-03-18 10:09 ` Suzuki K. Poulose
-- strict thread matches above, loose matches on Subject: below --
2015-03-18 12:24 [PATCHv4 " Suzuki K. Poulose
2015-03-18 12:24 ` [PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions Suzuki K. Poulose
2015-03-02 11:29 [PATCH v2 0/5] arm-cci400: PMU monitoring support on ARM64 Suzuki K. Poulose
2015-03-02 11:29 ` [PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions Suzuki K. Poulose
2015-03-02 11:29 ` Suzuki K. Poulose
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150317184918.GD8399@arm.com \
--to=will.deacon@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.