From patchwork Fri Sep 18 16:26:15 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathieu Poirier X-Patchwork-Id: 53921 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f200.google.com (mail-wi0-f200.google.com [209.85.212.200]) by patches.linaro.org (Postfix) with ESMTPS id 7FD81218E3 for ; Fri, 18 Sep 2015 16:27:23 +0000 (UTC) Received: by wicuu12 with SMTP id uu12sf10823310wic.2 for ; Fri, 18 Sep 2015 09:27:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=3ppV3lFxVHwYgm4XwwDLdjAs/P1ou6tov1ViTy0nJRM=; b=bv9fBChoQ8bBrjw7xXoanxmrPdUbagzt7Oq9BPOe8iPer0Lhn5RLrBJ4mxPRAL0Jun fJVVfaZkbPOkRN+KqVcyu+cBQwsN5r7qofUlqH1Y0FidNknTLIe9fVzztRiFDwetLQxj eSTtwEOReucCC/4o2vdZiRKT/M6Qz2/pWh47noaG4Q+11zoofXJiAFVXZ1KA3gICRqZk Vz+5ZH+IvvMEPe1H7GxUep33148M0ptXbRfK/bRddFF/cDT9mAqxOn1Z95iZ99LYMH39 BEmWtDaHV25h8cDIJNRAmewnez+eZsh9SizT+EswSBacQTo6rmZ8PycyPgGnYeQXJYbF 65Cw== X-Gm-Message-State: ALoCoQkjF+jb9lLZ/jWmnC8eQbpXjy50lxEg8q4Ed5VeeHMr0FNgY0VS5om8m5ZzfOBNAwQA34nu X-Received: by 10.112.145.3 with SMTP id sq3mr1075567lbb.7.1442593642779; Fri, 18 Sep 2015 09:27:22 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.4.137 with SMTP id k9ls289281lak.79.gmail; Fri, 18 Sep 2015 09:27:22 -0700 (PDT) X-Received: by 10.153.4.40 with SMTP id cb8mr3615293lad.100.1442593642651; Fri, 18 Sep 2015 09:27:22 -0700 (PDT) Received: from mail-la0-f47.google.com (mail-la0-f47.google.com. [209.85.215.47]) by mx.google.com with ESMTPS id dd9si6728707lad.59.2015.09.18.09.27.22 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 Sep 2015 09:27:22 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.47 as permitted sender) client-ip=209.85.215.47; Received: by lagj9 with SMTP id j9so34091519lag.2 for ; Fri, 18 Sep 2015 09:27:22 -0700 (PDT) X-Received: by 10.112.180.230 with SMTP id dr6mr3570634lbc.72.1442593642166; Fri, 18 Sep 2015 09:27:22 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp401507lbq; Fri, 18 Sep 2015 09:27:21 -0700 (PDT) X-Received: by 10.107.128.88 with SMTP id b85mr14256052iod.64.1442593639079; Fri, 18 Sep 2015 09:27:19 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ti9si7525712igb.18.2015.09.18.09.27.18; Fri, 18 Sep 2015 09:27:19 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754636AbbIRQ1K (ORCPT + 30 others); Fri, 18 Sep 2015 12:27:10 -0400 Received: from mail-pa0-f46.google.com ([209.85.220.46]:34660 "EHLO mail-pa0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754112AbbIRQ1F (ORCPT ); Fri, 18 Sep 2015 12:27:05 -0400 Received: by padhy16 with SMTP id hy16so55266783pad.1 for ; Fri, 18 Sep 2015 09:27:04 -0700 (PDT) X-Received: by 10.66.141.42 with SMTP id rl10mr8199151pab.18.1442593623349; Fri, 18 Sep 2015 09:27:03 -0700 (PDT) Received: from t430.cg.shawcable.net ([184.64.168.246]) by smtp.gmail.com with ESMTPSA id la4sm9847027pbc.76.2015.09.18.09.27.01 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 18 Sep 2015 09:27:02 -0700 (PDT) From: Mathieu Poirier To: gregkh@linuxfoundation.org, a.p.zijlstra@chello.nl, alexander.shishkin@linux.intel.com, acme@kernel.org, mingo@redhat.com, corbet@lwn.net Cc: adrian.hunter@intel.com, zhang.chunyan@linaro.org, mike.leach@arm.com, tor@ti.com, al.grant@arm.com, pawel.moll@arm.com, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 01/20] coresight: etm3x: splitting 'etm_enable_hw()' operations Date: Fri, 18 Sep 2015 10:26:15 -0600 Message-Id: <1442593594-10665-2-git-send-email-mathieu.poirier@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1442593594-10665-1-git-send-email-mathieu.poirier@linaro.org> References: <1442593594-10665-1-git-send-email-mathieu.poirier@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: mathieu.poirier@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.47 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , When dealing with other kernel subsystems or automated tools it is desirable to split the current etm_enable_hw() operation in three: power up, configuration and enabling of the tracer. That way it is possible to have more control on the operations done by a tracer. Signed-off-by: Mathieu Poirier --- drivers/hwtracing/coresight/coresight-etm3x.c | 167 +++++++++++++++++++++----- include/linux/coresight.h | 10 +- 2 files changed, 146 insertions(+), 31 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index d630b7ece735..999c62a59c70 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -247,11 +247,12 @@ static void etm_set_default(struct etm_drvdata *drvdata) drvdata->ctxid_mask = 0x0; } -static void etm_enable_hw(void *info) +static void etm_power_up_cpu(void *info) { - int i; - u32 etmcr; - struct etm_drvdata *drvdata = info; + struct coresight_device *csdev = info; + struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + WARN_ON(drvdata->cpu != smp_processor_id()); CS_UNLOCK(drvdata->base); @@ -262,10 +263,65 @@ static void etm_enable_hw(void *info) /* Make sure all registers are accessible */ etm_os_unlock(drvdata); + CS_LOCK(drvdata->base); +} + +static int etm_power_up(struct coresight_device *csdev) +{ + struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + /* tell the core we need this tracer */ + pm_runtime_get_sync(csdev->dev.parent); + + return smp_call_function_single(drvdata->cpu, + etm_power_up_cpu, csdev, 1); +} + +static void etm_power_down_cpu(void *info) +{ + struct coresight_device *csdev = info; + struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + WARN_ON(drvdata->cpu != smp_processor_id()); + + CS_UNLOCK(drvdata->base); + etm_clr_pwrup(drvdata); + etm_set_pwrdwn(drvdata); + CS_LOCK(drvdata->base); +} + +static void etm_power_down(struct coresight_device *csdev) +{ + struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + smp_call_function_single(drvdata->cpu, + etm_power_down_cpu, csdev, 1); + + /* tell the core this tracer is no longer needed */ + pm_runtime_put(csdev->dev.parent); +} + +/** + * etm_configure_cpu - configure ETM registers + * @csdev - the etm that needs to be configure. + * + * Applies a configuration set to the ETM registers _without_ enabling the + * tracer. This function needs to be executed on the CPU who's tracer is + * being configured. + */ +static void etm_configure_cpu(void *info) +{ + int i; + u32 etmcr; + struct coresight_device *csdev = info; + struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + WARN_ON(drvdata->cpu != smp_processor_id()); + + CS_UNLOCK(drvdata->base); etm_set_prog(drvdata); etmcr = etm_readl(drvdata, ETMCR); - etmcr &= (ETMCR_PWD_DWN | ETMCR_ETM_PRG); etmcr |= drvdata->port_size; etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR); etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER); @@ -306,13 +362,71 @@ 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, drvdata->ctrl | ETMCR_ETM_EN | etmcr, ETMCR); + etm_clr_prog(drvdata); + CS_LOCK(drvdata->base); +} + +static int etm_configure(struct coresight_device *csdev) +{ + struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + return smp_call_function_single(drvdata->cpu, + etm_configure_cpu, csdev, 1); +} + +/** + * etm_trace_enable - enable ETM tracer + * @csdev - the etm that needs to be enabled/disabled. + * @enable - whether to enable or disable the tracer. + * + * Only enables the tracer - register configuration should have been made + * prior to calling this function. This should be executed on the CPU who's + * tracer is being enabled. + */ +static int etm_trace_enable(struct coresight_device *csdev, bool enable) +{ + u32 etmcr; + struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + WARN_ON(drvdata->cpu != smp_processor_id()); + + /* + * It is assumed that etm_configure_cpu() has been called. As such + * the ETM should be turned on, power applied to the trace registers + * and all registers accessible. + */ + CS_UNLOCK(drvdata->base); + etm_set_prog(drvdata); + + etmcr = etm_readl(drvdata, ETMCR); + + enable ? (etmcr |= ETMCR_ETM_EN) : + (etmcr &= ~ETMCR_ETM_EN); + + etm_writel(drvdata, ETMCR_ETM_EN | etmcr, ETMCR); etm_clr_prog(drvdata); CS_LOCK(drvdata->base); + return 0; +} + +static void etm_config_enable(void *info) +{ + struct coresight_device *csdev = info; + struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + spin_lock(&drvdata->spinlock); + + etm_power_up_cpu(csdev); + etm_configure_cpu(csdev); + etm_trace_enable(csdev, true); dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu); + + drvdata->enable = true; + drvdata->sticky_enable = true; + + spin_unlock(&drvdata->spinlock); } static int etm_trace_id(struct coresight_device *csdev) @@ -339,11 +453,8 @@ static int etm_trace_id(struct coresight_device *csdev) static int etm_enable(struct coresight_device *csdev) { - struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); int ret; - - pm_runtime_get_sync(csdev->dev.parent); - spin_lock(&drvdata->spinlock); + struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); /* * Configure the ETM only if the CPU is online. If it isn't online @@ -352,34 +463,28 @@ static int etm_enable(struct coresight_device *csdev) */ if (cpu_online(drvdata->cpu)) { ret = smp_call_function_single(drvdata->cpu, - etm_enable_hw, drvdata, 1); + etm_config_enable, csdev, 1); if (ret) goto err; } - drvdata->enable = true; - drvdata->sticky_enable = true; - - spin_unlock(&drvdata->spinlock); - dev_info(drvdata->dev, "ETM tracing enabled\n"); return 0; err: - spin_unlock(&drvdata->spinlock); - pm_runtime_put(csdev->dev.parent); return ret; } -static void etm_disable_hw(void *info) +static void etm_disable_powerdown(void *info) { int i; struct etm_drvdata *drvdata = info; + spin_lock(&drvdata->spinlock); CS_UNLOCK(drvdata->base); etm_set_prog(drvdata); - /* Program trace enable to low by using always false event */ - etm_writel(drvdata, ETM_HARD_WIRE_RES_A | ETM_EVENT_NOT_A, ETMTEEVR); + etm_trace_enable(drvdata->csdev, false); + drvdata->enable = false; /* Read back sequencer and counters for post trace analysis */ drvdata->seq_curr_state = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK); @@ -387,8 +492,9 @@ static void etm_disable_hw(void *info) for (i = 0; i < drvdata->nr_cntr; i++) drvdata->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i)); - etm_set_pwrdwn(drvdata); + etm_power_down(drvdata->csdev); CS_LOCK(drvdata->base); + spin_unlock(&drvdata->spinlock); dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu); } @@ -404,26 +510,27 @@ static void etm_disable(struct coresight_device *csdev) * DYING hotplug callback is serviced by the ETM driver. */ get_online_cpus(); - spin_lock(&drvdata->spinlock); /* * Executing etm_disable_hw on the cpu whose ETM is being disabled * ensures that register writes occur when cpu is powered. */ - smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1); - drvdata->enable = false; + smp_call_function_single(drvdata->cpu, + etm_disable_powerdown, drvdata, 1); - spin_unlock(&drvdata->spinlock); put_online_cpus(); - pm_runtime_put(csdev->dev.parent); dev_info(drvdata->dev, "ETM tracing disabled\n"); } static const struct coresight_ops_source etm_source_ops = { .trace_id = etm_trace_id, + .configure = etm_configure, + .trace_enable = etm_trace_enable, .enable = etm_enable, .disable = etm_disable, + .poweron = etm_power_up, + .poweroff = etm_power_down, }; static const struct coresight_ops etm_cs_ops = { @@ -1659,7 +1766,7 @@ static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action, } if (etmdrvdata[cpu]->enable) - etm_enable_hw(etmdrvdata[cpu]); + etm_config_enable(etmdrvdata[cpu]->csdev); spin_unlock(&etmdrvdata[cpu]->spinlock); break; @@ -1672,7 +1779,7 @@ static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action, case CPU_DYING: spin_lock(&etmdrvdata[cpu]->spinlock); if (etmdrvdata[cpu]->enable) - etm_disable_hw(etmdrvdata[cpu]); + etm_disable_powerdown(etmdrvdata[cpu]->csdev); spin_unlock(&etmdrvdata[cpu]->spinlock); break; } diff --git a/include/linux/coresight.h b/include/linux/coresight.h index a7cabfa23b55..70f3dafa5194 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -206,14 +206,22 @@ struct coresight_ops_link { * struct coresight_ops_source - basic operations for a source * Operations available for sources. * @trace_id: returns the value of the component's trace ID as known - to the HW. + * to the HW. + * @configure: performs configuration for a source but doesn't enable it. + * @trace_enable: enable/disable tracing on a source. * @enable: enables tracing for a source. * @disable: disables tracing for a source. + * @poweron: switch on power to a source. + * @poweroff: switch off power to a source. */ struct coresight_ops_source { int (*trace_id)(struct coresight_device *csdev); + int (*configure)(struct coresight_device *csdev); + int (*trace_enable)(struct coresight_device *csdev, bool enable); int (*enable)(struct coresight_device *csdev); void (*disable)(struct coresight_device *csdev); + int (*poweron)(struct coresight_device *csdev); + void (*poweroff)(struct coresight_device *csdev); }; struct coresight_ops {