From patchwork Tue Dec 12 15:53:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Clark X-Patchwork-Id: 13489558 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E846EC4332F for ; Tue, 12 Dec 2023 15:55:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=cgt47C3MxlqydO+jE3PqfQsrFpNxIJc30UAhRhJLeD8=; b=AzI1xftWXKepRD EMTvGPXJh+XOFLUHw/Q6Fm8/hp5bzOZi0TG/2H5pSlM+Ok1y3QCz7fewoe+JVnB9JTyNk93MaPC5d a+EQK+AEJOgwbRkAcfX6TbJh89AJoFsP/GXw3TDMMbqzeLnLrtAAUKCKAui5qMPQDuVhft5qoEcRD nBLx54j4QqXb2qLXX8Ga3BD85FiGvdBEF+Uo8TJSvPvIkfYhg545PWYhs7r5OQ/ab3ZixOrz+1xP4 uzvE4iwoN+MsHE+eF9tr5pQ0gS5cOy4ZCpRiBOX4zhPaKzKzvQh1GPzuYZQLCRbN+tClMcu7j0MXr StKfSQkUtGALMyVggE9w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56I-00C884-1L; Tue, 12 Dec 2023 15:55:14 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56D-00C84i-2I for linux-arm-kernel@lists.infradead.org; Tue, 12 Dec 2023 15:55:11 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 532C9143D; Tue, 12 Dec 2023 07:55:55 -0800 (PST) Received: from e127643.broadband (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7F0E53F738; Tue, 12 Dec 2023 07:55:07 -0800 (PST) From: James Clark To: coresight@lists.linaro.org, suzuki.poulose@arm.com Cc: James Clark , Mike Leach , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com Subject: [PATCH 1/8] coresight: Fix issue where a source device's helpers aren't disabled Date: Tue, 12 Dec 2023 15:53:58 +0000 Message-Id: <20231212155407.1429121-2-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231212155407.1429121-1-james.clark@arm.com> References: <20231212155407.1429121-1-james.clark@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231212_075509_851037_76893B87 X-CRM114-Status: GOOD ( 17.08 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The linked commit reverts the change that accidentally used some sysfs enable/disable functions from Perf which broke the refcounting, but it also removes the fact that the sysfs disable function disabled the helpers. Add a new wrapper function that does both which is used by both Perf and sysfs, and label the sysfs disable function appropriately. The naming of all of the functions will be tidied up later to avoid this happening again. Fixes: 287e82cf69aa ("coresight: Fix crash when Perf and sysfs modes are used concurrently") Signed-off-by: James Clark --- drivers/hwtracing/coresight/coresight-core.c | 30 ++++++++++++++----- .../hwtracing/coresight/coresight-etm-perf.c | 2 +- drivers/hwtracing/coresight/coresight-priv.h | 2 +- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index d7f0e231feb9..965bb6d4e1bf 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -441,8 +441,26 @@ static void coresight_disable_helpers(struct coresight_device *csdev) } } +/* + * Helper function to call source_ops(csdev)->disable and also disable the + * helpers. + * + * There is an imbalance between coresight_enable_path() and + * coresight_disable_path(). Enabling also enables the source's helpers as part + * of the path, but disabling always skips the first item in the path (which is + * the source), so sources and their helpers don't get disabled as part of that + * function and we need the extra step here. + */ +void coresight_disable_source(struct coresight_device *csdev, void *data) +{ + if (source_ops(csdev)->disable) + source_ops(csdev)->disable(csdev, data); + coresight_disable_helpers(csdev); +} +EXPORT_SYMBOL_GPL(coresight_disable_source); + /** - * coresight_disable_source - Drop the reference count by 1 and disable + * coresight_disable_source_sysfs - Drop the reference count by 1 and disable * the device if there are no users left. * * @csdev: The coresight device to disable @@ -451,17 +469,15 @@ static void coresight_disable_helpers(struct coresight_device *csdev) * * Returns true if the device has been disabled. */ -bool coresight_disable_source(struct coresight_device *csdev, void *data) +static bool coresight_disable_source_sysfs(struct coresight_device *csdev, + void *data) { if (atomic_dec_return(&csdev->refcnt) == 0) { - if (source_ops(csdev)->disable) - source_ops(csdev)->disable(csdev, data); - coresight_disable_helpers(csdev); + coresight_disable_source(csdev, data); csdev->enable = false; } return !csdev->enable; } -EXPORT_SYMBOL_GPL(coresight_disable_source); /* * coresight_disable_path_from : Disable components in the given path beyond @@ -1204,7 +1220,7 @@ void coresight_disable(struct coresight_device *csdev) if (ret) goto out; - if (!csdev->enable || !coresight_disable_source(csdev, NULL)) + if (!csdev->enable || !coresight_disable_source_sysfs(csdev, NULL)) goto out; switch (csdev->subtype.source_subtype) { diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index a52cfcce25d6..c0c60e6a1703 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -589,7 +589,7 @@ static void etm_event_stop(struct perf_event *event, int mode) return; /* stop tracer */ - source_ops(csdev)->disable(csdev, event); + coresight_disable_source(csdev, event); /* tell the core */ event->hw.state = PERF_HES_STOPPED; diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 767076e07970..30c051055e54 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -233,6 +233,6 @@ void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev); struct coresight_device *coresight_get_percpu_sink(int cpu); int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode, void *data); -bool coresight_disable_source(struct coresight_device *csdev, void *data); +void coresight_disable_source(struct coresight_device *csdev, void *data); #endif From patchwork Tue Dec 12 15:53:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Clark X-Patchwork-Id: 13489560 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C1DF5C4167D for ; Tue, 12 Dec 2023 15:55:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Rf6bhcb1ABmnWvDe+yprad8jBlZV27tkRyM1T0mC3yk=; b=KDTwdPugdwHObN h1FuKtjIX/6vg2r2Il+XmC6YWqC8awhqCRagq7fCNotR1Lw5xoPlxM1aQ8PQl1wYCjC32IawzrCuC Bclmy003AIxcxrgsYhDJVY+UUvgRUhhL0OqS+njxkMmBVDg1xwv/wBJe9b1FJos8IYE9eEBTnI9N9 o0Xxbs/P4NYu5T1ABgRAaIzo32rmP1/eqm6vcK+W7DvDh1Ttq0GALal5KeI6RXrpIefy+lxuRCc94 opm8wYNrCXqf1VDTR2QRA5ywIPMFQTiTcEanoodP3aB7J9Y/tsHTDMknnG4k+1K0sjsTJVNn7e7TR HIhHYWZqFKfzO6Bcwb9A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56N-00C8AC-0u; Tue, 12 Dec 2023 15:55:19 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56H-00C87E-0v for linux-arm-kernel@lists.infradead.org; Tue, 12 Dec 2023 15:55:15 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 22DEA143D; Tue, 12 Dec 2023 07:55:59 -0800 (PST) Received: from e127643.broadband (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 4E8F43F738; Tue, 12 Dec 2023 07:55:11 -0800 (PST) From: James Clark To: coresight@lists.linaro.org, suzuki.poulose@arm.com Cc: James Clark , Mike Leach , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com Subject: [PATCH 2/8] coresight: Make language around "activated" sinks consistent Date: Tue, 12 Dec 2023 15:53:59 +0000 Message-Id: <20231212155407.1429121-3-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231212155407.1429121-1-james.clark@arm.com> References: <20231212155407.1429121-1-james.clark@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231212_075513_519603_F32B55E5 X-CRM114-Status: GOOD ( 24.16 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Activated has the specific meaning of a sink that's selected for use by the user via sysfs. But comments in some code that's shared by Perf use the same word, so in those cases change them to just say "selected" instead. With selected implying either via Perf or "activated" via sysfs. coresight_get_enabled_sink() doesn't actually get an enabled sink, it only gets an activated one, so change that too. And change the activated variable name to include "sysfs" so it can't be confused as a general status. Signed-off-by: James Clark --- drivers/hwtracing/coresight/coresight-core.c | 51 ++++++++------------ drivers/hwtracing/coresight/coresight-priv.h | 2 - include/linux/coresight.h | 14 +++--- 3 files changed, 27 insertions(+), 40 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 965bb6d4e1bf..f79aa9ff9b64 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -500,7 +500,7 @@ static void coresight_disable_path_from(struct list_head *path, /* * ETF devices are tricky... They can be a link or a sink, * depending on how they are configured. If an ETF has been - * "activated" it will be configured as a sink, otherwise + * selected as a sink it will be configured as a sink, otherwise * go ahead with the link configuration. */ if (type == CORESIGHT_DEV_TYPE_LINKSINK) @@ -578,7 +578,7 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode, /* * ETF devices are tricky... They can be a link or a sink, * depending on how they are configured. If an ETF has been - * "activated" it will be configured as a sink, otherwise + * selected as a sink it will be configured as a sink, otherwise * go ahead with the link configuration. */ if (type == CORESIGHT_DEV_TYPE_LINKSINK) @@ -635,15 +635,21 @@ struct coresight_device *coresight_get_sink(struct list_head *path) return csdev; } +/** + * coresight_find_activated_sysfs_sink - returns the first sink activated via + * sysfs using connection based search starting from the source reference. + * + * @csdev: Coresight source device reference + */ static struct coresight_device * -coresight_find_enabled_sink(struct coresight_device *csdev) +coresight_find_activated_sysfs_sink(struct coresight_device *csdev) { int i; struct coresight_device *sink = NULL; if ((csdev->type == CORESIGHT_DEV_TYPE_SINK || csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && - csdev->activated) + csdev->sysfs_sink_activated) return csdev; /* @@ -654,7 +660,7 @@ coresight_find_enabled_sink(struct coresight_device *csdev) child_dev = csdev->pdata->out_conns[i]->dest_dev; if (child_dev) - sink = coresight_find_enabled_sink(child_dev); + sink = coresight_find_activated_sysfs_sink(child_dev); if (sink) return sink; } @@ -662,21 +668,6 @@ coresight_find_enabled_sink(struct coresight_device *csdev) return NULL; } -/** - * coresight_get_enabled_sink - returns the first enabled sink using - * connection based search starting from the source reference - * - * @source: Coresight source device reference - */ -struct coresight_device * -coresight_get_enabled_sink(struct coresight_device *source) -{ - if (!source) - return NULL; - - return coresight_find_enabled_sink(source); -} - static int coresight_sink_by_id(struct device *dev, const void *data) { struct coresight_device *csdev = to_coresight_device(dev); @@ -810,11 +801,10 @@ static void coresight_drop_device(struct coresight_device *csdev) * @sink: The final sink we want in this path. * @path: The list to add devices to. * - * The tree of Coresight device is traversed until an activated sink is - * found. From there the sink is added to the list along with all the - * devices that led to that point - the end result is a list from source - * to sink. In that list the source is the first device and the sink the - * last one. + * The tree of Coresight device is traversed until the selected sink is found. + * From there the sink is added to the list along with all the devices that led + * to that point - the end result is a list from source to sink. In that list + * the source is the first device and the sink the last one. */ static int _coresight_build_path(struct coresight_device *csdev, struct coresight_device *sink, @@ -824,7 +814,7 @@ static int _coresight_build_path(struct coresight_device *csdev, bool found = false; struct coresight_node *node; - /* An activated sink has been found. Enqueue the element */ + /* The selected sink has been found. Enqueue the element */ if (csdev == sink) goto out; @@ -1145,7 +1135,7 @@ int coresight_enable(struct coresight_device *csdev) goto out; } - sink = coresight_get_enabled_sink(csdev); + sink = coresight_find_activated_sysfs_sink(csdev); if (!sink) { ret = -EINVAL; goto out; @@ -1259,7 +1249,7 @@ static ssize_t enable_sink_show(struct device *dev, { struct coresight_device *csdev = to_coresight_device(dev); - return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->activated); + return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->sysfs_sink_activated); } static ssize_t enable_sink_store(struct device *dev, @@ -1274,10 +1264,7 @@ static ssize_t enable_sink_store(struct device *dev, if (ret) return ret; - if (val) - csdev->activated = true; - else - csdev->activated = false; + csdev->sysfs_sink_activated = !!val; return size; diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 30c051055e54..ced5be05a527 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -130,8 +130,6 @@ void coresight_disable_path(struct list_head *path); int coresight_enable_path(struct list_head *path, enum cs_mode mode, void *sink_data); struct coresight_device *coresight_get_sink(struct list_head *path); -struct coresight_device * -coresight_get_enabled_sink(struct coresight_device *source); struct coresight_device *coresight_get_sink_by_id(u32 id); struct coresight_device * coresight_find_default_sink(struct coresight_device *csdev); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index a4cb7dd6ca23..65131bfbd904 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -229,10 +229,12 @@ struct coresight_sysfs_link { * @refcnt: keep track of what is in use. * @orphan: true if the component has connections that haven't been linked. * @enable: 'true' if component is currently part of an active path. - * @activated: 'true' only if a _sink_ has been activated. A sink can be - * activated but not yet enabled. Enabling for a _sink_ - * happens when a source has been selected and a path is enabled - * from source to that sink. + * @sysfs_sink_activated: 'true' when a sink has been selected for use via sysfs + * by writing a 1 to the 'enable_sink' file. A sink can be + * activated but not yet enabled. Enabling for a _sink_ happens + * when a source has been selected and a path is enabled from + * source to that sink. A sink can also become enabled but not + * activated if it's used via Perf. * @ea: Device attribute for sink representation under PMU directory. * @def_sink: cached reference to default sink found for this device. * @nr_links: number of sysfs links created to other components from this @@ -252,9 +254,9 @@ struct coresight_device { struct device dev; atomic_t refcnt; bool orphan; - bool enable; /* true only if configured as part of a path */ + bool enable; /* sink specific fields */ - bool activated; /* true only if a sink is part of a path */ + bool sysfs_sink_activated; struct dev_ext_attribute *ea; struct coresight_device *def_sink; /* sysfs links between components */ From patchwork Tue Dec 12 15:54:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Clark X-Patchwork-Id: 13489559 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 267A2C4332F for ; Tue, 12 Dec 2023 15:55:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=uPdVcGLlC/tM0FnxgOliADVm1ZSBfnpEZmJ0vDKwEMQ=; b=zu2iQ/MOAue9jy n4U/ASyY6si19V43QAeba7PS8bG9mcHeM7uU46bqV8+5+07yvswKpCtwxiMKBWiy5edds+MgT7ZKA Q5kApxlcOfXK2iDJqIvdX5aU+cijGoci/mHPpmeu/kgD8bEXUSDuIlyqa7D0SmB19FmM11en0N6G7 GKWg80oomlzWFIiZTW+tyTdu2w9A23pe4zYtO/mcM2O9u07/IZcYSrlM9rOyEmf/y11+AzzpnPXRX S3h3W5Q0hNpu9sgwOSs5MlHbXikaYTpnFgMqSTRPKUHtToBJodt8beKEiDjmDPnOHxE3jFGUx/8Su WSNpPu54FtGmDS4Dc+0A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56N-00C8AZ-3D; Tue, 12 Dec 2023 15:55:20 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56L-00C890-12 for linux-arm-kernel@lists.infradead.org; Tue, 12 Dec 2023 15:55:18 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 05E23143D; Tue, 12 Dec 2023 07:56:03 -0800 (PST) Received: from e127643.broadband (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 322E13F738; Tue, 12 Dec 2023 07:55:15 -0800 (PST) From: James Clark To: coresight@lists.linaro.org, suzuki.poulose@arm.com Cc: James Clark , Mike Leach , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com Subject: [PATCH 3/8] coresight: Remove ops callback checks Date: Tue, 12 Dec 2023 15:54:00 +0000 Message-Id: <20231212155407.1429121-4-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231212155407.1429121-1-james.clark@arm.com> References: <20231212155407.1429121-1-james.clark@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231212_075517_458791_FAA3DF09 X-CRM114-Status: GOOD ( 17.60 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The check for the existence of callbacks before using them implies that this happens and is supported. There are no devices without enable/disable callbacks, and it wouldn't be possible to add a new working device without adding them either, so just remove them. Furthermore, there are more callbacks than just enable and disable that are already used unguarded in other places. The comment about new session compatibility doesn't seem to match up to the line of code that it's on so remove it. I think it's alluding to the fact that sinks will check if they were already enabled via sysfs or Perf and fail the enable. But there are more detailed comments at those places, and this one isn't very useful. Signed-off-by: James Clark --- drivers/hwtracing/coresight/coresight-core.c | 51 +++++--------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index f79aa9ff9b64..ab226441e5f4 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -279,16 +279,8 @@ EXPORT_SYMBOL_GPL(coresight_add_helper); static int coresight_enable_sink(struct coresight_device *csdev, enum cs_mode mode, void *data) { - int ret; - - /* - * We need to make sure the "new" session is compatible with the - * existing "mode" of operation. - */ - if (!sink_ops(csdev)->enable) - return -EINVAL; + int ret = sink_ops(csdev)->enable(csdev, mode, data); - ret = sink_ops(csdev)->enable(csdev, mode, data); if (ret) return ret; @@ -299,12 +291,7 @@ static int coresight_enable_sink(struct coresight_device *csdev, static void coresight_disable_sink(struct coresight_device *csdev) { - int ret; - - if (!sink_ops(csdev)->disable) - return; - - ret = sink_ops(csdev)->disable(csdev); + int ret = sink_ops(csdev)->disable(csdev); if (ret) return; csdev->enable = false; @@ -330,11 +317,9 @@ static int coresight_enable_link(struct coresight_device *csdev, if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && IS_ERR(outconn)) return PTR_ERR(outconn); - if (link_ops(csdev)->enable) { - ret = link_ops(csdev)->enable(csdev, inconn, outconn); - if (!ret) - csdev->enable = true; - } + ret = link_ops(csdev)->enable(csdev, inconn, outconn); + if (!ret) + csdev->enable = true; return ret; } @@ -354,9 +339,7 @@ static void coresight_disable_link(struct coresight_device *csdev, outconn = coresight_find_out_connection(csdev, child); link_subtype = csdev->subtype.link_subtype; - if (link_ops(csdev)->disable) { - link_ops(csdev)->disable(csdev, inconn, outconn); - } + link_ops(csdev)->disable(csdev, inconn, outconn); if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) { for (i = 0; i < csdev->pdata->nr_inconns; i++) @@ -382,11 +365,9 @@ int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode, int ret; if (!csdev->enable) { - if (source_ops(csdev)->enable) { - ret = source_ops(csdev)->enable(csdev, data, mode); - if (ret) - return ret; - } + ret = source_ops(csdev)->enable(csdev, data, mode); + if (ret) + return ret; csdev->enable = true; } @@ -404,11 +385,8 @@ static bool coresight_is_helper(struct coresight_device *csdev) static int coresight_enable_helper(struct coresight_device *csdev, enum cs_mode mode, void *data) { - int ret; + int ret = helper_ops(csdev)->enable(csdev, mode, data); - if (!helper_ops(csdev)->enable) - return 0; - ret = helper_ops(csdev)->enable(csdev, mode, data); if (ret) return ret; @@ -418,12 +396,8 @@ static int coresight_enable_helper(struct coresight_device *csdev, static void coresight_disable_helper(struct coresight_device *csdev) { - int ret; - - if (!helper_ops(csdev)->disable) - return; + int ret = helper_ops(csdev)->disable(csdev, NULL); - ret = helper_ops(csdev)->disable(csdev, NULL); if (ret) return; csdev->enable = false; @@ -453,8 +427,7 @@ static void coresight_disable_helpers(struct coresight_device *csdev) */ void coresight_disable_source(struct coresight_device *csdev, void *data) { - if (source_ops(csdev)->disable) - source_ops(csdev)->disable(csdev, data); + source_ops(csdev)->disable(csdev, data); coresight_disable_helpers(csdev); } EXPORT_SYMBOL_GPL(coresight_disable_source); From patchwork Tue Dec 12 15:54:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Clark X-Patchwork-Id: 13489562 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 68E0DC4332F for ; Tue, 12 Dec 2023 15:56:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=9/u0x/uJG7WomjjVGvuUB7TmG13itqdHZJsDvSgNcj8=; b=Qbz4vsUosVvemV dhn+tuNVB2zdWQp3NU9/FqC8QHr2MRiv433ksM5CZv8DcZGRcsKsnfKEQnL8Qu41kfIX1UXaNgByb Q/vIJiSQajWy5nD6LEoaJjpwulRym49p/oFw1KowC/H5MGERvhvik2Ol78m38Dc/kJTm/FhIswEZA lOtXKqsTQ8FgyPE3/M2Zoo/1GeDqzNlUJPdPphvIlvMoiw01zpSw1EZwx2+h9zMk86Cz8dTqa5TRl YHrmDczLjXKLyhJqQ6WUnmywhlb155SD7RdK9JRtjuP48ukQOVwlbKds+t+GQV9fOAtMBf6XMX2XE rSRg7Ye4uus1VWlpM7hg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56V-00C8DX-2d; Tue, 12 Dec 2023 15:55:27 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56P-00C8B9-1a for linux-arm-kernel@lists.infradead.org; Tue, 12 Dec 2023 15:55:24 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 39AB8143D; Tue, 12 Dec 2023 07:56:07 -0800 (PST) Received: from e127643.broadband (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 484433F738; Tue, 12 Dec 2023 07:55:19 -0800 (PST) From: James Clark To: coresight@lists.linaro.org, suzuki.poulose@arm.com Cc: James Clark , Mike Leach , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com Subject: [PATCH 4/8] coresight: Move mode to struct coresight_device Date: Tue, 12 Dec 2023 15:54:01 +0000 Message-Id: <20231212155407.1429121-5-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231212155407.1429121-1-james.clark@arm.com> References: <20231212155407.1429121-1-james.clark@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231212_075521_683287_4198EAE9 X-CRM114-Status: GOOD ( 28.74 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Most devices use mode, so move the mode definition out of the individual devices and up to the Coresight device. This will allow the core code to also know the mode which will be useful in a later commit. This also fixes the inconsistency of the documentation of the mode field on the individual device types. For example ETB10 had "this ETB is being used". Two devices didn't require an atomic mode type, so these usages have been converted to atomic_get() and atomic_set() only to make it compile, but the documentation of the field in struct coresight_device explains this type of usage. In the future, manipulation of the mode could be completely moved out of the individual devices and into the core code because it's almost all duplicate code, and this change is a step towards that. Signed-off-by: James Clark --- drivers/hwtracing/coresight/coresight-etb10.c | 18 ++++++------- drivers/hwtracing/coresight/coresight-etm.h | 2 -- .../coresight/coresight-etm3x-core.c | 13 +++++----- .../coresight/coresight-etm3x-sysfs.c | 4 +-- drivers/hwtracing/coresight/coresight-stm.c | 20 +++++++------- .../hwtracing/coresight/coresight-tmc-core.c | 2 +- .../hwtracing/coresight/coresight-tmc-etf.c | 26 +++++++++---------- .../hwtracing/coresight/coresight-tmc-etr.c | 20 +++++++------- drivers/hwtracing/coresight/coresight-tmc.h | 2 -- drivers/hwtracing/coresight/ultrasoc-smb.c | 13 +++++----- drivers/hwtracing/coresight/ultrasoc-smb.h | 2 -- include/linux/coresight.h | 6 +++++ 12 files changed, 62 insertions(+), 66 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index fa80039e0821..08e5bba862db 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -76,7 +76,6 @@ DEFINE_CORESIGHT_DEVLIST(etb_devs, "etb"); * @pid: Process ID of the process being monitored by the session * that is using this component. * @buf: area of memory where ETB buffer content gets sent. - * @mode: this ETB is being used. * @buffer_depth: size of @buf. * @trigger_cntr: amount of words to store after a trigger. */ @@ -89,7 +88,6 @@ struct etb_drvdata { local_t reading; pid_t pid; u8 *buf; - u32 mode; u32 buffer_depth; u32 trigger_cntr; }; @@ -150,17 +148,17 @@ static int etb_enable_sysfs(struct coresight_device *csdev) spin_lock_irqsave(&drvdata->spinlock, flags); /* Don't messup with perf sessions. */ - if (drvdata->mode == CS_MODE_PERF) { + if (local_read(&csdev->mode) == CS_MODE_PERF) { ret = -EBUSY; goto out; } - if (drvdata->mode == CS_MODE_DISABLED) { + if (local_read(&csdev->mode) == CS_MODE_DISABLED) { ret = etb_enable_hw(drvdata); if (ret) goto out; - drvdata->mode = CS_MODE_SYSFS; + local_set(&csdev->mode, CS_MODE_SYSFS); } atomic_inc(&csdev->refcnt); @@ -181,7 +179,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) spin_lock_irqsave(&drvdata->spinlock, flags); /* No need to continue if the component is already in used by sysFS. */ - if (drvdata->mode == CS_MODE_SYSFS) { + if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) { ret = -EBUSY; goto out; } @@ -216,7 +214,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) if (!ret) { /* Associate with monitored process. */ drvdata->pid = pid; - drvdata->mode = CS_MODE_PERF; + local_set(&drvdata->csdev->mode, CS_MODE_PERF); atomic_inc(&csdev->refcnt); } @@ -362,11 +360,11 @@ static int etb_disable(struct coresight_device *csdev) } /* Complain if we (somehow) got out of sync */ - WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED); + WARN_ON_ONCE(local_read(&csdev->mode) == CS_MODE_DISABLED); etb_disable_hw(drvdata); /* Dissociate from monitored process. */ drvdata->pid = -1; - drvdata->mode = CS_MODE_DISABLED; + local_set(&csdev->mode, CS_MODE_DISABLED); spin_unlock_irqrestore(&drvdata->spinlock, flags); dev_dbg(&csdev->dev, "ETB disabled\n"); @@ -589,7 +587,7 @@ static void etb_dump(struct etb_drvdata *drvdata) unsigned long flags; spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->mode == CS_MODE_SYSFS) { + if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) { __etb_disable_hw(drvdata); etb_dump_hw(drvdata); __etb_enable_hw(drvdata); diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h index 9a0d08b092ae..e02c3ea972c9 100644 --- a/drivers/hwtracing/coresight/coresight-etm.h +++ b/drivers/hwtracing/coresight/coresight-etm.h @@ -215,7 +215,6 @@ struct etm_config { * @port_size: port size as reported by ETMCR bit 4-6 and 21. * @arch: ETM/PTM version number. * @use_cpu14: true if management registers need to be accessed via CP14. - * @mode: this tracer's mode, i.e sysFS, Perf or disabled. * @sticky_enable: true if ETM base configuration has been done. * @boot_enable:true if we should start tracing at boot time. * @os_unlock: true if access to management registers is allowed. @@ -238,7 +237,6 @@ struct etm_drvdata { int port_size; u8 arch; bool use_cp14; - local_t mode; bool sticky_enable; bool boot_enable; bool os_unlock; diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c index 116a91d90ac2..29f62dfac673 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c @@ -559,7 +559,7 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event, u32 val; struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode); + val = local_cmpxchg(&drvdata->csdev->mode, CS_MODE_DISABLED, mode); /* Someone is already using the tracer */ if (val) @@ -578,7 +578,7 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event, /* The tracer didn't start */ if (ret) - local_set(&drvdata->mode, CS_MODE_DISABLED); + local_set(&drvdata->csdev->mode, CS_MODE_DISABLED); return ret; } @@ -672,14 +672,13 @@ static void etm_disable(struct coresight_device *csdev, struct perf_event *event) { enum cs_mode mode; - struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); /* * For as long as the tracer isn't disabled another entity can't * change its status. As such we can read the status here without * fearing it will change under us. */ - mode = local_read(&drvdata->mode); + mode = local_read(&csdev->mode); switch (mode) { case CS_MODE_DISABLED: @@ -696,7 +695,7 @@ static void etm_disable(struct coresight_device *csdev, } if (mode) - local_set(&drvdata->mode, CS_MODE_DISABLED); + local_set(&csdev->mode, CS_MODE_DISABLED); } static const struct coresight_ops_source etm_source_ops = { @@ -730,7 +729,7 @@ static int etm_starting_cpu(unsigned int cpu) etmdrvdata[cpu]->os_unlock = true; } - if (local_read(&etmdrvdata[cpu]->mode)) + if (local_read(&etmdrvdata[cpu]->csdev->mode)) etm_enable_hw(etmdrvdata[cpu]); spin_unlock(&etmdrvdata[cpu]->spinlock); return 0; @@ -742,7 +741,7 @@ static int etm_dying_cpu(unsigned int cpu) return 0; spin_lock(&etmdrvdata[cpu]->spinlock); - if (local_read(&etmdrvdata[cpu]->mode)) + if (local_read(&etmdrvdata[cpu]->csdev->mode)) etm_disable_hw(etmdrvdata[cpu]); spin_unlock(&etmdrvdata[cpu]->spinlock); return 0; diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c index 2f271b7fb048..6c8429c980b1 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c @@ -722,7 +722,7 @@ static ssize_t cntr_val_show(struct device *dev, struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etm_config *config = &drvdata->config; - if (!local_read(&drvdata->mode)) { + if (!local_read(&drvdata->csdev->mode)) { spin_lock(&drvdata->spinlock); for (i = 0; i < drvdata->nr_cntr; i++) ret += sprintf(buf, "counter %d: %x\n", @@ -941,7 +941,7 @@ static ssize_t seq_curr_state_show(struct device *dev, struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etm_config *config = &drvdata->config; - if (!local_read(&drvdata->mode)) { + if (!local_read(&drvdata->csdev->mode)) { val = config->seq_curr_state; goto out; } diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index a1c27c901ad1..190ba569b05a 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -119,7 +119,6 @@ DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm"); * @spinlock: only one at a time pls. * @chs: the channels accociated to this STM. * @stm: structure associated to the generic STM interface. - * @mode: this tracer's mode (enum cs_mode), i.e sysFS, or disabled. * @traceid: value of the current ID for this component. * @write_bytes: Maximus bytes this STM can write at a time. * @stmsper: settings for register STMSPER. @@ -136,7 +135,6 @@ struct stm_drvdata { spinlock_t spinlock; struct channel_space chs; struct stm_data stm; - local_t mode; u8 traceid; u32 write_bytes; u32 stmsper; @@ -201,7 +199,7 @@ static int stm_enable(struct coresight_device *csdev, struct perf_event *event, if (mode != CS_MODE_SYSFS) return -EINVAL; - val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode); + val = local_cmpxchg(&csdev->mode, CS_MODE_DISABLED, mode); /* Someone is already using the tracer */ if (val) @@ -266,7 +264,7 @@ static void stm_disable(struct coresight_device *csdev, * change its status. As such we can read the status here without * fearing it will change under us. */ - if (local_read(&drvdata->mode) == CS_MODE_SYSFS) { + if (local_read(&csdev->mode) == CS_MODE_SYSFS) { spin_lock(&drvdata->spinlock); stm_disable_hw(drvdata); spin_unlock(&drvdata->spinlock); @@ -276,7 +274,7 @@ static void stm_disable(struct coresight_device *csdev, pm_runtime_put(csdev->dev.parent); - local_set(&drvdata->mode, CS_MODE_DISABLED); + local_set(&csdev->mode, CS_MODE_DISABLED); dev_dbg(&csdev->dev, "STM tracing disabled\n"); } } @@ -373,7 +371,7 @@ static long stm_generic_set_options(struct stm_data *stm_data, { struct stm_drvdata *drvdata = container_of(stm_data, struct stm_drvdata, stm); - if (!(drvdata && local_read(&drvdata->mode))) + if (!(drvdata && local_read(&drvdata->csdev->mode))) return -EINVAL; if (channel >= drvdata->numsp) @@ -408,7 +406,7 @@ static ssize_t notrace stm_generic_packet(struct stm_data *stm_data, struct stm_drvdata, stm); unsigned int stm_flags; - if (!(drvdata && local_read(&drvdata->mode))) + if (!(drvdata && local_read(&drvdata->csdev->mode))) return -EACCES; if (channel >= drvdata->numsp) @@ -515,7 +513,7 @@ static ssize_t port_select_show(struct device *dev, struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent); unsigned long val; - if (!local_read(&drvdata->mode)) { + if (!local_read(&drvdata->csdev->mode)) { val = drvdata->stmspscr; } else { spin_lock(&drvdata->spinlock); @@ -541,7 +539,7 @@ static ssize_t port_select_store(struct device *dev, spin_lock(&drvdata->spinlock); drvdata->stmspscr = val; - if (local_read(&drvdata->mode)) { + if (local_read(&drvdata->csdev->mode)) { CS_UNLOCK(drvdata->base); /* Process as per ARM's TRM recommendation */ stmsper = readl_relaxed(drvdata->base + STMSPER); @@ -562,7 +560,7 @@ static ssize_t port_enable_show(struct device *dev, struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent); unsigned long val; - if (!local_read(&drvdata->mode)) { + if (!local_read(&drvdata->csdev->mode)) { val = drvdata->stmsper; } else { spin_lock(&drvdata->spinlock); @@ -588,7 +586,7 @@ static ssize_t port_enable_store(struct device *dev, spin_lock(&drvdata->spinlock); drvdata->stmsper = val; - if (local_read(&drvdata->mode)) { + if (local_read(&drvdata->csdev->mode)) { CS_UNLOCK(drvdata->base); writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER); CS_LOCK(drvdata->base); diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index 7ec5365e2b64..e5d47f61f9f3 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -558,7 +558,7 @@ static void tmc_shutdown(struct amba_device *adev) spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->mode == CS_MODE_DISABLED) + if (local_read(&drvdata->csdev->mode) == CS_MODE_DISABLED) goto out; if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 7406b65e2cdd..2a7e516052a2 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -89,7 +89,7 @@ static void __tmc_etb_disable_hw(struct tmc_drvdata *drvdata) * When operating in sysFS mode the content of the buffer needs to be * read before the TMC is disabled. */ - if (drvdata->mode == CS_MODE_SYSFS) + if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) tmc_etb_dump_hw(drvdata); tmc_disable_hw(drvdata); @@ -205,7 +205,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) * sink is already enabled no memory is needed and the HW need not be * touched. */ - if (drvdata->mode == CS_MODE_SYSFS) { + if (local_read(&csdev->mode) == CS_MODE_SYSFS) { atomic_inc(&csdev->refcnt); goto out; } @@ -228,7 +228,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) ret = tmc_etb_enable_hw(drvdata); if (!ret) { - drvdata->mode = CS_MODE_SYSFS; + local_set(&csdev->mode, CS_MODE_SYSFS); atomic_inc(&csdev->refcnt); } else { /* Free up the buffer if we failed to enable */ @@ -262,7 +262,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) * No need to continue if the ETB/ETF is already operated * from sysFS. */ - if (drvdata->mode == CS_MODE_SYSFS) { + if (local_read(&csdev->mode) == CS_MODE_SYSFS) { ret = -EBUSY; break; } @@ -292,7 +292,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) if (!ret) { /* Associate with monitored process. */ drvdata->pid = pid; - drvdata->mode = CS_MODE_PERF; + local_set(&csdev->mode, CS_MODE_PERF); atomic_inc(&csdev->refcnt); } } while (0); @@ -344,11 +344,11 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev) } /* Complain if we (somehow) got out of sync */ - WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED); + WARN_ON_ONCE(local_read(&csdev->mode) == CS_MODE_DISABLED); tmc_etb_disable_hw(drvdata); /* Dissociate from monitored process. */ drvdata->pid = -1; - drvdata->mode = CS_MODE_DISABLED; + local_set(&csdev->mode, CS_MODE_DISABLED); spin_unlock_irqrestore(&drvdata->spinlock, flags); @@ -374,7 +374,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev, if (atomic_read(&csdev->refcnt) == 0) { ret = tmc_etf_enable_hw(drvdata); if (!ret) { - drvdata->mode = CS_MODE_SYSFS; + local_set(&csdev->mode, CS_MODE_SYSFS); first_enable = true; } } @@ -403,7 +403,7 @@ static void tmc_disable_etf_link(struct coresight_device *csdev, if (atomic_dec_return(&csdev->refcnt) == 0) { tmc_etf_disable_hw(drvdata); - drvdata->mode = CS_MODE_DISABLED; + local_set(&csdev->mode, CS_MODE_DISABLED); last_disable = true; } spin_unlock_irqrestore(&drvdata->spinlock, flags); @@ -483,7 +483,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, return 0; /* This shouldn't happen */ - if (WARN_ON_ONCE(drvdata->mode != CS_MODE_PERF)) + if (WARN_ON_ONCE(local_read(&csdev->mode) != CS_MODE_PERF)) return 0; spin_lock_irqsave(&drvdata->spinlock, flags); @@ -629,7 +629,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) } /* Don't interfere if operated from Perf */ - if (drvdata->mode == CS_MODE_PERF) { + if (local_read(&drvdata->csdev->mode) == CS_MODE_PERF) { ret = -EINVAL; goto out; } @@ -641,7 +641,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) } /* Disable the TMC if need be */ - if (drvdata->mode == CS_MODE_SYSFS) { + if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) { /* There is no point in reading a TMC in HW FIFO mode */ mode = readl_relaxed(drvdata->base + TMC_MODE); if (mode != TMC_MODE_CIRCULAR_BUFFER) { @@ -673,7 +673,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) spin_lock_irqsave(&drvdata->spinlock, flags); /* Re-enable the TMC if need be */ - if (drvdata->mode == CS_MODE_SYSFS) { + if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) { /* There is no point in reading a TMC in HW FIFO mode */ mode = readl_relaxed(drvdata->base + TMC_MODE); if (mode != TMC_MODE_CIRCULAR_BUFFER) { diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index af02ba5d5f15..3dc989d4fcab 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1143,7 +1143,7 @@ static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata) * When operating in sysFS mode the content of the buffer needs to be * read before the TMC is disabled. */ - if (drvdata->mode == CS_MODE_SYSFS) + if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) tmc_etr_sync_sysfs_buf(drvdata); tmc_disable_hw(drvdata); @@ -1189,7 +1189,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev) spin_lock_irqsave(&drvdata->spinlock, flags); } - if (drvdata->reading || drvdata->mode == CS_MODE_PERF) { + if (drvdata->reading || local_read(&csdev->mode) == CS_MODE_PERF) { ret = -EBUSY; goto out; } @@ -1230,14 +1230,14 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) * sink is already enabled no memory is needed and the HW need not be * touched, even if the buffer size has changed. */ - if (drvdata->mode == CS_MODE_SYSFS) { + if (local_read(&csdev->mode) == CS_MODE_SYSFS) { atomic_inc(&csdev->refcnt); goto out; } ret = tmc_etr_enable_hw(drvdata, sysfs_buf); if (!ret) { - drvdata->mode = CS_MODE_SYSFS; + local_set(&csdev->mode, CS_MODE_SYSFS); atomic_inc(&csdev->refcnt); } @@ -1652,7 +1652,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) spin_lock_irqsave(&drvdata->spinlock, flags); /* Don't use this sink if it is already claimed by sysFS */ - if (drvdata->mode == CS_MODE_SYSFS) { + if (local_read(&csdev->mode) == CS_MODE_SYSFS) { rc = -EBUSY; goto unlock_out; } @@ -1684,7 +1684,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) if (!rc) { /* Associate with monitored process. */ drvdata->pid = pid; - drvdata->mode = CS_MODE_PERF; + local_set(&csdev->mode, CS_MODE_PERF); drvdata->perf_buf = etr_perf->etr_buf; atomic_inc(&csdev->refcnt); } @@ -1725,11 +1725,11 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev) } /* Complain if we (somehow) got out of sync */ - WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED); + WARN_ON_ONCE(local_read(&csdev->mode) == CS_MODE_DISABLED); tmc_etr_disable_hw(drvdata); /* Dissociate from monitored process. */ drvdata->pid = -1; - drvdata->mode = CS_MODE_DISABLED; + local_set(&csdev->mode, CS_MODE_DISABLED); /* Reset perf specific data */ drvdata->perf_buf = NULL; @@ -1777,7 +1777,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) } /* Disable the TMC if we are trying to read from a running session. */ - if (drvdata->mode == CS_MODE_SYSFS) + if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) __tmc_etr_disable_hw(drvdata); drvdata->reading = true; @@ -1799,7 +1799,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) spin_lock_irqsave(&drvdata->spinlock, flags); /* RE-enable the TMC if need be */ - if (drvdata->mode == CS_MODE_SYSFS) { + if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) { /* * The trace run will continue with the same allocated trace * buffer. Since the tracer is still enabled drvdata::buf can't diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index 8dcb426ac3e7..cef979c897e6 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -178,7 +178,6 @@ struct etr_buf { * @size: trace buffer size for this TMC (common for all modes). * @max_burst_size: The maximum burst size that can be initiated by * TMC-ETR on AXI bus. - * @mode: how this TMC is being used. * @config_type: TMC variant, must be of type @tmc_config_type. * @memwidth: width of the memory interface databus, in bytes. * @trigger_cntr: amount of words to store after a trigger. @@ -203,7 +202,6 @@ struct tmc_drvdata { u32 len; u32 size; u32 max_burst_size; - u32 mode; enum tmc_config_type config_type; enum tmc_mem_intf_width memwidth; u32 trigger_cntr; diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c index 10e886455b8b..1a8c64645b92 100644 --- a/drivers/hwtracing/coresight/ultrasoc-smb.c +++ b/drivers/hwtracing/coresight/ultrasoc-smb.c @@ -207,11 +207,11 @@ static void smb_enable_sysfs(struct coresight_device *csdev) { struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent); - if (drvdata->mode != CS_MODE_DISABLED) + if (local_read(&csdev->mode) != CS_MODE_DISABLED) return; smb_enable_hw(drvdata); - drvdata->mode = CS_MODE_SYSFS; + local_set(&csdev->mode, CS_MODE_SYSFS); } static int smb_enable_perf(struct coresight_device *csdev, void *data) @@ -234,7 +234,7 @@ static int smb_enable_perf(struct coresight_device *csdev, void *data) if (drvdata->pid == -1) { smb_enable_hw(drvdata); drvdata->pid = pid; - drvdata->mode = CS_MODE_PERF; + local_set(&csdev->mode, CS_MODE_PERF); } return 0; @@ -253,7 +253,8 @@ static int smb_enable(struct coresight_device *csdev, enum cs_mode mode, return -EBUSY; /* Do nothing, the SMB is already enabled as other mode */ - if (drvdata->mode != CS_MODE_DISABLED && drvdata->mode != mode) + if (local_read(&csdev->mode) != CS_MODE_DISABLED && + local_read(&csdev->mode) != mode) return -EBUSY; switch (mode) { @@ -289,13 +290,13 @@ static int smb_disable(struct coresight_device *csdev) return -EBUSY; /* Complain if we (somehow) got out of sync */ - WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED); + WARN_ON_ONCE(local_read(&csdev->mode) == CS_MODE_DISABLED); smb_disable_hw(drvdata); /* Dissociate from the target process. */ drvdata->pid = -1; - drvdata->mode = CS_MODE_DISABLED; + local_set(&csdev->mode, CS_MODE_DISABLED); dev_dbg(&csdev->dev, "Ultrasoc SMB disabled\n"); return 0; diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.h b/drivers/hwtracing/coresight/ultrasoc-smb.h index 82a44c14a882..a91d39cfccb8 100644 --- a/drivers/hwtracing/coresight/ultrasoc-smb.h +++ b/drivers/hwtracing/coresight/ultrasoc-smb.h @@ -109,7 +109,6 @@ struct smb_data_buffer { * @reading: Synchronise user space access to SMB buffer. * @pid: Process ID of the process being monitored by the * session that is using this component. - * @mode: How this SMB is being used, perf mode or sysfs mode. */ struct smb_drv_data { void __iomem *base; @@ -119,7 +118,6 @@ struct smb_drv_data { spinlock_t spinlock; bool reading; pid_t pid; - enum cs_mode mode; }; #endif diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 65131bfbd904..ba817f563ff7 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -226,6 +226,11 @@ struct coresight_sysfs_link { * by @coresight_ops. * @access: Device i/o access abstraction for this device. * @dev: The device entity associated to this component. + * @mode: This tracer's mode, i.e sysFS, Perf or disabled. This is + * actually an 'enum cs_mode', but is stored in an atomic type. + * This is always accessed through local_read() and local_set(), + * but wherever it's done from within the Coresight device's lock, + * a non-atomic read would also work. * @refcnt: keep track of what is in use. * @orphan: true if the component has connections that haven't been linked. * @enable: 'true' if component is currently part of an active path. @@ -252,6 +257,7 @@ struct coresight_device { const struct coresight_ops *ops; struct csdev_access access; struct device dev; + local_t mode; atomic_t refcnt; bool orphan; bool enable; From patchwork Tue Dec 12 15:54:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Clark X-Patchwork-Id: 13489561 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C373BC4332F for ; Tue, 12 Dec 2023 15:55:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=uxQ6fIK7gpLokFRQsFP3zP/jhQEPrrYO64HBcoIj5QU=; b=Df3F8JSunWqSHH xLjrKboY7k+gWZjOKQMnRfLMiDDr0JlpKFrXF+ZWRKyaEkNRq/YIpynJqmCuye0/TFYSZ2K9tHvVu gMb8wzXW91M5j6g6yhoZBDwS5WWw0sm57jukLHkfS9BQpjTSCFSIDT9tiyfYvnGyYMWT0pNiA4d1I e6e16/ir8RibEjjDp2EE8RmnyvJMss174mmVSseUuvKUsRy/r3ie2PnOrcOvXZ3rSHBhYB6doOaze 5ifop9qP0RfSQrKBNaPOv0yM5MXRqB4DOv8EVAE3CmQr/JY1amQ6nxuuY/oefkx423hjCyuL/jVfc s+gUtsKUWLlBamQDoLZA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56W-00C8Dw-1S; Tue, 12 Dec 2023 15:55:28 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56T-00C8Ca-0o for linux-arm-kernel@lists.infradead.org; Tue, 12 Dec 2023 15:55:27 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 28F3F1474; Tue, 12 Dec 2023 07:56:11 -0800 (PST) Received: from e127643.broadband (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 54AAA3F738; Tue, 12 Dec 2023 07:55:23 -0800 (PST) From: James Clark To: coresight@lists.linaro.org, suzuki.poulose@arm.com Cc: James Clark , Mike Leach , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com Subject: [PATCH 5/8] coresight: Remove the 'enable' field. Date: Tue, 12 Dec 2023 15:54:02 +0000 Message-Id: <20231212155407.1429121-6-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231212155407.1429121-1-james.clark@arm.com> References: <20231212155407.1429121-1-james.clark@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231212_075525_406930_DD8150B8 X-CRM114-Status: GOOD ( 24.23 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 'enable', which probably should have been 'enabled', is only ever read in the core code in relation to controlling sources, and specifically only sources in sysfs mode. Confusingly it's not labelled as such and relying on it can be a source of bugs like the one fixed by commit 078dbba3f0c9 ("coresight: Fix crash when Perf and sysfs modes are used concurrently"). Most importantly, it can only be used when the coresight_mutex is held which is only done when enabling and disabling paths in sysfs mode, and not Perf mode. So to prevent its usage spreading and leaking out to other devices, remove it. It's use is equivalent to checking if the mode is currently sysfs, as due to the coresight_mutex lock, mode == CS_MODE_SYSFS can only become true or untrue when that lock is held, and when mode == CS_MODE_SYSFS the device is both enabled and in sysfs mode. The one place it was used outside of the core code is in TPDA, but that pattern is more appropriately represented using refcounts inside the device's own spinlock. Signed-off-by: James Clark --- drivers/hwtracing/coresight/coresight-core.c | 86 +++++++------------- drivers/hwtracing/coresight/coresight-tpda.c | 12 ++- include/linux/coresight.h | 2 - 3 files changed, 38 insertions(+), 62 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index ab226441e5f4..1d0bd1586590 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -279,29 +279,18 @@ EXPORT_SYMBOL_GPL(coresight_add_helper); static int coresight_enable_sink(struct coresight_device *csdev, enum cs_mode mode, void *data) { - int ret = sink_ops(csdev)->enable(csdev, mode, data); - - if (ret) - return ret; - - csdev->enable = true; - - return 0; + return sink_ops(csdev)->enable(csdev, mode, data); } static void coresight_disable_sink(struct coresight_device *csdev) { - int ret = sink_ops(csdev)->disable(csdev); - if (ret) - return; - csdev->enable = false; + sink_ops(csdev)->disable(csdev); } static int coresight_enable_link(struct coresight_device *csdev, struct coresight_device *parent, struct coresight_device *child) { - int ret = 0; int link_subtype; struct coresight_connection *inconn, *outconn; @@ -317,19 +306,13 @@ static int coresight_enable_link(struct coresight_device *csdev, if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && IS_ERR(outconn)) return PTR_ERR(outconn); - ret = link_ops(csdev)->enable(csdev, inconn, outconn); - if (!ret) - csdev->enable = true; - - return ret; + return link_ops(csdev)->enable(csdev, inconn, outconn); } static void coresight_disable_link(struct coresight_device *csdev, struct coresight_device *parent, struct coresight_device *child) { - int i; - int link_subtype; struct coresight_connection *inconn, *outconn; if (!parent || !child) @@ -337,26 +320,8 @@ static void coresight_disable_link(struct coresight_device *csdev, inconn = coresight_find_out_connection(parent, csdev); outconn = coresight_find_out_connection(csdev, child); - link_subtype = csdev->subtype.link_subtype; link_ops(csdev)->disable(csdev, inconn, outconn); - - if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) { - for (i = 0; i < csdev->pdata->nr_inconns; i++) - if (atomic_read(&csdev->pdata->in_conns[i]->dest_refcnt) != - 0) - return; - } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) { - for (i = 0; i < csdev->pdata->nr_outconns; i++) - if (atomic_read(&csdev->pdata->out_conns[i]->src_refcnt) != - 0) - return; - } else { - if (atomic_read(&csdev->refcnt) != 0) - return; - } - - csdev->enable = false; } int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode, @@ -364,11 +329,16 @@ int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode, { int ret; - if (!csdev->enable) { + /* + * Comparison with CS_MODE_SYSFS works without taking any device + * specific spinlock because the truthyness of that comparison can only + * change with coresight_mutex held, which we already have here. + */ + lockdep_assert_held(&coresight_mutex); + if (local_read(&csdev->mode) != CS_MODE_SYSFS) { ret = source_ops(csdev)->enable(csdev, data, mode); if (ret) return ret; - csdev->enable = true; } atomic_inc(&csdev->refcnt); @@ -385,22 +355,12 @@ static bool coresight_is_helper(struct coresight_device *csdev) static int coresight_enable_helper(struct coresight_device *csdev, enum cs_mode mode, void *data) { - int ret = helper_ops(csdev)->enable(csdev, mode, data); - - if (ret) - return ret; - - csdev->enable = true; - return 0; + return helper_ops(csdev)->enable(csdev, mode, data); } static void coresight_disable_helper(struct coresight_device *csdev) { - int ret = helper_ops(csdev)->disable(csdev, NULL); - - if (ret) - return; - csdev->enable = false; + helper_ops(csdev)->disable(csdev, NULL); } static void coresight_disable_helpers(struct coresight_device *csdev) @@ -445,11 +405,15 @@ EXPORT_SYMBOL_GPL(coresight_disable_source); static bool coresight_disable_source_sysfs(struct coresight_device *csdev, void *data) { + lockdep_assert_held(&coresight_mutex); + if (local_read(&csdev->mode) != CS_MODE_SYSFS) + return false; + if (atomic_dec_return(&csdev->refcnt) == 0) { coresight_disable_source(csdev, data); - csdev->enable = false; + return true; } - return !csdev->enable; + return false; } /* @@ -1097,7 +1061,13 @@ int coresight_enable(struct coresight_device *csdev) if (ret) goto out; - if (csdev->enable) { + /* + * mode == SYSFS implies that it's already enabled. Don't look at the + * refcount to determine this because we don't claim the source until + * coresight_enable_source() so can still race with Perf mode which + * doesn't hold coresight_mutex. + */ + if (local_read(&csdev->mode) == CS_MODE_SYSFS) { /* * There could be multiple applications driving the software * source. So keep the refcount for each such user when the @@ -1183,7 +1153,7 @@ void coresight_disable(struct coresight_device *csdev) if (ret) goto out; - if (!csdev->enable || !coresight_disable_source_sysfs(csdev, NULL)) + if (!coresight_disable_source_sysfs(csdev, NULL)) goto out; switch (csdev->subtype.source_subtype) { @@ -1249,7 +1219,9 @@ static ssize_t enable_source_show(struct device *dev, { struct coresight_device *csdev = to_coresight_device(dev); - return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->enable); + guard(mutex)(&coresight_mutex); + return scnprintf(buf, PAGE_SIZE, "%u\n", + local_read(&csdev->mode) == CS_MODE_SYSFS); } static ssize_t enable_source_store(struct device *dev, diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 5f82737c37bb..65c70995ab00 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -148,7 +148,11 @@ static int __tpda_enable(struct tpda_drvdata *drvdata, int port) CS_UNLOCK(drvdata->base); - if (!drvdata->csdev->enable) + /* + * Only do pre-port enable for first port that calls enable when the + * device's main refcount is still 0 + */ + if (!atomic_read(&drvdata->csdev->refcnt)) tpda_enable_pre_port(drvdata); ret = tpda_enable_port(drvdata, port); @@ -169,6 +173,7 @@ static int tpda_enable(struct coresight_device *csdev, ret = __tpda_enable(drvdata, in->dest_port); if (!ret) { atomic_inc(&in->dest_refcnt); + atomic_inc(&csdev->refcnt); dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); } } @@ -197,9 +202,10 @@ static void tpda_disable(struct coresight_device *csdev, struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); spin_lock(&drvdata->spinlock); - if (atomic_dec_return(&in->dest_refcnt) == 0) + if (atomic_dec_return(&in->dest_refcnt) == 0) { __tpda_disable(drvdata, in->dest_port); - + atomic_dec(&csdev->refcnt); + } spin_unlock(&drvdata->spinlock); dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index ba817f563ff7..46e6667f72ce 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -233,7 +233,6 @@ struct coresight_sysfs_link { * a non-atomic read would also work. * @refcnt: keep track of what is in use. * @orphan: true if the component has connections that haven't been linked. - * @enable: 'true' if component is currently part of an active path. * @sysfs_sink_activated: 'true' when a sink has been selected for use via sysfs * by writing a 1 to the 'enable_sink' file. A sink can be * activated but not yet enabled. Enabling for a _sink_ happens @@ -260,7 +259,6 @@ struct coresight_device { local_t mode; atomic_t refcnt; bool orphan; - bool enable; /* sink specific fields */ bool sysfs_sink_activated; struct dev_ext_attribute *ea; From patchwork Tue Dec 12 15:54:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Clark X-Patchwork-Id: 13489564 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BA954C4332F for ; Tue, 12 Dec 2023 15:56:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=LR/rBxVCCS1OVFpM0FGiY6kmK2hmj3dpSQMlZhQPiWQ=; b=CHz3OacrQh2Ut/ 3/mETzBq6JwD5qtdaxpu7rQ1hJArPGoLMHnjbfWi6BnR4DYk6G12JpUSGJBtGQ6m2f47Bp+6csqoc AGcRTbkHUZEagJvyJfzN5thzMS8bsk2bYjCdkcQvCV6EwmQv9vIRjOIrowlTf2xwtFrmkT1LDjrhN DFdsQbEfJPARzCKtIJN0lWBj+YX/jIvhyUDx7rSjyjNCXdscEyJAyKnhMADiMcb+UY5xGT3NGlqrk Oi1GrmcvFcAx6iA6Q+Ri+lT/9MzT19gRWe3rbW9YhJP6sGBgitwqkh1AEvk/7cV+lDa/4rZa3IgiA pCaqtfQpMOKqOhUsKbiQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56f-00C8IK-1M; Tue, 12 Dec 2023 15:55:37 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56X-00C8Eg-2K for linux-arm-kernel@lists.infradead.org; Tue, 12 Dec 2023 15:55:33 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 68F98143D; Tue, 12 Dec 2023 07:56:15 -0800 (PST) Received: from e127643.broadband (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 77E793F738; Tue, 12 Dec 2023 07:55:27 -0800 (PST) From: James Clark To: coresight@lists.linaro.org, suzuki.poulose@arm.com Cc: James Clark , Mike Leach , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com Subject: [PATCH 6/8] coresight: Move all sysfs code to sysfs file Date: Tue, 12 Dec 2023 15:54:03 +0000 Message-Id: <20231212155407.1429121-7-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231212155407.1429121-1-james.clark@arm.com> References: <20231212155407.1429121-1-james.clark@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231212_075529_910001_C769B1E4 X-CRM114-Status: GOOD ( 35.30 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org At the moment the core file contains both sysfs functionality and core functionality, while the Perf mode is in a separate file in coresight-etm-perf.c Many of the functions have ambiguous names like coresight_enable_source() which actually only work in relation to the sysfs mode. To avoid further confusion, move everything that isn't core functionality into the sysfs file and append _sysfs to the ambiguous functions. Signed-off-by: James Clark --- drivers/hwtracing/coresight/coresight-core.c | 394 +----------------- .../coresight/coresight-etm3x-core.c | 4 +- .../coresight/coresight-etm4x-core.c | 4 +- drivers/hwtracing/coresight/coresight-priv.h | 5 +- drivers/hwtracing/coresight/coresight-stm.c | 4 +- drivers/hwtracing/coresight/coresight-sysfs.c | 390 +++++++++++++++++ include/linux/coresight.h | 8 +- 7 files changed, 407 insertions(+), 402 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 1d0bd1586590..eb72cdd1a273 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -25,15 +24,12 @@ #include "coresight-priv.h" #include "coresight-syscfg.h" -static DEFINE_MUTEX(coresight_mutex); -static DEFINE_PER_CPU(struct coresight_device *, csdev_sink); - /* - * Use IDR to map the hash of the source's device name - * to the pointer of path for the source. The idr is for - * the sources which aren't associated with CPU. + * Mutex used to lock all sysfs enable and disable actions and loading and + * unloading devices by the Coresight core. */ -static DEFINE_IDR(path_idr); +DEFINE_MUTEX(coresight_mutex); +static DEFINE_PER_CPU(struct coresight_device *, csdev_sink); /** * struct coresight_node - elements of a path, from source to sink @@ -45,12 +41,6 @@ struct coresight_node { struct list_head link; }; -/* - * When operating Coresight drivers from the sysFS interface, only a single - * path can exist from a tracer (associated to a CPU) to a sink. - */ -static DEFINE_PER_CPU(struct list_head *, tracer_path); - /* * When losing synchronisation a new barrier packet needs to be inserted at the * beginning of the data collected in a buffer. That way the decoder knows that @@ -61,34 +51,6 @@ EXPORT_SYMBOL_GPL(coresight_barrier_pkt); static const struct cti_assoc_op *cti_assoc_ops; -ssize_t coresight_simple_show_pair(struct device *_dev, - struct device_attribute *attr, char *buf) -{ - struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev); - struct cs_pair_attribute *cs_attr = container_of(attr, struct cs_pair_attribute, attr); - u64 val; - - pm_runtime_get_sync(_dev->parent); - val = csdev_access_relaxed_read_pair(&csdev->access, cs_attr->lo_off, cs_attr->hi_off); - pm_runtime_put_sync(_dev->parent); - return sysfs_emit(buf, "0x%llx\n", val); -} -EXPORT_SYMBOL_GPL(coresight_simple_show_pair); - -ssize_t coresight_simple_show32(struct device *_dev, - struct device_attribute *attr, char *buf) -{ - struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev); - struct cs_off_attribute *cs_attr = container_of(attr, struct cs_off_attribute, attr); - u64 val; - - pm_runtime_get_sync(_dev->parent); - val = csdev_access_relaxed_read32(&csdev->access, cs_attr->off); - pm_runtime_put_sync(_dev->parent); - return sysfs_emit(buf, "0x%llx\n", val); -} -EXPORT_SYMBOL_GPL(coresight_simple_show32); - void coresight_set_cti_ops(const struct cti_assoc_op *cti_op) { cti_assoc_ops = cti_op; @@ -324,29 +286,6 @@ static void coresight_disable_link(struct coresight_device *csdev, link_ops(csdev)->disable(csdev, inconn, outconn); } -int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode, - void *data) -{ - int ret; - - /* - * Comparison with CS_MODE_SYSFS works without taking any device - * specific spinlock because the truthyness of that comparison can only - * change with coresight_mutex held, which we already have here. - */ - lockdep_assert_held(&coresight_mutex); - if (local_read(&csdev->mode) != CS_MODE_SYSFS) { - ret = source_ops(csdev)->enable(csdev, data, mode); - if (ret) - return ret; - } - - atomic_inc(&csdev->refcnt); - - return 0; -} -EXPORT_SYMBOL_GPL(coresight_enable_source); - static bool coresight_is_helper(struct coresight_device *csdev) { return csdev->type == CORESIGHT_DEV_TYPE_HELPER; @@ -392,30 +331,6 @@ void coresight_disable_source(struct coresight_device *csdev, void *data) } EXPORT_SYMBOL_GPL(coresight_disable_source); -/** - * coresight_disable_source_sysfs - Drop the reference count by 1 and disable - * the device if there are no users left. - * - * @csdev: The coresight device to disable - * @data: Opaque data to pass on to the disable function of the source device. - * For example in perf mode this is a pointer to the struct perf_event. - * - * Returns true if the device has been disabled. - */ -static bool coresight_disable_source_sysfs(struct coresight_device *csdev, - void *data) -{ - lockdep_assert_held(&coresight_mutex); - if (local_read(&csdev->mode) != CS_MODE_SYSFS) - return false; - - if (atomic_dec_return(&csdev->refcnt) == 0) { - coresight_disable_source(csdev, data); - return true; - } - return false; -} - /* * coresight_disable_path_from : Disable components in the given path beyond * @nd in the list. If @nd is NULL, all the components, except the SOURCE are @@ -572,39 +487,6 @@ struct coresight_device *coresight_get_sink(struct list_head *path) return csdev; } -/** - * coresight_find_activated_sysfs_sink - returns the first sink activated via - * sysfs using connection based search starting from the source reference. - * - * @csdev: Coresight source device reference - */ -static struct coresight_device * -coresight_find_activated_sysfs_sink(struct coresight_device *csdev) -{ - int i; - struct coresight_device *sink = NULL; - - if ((csdev->type == CORESIGHT_DEV_TYPE_SINK || - csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && - csdev->sysfs_sink_activated) - return csdev; - - /* - * Recursively explore each port found on this element. - */ - for (i = 0; i < csdev->pdata->nr_outconns; i++) { - struct coresight_device *child_dev; - - child_dev = csdev->pdata->out_conns[i]->dest_dev; - if (child_dev) - sink = coresight_find_activated_sysfs_sink(child_dev); - if (sink) - return sink; - } - - return NULL; -} - static int coresight_sink_by_id(struct device *dev, const void *data) { struct coresight_device *csdev = to_coresight_device(dev); @@ -1015,274 +897,6 @@ static void coresight_clear_default_sink(struct coresight_device *csdev) } } -/** coresight_validate_source - make sure a source has the right credentials - * @csdev: the device structure for a source. - * @function: the function this was called from. - * - * Assumes the coresight_mutex is held. - */ -static int coresight_validate_source(struct coresight_device *csdev, - const char *function) -{ - u32 type, subtype; - - type = csdev->type; - subtype = csdev->subtype.source_subtype; - - if (type != CORESIGHT_DEV_TYPE_SOURCE) { - dev_err(&csdev->dev, "wrong device type in %s\n", function); - return -EINVAL; - } - - if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC && - subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE && - subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM && - subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) { - dev_err(&csdev->dev, "wrong device subtype in %s\n", function); - return -EINVAL; - } - - return 0; -} - -int coresight_enable(struct coresight_device *csdev) -{ - int cpu, ret = 0; - struct coresight_device *sink; - struct list_head *path; - enum coresight_dev_subtype_source subtype; - u32 hash; - - subtype = csdev->subtype.source_subtype; - - mutex_lock(&coresight_mutex); - - ret = coresight_validate_source(csdev, __func__); - if (ret) - goto out; - - /* - * mode == SYSFS implies that it's already enabled. Don't look at the - * refcount to determine this because we don't claim the source until - * coresight_enable_source() so can still race with Perf mode which - * doesn't hold coresight_mutex. - */ - if (local_read(&csdev->mode) == CS_MODE_SYSFS) { - /* - * There could be multiple applications driving the software - * source. So keep the refcount for each such user when the - * source is already enabled. - */ - if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE) - atomic_inc(&csdev->refcnt); - goto out; - } - - sink = coresight_find_activated_sysfs_sink(csdev); - if (!sink) { - ret = -EINVAL; - goto out; - } - - path = coresight_build_path(csdev, sink); - if (IS_ERR(path)) { - pr_err("building path(s) failed\n"); - ret = PTR_ERR(path); - goto out; - } - - ret = coresight_enable_path(path, CS_MODE_SYSFS, NULL); - if (ret) - goto err_path; - - ret = coresight_enable_source(csdev, CS_MODE_SYSFS, NULL); - if (ret) - goto err_source; - - switch (subtype) { - case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: - /* - * When working from sysFS it is important to keep track - * of the paths that were created so that they can be - * undone in 'coresight_disable()'. Since there can only - * be a single session per tracer (when working from sysFS) - * a per-cpu variable will do just fine. - */ - cpu = source_ops(csdev)->cpu_id(csdev); - per_cpu(tracer_path, cpu) = path; - break; - case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: - case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM: - case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS: - /* - * Use the hash of source's device name as ID - * and map the ID to the pointer of the path. - */ - hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev))); - ret = idr_alloc_u32(&path_idr, path, &hash, hash, GFP_KERNEL); - if (ret) - goto err_source; - break; - default: - /* We can't be here */ - break; - } - -out: - mutex_unlock(&coresight_mutex); - return ret; - -err_source: - coresight_disable_path(path); - -err_path: - coresight_release_path(path); - goto out; -} -EXPORT_SYMBOL_GPL(coresight_enable); - -void coresight_disable(struct coresight_device *csdev) -{ - int cpu, ret; - struct list_head *path = NULL; - u32 hash; - - mutex_lock(&coresight_mutex); - - ret = coresight_validate_source(csdev, __func__); - if (ret) - goto out; - - if (!coresight_disable_source_sysfs(csdev, NULL)) - goto out; - - switch (csdev->subtype.source_subtype) { - case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: - cpu = source_ops(csdev)->cpu_id(csdev); - path = per_cpu(tracer_path, cpu); - per_cpu(tracer_path, cpu) = NULL; - break; - case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: - case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM: - case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS: - hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev))); - /* Find the path by the hash. */ - path = idr_find(&path_idr, hash); - if (path == NULL) { - pr_err("Path is not found for %s\n", dev_name(&csdev->dev)); - goto out; - } - idr_remove(&path_idr, hash); - break; - default: - /* We can't be here */ - break; - } - - coresight_disable_path(path); - coresight_release_path(path); - -out: - mutex_unlock(&coresight_mutex); -} -EXPORT_SYMBOL_GPL(coresight_disable); - -static ssize_t enable_sink_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct coresight_device *csdev = to_coresight_device(dev); - - return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->sysfs_sink_activated); -} - -static ssize_t enable_sink_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - int ret; - unsigned long val; - struct coresight_device *csdev = to_coresight_device(dev); - - ret = kstrtoul(buf, 10, &val); - if (ret) - return ret; - - csdev->sysfs_sink_activated = !!val; - - return size; - -} -static DEVICE_ATTR_RW(enable_sink); - -static ssize_t enable_source_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct coresight_device *csdev = to_coresight_device(dev); - - guard(mutex)(&coresight_mutex); - return scnprintf(buf, PAGE_SIZE, "%u\n", - local_read(&csdev->mode) == CS_MODE_SYSFS); -} - -static ssize_t enable_source_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - int ret = 0; - unsigned long val; - struct coresight_device *csdev = to_coresight_device(dev); - - ret = kstrtoul(buf, 10, &val); - if (ret) - return ret; - - if (val) { - ret = coresight_enable(csdev); - if (ret) - return ret; - } else { - coresight_disable(csdev); - } - - return size; -} -static DEVICE_ATTR_RW(enable_source); - -static struct attribute *coresight_sink_attrs[] = { - &dev_attr_enable_sink.attr, - NULL, -}; -ATTRIBUTE_GROUPS(coresight_sink); - -static struct attribute *coresight_source_attrs[] = { - &dev_attr_enable_source.attr, - NULL, -}; -ATTRIBUTE_GROUPS(coresight_source); - -static struct device_type coresight_dev_type[] = { - { - .name = "sink", - .groups = coresight_sink_groups, - }, - { - .name = "link", - }, - { - .name = "linksink", - .groups = coresight_sink_groups, - }, - { - .name = "source", - .groups = coresight_source_groups, - }, - { - .name = "helper", - } -}; -/* Ensure the enum matches the names and groups */ -static_assert(ARRAY_SIZE(coresight_dev_type) == CORESIGHT_DEV_TYPE_MAX); - static void coresight_device_release(struct device *dev) { struct coresight_device *csdev = to_coresight_device(dev); diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c index 29f62dfac673..a8be115636f0 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c @@ -714,7 +714,7 @@ static int etm_online_cpu(unsigned int cpu) return 0; if (etmdrvdata[cpu]->boot_enable && !etmdrvdata[cpu]->sticky_enable) - coresight_enable(etmdrvdata[cpu]->csdev); + coresight_enable_sysfs(etmdrvdata[cpu]->csdev); return 0; } @@ -924,7 +924,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) dev_info(&drvdata->csdev->dev, "%s initialized\n", (char *)coresight_get_uci_data(id)); if (boot_enable) { - coresight_enable(drvdata->csdev); + coresight_enable_sysfs(drvdata->csdev); drvdata->boot_enable = true; } diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index ce1995a2827f..cbb4ac8be133 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -1650,7 +1650,7 @@ static int etm4_online_cpu(unsigned int cpu) return etm4_probe_cpu(cpu); if (etmdrvdata[cpu]->boot_enable && !etmdrvdata[cpu]->sticky_enable) - coresight_enable(etmdrvdata[cpu]->csdev); + coresight_enable_sysfs(etmdrvdata[cpu]->csdev); return 0; } @@ -2098,7 +2098,7 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg) drvdata->cpu, type_name, major, minor); if (boot_enable) { - coresight_enable(drvdata->csdev); + coresight_enable_sysfs(drvdata->csdev); drvdata->boot_enable = true; } diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index ced5be05a527..eb365236f9a9 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -12,6 +12,9 @@ #include #include +extern struct mutex coresight_mutex; +extern struct device_type coresight_dev_type[]; + /* * Coresight management registers (0xf00-0xfcc) * 0xfa0 - 0xfa4: Management registers in PFTv1.0 @@ -229,8 +232,6 @@ void coresight_add_helper(struct coresight_device *csdev, void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev); struct coresight_device *coresight_get_percpu_sink(int cpu); -int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode, - void *data); void coresight_disable_source(struct coresight_device *csdev, void *data); #endif diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 190ba569b05a..af9b21224246 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -332,7 +332,7 @@ static int stm_generic_link(struct stm_data *stm_data, if (!drvdata || !drvdata->csdev) return -EINVAL; - return coresight_enable(drvdata->csdev); + return coresight_enable_sysfs(drvdata->csdev); } static void stm_generic_unlink(struct stm_data *stm_data, @@ -343,7 +343,7 @@ static void stm_generic_unlink(struct stm_data *stm_data, if (!drvdata || !drvdata->csdev) return; - coresight_disable(drvdata->csdev); + coresight_disable_sysfs(drvdata->csdev); } static phys_addr_t diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c index dd78e9fcfc4d..92cdf8139f23 100644 --- a/drivers/hwtracing/coresight/coresight-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-sysfs.c @@ -5,10 +5,400 @@ */ #include +#include #include #include "coresight-priv.h" +/* + * Use IDR to map the hash of the source's device name + * to the pointer of path for the source. The idr is for + * the sources which aren't associated with CPU. + */ +static DEFINE_IDR(path_idr); + +/* + * When operating Coresight drivers from the sysFS interface, only a single + * path can exist from a tracer (associated to a CPU) to a sink. + */ +static DEFINE_PER_CPU(struct list_head *, tracer_path); + +ssize_t coresight_simple_show_pair(struct device *_dev, + struct device_attribute *attr, char *buf) +{ + struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev); + struct cs_pair_attribute *cs_attr = container_of(attr, struct cs_pair_attribute, attr); + u64 val; + + pm_runtime_get_sync(_dev->parent); + val = csdev_access_relaxed_read_pair(&csdev->access, cs_attr->lo_off, cs_attr->hi_off); + pm_runtime_put_sync(_dev->parent); + return sysfs_emit(buf, "0x%llx\n", val); +} +EXPORT_SYMBOL_GPL(coresight_simple_show_pair); + +ssize_t coresight_simple_show32(struct device *_dev, + struct device_attribute *attr, char *buf) +{ + struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev); + struct cs_off_attribute *cs_attr = container_of(attr, struct cs_off_attribute, attr); + u64 val; + + pm_runtime_get_sync(_dev->parent); + val = csdev_access_relaxed_read32(&csdev->access, cs_attr->off); + pm_runtime_put_sync(_dev->parent); + return sysfs_emit(buf, "0x%llx\n", val); +} +EXPORT_SYMBOL_GPL(coresight_simple_show32); + +static int coresight_enable_source_sysfs(struct coresight_device *csdev, + enum cs_mode mode, void *data) +{ + int ret; + + /* + * Comparison with CS_MODE_SYSFS works without taking any device + * specific spinlock because the truthyness of that comparison can only + * change with coresight_mutex held, which we already have here. + */ + lockdep_assert_held(&coresight_mutex); + if (local_read(&csdev->mode) != CS_MODE_SYSFS) { + ret = source_ops(csdev)->enable(csdev, data, mode); + if (ret) + return ret; + } + + atomic_inc(&csdev->refcnt); + + return 0; +} + +/** + * coresight_disable_source_sysfs - Drop the reference count by 1 and disable + * the device if there are no users left. + * + * @csdev: The coresight device to disable + * @data: Opaque data to pass on to the disable function of the source device. + * For example in perf mode this is a pointer to the struct perf_event. + * + * Returns true if the device has been disabled. + */ +static bool coresight_disable_source_sysfs(struct coresight_device *csdev, + void *data) +{ + lockdep_assert_held(&coresight_mutex); + if (local_read(&csdev->mode) != CS_MODE_SYSFS) + return false; + + if (atomic_dec_return(&csdev->refcnt) == 0) { + coresight_disable_source(csdev, data); + return true; + } + return false; +} + +/** + * coresight_find_activated_sysfs_sink - returns the first sink activated via + * sysfs using connection based search starting from the source reference. + * + * @csdev: Coresight source device reference + */ +static struct coresight_device * +coresight_find_activated_sysfs_sink(struct coresight_device *csdev) +{ + int i; + struct coresight_device *sink = NULL; + + if ((csdev->type == CORESIGHT_DEV_TYPE_SINK || + csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && + csdev->sysfs_sink_activated) + return csdev; + + /* + * Recursively explore each port found on this element. + */ + for (i = 0; i < csdev->pdata->nr_outconns; i++) { + struct coresight_device *child_dev; + + child_dev = csdev->pdata->out_conns[i]->dest_dev; + if (child_dev) + sink = coresight_find_activated_sysfs_sink(child_dev); + if (sink) + return sink; + } + + return NULL; +} + +/** coresight_validate_source - make sure a source has the right credentials to + * be used via sysfs. + * @csdev: the device structure for a source. + * @function: the function this was called from. + * + * Assumes the coresight_mutex is held. + */ +static int coresight_validate_source_sysfs(struct coresight_device *csdev, + const char *function) +{ + u32 type, subtype; + + type = csdev->type; + subtype = csdev->subtype.source_subtype; + + if (type != CORESIGHT_DEV_TYPE_SOURCE) { + dev_err(&csdev->dev, "wrong device type in %s\n", function); + return -EINVAL; + } + + if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC && + subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE && + subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM && + subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) { + dev_err(&csdev->dev, "wrong device subtype in %s\n", function); + return -EINVAL; + } + + return 0; +} + +int coresight_enable_sysfs(struct coresight_device *csdev) +{ + int cpu, ret = 0; + struct coresight_device *sink; + struct list_head *path; + enum coresight_dev_subtype_source subtype; + u32 hash; + + subtype = csdev->subtype.source_subtype; + + mutex_lock(&coresight_mutex); + + ret = coresight_validate_source_sysfs(csdev, __func__); + if (ret) + goto out; + + /* + * mode == SYSFS implies that it's already enabled. Don't look at the + * refcount to determine this because we don't claim the source until + * coresight_enable_source() so can still race with Perf mode which + * doesn't hold coresight_mutex. + */ + if (local_read(&csdev->mode) == CS_MODE_SYSFS) { + /* + * There could be multiple applications driving the software + * source. So keep the refcount for each such user when the + * source is already enabled. + */ + if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE) + atomic_inc(&csdev->refcnt); + goto out; + } + + sink = coresight_find_activated_sysfs_sink(csdev); + if (!sink) { + ret = -EINVAL; + goto out; + } + + path = coresight_build_path(csdev, sink); + if (IS_ERR(path)) { + pr_err("building path(s) failed\n"); + ret = PTR_ERR(path); + goto out; + } + + ret = coresight_enable_path(path, CS_MODE_SYSFS, NULL); + if (ret) + goto err_path; + + ret = coresight_enable_source_sysfs(csdev, CS_MODE_SYSFS, NULL); + if (ret) + goto err_source; + + switch (subtype) { + case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: + /* + * When working from sysFS it is important to keep track + * of the paths that were created so that they can be + * undone in 'coresight_disable()'. Since there can only + * be a single session per tracer (when working from sysFS) + * a per-cpu variable will do just fine. + */ + cpu = source_ops(csdev)->cpu_id(csdev); + per_cpu(tracer_path, cpu) = path; + break; + case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: + case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM: + case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS: + /* + * Use the hash of source's device name as ID + * and map the ID to the pointer of the path. + */ + hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev))); + ret = idr_alloc_u32(&path_idr, path, &hash, hash, GFP_KERNEL); + if (ret) + goto err_source; + break; + default: + /* We can't be here */ + break; + } + +out: + mutex_unlock(&coresight_mutex); + return ret; + +err_source: + coresight_disable_path(path); + +err_path: + coresight_release_path(path); + goto out; +} +EXPORT_SYMBOL_GPL(coresight_enable_sysfs); + +void coresight_disable_sysfs(struct coresight_device *csdev) +{ + int cpu, ret; + struct list_head *path = NULL; + u32 hash; + + mutex_lock(&coresight_mutex); + + ret = coresight_validate_source_sysfs(csdev, __func__); + if (ret) + goto out; + + if (!coresight_disable_source_sysfs(csdev, NULL)) + goto out; + + switch (csdev->subtype.source_subtype) { + case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: + cpu = source_ops(csdev)->cpu_id(csdev); + path = per_cpu(tracer_path, cpu); + per_cpu(tracer_path, cpu) = NULL; + break; + case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: + case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM: + case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS: + hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev))); + /* Find the path by the hash. */ + path = idr_find(&path_idr, hash); + if (path == NULL) { + pr_err("Path is not found for %s\n", dev_name(&csdev->dev)); + goto out; + } + idr_remove(&path_idr, hash); + break; + default: + /* We can't be here */ + break; + } + + coresight_disable_path(path); + coresight_release_path(path); + +out: + mutex_unlock(&coresight_mutex); +} +EXPORT_SYMBOL_GPL(coresight_disable_sysfs); + +static ssize_t enable_sink_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct coresight_device *csdev = to_coresight_device(dev); + + return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->sysfs_sink_activated); +} + +static ssize_t enable_sink_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + unsigned long val; + struct coresight_device *csdev = to_coresight_device(dev); + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + csdev->sysfs_sink_activated = !!val; + + return size; + +} +static DEVICE_ATTR_RW(enable_sink); + +static ssize_t enable_source_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct coresight_device *csdev = to_coresight_device(dev); + + guard(mutex)(&coresight_mutex); + return scnprintf(buf, PAGE_SIZE, "%u\n", + local_read(&csdev->mode) == CS_MODE_SYSFS); +} + +static ssize_t enable_source_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + unsigned long val; + struct coresight_device *csdev = to_coresight_device(dev); + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + if (val) { + ret = coresight_enable_sysfs(csdev); + if (ret) + return ret; + } else { + coresight_disable_sysfs(csdev); + } + + return size; +} +static DEVICE_ATTR_RW(enable_source); + +static struct attribute *coresight_sink_attrs[] = { + &dev_attr_enable_sink.attr, + NULL, +}; +ATTRIBUTE_GROUPS(coresight_sink); + +static struct attribute *coresight_source_attrs[] = { + &dev_attr_enable_source.attr, + NULL, +}; +ATTRIBUTE_GROUPS(coresight_source); + +struct device_type coresight_dev_type[] = { + { + .name = "sink", + .groups = coresight_sink_groups, + }, + { + .name = "link", + }, + { + .name = "linksink", + .groups = coresight_sink_groups, + }, + { + .name = "source", + .groups = coresight_source_groups, + }, + { + .name = "helper", + } +}; +/* Ensure the enum matches the names and groups */ +static_assert(ARRAY_SIZE(coresight_dev_type) == CORESIGHT_DEV_TYPE_MAX); + /* * Connections group - links attribute. * Count of created links between coresight components in the group. diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 46e6667f72ce..e8dd0df98881 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -578,8 +578,8 @@ static inline bool coresight_is_percpu_sink(struct coresight_device *csdev) extern struct coresight_device * coresight_register(struct coresight_desc *desc); extern void coresight_unregister(struct coresight_device *csdev); -extern int coresight_enable(struct coresight_device *csdev); -extern void coresight_disable(struct coresight_device *csdev); +extern int coresight_enable_sysfs(struct coresight_device *csdev); +extern void coresight_disable_sysfs(struct coresight_device *csdev); extern int coresight_timeout(struct csdev_access *csa, u32 offset, int position, int value); @@ -609,8 +609,8 @@ static inline struct coresight_device * coresight_register(struct coresight_desc *desc) { return NULL; } static inline void coresight_unregister(struct coresight_device *csdev) {} static inline int -coresight_enable(struct coresight_device *csdev) { return -ENOSYS; } -static inline void coresight_disable(struct coresight_device *csdev) {} +coresight_enable_sysfs(struct coresight_device *csdev) { return -ENOSYS; } +static inline void coresight_disable_sysfs(struct coresight_device *csdev) {} static inline int coresight_timeout(struct csdev_access *csa, u32 offset, int position, int value) From patchwork Tue Dec 12 15:54:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Clark X-Patchwork-Id: 13489565 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D4086C4167D for ; Tue, 12 Dec 2023 15:56:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=X1To+NXvUvqzkbrH6wo3U9dH2PHPb2kW/sYHdGrTCTU=; b=xV8fAZs3j930iG lnnVo5X8ui8G3Gn7RcYWeE6vq1uB2gHo8fp8jvf/lXWQnPDESjSqNyNUfdgIQwrEM8DbbceQZZO7W 6eETZXQoKL8QxEVBOkSiUKFRGCsuvvJRZLqahQDRDs15qOv85Kcea9XquyW8fce3Vdb4nKIowpP5J Y1CrPFG5yas3Ma4XvgHIKFF2g11LtUxQsiBbYzpbx+kfBp/BgeYdQVmKr/Mlfr9vZSpqXAFNVjZuZ s58o2mhdXQkEpBfSOTxHDGSpouI8CErllyCTAPxtH2GUoJ75WCAveTUsMK/tRZ597chl7aZceZRVu anBocrNBOnHmfmwTGVJg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56j-00C8L5-1i; Tue, 12 Dec 2023 15:55:41 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56b-00C8GS-23 for linux-arm-kernel@lists.infradead.org; Tue, 12 Dec 2023 15:55:35 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 5A2DC1474; Tue, 12 Dec 2023 07:56:19 -0800 (PST) Received: from e127643.broadband (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 862AC3F738; Tue, 12 Dec 2023 07:55:31 -0800 (PST) From: James Clark To: coresight@lists.linaro.org, suzuki.poulose@arm.com Cc: James Clark , Mike Leach , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com Subject: [PATCH 7/8] coresight: Remove atomic type from refcnt Date: Tue, 12 Dec 2023 15:54:04 +0000 Message-Id: <20231212155407.1429121-8-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231212155407.1429121-1-james.clark@arm.com> References: <20231212155407.1429121-1-james.clark@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231212_075533_826703_A751FDD4 X-CRM114-Status: GOOD ( 26.58 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Refcnt is only ever accessed from either inside the coresight_mutex, or the device's spinlock, making the atomic type and atomic_dec_return() calls confusing and unnecessary. The only point of synchronisation outside of these two types of locks is already done with a compare and swap on 'mode', which a comment has been added for. There was one instance of refcnt being used outside of a lock in TPIU, but that can easily be fixed by making it the same as all the other devices and adding a spinlock. Potentially in the future all the refcounting and locking can be moved up into the core code, and all the mostly duplicate code from the individual devices can be removed. Signed-off-by: James Clark --- drivers/hwtracing/coresight/coresight-etb10.c | 11 +++++----- drivers/hwtracing/coresight/coresight-sysfs.c | 7 ++++--- .../hwtracing/coresight/coresight-tmc-etf.c | 20 ++++++++++--------- .../hwtracing/coresight/coresight-tmc-etr.c | 13 ++++++------ drivers/hwtracing/coresight/coresight-tpda.c | 7 ++++--- drivers/hwtracing/coresight/coresight-tpiu.c | 14 +++++++++++-- drivers/hwtracing/coresight/ultrasoc-smb.c | 9 +++++---- include/linux/coresight.h | 13 +++++++++--- 8 files changed, 59 insertions(+), 35 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 08e5bba862db..5f2bb95955b7 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -161,7 +161,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev) local_set(&csdev->mode, CS_MODE_SYSFS); } - atomic_inc(&csdev->refcnt); + csdev->refcnt++; out: spin_unlock_irqrestore(&drvdata->spinlock, flags); return ret; @@ -197,7 +197,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) * use for this session. */ if (drvdata->pid == pid) { - atomic_inc(&csdev->refcnt); + csdev->refcnt++; goto out; } @@ -215,7 +215,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) /* Associate with monitored process. */ drvdata->pid = pid; local_set(&drvdata->csdev->mode, CS_MODE_PERF); - atomic_inc(&csdev->refcnt); + csdev->refcnt++; } out: @@ -354,7 +354,8 @@ static int etb_disable(struct coresight_device *csdev) spin_lock_irqsave(&drvdata->spinlock, flags); - if (atomic_dec_return(&csdev->refcnt)) { + csdev->refcnt--; + if (csdev->refcnt) { spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY; } @@ -445,7 +446,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, spin_lock_irqsave(&drvdata->spinlock, flags); /* Don't do anything if another tracer is using this sink */ - if (atomic_read(&csdev->refcnt) != 1) + if (csdev->refcnt != 1) goto out; __etb_disable_hw(drvdata); diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c index 92cdf8139f23..5992f2c2200a 100644 --- a/drivers/hwtracing/coresight/coresight-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-sysfs.c @@ -68,7 +68,7 @@ static int coresight_enable_source_sysfs(struct coresight_device *csdev, return ret; } - atomic_inc(&csdev->refcnt); + csdev->refcnt++; return 0; } @@ -90,7 +90,8 @@ static bool coresight_disable_source_sysfs(struct coresight_device *csdev, if (local_read(&csdev->mode) != CS_MODE_SYSFS) return false; - if (atomic_dec_return(&csdev->refcnt) == 0) { + csdev->refcnt--; + if (csdev->refcnt == 0) { coresight_disable_source(csdev, data); return true; } @@ -190,7 +191,7 @@ int coresight_enable_sysfs(struct coresight_device *csdev) * source is already enabled. */ if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE) - atomic_inc(&csdev->refcnt); + csdev->refcnt++; goto out; } diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 2a7e516052a2..f3281c958a57 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -206,7 +206,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) * touched. */ if (local_read(&csdev->mode) == CS_MODE_SYSFS) { - atomic_inc(&csdev->refcnt); + csdev->refcnt++; goto out; } @@ -229,7 +229,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) ret = tmc_etb_enable_hw(drvdata); if (!ret) { local_set(&csdev->mode, CS_MODE_SYSFS); - atomic_inc(&csdev->refcnt); + csdev->refcnt++; } else { /* Free up the buffer if we failed to enable */ used = false; @@ -284,7 +284,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) * use for this session. */ if (drvdata->pid == pid) { - atomic_inc(&csdev->refcnt); + csdev->refcnt++; break; } @@ -293,7 +293,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) /* Associate with monitored process. */ drvdata->pid = pid; local_set(&csdev->mode, CS_MODE_PERF); - atomic_inc(&csdev->refcnt); + csdev->refcnt++; } } while (0); spin_unlock_irqrestore(&drvdata->spinlock, flags); @@ -338,7 +338,8 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev) return -EBUSY; } - if (atomic_dec_return(&csdev->refcnt)) { + csdev->refcnt--; + if (csdev->refcnt) { spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY; } @@ -371,7 +372,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev, return -EBUSY; } - if (atomic_read(&csdev->refcnt) == 0) { + if (csdev->refcnt == 0) { ret = tmc_etf_enable_hw(drvdata); if (!ret) { local_set(&csdev->mode, CS_MODE_SYSFS); @@ -379,7 +380,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev, } } if (!ret) - atomic_inc(&csdev->refcnt); + csdev->refcnt++; spin_unlock_irqrestore(&drvdata->spinlock, flags); if (first_enable) @@ -401,7 +402,8 @@ static void tmc_disable_etf_link(struct coresight_device *csdev, return; } - if (atomic_dec_return(&csdev->refcnt) == 0) { + csdev->refcnt--; + if (csdev->refcnt == 0) { tmc_etf_disable_hw(drvdata); local_set(&csdev->mode, CS_MODE_DISABLED); last_disable = true; @@ -489,7 +491,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, spin_lock_irqsave(&drvdata->spinlock, flags); /* Don't do anything if another tracer is using this sink */ - if (atomic_read(&csdev->refcnt) != 1) + if (csdev->refcnt != 1) goto out; CS_UNLOCK(drvdata->base); diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 3dc989d4fcab..88a0fc375b4d 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1231,14 +1231,14 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) * touched, even if the buffer size has changed. */ if (local_read(&csdev->mode) == CS_MODE_SYSFS) { - atomic_inc(&csdev->refcnt); + csdev->refcnt++; goto out; } ret = tmc_etr_enable_hw(drvdata, sysfs_buf); if (!ret) { local_set(&csdev->mode, CS_MODE_SYSFS); - atomic_inc(&csdev->refcnt); + csdev->refcnt++; } out: @@ -1564,7 +1564,7 @@ tmc_update_etr_buffer(struct coresight_device *csdev, spin_lock_irqsave(&drvdata->spinlock, flags); /* Don't do anything if another tracer is using this sink */ - if (atomic_read(&csdev->refcnt) != 1) { + if (csdev->refcnt != 1) { spin_unlock_irqrestore(&drvdata->spinlock, flags); goto out; } @@ -1676,7 +1676,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) * use for this session. */ if (drvdata->pid == pid) { - atomic_inc(&csdev->refcnt); + csdev->refcnt++; goto unlock_out; } @@ -1686,7 +1686,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) drvdata->pid = pid; local_set(&csdev->mode, CS_MODE_PERF); drvdata->perf_buf = etr_perf->etr_buf; - atomic_inc(&csdev->refcnt); + csdev->refcnt++; } unlock_out: @@ -1719,7 +1719,8 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev) return -EBUSY; } - if (atomic_dec_return(&csdev->refcnt)) { + csdev->refcnt--; + if (csdev->refcnt) { spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY; } diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 65c70995ab00..135a89654c4c 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -152,7 +152,8 @@ static int __tpda_enable(struct tpda_drvdata *drvdata, int port) * Only do pre-port enable for first port that calls enable when the * device's main refcount is still 0 */ - if (!atomic_read(&drvdata->csdev->refcnt)) + lockdep_assert_held(&drvdata->spinlock); + if (!drvdata->csdev->refcnt) tpda_enable_pre_port(drvdata); ret = tpda_enable_port(drvdata, port); @@ -173,7 +174,7 @@ static int tpda_enable(struct coresight_device *csdev, ret = __tpda_enable(drvdata, in->dest_port); if (!ret) { atomic_inc(&in->dest_refcnt); - atomic_inc(&csdev->refcnt); + csdev->refcnt++; dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); } } @@ -204,7 +205,7 @@ static void tpda_disable(struct coresight_device *csdev, spin_lock(&drvdata->spinlock); if (atomic_dec_return(&in->dest_refcnt) == 0) { __tpda_disable(drvdata, in->dest_port); - atomic_dec(&csdev->refcnt); + csdev->refcnt--; } spin_unlock(&drvdata->spinlock); diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 59eac93fd6bb..c23a6b9b41fe 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -58,6 +58,7 @@ struct tpiu_drvdata { void __iomem *base; struct clk *atclk; struct coresight_device *csdev; + spinlock_t spinlock; }; static void tpiu_enable_hw(struct csdev_access *csa) @@ -72,8 +73,11 @@ static void tpiu_enable_hw(struct csdev_access *csa) static int tpiu_enable(struct coresight_device *csdev, enum cs_mode mode, void *__unused) { + struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + guard(spinlock)(&drvdata->spinlock); tpiu_enable_hw(&csdev->access); - atomic_inc(&csdev->refcnt); + csdev->refcnt++; dev_dbg(&csdev->dev, "TPIU enabled\n"); return 0; } @@ -96,7 +100,11 @@ static void tpiu_disable_hw(struct csdev_access *csa) static int tpiu_disable(struct coresight_device *csdev) { - if (atomic_dec_return(&csdev->refcnt)) + struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + + guard(spinlock)(&drvdata->spinlock); + csdev->refcnt--; + if (csdev->refcnt) return -EBUSY; tpiu_disable_hw(&csdev->access); @@ -132,6 +140,8 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id) if (!drvdata) return -ENOMEM; + spin_lock_init(&drvdata->spinlock); + drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */ if (!IS_ERR(drvdata->atclk)) { ret = clk_prepare_enable(drvdata->atclk); diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c index 1a8c64645b92..1146584a1745 100644 --- a/drivers/hwtracing/coresight/ultrasoc-smb.c +++ b/drivers/hwtracing/coresight/ultrasoc-smb.c @@ -103,7 +103,7 @@ static int smb_open(struct inode *inode, struct file *file) if (drvdata->reading) return -EBUSY; - if (atomic_read(&drvdata->csdev->refcnt)) + if (drvdata->csdev->refcnt) return -EBUSY; smb_update_data_size(drvdata); @@ -271,7 +271,7 @@ static int smb_enable(struct coresight_device *csdev, enum cs_mode mode, if (ret) return ret; - atomic_inc(&csdev->refcnt); + csdev->refcnt++; dev_dbg(&csdev->dev, "Ultrasoc SMB enabled\n"); return ret; @@ -286,7 +286,8 @@ static int smb_disable(struct coresight_device *csdev) if (drvdata->reading) return -EBUSY; - if (atomic_dec_return(&csdev->refcnt)) + csdev->refcnt--; + if (csdev->refcnt) return -EBUSY; /* Complain if we (somehow) got out of sync */ @@ -381,7 +382,7 @@ static unsigned long smb_update_buffer(struct coresight_device *csdev, guard(spinlock)(&drvdata->spinlock); /* Don't do anything if another tracer is using this sink. */ - if (atomic_read(&csdev->refcnt) != 1) + if (csdev->refcnt != 1) return 0; smb_disable_hw(drvdata); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index e8dd0df98881..4400d554a16b 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -230,8 +230,15 @@ struct coresight_sysfs_link { * actually an 'enum cs_mode', but is stored in an atomic type. * This is always accessed through local_read() and local_set(), * but wherever it's done from within the Coresight device's lock, - * a non-atomic read would also work. - * @refcnt: keep track of what is in use. + * a non-atomic read would also work. This is the main point of + * synchronisation between code happening inside the sysfs mode's + * coresight_mutex and outside when running in Perf mode. A compare + * and exchange swap is done to atomically claim one mode or the + * other. + * @refcnt: keep track of what is in use. Only access this outside of the + * device's spinlock when the coresight_mutex held and mode == + * CS_MODE_SYSFS. Otherwise it must be accessed from inside the + * spinlock. * @orphan: true if the component has connections that haven't been linked. * @sysfs_sink_activated: 'true' when a sink has been selected for use via sysfs * by writing a 1 to the 'enable_sink' file. A sink can be @@ -257,7 +264,7 @@ struct coresight_device { struct csdev_access access; struct device dev; local_t mode; - atomic_t refcnt; + int refcnt; bool orphan; /* sink specific fields */ bool sysfs_sink_activated; From patchwork Tue Dec 12 15:54:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Clark X-Patchwork-Id: 13489563 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9938BC4332F for ; Tue, 12 Dec 2023 15:56:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=28zbHMpY9VOE+429bFrJnxRiJpq3IIWuf8IzlhiRsYA=; b=az3veuhFUPBPdg 3Zss+0Ooedh/fhOXTlAPewou4is2tFRuwCcuttpVwGrWXOn6X7BU40Y02vKaPkebTNUjA7MDuIqs+ hN0az1/+6Xw5mCWvBzd06dC/BJ+BYb0ZDX+US6kmppDDnYG4Fm7G6WuSF3ZjHc5ig0HBXxGmrSCfD HB4z4xylsmbW/CDLGwQwUUm+hWq2OYmQlmx1Z2u8+iTJdejrKW0iXJuVortsh5M3t/HTv1skQICS/ E1mCTx1smuD6wTsXp+lF6EyOxQbH/EPdLlI1W1qqD8iSz2jczYOC5iXbFEAt/lupNwz7pKjNgy/wM rtkhTa9YrEtZGVxoRUBQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56l-00C8MW-02; Tue, 12 Dec 2023 15:55:43 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD56f-00C8IR-2D for linux-arm-kernel@lists.infradead.org; Tue, 12 Dec 2023 15:55:39 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 37A2B1516; Tue, 12 Dec 2023 07:56:23 -0800 (PST) Received: from e127643.broadband (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 62DE23F738; Tue, 12 Dec 2023 07:55:35 -0800 (PST) From: James Clark To: coresight@lists.linaro.org, suzuki.poulose@arm.com Cc: James Clark , Mike Leach , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com Subject: [PATCH 8/8] coresight: Remove unused stubs Date: Tue, 12 Dec 2023 15:54:05 +0000 Message-Id: <20231212155407.1429121-9-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231212155407.1429121-1-james.clark@arm.com> References: <20231212155407.1429121-1-james.clark@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231212_075537_866828_C459D0EB X-CRM114-Status: UNSURE ( 8.10 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org These are a bit annoying to keep up to date when the function signatures change. But if CONFIG_CORESIGHT isn't enabled, then they're not used anyway so just delete them. Signed-off-by: James Clark --- include/linux/coresight.h | 79 --------------------------------------- 1 file changed, 79 deletions(-) diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 4400d554a16b..c5be46d7f85c 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -391,8 +391,6 @@ struct coresight_ops { const struct coresight_ops_helper *helper_ops; }; -#if IS_ENABLED(CONFIG_CORESIGHT) - static inline u32 csdev_access_relaxed_read32(struct csdev_access *csa, u32 offset) { @@ -611,83 +609,6 @@ void coresight_relaxed_write64(struct coresight_device *csdev, u64 val, u32 offset); void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset); -#else -static inline struct coresight_device * -coresight_register(struct coresight_desc *desc) { return NULL; } -static inline void coresight_unregister(struct coresight_device *csdev) {} -static inline int -coresight_enable_sysfs(struct coresight_device *csdev) { return -ENOSYS; } -static inline void coresight_disable_sysfs(struct coresight_device *csdev) {} - -static inline int coresight_timeout(struct csdev_access *csa, u32 offset, - int position, int value) -{ - return 1; -} - -static inline int coresight_claim_device_unlocked(struct coresight_device *csdev) -{ - return -EINVAL; -} - -static inline int coresight_claim_device(struct coresight_device *csdev) -{ - return -EINVAL; -} - -static inline void coresight_disclaim_device(struct coresight_device *csdev) {} -static inline void coresight_disclaim_device_unlocked(struct coresight_device *csdev) {} - -static inline bool coresight_loses_context_with_cpu(struct device *dev) -{ - return false; -} - -static inline u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset) -{ - WARN_ON_ONCE(1); - return 0; -} - -static inline u32 coresight_read32(struct coresight_device *csdev, u32 offset) -{ - WARN_ON_ONCE(1); - return 0; -} - -static inline void coresight_write32(struct coresight_device *csdev, u32 val, u32 offset) -{ -} - -static inline void coresight_relaxed_write32(struct coresight_device *csdev, - u32 val, u32 offset) -{ -} - -static inline u64 coresight_relaxed_read64(struct coresight_device *csdev, - u32 offset) -{ - WARN_ON_ONCE(1); - return 0; -} - -static inline u64 coresight_read64(struct coresight_device *csdev, u32 offset) -{ - WARN_ON_ONCE(1); - return 0; -} - -static inline void coresight_relaxed_write64(struct coresight_device *csdev, - u64 val, u32 offset) -{ -} - -static inline void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset) -{ -} - -#endif /* IS_ENABLED(CONFIG_CORESIGHT) */ - extern int coresight_get_cpu(struct device *dev); struct coresight_platform_data *coresight_get_platform_data(struct device *dev);