From patchwork Wed Mar 9 16:21:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Glauber X-Patchwork-Id: 8547421 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 313069F46A for ; Wed, 9 Mar 2016 16:23:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 07300202A1 for ; Wed, 9 Mar 2016 16:23:57 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E4C282021F for ; Wed, 9 Mar 2016 16:23:55 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1adgs9-0007tQ-FO; Wed, 09 Mar 2016 16:22:05 +0000 Received: from mail-wm0-f68.google.com ([74.125.82.68]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1adgrw-0007Zp-AT for linux-arm-kernel@lists.infradead.org; Wed, 09 Mar 2016 16:21:54 +0000 Received: by mail-wm0-f68.google.com with SMTP id l68so11054442wml.3 for ; Wed, 09 Mar 2016 08:21:34 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=7iSRSLXPLkMIgLKJXg+A66ETOXSaDnkOmBGkM76J54g=; b=N6MAsvjQXR9O5zkPzgRVkvf2UbUNrXSYCAKtHOlFpFJoILEuAu+OVK2y0lN3vXHjwg cSZmciLntcn0ONNPuITh/k1/iNT6EwfHDuUeHCvhomQNJWwf+oSl+ZYE2Eta8eBCziqo NON5lQmHtBMNLCQzT2REgx9pcVdIeuq4etk9dGtKFem/pS7O3vcu3VipxyNT98+Smj9d dzZZT7IjUurm/lBzUWdSp07ZGFyG95co2S+UQ0tHjC+yCY+yyhqon62cefpsG8SWdqhF aLbTJdZ5ZHQRTEuXaelevf9LdozJIDbFRySub0xjYJWVGnCOHntcYzLYyj9f0dJNSwdV 9wuQ== X-Gm-Message-State: AD7BkJItdZdc6pB7+wJr69zVx2p5nDPmcPILHGYZ73IeR1d2kvvqo5rJ/sOGIuyVM1uLdQ== X-Received: by 10.28.218.145 with SMTP id r139mr28466715wmg.52.1457540493410; Wed, 09 Mar 2016 08:21:33 -0800 (PST) Received: from wintermute.fritz.box (HSI-KBW-109-193-046-085.hsi7.kabel-badenwuerttemberg.de. [109.193.46.85]) by smtp.gmail.com with ESMTPSA id 202sm9127757wmo.7.2016.03.09.08.21.32 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 09 Mar 2016 08:21:32 -0800 (PST) From: Jan Glauber To: Mark Rutland , Will Deacon Subject: [PATCH v2 4/5] arm64/perf: Cavium ThunderX LMC uncore support Date: Wed, 9 Mar 2016 17:21:06 +0100 Message-Id: <0409c7b35218b788bc33b974ab89f610e0db2c9a.1457539622.git.jglauber@cavium.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: References: In-Reply-To: References: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160309_082152_603468_6A19A52B X-CRM114-Status: GOOD ( 21.37 ) X-Spam-Score: -2.4 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Jan Glauber MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Support counters on the DRAM controllers. Also support pass2 added counters by checking MIDR. Signed-off-by: Jan Glauber --- drivers/perf/uncore/Makefile | 3 +- drivers/perf/uncore/uncore_cavium.c | 3 + drivers/perf/uncore/uncore_cavium.h | 4 + drivers/perf/uncore/uncore_cavium_lmc.c | 196 ++++++++++++++++++++++++++++++++ 4 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 drivers/perf/uncore/uncore_cavium_lmc.c diff --git a/drivers/perf/uncore/Makefile b/drivers/perf/uncore/Makefile index d52ecc9..81479e8 100644 --- a/drivers/perf/uncore/Makefile +++ b/drivers/perf/uncore/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_ARCH_THUNDER) += uncore_cavium.o \ uncore_cavium_l2c_tad.o \ - uncore_cavium_l2c_cbc.o + uncore_cavium_l2c_cbc.o \ + uncore_cavium_lmc.o diff --git a/drivers/perf/uncore/uncore_cavium.c b/drivers/perf/uncore/uncore_cavium.c index a230450..45c81d0 100644 --- a/drivers/perf/uncore/uncore_cavium.c +++ b/drivers/perf/uncore/uncore_cavium.c @@ -19,6 +19,8 @@ struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event) return thunder_uncore_l2c_tad; else if (event->pmu->type == thunder_l2c_cbc_pmu.type) return thunder_uncore_l2c_cbc; + else if (event->pmu->type == thunder_lmc_pmu.type) + return thunder_uncore_lmc; else return NULL; } @@ -303,6 +305,7 @@ static int __init thunder_uncore_init(void) thunder_uncore_l2c_tad_setup(); thunder_uncore_l2c_cbc_setup(); + thunder_uncore_lmc_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 94bd02c..f14f6be 100644 --- a/drivers/perf/uncore/uncore_cavium.h +++ b/drivers/perf/uncore/uncore_cavium.h @@ -9,6 +9,7 @@ enum uncore_type { L2C_TAD_TYPE, L2C_CBC_TYPE, + LMC_TYPE, }; extern int thunder_uncore_version; @@ -68,8 +69,10 @@ 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 pmu thunder_l2c_tad_pmu; extern struct pmu thunder_l2c_cbc_pmu; +extern struct pmu thunder_lmc_pmu; /* Prototypes */ struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event); @@ -85,3 +88,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); diff --git a/drivers/perf/uncore/uncore_cavium_lmc.c b/drivers/perf/uncore/uncore_cavium_lmc.c new file mode 100644 index 0000000..b8d21b4 --- /dev/null +++ b/drivers/perf/uncore/uncore_cavium_lmc.c @@ -0,0 +1,196 @@ +/* + * Cavium Thunder uncore PMU support, LMC counters. + * + * Copyright 2016 Cavium Inc. + * Author: Jan Glauber + */ + +#include +#include + +#include "uncore_cavium.h" + +#ifndef PCI_DEVICE_ID_THUNDER_LMC +#define PCI_DEVICE_ID_THUNDER_LMC 0xa022 +#endif + +#define LMC_NR_COUNTERS 3 +#define LMC_PASS2_NR_COUNTERS 5 +#define LMC_MAX_NR_COUNTERS LMC_PASS2_NR_COUNTERS + +/* LMC event list */ +#define LMC_EVENT_IFB_CNT 0 +#define LMC_EVENT_OPS_CNT 1 +#define LMC_EVENT_DCLK_CNT 2 + +/* pass 2 added counters */ +#define LMC_EVENT_BANK_CONFLICT1 3 +#define LMC_EVENT_BANK_CONFLICT2 4 + +#define LMC_COUNTER_START LMC_EVENT_IFB_CNT +#define LMC_COUNTER_END (LMC_EVENT_BANK_CONFLICT2 + 8) + +struct thunder_uncore *thunder_uncore_lmc; + +int lmc_events[LMC_MAX_NR_COUNTERS] = { 0x1d0, 0x1d8, 0x1e0, 0x360, 0x368 }; + +static void thunder_uncore_start(struct perf_event *event, int flags) +{ + struct hw_perf_event *hwc = &event->hw; + + hwc->state = 0; + perf_event_update_userpage(event); +} + +static void thunder_uncore_stop(struct perf_event *event, int flags) +{ + struct hw_perf_event *hwc = &event->hw; + + if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) { + thunder_uncore_read(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; + } + } + + /* these counters are self-sustained so idx must match the counter! */ + hwc->idx = -1; + if (cmpxchg(&node->events[id], NULL, event) == NULL) + hwc->idx = i; + +out: + if (hwc->idx == -1) + return -EBUSY; + + hwc->event_base = lmc_events[id]; + hwc->state = PERF_HES_UPTODATE; + + /* counters are read-only, so avoid PERF_EF_RELOAD */ + if (flags & PERF_EF_START) + thunder_uncore_start(event, 0); + + return 0; +} + +PMU_FORMAT_ATTR(event, "config:0-2"); + +static struct attribute *thunder_lmc_format_attr[] = { + &format_attr_event.attr, + &format_attr_node.attr, + NULL, +}; + +static struct attribute_group thunder_lmc_format_group = { + .name = "format", + .attrs = thunder_lmc_format_attr, +}; + +EVENT_ATTR(ifb_cnt, LMC_EVENT_IFB_CNT); +EVENT_ATTR(ops_cnt, LMC_EVENT_OPS_CNT); +EVENT_ATTR(dclk_cnt, LMC_EVENT_DCLK_CNT); +EVENT_ATTR(bank_conflict1, LMC_EVENT_BANK_CONFLICT1); +EVENT_ATTR(bank_conflict2, LMC_EVENT_BANK_CONFLICT2); + +static struct attribute *thunder_lmc_events_attr[] = { + EVENT_PTR(ifb_cnt), + EVENT_PTR(ops_cnt), + EVENT_PTR(dclk_cnt), + NULL, +}; + +static struct attribute *thunder_lmc_pass2_events_attr[] = { + EVENT_PTR(ifb_cnt), + EVENT_PTR(ops_cnt), + EVENT_PTR(dclk_cnt), + EVENT_PTR(bank_conflict1), + EVENT_PTR(bank_conflict2), + NULL, +}; + +static struct attribute_group thunder_lmc_events_group = { + .name = "events", + .attrs = NULL, +}; + +static const struct attribute_group *thunder_lmc_attr_groups[] = { + &thunder_uncore_attr_group, + &thunder_lmc_format_group, + &thunder_lmc_events_group, + NULL, +}; + +struct pmu thunder_lmc_pmu = { + .attr_groups = thunder_lmc_attr_groups, + .name = "thunder_lmc", + .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, +}; + +static int event_valid(u64 config) +{ + if (config <= LMC_EVENT_DCLK_CNT) + return 1; + + if (thunder_uncore_version == 1) + if (config == LMC_EVENT_BANK_CONFLICT1 || + config == LMC_EVENT_BANK_CONFLICT2) + return 1; + return 0; +} + +int __init thunder_uncore_lmc_setup(void) +{ + int ret = -ENOMEM; + + thunder_uncore_lmc = kzalloc(sizeof(struct thunder_uncore), GFP_KERNEL); + if (!thunder_uncore_lmc) + goto fail_nomem; + + /* pass2 is default */ + thunder_lmc_events_group.attrs = (thunder_uncore_version == 0) ? + thunder_lmc_events_attr : thunder_lmc_pass2_events_attr; + + ret = thunder_uncore_setup(thunder_uncore_lmc, + PCI_DEVICE_ID_THUNDER_LMC, + LMC_COUNTER_START, + LMC_COUNTER_END - LMC_COUNTER_START, + &thunder_lmc_pmu, + (thunder_uncore_version == 1) ? + LMC_PASS2_NR_COUNTERS : LMC_NR_COUNTERS); + if (ret) + goto fail; + + thunder_uncore_lmc->type = LMC_TYPE; + thunder_uncore_lmc->event_valid = event_valid; + return 0; + +fail: + kfree(thunder_uncore_lmc); +fail_nomem: + return ret; +}