linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] arm-cci400: PMU monitoring support on ARM64
@ 2015-02-24 13:17 Suzuki K. Poulose
  2015-02-24 13:17 ` [PATCH 1/4] arm-cci: Rearrange code for splitting PMU vs driver code Suzuki K. Poulose
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Suzuki K. Poulose @ 2015-02-24 13:17 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Nicolas Pitre, Bartlomiej Zolnierkiewicz, Kukjin Kim,
	Abhilash Kesavan, Arnd Bergmann, devicetree, linux-kernel,
	Liviu Dudau, Lorenzo Pieralisi, Olof Johansson, Pawel Moll,
	Punit Agrawal, Sudeep Holla, Will Deacon, Catalin Marinas,
	Suzuki K. Poulose

From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>

This series enables the PMU monitoring support for CCI400 on ARM64.
The existing CCI400 driver code is a mix of PMU driver and the MCPM
driver code. The MCPM driver is only used on ARM(32) and contains
arm32 assembly and hence can't be built on ARM64. This patch splits
the code to

 - ARM_CCI400_MCPM driver - depends on ARM && V7
 - ARM_CCI400_PMU driver

Accessing the Peripheral ID2 register(PID2) on CCI-400, to detect
the revision of the chipset, is a secure operation. Hence, it prevents
us from running this on non-secure platforms. The issue is overcome by
explicitly mentioning the revision number of the CCI PMU in the device tree
binding. The device-tree binding has been updated with the new bindings.

i.e,	arm-cci-400-pmu,r0 => revision 0
	arm-cci-400-pmu,r1 => revision 1
	arm-cci-400-pmu => (old) DEPRECATED

The old binding has been DEPRECATED and must be used only on ARM32
system with secure access. We don't have a reliable dynamic way to detect
if the system is running secure. This series tries to use the best safe
method by relying on the availability of MCPM(as it was prior to the series).
It is upto the MCPM platform driver to decide, if the system is secure before
it goes ahead and registers its drivers and pokes the CCI. This series doesn't
address/solve the problem of MCPM. I will be happy to use a better approach,
if there is any.

Tested on (non-secure)TC2 and Juno.

Suzuki K. Poulose (4):
  arm-cci: Rearrange code for splitting PMU vs driver code
  arm-cci: Get rid of secure transactions for PMU driver
  arm-cci: Split the code for PMU vs driver support
  arm-cci: Fix CCI PMU event validation

 Documentation/devicetree/bindings/arm/cci.txt |    7 +-
 arch/arm/include/asm/arm-cci.h                |   42 +++
 arch/arm/mach-exynos/Kconfig                  |    2 +-
 arch/arm/mach-vexpress/Kconfig                |    4 +-
 arch/arm64/include/asm/arm-cci.h              |   27 ++
 drivers/bus/Kconfig                           |   28 +-
 drivers/bus/arm-cci.c                         |  483 ++++++++++++++-----------
 include/linux/arm-cci.h                       |    9 +-
 8 files changed, 383 insertions(+), 219 deletions(-)
 create mode 100644 arch/arm/include/asm/arm-cci.h
 create mode 100644 arch/arm64/include/asm/arm-cci.h

-- 
1.7.9.5



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/4] arm-cci: Rearrange code for splitting PMU vs driver code
  2015-02-24 13:17 [PATCH 0/4] arm-cci400: PMU monitoring support on ARM64 Suzuki K. Poulose
@ 2015-02-24 13:17 ` Suzuki K. Poulose
  2015-02-24 13:17 ` [PATCH 2/4] arm-cci: Get rid of secure transactions for PMU driver Suzuki K. Poulose
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Suzuki K. Poulose @ 2015-02-24 13:17 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Nicolas Pitre, Bartlomiej Zolnierkiewicz, Kukjin Kim,
	Abhilash Kesavan, Arnd Bergmann, devicetree, linux-kernel,
	Liviu Dudau, Lorenzo Pieralisi, Olof Johansson, Pawel Moll,
	Punit Agrawal, Sudeep Holla, Will Deacon, Catalin Marinas,
	Suzuki K. Poulose

From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>

No functional changes, only code re-arrangements for easier split of the
PMU code vs low level driver code. Extracts the port handling code
to cci_probe_ports().

Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
---
 drivers/bus/arm-cci.c |  330 +++++++++++++++++++++++++------------------------
 1 file changed, 168 insertions(+), 162 deletions(-)

diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 84fd660..f27cf56 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -29,42 +29,29 @@
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 
-#define DRIVER_NAME		"CCI-400"
-#define DRIVER_NAME_PMU		DRIVER_NAME " PMU"
-
-#define CCI_PORT_CTRL		0x0
-#define CCI_CTRL_STATUS		0xc
-
-#define CCI_ENABLE_SNOOP_REQ	0x1
-#define CCI_ENABLE_DVM_REQ	0x2
-#define CCI_ENABLE_REQ		(CCI_ENABLE_SNOOP_REQ | CCI_ENABLE_DVM_REQ)
+static void __iomem *cci_ctrl_base;
+static unsigned long cci_ctrl_phys;
 
 struct cci_nb_ports {
 	unsigned int nb_ace;
 	unsigned int nb_ace_lite;
 };
 
-enum cci_ace_port_type {
-	ACE_INVALID_PORT = 0x0,
-	ACE_PORT,
-	ACE_LITE_PORT,
+static const struct cci_nb_ports cci400_ports = {
+	.nb_ace = 2,
+	.nb_ace_lite = 3
 };
 
-struct cci_ace_port {
-	void __iomem *base;
-	unsigned long phys;
-	enum cci_ace_port_type type;
-	struct device_node *dn;
+static const struct of_device_id arm_cci_matches[] = {
+	{.compatible = "arm,cci-400", .data = &cci400_ports },
+	{},
 };
 
-static struct cci_ace_port *ports;
-static unsigned int nb_cci_ports;
-
-static void __iomem *cci_ctrl_base;
-static unsigned long cci_ctrl_phys;
-
 #ifdef CONFIG_HW_PERF_EVENTS
 
+#define DRIVER_NAME		"CCI-400"
+#define DRIVER_NAME_PMU		DRIVER_NAME " PMU"
+
 #define CCI_PMCR		0x0100
 #define CCI_PID2		0x0fe8
 
@@ -75,6 +62,47 @@ static unsigned long cci_ctrl_phys;
 #define CCI_PID2_REV_MASK	0xf0
 #define CCI_PID2_REV_SHIFT	4
 
+#define CCI_PMU_EVT_SEL		0x000
+#define CCI_PMU_CNTR		0x004
+#define CCI_PMU_CNTR_CTRL	0x008
+#define CCI_PMU_OVRFLW		0x00c
+
+#define CCI_PMU_OVRFLW_FLAG	1
+
+#define CCI_PMU_CNTR_BASE(idx)	((idx) * SZ_4K)
+
+#define CCI_PMU_CNTR_MASK	((1ULL << 32) -1)
+
+#define CCI_PMU_EVENT_MASK		0xff
+#define CCI_PMU_EVENT_SOURCE(event)	((event >> 5) & 0x7)
+#define CCI_PMU_EVENT_CODE(event)	(event & 0x1f)
+
+#define CCI_PMU_MAX_HW_EVENTS 5   /* CCI PMU has 4 counters + 1 cycle counter */
+
+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 {
+	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;
+	struct cci_pmu_hw_events hw_events;
+	struct platform_device *plat_device;
+	int num_events;
+	atomic_t active_events;
+	struct mutex reserve_mutex;
+	cpumask_t cpus;
+};
+static struct cci_pmu *pmu;
+
+#define to_cci_pmu(c)	(container_of(c, struct cci_pmu, pmu))
+
 /* Port ids */
 #define CCI_PORT_S0	0
 #define CCI_PORT_S1	1
@@ -89,17 +117,6 @@ static unsigned long cci_ctrl_phys;
 #define CCI_REV_R1		1
 #define CCI_REV_R1_PX		5
 
-#define CCI_PMU_EVT_SEL		0x000
-#define CCI_PMU_CNTR		0x004
-#define CCI_PMU_CNTR_CTRL	0x008
-#define CCI_PMU_OVRFLW		0x00c
-
-#define CCI_PMU_OVRFLW_FLAG	1
-
-#define CCI_PMU_CNTR_BASE(idx)	((idx) * SZ_4K)
-
-#define CCI_PMU_CNTR_MASK	((1ULL << 32) -1)
-
 /*
  * Instead of an event id to monitor CCI cycles, a dedicated counter is
  * provided. Use 0xff to represent CCI cycles and hope that no future revisions
@@ -109,12 +126,6 @@ enum cci400_perf_events {
 	CCI_PMU_CYCLES = 0xff
 };
 
-#define CCI_PMU_EVENT_MASK		0xff
-#define CCI_PMU_EVENT_SOURCE(event)	((event >> 5) & 0x7)
-#define CCI_PMU_EVENT_CODE(event)	(event & 0x1f)
-
-#define CCI_PMU_MAX_HW_EVENTS 5   /* CCI PMU has 4 counters + 1 cycle counter */
-
 #define CCI_PMU_CYCLE_CNTR_IDX		0
 #define CCI_PMU_CNTR0_IDX		1
 #define CCI_PMU_CNTR_LAST(cci_pmu)	(CCI_PMU_CYCLE_CNTR_IDX + cci_pmu->num_events - 1)
@@ -172,60 +183,6 @@ static char *const pmu_names[] = {
 	[CCI_REV_R1] = "CCI_400_r1",
 };
 
-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 {
-	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;
-	struct cci_pmu_hw_events hw_events;
-	struct platform_device *plat_device;
-	int num_events;
-	atomic_t active_events;
-	struct mutex reserve_mutex;
-	cpumask_t cpus;
-};
-static struct cci_pmu *pmu;
-
-#define to_cci_pmu(c)	(container_of(c, struct cci_pmu, pmu))
-
-static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
-{
-	int i;
-
-	for (i = 0; i < nr_irqs; i++)
-		if (irq == irqs[i])
-			return true;
-
-	return false;
-}
-
-static int probe_cci_revision(void)
-{
-	int rev;
-	rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK;
-	rev >>= CCI_PID2_REV_SHIFT;
-
-	if (rev < CCI_REV_R1_PX)
-		return CCI_REV_R0;
-	else
-		return CCI_REV_R1;
-}
-
-static struct pmu_port_event_ranges *port_range_by_rev(void)
-{
-	int rev = probe_cci_revision();
-
-	return &port_event_range[rev];
-}
-
 static int pmu_is_valid_slave_event(u8 ev_code)
 {
 	return pmu->port_ranges->slave_min <= ev_code &&
@@ -265,6 +222,25 @@ static int pmu_validate_hw_event(u8 hw_event)
 	return -ENOENT;
 }
 
+static int probe_cci_revision(void)
+{
+	int rev;
+	rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK;
+	rev >>= CCI_PID2_REV_SHIFT;
+
+	if (rev < CCI_REV_R1_PX)
+		return CCI_REV_R0;
+	else
+		return CCI_REV_R1;
+}
+
+static struct pmu_port_event_ranges *port_range_by_rev(void)
+{
+	int rev = probe_cci_revision();
+
+	return &port_event_range[rev];
+}
+
 static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
 {
 	return CCI_PMU_CYCLE_CNTR_IDX <= idx &&
@@ -893,6 +869,17 @@ static const struct of_device_id arm_cci_pmu_matches[] = {
 	{},
 };
 
+static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
+{
+	int i;
+
+	for (i = 0; i < nr_irqs; i++)
+		if (irq == irqs[i])
+			return true;
+
+	return false;
+}
+
 static int cci_pmu_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -963,8 +950,65 @@ static int cci_platform_probe(struct platform_device *pdev)
 	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
 }
 
+static struct platform_driver cci_pmu_driver = {
+	.driver = {
+		   .name = DRIVER_NAME_PMU,
+		   .of_match_table = arm_cci_pmu_matches,
+		  },
+	.probe = cci_pmu_probe,
+};
+
+static struct platform_driver cci_platform_driver = {
+	.driver = {
+		   .name = DRIVER_NAME,
+		   .of_match_table = arm_cci_matches,
+		  },
+	.probe = cci_platform_probe,
+};
+
+static int __init cci_platform_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&cci_pmu_driver);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&cci_platform_driver);
+}
+
+#else /* !CONFIG_HW_PERF_EVENTS */
+
+static int __init cci_platform_init(void)
+{
+	return 0;
+}
+
 #endif /* CONFIG_HW_PERF_EVENTS */
 
+#define CCI_PORT_CTRL		0x0
+#define CCI_CTRL_STATUS		0xc
+
+#define CCI_ENABLE_SNOOP_REQ	0x1
+#define CCI_ENABLE_DVM_REQ	0x2
+#define CCI_ENABLE_REQ		(CCI_ENABLE_SNOOP_REQ | CCI_ENABLE_DVM_REQ)
+
+enum cci_ace_port_type {
+	ACE_INVALID_PORT = 0x0,
+	ACE_PORT,
+	ACE_LITE_PORT,
+};
+
+struct cci_ace_port {
+	void __iomem *base;
+	unsigned long phys;
+	enum cci_ace_port_type type;
+	struct device_node *dn;
+};
+
+static struct cci_ace_port *ports;
+static unsigned int nb_cci_ports;
+
 struct cpu_port {
 	u64 mpidr;
 	u32 port;
@@ -1284,36 +1328,20 @@ int notrace __cci_control_port_by_index(u32 port, bool enable)
 }
 EXPORT_SYMBOL_GPL(__cci_control_port_by_index);
 
-static const struct cci_nb_ports cci400_ports = {
-	.nb_ace = 2,
-	.nb_ace_lite = 3
-};
-
-static const struct of_device_id arm_cci_matches[] = {
-	{.compatible = "arm,cci-400", .data = &cci400_ports },
-	{},
-};
-
 static const struct of_device_id arm_cci_ctrl_if_matches[] = {
 	{.compatible = "arm,cci-400-ctrl-if", },
 	{},
 };
 
-static int cci_probe(void)
+static int cci_probe_ports(struct device_node *np)
 {
 	struct cci_nb_ports const *cci_config;
 	int ret, i, nb_ace = 0, nb_ace_lite = 0;
-	struct device_node *np, *cp;
+	struct device_node *cp;
 	struct resource res;
 	const char *match_str;
 	bool is_ace;
 
-	np = of_find_matching_node(NULL, arm_cci_matches);
-	if (!np)
-		return -ENODEV;
-
-	if (!of_device_is_available(np))
-		return -ENODEV;
 
 	cci_config = of_match_node(arm_cci_matches, np)->data;
 	if (!cci_config)
@@ -1325,17 +1353,6 @@ static int cci_probe(void)
 	if (!ports)
 		return -ENOMEM;
 
-	ret = of_address_to_resource(np, 0, &res);
-	if (!ret) {
-		cci_ctrl_base = ioremap(res.start, resource_size(&res));
-		cci_ctrl_phys =	res.start;
-	}
-	if (ret || !cci_ctrl_base) {
-		WARN(1, "unable to ioremap CCI ctrl\n");
-		ret = -ENXIO;
-		goto memalloc_err;
-	}
-
 	for_each_child_of_node(np, cp) {
 		if (!of_match_node(arm_cci_ctrl_if_matches, cp))
 			continue;
@@ -1395,11 +1412,36 @@ static int cci_probe(void)
 	sync_cache_w(&cpu_port);
 	__sync_cache_range_w(ports, sizeof(*ports) * nb_cci_ports);
 	pr_info("ARM CCI driver probed\n");
+
 	return 0;
+}
+
+static int cci_probe(void)
+{
+	int ret;
+	struct device_node *np;
+	struct resource res;
+
+	np = of_find_matching_node(NULL, arm_cci_matches);
+	if (!np)
+		return -ENODEV;
 
-memalloc_err:
+	if (!of_device_is_available(np))
+		return -ENODEV;
+
+	ret = of_address_to_resource(np, 0, &res);
+	if (!ret) {
+		cci_ctrl_base = ioremap(res.start, resource_size(&res));
+		cci_ctrl_phys =	res.start;
+	}
+	if (ret || !cci_ctrl_base) {
+		WARN(1, "unable to ioremap CCI ctrl\n");
+		ret = -ENXIO;
+		goto out;
+	}
 
-	kfree(ports);
+	ret = cci_probe_ports(np);
+out:
 	return ret;
 }
 
@@ -1418,42 +1460,6 @@ static int cci_init(void)
 	return cci_init_status;
 }
 
-#ifdef CONFIG_HW_PERF_EVENTS
-static struct platform_driver cci_pmu_driver = {
-	.driver = {
-		   .name = DRIVER_NAME_PMU,
-		   .of_match_table = arm_cci_pmu_matches,
-		  },
-	.probe = cci_pmu_probe,
-};
-
-static struct platform_driver cci_platform_driver = {
-	.driver = {
-		   .name = DRIVER_NAME,
-		   .of_match_table = arm_cci_matches,
-		  },
-	.probe = cci_platform_probe,
-};
-
-static int __init cci_platform_init(void)
-{
-	int ret;
-
-	ret = platform_driver_register(&cci_pmu_driver);
-	if (ret)
-		return ret;
-
-	return platform_driver_register(&cci_platform_driver);
-}
-
-#else
-
-static int __init cci_platform_init(void)
-{
-	return 0;
-}
-
-#endif
 /*
  * To sort out early init calls ordering a helper function is provided to
  * check if the CCI driver has beed initialized. Function check if the driver
-- 
1.7.9.5



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] arm-cci: Get rid of secure transactions for PMU driver
  2015-02-24 13:17 [PATCH 0/4] arm-cci400: PMU monitoring support on ARM64 Suzuki K. Poulose
  2015-02-24 13:17 ` [PATCH 1/4] arm-cci: Rearrange code for splitting PMU vs driver code Suzuki K. Poulose
@ 2015-02-24 13:17 ` Suzuki K. Poulose
  2015-02-24 21:53   ` Nicolas Pitre
  2015-02-24 13:17 ` [PATCH 3/4] arm-cci: Split the code for PMU vs driver support Suzuki K. Poulose
  2015-02-24 13:17 ` [PATCH 4/4] arm-cci: Fix CCI PMU event validation Suzuki K. Poulose
  3 siblings, 1 reply; 10+ messages in thread
From: Suzuki K. Poulose @ 2015-02-24 13:17 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Nicolas Pitre, Bartlomiej Zolnierkiewicz, Kukjin Kim,
	Abhilash Kesavan, Arnd Bergmann, devicetree, linux-kernel,
	Liviu Dudau, Lorenzo Pieralisi, Olof Johansson, Pawel Moll,
	Punit Agrawal, Sudeep Holla, Will Deacon, Catalin Marinas,
	Suzuki K. Poulose

From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>

Avoid secure transactions while probing the CCI PMU. The
existing code makes use of the Peripheral ID2 (PID2) register
to determine the revision of the CCI400, which requires a
secure transaction. This puts a limitation on the usage of the
driver on systems running non-secure Linux(e.g, ARM64).

Updated the device-tree binding for cci pmu node to add the explicit
revision number for the compatible field.

The supported strings are :
	arm,cci-400-pmu,r0
	arm,cci-400-pmu,r1
	arm,cci-400-pmu - DEPRECATED. See NOTE below

NOTE: If the revision is not mentioned, we need to probe the cci revision,
which could be fatal on a platform running non-secure. We need a reliable way
to know if we can poke the CCI registers at runtime on ARM32. We depend on
'mcpm_is_available()' when it is available. mcpm_is_available() returns true
only when there is a registered driver for mcpm. Otherwise, we assume that we
don't have secure access, and skips probing the revision number(ARM64 case).

The MCPM should figure out if it is safe to access the CCI. Unfortunately
there isn't a reliable way to indicate the same via dtb. This patch doesn't
address/change the current situation. It only deals with the CCI-PMU, leaving
the assumptions about the secure access as it has been, prior to this patch.

Cc: devicetree@vger.kernel.org
Cc: Punit Agrawal <punit.agrawal@arm.com>
Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
---
 Documentation/devicetree/bindings/arm/cci.txt |    7 +-
 arch/arm/include/asm/arm-cci.h                |   42 ++++++++
 arch/arm64/include/asm/arm-cci.h              |   27 +++++
 drivers/bus/arm-cci.c                         |  138 ++++++++++++++++---------
 include/linux/arm-cci.h                       |    2 +
 5 files changed, 166 insertions(+), 50 deletions(-)
 create mode 100644 arch/arm/include/asm/arm-cci.h
 create mode 100644 arch/arm64/include/asm/arm-cci.h

diff --git a/Documentation/devicetree/bindings/arm/cci.txt b/Documentation/devicetree/bindings/arm/cci.txt
index f28d82b..0e4b6a7 100644
--- a/Documentation/devicetree/bindings/arm/cci.txt
+++ b/Documentation/devicetree/bindings/arm/cci.txt
@@ -94,8 +94,11 @@ specific to ARM.
 		- compatible
 			Usage: required
 			Value type: <string>
-			Definition: must be "arm,cci-400-pmu"
-
+			Definition: Supported strings are :
+				 "arm,cci-400-pmu,r0"
+				 "arm,cci-400-pmu,r1"
+				 "arm,cci-400-pmu"  - DEPRECATED, permitted only where OS has
+						      secure acces to CCI registers
 		- reg:
 			Usage: required
 			Value type: Integer cells. A register entry, expressed
diff --git a/arch/arm/include/asm/arm-cci.h b/arch/arm/include/asm/arm-cci.h
new file mode 100644
index 0000000..b828d7a
--- /dev/null
+++ b/arch/arm/include/asm/arm-cci.h
@@ -0,0 +1,42 @@
+/*
+ * arch/arm/include/asm/arm-cci.h
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_ARM_CCI_H
+#define __ASM_ARM_CCI_H
+
+#ifdef CONFIG_MCPM
+#include <asm/mcpm.h>
+
+/*
+ * We don't have a reliable way of detecting, whether
+ * we have access to secure-only registers, unless
+ * mcpm is registered.
+ */
+static inline int platform_has_secure_cci_access(void)
+{
+	return mcpm_is_available();
+}
+
+#else
+static inline int platform_has_secure_cci_access(void)
+{
+	return 0;
+}
+#endif
+
+#endif
diff --git a/arch/arm64/include/asm/arm-cci.h b/arch/arm64/include/asm/arm-cci.h
new file mode 100644
index 0000000..37bbe37
--- /dev/null
+++ b/arch/arm64/include/asm/arm-cci.h
@@ -0,0 +1,27 @@
+/*
+ * arch/arm64/include/asm/arm-cci.h
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_ARM_CCI_H
+#define __ASM_ARM_CCI_H
+
+static inline int platform_has_secure_cci_access(void)
+{
+	return 0;
+}
+
+#endif
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index f27cf56..fe9fa46 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,11 @@ 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];
+	if (platform_has_secure_cci_access())
+		return &cci_pmu_models[probe_cci_revision()];
+	return NULL;
 }
 
 static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
@@ -807,9 +795,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,13 +850,65 @@ 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",
+		.data	= NULL,
+	},
+	{
+		.compatible = "arm,cci-400-pmu,r0",
+		.data	= &cci_pmu_models[CCI_REV_R0],
+	},
+	{
+		.compatible = "arm,cci-400-pmu,r1",
+		.data	= &cci_pmu_models[CCI_REV_R1],
 	},
 	{},
 };
 
+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;
+	if (match->data)
+		return match->data;
+
+	dev_warn(&pdev->dev, "DEPERCATED compatible property,"
+			 "requires secure access to CCI registers");
+	return probe_cci_model(pdev);
+}
+
 static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
 {
 	int i;
@@ -884,11 +924,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 -EINVAL;
+	}
 
 	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 +968,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);
diff --git a/include/linux/arm-cci.h b/include/linux/arm-cci.h
index 79d6edf..aede5c7 100644
--- a/include/linux/arm-cci.h
+++ b/include/linux/arm-cci.h
@@ -24,6 +24,8 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 
+#include <asm/arm-cci.h>
+
 struct device_node;
 
 #ifdef CONFIG_ARM_CCI
-- 
1.7.9.5



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] arm-cci: Split the code for PMU vs driver support
  2015-02-24 13:17 [PATCH 0/4] arm-cci400: PMU monitoring support on ARM64 Suzuki K. Poulose
  2015-02-24 13:17 ` [PATCH 1/4] arm-cci: Rearrange code for splitting PMU vs driver code Suzuki K. Poulose
  2015-02-24 13:17 ` [PATCH 2/4] arm-cci: Get rid of secure transactions for PMU driver Suzuki K. Poulose
@ 2015-02-24 13:17 ` Suzuki K. Poulose
  2015-02-24 22:17   ` Nicolas Pitre
  2015-02-24 13:17 ` [PATCH 4/4] arm-cci: Fix CCI PMU event validation Suzuki K. Poulose
  3 siblings, 1 reply; 10+ messages in thread
From: Suzuki K. Poulose @ 2015-02-24 13:17 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Nicolas Pitre, Bartlomiej Zolnierkiewicz, Kukjin Kim,
	Abhilash Kesavan, Arnd Bergmann, devicetree, linux-kernel,
	Liviu Dudau, Lorenzo Pieralisi, Olof Johansson, Pawel Moll,
	Punit Agrawal, Sudeep Holla, Will Deacon, Catalin Marinas,
	Suzuki K. Poulose

From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>

This patch separates the PMU driver code from the low level
CCI driver code, and enables the CCI400-PMU for ARM64.

Introduces config options for both.

 - ARM_CCI400_MCPM	- controls the low level MCPM driver code for CCI
 - ARM_CCI400_PMU	- controls the PMU driver code
 - ARM_CCI400_COMMON	- CCI400 specific details shared by MCPM
			  and PMU
Changes:
 - ARM_CCI 		- common code for probing the CCI devices

Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Cc: Kukjin Kim <kgene@kernel.org>
Cc: Abhilash Kesavan <a.kesavan@samsung.com>
Cc: Liviu Dudau <liviu.dudau@arm.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
---
 arch/arm/mach-exynos/Kconfig   |    2 +-
 arch/arm/mach-vexpress/Kconfig |    4 ++--
 drivers/bus/Kconfig            |   28 +++++++++++++++++++++++-----
 drivers/bus/arm-cci.c          |   25 +++++++++++++++++++++----
 include/linux/arm-cci.h        |    7 ++++++-
 5 files changed, 53 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 603820e..9bc8b4d 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -123,7 +123,7 @@ config SOC_EXYNOS5800
 config EXYNOS5420_MCPM
 	bool "Exynos5420 Multi-Cluster PM support"
 	depends on MCPM && SOC_EXYNOS5420
-	select ARM_CCI
+	select ARM_CCI400_MCPM
 	select ARM_CPU_SUSPEND
 	help
 	  This is needed to provide CPU and cluster power management
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index d6b16d9..097912f 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -53,7 +53,7 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
 config ARCH_VEXPRESS_DCSCB
 	bool "Dual Cluster System Control Block (DCSCB) support"
 	depends on MCPM
-	select ARM_CCI
+	select ARM_CCI400_MCPM
 	help
 	  Support for the Dual Cluster System Configuration Block (DCSCB).
 	  This is needed to provide CPU and cluster power management
@@ -71,7 +71,7 @@ config ARCH_VEXPRESS_SPC
 config ARCH_VEXPRESS_TC2_PM
 	bool "Versatile Express TC2 power management"
 	depends on MCPM
-	select ARM_CCI
+	select ARM_CCI400_MCPM
 	select ARCH_VEXPRESS_SPC
 	help
 	  Support for CPU and cluster power management on Versatile Express
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index b99729e..91dd013 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -43,12 +43,30 @@ config OMAP_INTERCONNECT
 	help
 	  Driver to enable OMAP interconnect error handling driver.
 
-config ARM_CCI
-	bool "ARM CCI driver support"
-	depends on ARM && OF && CPU_V7
+config ARM_CCI400_MCPM
+	bool
+	depends on ARM && OF && CPU_V7 && MCPM
+	help
+	  Low level power management driver for CCI400 cache coherent
+	  interconnect for ARM platforms.
+
+config ARM_CCI400_PMU
+	bool "ARM CCI400 PMU support"
+	depends on ARM || ARM64
+	depends on HW_PERF_EVENTS
+	select ARM_CCI400_COMMON
 	help
-	  Driver supporting the CCI cache coherent interconnect for ARM
-	  platforms.
+	  Support for PMU events monitoring on the ARM CCI cache coherent
+	  interconnect.
+
+	  If unsure, say N
+
+config ARM_CCI400_COMMON
+	bool
+	select ARM_CCI
+
+config ARM_CCI
+	bool
 
 config ARM_CCN
 	bool "ARM CCN driver support"
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index fe9fa46..7e330fe 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -32,6 +32,7 @@
 static void __iomem *cci_ctrl_base;
 static unsigned long cci_ctrl_phys;
 
+#ifdef CONFIG_ARM_CCI400_MCPM
 struct cci_nb_ports {
 	unsigned int nb_ace;
 	unsigned int nb_ace_lite;
@@ -42,12 +43,19 @@ static const struct cci_nb_ports cci400_ports = {
 	.nb_ace_lite = 3
 };
 
+#define CCI400_MCPM_PORTS_DATA	(&cci400_ports)
+#else
+#define CCI400_MCPM_PORTS_DATA	(NULL)
+#endif
+
 static const struct of_device_id arm_cci_matches[] = {
-	{.compatible = "arm,cci-400", .data = &cci400_ports },
+#ifdef CONFIG_ARM_CCI400_COMMON
+	{.compatible = "arm,cci-400", .data = CCI400_MCPM_PORTS_DATA },
+#endif
 	{},
 };
 
-#ifdef CONFIG_HW_PERF_EVENTS
+#ifdef CONFIG_ARM_CCI400_PMU
 
 #define DRIVER_NAME		"CCI-400"
 #define DRIVER_NAME_PMU		DRIVER_NAME " PMU"
@@ -981,6 +989,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;
 }
 
@@ -1019,14 +1028,16 @@ static int __init cci_platform_init(void)
 	return platform_driver_register(&cci_platform_driver);
 }
 
-#else /* !CONFIG_HW_PERF_EVENTS */
+#else /* !CONFIG_ARM_CCI400_PMU */
 
 static int __init cci_platform_init(void)
 {
 	return 0;
 }
 
-#endif /* CONFIG_HW_PERF_EVENTS */
+#endif /* CONFIG_ARM_CCI400_PMU */
+
+#ifdef CONFIG_ARM_CCI400_MCPM
 
 #define CCI_PORT_CTRL		0x0
 #define CCI_CTRL_STATUS		0xc
@@ -1457,6 +1468,12 @@ static int cci_probe_ports(struct device_node *np)
 
 	return 0;
 }
+#else /* !CONFIG_ARM_CCI400_MCPM */
+static inline int cci_probe_ports(struct device_node *np)
+{
+	return 0;
+}
+#endif /* CONFIG_ARM_CCI400_MCPM */
 
 static int cci_probe(void)
 {
diff --git a/include/linux/arm-cci.h b/include/linux/arm-cci.h
index aede5c7..77d06f5 100644
--- a/include/linux/arm-cci.h
+++ b/include/linux/arm-cci.h
@@ -30,12 +30,16 @@ struct device_node;
 
 #ifdef CONFIG_ARM_CCI
 extern bool cci_probed(void);
+#else
+static inline bool cci_probed(void) { return false; }
+#endif
+
+#ifdef CONFIG_ARM_CCI400_MCPM
 extern int cci_ace_get_port(struct device_node *dn);
 extern int cci_disable_port_by_cpu(u64 mpidr);
 extern int __cci_control_port_by_device(struct device_node *dn, bool enable);
 extern int __cci_control_port_by_index(u32 port, bool enable);
 #else
-static inline bool cci_probed(void) { return false; }
 static inline int cci_ace_get_port(struct device_node *dn)
 {
 	return -ENODEV;
@@ -51,6 +55,7 @@ static inline int __cci_control_port_by_index(u32 port, bool enable)
 	return -ENODEV;
 }
 #endif
+
 #define cci_disable_port_by_device(dev) \
 	__cci_control_port_by_device(dev, false)
 #define cci_enable_port_by_device(dev) \
-- 
1.7.9.5



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] arm-cci: Fix CCI PMU event validation
  2015-02-24 13:17 [PATCH 0/4] arm-cci400: PMU monitoring support on ARM64 Suzuki K. Poulose
                   ` (2 preceding siblings ...)
  2015-02-24 13:17 ` [PATCH 3/4] arm-cci: Split the code for PMU vs driver support Suzuki K. Poulose
@ 2015-02-24 13:17 ` Suzuki K. Poulose
  3 siblings, 0 replies; 10+ messages in thread
From: Suzuki K. Poulose @ 2015-02-24 13:17 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Nicolas Pitre, Bartlomiej Zolnierkiewicz, Kukjin Kim,
	Abhilash Kesavan, Arnd Bergmann, devicetree, linux-kernel,
	Liviu Dudau, Lorenzo Pieralisi, Olof Johansson, Pawel Moll,
	Punit Agrawal, Sudeep Holla, Will Deacon, Catalin Marinas,
	Suzuki K. Poulose

From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>

We mask the event with the CCI_PMU_EVENT_MASK, before passing
the config to pmu_validate_hw_event(), which causes extra bits
to be ignored and qualifies an invalid event code as valid.

e.g,
 $ perf stat -a -C 0 -e CCI_400/config=0x1ff,name=cycles/ sleep 1
   Performance counter stats for 'system wide':

         506951142      cycles

       1.013879626 seconds time elapsed

where, cycles has an event coding of 0xff. This patch also removes
the unnecessary 'event' mask in pmu_write_register, since the config_base
is set by the pmu code after the event is validated.

Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
---
 drivers/bus/arm-cci.c |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 7e330fe..b0ee582 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -191,11 +191,14 @@ static int pmu_is_valid_master_event(u8 ev_code)
 		ev_code <= pmu->model->event_ranges[CCI_IF_MASTER].max;
 }
 
-static int pmu_validate_hw_event(u8 hw_event)
+static int pmu_validate_hw_event(u32 hw_event)
 {
 	u8 ev_source = CCI_PMU_EVENT_SOURCE(hw_event);
 	u8 ev_code = CCI_PMU_EVENT_CODE(hw_event);
 
+	if (hw_event & ~CCI_PMU_EVENT_MASK)
+		return -ENOENT;
+
 	switch (ev_source) {
 	case CCI_PORT_S0:
 	case CCI_PORT_S1:
@@ -265,7 +268,6 @@ static void pmu_enable_counter(int idx)
 
 static void pmu_set_event(int idx, unsigned long event)
 {
-	event &= CCI_PMU_EVENT_MASK;
 	pmu_write_register(event, idx, CCI_PMU_EVT_SEL);
 }
 
@@ -282,7 +284,7 @@ static int pmu_get_event_idx(struct cci_pmu_hw_events *hw, struct perf_event *ev
 {
 	struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
 	struct hw_perf_event *hw_event = &event->hw;
-	unsigned long cci_event = hw_event->config_base & CCI_PMU_EVENT_MASK;
+	unsigned long cci_event = hw_event->config_base;
 	int idx;
 
 	if (cci_event == CCI_PMU_CYCLES) {
@@ -303,7 +305,7 @@ static int pmu_get_event_idx(struct cci_pmu_hw_events *hw, struct perf_event *ev
 static int pmu_map_event(struct perf_event *event)
 {
 	int mapping;
-	u8 config = event->attr.config & CCI_PMU_EVENT_MASK;
+	u32 config = event->attr.config;
 
 	if (event->attr.type < PERF_TYPE_MAX)
 		return -ENOENT;
-- 
1.7.9.5



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] arm-cci: Get rid of secure transactions for PMU driver
  2015-02-24 13:17 ` [PATCH 2/4] arm-cci: Get rid of secure transactions for PMU driver Suzuki K. Poulose
@ 2015-02-24 21:53   ` Nicolas Pitre
  2015-02-25 10:20     ` Suzuki K. Poulose
  0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Pitre @ 2015-02-24 21:53 UTC (permalink / raw)
  To: Suzuki K. Poulose
  Cc: linux-arm-kernel, Bartlomiej Zolnierkiewicz, Kukjin Kim,
	Abhilash Kesavan, Arnd Bergmann, devicetree, linux-kernel,
	Liviu Dudau, Lorenzo Pieralisi, Olof Johansson, Pawel Moll,
	Punit Agrawal, Sudeep Holla, Will Deacon, Catalin Marinas

On Tue, 24 Feb 2015, Suzuki K. Poulose wrote:

> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
> 
> Avoid secure transactions while probing the CCI PMU. The
> existing code makes use of the Peripheral ID2 (PID2) register
> to determine the revision of the CCI400, which requires a
> secure transaction. This puts a limitation on the usage of the
> driver on systems running non-secure Linux(e.g, ARM64).
> 
> Updated the device-tree binding for cci pmu node to add the explicit
> revision number for the compatible field.
> 
> The supported strings are :
> 	arm,cci-400-pmu,r0
> 	arm,cci-400-pmu,r1
> 	arm,cci-400-pmu - DEPRECATED. See NOTE below
> 
> NOTE: If the revision is not mentioned, we need to probe the cci revision,
> which could be fatal on a platform running non-secure. We need a reliable way
> to know if we can poke the CCI registers at runtime on ARM32. We depend on
> 'mcpm_is_available()' when it is available. mcpm_is_available() returns true
> only when there is a registered driver for mcpm. Otherwise, we assume that we
> don't have secure access, and skips probing the revision number(ARM64 case).
> 
> The MCPM should figure out if it is safe to access the CCI. Unfortunately
> there isn't a reliable way to indicate the same via dtb. This patch doesn't
> address/change the current situation. It only deals with the CCI-PMU, leaving
> the assumptions about the secure access as it has been, prior to this patch.

This is an extensive commit log about secure access issues which is nice 
and appreciated.  However the patch does quite some more code reorg not 
mentioned here.  Could you please move this code reorg to a separate 
patch and then have a patch on top introducing these probing changes?  
This should make the implication of what is said above clearer.

> Cc: devicetree@vger.kernel.org
> Cc: Punit Agrawal <punit.agrawal@arm.com>
> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
> ---
>  Documentation/devicetree/bindings/arm/cci.txt |    7 +-
>  arch/arm/include/asm/arm-cci.h                |   42 ++++++++
>  arch/arm64/include/asm/arm-cci.h              |   27 +++++
>  drivers/bus/arm-cci.c                         |  138 ++++++++++++++++---------
>  include/linux/arm-cci.h                       |    2 +
>  5 files changed, 166 insertions(+), 50 deletions(-)
>  create mode 100644 arch/arm/include/asm/arm-cci.h
>  create mode 100644 arch/arm64/include/asm/arm-cci.h
> 
> diff --git a/Documentation/devicetree/bindings/arm/cci.txt b/Documentation/devicetree/bindings/arm/cci.txt
> index f28d82b..0e4b6a7 100644
> --- a/Documentation/devicetree/bindings/arm/cci.txt
> +++ b/Documentation/devicetree/bindings/arm/cci.txt
> @@ -94,8 +94,11 @@ specific to ARM.
>  		- compatible
>  			Usage: required
>  			Value type: <string>
> -			Definition: must be "arm,cci-400-pmu"
> -
> +			Definition: Supported strings are :
> +				 "arm,cci-400-pmu,r0"
> +				 "arm,cci-400-pmu,r1"
> +				 "arm,cci-400-pmu"  - DEPRECATED, permitted only where OS has
> +						      secure acces to CCI registers
>  		- reg:
>  			Usage: required
>  			Value type: Integer cells. A register entry, expressed
> diff --git a/arch/arm/include/asm/arm-cci.h b/arch/arm/include/asm/arm-cci.h
> new file mode 100644
> index 0000000..b828d7a
> --- /dev/null
> +++ b/arch/arm/include/asm/arm-cci.h
> @@ -0,0 +1,42 @@
> +/*
> + * arch/arm/include/asm/arm-cci.h
> + *
> + * Copyright (C) 2015 ARM Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __ASM_ARM_CCI_H
> +#define __ASM_ARM_CCI_H
> +
> +#ifdef CONFIG_MCPM
> +#include <asm/mcpm.h>
> +
> +/*
> + * We don't have a reliable way of detecting, whether
> + * we have access to secure-only registers, unless
> + * mcpm is registered.
> + */
> +static inline int platform_has_secure_cci_access(void)
> +{
> +	return mcpm_is_available();
> +}
> +
> +#else
> +static inline int platform_has_secure_cci_access(void)
> +{
> +	return 0;
> +}
> +#endif
> +
> +#endif
> diff --git a/arch/arm64/include/asm/arm-cci.h b/arch/arm64/include/asm/arm-cci.h
> new file mode 100644
> index 0000000..37bbe37
> --- /dev/null
> +++ b/arch/arm64/include/asm/arm-cci.h
> @@ -0,0 +1,27 @@
> +/*
> + * arch/arm64/include/asm/arm-cci.h
> + *
> + * Copyright (C) 2015 ARM Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __ASM_ARM_CCI_H
> +#define __ASM_ARM_CCI_H
> +
> +static inline int platform_has_secure_cci_access(void)
> +{
> +	return 0;
> +}
> +
> +#endif
> diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
> index f27cf56..fe9fa46 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,11 @@ 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];
> +	if (platform_has_secure_cci_access())
> +		return &cci_pmu_models[probe_cci_revision()];
> +	return NULL;
>  }
>  
>  static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
> @@ -807,9 +795,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,13 +850,65 @@ 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",
> +		.data	= NULL,
> +	},
> +	{
> +		.compatible = "arm,cci-400-pmu,r0",
> +		.data	= &cci_pmu_models[CCI_REV_R0],
> +	},
> +	{
> +		.compatible = "arm,cci-400-pmu,r1",
> +		.data	= &cci_pmu_models[CCI_REV_R1],
>  	},
>  	{},
>  };
>  
> +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;
> +	if (match->data)
> +		return match->data;
> +
> +	dev_warn(&pdev->dev, "DEPERCATED compatible property,"
> +			 "requires secure access to CCI registers");
> +	return probe_cci_model(pdev);
> +}
> +
>  static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
>  {
>  	int i;
> @@ -884,11 +924,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 -EINVAL;
> +	}
>  
>  	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 +968,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);
> diff --git a/include/linux/arm-cci.h b/include/linux/arm-cci.h
> index 79d6edf..aede5c7 100644
> --- a/include/linux/arm-cci.h
> +++ b/include/linux/arm-cci.h
> @@ -24,6 +24,8 @@
>  #include <linux/errno.h>
>  #include <linux/types.h>
>  
> +#include <asm/arm-cci.h>
> +
>  struct device_node;
>  
>  #ifdef CONFIG_ARM_CCI
> -- 
> 1.7.9.5
> 
> 
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/4] arm-cci: Split the code for PMU vs driver support
  2015-02-24 13:17 ` [PATCH 3/4] arm-cci: Split the code for PMU vs driver support Suzuki K. Poulose
@ 2015-02-24 22:17   ` Nicolas Pitre
  2015-02-25 10:26     ` Suzuki K. Poulose
  0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Pitre @ 2015-02-24 22:17 UTC (permalink / raw)
  To: Suzuki K. Poulose
  Cc: linux-arm-kernel, Bartlomiej Zolnierkiewicz, Kukjin Kim,
	Abhilash Kesavan, Arnd Bergmann, devicetree, linux-kernel,
	Liviu Dudau, Lorenzo Pieralisi, Olof Johansson, Pawel Moll,
	Punit Agrawal, Sudeep Holla, Will Deacon, Catalin Marinas

On Tue, 24 Feb 2015, Suzuki K. Poulose wrote:

> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
> 
> This patch separates the PMU driver code from the low level
> CCI driver code, and enables the CCI400-PMU for ARM64.
> 
> Introduces config options for both.
> 
>  - ARM_CCI400_MCPM	- controls the low level MCPM driver code for CCI
>  - ARM_CCI400_PMU	- controls the PMU driver code
>  - ARM_CCI400_COMMON	- CCI400 specific details shared by MCPM
> 			  and PMU
> Changes:
>  - ARM_CCI 		- common code for probing the CCI devices
> 
> Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Cc: Kukjin Kim <kgene@kernel.org>
> Cc: Abhilash Kesavan <a.kesavan@samsung.com>
> Cc: Liviu Dudau <liviu.dudau@arm.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Sudeep Holla <sudeep.holla@arm.com>
> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>

Comments inline.

> ---
>  arch/arm/mach-exynos/Kconfig   |    2 +-
>  arch/arm/mach-vexpress/Kconfig |    4 ++--
>  drivers/bus/Kconfig            |   28 +++++++++++++++++++++++-----
>  drivers/bus/arm-cci.c          |   25 +++++++++++++++++++++----
>  include/linux/arm-cci.h        |    7 ++++++-
>  5 files changed, 53 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
> index 603820e..9bc8b4d 100644
> --- a/arch/arm/mach-exynos/Kconfig
> +++ b/arch/arm/mach-exynos/Kconfig
> @@ -123,7 +123,7 @@ config SOC_EXYNOS5800
>  config EXYNOS5420_MCPM
>  	bool "Exynos5420 Multi-Cluster PM support"
>  	depends on MCPM && SOC_EXYNOS5420
> -	select ARM_CCI
> +	select ARM_CCI400_MCPM
>  	select ARM_CPU_SUSPEND
>  	help
>  	  This is needed to provide CPU and cluster power management
> diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
> index d6b16d9..097912f 100644
> --- a/arch/arm/mach-vexpress/Kconfig
> +++ b/arch/arm/mach-vexpress/Kconfig
> @@ -53,7 +53,7 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
>  config ARCH_VEXPRESS_DCSCB
>  	bool "Dual Cluster System Control Block (DCSCB) support"
>  	depends on MCPM
> -	select ARM_CCI
> +	select ARM_CCI400_MCPM
>  	help
>  	  Support for the Dual Cluster System Configuration Block (DCSCB).
>  	  This is needed to provide CPU and cluster power management
> @@ -71,7 +71,7 @@ config ARCH_VEXPRESS_SPC
>  config ARCH_VEXPRESS_TC2_PM
>  	bool "Versatile Express TC2 power management"
>  	depends on MCPM
> -	select ARM_CCI
> +	select ARM_CCI400_MCPM
>  	select ARCH_VEXPRESS_SPC
>  	help
>  	  Support for CPU and cluster power management on Versatile Express
> diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
> index b99729e..91dd013 100644
> --- a/drivers/bus/Kconfig
> +++ b/drivers/bus/Kconfig
> @@ -43,12 +43,30 @@ config OMAP_INTERCONNECT
>  	help
>  	  Driver to enable OMAP interconnect error handling driver.
>  
> -config ARM_CCI
> -	bool "ARM CCI driver support"
> -	depends on ARM && OF && CPU_V7
> +config ARM_CCI400_MCPM
> +	bool
> +	depends on ARM && OF && CPU_V7 && MCPM

MCPM is not an actual dependency and therefore should probably not be 
added here.  You removed the prompt string therefore this will only be 
selectable explicitly as needed.

Also, shouldn't it select ARM_CCI400_COMMON ?

> +	help
> +	  Low level power management driver for CCI400 cache coherent
> +	  interconnect for ARM platforms.
> +
> +config ARM_CCI400_PMU
> +	bool "ARM CCI400 PMU support"
> +	depends on ARM || ARM64
> +	depends on HW_PERF_EVENTS
> +	select ARM_CCI400_COMMON
>  	help
> -	  Driver supporting the CCI cache coherent interconnect for ARM
> -	  platforms.
> +	  Support for PMU events monitoring on the ARM CCI cache coherent
> +	  interconnect.
> +
> +	  If unsure, say N
> +
> +config ARM_CCI400_COMMON
> +	bool
> +	select ARM_CCI
> +
> +config ARM_CCI
> +	bool

Surely you could do with only one of ARM_CCI or ARM_CCI400_COMMON?  
Personally I'd go with the later as it is more precise.

>  config ARM_CCN
>  	bool "ARM CCN driver support"
> diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
> index fe9fa46..7e330fe 100644
> --- a/drivers/bus/arm-cci.c
> +++ b/drivers/bus/arm-cci.c
> @@ -32,6 +32,7 @@
>  static void __iomem *cci_ctrl_base;
>  static unsigned long cci_ctrl_phys;
>  
> +#ifdef CONFIG_ARM_CCI400_MCPM
>  struct cci_nb_ports {
>  	unsigned int nb_ace;
>  	unsigned int nb_ace_lite;
> @@ -42,12 +43,19 @@ static const struct cci_nb_ports cci400_ports = {
>  	.nb_ace_lite = 3
>  };
>  
> +#define CCI400_MCPM_PORTS_DATA	(&cci400_ports)

I'm a bit uneasy with the conflation of MCPM in here.  Sure (most) MCPM 
backends are the only users of this code, but that doesn't mean MCPM has 
to have exclusive access.  Having "MCPM" entranched into the code and 
config symbols like that is misrepresenting this code somewhat.

> +#else
> +#define CCI400_MCPM_PORTS_DATA	(NULL)
> +#endif
> +
>  static const struct of_device_id arm_cci_matches[] = {
> -	{.compatible = "arm,cci-400", .data = &cci400_ports },
> +#ifdef CONFIG_ARM_CCI400_COMMON
> +	{.compatible = "arm,cci-400", .data = CCI400_MCPM_PORTS_DATA },
> +#endif
>  	{},
>  };
>  
> -#ifdef CONFIG_HW_PERF_EVENTS
> +#ifdef CONFIG_ARM_CCI400_PMU
>  
>  #define DRIVER_NAME		"CCI-400"
>  #define DRIVER_NAME_PMU		DRIVER_NAME " PMU"
> @@ -981,6 +989,7 @@ static int cci_pmu_probe(struct platform_device *pdev)
>  	if (ret)
>  		return ret;
>  
> +	pr_info("ARM %s PMU driver probed", pmu->model->name);

Wouldn't this addition fit better in one of the previous patches?

>  	return 0;
>  }
>  
> @@ -1019,14 +1028,16 @@ static int __init cci_platform_init(void)
>  	return platform_driver_register(&cci_platform_driver);
>  }
>  
> -#else /* !CONFIG_HW_PERF_EVENTS */
> +#else /* !CONFIG_ARM_CCI400_PMU */
>  
>  static int __init cci_platform_init(void)
>  {
>  	return 0;
>  }
>  
> -#endif /* CONFIG_HW_PERF_EVENTS */
> +#endif /* CONFIG_ARM_CCI400_PMU */
> +
> +#ifdef CONFIG_ARM_CCI400_MCPM
>  
>  #define CCI_PORT_CTRL		0x0
>  #define CCI_CTRL_STATUS		0xc
> @@ -1457,6 +1468,12 @@ static int cci_probe_ports(struct device_node *np)
>  
>  	return 0;
>  }
> +#else /* !CONFIG_ARM_CCI400_MCPM */
> +static inline int cci_probe_ports(struct device_node *np)
> +{
> +	return 0;
> +}
> +#endif /* CONFIG_ARM_CCI400_MCPM */
>  
>  static int cci_probe(void)
>  {
> diff --git a/include/linux/arm-cci.h b/include/linux/arm-cci.h
> index aede5c7..77d06f5 100644
> --- a/include/linux/arm-cci.h
> +++ b/include/linux/arm-cci.h
> @@ -30,12 +30,16 @@ struct device_node;
>  
>  #ifdef CONFIG_ARM_CCI
>  extern bool cci_probed(void);
> +#else
> +static inline bool cci_probed(void) { return false; }
> +#endif
> +
> +#ifdef CONFIG_ARM_CCI400_MCPM
>  extern int cci_ace_get_port(struct device_node *dn);
>  extern int cci_disable_port_by_cpu(u64 mpidr);
>  extern int __cci_control_port_by_device(struct device_node *dn, bool enable);
>  extern int __cci_control_port_by_index(u32 port, bool enable);
>  #else
> -static inline bool cci_probed(void) { return false; }
>  static inline int cci_ace_get_port(struct device_node *dn)
>  {
>  	return -ENODEV;
> @@ -51,6 +55,7 @@ static inline int __cci_control_port_by_index(u32 port, bool enable)
>  	return -ENODEV;
>  }
>  #endif
> +
>  #define cci_disable_port_by_device(dev) \
>  	__cci_control_port_by_device(dev, false)
>  #define cci_enable_port_by_device(dev) \
> -- 
> 1.7.9.5
> 
> 
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] arm-cci: Get rid of secure transactions for PMU driver
  2015-02-24 21:53   ` Nicolas Pitre
@ 2015-02-25 10:20     ` Suzuki K. Poulose
  0 siblings, 0 replies; 10+ messages in thread
From: Suzuki K. Poulose @ 2015-02-25 10:20 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: linux-arm-kernel, Bartlomiej Zolnierkiewicz, Kukjin Kim,
	Abhilash Kesavan, Arnd Bergmann, devicetree, linux-kernel,
	Liviu Dudau, Lorenzo Pieralisi, Olof Johansson, Pawel Moll,
	Punit Agrawal, Sudeep Holla, Will Deacon, Catalin Marinas

On 24/02/15 21:53, Nicolas Pitre wrote:
> On Tue, 24 Feb 2015, Suzuki K. Poulose wrote:
>
>> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
>>
>> Avoid secure transactions while probing the CCI PMU. The
>> existing code makes use of the Peripheral ID2 (PID2) register
>> to determine the revision of the CCI400, which requires a
>> secure transaction. This puts a limitation on the usage of the
>> driver on systems running non-secure Linux(e.g, ARM64).
>>
>> Updated the device-tree binding for cci pmu node to add the explicit
>> revision number for the compatible field.
>>
>> The supported strings are :
>>        arm,cci-400-pmu,r0
>>        arm,cci-400-pmu,r1
>>        arm,cci-400-pmu - DEPRECATED. See NOTE below
>>
>> NOTE: If the revision is not mentioned, we need to probe the cci revision,
>> which could be fatal on a platform running non-secure. We need a reliable way
>> to know if we can poke the CCI registers at runtime on ARM32. We depend on
>> 'mcpm_is_available()' when it is available. mcpm_is_available() returns true
>> only when there is a registered driver for mcpm. Otherwise, we assume that we
>> don't have secure access, and skips probing the revision number(ARM64 case).
>>
>> The MCPM should figure out if it is safe to access the CCI. Unfortunately
>> there isn't a reliable way to indicate the same via dtb. This patch doesn't
>> address/change the current situation. It only deals with the CCI-PMU, leaving
>> the assumptions about the secure access as it has been, prior to this patch.
>
> This is an extensive commit log about secure access issues which is nice
> and appreciated.  However the patch does quite some more code reorg not
> mentioned here.  Could you please move this code reorg to a separate
> patch and then have a patch on top introducing these probing changes?
> This should make the implication of what is said above clearer.

Sure, I will do that in the next revision. What I missed in the commit
follows (which will be added in the next version):

"This patch abstracts the representation of the CCI400 chipset
  PMU specific definitions, so that we can avoid probing the
  revision for any details. The new device-tree bindings helps to
  get the revision, without poking the CCI, and initialises the pmu with
  specific model details."

Thanks
Suzuki

>
>> Cc: devicetree@vger.kernel.org
>> Cc: Punit Agrawal <punit.agrawal@arm.com>
>> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
>> ---
>>   Documentation/devicetree/bindings/arm/cci.txt |    7 +-
>>   arch/arm/include/asm/arm-cci.h                |   42 ++++++++
>>   arch/arm64/include/asm/arm-cci.h              |   27 +++++
>>   drivers/bus/arm-cci.c                         |  138 ++++++++++++++++---------
>>   include/linux/arm-cci.h                       |    2 +
>>   5 files changed, 166 insertions(+), 50 deletions(-)
>>   create mode 100644 arch/arm/include/asm/arm-cci.h
>>   create mode 100644 arch/arm64/include/asm/arm-cci.h
>>
>> diff --git a/Documentation/devicetree/bindings/arm/cci.txt b/Documentation/devicetree/bindings/arm/cci.txt
>> index f28d82b..0e4b6a7 100644
>> --- a/Documentation/devicetree/bindings/arm/cci.txt
>> +++ b/Documentation/devicetree/bindings/arm/cci.txt
>> @@ -94,8 +94,11 @@ specific to ARM.
>>                - compatible
>>                        Usage: required
>>                        Value type: <string>
>> -                     Definition: must be "arm,cci-400-pmu"
>> -
>> +                     Definition: Supported strings are :
>> +                              "arm,cci-400-pmu,r0"
>> +                              "arm,cci-400-pmu,r1"
>> +                              "arm,cci-400-pmu"  - DEPRECATED, permitted only where OS has
>> +                                                   secure acces to CCI registers
>>                - reg:
>>                        Usage: required
>>                        Value type: Integer cells. A register entry, expressed
>> diff --git a/arch/arm/include/asm/arm-cci.h b/arch/arm/include/asm/arm-cci.h
>> new file mode 100644
>> index 0000000..b828d7a
>> --- /dev/null
>> +++ b/arch/arm/include/asm/arm-cci.h
>> @@ -0,0 +1,42 @@
>> +/*
>> + * arch/arm/include/asm/arm-cci.h
>> + *
>> + * Copyright (C) 2015 ARM Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef __ASM_ARM_CCI_H
>> +#define __ASM_ARM_CCI_H
>> +
>> +#ifdef CONFIG_MCPM
>> +#include <asm/mcpm.h>
>> +
>> +/*
>> + * We don't have a reliable way of detecting, whether
>> + * we have access to secure-only registers, unless
>> + * mcpm is registered.
>> + */
>> +static inline int platform_has_secure_cci_access(void)
>> +{
>> +     return mcpm_is_available();
>> +}
>> +
>> +#else
>> +static inline int platform_has_secure_cci_access(void)
>> +{
>> +     return 0;
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/arch/arm64/include/asm/arm-cci.h b/arch/arm64/include/asm/arm-cci.h
>> new file mode 100644
>> index 0000000..37bbe37
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/arm-cci.h
>> @@ -0,0 +1,27 @@
>> +/*
>> + * arch/arm64/include/asm/arm-cci.h
>> + *
>> + * Copyright (C) 2015 ARM Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef __ASM_ARM_CCI_H
>> +#define __ASM_ARM_CCI_H
>> +
>> +static inline int platform_has_secure_cci_access(void)
>> +{
>> +     return 0;
>> +}
>> +
>> +#endif
>> diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
>> index f27cf56..fe9fa46 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,11 @@ 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];
>> +     if (platform_has_secure_cci_access())
>> +             return &cci_pmu_models[probe_cci_revision()];
>> +     return NULL;
>>   }
>>
>>   static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
>> @@ -807,9 +795,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,13 +850,65 @@ 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",
>> +             .data   = NULL,
>> +     },
>> +     {
>> +             .compatible = "arm,cci-400-pmu,r0",
>> +             .data   = &cci_pmu_models[CCI_REV_R0],
>> +     },
>> +     {
>> +             .compatible = "arm,cci-400-pmu,r1",
>> +             .data   = &cci_pmu_models[CCI_REV_R1],
>>        },
>>        {},
>>   };
>>
>> +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;
>> +     if (match->data)
>> +             return match->data;
>> +
>> +     dev_warn(&pdev->dev, "DEPERCATED compatible property,"
>> +                      "requires secure access to CCI registers");
>> +     return probe_cci_model(pdev);
>> +}
>> +
>>   static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
>>   {
>>        int i;
>> @@ -884,11 +924,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 -EINVAL;
>> +     }
>>
>>        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 +968,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);
>> diff --git a/include/linux/arm-cci.h b/include/linux/arm-cci.h
>> index 79d6edf..aede5c7 100644
>> --- a/include/linux/arm-cci.h
>> +++ b/include/linux/arm-cci.h
>> @@ -24,6 +24,8 @@
>>   #include <linux/errno.h>
>>   #include <linux/types.h>
>>
>> +#include <asm/arm-cci.h>
>> +
>>   struct device_node;
>>
>>   #ifdef CONFIG_ARM_CCI
>> --
>> 1.7.9.5
>>
>>
>>
>



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/4] arm-cci: Split the code for PMU vs driver support
  2015-02-24 22:17   ` Nicolas Pitre
@ 2015-02-25 10:26     ` Suzuki K. Poulose
  2015-02-25 14:31       ` Nicolas Pitre
  0 siblings, 1 reply; 10+ messages in thread
From: Suzuki K. Poulose @ 2015-02-25 10:26 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: linux-arm-kernel, Bartlomiej Zolnierkiewicz, Kukjin Kim,
	Abhilash Kesavan, Arnd Bergmann, devicetree, linux-kernel,
	Liviu Dudau, Lorenzo Pieralisi, Olof Johansson, Pawel Moll,
	Punit Agrawal, Sudeep Holla, Will Deacon, Catalin Marinas

On 24/02/15 22:17, Nicolas Pitre wrote:
> On Tue, 24 Feb 2015, Suzuki K. Poulose wrote:
>
>> From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
>>
>> This patch separates the PMU driver code from the low level
>> CCI driver code, and enables the CCI400-PMU for ARM64.
>>
>> Introduces config options for both.
>>
>>   - ARM_CCI400_MCPM	- controls the low level MCPM driver code for CCI
>>   - ARM_CCI400_PMU	- controls the PMU driver code
>>   - ARM_CCI400_COMMON	- CCI400 specific details shared by MCPM
>> 			  and PMU
>> Changes:
>>   - ARM_CCI 		- common code for probing the CCI devices
>>
>> Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
>> Cc: Kukjin Kim <kgene@kernel.org>
>> Cc: Abhilash Kesavan <a.kesavan@samsung.com>
>> Cc: Liviu Dudau <liviu.dudau@arm.com>
>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Sudeep Holla <sudeep.holla@arm.com>
>> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
>
> Comments inline.
>
>> ---
>>   arch/arm/mach-exynos/Kconfig   |    2 +-
>>   arch/arm/mach-vexpress/Kconfig |    4 ++--
>>   drivers/bus/Kconfig            |   28 +++++++++++++++++++++++-----
>>   drivers/bus/arm-cci.c          |   25 +++++++++++++++++++++----
>>   include/linux/arm-cci.h        |    7 ++++++-
>>   5 files changed, 53 insertions(+), 13 deletions(-)
>>
>> diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
>> index 603820e..9bc8b4d 100644
>> --- a/arch/arm/mach-exynos/Kconfig
>> +++ b/arch/arm/mach-exynos/Kconfig
>> @@ -123,7 +123,7 @@ config SOC_EXYNOS5800
>>   config EXYNOS5420_MCPM
>>   	bool "Exynos5420 Multi-Cluster PM support"
>>   	depends on MCPM && SOC_EXYNOS5420
>> -	select ARM_CCI
>> +	select ARM_CCI400_MCPM
>>   	select ARM_CPU_SUSPEND
>>   	help
>>   	  This is needed to provide CPU and cluster power management
>> diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
>> index d6b16d9..097912f 100644
>> --- a/arch/arm/mach-vexpress/Kconfig
>> +++ b/arch/arm/mach-vexpress/Kconfig
>> @@ -53,7 +53,7 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
>>   config ARCH_VEXPRESS_DCSCB
>>   	bool "Dual Cluster System Control Block (DCSCB) support"
>>   	depends on MCPM
>> -	select ARM_CCI
>> +	select ARM_CCI400_MCPM
>>   	help
>>   	  Support for the Dual Cluster System Configuration Block (DCSCB).
>>   	  This is needed to provide CPU and cluster power management
>> @@ -71,7 +71,7 @@ config ARCH_VEXPRESS_SPC
>>   config ARCH_VEXPRESS_TC2_PM
>>   	bool "Versatile Express TC2 power management"
>>   	depends on MCPM
>> -	select ARM_CCI
>> +	select ARM_CCI400_MCPM
>>   	select ARCH_VEXPRESS_SPC
>>   	help
>>   	  Support for CPU and cluster power management on Versatile Express
>> diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
>> index b99729e..91dd013 100644
>> --- a/drivers/bus/Kconfig
>> +++ b/drivers/bus/Kconfig
>> @@ -43,12 +43,30 @@ config OMAP_INTERCONNECT
>>   	help
>>   	  Driver to enable OMAP interconnect error handling driver.
>>
>> -config ARM_CCI
>> -	bool "ARM CCI driver support"
>> -	depends on ARM && OF && CPU_V7
>> +config ARM_CCI400_MCPM
>> +	bool
>> +	depends on ARM && OF && CPU_V7 && MCPM
>
> MCPM is not an actual dependency and therefore should probably not be
> added here.
OK, will remove that.

> You removed the prompt string therefore this will only be
> selectable explicitly as needed.
This was intentional, I missed mentioning about it. Do you think we
need to change it back ?
>
> Also, shouldn't it select ARM_CCI400_COMMON ?
Thanks for that, yes it should.
>
>> +	help
>> +	  Low level power management driver for CCI400 cache coherent
>> +	  interconnect for ARM platforms.
>> +
>> +config ARM_CCI400_PMU
>> +	bool "ARM CCI400 PMU support"
>> +	depends on ARM || ARM64
>> +	depends on HW_PERF_EVENTS
>> +	select ARM_CCI400_COMMON
>>   	help
>> -	  Driver supporting the CCI cache coherent interconnect for ARM
>> -	  platforms.
>> +	  Support for PMU events monitoring on the ARM CCI cache coherent
>> +	  interconnect.
>> +
>> +	  If unsure, say N
>> +
>> +config ARM_CCI400_COMMON
>> +	bool
>> +	select ARM_CCI
>> +
>> +config ARM_CCI
>> +	bool
>
> Surely you could do with only one of ARM_CCI or ARM_CCI400_COMMON?
> Personally I'd go with the later as it is more precise.

The ARM_CCI now stands for CCI version agnostic code. This can be used
for adding support for the newer versions, e.g CCI-500, which I am
planning to post, after this series gets sorted out.


>
>>   config ARM_CCN
>>   	bool "ARM CCN driver support"
>> diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
>> index fe9fa46..7e330fe 100644
>> --- a/drivers/bus/arm-cci.c
>> +++ b/drivers/bus/arm-cci.c
>> @@ -32,6 +32,7 @@
>>   static void __iomem *cci_ctrl_base;
>>   static unsigned long cci_ctrl_phys;
>>
>> +#ifdef CONFIG_ARM_CCI400_MCPM
>>   struct cci_nb_ports {
>>   	unsigned int nb_ace;
>>   	unsigned int nb_ace_lite;
>> @@ -42,12 +43,19 @@ static const struct cci_nb_ports cci400_ports = {
>>   	.nb_ace_lite = 3
>>   };
>>
>> +#define CCI400_MCPM_PORTS_DATA	(&cci400_ports)
>
> I'm a bit uneasy with the conflation of MCPM in here.  Sure (most) MCPM
> backends are the only users of this code, but that doesn't mean MCPM has
> to have exclusive access.  Having "MCPM" entranched into the code and
> config symbols like that is misrepresenting this code somewhat.
So, would you like to change the ARM_CCI400_MCPM as well, to something like:
	ARM_CCI400_DRIVER or even ARM_CCI400_LL_DRIVER ?

>
>> +#else
>> +#define CCI400_MCPM_PORTS_DATA	(NULL)
>> +#endif
>> +
>>   static const struct of_device_id arm_cci_matches[] = {
>> -	{.compatible = "arm,cci-400", .data = &cci400_ports },
>> +#ifdef CONFIG_ARM_CCI400_COMMON
>> +	{.compatible = "arm,cci-400", .data = CCI400_MCPM_PORTS_DATA },
>> +#endif
>>   	{},
>>   };
>>
>> -#ifdef CONFIG_HW_PERF_EVENTS
>> +#ifdef CONFIG_ARM_CCI400_PMU
>>
>>   #define DRIVER_NAME		"CCI-400"
>>   #define DRIVER_NAME_PMU		DRIVER_NAME " PMU"
>> @@ -981,6 +989,7 @@ static int cci_pmu_probe(struct platform_device *pdev)
>>   	if (ret)
>>   		return ret;
>>
>> +	pr_info("ARM %s PMU driver probed", pmu->model->name);
>
> Wouldn't this addition fit better in one of the previous patches?
Yes, it could have been moved to the previous one, will fix it in the 
next revision.


Thanks
Suzuki



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/4] arm-cci: Split the code for PMU vs driver support
  2015-02-25 10:26     ` Suzuki K. Poulose
@ 2015-02-25 14:31       ` Nicolas Pitre
  0 siblings, 0 replies; 10+ messages in thread
From: Nicolas Pitre @ 2015-02-25 14:31 UTC (permalink / raw)
  To: Suzuki K. Poulose
  Cc: linux-arm-kernel, Bartlomiej Zolnierkiewicz, Kukjin Kim,
	Abhilash Kesavan, Arnd Bergmann, devicetree, linux-kernel,
	Liviu Dudau, Lorenzo Pieralisi, Olof Johansson, Pawel Moll,
	Punit Agrawal, Sudeep Holla, Will Deacon, Catalin Marinas

On Wed, 25 Feb 2015, Suzuki K. Poulose wrote:

> On 24/02/15 22:17, Nicolas Pitre wrote:
> > On Tue, 24 Feb 2015, Suzuki K. Poulose wrote:
> >
> > > From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
> > >
> > > This patch separates the PMU driver code from the low level
> > > CCI driver code, and enables the CCI400-PMU for ARM64.
> > >
> > > Introduces config options for both.
> > >
> > >   - ARM_CCI400_MCPM	- controls the low level MCPM driver code for CCI
> > >   - ARM_CCI400_PMU	- controls the PMU driver code
> > >   - ARM_CCI400_COMMON	- CCI400 specific details shared by MCPM
> > > 			  and PMU
> > > Changes:
> > >   - ARM_CCI 		- common code for probing the CCI devices
> > >
> > > Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > > Cc: Kukjin Kim <kgene@kernel.org>
> > > Cc: Abhilash Kesavan <a.kesavan@samsung.com>
> > > Cc: Liviu Dudau <liviu.dudau@arm.com>
> > > Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > > Cc: Sudeep Holla <sudeep.holla@arm.com>
> > > Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
> >
> > Comments inline.
> >
> > > ---
> > >   arch/arm/mach-exynos/Kconfig   |    2 +-
> > >   arch/arm/mach-vexpress/Kconfig |    4 ++--
> > >   drivers/bus/Kconfig            |   28 +++++++++++++++++++++++-----
> > >   drivers/bus/arm-cci.c          |   25 +++++++++++++++++++++----
> > >   include/linux/arm-cci.h        |    7 ++++++-
> > >   5 files changed, 53 insertions(+), 13 deletions(-)
> > >
> > > diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
> > > index 603820e..9bc8b4d 100644
> > > --- a/arch/arm/mach-exynos/Kconfig
> > > +++ b/arch/arm/mach-exynos/Kconfig
> > > @@ -123,7 +123,7 @@ config SOC_EXYNOS5800
> > >   config EXYNOS5420_MCPM
> > >    bool "Exynos5420 Multi-Cluster PM support"
> > >    depends on MCPM && SOC_EXYNOS5420
> > > -	select ARM_CCI
> > > +	select ARM_CCI400_MCPM
> > >    select ARM_CPU_SUSPEND
> > >    help
> > >   	  This is needed to provide CPU and cluster power management
> > > diff --git a/arch/arm/mach-vexpress/Kconfig
> > > b/arch/arm/mach-vexpress/Kconfig
> > > index d6b16d9..097912f 100644
> > > --- a/arch/arm/mach-vexpress/Kconfig
> > > +++ b/arch/arm/mach-vexpress/Kconfig
> > > @@ -53,7 +53,7 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
> > >   config ARCH_VEXPRESS_DCSCB
> > >    bool "Dual Cluster System Control Block (DCSCB) support"
> > >    depends on MCPM
> > > -	select ARM_CCI
> > > +	select ARM_CCI400_MCPM
> > >    help
> > >      Support for the Dual Cluster System Configuration Block (DCSCB).
> > >      This is needed to provide CPU and cluster power management
> > > @@ -71,7 +71,7 @@ config ARCH_VEXPRESS_SPC
> > >   config ARCH_VEXPRESS_TC2_PM
> > >    bool "Versatile Express TC2 power management"
> > >    depends on MCPM
> > > -	select ARM_CCI
> > > +	select ARM_CCI400_MCPM
> > >    select ARCH_VEXPRESS_SPC
> > >    help
> > >   	  Support for CPU and cluster power management on Versatile Express
> > > diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
> > > index b99729e..91dd013 100644
> > > --- a/drivers/bus/Kconfig
> > > +++ b/drivers/bus/Kconfig
> > > @@ -43,12 +43,30 @@ config OMAP_INTERCONNECT
> > >    help
> > >      Driver to enable OMAP interconnect error handling driver.
> > >
> > > -config ARM_CCI
> > > -	bool "ARM CCI driver support"
> > > -	depends on ARM && OF && CPU_V7
> > > +config ARM_CCI400_MCPM
> > > +	bool
> > > +	depends on ARM && OF && CPU_V7 && MCPM
> >
> > MCPM is not an actual dependency and therefore should probably not be
> > added here.
> OK, will remove that.
> 
> > You removed the prompt string therefore this will only be
> > selectable explicitly as needed.
> This was intentional, I missed mentioning about it. Do you think we
> need to change it back ?

No.  I'm perfectly fine with those platforms needing it for proper 
operation to explicitly select this.  I don't see much value in having 
this user configurable.

> >
> > Also, shouldn't it select ARM_CCI400_COMMON ?
> Thanks for that, yes it should.
> >
> > > +	help
> > > +	  Low level power management driver for CCI400 cache coherent
> > > +	  interconnect for ARM platforms.
> > > +
> > > +config ARM_CCI400_PMU
> > > +	bool "ARM CCI400 PMU support"
> > > +	depends on ARM || ARM64
> > > +	depends on HW_PERF_EVENTS
> > > +	select ARM_CCI400_COMMON
> > >   	help
> > > -	  Driver supporting the CCI cache coherent interconnect for ARM
> > > -	  platforms.
> > > +	  Support for PMU events monitoring on the ARM CCI cache coherent
> > > +	  interconnect.
> > > +
> > > +	  If unsure, say N
> > > +
> > > +config ARM_CCI400_COMMON
> > > +	bool
> > > +	select ARM_CCI
> > > +
> > > +config ARM_CCI
> > > +	bool
> >
> > Surely you could do with only one of ARM_CCI or ARM_CCI400_COMMON?
> > Personally I'd go with the later as it is more precise.
> 
> The ARM_CCI now stands for CCI version agnostic code. This can be used
> for adding support for the newer versions, e.g CCI-500, which I am
> planning to post, after this series gets sorted out.

OK.  Please add a note to that effect in the commit log.

> >
> > >   config ARM_CCN
> > >   	bool "ARM CCN driver support"
> > > diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
> > > index fe9fa46..7e330fe 100644
> > > --- a/drivers/bus/arm-cci.c
> > > +++ b/drivers/bus/arm-cci.c
> > > @@ -32,6 +32,7 @@
> > >   static void __iomem *cci_ctrl_base;
> > >   static unsigned long cci_ctrl_phys;
> > >
> > > +#ifdef CONFIG_ARM_CCI400_MCPM
> > >   struct cci_nb_ports {
> > >    unsigned int nb_ace;
> > >    unsigned int nb_ace_lite;
> > > @@ -42,12 +43,19 @@ static const struct cci_nb_ports cci400_ports = {
> > >   	.nb_ace_lite = 3
> > >   };
> > >
> > > +#define CCI400_MCPM_PORTS_DATA	(&cci400_ports)
> >
> > I'm a bit uneasy with the conflation of MCPM in here.  Sure (most) MCPM
> > backends are the only users of this code, but that doesn't mean MCPM has
> > to have exclusive access.  Having "MCPM" entranched into the code and
> > config symbols like that is misrepresenting this code somewhat.
> So, would you like to change the ARM_CCI400_MCPM as well, to something like:
> 	ARM_CCI400_DRIVER or even ARM_CCI400_LL_DRIVER ?

That would make more sense.  Or even ARM_CCI400_PORT_CTRL or the like.


Nicolas

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2015-02-25 14:31 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-24 13:17 [PATCH 0/4] arm-cci400: PMU monitoring support on ARM64 Suzuki K. Poulose
2015-02-24 13:17 ` [PATCH 1/4] arm-cci: Rearrange code for splitting PMU vs driver code Suzuki K. Poulose
2015-02-24 13:17 ` [PATCH 2/4] arm-cci: Get rid of secure transactions for PMU driver Suzuki K. Poulose
2015-02-24 21:53   ` Nicolas Pitre
2015-02-25 10:20     ` Suzuki K. Poulose
2015-02-24 13:17 ` [PATCH 3/4] arm-cci: Split the code for PMU vs driver support Suzuki K. Poulose
2015-02-24 22:17   ` Nicolas Pitre
2015-02-25 10:26     ` Suzuki K. Poulose
2015-02-25 14:31       ` Nicolas Pitre
2015-02-24 13:17 ` [PATCH 4/4] arm-cci: Fix CCI PMU event validation Suzuki K. Poulose

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).