LKML Archive on lore.kernel.org help / color / mirror / Atom feed
From: Madhavan Srinivasan <maddy@linux.vnet.ibm.com> To: mpe@ellerman.id.au, benh@kernel.crashing.org, paulus@samba.org Cc: linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linuxppc-dev@ozlabs.org, eranian@google.com, ak@linux.intel.com, srivatsa@mit.edu, Madhavan Srinivasan <maddy@linux.vnet.ibm.com> Subject: [RFC PATCH 6/7]powerpc/powernv: add support to parse dt for nest pmu Date: Wed, 11 Mar 2015 18:37:12 +0530 [thread overview] Message-ID: <1426079233-16720-7-git-send-email-maddy@linux.vnet.ibm.com> (raw) In-Reply-To: <1426079233-16720-1-git-send-email-maddy@linux.vnet.ibm.com> Nest counter unit informations are passed on as part of device-tree to kernel. Here is the Device-tree layout. DT root folder /: / | -uncore@<chip-id> | -phb <--dt node for pcie host bridge (uncore pmu type) -... -mcs <--dt node for memory controller (uncore pmu type) | -mcs@0 <-- dt node for memory controller sub units -mcs@1 -mcs@2 -mcs@3 | - mcs_read <-- Sample event file - unit.mcs_read.unit <-- Sample event unit file. - scale.mcs_read.scale <-- Sample event scale file Patch implements generic function to creates type structure and populate events and event related information from DT. For each type structure, new pmu is registered. Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com> --- arch/powerpc/perf/uncore_pmu_p8.c | 240 +++++++++++++++++++++++++++++++++++++- 1 file changed, 238 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/perf/uncore_pmu_p8.c b/arch/powerpc/perf/uncore_pmu_p8.c index 411c077..6a347d6 100644 --- a/arch/powerpc/perf/uncore_pmu_p8.c +++ b/arch/powerpc/perf/uncore_pmu_p8.c @@ -153,8 +153,246 @@ struct pmu p8_uncore_pmu = { .read = p8_uncore_perf_event_update, }; +/* + * Populate event name and string in attribute + */ +struct attribute *dev_str_attr(char *name, char *str) +{ + struct perf_pmu_events_attr *attr; + + attr = kzalloc(sizeof(*attr), GFP_KERNEL); + + attr->event_str = (const char *)str; + attr->attr.attr.name = name; + attr->attr.attr.mode = 0444; + attr->attr.show = perf_event_sysfs_show; + + return &attr->attr.attr; +} + +int update_uncore_unit_event_group( + struct ppc64_uncore_type *ptr) +{ + struct attribute_group *attr_group; + struct attribute **attrs; + struct ppc64_uncore_type_events *ev_arry = ptr->event_arry; + char *ev_val; + int i, j; + + /* + * Count the total # of events for this uncore pmu + */ + for (j = 0; ev_arry[0].ev_offset[j] != 0; j++) + ; + + attr_group = kzalloc(sizeof(struct attribute *) * (j) + + sizeof(*attr_group), GFP_KERNEL); + if (!attr_group) + return -ENOMEM; + + attrs = (struct attribute **)(attr_group + 1); + attr_group->name = "events"; + attr_group->attrs = attrs; + + for (i = 0; i < j; i++) { + if (ev_arry[0].ev_offset[i] < 0) { + attrs[i] = dev_str_attr((char *)ev_arry[0].ev_name[i], (char *)ev_arry[0].ev_value[i]); + } else { + ev_val = kzalloc(MAX_PMU_NAME_LEN, GFP_KERNEL); + if (!ev_val) + return -ENOMEM; + sprintf((char *)ev_val, "event=0x%02x", (i+1)); + attrs[i] = dev_str_attr((char *)ev_arry[0].ev_name[i], ev_val); + } + } + + ptr->events_group = attr_group; + return 0; +} + +/* + * Parse the child node and identify events associated + * with this pmu. + */ +static int populate_events(struct device_node *dev, + struct ppc64_uncore_type *ptr, int idx) +{ + struct ppc64_uncore_type_events *ev_arry = ptr->event_arry; + struct property *pp; + int ev_idx = 0, len = 0; + const char *start, *end, *out_str; + char *buf; + const __be32 *lval; + u32 val; + + /* + * Loop through each property + */ + for_each_property_of_node(dev, pp) { + start = pp->name; + end = start + strlen(start); + len = strlen(start); + + /* Skip these, we dont need it */ + if (!strcmp(pp->name, "name") || + !strcmp(pp->name, "phandle") || + !strcmp(pp->name, "ibm,dev-id") || + !strcmp(pp->name, "linux,phandle")) + continue; + + buf = kzalloc(MAX_PMU_NAME_LEN, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + /* + * Event may have corresponding unit and scale + * information. Incase of unit and scale, populate + * the offset value to negative. + */ + if (strncmp(pp->name, "unit.", 5) == 0) { + of_property_read_string(dev, pp->name, &out_str); + start += 5; + len = strlen(start); + strncpy(buf, start, strlen(start)); + of_property_read_string(dev, pp->value, &out_str); + + ev_arry[idx].ev_offset[ev_idx] = -1; + ev_arry[idx].ev_name[ev_idx] = buf; + ev_arry[idx].ev_value[ev_idx] = out_str; + ev_idx++; + continue; + } + + if (strncmp(pp->name, "scale.", 6) == 0) { + of_property_read_string(dev, pp->name, &out_str); + start += 6; + len = strlen(start); + strncpy(buf, start, strlen(start)); + of_property_read_string(dev, pp->value, &out_str); + + ev_arry[idx].ev_offset[ev_idx] = -1; + ev_arry[idx].ev_name[ev_idx] = buf; + ev_arry[idx].ev_value[ev_idx] = out_str; + ev_idx++; + continue; + } + + /* + * Event support by this pmu. + */ + lval = of_get_property(dev, pp->name, NULL); + val = (uint32_t)be32_to_cpup(lval); + strncpy(buf, start, len); + ev_arry[idx].ev_offset[ev_idx] = val; + ev_arry[idx].ev_name[ev_idx] = buf; + ev_arry[idx].ev_value[ev_idx] = "\0"; + ev_idx++; + } + return 0; +} + +static int uncore_unit_parse(struct device_node *parent, + struct ppc64_uncore_type *ptr) +{ + struct device_node *child; + const __be32 *unit_idx; + int idx; + + for_each_available_child_of_node(parent, child) { + unit_idx = of_get_property(child, "ibm,dev-id", NULL); + idx = (uint32_t)be32_to_cpup(unit_idx); + if (populate_events(child, ptr, idx)) + return -1; + } + + if (update_uncore_unit_event_group(ptr)) + return -1; + + return 0; +} + +static int uncore_create_types(struct device_node *parent) +{ + struct device_node *dev_type; + struct ppc64_uncore_type *uncore_type; + const __be32 *uncore_type_units; + int idx = 0, i; + + for_each_child_of_node(parent, dev_type) { + uncore_type = (struct ppc64_uncore_type *) + kzalloc(sizeof(struct ppc64_uncore_type), + GFP_KERNEL); + if (!uncore_type) + goto fail; + + /* + * Populate the uncore pmu type name and + * # of sub units. + */ + uncore_type->name = of_get_property(dev_type, + "name", NULL); + uncore_type_units = of_get_property(dev_type, + "sub_units", NULL); + uncore_type->num_boxes = be32_to_cpup(uncore_type_units); + + if (uncore_unit_parse(dev_type, uncore_type)) + goto fail; + + uncore_type->format_group = &p8_uncore_format_group; + uncore_type->pmu = &p8_uncore_pmu; + + p8_uncore[idx++] = uncore_type; + } + + return 0; + +fail: + for (i = 0; i < idx; i++) + kfree(p8_uncore[i]); + return -1; +} + static int uncore_init(void) { + struct device_node *dev; + const __be32 *gcid; + const __be64 *chip_ima_reg; + const __be32 *chip_ima_size; + int idx = 0; + + dev = of_find_node_with_property(NULL, "ibm,uncore"); + if (!dev) + return -EINVAL; + + for_each_node_with_property(dev, "ibm,uncore") { + gcid = of_get_property(dev, "ibm,chip-id", NULL); + chip_ima_reg = of_get_property(dev, "reg", NULL); + chip_ima_size = of_get_property(dev, "size", NULL); + if ((!gcid) || (!chip_ima_reg) || (!chip_ima_size)) { + pr_err("%s: device %s missing property \n", + __func__, dev->full_name); + return -EINVAL; + } + + /* + * Get the chip id, populate + * address range/size and translate it. + */ + idx = (uint32_t)be32_to_cpup(gcid); + uncore_per_chip[idx].chip_id = (uint32_t)be32_to_cpup(gcid); + uncore_per_chip[idx].preg_base = be64_to_cpup(chip_ima_reg); + uncore_per_chip[idx].size = be32_to_cpup(chip_ima_size); + uncore_per_chip[idx].vreg_base = (u64)ioremap( + (phys_addr_t)uncore_per_chip[idx].preg_base, + uncore_per_chip[idx].size); + + /* + * looks for uncore pmu types supported here. + */ + if (uncore_create_types(dev)) + return -EINVAL; + } + return 0; } @@ -163,5 +401,3 @@ int uncore_p8_init(void) ppc64_uncore = p8_uncore; return uncore_init(); } - - -- 1.9.1
next prev parent reply other threads:[~2015-03-11 13:10 UTC|newest] Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-03-11 13:07 [RFC PATCH 0/7] powerpc/powernv: Nest Instrumentation support Madhavan Srinivasan 2015-03-11 13:07 ` [RFC PATCH 1/7] powerpc/powernv: Data structure and macros definition Madhavan Srinivasan 2015-03-11 13:07 ` [RFC PATCH 2/7] powerpc/powernv: uncore foundation code Madhavan Srinivasan 2015-03-11 13:07 ` [RFC PATCH 3/7] powerpc/powernv: uncore cpumask and CPU hotplug Madhavan Srinivasan 2015-03-11 13:07 ` [RFC PATCH 4/7]powerpc/powernv: Add OPAL support for Nest pmu Madhavan Srinivasan 2015-03-11 22:57 ` Stewart Smith 2015-03-12 8:47 ` maddy 2015-03-11 13:07 ` [RFC PATCH 5/7]powerpc/powernv: Add POWER8 specific nest pmu support Madhavan Srinivasan 2015-03-11 13:07 ` Madhavan Srinivasan [this message] 2015-03-11 13:07 ` [RFC PATCH 7/7]powerpc/powernv: enable nest pmu related file in Makefile Madhavan Srinivasan
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=1426079233-16720-7-git-send-email-maddy@linux.vnet.ibm.com \ --to=maddy@linux.vnet.ibm.com \ --cc=ak@linux.intel.com \ --cc=benh@kernel.crashing.org \ --cc=eranian@google.com \ --cc=linux-kernel@vger.kernel.org \ --cc=linuxppc-dev@lists.ozlabs.org \ --cc=linuxppc-dev@ozlabs.org \ --cc=mpe@ellerman.id.au \ --cc=paulus@samba.org \ --cc=srivatsa@mit.edu \ /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: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
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).