Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.2/patches/833364/?format=api
{ "id": 833364, "url": "http://patchwork.ozlabs.org/api/1.2/patches/833364/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ubuntu-kernel/patch/20171102140501.87671-3-gwalbon@linux.vnet.ibm.com/", "project": { "id": 15, "url": "http://patchwork.ozlabs.org/api/1.2/projects/15/?format=api", "name": "Ubuntu Kernel", "link_name": "ubuntu-kernel", "list_id": "kernel-team.lists.ubuntu.com", "list_email": "kernel-team@lists.ubuntu.com", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20171102140501.87671-3-gwalbon@linux.vnet.ibm.com>", "list_archive_url": null, "date": "2017-11-02T14:04:51", "name": "[Artful,02/12] powerpc/powernv: Detect and create IMC device", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "9058378f40909856044bdf092d02d76ba7e3886d", "submitter": { "id": 71662, "url": "http://patchwork.ozlabs.org/api/1.2/people/71662/?format=api", "name": "Gustavo Walbon", "email": "gwalbon@linux.vnet.ibm.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/ubuntu-kernel/patch/20171102140501.87671-3-gwalbon@linux.vnet.ibm.com/mbox/", "series": [ { "id": 11509, "url": "http://patchwork.ozlabs.org/api/1.2/series/11509/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ubuntu-kernel/list/?series=11509", "date": "2017-11-02T14:04:50", "name": "Backport for Power9 Nest PMU Instrumentation", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/11509/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/833364/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/833364/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<kernel-team-bounces@lists.ubuntu.com>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com\n\t(client-ip=91.189.94.19; helo=huckleberry.canonical.com;\n\tenvelope-from=kernel-team-bounces@lists.ubuntu.com;\n\treceiver=<UNKNOWN>)", "Received": [ "from huckleberry.canonical.com (huckleberry.canonical.com\n\t[91.189.94.19])\n\tby ozlabs.org (Postfix) with ESMTP id 3ySRgV4YFYz9t3f;\n\tFri, 3 Nov 2017 01:05:26 +1100 (AEDT)", "from localhost ([127.0.0.1] helo=huckleberry.canonical.com)\n\tby huckleberry.canonical.com with esmtp (Exim 4.86_2)\n\t(envelope-from <kernel-team-bounces@lists.ubuntu.com>)\n\tid 1eAG7W-0002Du-9O; Thu, 02 Nov 2017 14:05:22 +0000", "from mx0a-001b2d01.pphosted.com ([148.163.156.1])\n\tby huckleberry.canonical.com with esmtps\n\t(TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2)\n\t(envelope-from <gwalbon@linux.vnet.ibm.com>) id 1eAG7P-00027p-1P\n\tfor kernel-team@lists.ubuntu.com; Thu, 02 Nov 2017 14:05:15 +0000", "from pps.filterd (m0098396.ppops.net [127.0.0.1])\n\tby mx0a-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id\n\tvA2E4UnJ062539\n\tfor <kernel-team@lists.ubuntu.com>; Thu, 2 Nov 2017 10:05:13 -0400", "from e19.ny.us.ibm.com (e19.ny.us.ibm.com [129.33.205.209])\n\tby mx0a-001b2d01.pphosted.com with ESMTP id 2e038upewk-1\n\t(version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT)\n\tfor <kernel-team@lists.ubuntu.com>; Thu, 02 Nov 2017 10:05:11 -0400", "from localhost\n\tby e19.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use\n\tOnly! Violators will be prosecuted\n\tfor <kernel-team@lists.ubuntu.com> from <gwalbon@linux.vnet.ibm.com>; \n\tThu, 2 Nov 2017 10:05:09 -0400", "from b01cxnp22033.gho.pok.ibm.com (9.57.198.23)\n\tby e19.ny.us.ibm.com (146.89.104.206) with IBM ESMTP SMTP Gateway:\n\tAuthorized Use Only! Violators will be prosecuted; \n\tThu, 2 Nov 2017 10:05:08 -0400", "from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com\n\t[9.57.199.110])\n\tby b01cxnp22033.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP\n\tid vA2E57fw40239192; Thu, 2 Nov 2017 14:05:07 GMT", "from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1])\n\tby IMSVA (Postfix) with ESMTP id 525A1AE034;\n\tThu, 2 Nov 2017 10:05:54 -0400 (EDT)", "from localhost (unknown [9.85.138.60])\n\tby b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP id 826A7AE054;\n\tThu, 2 Nov 2017 10:05:53 -0400 (EDT)" ], "From": "Gustavo Walbon <gwalbon@linux.vnet.ibm.com>", "To": "kernel-team@lists.ubuntu.com", "Subject": "[Artful][PATCH 02/12] powerpc/powernv: Detect and create IMC device", "Date": "Thu, 2 Nov 2017 12:04:51 -0200", "X-Mailer": "git-send-email 2.13.3", "In-Reply-To": "<20171102140501.87671-1-gwalbon@linux.vnet.ibm.com>", "References": "<20171102140501.87671-1-gwalbon@linux.vnet.ibm.com>", "X-TM-AS-GCONF": "00", "x-cbid": "17110214-0056-0000-0000-000003E36CAC", "X-IBM-SpamModules-Scores": "", "X-IBM-SpamModules-Versions": "BY=3.00007997; HX=3.00000241; KW=3.00000007;\n\tPH=3.00000004; SC=3.00000239; SDB=6.00940090; UDB=6.00474019;\n\tIPR=6.00720346; \n\tBA=6.00005666; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009;\n\tZB=6.00000000; \n\tZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00017836;\n\tXFM=3.00000015; UTC=2017-11-02 14:05:09", "X-IBM-AV-DETECTION": "SAVI=unused REMOTE=unused XFE=unused", "x-cbparentid": "17110214-0057-0000-0000-0000081A7FD0", "Message-Id": "<20171102140501.87671-3-gwalbon@linux.vnet.ibm.com>", "X-Proofpoint-Virus-Version": "vendor=fsecure engine=2.50.10432:, ,\n\tdefinitions=2017-11-02_05:, , signatures=0", "X-Proofpoint-Spam-Details": "rule=outbound_notspam policy=outbound score=0\n\tpriorityscore=1501\n\tmalwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0\n\tclxscore=1011 lowpriorityscore=0 impostorscore=0 adultscore=0\n\tclassifier=spam adjust=0 reason=mlx scancount=1\n\tengine=8.0.1-1707230000\n\tdefinitions=main-1711020178", "X-BeenThere": "kernel-team@lists.ubuntu.com", "X-Mailman-Version": "2.1.20", "Precedence": "list", "List-Id": "Kernel team discussions <kernel-team.lists.ubuntu.com>", "List-Unsubscribe": "<https://lists.ubuntu.com/mailman/options/kernel-team>,\n\t<mailto:kernel-team-request@lists.ubuntu.com?subject=unsubscribe>", "List-Archive": "<https://lists.ubuntu.com/archives/kernel-team>", "List-Post": "<mailto:kernel-team@lists.ubuntu.com>", "List-Help": "<mailto:kernel-team-request@lists.ubuntu.com?subject=help>", "List-Subscribe": "<https://lists.ubuntu.com/mailman/listinfo/kernel-team>,\n\t<mailto:kernel-team-request@lists.ubuntu.com?subject=subscribe>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "base64", "Errors-To": "kernel-team-bounces@lists.ubuntu.com", "Sender": "\"kernel-team\" <kernel-team-bounces@lists.ubuntu.com>" }, "content": "From: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>\n\nBugLink: https://bugs.launchpad.net/bugs/1481347\n\nCode to create platform device for the In-Memory Collection (IMC)\ncounters. Platform devices are created based on the IMC compatibility.\nNew header file created to contain the data structures and macros\nneeded for In-Memory Collection (IMC) counter pmu devices.\n\nThe device tree for IMC counters starts at the node \"imc-counters\".\nThis node contains all the IMC PMU nodes and event nodes for these IMC\nPMUs. Device probe() parses the device to locate three possible IMC\ndevice types (Nest/Core/Thread). Function then branch to parse each\nunit nodes to populate vital information such as device memory sizes,\nevent nodes information, base address for reserve memory access (if\nany) and so on. Simple bare-minimum shutdown function added which only\n\"stops\" the engines.\n\nSigned-off-by: Anju T Sudhakar <anju@linux.vnet.ibm.com>\nSigned-off-by: Hemant Kumar <hemant@linux.vnet.ibm.com>\nSigned-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>\n[mpe: Fix build with CONFIG_PERF_EVENTS=n]\nSigned-off-by: Michael Ellerman <mpe@ellerman.id.au>\n(cherry-picked from 8f95faaac56c18b32d0e23ace55417a440abdb7e)\nSigned-off-by: Gustavo Walbon <gwalbon@linux.vnet.ibm.com>\n---\n arch/powerpc/include/asm/imc-pmu.h | 128 +++++++++++++++++\n arch/powerpc/platforms/powernv/Makefile | 1 +\n arch/powerpc/platforms/powernv/opal-imc.c | 221 ++++++++++++++++++++++++++++++\n arch/powerpc/platforms/powernv/opal.c | 14 ++\n 4 files changed, 364 insertions(+)\n create mode 100644 arch/powerpc/include/asm/imc-pmu.h\n create mode 100644 arch/powerpc/platforms/powernv/opal-imc.c", "diff": "diff --git a/arch/powerpc/include/asm/imc-pmu.h b/arch/powerpc/include/asm/imc-pmu.h\nnew file mode 100644\nindex 000000000000..7f74c282710f\n--- /dev/null\n+++ b/arch/powerpc/include/asm/imc-pmu.h\n@@ -0,0 +1,128 @@\n+#ifndef __ASM_POWERPC_IMC_PMU_H\n+#define __ASM_POWERPC_IMC_PMU_H\n+\n+/*\n+ * IMC Nest Performance Monitor counter support.\n+ *\n+ * Copyright (C) 2017 Madhavan Srinivasan, IBM Corporation.\n+ * (C) 2017 Anju T Sudhakar, IBM Corporation.\n+ * (C) 2017 Hemant K Shaw, IBM Corporation.\n+ *\n+ * This program is free software; you can redistribute it and/or\n+ * modify it under the terms of the GNU General Public License\n+ * as published by the Free Software Foundation; either version\n+ * 2 of the License, or later version.\n+ */\n+\n+#include <linux/perf_event.h>\n+#include <linux/slab.h>\n+#include <linux/of.h>\n+#include <linux/io.h>\n+#include <asm/opal.h>\n+\n+/*\n+ * For static allocation of some of the structures.\n+ */\n+#define IMC_MAX_PMUS\t\t\t32\n+\n+/*\n+ * Compatibility macros for IMC devices\n+ */\n+#define IMC_DTB_COMPAT\t\t\t\"ibm,opal-in-memory-counters\"\n+#define IMC_DTB_UNIT_COMPAT\t\t\"ibm,imc-counters\"\n+\n+\n+/*\n+ * LDBAR: Counter address and Enable/Disable macro.\n+ * perf/imc-pmu.c has the LDBAR layout information.\n+ */\n+#define THREAD_IMC_LDBAR_MASK 0x0003ffffffffe000ULL\n+#define THREAD_IMC_ENABLE 0x8000000000000000ULL\n+\n+/*\n+ * Structure to hold memory address information for imc units.\n+ */\n+struct imc_mem_info {\n+\tu64 *vbase;\n+\tu32 id;\n+};\n+\n+/*\n+ * Place holder for nest pmu events and values.\n+ */\n+struct imc_events {\n+\tu32 value;\n+\tchar *name;\n+\tchar *unit;\n+\tchar *scale;\n+};\n+\n+/* Event attribute array index */\n+#define IMC_FORMAT_ATTR\t\t0\n+#define IMC_EVENT_ATTR\t\t1\n+#define IMC_CPUMASK_ATTR\t2\n+#define IMC_NULL_ATTR\t\t3\n+\n+/* PMU Format attribute macros */\n+#define IMC_EVENT_OFFSET_MASK\t0xffffffffULL\n+\n+/*\n+ * Device tree parser code detects IMC pmu support and\n+ * registers new IMC pmus. This structure will hold the\n+ * pmu functions, events, counter memory information\n+ * and attrs for each imc pmu and will be referenced at\n+ * the time of pmu registration.\n+ */\n+struct imc_pmu {\n+\tstruct pmu pmu;\n+\tstruct imc_mem_info *mem_info;\n+\tstruct imc_events **events;\n+\t/*\n+\t * Attribute groups for the PMU. Slot 0 used for\n+\t * format attribute, slot 1 used for cpusmask attribute,\n+\t * slot 2 used for event attribute. Slot 3 keep as\n+\t * NULL.\n+\t */\n+\tconst struct attribute_group *attr_groups[4];\n+\tu32 counter_mem_size;\n+\tint domain;\n+\t/*\n+\t * flag to notify whether the memory is mmaped\n+\t * or allocated by kernel.\n+\t */\n+\tbool imc_counter_mmaped;\n+};\n+\n+/*\n+ * Structure to hold id, lock and reference count for the imc events which\n+ * are inited.\n+ */\n+struct imc_pmu_ref {\n+\tstruct mutex lock;\n+\tunsigned int id;\n+\tint refc;\n+};\n+\n+/*\n+ * In-Memory Collection Counters type.\n+ * Data comes from Device tree.\n+ * Three device type are supported.\n+ */\n+\n+enum {\n+\tIMC_TYPE_THREAD\t\t= 0x1,\n+\tIMC_TYPE_CORE\t\t= 0x4,\n+\tIMC_TYPE_CHIP = 0x10,\n+};\n+\n+/*\n+ * Domains for IMC PMUs\n+ */\n+#define IMC_DOMAIN_NEST\t\t1\n+#define IMC_DOMAIN_CORE\t\t2\n+#define IMC_DOMAIN_THREAD\t3\n+\n+extern int init_imc_pmu(struct device_node *parent,\n+\t\t\t\tstruct imc_pmu *pmu_ptr, int pmu_id);\n+extern void thread_imc_disable(void);\n+#endif /* __ASM_POWERPC_IMC_PMU_H */\ndiff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile\nindex b5d98cb3f482..a0d4353a17c9 100644\n--- a/arch/powerpc/platforms/powernv/Makefile\n+++ b/arch/powerpc/platforms/powernv/Makefile\n@@ -12,3 +12,4 @@ obj-$(CONFIG_PPC_SCOM)\t+= opal-xscom.o\n obj-$(CONFIG_MEMORY_FAILURE)\t+= opal-memory-errors.o\n obj-$(CONFIG_TRACEPOINTS)\t+= opal-tracepoints.o\n obj-$(CONFIG_OPAL_PRD)\t+= opal-prd.o\n+obj-$(CONFIG_PERF_EVENTS) += opal-imc.o\ndiff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c\nnew file mode 100644\nindex 000000000000..f57a6fbd3f57\n--- /dev/null\n+++ b/arch/powerpc/platforms/powernv/opal-imc.c\n@@ -0,0 +1,221 @@\n+/*\n+ * OPAL IMC interface detection driver\n+ * Supported on POWERNV platform\n+ *\n+ * Copyright\t(C) 2017 Madhavan Srinivasan, IBM Corporation.\n+ *\t\t(C) 2017 Anju T Sudhakar, IBM Corporation.\n+ *\t\t(C) 2017 Hemant K Shaw, IBM Corporation.\n+ *\n+ * This program is free software; you can redistribute it and/or\n+ * modify it under the terms of the GNU General Public License\n+ * as published by the Free Software Foundation; either version\n+ * 2 of the License, or later version.\n+ */\n+#include <linux/kernel.h>\n+#include <linux/platform_device.h>\n+#include <linux/of.h>\n+#include <linux/of_address.h>\n+#include <linux/of_platform.h>\n+#include <linux/crash_dump.h>\n+#include <asm/opal.h>\n+#include <asm/io.h>\n+#include <asm/imc-pmu.h>\n+#include <asm/cputhreads.h>\n+\n+/*\n+ * imc_get_mem_addr_nest: Function to get nest counter memory region\n+ * for each chip\n+ */\n+static int imc_get_mem_addr_nest(struct device_node *node,\n+\t\t\t\t struct imc_pmu *pmu_ptr,\n+\t\t\t\t u32 offset)\n+{\n+\tint nr_chips = 0, i;\n+\tu64 *base_addr_arr, baddr;\n+\tu32 *chipid_arr;\n+\n+\tnr_chips = of_property_count_u32_elems(node, \"chip-id\");\n+\tif (nr_chips <= 0)\n+\t\treturn -ENODEV;\n+\n+\tbase_addr_arr = kcalloc(nr_chips, sizeof(u64), GFP_KERNEL);\n+\tif (!base_addr_arr)\n+\t\treturn -ENOMEM;\n+\n+\tchipid_arr = kcalloc(nr_chips, sizeof(u32), GFP_KERNEL);\n+\tif (!chipid_arr)\n+\t\treturn -ENOMEM;\n+\n+\tif (of_property_read_u32_array(node, \"chip-id\", chipid_arr, nr_chips))\n+\t\tgoto error;\n+\n+\tif (of_property_read_u64_array(node, \"base-addr\", base_addr_arr,\n+\t\t\t\t\t\t\t\tnr_chips))\n+\t\tgoto error;\n+\n+\tpmu_ptr->mem_info = kcalloc(nr_chips, sizeof(struct imc_mem_info),\n+\t\t\t\t\t\t\t\tGFP_KERNEL);\n+\tif (!pmu_ptr->mem_info)\n+\t\tgoto error;\n+\n+\tfor (i = 0; i < nr_chips; i++) {\n+\t\tpmu_ptr->mem_info[i].id = chipid_arr[i];\n+\t\tbaddr = base_addr_arr[i] + offset;\n+\t\tpmu_ptr->mem_info[i].vbase = phys_to_virt(baddr);\n+\t}\n+\n+\tpmu_ptr->imc_counter_mmaped = true;\n+\tkfree(base_addr_arr);\n+\tkfree(chipid_arr);\n+\treturn 0;\n+\n+error:\n+\tkfree(pmu_ptr->mem_info);\n+\tkfree(base_addr_arr);\n+\tkfree(chipid_arr);\n+\treturn -1;\n+}\n+\n+/*\n+ * imc_pmu_create : Takes the parent device which is the pmu unit, pmu_index\n+ *\t\t and domain as the inputs.\n+ * Allocates memory for the struct imc_pmu, sets up its domain, size and offsets\n+ */\n+static int imc_pmu_create(struct device_node *parent, int pmu_index, int domain)\n+{\n+\tint ret = 0;\n+\tstruct imc_pmu *pmu_ptr;\n+\tu32 offset;\n+\n+\t/* memory for pmu */\n+\tpmu_ptr = kzalloc(sizeof(struct imc_pmu), GFP_KERNEL);\n+\tif (!pmu_ptr)\n+\t\treturn -ENOMEM;\n+\n+\t/* Set the domain */\n+\tpmu_ptr->domain = domain;\n+\n+\tret = of_property_read_u32(parent, \"size\", &pmu_ptr->counter_mem_size);\n+\tif (ret) {\n+\t\tret = -EINVAL;\n+\t\tgoto free_pmu;\n+\t}\n+\n+\tif (!of_property_read_u32(parent, \"offset\", &offset)) {\n+\t\tif (imc_get_mem_addr_nest(parent, pmu_ptr, offset)) {\n+\t\t\tret = -EINVAL;\n+\t\t\tgoto free_pmu;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+\n+free_pmu:\n+\tkfree(pmu_ptr);\n+\treturn ret;\n+}\n+\n+static void disable_nest_pmu_counters(void)\n+{\n+\tint nid, cpu;\n+\tstruct cpumask *l_cpumask;\n+\n+\tget_online_cpus();\n+\tfor_each_online_node(nid) {\n+\t\tl_cpumask = cpumask_of_node(nid);\n+\t\tcpu = cpumask_first(l_cpumask);\n+\t\topal_imc_counters_stop(OPAL_IMC_COUNTERS_NEST,\n+\t\t\t\t get_hard_smp_processor_id(cpu));\n+\t}\n+\tput_online_cpus();\n+}\n+\n+static void disable_core_pmu_counters(void)\n+{\n+\tcpumask_t cores_map;\n+\tint cpu, rc;\n+\n+\tget_online_cpus();\n+\t/* Disable the IMC Core functions */\n+\tcores_map = cpu_online_cores_map();\n+\tfor_each_cpu(cpu, &cores_map) {\n+\t\trc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,\n+\t\t\t\t\t get_hard_smp_processor_id(cpu));\n+\t\tif (rc)\n+\t\t\tpr_err(\"%s: Failed to stop Core (cpu = %d)\\n\",\n+\t\t\t\t__FUNCTION__, cpu);\n+\t}\n+\tput_online_cpus();\n+}\n+\n+static int opal_imc_counters_probe(struct platform_device *pdev)\n+{\n+\tstruct device_node *imc_dev = pdev->dev.of_node;\n+\tint pmu_count = 0, domain;\n+\tu32 type;\n+\n+\t/*\n+\t * Check whether this is kdump kernel. If yes, force the engines to\n+\t * stop and return.\n+\t */\n+\tif (is_kdump_kernel()) {\n+\t\tdisable_nest_pmu_counters();\n+\t\tdisable_core_pmu_counters();\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tfor_each_compatible_node(imc_dev, NULL, IMC_DTB_UNIT_COMPAT) {\n+\t\tif (of_property_read_u32(imc_dev, \"type\", &type)) {\n+\t\t\tpr_warn(\"IMC Device without type property\\n\");\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tswitch (type) {\n+\t\tcase IMC_TYPE_CHIP:\n+\t\t\tdomain = IMC_DOMAIN_NEST;\n+\t\t\tbreak;\n+\t\tcase IMC_TYPE_CORE:\n+\t\t\tdomain =IMC_DOMAIN_CORE;\n+\t\t\tbreak;\n+\t\tcase IMC_TYPE_THREAD:\n+\t\t\tdomain = IMC_DOMAIN_THREAD;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tpr_warn(\"IMC Unknown Device type \\n\");\n+\t\t\tdomain = -1;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (!imc_pmu_create(imc_dev, pmu_count, domain))\n+\t\t\tpmu_count++;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static void opal_imc_counters_shutdown(struct platform_device *pdev)\n+{\n+\t/*\n+\t * Function only stops the engines which is bare minimum.\n+\t * TODO: Need to handle proper memory cleanup and pmu\n+\t * unregister.\n+\t */\n+\tdisable_nest_pmu_counters();\n+\tdisable_core_pmu_counters();\n+}\n+\n+static const struct of_device_id opal_imc_match[] = {\n+\t{ .compatible = IMC_DTB_COMPAT },\n+\t{},\n+};\n+\n+static struct platform_driver opal_imc_driver = {\n+\t.driver = {\n+\t\t.name = \"opal-imc-counters\",\n+\t\t.of_match_table = opal_imc_match,\n+\t},\n+\t.probe = opal_imc_counters_probe,\n+\t.shutdown = opal_imc_counters_shutdown,\n+};\n+\n+builtin_platform_driver(opal_imc_driver);\ndiff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c\nindex cad6b57ce494..946158e6fc1d 100644\n--- a/arch/powerpc/platforms/powernv/opal.c\n+++ b/arch/powerpc/platforms/powernv/opal.c\n@@ -16,6 +16,7 @@\n #include <linux/of.h>\n #include <linux/of_fdt.h>\n #include <linux/of_platform.h>\n+#include <linux/of_address.h>\n #include <linux/interrupt.h>\n #include <linux/notifier.h>\n #include <linux/slab.h>\n@@ -30,6 +31,7 @@\n #include <asm/opal.h>\n #include <asm/firmware.h>\n #include <asm/mce.h>\n+#include <asm/imc-pmu.h>\n \n #include \"powernv.h\"\n \n@@ -720,6 +722,15 @@ static void opal_pdev_init(const char *compatible)\n \t\tof_platform_device_create(np, NULL, NULL);\n }\n \n+static void __init opal_imc_init_dev(void)\n+{\n+\tstruct device_node *np;\n+\n+\tnp = of_find_compatible_node(NULL, NULL, IMC_DTB_COMPAT);\n+\tif (np)\n+\t\tof_platform_device_create(np, NULL, NULL);\n+}\n+\n static int kopald(void *unused)\n {\n \tunsigned long timeout = msecs_to_jiffies(opal_heartbeat) + 1;\n@@ -793,6 +804,9 @@ static int __init opal_init(void)\n \t/* Setup a heatbeat thread if requested by OPAL */\n \topal_init_heartbeat();\n \n+\t/* Detect In-Memory Collection counters and create devices*/\n+\topal_imc_init_dev();\n+\n \t/* Create leds platform devices */\n \tleds = of_find_node_by_path(\"/ibm,opal/leds\");\n \tif (leds) {\n", "prefixes": [ "Artful", "02/12" ] }