[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20150317184918.GD8399@arm.com>
Date: Tue, 17 Mar 2015 18:49:20 +0000
From: Will Deacon <will.deacon@....com>
To: "Suzuki K. Poulose" <suzuki.poulose@....com>
Cc: "linux-arm-kernel@...ts.infradead.org"
<linux-arm-kernel@...ts.infradead.org>,
Nicolas Pitre <nico@...aro.org>,
Bartlomiej Zolnierkiewicz <b.zolnierkie@...sung.com>,
Kukjin Kim <kgene@...nel.org>,
Abhilash Kesavan <a.kesavan@...sung.com>,
Arnd Bergmann <arnd@...db.de>,
"devicetree@...r.kernel.org" <devicetree@...r.kernel.org>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
Liviu Dudau <Liviu.Dudau@....com>,
Lorenzo Pieralisi <Lorenzo.Pieralisi@....com>,
Olof Johansson <olof@...om.net>,
Pawel Moll <Pawel.Moll@....com>,
Punit Agrawal <Punit.Agrawal@....com>,
Sudeep Holla <Sudeep.Holla@....com>,
Catalin Marinas <Catalin.Marinas@....com>
Subject: Re: [PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific
definitions
On Tue, Mar 10, 2015 at 03:18:52PM +0000, Suzuki K. Poulose wrote:
> From: "Suzuki K. Poulose" <suzuki.poulose@....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@....com>
> ---
Looks good to me:
Reviewed-by: Will Deacon <will.deacon@....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
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists