mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] coresight: handle runtime PM resume failures
@ 2026-09-11 10:28 Yuanfang Zhang
  2026-09-11 13:11 ` Ulf Hansson
  2026-09-16 10:30 ` Leo Yan
  0 siblings, 2 replies; 3+ messages in thread
From: Yuanfang Zhang @ 2026-09-11 10:28 UTC (permalink / raw)
  To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
	Alexander Shishkin, Maxime Coquelin, Alexandre Torgue
  Cc: kernel, coresight, linux-arm-kernel, linux-kernel, linux-stm32,
	Yuanfang Zhang

When a CoreSight component's parent power domain, such as a CPU cluster
genpd, fails to power on, runtime resume returns a negative error. Several
call sites ignored that error and continued to access registers on an
unpowered device, risking an external abort.

Replace the remaining pm_runtime_get_sync() calls with
pm_runtime_resume_and_get(), which restores the runtime PM usage count
when resume fails. Abort before accessing hardware and propagate the
error to the caller.

In coresight_get_ref(), unwind the module and device references. In
debug_enable_func(), roll back the CPUs that resumed successfully before
the failure. Finally, release the mode acquired by stm_enable() if its
runtime resume fails.

Signed-off-by: Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>
---
This patch converts the remaining CoreSight pm_runtime_get_sync() users
to pm_runtime_resume_and_get(), propagates resume failures before
hardware access, and completes the related module, device, CPU and mode
unwind paths.
---
 drivers/hwtracing/coresight/coresight-core.c        | 13 ++++++++++---
 drivers/hwtracing/coresight/coresight-cpu-debug.c   | 10 +++++-----
 drivers/hwtracing/coresight/coresight-cti-sysfs.c   | 10 ++++++++--
 drivers/hwtracing/coresight/coresight-etm3x-sysfs.c | 10 ++++++++--
 drivers/hwtracing/coresight/coresight-etm4x-sysfs.c |  5 ++++-
 drivers/hwtracing/coresight/coresight-funnel.c      |  5 ++++-
 drivers/hwtracing/coresight/coresight-stm.c         |  7 ++++++-
 drivers/hwtracing/coresight/coresight-sysfs.c       | 11 +++++++++--
 8 files changed, 54 insertions(+), 17 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 928488a216d4eafa3cdb5f882ae5f44ddaff0448..ff93a017dbe22b01236ac2e5021da9b82890e72c 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -822,14 +822,16 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
  *
  * @csdev: The coresight device to get a reference on.
  *
- * Return true in successful case and power up the device.
- * Return false when failed to get reference of module.
+ * Return true on success and power up the device.
+ * Return false if a reference cannot be obtained or the device cannot be
+ * powered up.
  */
 static bool coresight_get_ref(struct coresight_device *csdev)
 {
 	struct device *dev = &csdev->dev;
 	struct device *parent = csdev->dev.parent;
 	struct device_driver *drv;
+	int ret;
 
 	/* Make sure csdev can't go away */
 	get_device(dev);
@@ -843,9 +845,14 @@ static bool coresight_get_ref(struct coresight_device *csdev)
 		goto err_module;
 
 	/* Make sure the device is powered on */
-	pm_runtime_get_sync(parent);
+	ret = pm_runtime_resume_and_get(parent);
+	if (ret < 0)
+		goto err_pm;
+
 	return true;
 
+err_pm:
+	module_put(drv->owner);
 err_module:
 	put_device(parent);
 	put_device(dev);
diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c
index 3a806c1d50eafb4249ab516ef846e437831b9681..39602d610e5b22ec4f165dbb126a7c06aea08eb0 100644
--- a/drivers/hwtracing/coresight/coresight-cpu-debug.c
+++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c
@@ -429,19 +429,19 @@ static int debug_enable_func(void)
 		if (!drvdata)
 			continue;
 
-		ret = pm_runtime_get_sync(drvdata->dev);
+		ret = pm_runtime_resume_and_get(drvdata->dev);
 		if (ret < 0)
 			goto err;
-		else
-			cpumask_set_cpu(cpu, &mask);
+
+		cpumask_set_cpu(cpu, &mask);
 	}
 
 	return 0;
 
 err:
 	/*
-	 * If pm_runtime_get_sync() has failed, need rollback on
-	 * all the other CPUs that have been enabled before that.
+	 * If runtime resume has failed, roll back all the other CPUs
+	 * that have been enabled before that.
 	 */
 	for_each_cpu(cpu, &mask) {
 		drvdata = per_cpu(debug_drvdata, cpu);
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index 3fe2c916d228808233ef19e9213a0cc0ce3cf297..6886b8713368058b9cf33ab7fafb5f87e23c1ec9 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -167,8 +167,11 @@ static ssize_t coresight_cti_reg_show(struct device *dev,
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct cs_off_attribute *cti_attr = container_of(attr, struct cs_off_attribute, attr);
 	u32 val = 0;
+	int ret;
 
-	pm_runtime_get_sync(dev->parent);
+	ret = pm_runtime_resume_and_get(dev->parent);
+	if (ret < 0)
+		return ret;
 
 	scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
 		val = cti_read_single_reg(drvdata, cti_attr->off);
@@ -185,11 +188,14 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
 	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct cs_off_attribute *cti_attr = container_of(attr, struct cs_off_attribute, attr);
 	unsigned long val = 0;
+	int ret;
 
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	pm_runtime_get_sync(dev->parent);
+	ret = pm_runtime_resume_and_get(dev->parent);
+	if (ret < 0)
+		return ret;
 
 	scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
 		cti_write_single_reg(drvdata, cti_attr->off, val);
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
index b3c67e96a82a4995515457d1ac0a5b183b162f0f..b34e282ec4a5f37f7de1d2ff118042b47368acd7 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
@@ -47,8 +47,11 @@ static ssize_t etmsr_show(struct device *dev,
 {
 	unsigned long flags, val;
 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	int ret;
 
-	pm_runtime_get_sync(dev->parent);
+	ret = pm_runtime_resume_and_get(dev->parent);
+	if (ret < 0)
+		return ret;
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 	CS_UNLOCK(drvdata->csa.base);
 
@@ -933,13 +936,16 @@ static ssize_t seq_curr_state_show(struct device *dev,
 	unsigned long val, flags;
 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	struct etm_config *config = &drvdata->config;
+	int ret;
 
 	if (!coresight_get_mode(drvdata->csdev)) {
 		val = config->seq_curr_state;
 		goto out;
 	}
 
-	pm_runtime_get_sync(dev->parent);
+	ret = pm_runtime_resume_and_get(dev->parent);
+	if (ret < 0)
+		return ret;
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	CS_UNLOCK(drvdata->csa.base);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index cc6cdd3ae29d502a2e67f07400de957b6dc71af6..55e05c20b302d4bf55c4df30c9ee6d6a1b5f1031 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -2457,10 +2457,13 @@ static ssize_t coresight_etm4x_reg_show(struct device *dev,
 {
 	u32 val, offset;
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	int ret;
 
 	offset = coresight_etm4x_attr_to_offset(d_attr);
 
-	pm_runtime_get_sync(dev->parent);
+	ret = pm_runtime_resume_and_get(dev->parent);
+	if (ret < 0)
+		return ret;
 	val = etmv4_cross_read(drvdata, offset);
 	pm_runtime_put_sync(dev->parent);
 
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 0abc11f0690c5272ebd55df9e98544e3b401cfe6..5824a1e4d046a3caf5b32ed1d8526b8bd7e9ca76 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -190,9 +190,12 @@ static ssize_t funnel_ctrl_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
 	u32 val;
+	int ret;
 	struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-	pm_runtime_get_sync(dev->parent);
+	ret = pm_runtime_resume_and_get(dev->parent);
+	if (ret < 0)
+		return ret;
 
 	val = get_funnel_ctrl_hw(drvdata);
 
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index 4e860519a73f6fff640090cf58298b89a31e6359..b9f15990ed994ea827c8e237d764e74d8d231ddd 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -196,6 +196,7 @@ static int stm_enable(struct coresight_device *csdev, struct perf_event *event,
 		      __maybe_unused struct coresight_path *path)
 {
 	struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	int ret;
 
 	if (mode != CS_MODE_SYSFS)
 		return -EINVAL;
@@ -205,7 +206,11 @@ static int stm_enable(struct coresight_device *csdev, struct perf_event *event,
 		return -EBUSY;
 	}
 
-	pm_runtime_get_sync(csdev->dev.parent);
+	ret = pm_runtime_resume_and_get(csdev->dev.parent);
+	if (ret < 0) {
+		coresight_set_mode(csdev, CS_MODE_DISABLED);
+		return ret;
+	}
 
 	spin_lock(&drvdata->spinlock);
 	stm_enable_hw(drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c
index 4b010f8bc4c08da31b3d295be6c37b6d941629d2..5849dfbd9d0bd3ad10734919f78bc39cc968539c 100644
--- a/drivers/hwtracing/coresight/coresight-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-sysfs.c
@@ -17,8 +17,12 @@ ssize_t coresight_simple_show_pair(struct device *_dev,
 	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;
+	int ret;
+
+	ret = pm_runtime_resume_and_get(_dev->parent);
+	if (ret < 0)
+		return ret;
 
-	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);
@@ -31,8 +35,11 @@ ssize_t coresight_simple_show32(struct device *_dev,
 	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;
+	int ret;
 
-	pm_runtime_get_sync(_dev->parent);
+	ret = pm_runtime_resume_and_get(_dev->parent);
+	if (ret < 0)
+		return ret;
 	val = csdev_access_relaxed_read32(&csdev->access, cs_attr->off);
 	pm_runtime_put_sync(_dev->parent);
 	return sysfs_emit(buf, "0x%llx\n", val);

---
base-commit: 08df884136f1c1197bab2a27814404fd329d9aac
change-id: 20260911-b4-coresight-runtime-pm-failures-70f250927aeb

Best regards,
-- 
Yuanfang Zhang <yuanfang@qti.qualcomm.com>


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] coresight: handle runtime PM resume failures
  2026-09-11 10:28 [PATCH] coresight: handle runtime PM resume failures Yuanfang Zhang
@ 2026-09-11 13:11 ` Ulf Hansson
  2026-09-16 10:30 ` Leo Yan
  1 sibling, 0 replies; 3+ messages in thread
From: Ulf Hansson @ 2026-09-11 13:11 UTC (permalink / raw)
  To: Yuanfang Zhang
  Cc: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
	Alexander Shishkin, Maxime Coquelin, Alexandre Torgue, kernel,
	coresight, linux-arm-kernel, linux-kernel, linux-stm32

On Fri, Sep 11, 2026 at 12:29 PM Yuanfang Zhang
<yuanfang.zhang@oss.qualcomm.com> wrote:
>
> When a CoreSight component's parent power domain, such as a CPU cluster
> genpd, fails to power on, runtime resume returns a negative error. Several
> call sites ignored that error and continued to access registers on an
> unpowered device, risking an external abort.
>
> Replace the remaining pm_runtime_get_sync() calls with
> pm_runtime_resume_and_get(), which restores the runtime PM usage count
> when resume fails. Abort before accessing hardware and propagate the
> error to the caller.
>
> In coresight_get_ref(), unwind the module and device references. In
> debug_enable_func(), roll back the CPUs that resumed successfully before
> the failure. Finally, release the mode acquired by stm_enable() if its
> runtime resume fails.
>
> Signed-off-by: Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>

Feel free to add:

Reviewed-by: Ulf Hansson <ulfh@kernel.org>

Kind regards
Uffe

> ---
> This patch converts the remaining CoreSight pm_runtime_get_sync() users
> to pm_runtime_resume_and_get(), propagates resume failures before
> hardware access, and completes the related module, device, CPU and mode
> unwind paths.
> ---
>  drivers/hwtracing/coresight/coresight-core.c        | 13 ++++++++++---
>  drivers/hwtracing/coresight/coresight-cpu-debug.c   | 10 +++++-----
>  drivers/hwtracing/coresight/coresight-cti-sysfs.c   | 10 ++++++++--
>  drivers/hwtracing/coresight/coresight-etm3x-sysfs.c | 10 ++++++++--
>  drivers/hwtracing/coresight/coresight-etm4x-sysfs.c |  5 ++++-
>  drivers/hwtracing/coresight/coresight-funnel.c      |  5 ++++-
>  drivers/hwtracing/coresight/coresight-stm.c         |  7 ++++++-
>  drivers/hwtracing/coresight/coresight-sysfs.c       | 11 +++++++++--
>  8 files changed, 54 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 928488a216d4eafa3cdb5f882ae5f44ddaff0448..ff93a017dbe22b01236ac2e5021da9b82890e72c 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -822,14 +822,16 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
>   *
>   * @csdev: The coresight device to get a reference on.
>   *
> - * Return true in successful case and power up the device.
> - * Return false when failed to get reference of module.
> + * Return true on success and power up the device.
> + * Return false if a reference cannot be obtained or the device cannot be
> + * powered up.
>   */
>  static bool coresight_get_ref(struct coresight_device *csdev)
>  {
>         struct device *dev = &csdev->dev;
>         struct device *parent = csdev->dev.parent;
>         struct device_driver *drv;
> +       int ret;
>
>         /* Make sure csdev can't go away */
>         get_device(dev);
> @@ -843,9 +845,14 @@ static bool coresight_get_ref(struct coresight_device *csdev)
>                 goto err_module;
>
>         /* Make sure the device is powered on */
> -       pm_runtime_get_sync(parent);
> +       ret = pm_runtime_resume_and_get(parent);
> +       if (ret < 0)
> +               goto err_pm;
> +
>         return true;
>
> +err_pm:
> +       module_put(drv->owner);
>  err_module:
>         put_device(parent);
>         put_device(dev);
> diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c
> index 3a806c1d50eafb4249ab516ef846e437831b9681..39602d610e5b22ec4f165dbb126a7c06aea08eb0 100644
> --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c
> +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c
> @@ -429,19 +429,19 @@ static int debug_enable_func(void)
>                 if (!drvdata)
>                         continue;
>
> -               ret = pm_runtime_get_sync(drvdata->dev);
> +               ret = pm_runtime_resume_and_get(drvdata->dev);
>                 if (ret < 0)
>                         goto err;
> -               else
> -                       cpumask_set_cpu(cpu, &mask);
> +
> +               cpumask_set_cpu(cpu, &mask);
>         }
>
>         return 0;
>
>  err:
>         /*
> -        * If pm_runtime_get_sync() has failed, need rollback on
> -        * all the other CPUs that have been enabled before that.
> +        * If runtime resume has failed, roll back all the other CPUs
> +        * that have been enabled before that.
>          */
>         for_each_cpu(cpu, &mask) {
>                 drvdata = per_cpu(debug_drvdata, cpu);
> diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> index 3fe2c916d228808233ef19e9213a0cc0ce3cf297..6886b8713368058b9cf33ab7fafb5f87e23c1ec9 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> @@ -167,8 +167,11 @@ static ssize_t coresight_cti_reg_show(struct device *dev,
>         struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
>         struct cs_off_attribute *cti_attr = container_of(attr, struct cs_off_attribute, attr);
>         u32 val = 0;
> +       int ret;
>
> -       pm_runtime_get_sync(dev->parent);
> +       ret = pm_runtime_resume_and_get(dev->parent);
> +       if (ret < 0)
> +               return ret;
>
>         scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
>                 val = cti_read_single_reg(drvdata, cti_attr->off);
> @@ -185,11 +188,14 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
>         struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
>         struct cs_off_attribute *cti_attr = container_of(attr, struct cs_off_attribute, attr);
>         unsigned long val = 0;
> +       int ret;
>
>         if (kstrtoul(buf, 0, &val))
>                 return -EINVAL;
>
> -       pm_runtime_get_sync(dev->parent);
> +       ret = pm_runtime_resume_and_get(dev->parent);
> +       if (ret < 0)
> +               return ret;
>
>         scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
>                 cti_write_single_reg(drvdata, cti_attr->off, val);
> diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
> index b3c67e96a82a4995515457d1ac0a5b183b162f0f..b34e282ec4a5f37f7de1d2ff118042b47368acd7 100644
> --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
> @@ -47,8 +47,11 @@ static ssize_t etmsr_show(struct device *dev,
>  {
>         unsigned long flags, val;
>         struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +       int ret;
>
> -       pm_runtime_get_sync(dev->parent);
> +       ret = pm_runtime_resume_and_get(dev->parent);
> +       if (ret < 0)
> +               return ret;
>         spin_lock_irqsave(&drvdata->spinlock, flags);
>         CS_UNLOCK(drvdata->csa.base);
>
> @@ -933,13 +936,16 @@ static ssize_t seq_curr_state_show(struct device *dev,
>         unsigned long val, flags;
>         struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
>         struct etm_config *config = &drvdata->config;
> +       int ret;
>
>         if (!coresight_get_mode(drvdata->csdev)) {
>                 val = config->seq_curr_state;
>                 goto out;
>         }
>
> -       pm_runtime_get_sync(dev->parent);
> +       ret = pm_runtime_resume_and_get(dev->parent);
> +       if (ret < 0)
> +               return ret;
>         spin_lock_irqsave(&drvdata->spinlock, flags);
>
>         CS_UNLOCK(drvdata->csa.base);
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> index cc6cdd3ae29d502a2e67f07400de957b6dc71af6..55e05c20b302d4bf55c4df30c9ee6d6a1b5f1031 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> @@ -2457,10 +2457,13 @@ static ssize_t coresight_etm4x_reg_show(struct device *dev,
>  {
>         u32 val, offset;
>         struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +       int ret;
>
>         offset = coresight_etm4x_attr_to_offset(d_attr);
>
> -       pm_runtime_get_sync(dev->parent);
> +       ret = pm_runtime_resume_and_get(dev->parent);
> +       if (ret < 0)
> +               return ret;
>         val = etmv4_cross_read(drvdata, offset);
>         pm_runtime_put_sync(dev->parent);
>
> diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
> index 0abc11f0690c5272ebd55df9e98544e3b401cfe6..5824a1e4d046a3caf5b32ed1d8526b8bd7e9ca76 100644
> --- a/drivers/hwtracing/coresight/coresight-funnel.c
> +++ b/drivers/hwtracing/coresight/coresight-funnel.c
> @@ -190,9 +190,12 @@ static ssize_t funnel_ctrl_show(struct device *dev,
>                              struct device_attribute *attr, char *buf)
>  {
>         u32 val;
> +       int ret;
>         struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
>
> -       pm_runtime_get_sync(dev->parent);
> +       ret = pm_runtime_resume_and_get(dev->parent);
> +       if (ret < 0)
> +               return ret;
>
>         val = get_funnel_ctrl_hw(drvdata);
>
> diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
> index 4e860519a73f6fff640090cf58298b89a31e6359..b9f15990ed994ea827c8e237d764e74d8d231ddd 100644
> --- a/drivers/hwtracing/coresight/coresight-stm.c
> +++ b/drivers/hwtracing/coresight/coresight-stm.c
> @@ -196,6 +196,7 @@ static int stm_enable(struct coresight_device *csdev, struct perf_event *event,
>                       __maybe_unused struct coresight_path *path)
>  {
>         struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +       int ret;
>
>         if (mode != CS_MODE_SYSFS)
>                 return -EINVAL;
> @@ -205,7 +206,11 @@ static int stm_enable(struct coresight_device *csdev, struct perf_event *event,
>                 return -EBUSY;
>         }
>
> -       pm_runtime_get_sync(csdev->dev.parent);
> +       ret = pm_runtime_resume_and_get(csdev->dev.parent);
> +       if (ret < 0) {
> +               coresight_set_mode(csdev, CS_MODE_DISABLED);
> +               return ret;
> +       }
>
>         spin_lock(&drvdata->spinlock);
>         stm_enable_hw(drvdata);
> diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c
> index 4b010f8bc4c08da31b3d295be6c37b6d941629d2..5849dfbd9d0bd3ad10734919f78bc39cc968539c 100644
> --- a/drivers/hwtracing/coresight/coresight-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-sysfs.c
> @@ -17,8 +17,12 @@ ssize_t coresight_simple_show_pair(struct device *_dev,
>         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;
> +       int ret;
> +
> +       ret = pm_runtime_resume_and_get(_dev->parent);
> +       if (ret < 0)
> +               return ret;
>
> -       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);
> @@ -31,8 +35,11 @@ ssize_t coresight_simple_show32(struct device *_dev,
>         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;
> +       int ret;
>
> -       pm_runtime_get_sync(_dev->parent);
> +       ret = pm_runtime_resume_and_get(_dev->parent);
> +       if (ret < 0)
> +               return ret;
>         val = csdev_access_relaxed_read32(&csdev->access, cs_attr->off);
>         pm_runtime_put_sync(_dev->parent);
>         return sysfs_emit(buf, "0x%llx\n", val);
>
> ---
> base-commit: 08df884136f1c1197bab2a27814404fd329d9aac
> change-id: 20260911-b4-coresight-runtime-pm-failures-70f250927aeb
>
> Best regards,
> --
> Yuanfang Zhang <yuanfang@qti.qualcomm.com>
>
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] coresight: handle runtime PM resume failures
  2026-09-11 10:28 [PATCH] coresight: handle runtime PM resume failures Yuanfang Zhang
  2026-09-11 13:11 ` Ulf Hansson
@ 2026-09-16 10:30 ` Leo Yan
  1 sibling, 0 replies; 3+ messages in thread
From: Leo Yan @ 2026-09-16 10:30 UTC (permalink / raw)
  To: Yuanfang Zhang
  Cc: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
	Maxime Coquelin, Alexandre Torgue, kernel, coresight,
	linux-arm-kernel, linux-kernel, linux-stm32

On Fri, Sep 11, 2026 at 03:28:52AM -0700, Yuanfang Zhang wrote:

[...]

> Replace the remaining pm_runtime_get_sync() calls with
> pm_runtime_resume_and_get(), which restores the runtime PM usage count
> when resume fails. Abort before accessing hardware and propagate the
> error to the caller.

The change makes sense to me.

> In coresight_get_ref(), unwind the module and device references.

Sashiko reported a pre-existing issue where the callers don't handle
errors returned by coresight_get_ref() [1]. In this case, we need to
remove nodes from path->path_list and release them. However, this
should be done in a separate patch.

[1] https://sashiko.dev/#/patchset/20260911-b4-coresight-runtime-pm-failures-v1-1-acdf49756e11%40qti.qualcomm.com

> Signed-off-by: Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>

Thanks for the fix! Feel free to add:

Reviewed-by: Leo Yan <leo.yan@arm.com>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-09-16 10:30 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-11 10:28 [PATCH] coresight: handle runtime PM resume failures Yuanfang Zhang
2026-09-11 13:11 ` Ulf Hansson
2026-09-16 10:30 ` Leo Yan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®