[PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions

2015-03-18 Thread Suzuki K. Poulose
From: "Suzuki K. Poulose" 

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 
Tested-by: Sudeep Holla 
Acked-by: Punit Agrawal 
Reviewed-by: Will Deacon 
---
 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 5d29ec3..ae3864d 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 _event_range[rev];
+   return _pmu_models[probe_cci_revision()];
 }
 
 static int pmu_is_valid_counter(struct cci_pmu 

[PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions

2015-03-18 Thread Suzuki K. Poulose
From: Suzuki K. Poulose suzuki.poul...@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.poul...@arm.com
Tested-by: Sudeep Holla sudeep.ho...@arm.com
Acked-by: Punit Agrawal punit.agra...@arm.com
Reviewed-by: Will Deacon will.dea...@arm.com
---
 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 5d29ec3..ae3864d 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 

Re: [PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions

2015-03-17 Thread Will Deacon
On Tue, Mar 10, 2015 at 03:18:52PM +, Suzuki K. Poulose wrote:
> From: "Suzuki K. Poulose" 
> 
> 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 
> ---

Looks good to me:

Reviewed-by: Will Deacon 

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_EV0x00
>  #define CCI_REV_R1_MASTER_PORT_MAX_EV0x11
>  
> -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 

Re: [PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions

2015-03-17 Thread Will Deacon
On Tue, Mar 10, 2015 at 03:18:52PM +, Suzuki K. Poulose wrote:
 From: Suzuki K. Poulose suzuki.poul...@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.poul...@arm.com
 ---

Looks good to me:

Reviewed-by: Will Deacon will.dea...@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_EV0x00
  #define CCI_REV_R1_MASTER_PORT_MAX_EV0x11
  
 -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];
 + 

[PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions

2015-03-10 Thread Suzuki K. Poulose
From: "Suzuki K. Poulose" 

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 
---
 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 _event_range[rev];
+   return _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 

[PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions

2015-03-10 Thread Suzuki K. Poulose
From: Suzuki K. Poulose suzuki.poul...@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.poul...@arm.com
---
 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 

[PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions

2015-03-02 Thread Suzuki K. Poulose
From: "Suzuki K. Poulose" 

CCI400 has different event specifications for PMU, for revsion0 and
revision 1. As of now, we check the revision twice, for 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.

This will also help us to add new PMU versions.

Signed-off-by: Suzuki K. Poulose 
---
 drivers/bus/arm-cci.c |  124 ++---
 1 file changed, 76 insertions(+), 48 deletions(-)

diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index f27cf56..bec014b 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,47 +171,16 @@ 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;
+   return pmu->model->event_ranges[CCI_IF_SLAVE].min <= ev_code &&
+   ev_code <= pmu->model->event_ranges[CCI_IF_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;
+   return pmu->model->event_ranges[CCI_IF_MASTER].min <= ev_code &&
+   ev_code <= pmu->model->event_ranges[CCI_IF_MASTER].max;
 }
 
 static int pmu_validate_hw_event(u8 hw_event)
@@ -234,11 +222,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 _event_range[rev];
+   return _pmu_models[probe_cci_revision()];
 }
 
 static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
@@ -807,9 +793,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 +848,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,

[PATCH 2/5] arm-cci: Abstract the CCI400 PMU speicific definitions

2015-03-02 Thread Suzuki K. Poulose
From: Suzuki K. Poulose suzuki.poul...@arm.com

CCI400 has different event specifications for PMU, for revsion0 and
revision 1. As of now, we check the revision twice, for 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.

This will also help us to add new PMU versions.

Signed-off-by: Suzuki K. Poulose suzuki.poul...@arm.com
---
 drivers/bus/arm-cci.c |  124 ++---
 1 file changed, 76 insertions(+), 48 deletions(-)

diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index f27cf56..bec014b 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,47 +171,16 @@ 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;
+   return pmu-model-event_ranges[CCI_IF_SLAVE].min = ev_code 
+   ev_code = pmu-model-event_ranges[CCI_IF_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;
+   return pmu-model-event_ranges[CCI_IF_MASTER].min = ev_code 
+   ev_code = pmu-model-event_ranges[CCI_IF_MASTER].max;
 }
 
 static int pmu_validate_hw_event(u8 hw_event)
@@ -234,11 +222,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 +793,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 +848,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] = {
+