From nobody Mon Feb 9 16:00:59 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 910DA1991BA for ; Mon, 25 Nov 2024 09:48:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732528123; cv=none; b=dwAr6HHDmq8VzHwlTUhm+E1R1jndAKITLaIHgiooBnhPzBIigh7hHzqSQi/aAPBbkR7qiZp9QkobYxZ1Rbz0VBHCPDaLw5MqZiUyFOd7EhsCZLlpdRnFnBJiPOBnOb0/NqEnu8tchJ4JrePDzOEEeDi6NqJ3TIu6BbC4YLu8yuo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732528123; c=relaxed/simple; bh=TMiHiJsqIGh8+QjSe7HSOQhWXtSEkDHkX5bMzjevXEY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=oV7DfkZo9Y1IBofPHtpSr6t13J29GGFfqTvKWTBHGJqHpgFibpLyywUOSHnsklaFtcPYY2OTVAQW2+z3rzpzPq0ZzUpGL6IsOnodXrNvL+2y77+bn1DDMaGZ6ta52bhvN6BnJPHIQQG28Dkq2UNY+fiaqxyt4qKtwsBB4I4ZqlU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com 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 48BBD1692; Mon, 25 Nov 2024 01:49:11 -0800 (PST) Received: from e129823.cambridge.arm.com (e129823.arm.com [10.1.197.6]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 14E203F66E; Mon, 25 Nov 2024 01:48:38 -0800 (PST) From: Yeoreum Yun To: suzuki.poulose@arm.com, mike.leach@linaro.org, james.clark@linaro.org, alexander.shishkin@linux.intel.com, bigeasy@linutronix.de, clrkwllms@kernel.org, rostedt@goodmis.org Cc: coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, nd@arm.com, Levi Yun Subject: [PATCH 8/9] coresight-tmc: change tmc_drvdata spinlock's type to raw_spinlock_t Date: Mon, 25 Nov 2024 09:48:15 +0000 Message-Id: <20241125094816.365472-9-yeoreum.yun@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241125094816.365472-1-yeoreum.yun@arm.com> References: <20241125094816.365472-1-yeoreum.yun@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Levi Yun In coresight-tmc drivers, tmc_drvdata->spinlock can be held during __schedule() by perf_event_task_sched_out()/in(). Since tmc_drvdata->spinlock type is spinlock_t and perf_event_task_sched_out()/in() is called after acquiring rq_lock, which is raw_spinlock_t (an unsleepable lock), this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable. To address this, change type tmc_drvdata->spinlock in coresight-tmc drivers, which can be called by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t. Signed-off-by: Yeoreum Yun --- .../hwtracing/coresight/coresight-tmc-core.c | 9 +- .../hwtracing/coresight/coresight-tmc-etf.c | 195 +++++++---------- .../hwtracing/coresight/coresight-tmc-etr.c | 199 ++++++++---------- drivers/hwtracing/coresight/coresight-tmc.h | 2 +- 4 files changed, 169 insertions(+), 236 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwt= racing/coresight/coresight-tmc-core.c index 3a482fd2cb22..d6499eb14745 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -492,7 +492,7 @@ static int __tmc_probe(struct device *dev, struct resou= rce *res) drvdata->base =3D base; desc.access =3D CSDEV_ACCESS_IOMEM(base); =20 - spin_lock_init(&drvdata->spinlock); + raw_spin_lock_init(&drvdata->spinlock); =20 devid =3D readl_relaxed(drvdata->base + CORESIGHT_DEVID); drvdata->config_type =3D BMVAL(devid, 6, 7); @@ -593,13 +593,12 @@ static int tmc_probe(struct amba_device *adev, const = struct amba_id *id) =20 static void tmc_shutdown(struct amba_device *adev) { - unsigned long flags; struct tmc_drvdata *drvdata =3D amba_get_drvdata(adev); =20 - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); =20 if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_DISABLED) - goto out; + return; =20 if (drvdata->config_type =3D=3D TMC_CONFIG_TYPE_ETR) tmc_etr_disable_hw(drvdata); @@ -609,8 +608,6 @@ static void tmc_shutdown(struct amba_device *adev) * callback which is required for making coresight modular since * the system is going down after this. */ -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); } =20 static void __tmc_remove(struct device *dev) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtr= acing/coresight/coresight-tmc-etf.c index d4f641cd9de6..b2f97defbba2 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -182,9 +182,9 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_d= evice *csdev) * If we don't have a buffer release the lock and allocate memory. * Otherwise keep the lock and move along. */ - spin_lock_irqsave(&drvdata->spinlock, flags); + raw_spin_lock_irqsave(&drvdata->spinlock, flags); if (!drvdata->buf) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); =20 /* Allocating the memory here while outside of the spinlock */ buf =3D kzalloc(drvdata->size, GFP_KERNEL); @@ -192,7 +192,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_d= evice *csdev) return -ENOMEM; =20 /* Let's try again */ - spin_lock_irqsave(&drvdata->spinlock, flags); + raw_spin_lock_irqsave(&drvdata->spinlock, flags); } =20 if (drvdata->reading) { @@ -235,7 +235,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_d= evice *csdev) used =3D false; } out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); =20 /* Free memory outside the spinlock if need be */ if (!used) @@ -248,12 +248,12 @@ static int tmc_enable_etf_sink_perf(struct coresight_= device *csdev, void *data) { int ret =3D 0; pid_t pid; - unsigned long flags; struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); struct perf_output_handle *handle =3D data; struct cs_buffers *buf =3D etm_perf_sink_config(handle); =20 - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); + do { ret =3D -EINVAL; if (drvdata->reading) @@ -296,7 +296,6 @@ static int tmc_enable_etf_sink_perf(struct coresight_de= vice *csdev, void *data) csdev->refcnt++; } } while (0); - spin_unlock_irqrestore(&drvdata->spinlock, flags); =20 return ret; } @@ -328,31 +327,24 @@ static int tmc_enable_etf_sink(struct coresight_devic= e *csdev, =20 static int tmc_disable_etf_sink(struct coresight_device *csdev) { - unsigned long flags; struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); =20 - spin_lock_irqsave(&drvdata->spinlock, flags); + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + if (drvdata->reading) + return -EBUSY; =20 - if (drvdata->reading) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return -EBUSY; - } + csdev->refcnt--; + if (csdev->refcnt) + return -EBUSY; =20 - csdev->refcnt--; - if (csdev->refcnt) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return -EBUSY; + /* Complain if we (somehow) got out of sync */ + WARN_ON_ONCE(coresight_get_mode(csdev) =3D=3D CS_MODE_DISABLED); + tmc_etb_disable_hw(drvdata); + /* Dissociate from monitored process. */ + drvdata->pid =3D -1; + coresight_set_mode(csdev, CS_MODE_DISABLED); } =20 - /* Complain if we (somehow) got out of sync */ - WARN_ON_ONCE(coresight_get_mode(csdev) =3D=3D CS_MODE_DISABLED); - tmc_etb_disable_hw(drvdata); - /* Dissociate from monitored process. */ - drvdata->pid =3D -1; - coresight_set_mode(csdev, CS_MODE_DISABLED); - - spin_unlock_irqrestore(&drvdata->spinlock, flags); - dev_dbg(&csdev->dev, "TMC-ETB/ETF disabled\n"); return 0; } @@ -362,26 +354,23 @@ static int tmc_enable_etf_link(struct coresight_devic= e *csdev, struct coresight_connection *out) { int ret =3D 0; - unsigned long flags; struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); bool first_enable =3D false; =20 - spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return -EBUSY; - } - - if (csdev->refcnt =3D=3D 0) { - ret =3D tmc_etf_enable_hw(drvdata); - if (!ret) { - coresight_set_mode(csdev, CS_MODE_SYSFS); - first_enable =3D true; + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + if (drvdata->reading) + return -EBUSY; + + if (csdev->refcnt =3D=3D 0) { + ret =3D tmc_etf_enable_hw(drvdata); + if (!ret) { + coresight_set_mode(csdev, CS_MODE_SYSFS); + first_enable =3D true; + } } + if (!ret) + csdev->refcnt++; } - if (!ret) - csdev->refcnt++; - spin_unlock_irqrestore(&drvdata->spinlock, flags); =20 if (first_enable) dev_dbg(&csdev->dev, "TMC-ETF enabled\n"); @@ -392,23 +381,20 @@ static void tmc_disable_etf_link(struct coresight_dev= ice *csdev, struct coresight_connection *in, struct coresight_connection *out) { - unsigned long flags; struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); bool last_disable =3D false; =20 - spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return; - } + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + if (drvdata->reading) + return; =20 - csdev->refcnt--; - if (csdev->refcnt =3D=3D 0) { - tmc_etf_disable_hw(drvdata); - coresight_set_mode(csdev, CS_MODE_DISABLED); - last_disable =3D true; + csdev->refcnt--; + if (csdev->refcnt =3D=3D 0) { + tmc_etf_disable_hw(drvdata); + coresight_set_mode(csdev, CS_MODE_DISABLED); + last_disable =3D true; + } } - spin_unlock_irqrestore(&drvdata->spinlock, flags); =20 if (last_disable) dev_dbg(&csdev->dev, "TMC-ETF disabled\n"); @@ -477,7 +463,7 @@ static unsigned long tmc_update_etf_buffer(struct cores= ight_device *csdev, u32 *buf_ptr; u64 read_ptr, write_ptr; u32 status; - unsigned long offset, to_read =3D 0, flags; + unsigned long offset, to_read =3D 0; struct cs_buffers *buf =3D sink_config; struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); =20 @@ -488,11 +474,11 @@ static unsigned long tmc_update_etf_buffer(struct cor= esight_device *csdev, if (WARN_ON_ONCE(coresight_get_mode(csdev) !=3D CS_MODE_PERF)) return 0; =20 - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); =20 /* Don't do anything if another tracer is using this sink */ if (csdev->refcnt !=3D 1) - goto out; + return 0; =20 CS_UNLOCK(drvdata->base); =20 @@ -584,8 +570,6 @@ static unsigned long tmc_update_etf_buffer(struct cores= ight_device *csdev, * is expected by the perf ring buffer. */ CS_LOCK(drvdata->base); -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); =20 return to_read; } @@ -615,56 +599,43 @@ const struct coresight_ops tmc_etf_cs_ops =3D { int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) { enum tmc_mode mode; - int ret =3D 0; - unsigned long flags; =20 /* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type !=3D TMC_CONFIG_TYPE_ETB && drvdata->config_type !=3D TMC_CONFIG_TYPE_ETF)) return -EINVAL; =20 - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); =20 - if (drvdata->reading) { - ret =3D -EBUSY; - goto out; - } + if (drvdata->reading) + return -EBUSY; =20 /* Don't interfere if operated from Perf */ - if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_PERF) { - ret =3D -EINVAL; - goto out; - } + if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_PERF) + return -EINVAL; =20 /* If drvdata::buf is NULL the trace data has been read already */ - if (drvdata->buf =3D=3D NULL) { - ret =3D -EINVAL; - goto out; - } + if (drvdata->buf =3D=3D NULL) + return -EINVAL; =20 /* Disable the TMC if need be */ if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_SYSFS) { /* There is no point in reading a TMC in HW FIFO mode */ mode =3D readl_relaxed(drvdata->base + TMC_MODE); - if (mode !=3D TMC_MODE_CIRCULAR_BUFFER) { - ret =3D -EINVAL; - goto out; - } + if (mode !=3D TMC_MODE_CIRCULAR_BUFFER) + return -EINVAL; __tmc_etb_disable_hw(drvdata); } =20 drvdata->reading =3D true; -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); =20 - return ret; + return 0; } =20 int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) { char *buf =3D NULL; enum tmc_mode mode; - unsigned long flags; int rc =3D 0; =20 /* config types are set a boot time and never change */ @@ -672,41 +643,37 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdat= a) drvdata->config_type !=3D TMC_CONFIG_TYPE_ETF)) return -EINVAL; =20 - spin_lock_irqsave(&drvdata->spinlock, flags); - - /* Re-enable the TMC if need be */ - if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_SYSFS) { - /* There is no point in reading a TMC in HW FIFO mode */ - mode =3D readl_relaxed(drvdata->base + TMC_MODE); - if (mode !=3D TMC_MODE_CIRCULAR_BUFFER) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return -EINVAL; - } - /* - * The trace run will continue with the same allocated trace - * buffer. As such zero-out the buffer so that we don't end - * up with stale data. - * - * Since the tracer is still enabled drvdata::buf - * can't be NULL. - */ - memset(drvdata->buf, 0, drvdata->size); - rc =3D __tmc_etb_enable_hw(drvdata); - if (rc) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return rc; + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + /* Re-enable the TMC if need be */ + if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_SYSFS) { + /* There is no point in reading a TMC in HW FIFO mode */ + mode =3D readl_relaxed(drvdata->base + TMC_MODE); + if (mode !=3D TMC_MODE_CIRCULAR_BUFFER) + return -EINVAL; + + /* + * The trace run will continue with the same allocated trace + * buffer. As such zero-out the buffer so that we don't end + * up with stale data. + * + * Since the tracer is still enabled drvdata::buf + * can't be NULL. + */ + memset(drvdata->buf, 0, drvdata->size); + rc =3D __tmc_etb_enable_hw(drvdata); + if (rc) + return rc; + } else { + /* + * The ETB/ETF is not tracing and the buffer was just read. + * As such prepare to free the trace buffer. + */ + buf =3D drvdata->buf; + drvdata->buf =3D NULL; } - } else { - /* - * The ETB/ETF is not tracing and the buffer was just read. - * As such prepare to free the trace buffer. - */ - buf =3D drvdata->buf; - drvdata->buf =3D NULL; - } =20 - drvdata->reading =3D false; - spin_unlock_irqrestore(&drvdata->spinlock, flags); + drvdata->reading =3D false; + } =20 /* * Free allocated memory outside of the spinlock. There is no need diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtr= acing/coresight/coresight-tmc-etr.c index a48bb85d0e7f..6672bea4d2b9 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1176,10 +1176,10 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(str= uct coresight_device *csdev) * buffer, provided the size matches. Any allocation has to be done * with the lock released. */ - spin_lock_irqsave(&drvdata->spinlock, flags); + raw_spin_lock_irqsave(&drvdata->spinlock, flags); sysfs_buf =3D READ_ONCE(drvdata->sysfs_buf); if (!sysfs_buf || (sysfs_buf->size !=3D drvdata->size)) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); =20 /* Allocate memory with the locks released */ free_buf =3D new_buf =3D tmc_etr_setup_sysfs_buf(drvdata); @@ -1187,7 +1187,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struc= t coresight_device *csdev) return new_buf; =20 /* Let's try again */ - spin_lock_irqsave(&drvdata->spinlock, flags); + raw_spin_lock_irqsave(&drvdata->spinlock, flags); } =20 if (drvdata->reading || coresight_get_mode(csdev) =3D=3D CS_MODE_PERF) { @@ -1206,7 +1206,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struc= t coresight_device *csdev) } =20 out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); =20 /* Free memory outside the spinlock if need be */ if (free_buf) @@ -1216,35 +1216,31 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(str= uct coresight_device *csdev) =20 static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) { - int ret =3D 0; - unsigned long flags; + int ret; struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); struct etr_buf *sysfs_buf =3D tmc_etr_get_sysfs_buffer(csdev); =20 if (IS_ERR(sysfs_buf)) return PTR_ERR(sysfs_buf); =20 - spin_lock_irqsave(&drvdata->spinlock, flags); - - /* - * In sysFS mode we can have multiple writers per sink. Since this - * sink is already enabled no memory is needed and the HW need not be - * touched, even if the buffer size has changed. - */ - if (coresight_get_mode(csdev) =3D=3D CS_MODE_SYSFS) { - csdev->refcnt++; - goto out; - } + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + /* + * In sysFS mode we can have multiple writers per sink. Since this + * sink is already enabled no memory is needed and the HW need not be + * touched, even if the buffer size has changed. + */ + if (coresight_get_mode(csdev) =3D=3D CS_MODE_SYSFS) { + csdev->refcnt++; + return 0; + } =20 - ret =3D tmc_etr_enable_hw(drvdata, sysfs_buf); - if (!ret) { - coresight_set_mode(csdev, CS_MODE_SYSFS); - csdev->refcnt++; + ret =3D tmc_etr_enable_hw(drvdata, sysfs_buf); + if (!ret) { + coresight_set_mode(csdev, CS_MODE_SYSFS); + csdev->refcnt++; + } } =20 -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); - if (!ret) dev_dbg(&csdev->dev, "TMC-ETR enabled\n"); =20 @@ -1557,32 +1553,28 @@ tmc_update_etr_buffer(struct coresight_device *csde= v, void *config) { bool lost =3D false; - unsigned long flags, offset, size =3D 0; + unsigned long offset, size =3D 0; struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); struct etr_perf_buffer *etr_perf =3D config; struct etr_buf *etr_buf =3D etr_perf->etr_buf; =20 - spin_lock_irqsave(&drvdata->spinlock, flags); - - /* Don't do anything if another tracer is using this sink */ - if (csdev->refcnt !=3D 1) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - goto out; - } + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + /* Don't do anything if another tracer is using this sink */ + if (csdev->refcnt !=3D 1) + goto out; =20 - if (WARN_ON(drvdata->perf_buf !=3D etr_buf)) { - lost =3D true; - spin_unlock_irqrestore(&drvdata->spinlock, flags); - goto out; - } + if (WARN_ON(drvdata->perf_buf !=3D etr_buf)) { + lost =3D true; + goto out; + } =20 - CS_UNLOCK(drvdata->base); + CS_UNLOCK(drvdata->base); =20 - tmc_flush_and_stop(drvdata); - tmc_sync_etr_buf(drvdata); + tmc_flush_and_stop(drvdata); + tmc_sync_etr_buf(drvdata); =20 - CS_LOCK(drvdata->base); - spin_unlock_irqrestore(&drvdata->spinlock, flags); + CS_LOCK(drvdata->base); + } =20 lost =3D etr_buf->full; offset =3D etr_buf->offset; @@ -1644,33 +1636,27 @@ tmc_update_etr_buffer(struct coresight_device *csde= v, =20 static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *= data) { - int rc =3D 0; + int rc; pid_t pid; - unsigned long flags; struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); struct perf_output_handle *handle =3D data; struct etr_perf_buffer *etr_perf =3D etm_perf_sink_config(handle); =20 - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); + /* Don't use this sink if it is already claimed by sysFS */ - if (coresight_get_mode(csdev) =3D=3D CS_MODE_SYSFS) { - rc =3D -EBUSY; - goto unlock_out; - } + if (coresight_get_mode(csdev) =3D=3D CS_MODE_SYSFS) + return -EBUSY; =20 - if (WARN_ON(!etr_perf || !etr_perf->etr_buf)) { - rc =3D -EINVAL; - goto unlock_out; - } + if (WARN_ON(!etr_perf || !etr_perf->etr_buf)) + return -EINVAL; =20 /* Get a handle on the pid of the session owner */ pid =3D etr_perf->pid; =20 /* Do not proceed if this device is associated with another session */ - if (drvdata->pid !=3D -1 && drvdata->pid !=3D pid) { - rc =3D -EBUSY; - goto unlock_out; - } + if (drvdata->pid !=3D -1 && drvdata->pid !=3D pid) + return -EBUSY; =20 /* * No HW configuration is needed if the sink is already in @@ -1678,7 +1664,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_= device *csdev, void *data) */ if (drvdata->pid =3D=3D pid) { csdev->refcnt++; - goto unlock_out; + return 0; } =20 rc =3D tmc_etr_enable_hw(drvdata, etr_perf->etr_buf); @@ -1690,8 +1676,6 @@ static int tmc_enable_etr_sink_perf(struct coresight_= device *csdev, void *data) csdev->refcnt++; } =20 -unlock_out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); return rc; } =20 @@ -1710,33 +1694,26 @@ static int tmc_enable_etr_sink(struct coresight_dev= ice *csdev, =20 static int tmc_disable_etr_sink(struct coresight_device *csdev) { - unsigned long flags; struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); =20 - spin_lock_irqsave(&drvdata->spinlock, flags); - - if (drvdata->reading) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return -EBUSY; - } - - csdev->refcnt--; - if (csdev->refcnt) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return -EBUSY; + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + if (drvdata->reading) + return -EBUSY; + + csdev->refcnt--; + if (csdev->refcnt) + return -EBUSY; + + /* Complain if we (somehow) got out of sync */ + WARN_ON_ONCE(coresight_get_mode(csdev) =3D=3D CS_MODE_DISABLED); + tmc_etr_disable_hw(drvdata); + /* Dissociate from monitored process. */ + drvdata->pid =3D -1; + coresight_set_mode(csdev, CS_MODE_DISABLED); + /* Reset perf specific data */ + drvdata->perf_buf =3D NULL; } =20 - /* Complain if we (somehow) got out of sync */ - WARN_ON_ONCE(coresight_get_mode(csdev) =3D=3D CS_MODE_DISABLED); - tmc_etr_disable_hw(drvdata); - /* Dissociate from monitored process. */ - drvdata->pid =3D -1; - coresight_set_mode(csdev, CS_MODE_DISABLED); - /* Reset perf specific data */ - drvdata->perf_buf =3D NULL; - - spin_unlock_irqrestore(&drvdata->spinlock, flags); - dev_dbg(&csdev->dev, "TMC-ETR disabled\n"); return 0; } @@ -1756,70 +1733,62 @@ const struct coresight_ops tmc_etr_cs_ops =3D { int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) { int ret =3D 0; - unsigned long flags; =20 /* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type !=3D TMC_CONFIG_TYPE_ETR)) return -EINVAL; =20 - spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { - ret =3D -EBUSY; - goto out; - } + guard(raw_spinlock_irqsave)(&drvdata->spinlock); + + if (drvdata->reading) + return -EBUSY; =20 /* * We can safely allow reads even if the ETR is operating in PERF mode, * since the sysfs session is captured in mode specific data. * If drvdata::sysfs_data is NULL the trace data has been read already. */ - if (!drvdata->sysfs_buf) { - ret =3D -EINVAL; - goto out; - } + if (!drvdata->sysfs_buf) + return -EINVAL; =20 /* Disable the TMC if we are trying to read from a running session. */ if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_SYSFS) __tmc_etr_disable_hw(drvdata); =20 drvdata->reading =3D true; -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); =20 return ret; } =20 int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) { - unsigned long flags; struct etr_buf *sysfs_buf =3D NULL; =20 /* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type !=3D TMC_CONFIG_TYPE_ETR)) return -EINVAL; =20 - spin_lock_irqsave(&drvdata->spinlock, flags); + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + /* RE-enable the TMC if need be */ + if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_SYSFS) { + /* + * The trace run will continue with the same allocated trace + * buffer. Since the tracer is still enabled drvdata::buf can't + * be NULL. + */ + __tmc_etr_enable_hw(drvdata); + } else { + /* + * The ETR is not tracing and the buffer was just read. + * As such prepare to free the trace buffer. + */ + sysfs_buf =3D drvdata->sysfs_buf; + drvdata->sysfs_buf =3D NULL; + } =20 - /* RE-enable the TMC if need be */ - if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_SYSFS) { - /* - * The trace run will continue with the same allocated trace - * buffer. Since the tracer is still enabled drvdata::buf can't - * be NULL. - */ - __tmc_etr_enable_hw(drvdata); - } else { - /* - * The ETR is not tracing and the buffer was just read. - * As such prepare to free the trace buffer. - */ - sysfs_buf =3D drvdata->sysfs_buf; - drvdata->sysfs_buf =3D NULL; + drvdata->reading =3D false; } =20 - drvdata->reading =3D false; - spin_unlock_irqrestore(&drvdata->spinlock, flags); - /* Free allocated memory out side of the spinlock */ if (sysfs_buf) tmc_etr_free_sysfs_buf(sysfs_buf); diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracin= g/coresight/coresight-tmc.h index 2671926be62a..60b395025bc4 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -195,7 +195,7 @@ struct tmc_drvdata { void __iomem *base; struct coresight_device *csdev; struct miscdevice miscdev; - spinlock_t spinlock; + raw_spinlock_t spinlock; pid_t pid; bool reading; union { --=20 LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}