From patchwork Fri Jun 23 13:01:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Glauber X-Patchwork-Id: 9806431 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 08F5560329 for ; Fri, 23 Jun 2017 13:03:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E23FF2865B for ; Fri, 23 Jun 2017 13:03:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D692E2868F; Fri, 23 Jun 2017 13:03:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1A7282867D for ; Fri, 23 Jun 2017 13:03:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=ebUjMFdVLdpLLqX8cfiKQawu6b6wluhhEYD3YeyvRjI=; b=MMSdIrJpEmBmS4YeogQ3gKo/6N 3QM2c5GxYXJRNy8PowM36RlUqYPXMXfoHNnGR0omS7aVEldcl7QtnyhZPp78+M3izu+RIYHd3V/oh b+ygrTUXo+Ipx2HZQubacM29Erlu2/Ej8iaGiK4/OCjGgaoZs2jr8csWLzmeLxXPyX1kEraPvK2NF 9N+1za3h2ujAGB/SkbC685u9NQ/lyaAoVtq85JueV6V/7oDlNTou9jZ4kWb15abl8eCZMH5yasQOU luxaD0ZPzQ2fU+b97YJgoncXSXddV8PfcpxOftfpMIGd25JSjQKnP/JCGfSejmrfIDc91fPqD0jrK JaA8ZHgA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dOOEs-0004f8-Tr; Fri, 23 Jun 2017 13:03:06 +0000 Received: from mail-wr0-f193.google.com ([209.85.128.193]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dOOEI-0003bh-Oa for linux-arm-kernel@lists.infradead.org; Fri, 23 Jun 2017 13:02:33 +0000 Received: by mail-wr0-f193.google.com with SMTP id k67so12384063wrc.1 for ; Fri, 23 Jun 2017 06:02:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4kVVu3i3rJWd2bPQJkHokGQK4Vny81+WNziyp28wTpk=; b=Wt4VX/XKTyZLGM4Tw8qDQI2TUcXpabFTNv4RsKxOisGlbgDHUpT+0sd2pEcl8ED7ML A5svmDv2LTy59wIPL9RPD3QJeC8j/wNIeLkA8bXNnVF5Cs/GVAmiSDqRrMtdOa04+QdJ 1QCzpQzoPrHF98YijgCY0Cuv0EzKr+b2WMR3aus6gD7noUxhbsSKgKUsECSMy2hIUJPJ eFZM0ie7Ko7+OzWVfYrjlXUGidDm3GveFeZhUtU5svqx/LDn+vNelk4WBYtu1aqaXH1K 2OP301Q9n7ptSRuHFp+uMiM4Jr6OxS8PReNVbbeJGcl1H1mvFi7ULk5LH0Opy6HZ0aCK ITnQ== X-Gm-Message-State: AKS2vOwFzx/r/2ogmGtSvsbeC6EJ5Eb0VRsLx3Bq9PANYzA9cmuHVtIN M+2AW+V8qdOk5Q== X-Received: by 10.223.128.141 with SMTP id 13mr6315972wrl.141.1498222927959; Fri, 23 Jun 2017 06:02:07 -0700 (PDT) Received: from localhost.localdomain (dslb-088-067-130-225.088.067.pools.vodafone-ip.de. [88.67.130.225]) by smtp.gmail.com with ESMTPSA id h16sm6946163wma.14.2017.06.23.06.01.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 23 Jun 2017 06:01:46 -0700 (PDT) From: Jan Glauber To: Mark Rutland Subject: [PATCH v6 2/3] perf: cavium: Support transmit-link PMU counters Date: Fri, 23 Jun 2017 15:01:27 +0200 Message-Id: <20170623130128.11006-3-jglauber@cavium.com> X-Mailer: git-send-email 2.9.0.rc0.21.g7777322 In-Reply-To: <20170623130128.11006-1-jglauber@cavium.com> References: <20170623130128.11006-1-jglauber@cavium.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170623_060231_155297_59E18E77 X-CRM114-Status: GOOD ( 16.73 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Borislav Petkov , Will Deacon , 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-Virus-Scanned: ClamAV using ClamSMTP Add support for the transmit-link (OCX TLK) PMU counters found on Caviums SOCs with a processor interconnect. Properties of the OCX TLK counters: - per-unit control - fixed purpose - writable - one PCI device with multiple TLK units Signed-off-by: Jan Glauber --- drivers/edac/thunderx_edac.c | 6 ++ drivers/perf/cavium_pmu.c | 225 ++++++++++++++++++++++++++++++++++++++++ include/linux/perf/cavium_pmu.h | 1 + 3 files changed, 232 insertions(+) diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c index 884499a..6b7a43e 100644 --- a/drivers/edac/thunderx_edac.c +++ b/drivers/edac/thunderx_edac.c @@ -1094,6 +1094,8 @@ struct thunderx_ocx { unsigned long link_ring_head; unsigned long link_ring_tail; + + void *pmu_data; }; #define OCX_MESSAGE_SIZE SZ_1K @@ -1491,6 +1493,8 @@ static int thunderx_ocx_probe(struct pci_dev *pdev, writeq(OCX_COM_INT_ENA_ALL, ocx->regs + OCX_COM_INT_ENA_W1S); + ocx->pmu_data = cvm_pmu_probe(pdev, ocx->regs, CVM_PMU_TLK); + return 0; err_free: edac_device_free_ctl_info(edac_dev); @@ -1504,6 +1508,8 @@ static void thunderx_ocx_remove(struct pci_dev *pdev) struct thunderx_ocx *ocx = edac_dev->pvt_info; int i; + cvm_pmu_remove(pdev, ocx->pmu_data, CVM_PMU_TLK); + writeq(OCX_COM_INT_ENA_ALL, ocx->regs + OCX_COM_INT_ENA_W1C); for (i = 0; i < OCX_INTS; i++) { diff --git a/drivers/perf/cavium_pmu.c b/drivers/perf/cavium_pmu.c index 4a85c7fac..ce5648f 100644 --- a/drivers/perf/cavium_pmu.c +++ b/drivers/perf/cavium_pmu.c @@ -21,6 +21,7 @@ static bool cvm_pmu_initialized; static struct list_head cvm_pmu_lmcs; +static struct list_head cvm_pmu_tlks; /* * Common Cavium PMU stuff @@ -381,12 +382,232 @@ static void cvm_pmu_lmc_remove(struct pci_dev *pdev, void *pmu_data) } EXPORT_SYMBOL_GPL(cvm_pmu_lmc_remove); +/* + * CCPI interface controller (OCX) Transmit link (TLK) counters: + * - per-unit control + * - writable + * - one PCI device with multiple TLK units + */ + +#define TLK_NR_UNITS 3 +#define TLK_UNIT_OFFSET 0x2000 +#define TLK_START_ADDR 0x10000 +#define TLK_STAT_CTL_OFFSET 0x40 +#define TLK_STAT_OFFSET 0x400 + +#define TLK_STAT_ENABLE_BIT BIT(0) +#define TLK_STAT_RESET_BIT BIT(1) + +#define CVM_PMU_TLK_EVENT_ATTR(_name, _id) \ + &((struct perf_pmu_events_attr[]) { \ + { \ + __ATTR(_name, S_IRUGO, cvm_pmu_event_sysfs_show, NULL), \ + _id, \ + "tlk_event=" __stringify(_id), \ + } \ + })[0].attr.attr + +static void cvm_pmu_tlk_enable_pmu(struct pmu *pmu) +{ + struct cvm_pmu_dev *pmu_dev = container_of(pmu, struct cvm_pmu_dev, pmu); + + /* enable all counters */ + writeb(TLK_STAT_ENABLE_BIT, pmu_dev->map + TLK_STAT_CTL_OFFSET); +} + +static void cvm_pmu_tlk_disable_pmu(struct pmu *pmu) +{ + struct cvm_pmu_dev *pmu_dev = container_of(pmu, struct cvm_pmu_dev, pmu); + + /* disable all counters */ + writeb(0, pmu_dev->map + TLK_STAT_CTL_OFFSET); +} + +static int cvm_pmu_tlk_add(struct perf_event *event, int flags) +{ + struct hw_perf_event *hwc = &event->hw; + + return cvm_pmu_add(event, flags, TLK_STAT_CTL_OFFSET, + TLK_STAT_OFFSET + hwc->config * 8); +} + +PMU_FORMAT_ATTR(tlk_event, "config:0-5"); + +static struct attribute *cvm_pmu_tlk_format_attr[] = { + &format_attr_tlk_event.attr, + NULL, +}; + +static struct attribute_group cvm_pmu_tlk_format_group = { + .name = "format", + .attrs = cvm_pmu_tlk_format_attr, +}; + +static struct attribute *cvm_pmu_tlk_events_attr[] = { + CVM_PMU_TLK_EVENT_ATTR(idle_cnt, 0x00), + CVM_PMU_TLK_EVENT_ATTR(data_cnt, 0x01), + CVM_PMU_TLK_EVENT_ATTR(sync_cnt, 0x02), + CVM_PMU_TLK_EVENT_ATTR(retry_cnt, 0x03), + CVM_PMU_TLK_EVENT_ATTR(err_cnt, 0x04), + CVM_PMU_TLK_EVENT_ATTR(mat0_cnt, 0x08), + CVM_PMU_TLK_EVENT_ATTR(mat1_cnt, 0x09), + CVM_PMU_TLK_EVENT_ATTR(mat2_cnt, 0x0a), + CVM_PMU_TLK_EVENT_ATTR(mat3_cnt, 0x0b), + CVM_PMU_TLK_EVENT_ATTR(vc0_cmd, 0x10), + CVM_PMU_TLK_EVENT_ATTR(vc1_cmd, 0x11), + CVM_PMU_TLK_EVENT_ATTR(vc2_cmd, 0x12), + CVM_PMU_TLK_EVENT_ATTR(vc3_cmd, 0x13), + CVM_PMU_TLK_EVENT_ATTR(vc4_cmd, 0x14), + CVM_PMU_TLK_EVENT_ATTR(vc5_cmd, 0x15), + CVM_PMU_TLK_EVENT_ATTR(vc0_pkt, 0x20), + CVM_PMU_TLK_EVENT_ATTR(vc1_pkt, 0x21), + CVM_PMU_TLK_EVENT_ATTR(vc2_pkt, 0x22), + CVM_PMU_TLK_EVENT_ATTR(vc3_pkt, 0x23), + CVM_PMU_TLK_EVENT_ATTR(vc4_pkt, 0x24), + CVM_PMU_TLK_EVENT_ATTR(vc5_pkt, 0x25), + CVM_PMU_TLK_EVENT_ATTR(vc6_pkt, 0x26), + CVM_PMU_TLK_EVENT_ATTR(vc7_pkt, 0x27), + CVM_PMU_TLK_EVENT_ATTR(vc8_pkt, 0x28), + CVM_PMU_TLK_EVENT_ATTR(vc9_pkt, 0x29), + CVM_PMU_TLK_EVENT_ATTR(vc10_pkt, 0x2a), + CVM_PMU_TLK_EVENT_ATTR(vc11_pkt, 0x2b), + CVM_PMU_TLK_EVENT_ATTR(vc12_pkt, 0x2c), + CVM_PMU_TLK_EVENT_ATTR(vc13_pkt, 0x2d), + CVM_PMU_TLK_EVENT_ATTR(vc0_con, 0x30), + CVM_PMU_TLK_EVENT_ATTR(vc1_con, 0x31), + CVM_PMU_TLK_EVENT_ATTR(vc2_con, 0x32), + CVM_PMU_TLK_EVENT_ATTR(vc3_con, 0x33), + CVM_PMU_TLK_EVENT_ATTR(vc4_con, 0x34), + CVM_PMU_TLK_EVENT_ATTR(vc5_con, 0x35), + CVM_PMU_TLK_EVENT_ATTR(vc6_con, 0x36), + CVM_PMU_TLK_EVENT_ATTR(vc7_con, 0x37), + CVM_PMU_TLK_EVENT_ATTR(vc8_con, 0x38), + CVM_PMU_TLK_EVENT_ATTR(vc9_con, 0x39), + CVM_PMU_TLK_EVENT_ATTR(vc10_con, 0x3a), + CVM_PMU_TLK_EVENT_ATTR(vc11_con, 0x3b), + CVM_PMU_TLK_EVENT_ATTR(vc12_con, 0x3c), + CVM_PMU_TLK_EVENT_ATTR(vc13_con, 0x3d), + NULL, +}; + +static struct attribute_group cvm_pmu_tlk_events_group = { + .name = "events", + .attrs = cvm_pmu_tlk_events_attr, +}; +static const struct attribute_group *cvm_pmu_tlk_attr_groups[] = { + &cvm_pmu_attr_group, + &cvm_pmu_tlk_format_group, + &cvm_pmu_tlk_events_group, + NULL, +}; + +static bool cvm_pmu_tlk_event_valid(u64 config) +{ + struct perf_pmu_events_attr *attr; + int i; + + for (i = 0; i < ARRAY_SIZE(cvm_pmu_tlk_events_attr) - 1; i++) { + attr = (struct perf_pmu_events_attr *)cvm_pmu_tlk_events_attr[i]; + if (attr->id == config) + return true; + } + return false; +} + +static void *cvm_pmu_tlk_probe_unit(struct pci_dev *pdev, void __iomem *regs, + int nr) +{ + struct cvm_pmu_dev *tlk; + int ret = -ENOMEM; + + tlk = kzalloc(sizeof(*tlk), GFP_KERNEL); + if (!tlk) + goto fail_nomem; + + tlk->pmu_name = kasprintf(GFP_KERNEL, "ocx_tlk%d", nr); + + tlk->pdev = pdev; + tlk->map = regs + TLK_START_ADDR + nr * TLK_UNIT_OFFSET; + tlk->num_counters = ARRAY_SIZE(cvm_pmu_tlk_events_attr) - 1; + tlk->pmu = (struct pmu) { + .task_ctx_nr = perf_invalid_context, + .pmu_enable = cvm_pmu_tlk_enable_pmu, + .pmu_disable = cvm_pmu_tlk_disable_pmu, + .event_init = cvm_pmu_event_init, + .add = cvm_pmu_tlk_add, + .del = cvm_pmu_del, + .start = cvm_pmu_start, + .stop = cvm_pmu_stop, + .read = cvm_pmu_read, + .attr_groups = cvm_pmu_tlk_attr_groups, + }; + + cpuhp_state_add_instance_nocalls(CPUHP_AP_PERF_ARM_CVM_ONLINE, + &tlk->cpuhp_node); + + /* + * perf PMU is CPU dependent so pick a random CPU and migrate away + * if it goes offline. + */ + cpumask_set_cpu(smp_processor_id(), &tlk->active_mask); + + ret = perf_pmu_register(&tlk->pmu, tlk->pmu_name, -1); + if (ret) + goto fail_hp; + + list_add(&tlk->entry, &cvm_pmu_tlks); + + tlk->event_valid = cvm_pmu_tlk_event_valid; + return tlk; + +fail_hp: + kfree(tlk->pmu_name); + cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_CVM_ONLINE, + &tlk->cpuhp_node); + kfree(tlk); +fail_nomem: + return ERR_PTR(ret); +} + +static void *cvm_pmu_tlk_probe(struct pci_dev *pdev, void __iomem *regs) +{ + struct cvm_pmu_dev *tlk; + int i; + + for (i = 0; i < TLK_NR_UNITS; i++) { + tlk = cvm_pmu_tlk_probe_unit(pdev, regs, i); + if (PTR_ERR(tlk)) + continue; + dev_info(&pdev->dev, "Enabled %s PMU with %d counters\n", + tlk->pmu_name, tlk->num_counters); + } + return &cvm_pmu_tlks; +} + +static void cvm_pmu_tlk_remove(struct pci_dev *pdev, void *pmu_data) +{ + struct list_head *l, *tmp; + struct cvm_pmu_dev *tlk; + + list_for_each_safe(l, tmp, &cvm_pmu_tlks) { + tlk = list_entry(l, struct cvm_pmu_dev, entry); + + list_del(&tlk->entry); + cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_CVM_ONLINE, + &tlk->cpuhp_node); + perf_pmu_unregister(&tlk->pmu); + kfree(tlk->pmu_name); + kfree(tlk); + } +} + static int cvm_pmu_init(void) { if (cvm_pmu_initialized) return 0; INIT_LIST_HEAD(&cvm_pmu_lmcs); + INIT_LIST_HEAD(&cvm_pmu_tlks); return cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_CVM_ONLINE, "perf/arm/cvm:online", NULL, @@ -403,6 +624,8 @@ void *cvm_pmu_probe(struct pci_dev *pdev, void __iomem *regs, int type) switch (type) { case CVM_PMU_LMC: return cvm_pmu_lmc_probe(pdev, regs); + case CVM_PMU_TLK: + return cvm_pmu_tlk_probe(pdev, regs); } return NULL; } @@ -413,6 +636,8 @@ void cvm_pmu_remove(struct pci_dev *pdev, void *pmu_data, int type) switch (type) { case CVM_PMU_LMC: return cvm_pmu_lmc_remove(pdev, pmu_data); + case CVM_PMU_TLK: + return cvm_pmu_tlk_remove(pdev, pmu_data); } } EXPORT_SYMBOL_GPL(cvm_pmu_remove); diff --git a/include/linux/perf/cavium_pmu.h b/include/linux/perf/cavium_pmu.h index 6ddc1c6..d15b435 100644 --- a/include/linux/perf/cavium_pmu.h +++ b/include/linux/perf/cavium_pmu.h @@ -6,6 +6,7 @@ enum cvm_pmu_type { CVM_PMU_LMC, + CVM_PMU_TLK, }; #ifdef CONFIG_CAVIUM_PMU