From patchwork Thu Feb 18 00:51:57 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathieu Poirier X-Patchwork-Id: 8344441 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 B23439F2F0 for ; Thu, 18 Feb 2016 01:01:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CFA0F2022A for ; Thu, 18 Feb 2016 01:01:34 +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 1036020272 for ; Thu, 18 Feb 2016 01:01:29 +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 1aWCwO-00033O-JN; Thu, 18 Feb 2016 00:59:32 +0000 Received: from mail-ob0-x22e.google.com ([2607:f8b0:4003:c01::22e]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1aWCpk-0004cd-FI for linux-arm-kernel@lists.infradead.org; Thu, 18 Feb 2016 00:52:48 +0000 Received: by mail-ob0-x22e.google.com with SMTP id gc3so42005782obb.3 for ; Wed, 17 Feb 2016 16:52:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=rco9FcSzSzghHuUH8ndrzB9/78GpgwsZLu2S+GHlMdg=; b=AM72bB4aMGafW+9rD9DGOckzlmH2o1GdzwhSpahKtAdGZsUeCA3fU05X45faBlZWv2 cm2a6S0MhvrXRyjSTHthT31j1hBn+YVHmjZPu/3bVNgGEg3wTR2Murwz594l1mHJClpx A9jMFKyzR1A2Pxid/2ociDs6hWkDNIT/X77Lg= 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; bh=rco9FcSzSzghHuUH8ndrzB9/78GpgwsZLu2S+GHlMdg=; b=Vj3CQCeBfm0z02nqCVvwHEbSHiaigmdsAdvphbHunowQKvKszTVywrbg1Y92W0H/a8 q0myVsDC91deWcUhxzoFqUj+rgy4gdd0ZtpeovwZizEiATudfS8loxFqhF809eFjkWRV 9EU1qlW4oc+FbF3oCtpXbAV+qdKZLpKBNC0QerRAPtpkcx98QddhJVoJi2lMgc5g/zAD K777iUPaMXPKityswYLK/Gdfvrzx9RX20wv3cW+iUrtOGOy/llu0tUpulXcgNBNF/w/u hWFHto0o/upRLGqAxT4I/4oKFwKgZyQ6WmopNrK1AbfoSQAKrJo+ANeOB4S8LzkBLEv/ 82TQ== X-Gm-Message-State: AG10YOQ7aL58+HSDVqTLDITyuYvUPOIfnYXEBeKCQCoLOTIz1X5o//RGI2J0j5/RaQk0mbB1 X-Received: by 10.60.233.193 with SMTP id ty1mr3941669oec.0.1455756740950; Wed, 17 Feb 2016 16:52:20 -0800 (PST) Received: from t430.globalsuite.net (h58.159.185.173.static.ip.windstream.net. [173.185.159.58]) by smtp.gmail.com with ESMTPSA id gi5sm2357650obb.6.2016.02.17.16.52.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 17 Feb 2016 16:52:20 -0800 (PST) From: Mathieu Poirier To: gregkh@linuxfoundation.org Subject: [PATCH 15/21] coresight: etm3x: implementing perf_enable/disable() API Date: Wed, 17 Feb 2016 17:51:57 -0700 Message-Id: <1455756723-8456-16-git-send-email-mathieu.poirier@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1455756723-8456-1-git-send-email-mathieu.poirier@linaro.org> References: <1455756723-8456-1-git-send-email-mathieu.poirier@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160217_165240_841199_0B1CB123 X-CRM114-Status: GOOD ( 23.03 ) X-Spam-Score: -2.7 (--) 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 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.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,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 That way traces can be enabled and disabled automatically from the Perf subystem using the PMU abstraction. Signed-off-by: Mathieu Poirier --- drivers/hwtracing/coresight/Kconfig | 1 + drivers/hwtracing/coresight/coresight-etm3x.c | 95 +++++++++++++++++++++++++-- drivers/hwtracing/coresight/coresight-etm4x.c | 4 +- drivers/hwtracing/coresight/coresight.c | 2 +- include/linux/coresight.h | 6 +- 5 files changed, 99 insertions(+), 9 deletions(-) diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index c85935f3525a..db0541031c72 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -4,6 +4,7 @@ menuconfig CORESIGHT bool "CoreSight Tracing Support" select ARM_AMBA + select PERF_EVENTS help This framework provides a kernel interface for the CoreSight debug and trace drivers to register themselves with. It's intended to build diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index c82d545e68ef..a9b820ec16aa 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "coresight-etm.h" @@ -297,6 +298,47 @@ void etm_config_trace_mode(struct etm_config *config) config->addr_type[1] = ETM_ADDR_TYPE_RANGE; } +#define ETM3X_SUPPORTED_OPTIONS (ETMCR_CYC_ACC | ETMCR_TIMESTAMP_EN) + +static int etm_parse_event_config(struct etm_drvdata *drvdata, + struct perf_event_attr *attr) +{ + struct etm_config *config = &drvdata->config; + + if (!attr) + return -EINVAL; + + /* Clear configuration from previous run */ + memset(config, 0, sizeof(struct etm_config)); + + if (attr->exclude_kernel) + config->mode = ETM_MODE_EXCL_KERN; + + if (attr->exclude_user) + config->mode = ETM_MODE_EXCL_USER; + + /* Always start from the default config */ + etm_set_default(config); + + /* + * By default the tracers are configured to trace the whole address + * range. Narrow the field only if requested by user space. + */ + if (config->mode) + etm_config_trace_mode(config); + + /* + * At this time only cycle accurate and timestamp options are + * available. + */ + if (attr->config & ~ETM3X_SUPPORTED_OPTIONS) + return -EINVAL; + + config->ctrl = attr->config; + + return 0; +} + static void etm_enable_hw(void *info) { int i; @@ -316,8 +358,10 @@ static void etm_enable_hw(void *info) etm_set_prog(drvdata); etmcr = etm_readl(drvdata, ETMCR); - etmcr &= (ETMCR_PWD_DWN | ETMCR_ETM_PRG); + /* Clear setting from a previous run if need be */ + etmcr &= ~ETM3X_SUPPORTED_OPTIONS; etmcr |= drvdata->port_size; + etmcr |= ETMCR_ETM_EN; etm_writel(drvdata, config->ctrl | etmcr, ETMCR); etm_writel(drvdata, config->trigger_event, ETMTRIGGER); etm_writel(drvdata, config->startstop_ctrl, ETMTSSCR); @@ -357,9 +401,6 @@ static void etm_enable_hw(void *info) /* No VMID comparator value selected */ etm_writel(drvdata, 0x0, ETMVMIDCVR); - /* Ensures trace output is enabled from this ETM */ - etm_writel(drvdata, config->ctrl | ETMCR_ETM_EN | etmcr, ETMCR); - etm_clr_prog(drvdata); CS_LOCK(drvdata->base); @@ -407,6 +448,22 @@ static int etm_trace_id(struct coresight_device *csdev) return etm_get_trace_id(drvdata); } +static int etm_enable_perf(struct coresight_device *csdev, + struct perf_event_attr *attr) +{ + struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) + return -EINVAL; + + /* Configure the tracer based on the session's specifics */ + etm_parse_event_config(drvdata, attr); + /* And enable it */ + etm_enable_hw(drvdata); + + return 0; +} + static int etm_enable_sysfs(struct coresight_device *csdev) { struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -437,7 +494,8 @@ err: return ret; } -static int etm_enable(struct coresight_device *csdev, u32 mode) +static int etm_enable(struct coresight_device *csdev, + struct perf_event_attr *attr, u32 mode) { int ret; u32 val; @@ -453,6 +511,9 @@ static int etm_enable(struct coresight_device *csdev, u32 mode) case CS_MODE_SYSFS: ret = etm_enable_sysfs(csdev); break; + case CS_MODE_PERF: + ret = etm_enable_perf(csdev, attr); + break; default: ret = -EINVAL; } @@ -485,6 +546,27 @@ static void etm_disable_hw(void *info) dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu); } +static void etm_disable_perf(struct coresight_device *csdev) +{ + struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) + return; + + CS_UNLOCK(drvdata->base); + + /* Setting the prog bit disables tracing immediately */ + etm_set_prog(drvdata); + + /* + * There is no way to know when the tracer will be used again so + * power down the tracer. + */ + etm_set_pwrdwn(drvdata); + + CS_LOCK(drvdata->base); +} + static void etm_disable_sysfs(struct coresight_device *csdev) { struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -528,6 +610,9 @@ static void etm_disable(struct coresight_device *csdev) case CS_MODE_SYSFS: etm_disable_sysfs(csdev); break; + case CS_MODE_PERF: + etm_disable_perf(csdev); + break; default: WARN_ON_ONCE(mode); return; diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 0026092fec7f..d0169ba7fbf2 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "coresight-etm4x.h" @@ -187,7 +188,8 @@ static void etm4_enable_hw(void *info) dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu); } -static int etm4_enable(struct coresight_device *csdev, u32 mode) +static int etm4_enable(struct coresight_device *csdev, + struct perf_event_attr *attr, u32 mode) { struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); int ret; diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index b20afb709141..95cccb179763 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -234,7 +234,7 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode) if (!csdev->enable) { if (source_ops(csdev)->enable) { - ret = source_ops(csdev)->enable(csdev, mode); + ret = source_ops(csdev)->enable(csdev, NULL, mode); if (ret) return ret; } diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 61dfb8d511ea..6801dd64ee5d 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -14,6 +14,7 @@ #define _LINUX_CORESIGHT_H #include +#include #include /* Peripheral id registers (0xFD0-0xFEC) */ @@ -206,14 +207,15 @@ struct coresight_ops_link { * @cpu_id: returns the value of the CPU number this component * is associated to. * @trace_id: returns the value of the component's trace ID as known - to the HW. + * to the HW. * @enable: enables tracing for a source. * @disable: disables tracing for a source. */ struct coresight_ops_source { int (*cpu_id)(struct coresight_device *csdev); int (*trace_id)(struct coresight_device *csdev); - int (*enable)(struct coresight_device *csdev, u32 mode); + int (*enable)(struct coresight_device *csdev, + struct perf_event_attr *attr, u32 mode); void (*disable)(struct coresight_device *csdev); };