All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Glauber <jglauber@cavium.com>
To: Mark Rutland <mark.rutland@arm.com>, Will Deacon <will.deacon@arm.com>
Cc: linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	Jan Glauber <jglauber@cavium.com>
Subject: [PATCH v2 5/5] arm64/perf: Cavium ThunderX OCX TLK uncore support
Date: Wed,  9 Mar 2016 17:21:07 +0100	[thread overview]
Message-ID: <876bae8e4fc594a646651c02ae8ab9a8c423a49e.1457539622.git.jglauber@cavium.com> (raw)
In-Reply-To: <cover.1457539621.git.jglauber@cavium.com>
In-Reply-To: <cover.1457539621.git.jglauber@cavium.com>

Support for the OCX transmit link counters.

Signed-off-by: Jan Glauber <jglauber@cavium.com>
---
 drivers/perf/uncore/Makefile                |   3 +-
 drivers/perf/uncore/uncore_cavium.c         |   3 +
 drivers/perf/uncore/uncore_cavium.h         |   4 +
 drivers/perf/uncore/uncore_cavium_ocx_tlk.c | 380 ++++++++++++++++++++++++++++
 4 files changed, 389 insertions(+), 1 deletion(-)
 create mode 100644 drivers/perf/uncore/uncore_cavium_ocx_tlk.c

diff --git a/drivers/perf/uncore/Makefile b/drivers/perf/uncore/Makefile
index 81479e8..88d1f57 100644
--- a/drivers/perf/uncore/Makefile
+++ b/drivers/perf/uncore/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_ARCH_THUNDER) += uncore_cavium.o		\
 			      uncore_cavium_l2c_tad.o	\
 			      uncore_cavium_l2c_cbc.o	\
-			      uncore_cavium_lmc.o
+			      uncore_cavium_lmc.o	\
+			      uncore_cavium_ocx_tlk.o
diff --git a/drivers/perf/uncore/uncore_cavium.c b/drivers/perf/uncore/uncore_cavium.c
index 45c81d0..e210457 100644
--- a/drivers/perf/uncore/uncore_cavium.c
+++ b/drivers/perf/uncore/uncore_cavium.c
@@ -21,6 +21,8 @@ struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event)
 		return thunder_uncore_l2c_cbc;
 	else if (event->pmu->type == thunder_lmc_pmu.type)
 		return thunder_uncore_lmc;
+	else if (event->pmu->type == thunder_ocx_tlk_pmu.type)
+		return thunder_uncore_ocx_tlk;
 	else
 		return NULL;
 }
@@ -306,6 +308,7 @@ static int __init thunder_uncore_init(void)
 	thunder_uncore_l2c_tad_setup();
 	thunder_uncore_l2c_cbc_setup();
 	thunder_uncore_lmc_setup();
+	thunder_uncore_ocx_tlk_setup();
 	return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/drivers/perf/uncore/uncore_cavium.h b/drivers/perf/uncore/uncore_cavium.h
index f14f6be..78e95c7 100644
--- a/drivers/perf/uncore/uncore_cavium.h
+++ b/drivers/perf/uncore/uncore_cavium.h
@@ -10,6 +10,7 @@ enum uncore_type {
 	L2C_TAD_TYPE,
 	L2C_CBC_TYPE,
 	LMC_TYPE,
+	OCX_TLK_TYPE,
 };
 
 extern int thunder_uncore_version;
@@ -70,9 +71,11 @@ extern struct device_attribute format_attr_node;
 extern struct thunder_uncore *thunder_uncore_l2c_tad;
 extern struct thunder_uncore *thunder_uncore_l2c_cbc;
 extern struct thunder_uncore *thunder_uncore_lmc;
+extern struct thunder_uncore *thunder_uncore_ocx_tlk;
 extern struct pmu thunder_l2c_tad_pmu;
 extern struct pmu thunder_l2c_cbc_pmu;
 extern struct pmu thunder_lmc_pmu;
+extern struct pmu thunder_ocx_tlk_pmu;
 
 /* Prototypes */
 struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event);
@@ -89,3 +92,4 @@ ssize_t thunder_events_sysfs_show(struct device *dev,
 int thunder_uncore_l2c_tad_setup(void);
 int thunder_uncore_l2c_cbc_setup(void);
 int thunder_uncore_lmc_setup(void);
+int thunder_uncore_ocx_tlk_setup(void);
diff --git a/drivers/perf/uncore/uncore_cavium_ocx_tlk.c b/drivers/perf/uncore/uncore_cavium_ocx_tlk.c
new file mode 100644
index 0000000..02f1bc1
--- /dev/null
+++ b/drivers/perf/uncore/uncore_cavium_ocx_tlk.c
@@ -0,0 +1,380 @@
+/*
+ * Cavium Thunder uncore PMU support, OCX TLK counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glauber@cavium.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/perf_event.h>
+
+#include "uncore_cavium.h"
+
+#ifndef PCI_DEVICE_ID_THUNDER_OCX
+#define PCI_DEVICE_ID_THUNDER_OCX		0xa013
+#endif
+
+#define OCX_TLK_NR_UNITS			3
+#define OCX_TLK_UNIT_OFFSET			0x2000
+#define OCX_TLK_CONTROL_OFFSET			0x10040
+#define OCX_TLK_COUNTER_OFFSET			0x10400
+
+#define OCX_TLK_STAT_DISABLE			0
+#define OCX_TLK_STAT_ENABLE			1
+
+/* OCX TLK event list */
+#define OCX_TLK_EVENT_STAT_IDLE_CNT		0x00
+#define OCX_TLK_EVENT_STAT_DATA_CNT		0x01
+#define OCX_TLK_EVENT_STAT_SYNC_CNT		0x02
+#define OCX_TLK_EVENT_STAT_RETRY_CNT		0x03
+#define OCX_TLK_EVENT_STAT_ERR_CNT		0x04
+
+#define OCX_TLK_EVENT_STAT_MAT0_CNT		0x08
+#define OCX_TLK_EVENT_STAT_MAT1_CNT		0x09
+#define OCX_TLK_EVENT_STAT_MAT2_CNT		0x0a
+#define OCX_TLK_EVENT_STAT_MAT3_CNT		0x0b
+
+#define OCX_TLK_EVENT_STAT_VC0_CMD		0x10
+#define OCX_TLK_EVENT_STAT_VC1_CMD		0x11
+#define OCX_TLK_EVENT_STAT_VC2_CMD		0x12
+#define OCX_TLK_EVENT_STAT_VC3_CMD		0x13
+#define OCX_TLK_EVENT_STAT_VC4_CMD		0x14
+#define OCX_TLK_EVENT_STAT_VC5_CMD		0x15
+
+#define OCX_TLK_EVENT_STAT_VC0_PKT		0x20
+#define OCX_TLK_EVENT_STAT_VC1_PKT		0x21
+#define OCX_TLK_EVENT_STAT_VC2_PKT		0x22
+#define OCX_TLK_EVENT_STAT_VC3_PKT		0x23
+#define OCX_TLK_EVENT_STAT_VC4_PKT		0x24
+#define OCX_TLK_EVENT_STAT_VC5_PKT		0x25
+#define OCX_TLK_EVENT_STAT_VC6_PKT		0x26
+#define OCX_TLK_EVENT_STAT_VC7_PKT		0x27
+#define OCX_TLK_EVENT_STAT_VC8_PKT		0x28
+#define OCX_TLK_EVENT_STAT_VC9_PKT		0x29
+#define OCX_TLK_EVENT_STAT_VC10_PKT		0x2a
+#define OCX_TLK_EVENT_STAT_VC11_PKT		0x2b
+#define OCX_TLK_EVENT_STAT_VC12_PKT		0x2c
+#define OCX_TLK_EVENT_STAT_VC13_PKT		0x2d
+
+#define OCX_TLK_EVENT_STAT_VC0_CON		0x30
+#define OCX_TLK_EVENT_STAT_VC1_CON		0x31
+#define OCX_TLK_EVENT_STAT_VC2_CON		0x32
+#define OCX_TLK_EVENT_STAT_VC3_CON		0x33
+#define OCX_TLK_EVENT_STAT_VC4_CON		0x34
+#define OCX_TLK_EVENT_STAT_VC5_CON		0x35
+#define OCX_TLK_EVENT_STAT_VC6_CON		0x36
+#define OCX_TLK_EVENT_STAT_VC7_CON		0x37
+#define OCX_TLK_EVENT_STAT_VC8_CON		0x38
+#define OCX_TLK_EVENT_STAT_VC9_CON		0x39
+#define OCX_TLK_EVENT_STAT_VC10_CON		0x3a
+#define OCX_TLK_EVENT_STAT_VC11_CON		0x3b
+#define OCX_TLK_EVENT_STAT_VC12_CON		0x3c
+#define OCX_TLK_EVENT_STAT_VC13_CON		0x3d
+
+#define OCX_TLK_MAX_COUNTER			OCX_TLK_EVENT_STAT_VC13_CON
+#define OCX_TLK_NR_COUNTERS			OCX_TLK_MAX_COUNTER
+
+struct thunder_uncore *thunder_uncore_ocx_tlk;
+
+/*
+ * The OCX devices have a single device per node, therefore picking the
+ * first device from the list is correct.
+ */
+static inline void __iomem *map_offset(struct thunder_uncore_node *node,
+				       unsigned long addr, int offset, int nr)
+{
+	struct thunder_uncore_unit *unit;
+
+	unit = list_first_entry(&node->unit_list, struct thunder_uncore_unit,
+				entry);
+	return (void __iomem *) (addr + unit->map + nr * offset);
+}
+
+static void __iomem *map_offset_ocx_tlk(struct thunder_uncore_node *node,
+					unsigned long addr, int nr)
+{
+	return (void __iomem *) map_offset(node, addr, nr,
+					   OCX_TLK_UNIT_OFFSET);
+}
+
+/*
+ * Summarize counters across all TLK's. Different from the other uncore
+ * PMUs because all TLK's are on one PCI device.
+ */
+static void thunder_uncore_read_ocx_tlk(struct perf_event *event)
+{
+	struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	u64 prev, new = 0;
+	s64 delta;
+	int i;
+
+	/*
+	 * No counter overflow interrupts so we do not
+	 * have to worry about prev_count changing on us.
+	 */
+
+	prev = local64_read(&hwc->prev_count);
+
+	/* read counter values from all units */
+	node = get_node(hwc->config, uncore);
+	for (i = 0; i < OCX_TLK_NR_UNITS; i++)
+		new += readq(map_offset_ocx_tlk(node, hwc->event_base, i));
+
+	local64_set(&hwc->prev_count, new);
+	delta = new - prev;
+	local64_add(delta, &event->count);
+}
+
+static void thunder_uncore_start(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	int i;
+
+	hwc->state = 0;
+
+	/* enable counters on all units */
+	node = get_node(hwc->config, uncore);
+	for (i = 0; i < OCX_TLK_NR_UNITS; i++)
+		writeb(OCX_TLK_STAT_ENABLE,
+		       map_offset_ocx_tlk(node, hwc->config_base, i));
+
+	perf_event_update_userpage(event);
+}
+
+static void thunder_uncore_stop(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	int i;
+
+	/* disable counters on all units */
+	node = get_node(hwc->config, uncore);
+	for (i = 0; i < OCX_TLK_NR_UNITS; i++)
+		writeb(OCX_TLK_STAT_DISABLE,
+		       map_offset_ocx_tlk(node, hwc->config_base, i));
+	hwc->state |= PERF_HES_STOPPED;
+
+	if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+		thunder_uncore_read_ocx_tlk(event);
+		hwc->state |= PERF_HES_UPTODATE;
+	}
+}
+
+static int thunder_uncore_add(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	int id, i;
+
+	WARN_ON_ONCE(!uncore);
+	node = get_node(hwc->config, uncore);
+	id = get_id(hwc->config);
+
+	/* are we already assigned? */
+	if (hwc->idx != -1 && node->events[hwc->idx] == event)
+		goto out;
+
+	for (i = 0; i < node->num_counters; i++) {
+		if (node->events[i] == event) {
+			hwc->idx = i;
+			goto out;
+		}
+	}
+
+	/* counters are 1:1 */
+	hwc->idx = -1;
+	if (cmpxchg(&node->events[id], NULL, event) == NULL)
+		hwc->idx = id;
+
+out:
+	if (hwc->idx == -1)
+		return -EBUSY;
+
+	hwc->config_base = 0;
+	hwc->event_base = OCX_TLK_COUNTER_OFFSET - OCX_TLK_CONTROL_OFFSET +
+			hwc->idx * sizeof(unsigned long long);
+	hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+	if (flags & PERF_EF_START)
+		thunder_uncore_start(event, PERF_EF_RELOAD);
+	return 0;
+}
+
+PMU_FORMAT_ATTR(event, "config:0-5");
+
+static struct attribute *thunder_ocx_tlk_format_attr[] = {
+	&format_attr_event.attr,
+	&format_attr_node.attr,
+	NULL,
+};
+
+static struct attribute_group thunder_ocx_tlk_format_group = {
+	.name = "format",
+	.attrs = thunder_ocx_tlk_format_attr,
+};
+
+EVENT_ATTR(idle_cnt,	OCX_TLK_EVENT_STAT_IDLE_CNT);
+EVENT_ATTR(data_cnt,	OCX_TLK_EVENT_STAT_DATA_CNT);
+EVENT_ATTR(sync_cnt,	OCX_TLK_EVENT_STAT_SYNC_CNT);
+EVENT_ATTR(retry_cnt,	OCX_TLK_EVENT_STAT_RETRY_CNT);
+EVENT_ATTR(err_cnt,	OCX_TLK_EVENT_STAT_ERR_CNT);
+EVENT_ATTR(mat0_cnt,	OCX_TLK_EVENT_STAT_MAT0_CNT);
+EVENT_ATTR(mat1_cnt,	OCX_TLK_EVENT_STAT_MAT1_CNT);
+EVENT_ATTR(mat2_cnt,	OCX_TLK_EVENT_STAT_MAT2_CNT);
+EVENT_ATTR(mat3_cnt,	OCX_TLK_EVENT_STAT_MAT3_CNT);
+EVENT_ATTR(vc0_cmd,	OCX_TLK_EVENT_STAT_VC0_CMD);
+EVENT_ATTR(vc1_cmd,	OCX_TLK_EVENT_STAT_VC1_CMD);
+EVENT_ATTR(vc2_cmd,	OCX_TLK_EVENT_STAT_VC2_CMD);
+EVENT_ATTR(vc3_cmd,	OCX_TLK_EVENT_STAT_VC3_CMD);
+EVENT_ATTR(vc4_cmd,	OCX_TLK_EVENT_STAT_VC4_CMD);
+EVENT_ATTR(vc5_cmd,	OCX_TLK_EVENT_STAT_VC5_CMD);
+EVENT_ATTR(vc0_pkt,	OCX_TLK_EVENT_STAT_VC0_PKT);
+EVENT_ATTR(vc1_pkt,	OCX_TLK_EVENT_STAT_VC1_PKT);
+EVENT_ATTR(vc2_pkt,	OCX_TLK_EVENT_STAT_VC2_PKT);
+EVENT_ATTR(vc3_pkt,	OCX_TLK_EVENT_STAT_VC3_PKT);
+EVENT_ATTR(vc4_pkt,	OCX_TLK_EVENT_STAT_VC4_PKT);
+EVENT_ATTR(vc5_pkt,	OCX_TLK_EVENT_STAT_VC5_PKT);
+EVENT_ATTR(vc6_pkt,	OCX_TLK_EVENT_STAT_VC6_PKT);
+EVENT_ATTR(vc7_pkt,	OCX_TLK_EVENT_STAT_VC7_PKT);
+EVENT_ATTR(vc8_pkt,	OCX_TLK_EVENT_STAT_VC8_PKT);
+EVENT_ATTR(vc9_pkt,	OCX_TLK_EVENT_STAT_VC9_PKT);
+EVENT_ATTR(vc10_pkt,	OCX_TLK_EVENT_STAT_VC10_PKT);
+EVENT_ATTR(vc11_pkt,	OCX_TLK_EVENT_STAT_VC11_PKT);
+EVENT_ATTR(vc12_pkt,	OCX_TLK_EVENT_STAT_VC12_PKT);
+EVENT_ATTR(vc13_pkt,	OCX_TLK_EVENT_STAT_VC13_PKT);
+EVENT_ATTR(vc0_con,	OCX_TLK_EVENT_STAT_VC0_CON);
+EVENT_ATTR(vc1_con,	OCX_TLK_EVENT_STAT_VC1_CON);
+EVENT_ATTR(vc2_con,	OCX_TLK_EVENT_STAT_VC2_CON);
+EVENT_ATTR(vc3_con,	OCX_TLK_EVENT_STAT_VC3_CON);
+EVENT_ATTR(vc4_con,	OCX_TLK_EVENT_STAT_VC4_CON);
+EVENT_ATTR(vc5_con,	OCX_TLK_EVENT_STAT_VC5_CON);
+EVENT_ATTR(vc6_con,	OCX_TLK_EVENT_STAT_VC6_CON);
+EVENT_ATTR(vc7_con,	OCX_TLK_EVENT_STAT_VC7_CON);
+EVENT_ATTR(vc8_con,	OCX_TLK_EVENT_STAT_VC8_CON);
+EVENT_ATTR(vc9_con,	OCX_TLK_EVENT_STAT_VC9_CON);
+EVENT_ATTR(vc10_con,	OCX_TLK_EVENT_STAT_VC10_CON);
+EVENT_ATTR(vc11_con,	OCX_TLK_EVENT_STAT_VC11_CON);
+EVENT_ATTR(vc12_con,	OCX_TLK_EVENT_STAT_VC12_CON);
+EVENT_ATTR(vc13_con,	OCX_TLK_EVENT_STAT_VC13_CON);
+
+static struct attribute *thunder_ocx_tlk_events_attr[] = {
+	EVENT_PTR(idle_cnt),
+	EVENT_PTR(data_cnt),
+	EVENT_PTR(sync_cnt),
+	EVENT_PTR(retry_cnt),
+	EVENT_PTR(err_cnt),
+	EVENT_PTR(mat0_cnt),
+	EVENT_PTR(mat1_cnt),
+	EVENT_PTR(mat2_cnt),
+	EVENT_PTR(mat3_cnt),
+	EVENT_PTR(vc0_cmd),
+	EVENT_PTR(vc1_cmd),
+	EVENT_PTR(vc2_cmd),
+	EVENT_PTR(vc3_cmd),
+	EVENT_PTR(vc4_cmd),
+	EVENT_PTR(vc5_cmd),
+	EVENT_PTR(vc0_pkt),
+	EVENT_PTR(vc1_pkt),
+	EVENT_PTR(vc2_pkt),
+	EVENT_PTR(vc3_pkt),
+	EVENT_PTR(vc4_pkt),
+	EVENT_PTR(vc5_pkt),
+	EVENT_PTR(vc6_pkt),
+	EVENT_PTR(vc7_pkt),
+	EVENT_PTR(vc8_pkt),
+	EVENT_PTR(vc9_pkt),
+	EVENT_PTR(vc10_pkt),
+	EVENT_PTR(vc11_pkt),
+	EVENT_PTR(vc12_pkt),
+	EVENT_PTR(vc13_pkt),
+	EVENT_PTR(vc0_con),
+	EVENT_PTR(vc1_con),
+	EVENT_PTR(vc2_con),
+	EVENT_PTR(vc3_con),
+	EVENT_PTR(vc4_con),
+	EVENT_PTR(vc5_con),
+	EVENT_PTR(vc6_con),
+	EVENT_PTR(vc7_con),
+	EVENT_PTR(vc8_con),
+	EVENT_PTR(vc9_con),
+	EVENT_PTR(vc10_con),
+	EVENT_PTR(vc11_con),
+	EVENT_PTR(vc12_con),
+	EVENT_PTR(vc13_con),
+	NULL,
+};
+
+static struct attribute_group thunder_ocx_tlk_events_group = {
+	.name = "events",
+	.attrs = thunder_ocx_tlk_events_attr,
+};
+
+static const struct attribute_group *thunder_ocx_tlk_attr_groups[] = {
+	&thunder_uncore_attr_group,
+	&thunder_ocx_tlk_format_group,
+	&thunder_ocx_tlk_events_group,
+	NULL,
+};
+
+struct pmu thunder_ocx_tlk_pmu = {
+	.attr_groups	= thunder_ocx_tlk_attr_groups,
+	.name		= "thunder_ocx_tlk",
+	.event_init	= thunder_uncore_event_init,
+	.add		= thunder_uncore_add,
+	.del		= thunder_uncore_del,
+	.start		= thunder_uncore_start,
+	.stop		= thunder_uncore_stop,
+	.read		= thunder_uncore_read_ocx_tlk,
+};
+
+static int event_valid(u64 config)
+{
+	if (config <= OCX_TLK_EVENT_STAT_ERR_CNT ||
+	    (config >= OCX_TLK_EVENT_STAT_MAT0_CNT &&
+	     config <= OCX_TLK_EVENT_STAT_MAT3_CNT) ||
+	    (config >= OCX_TLK_EVENT_STAT_VC0_CMD &&
+	     config <= OCX_TLK_EVENT_STAT_VC5_CMD) ||
+	    (config >= OCX_TLK_EVENT_STAT_VC0_PKT &&
+	     config <= OCX_TLK_EVENT_STAT_VC13_PKT) ||
+	    (config >= OCX_TLK_EVENT_STAT_VC0_CON &&
+	     config <= OCX_TLK_EVENT_STAT_VC13_CON))
+		return 1;
+	else
+		return 0;
+}
+
+int __init thunder_uncore_ocx_tlk_setup(void)
+{
+	int ret;
+
+	thunder_uncore_ocx_tlk = kzalloc(sizeof(struct thunder_uncore),
+					 GFP_KERNEL);
+	if (!thunder_uncore_ocx_tlk) {
+		ret = -ENOMEM;
+		goto fail_nomem;
+	}
+
+	ret = thunder_uncore_setup(thunder_uncore_ocx_tlk,
+				   PCI_DEVICE_ID_THUNDER_OCX,
+				   OCX_TLK_CONTROL_OFFSET,
+				   OCX_TLK_UNIT_OFFSET * OCX_TLK_NR_UNITS,
+				   &thunder_ocx_tlk_pmu,
+				   OCX_TLK_NR_COUNTERS);
+	if (ret)
+		goto fail;
+
+	thunder_uncore_ocx_tlk->type = OCX_TLK_TYPE;
+	thunder_uncore_ocx_tlk->event_valid = event_valid;
+	return 0;
+
+fail:
+	kfree(thunder_uncore_ocx_tlk);
+fail_nomem:
+	return ret;
+}
-- 
1.9.1

WARNING: multiple messages have this Message-ID (diff)
From: jglauber@cavium.com (Jan Glauber)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 5/5] arm64/perf: Cavium ThunderX OCX TLK uncore support
Date: Wed,  9 Mar 2016 17:21:07 +0100	[thread overview]
Message-ID: <876bae8e4fc594a646651c02ae8ab9a8c423a49e.1457539622.git.jglauber@cavium.com> (raw)
In-Reply-To: <cover.1457539621.git.jglauber@cavium.com>

Support for the OCX transmit link counters.

Signed-off-by: Jan Glauber <jglauber@cavium.com>
---
 drivers/perf/uncore/Makefile                |   3 +-
 drivers/perf/uncore/uncore_cavium.c         |   3 +
 drivers/perf/uncore/uncore_cavium.h         |   4 +
 drivers/perf/uncore/uncore_cavium_ocx_tlk.c | 380 ++++++++++++++++++++++++++++
 4 files changed, 389 insertions(+), 1 deletion(-)
 create mode 100644 drivers/perf/uncore/uncore_cavium_ocx_tlk.c

diff --git a/drivers/perf/uncore/Makefile b/drivers/perf/uncore/Makefile
index 81479e8..88d1f57 100644
--- a/drivers/perf/uncore/Makefile
+++ b/drivers/perf/uncore/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_ARCH_THUNDER) += uncore_cavium.o		\
 			      uncore_cavium_l2c_tad.o	\
 			      uncore_cavium_l2c_cbc.o	\
-			      uncore_cavium_lmc.o
+			      uncore_cavium_lmc.o	\
+			      uncore_cavium_ocx_tlk.o
diff --git a/drivers/perf/uncore/uncore_cavium.c b/drivers/perf/uncore/uncore_cavium.c
index 45c81d0..e210457 100644
--- a/drivers/perf/uncore/uncore_cavium.c
+++ b/drivers/perf/uncore/uncore_cavium.c
@@ -21,6 +21,8 @@ struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event)
 		return thunder_uncore_l2c_cbc;
 	else if (event->pmu->type == thunder_lmc_pmu.type)
 		return thunder_uncore_lmc;
+	else if (event->pmu->type == thunder_ocx_tlk_pmu.type)
+		return thunder_uncore_ocx_tlk;
 	else
 		return NULL;
 }
@@ -306,6 +308,7 @@ static int __init thunder_uncore_init(void)
 	thunder_uncore_l2c_tad_setup();
 	thunder_uncore_l2c_cbc_setup();
 	thunder_uncore_lmc_setup();
+	thunder_uncore_ocx_tlk_setup();
 	return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/drivers/perf/uncore/uncore_cavium.h b/drivers/perf/uncore/uncore_cavium.h
index f14f6be..78e95c7 100644
--- a/drivers/perf/uncore/uncore_cavium.h
+++ b/drivers/perf/uncore/uncore_cavium.h
@@ -10,6 +10,7 @@ enum uncore_type {
 	L2C_TAD_TYPE,
 	L2C_CBC_TYPE,
 	LMC_TYPE,
+	OCX_TLK_TYPE,
 };
 
 extern int thunder_uncore_version;
@@ -70,9 +71,11 @@ extern struct device_attribute format_attr_node;
 extern struct thunder_uncore *thunder_uncore_l2c_tad;
 extern struct thunder_uncore *thunder_uncore_l2c_cbc;
 extern struct thunder_uncore *thunder_uncore_lmc;
+extern struct thunder_uncore *thunder_uncore_ocx_tlk;
 extern struct pmu thunder_l2c_tad_pmu;
 extern struct pmu thunder_l2c_cbc_pmu;
 extern struct pmu thunder_lmc_pmu;
+extern struct pmu thunder_ocx_tlk_pmu;
 
 /* Prototypes */
 struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event);
@@ -89,3 +92,4 @@ ssize_t thunder_events_sysfs_show(struct device *dev,
 int thunder_uncore_l2c_tad_setup(void);
 int thunder_uncore_l2c_cbc_setup(void);
 int thunder_uncore_lmc_setup(void);
+int thunder_uncore_ocx_tlk_setup(void);
diff --git a/drivers/perf/uncore/uncore_cavium_ocx_tlk.c b/drivers/perf/uncore/uncore_cavium_ocx_tlk.c
new file mode 100644
index 0000000..02f1bc1
--- /dev/null
+++ b/drivers/perf/uncore/uncore_cavium_ocx_tlk.c
@@ -0,0 +1,380 @@
+/*
+ * Cavium Thunder uncore PMU support, OCX TLK counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glauber@cavium.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/perf_event.h>
+
+#include "uncore_cavium.h"
+
+#ifndef PCI_DEVICE_ID_THUNDER_OCX
+#define PCI_DEVICE_ID_THUNDER_OCX		0xa013
+#endif
+
+#define OCX_TLK_NR_UNITS			3
+#define OCX_TLK_UNIT_OFFSET			0x2000
+#define OCX_TLK_CONTROL_OFFSET			0x10040
+#define OCX_TLK_COUNTER_OFFSET			0x10400
+
+#define OCX_TLK_STAT_DISABLE			0
+#define OCX_TLK_STAT_ENABLE			1
+
+/* OCX TLK event list */
+#define OCX_TLK_EVENT_STAT_IDLE_CNT		0x00
+#define OCX_TLK_EVENT_STAT_DATA_CNT		0x01
+#define OCX_TLK_EVENT_STAT_SYNC_CNT		0x02
+#define OCX_TLK_EVENT_STAT_RETRY_CNT		0x03
+#define OCX_TLK_EVENT_STAT_ERR_CNT		0x04
+
+#define OCX_TLK_EVENT_STAT_MAT0_CNT		0x08
+#define OCX_TLK_EVENT_STAT_MAT1_CNT		0x09
+#define OCX_TLK_EVENT_STAT_MAT2_CNT		0x0a
+#define OCX_TLK_EVENT_STAT_MAT3_CNT		0x0b
+
+#define OCX_TLK_EVENT_STAT_VC0_CMD		0x10
+#define OCX_TLK_EVENT_STAT_VC1_CMD		0x11
+#define OCX_TLK_EVENT_STAT_VC2_CMD		0x12
+#define OCX_TLK_EVENT_STAT_VC3_CMD		0x13
+#define OCX_TLK_EVENT_STAT_VC4_CMD		0x14
+#define OCX_TLK_EVENT_STAT_VC5_CMD		0x15
+
+#define OCX_TLK_EVENT_STAT_VC0_PKT		0x20
+#define OCX_TLK_EVENT_STAT_VC1_PKT		0x21
+#define OCX_TLK_EVENT_STAT_VC2_PKT		0x22
+#define OCX_TLK_EVENT_STAT_VC3_PKT		0x23
+#define OCX_TLK_EVENT_STAT_VC4_PKT		0x24
+#define OCX_TLK_EVENT_STAT_VC5_PKT		0x25
+#define OCX_TLK_EVENT_STAT_VC6_PKT		0x26
+#define OCX_TLK_EVENT_STAT_VC7_PKT		0x27
+#define OCX_TLK_EVENT_STAT_VC8_PKT		0x28
+#define OCX_TLK_EVENT_STAT_VC9_PKT		0x29
+#define OCX_TLK_EVENT_STAT_VC10_PKT		0x2a
+#define OCX_TLK_EVENT_STAT_VC11_PKT		0x2b
+#define OCX_TLK_EVENT_STAT_VC12_PKT		0x2c
+#define OCX_TLK_EVENT_STAT_VC13_PKT		0x2d
+
+#define OCX_TLK_EVENT_STAT_VC0_CON		0x30
+#define OCX_TLK_EVENT_STAT_VC1_CON		0x31
+#define OCX_TLK_EVENT_STAT_VC2_CON		0x32
+#define OCX_TLK_EVENT_STAT_VC3_CON		0x33
+#define OCX_TLK_EVENT_STAT_VC4_CON		0x34
+#define OCX_TLK_EVENT_STAT_VC5_CON		0x35
+#define OCX_TLK_EVENT_STAT_VC6_CON		0x36
+#define OCX_TLK_EVENT_STAT_VC7_CON		0x37
+#define OCX_TLK_EVENT_STAT_VC8_CON		0x38
+#define OCX_TLK_EVENT_STAT_VC9_CON		0x39
+#define OCX_TLK_EVENT_STAT_VC10_CON		0x3a
+#define OCX_TLK_EVENT_STAT_VC11_CON		0x3b
+#define OCX_TLK_EVENT_STAT_VC12_CON		0x3c
+#define OCX_TLK_EVENT_STAT_VC13_CON		0x3d
+
+#define OCX_TLK_MAX_COUNTER			OCX_TLK_EVENT_STAT_VC13_CON
+#define OCX_TLK_NR_COUNTERS			OCX_TLK_MAX_COUNTER
+
+struct thunder_uncore *thunder_uncore_ocx_tlk;
+
+/*
+ * The OCX devices have a single device per node, therefore picking the
+ * first device from the list is correct.
+ */
+static inline void __iomem *map_offset(struct thunder_uncore_node *node,
+				       unsigned long addr, int offset, int nr)
+{
+	struct thunder_uncore_unit *unit;
+
+	unit = list_first_entry(&node->unit_list, struct thunder_uncore_unit,
+				entry);
+	return (void __iomem *) (addr + unit->map + nr * offset);
+}
+
+static void __iomem *map_offset_ocx_tlk(struct thunder_uncore_node *node,
+					unsigned long addr, int nr)
+{
+	return (void __iomem *) map_offset(node, addr, nr,
+					   OCX_TLK_UNIT_OFFSET);
+}
+
+/*
+ * Summarize counters across all TLK's. Different from the other uncore
+ * PMUs because all TLK's are on one PCI device.
+ */
+static void thunder_uncore_read_ocx_tlk(struct perf_event *event)
+{
+	struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	u64 prev, new = 0;
+	s64 delta;
+	int i;
+
+	/*
+	 * No counter overflow interrupts so we do not
+	 * have to worry about prev_count changing on us.
+	 */
+
+	prev = local64_read(&hwc->prev_count);
+
+	/* read counter values from all units */
+	node = get_node(hwc->config, uncore);
+	for (i = 0; i < OCX_TLK_NR_UNITS; i++)
+		new += readq(map_offset_ocx_tlk(node, hwc->event_base, i));
+
+	local64_set(&hwc->prev_count, new);
+	delta = new - prev;
+	local64_add(delta, &event->count);
+}
+
+static void thunder_uncore_start(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	int i;
+
+	hwc->state = 0;
+
+	/* enable counters on all units */
+	node = get_node(hwc->config, uncore);
+	for (i = 0; i < OCX_TLK_NR_UNITS; i++)
+		writeb(OCX_TLK_STAT_ENABLE,
+		       map_offset_ocx_tlk(node, hwc->config_base, i));
+
+	perf_event_update_userpage(event);
+}
+
+static void thunder_uncore_stop(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	int i;
+
+	/* disable counters on all units */
+	node = get_node(hwc->config, uncore);
+	for (i = 0; i < OCX_TLK_NR_UNITS; i++)
+		writeb(OCX_TLK_STAT_DISABLE,
+		       map_offset_ocx_tlk(node, hwc->config_base, i));
+	hwc->state |= PERF_HES_STOPPED;
+
+	if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+		thunder_uncore_read_ocx_tlk(event);
+		hwc->state |= PERF_HES_UPTODATE;
+	}
+}
+
+static int thunder_uncore_add(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	int id, i;
+
+	WARN_ON_ONCE(!uncore);
+	node = get_node(hwc->config, uncore);
+	id = get_id(hwc->config);
+
+	/* are we already assigned? */
+	if (hwc->idx != -1 && node->events[hwc->idx] == event)
+		goto out;
+
+	for (i = 0; i < node->num_counters; i++) {
+		if (node->events[i] == event) {
+			hwc->idx = i;
+			goto out;
+		}
+	}
+
+	/* counters are 1:1 */
+	hwc->idx = -1;
+	if (cmpxchg(&node->events[id], NULL, event) == NULL)
+		hwc->idx = id;
+
+out:
+	if (hwc->idx == -1)
+		return -EBUSY;
+
+	hwc->config_base = 0;
+	hwc->event_base = OCX_TLK_COUNTER_OFFSET - OCX_TLK_CONTROL_OFFSET +
+			hwc->idx * sizeof(unsigned long long);
+	hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+	if (flags & PERF_EF_START)
+		thunder_uncore_start(event, PERF_EF_RELOAD);
+	return 0;
+}
+
+PMU_FORMAT_ATTR(event, "config:0-5");
+
+static struct attribute *thunder_ocx_tlk_format_attr[] = {
+	&format_attr_event.attr,
+	&format_attr_node.attr,
+	NULL,
+};
+
+static struct attribute_group thunder_ocx_tlk_format_group = {
+	.name = "format",
+	.attrs = thunder_ocx_tlk_format_attr,
+};
+
+EVENT_ATTR(idle_cnt,	OCX_TLK_EVENT_STAT_IDLE_CNT);
+EVENT_ATTR(data_cnt,	OCX_TLK_EVENT_STAT_DATA_CNT);
+EVENT_ATTR(sync_cnt,	OCX_TLK_EVENT_STAT_SYNC_CNT);
+EVENT_ATTR(retry_cnt,	OCX_TLK_EVENT_STAT_RETRY_CNT);
+EVENT_ATTR(err_cnt,	OCX_TLK_EVENT_STAT_ERR_CNT);
+EVENT_ATTR(mat0_cnt,	OCX_TLK_EVENT_STAT_MAT0_CNT);
+EVENT_ATTR(mat1_cnt,	OCX_TLK_EVENT_STAT_MAT1_CNT);
+EVENT_ATTR(mat2_cnt,	OCX_TLK_EVENT_STAT_MAT2_CNT);
+EVENT_ATTR(mat3_cnt,	OCX_TLK_EVENT_STAT_MAT3_CNT);
+EVENT_ATTR(vc0_cmd,	OCX_TLK_EVENT_STAT_VC0_CMD);
+EVENT_ATTR(vc1_cmd,	OCX_TLK_EVENT_STAT_VC1_CMD);
+EVENT_ATTR(vc2_cmd,	OCX_TLK_EVENT_STAT_VC2_CMD);
+EVENT_ATTR(vc3_cmd,	OCX_TLK_EVENT_STAT_VC3_CMD);
+EVENT_ATTR(vc4_cmd,	OCX_TLK_EVENT_STAT_VC4_CMD);
+EVENT_ATTR(vc5_cmd,	OCX_TLK_EVENT_STAT_VC5_CMD);
+EVENT_ATTR(vc0_pkt,	OCX_TLK_EVENT_STAT_VC0_PKT);
+EVENT_ATTR(vc1_pkt,	OCX_TLK_EVENT_STAT_VC1_PKT);
+EVENT_ATTR(vc2_pkt,	OCX_TLK_EVENT_STAT_VC2_PKT);
+EVENT_ATTR(vc3_pkt,	OCX_TLK_EVENT_STAT_VC3_PKT);
+EVENT_ATTR(vc4_pkt,	OCX_TLK_EVENT_STAT_VC4_PKT);
+EVENT_ATTR(vc5_pkt,	OCX_TLK_EVENT_STAT_VC5_PKT);
+EVENT_ATTR(vc6_pkt,	OCX_TLK_EVENT_STAT_VC6_PKT);
+EVENT_ATTR(vc7_pkt,	OCX_TLK_EVENT_STAT_VC7_PKT);
+EVENT_ATTR(vc8_pkt,	OCX_TLK_EVENT_STAT_VC8_PKT);
+EVENT_ATTR(vc9_pkt,	OCX_TLK_EVENT_STAT_VC9_PKT);
+EVENT_ATTR(vc10_pkt,	OCX_TLK_EVENT_STAT_VC10_PKT);
+EVENT_ATTR(vc11_pkt,	OCX_TLK_EVENT_STAT_VC11_PKT);
+EVENT_ATTR(vc12_pkt,	OCX_TLK_EVENT_STAT_VC12_PKT);
+EVENT_ATTR(vc13_pkt,	OCX_TLK_EVENT_STAT_VC13_PKT);
+EVENT_ATTR(vc0_con,	OCX_TLK_EVENT_STAT_VC0_CON);
+EVENT_ATTR(vc1_con,	OCX_TLK_EVENT_STAT_VC1_CON);
+EVENT_ATTR(vc2_con,	OCX_TLK_EVENT_STAT_VC2_CON);
+EVENT_ATTR(vc3_con,	OCX_TLK_EVENT_STAT_VC3_CON);
+EVENT_ATTR(vc4_con,	OCX_TLK_EVENT_STAT_VC4_CON);
+EVENT_ATTR(vc5_con,	OCX_TLK_EVENT_STAT_VC5_CON);
+EVENT_ATTR(vc6_con,	OCX_TLK_EVENT_STAT_VC6_CON);
+EVENT_ATTR(vc7_con,	OCX_TLK_EVENT_STAT_VC7_CON);
+EVENT_ATTR(vc8_con,	OCX_TLK_EVENT_STAT_VC8_CON);
+EVENT_ATTR(vc9_con,	OCX_TLK_EVENT_STAT_VC9_CON);
+EVENT_ATTR(vc10_con,	OCX_TLK_EVENT_STAT_VC10_CON);
+EVENT_ATTR(vc11_con,	OCX_TLK_EVENT_STAT_VC11_CON);
+EVENT_ATTR(vc12_con,	OCX_TLK_EVENT_STAT_VC12_CON);
+EVENT_ATTR(vc13_con,	OCX_TLK_EVENT_STAT_VC13_CON);
+
+static struct attribute *thunder_ocx_tlk_events_attr[] = {
+	EVENT_PTR(idle_cnt),
+	EVENT_PTR(data_cnt),
+	EVENT_PTR(sync_cnt),
+	EVENT_PTR(retry_cnt),
+	EVENT_PTR(err_cnt),
+	EVENT_PTR(mat0_cnt),
+	EVENT_PTR(mat1_cnt),
+	EVENT_PTR(mat2_cnt),
+	EVENT_PTR(mat3_cnt),
+	EVENT_PTR(vc0_cmd),
+	EVENT_PTR(vc1_cmd),
+	EVENT_PTR(vc2_cmd),
+	EVENT_PTR(vc3_cmd),
+	EVENT_PTR(vc4_cmd),
+	EVENT_PTR(vc5_cmd),
+	EVENT_PTR(vc0_pkt),
+	EVENT_PTR(vc1_pkt),
+	EVENT_PTR(vc2_pkt),
+	EVENT_PTR(vc3_pkt),
+	EVENT_PTR(vc4_pkt),
+	EVENT_PTR(vc5_pkt),
+	EVENT_PTR(vc6_pkt),
+	EVENT_PTR(vc7_pkt),
+	EVENT_PTR(vc8_pkt),
+	EVENT_PTR(vc9_pkt),
+	EVENT_PTR(vc10_pkt),
+	EVENT_PTR(vc11_pkt),
+	EVENT_PTR(vc12_pkt),
+	EVENT_PTR(vc13_pkt),
+	EVENT_PTR(vc0_con),
+	EVENT_PTR(vc1_con),
+	EVENT_PTR(vc2_con),
+	EVENT_PTR(vc3_con),
+	EVENT_PTR(vc4_con),
+	EVENT_PTR(vc5_con),
+	EVENT_PTR(vc6_con),
+	EVENT_PTR(vc7_con),
+	EVENT_PTR(vc8_con),
+	EVENT_PTR(vc9_con),
+	EVENT_PTR(vc10_con),
+	EVENT_PTR(vc11_con),
+	EVENT_PTR(vc12_con),
+	EVENT_PTR(vc13_con),
+	NULL,
+};
+
+static struct attribute_group thunder_ocx_tlk_events_group = {
+	.name = "events",
+	.attrs = thunder_ocx_tlk_events_attr,
+};
+
+static const struct attribute_group *thunder_ocx_tlk_attr_groups[] = {
+	&thunder_uncore_attr_group,
+	&thunder_ocx_tlk_format_group,
+	&thunder_ocx_tlk_events_group,
+	NULL,
+};
+
+struct pmu thunder_ocx_tlk_pmu = {
+	.attr_groups	= thunder_ocx_tlk_attr_groups,
+	.name		= "thunder_ocx_tlk",
+	.event_init	= thunder_uncore_event_init,
+	.add		= thunder_uncore_add,
+	.del		= thunder_uncore_del,
+	.start		= thunder_uncore_start,
+	.stop		= thunder_uncore_stop,
+	.read		= thunder_uncore_read_ocx_tlk,
+};
+
+static int event_valid(u64 config)
+{
+	if (config <= OCX_TLK_EVENT_STAT_ERR_CNT ||
+	    (config >= OCX_TLK_EVENT_STAT_MAT0_CNT &&
+	     config <= OCX_TLK_EVENT_STAT_MAT3_CNT) ||
+	    (config >= OCX_TLK_EVENT_STAT_VC0_CMD &&
+	     config <= OCX_TLK_EVENT_STAT_VC5_CMD) ||
+	    (config >= OCX_TLK_EVENT_STAT_VC0_PKT &&
+	     config <= OCX_TLK_EVENT_STAT_VC13_PKT) ||
+	    (config >= OCX_TLK_EVENT_STAT_VC0_CON &&
+	     config <= OCX_TLK_EVENT_STAT_VC13_CON))
+		return 1;
+	else
+		return 0;
+}
+
+int __init thunder_uncore_ocx_tlk_setup(void)
+{
+	int ret;
+
+	thunder_uncore_ocx_tlk = kzalloc(sizeof(struct thunder_uncore),
+					 GFP_KERNEL);
+	if (!thunder_uncore_ocx_tlk) {
+		ret = -ENOMEM;
+		goto fail_nomem;
+	}
+
+	ret = thunder_uncore_setup(thunder_uncore_ocx_tlk,
+				   PCI_DEVICE_ID_THUNDER_OCX,
+				   OCX_TLK_CONTROL_OFFSET,
+				   OCX_TLK_UNIT_OFFSET * OCX_TLK_NR_UNITS,
+				   &thunder_ocx_tlk_pmu,
+				   OCX_TLK_NR_COUNTERS);
+	if (ret)
+		goto fail;
+
+	thunder_uncore_ocx_tlk->type = OCX_TLK_TYPE;
+	thunder_uncore_ocx_tlk->event_valid = event_valid;
+	return 0;
+
+fail:
+	kfree(thunder_uncore_ocx_tlk);
+fail_nomem:
+	return ret;
+}
-- 
1.9.1

  parent reply	other threads:[~2016-03-09 16:22 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-09 16:21 [PATCH v2 0/5] Cavium ThunderX uncore PMU support Jan Glauber
2016-03-09 16:21 ` Jan Glauber
2016-03-09 16:21 ` [PATCH v2 1/5] arm64/perf: Basic uncore counter support for Cavium ThunderX Jan Glauber
2016-03-09 16:21   ` Jan Glauber
2016-04-19 15:06   ` Mark Rutland
2016-04-19 15:06     ` Mark Rutland
2016-04-20 12:29     ` Jan Glauber
2016-04-20 12:29       ` Jan Glauber
2016-03-09 16:21 ` [PATCH v2 2/5] arm64/perf: Cavium ThunderX L2C TAD uncore support Jan Glauber
2016-03-09 16:21   ` Jan Glauber
2016-04-19 15:43   ` Mark Rutland
2016-04-19 15:43     ` Mark Rutland
2016-03-09 16:21 ` [PATCH v2 3/5] arm64/perf: Cavium ThunderX L2C CBC " Jan Glauber
2016-03-09 16:21   ` Jan Glauber
2016-04-19 15:56   ` Mark Rutland
2016-04-19 15:56     ` Mark Rutland
2016-03-09 16:21 ` [PATCH v2 4/5] arm64/perf: Cavium ThunderX LMC " Jan Glauber
2016-03-09 16:21   ` Jan Glauber
2016-03-09 16:21 ` Jan Glauber [this message]
2016-03-09 16:21   ` [PATCH v2 5/5] arm64/perf: Cavium ThunderX OCX TLK " Jan Glauber
2016-04-04 12:19 ` [PATCH v2 0/5] Cavium ThunderX uncore PMU support Jan Glauber
2016-04-04 12:19   ` Jan Glauber
2016-04-25 11:22   ` Will Deacon
2016-04-25 11:22     ` Will Deacon
2016-04-25 12:02     ` Jan Glauber
2016-04-25 12:02       ` Jan Glauber
2016-04-25 13:19       ` Will Deacon
2016-04-25 13:19         ` Will Deacon
2016-04-26 12:08         ` Jan Glauber
2016-04-26 12:08           ` Jan Glauber
2016-04-26 13:53           ` Will Deacon
2016-04-26 13:53             ` Will Deacon
2016-04-27 10:51             ` Jan Glauber
2016-04-27 10:51               ` Jan Glauber
2016-04-27 11:18               ` Mark Rutland
2016-04-27 11:18                 ` Mark Rutland
     [not found] ` <CAEiAFz3eCsX3VoNus_Rq+En5zuB8fAxNCbC3ktw2NqLKwC=_kA@mail.gmail.com>
2016-04-19 10:35   ` Jan Glauber
2016-04-19 10:35     ` Jan Glauber
2016-04-19 16:03     ` Mark Rutland
2016-04-19 16:03       ` Mark Rutland
2016-06-28 10:24 ` Will Deacon
2016-06-28 10:24   ` Will Deacon
2016-06-28 14:04   ` Jan Glauber
2016-06-28 14:04     ` Jan Glauber
2016-07-04 10:11     ` Will Deacon
2016-07-04 10:11       ` Will Deacon
2016-09-16  7:55       ` Will Deacon
2016-09-16  7:55         ` Will Deacon
2016-09-16  8:39         ` Jan Glauber
2016-09-16  8:39           ` Jan Glauber

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=876bae8e4fc594a646651c02ae8ab9a8c423a49e.1457539622.git.jglauber@cavium.com \
    --to=jglauber@cavium.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=will.deacon@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.