From patchwork Mon Nov 25 09:48:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yeoreum Yun X-Patchwork-Id: 13884758 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 563C7D3B7F8 for ; Mon, 25 Nov 2024 10:17:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Zo5mimbPUNYnoumTueh0t1mauAGjhvK+A4v7TYhBmH8=; b=HOWJki/NNg+gQIzz8tiZZnfzce BPt1w0AWgC5dIV6MVtf4ndUaaMch0ieL6/nGGqz59RCOHqLzlfiTdoQ6AtXv5ImffYaVkMFok2hTW XPc7Qy79skh5OSVTPPFPkD9AxdsI4bEzGhiYk6x/UBzV7F97nb0vZp7wCwWxutYOEdyFs0IeMi4ku p8IlgEQuKDDWctjMJqJrmL1Pj44KaYSyqZSkVtBK6VLznXjLZwEhBnxneHz4A/ZRFXMSdxfly6YwE rww39StYNyv6+KXrzAt1MTkdzTxgMcD6kcl48wSyxCJqDSoZRrFyMtK3/I4I8OsO9ifgMKqN3pHfQ 19uAcOIg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFW9s-00000007hkq-13IU; Mon, 25 Nov 2024 10:17:32 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFVhg-00000007div-166U for linux-arm-kernel@lists.infradead.org; Mon, 25 Nov 2024 09:48:25 +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 76EE21756; Mon, 25 Nov 2024 01:48:53 -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 407E23F66E; Mon, 25 Nov 2024 01:48:21 -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 1/9] coresight: change coresight_device lock type to raw_spinlock_t Date: Mon, 25 Nov 2024 09:48:08 +0000 Message-Id: <20241125094816.365472-2-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> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241125_014824_391871_978D5842 X-CRM114-Status: GOOD ( 19.18 ) 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 From: Levi Yun coresight_device->cscfg_csdev_lock can be held during __schedule() by perf_event_task_sched_out()/in(). Since coresight->cscfg_csdev_lock 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 of coresight_device->cscfg_csdev_lock from spinlock_t to raw_spinlock_t. Signed-off-by: Yeoreum Yun --- .../hwtracing/coresight/coresight-syscfg.c | 75 +++++++++---------- include/linux/coresight.h | 2 +- 2 files changed, 35 insertions(+), 42 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c index 11138a9762b0..b7e9fb822e8f 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -65,7 +65,6 @@ static int cscfg_add_csdev_cfg(struct coresight_device *csdev, { struct cscfg_config_csdev *config_csdev = NULL; struct cscfg_feature_csdev *feat_csdev; - unsigned long flags; int i; /* look at each required feature and see if it matches any feature on the device */ @@ -89,9 +88,9 @@ static int cscfg_add_csdev_cfg(struct coresight_device *csdev, } /* if matched features, add config to device.*/ if (config_csdev) { - spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); - list_add(&config_csdev->node, &csdev->config_csdev_list); - spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); + scoped_guard(raw_spinlock_irqsave, &csdev->cscfg_csdev_lock) { + list_add(&config_csdev->node, &csdev->config_csdev_list); + } } return 0; @@ -177,7 +176,6 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev, struct cscfg_csdev_feat_ops *ops) { struct cscfg_feature_csdev *feat_csdev; - unsigned long flags; int err; if (!ops->load_feat) @@ -194,9 +192,9 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev, /* add to internal csdev feature list & initialise using reset call */ cscfg_reset_feat(feat_csdev); - spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); - list_add(&feat_csdev->node, &csdev->feature_csdev_list); - spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); + scoped_guard(raw_spinlock_irqsave, &csdev->cscfg_csdev_lock) { + list_add(&feat_csdev->node, &csdev->feature_csdev_list); + } return 0; } @@ -765,7 +763,7 @@ static int cscfg_list_add_csdev(struct coresight_device *csdev, INIT_LIST_HEAD(&csdev->feature_csdev_list); INIT_LIST_HEAD(&csdev->config_csdev_list); - spin_lock_init(&csdev->cscfg_csdev_lock); + raw_spin_lock_init(&csdev->cscfg_csdev_lock); return 0; } @@ -853,17 +851,14 @@ EXPORT_SYMBOL_GPL(cscfg_unregister_csdev); void cscfg_csdev_reset_feats(struct coresight_device *csdev) { struct cscfg_feature_csdev *feat_csdev; - unsigned long flags; - spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); + guard(raw_spinlock_irqsave)(&csdev->cscfg_csdev_lock); + if (list_empty(&csdev->feature_csdev_list)) - goto unlock_exit; + return; list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) cscfg_reset_feat(feat_csdev); - -unlock_exit: - spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); } EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats); @@ -1048,7 +1043,6 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev, { struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item; const struct cscfg_config_desc *config_desc; - unsigned long flags; int err = 0; /* quickly check global count */ @@ -1059,17 +1053,17 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev, * Look for matching configuration - set the active configuration * context if found. */ - spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); - list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) { - config_desc = config_csdev_item->config_desc; - if ((atomic_read(&config_desc->active_cnt)) && - ((unsigned long)config_desc->event_ea->var == cfg_hash)) { - config_csdev_active = config_csdev_item; - csdev->active_cscfg_ctxt = (void *)config_csdev_active; - break; + scoped_guard(raw_spinlock_irqsave, &csdev->cscfg_csdev_lock) { + list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) { + config_desc = config_csdev_item->config_desc; + if ((atomic_read(&config_desc->active_cnt)) && + ((unsigned long)config_desc->event_ea->var == cfg_hash)) { + config_csdev_active = config_csdev_item; + csdev->active_cscfg_ctxt = (void *)config_csdev_active; + break; + } } } - spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); /* * If found, attempt to enable @@ -1090,12 +1084,12 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev, * * Set enabled if OK, err if not. */ - spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); - if (csdev->active_cscfg_ctxt) - config_csdev_active->enabled = true; - else - err = -EBUSY; - spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); + scoped_guard(raw_spinlock_irqsave, &csdev->cscfg_csdev_lock) { + if (csdev->active_cscfg_ctxt) + config_csdev_active->enabled = true; + else + err = -EBUSY; + } } } return err; @@ -1117,23 +1111,22 @@ EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config); void cscfg_csdev_disable_active_config(struct coresight_device *csdev) { struct cscfg_config_csdev *config_csdev; - unsigned long flags; /* * Check if we have an active config, and that it was successfully enabled. * If it was not enabled, we have no work to do, otherwise mark as disabled. * Clear the active config pointer. */ - spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); - config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt; - if (config_csdev) { - if (!config_csdev->enabled) - config_csdev = NULL; - else - config_csdev->enabled = false; + scoped_guard(raw_spinlock_irqsave, &csdev->cscfg_csdev_lock) { + config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt; + if (config_csdev) { + if (!config_csdev->enabled) + config_csdev = NULL; + else + config_csdev->enabled = false; + } + csdev->active_cscfg_ctxt = NULL; } - csdev->active_cscfg_ctxt = NULL; - spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); /* true if there was an enabled active config */ if (config_csdev) diff --git a/include/linux/coresight.h b/include/linux/coresight.h index c13342594278..924b58c343b3 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -296,7 +296,7 @@ struct coresight_device { /* system configuration and feature lists */ struct list_head feature_csdev_list; struct list_head config_csdev_list; - spinlock_t cscfg_csdev_lock; + raw_spinlock_t cscfg_csdev_lock; void *active_cscfg_ctxt; }; From patchwork Mon Nov 25 09:48:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yeoreum Yun X-Patchwork-Id: 13884757 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 D43B8D3B7F5 for ; Mon, 25 Nov 2024 10:17:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=i9BVqUbFA42tcEjK6AhbR0R4ugDgiIQ3vuF30ApQ1OM=; b=CvfjiZtjJJEKGUlrZIUF4mM9E+ ZCmQFcQsgF5rhJshP+o06ioZvFeuTor4ZQZIcce0MlypZjLJGROKGrqrHtUqFWQ+fYeBq+racqHi2 gPBft5hh/c0Phxd3/fYqaqR9VN4alFLvHim2dev6QBN1Nn42xVozwDD4J/k7/R4ABkWrMxKVaLqok WGZmKqz3rnUcmE51agtLaVyB62MXBkhreNe+05iUe+7iGWP5d9kC8JkIntHlnXc/hULBXK4ItnhRn D6LXVjWekIpqivQ2gT143unwF+0FK3FX/mPkoUvOacppuwMy8Ip9PnUQtEL/6lZ9YR7CcsoEk+0lW ZXwIBcrQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFW9t-00000007hm4-0gan; Mon, 25 Nov 2024 10:17:33 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFVhi-00000007dk2-2oEA for linux-arm-kernel@lists.infradead.org; Mon, 25 Nov 2024 09:48:28 +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 463E11FC7; Mon, 25 Nov 2024 01:48:56 -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 BF5873F66E; Mon, 25 Nov 2024 01:48:23 -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 2/9] coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t Date: Mon, 25 Nov 2024 09:48:09 +0000 Message-Id: <20241125094816.365472-3-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> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241125_014826_861576_DAFA080F X-CRM114-Status: GOOD ( 24.26 ) 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 From: Levi Yun In coresight-etm4x drivers, etmv4_drvdata->spinlock can be held during __schedule() by perf_event_task_sched_out()/in(). Since etmv4_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 etmv4_drvdata->spinlock in coresight-etm4x 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-config.c | 21 +- .../hwtracing/coresight/coresight-config.h | 2 +- .../coresight/coresight-etm4x-core.c | 71 ++- .../coresight/coresight-etm4x-sysfs.c | 566 +++++++++--------- drivers/hwtracing/coresight/coresight-etm4x.h | 2 +- 5 files changed, 345 insertions(+), 317 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtracing/coresight/coresight-config.c index 4723bf7402a2..e70579d4ce7f 100644 --- a/drivers/hwtracing/coresight/coresight-config.c +++ b/drivers/hwtracing/coresight/coresight-config.c @@ -73,28 +73,29 @@ static void cscfg_init_reg_param(struct cscfg_feature_csdev *feat_csdev, /* set values into the driver locations referenced in cscfg_reg_csdev */ static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev) { - unsigned long flags; int i; - spin_lock_irqsave(feat_csdev->drv_spinlock, flags); - for (i = 0; i < feat_csdev->nr_regs; i++) - cscfg_set_reg(&feat_csdev->regs_csdev[i]); - spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags); + scoped_guard(raw_spinlock_irqsave, feat_csdev->drv_spinlock) { + for (i = 0; i < feat_csdev->nr_regs; i++) + cscfg_set_reg(&feat_csdev->regs_csdev[i]); + } + dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s", feat_csdev->feat_desc->name, "set on enable"); + return 0; } /* copy back values from the driver locations referenced in cscfg_reg_csdev */ static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev) { - unsigned long flags; int i; - spin_lock_irqsave(feat_csdev->drv_spinlock, flags); - for (i = 0; i < feat_csdev->nr_regs; i++) - cscfg_save_reg(&feat_csdev->regs_csdev[i]); - spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags); + scoped_guard(raw_spinlock_irqsave, feat_csdev->drv_spinlock) { + for (i = 0; i < feat_csdev->nr_regs; i++) + cscfg_save_reg(&feat_csdev->regs_csdev[i]); + } + dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s", feat_csdev->feat_desc->name, "save on disable"); } diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h index 6ba013975741..b9ebc9fcfb7f 100644 --- a/drivers/hwtracing/coresight/coresight-config.h +++ b/drivers/hwtracing/coresight/coresight-config.h @@ -206,7 +206,7 @@ struct cscfg_feature_csdev { const struct cscfg_feature_desc *feat_desc; struct coresight_device *csdev; struct list_head node; - spinlock_t *drv_spinlock; + raw_spinlock_t *drv_spinlock; int nr_params; struct cscfg_parameter_csdev *params_csdev; int nr_regs; diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index 66d44a404ad0..1740cf6ab956 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -807,33 +807,30 @@ static int etm4_enable_sysfs(struct coresight_device *csdev) return ret; } - spin_lock(&drvdata->spinlock); - - /* sysfs needs to read and allocate a trace ID */ - ret = etm4_read_alloc_trace_id(drvdata); - if (ret < 0) - goto unlock_sysfs_enable; - - /* - * Executing etm4_enable_hw on the cpu whose ETM is being enabled - * ensures that register writes occur when cpu is powered. - */ - arg.drvdata = drvdata; - ret = smp_call_function_single(drvdata->cpu, - etm4_enable_hw_smp_call, &arg, 1); - if (!ret) - ret = arg.rc; - if (!ret) - drvdata->sticky_enable = true; - - if (ret) - etm4_release_trace_id(drvdata); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + /* sysfs needs to read and allocate a trace ID */ + ret = etm4_read_alloc_trace_id(drvdata); + if (ret < 0) + return ret; -unlock_sysfs_enable: - spin_unlock(&drvdata->spinlock); + /* + * Executing etm4_enable_hw on the cpu whose ETM is being enabled + * ensures that register writes occur when cpu is powered. + */ + arg.drvdata = drvdata; + ret = smp_call_function_single(drvdata->cpu, + etm4_enable_hw_smp_call, &arg, 1); + if (!ret) { + ret = arg.rc; + drvdata->sticky_enable = true; + } else { + etm4_release_trace_id(drvdata); + } + } if (!ret) dev_dbg(&csdev->dev, "ETM tracing enabled\n"); + return ret; } @@ -977,15 +974,13 @@ static void etm4_disable_sysfs(struct coresight_device *csdev) * DYING hotplug callback is serviced by the ETM driver. */ cpus_read_lock(); - spin_lock(&drvdata->spinlock); - - /* - * Executing etm4_disable_hw on the cpu whose ETM is being disabled - * ensures that register writes occur when cpu is powered. - */ - smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1); - - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + /* + * Executing etm4_disable_hw on the cpu whose ETM is being disabled + * ensures that register writes occur when cpu is powered. + */ + smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1); + } cpus_read_unlock(); /* @@ -1663,13 +1658,14 @@ static int etm4_starting_cpu(unsigned int cpu) if (!etmdrvdata[cpu]) return 0; - spin_lock(&etmdrvdata[cpu]->spinlock); + guard(raw_spinlock)(&etmdrvdata[cpu]->spinlock); + if (!etmdrvdata[cpu]->os_unlock) etm4_os_unlock(etmdrvdata[cpu]); if (coresight_get_mode(etmdrvdata[cpu]->csdev)) etm4_enable_hw(etmdrvdata[cpu]); - spin_unlock(&etmdrvdata[cpu]->spinlock); + return 0; } @@ -1678,10 +1674,11 @@ static int etm4_dying_cpu(unsigned int cpu) if (!etmdrvdata[cpu]) return 0; - spin_lock(&etmdrvdata[cpu]->spinlock); + guard(raw_spinlock)(&etmdrvdata[cpu]->spinlock); + if (coresight_get_mode(etmdrvdata[cpu]->csdev)) etm4_disable_hw(etmdrvdata[cpu]); - spin_unlock(&etmdrvdata[cpu]->spinlock); + return 0; } @@ -2125,7 +2122,7 @@ static int etm4_probe(struct device *dev) return -ENOMEM; } - spin_lock_init(&drvdata->spinlock); + raw_spin_lock_init(&drvdata->spinlock); drvdata->cpu = coresight_get_cpu(dev); if (drvdata->cpu < 0) diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index a9f19629f3f8..2e6b79c37f87 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -174,99 +174,99 @@ static ssize_t reset_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); - if (val) - config->mode = 0x0; + scoped_guard(raw_spinlock, &drvdata->spinlock) { + if (val) + config->mode = 0x0; - /* Disable data tracing: do not trace load and store data transfers */ - config->mode &= ~(ETM_MODE_LOAD | ETM_MODE_STORE); - config->cfg &= ~(TRCCONFIGR_INSTP0_LOAD | TRCCONFIGR_INSTP0_STORE); + /* Disable data tracing: do not trace load and store data transfers */ + config->mode &= ~(ETM_MODE_LOAD | ETM_MODE_STORE); + config->cfg &= ~(TRCCONFIGR_INSTP0_LOAD | TRCCONFIGR_INSTP0_STORE); - /* Disable data value and data address tracing */ - config->mode &= ~(ETM_MODE_DATA_TRACE_ADDR | - ETM_MODE_DATA_TRACE_VAL); - config->cfg &= ~(TRCCONFIGR_DA | TRCCONFIGR_DV); + /* Disable data value and data address tracing */ + config->mode &= ~(ETM_MODE_DATA_TRACE_ADDR | + ETM_MODE_DATA_TRACE_VAL); + config->cfg &= ~(TRCCONFIGR_DA | TRCCONFIGR_DV); - /* Disable all events tracing */ - config->eventctrl0 = 0x0; - config->eventctrl1 = 0x0; + /* Disable all events tracing */ + config->eventctrl0 = 0x0; + config->eventctrl1 = 0x0; - /* Disable timestamp event */ - config->ts_ctrl = 0x0; + /* Disable timestamp event */ + config->ts_ctrl = 0x0; - /* Disable stalling */ - config->stall_ctrl = 0x0; + /* Disable stalling */ + config->stall_ctrl = 0x0; - /* Reset trace synchronization period to 2^8 = 256 bytes*/ - if (drvdata->syncpr == false) - config->syncfreq = 0x8; + /* Reset trace synchronization period to 2^8 = 256 bytes*/ + if (drvdata->syncpr == false) + config->syncfreq = 0x8; - /* - * Enable ViewInst to trace everything with start-stop logic in - * started state. ARM recommends start-stop logic is set before - * each trace run. - */ - config->vinst_ctrl = FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01); - if (drvdata->nr_addr_cmp > 0) { - config->mode |= ETM_MODE_VIEWINST_STARTSTOP; - /* SSSTATUS, bit[9] */ - config->vinst_ctrl |= TRCVICTLR_SSSTATUS; - } + /* + * Enable ViewInst to trace everything with start-stop logic in + * started state. ARM recommends start-stop logic is set before + * each trace run. + */ + config->vinst_ctrl = FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01); + if (drvdata->nr_addr_cmp > 0) { + config->mode |= ETM_MODE_VIEWINST_STARTSTOP; + /* SSSTATUS, bit[9] */ + config->vinst_ctrl |= TRCVICTLR_SSSTATUS; + } - /* No address range filtering for ViewInst */ - config->viiectlr = 0x0; + /* No address range filtering for ViewInst */ + config->viiectlr = 0x0; - /* No start-stop filtering for ViewInst */ - config->vissctlr = 0x0; - config->vipcssctlr = 0x0; + /* No start-stop filtering for ViewInst */ + config->vissctlr = 0x0; + config->vipcssctlr = 0x0; - /* Disable seq events */ - for (i = 0; i < drvdata->nrseqstate-1; i++) - config->seq_ctrl[i] = 0x0; - config->seq_rst = 0x0; - config->seq_state = 0x0; + /* Disable seq events */ + for (i = 0; i < drvdata->nrseqstate-1; i++) + config->seq_ctrl[i] = 0x0; + config->seq_rst = 0x0; + config->seq_state = 0x0; - /* Disable external input events */ - config->ext_inp = 0x0; + /* Disable external input events */ + config->ext_inp = 0x0; - config->cntr_idx = 0x0; - for (i = 0; i < drvdata->nr_cntr; i++) { - config->cntrldvr[i] = 0x0; - config->cntr_ctrl[i] = 0x0; - config->cntr_val[i] = 0x0; - } + config->cntr_idx = 0x0; + for (i = 0; i < drvdata->nr_cntr; i++) { + config->cntrldvr[i] = 0x0; + config->cntr_ctrl[i] = 0x0; + config->cntr_val[i] = 0x0; + } - config->res_idx = 0x0; - for (i = 2; i < 2 * drvdata->nr_resource; i++) - config->res_ctrl[i] = 0x0; + config->res_idx = 0x0; + for (i = 2; i < 2 * drvdata->nr_resource; i++) + config->res_ctrl[i] = 0x0; - config->ss_idx = 0x0; - for (i = 0; i < drvdata->nr_ss_cmp; i++) { - config->ss_ctrl[i] = 0x0; - config->ss_pe_cmp[i] = 0x0; - } + config->ss_idx = 0x0; + for (i = 0; i < drvdata->nr_ss_cmp; i++) { + config->ss_ctrl[i] = 0x0; + config->ss_pe_cmp[i] = 0x0; + } - config->addr_idx = 0x0; - for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) { - config->addr_val[i] = 0x0; - config->addr_acc[i] = 0x0; - config->addr_type[i] = ETM_ADDR_TYPE_NONE; - } + config->addr_idx = 0x0; + for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) { + config->addr_val[i] = 0x0; + config->addr_acc[i] = 0x0; + config->addr_type[i] = ETM_ADDR_TYPE_NONE; + } - config->ctxid_idx = 0x0; - for (i = 0; i < drvdata->numcidc; i++) - config->ctxid_pid[i] = 0x0; + config->ctxid_idx = 0x0; + for (i = 0; i < drvdata->numcidc; i++) + config->ctxid_pid[i] = 0x0; - config->ctxid_mask0 = 0x0; - config->ctxid_mask1 = 0x0; + config->ctxid_mask0 = 0x0; + config->ctxid_mask1 = 0x0; - config->vmid_idx = 0x0; - for (i = 0; i < drvdata->numvmidc; i++) - config->vmid_val[i] = 0x0; - config->vmid_mask0 = 0x0; - config->vmid_mask1 = 0x0; + config->vmid_idx = 0x0; + for (i = 0; i < drvdata->numvmidc; i++) + config->vmid_val[i] = 0x0; - spin_unlock(&drvdata->spinlock); + config->vmid_mask0 = 0x0; + config->vmid_mask1 = 0x0; + } /* for sysfs - only release trace id when resetting */ etm4_release_trace_id(drvdata); @@ -300,7 +300,8 @@ static ssize_t mode_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + config->mode = val & ETMv4_MODE_ALL; if (drvdata->instrp0 == true) { @@ -437,8 +438,6 @@ static ssize_t mode_store(struct device *dev, if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER)) etm4_config_trace_mode(config); - spin_unlock(&drvdata->spinlock); - return size; } static DEVICE_ATTR_RW(mode); @@ -466,14 +465,14 @@ static ssize_t pe_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + if (val > drvdata->nr_pe) { - spin_unlock(&drvdata->spinlock); return -EINVAL; } config->pe_sel = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(pe); @@ -501,7 +500,8 @@ static ssize_t event_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + switch (drvdata->nr_event) { case 0x0: /* EVENT0, bits[7:0] */ @@ -522,7 +522,7 @@ static ssize_t event_store(struct device *dev, default: break; } - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(event); @@ -550,7 +550,8 @@ static ssize_t event_instren_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + /* start by clearing all instruction event enable bits */ config->eventctrl1 &= ~TRCEVENTCTL1R_INSTEN_MASK; switch (drvdata->nr_event) { @@ -578,7 +579,7 @@ static ssize_t event_instren_store(struct device *dev, default: break; } - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(event_instren); @@ -739,11 +740,12 @@ static ssize_t event_vinst_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + val &= TRCVICTLR_EVENT_MASK >> __bf_shf(TRCVICTLR_EVENT_MASK); config->vinst_ctrl &= ~TRCVICTLR_EVENT_MASK; config->vinst_ctrl |= FIELD_PREP(TRCVICTLR_EVENT_MASK, val); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(event_vinst); @@ -771,13 +773,14 @@ static ssize_t s_exlevel_vinst_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + /* clear all EXLEVEL_S bits */ config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_S_MASK; /* enable instruction tracing for corresponding exception level */ val &= drvdata->s_ex_level; config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_S_MASK); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(s_exlevel_vinst); @@ -806,13 +809,14 @@ static ssize_t ns_exlevel_vinst_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + /* clear EXLEVEL_NS bits */ config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_NS_MASK; /* enable instruction tracing for corresponding exception level */ val &= drvdata->ns_ex_level; config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_NS_MASK); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(ns_exlevel_vinst); @@ -846,9 +850,10 @@ static ssize_t addr_idx_store(struct device *dev, * Use spinlock to ensure index doesn't change while it gets * dereferenced multiple times within a spinlock block elsewhere. */ - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + config->addr_idx = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(addr_idx); @@ -862,7 +867,8 @@ static ssize_t addr_instdatatype_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->addr_idx; val = FIELD_GET(TRCACATRn_TYPE_MASK, config->addr_acc[idx]); len = scnprintf(buf, PAGE_SIZE, "%s\n", @@ -870,7 +876,7 @@ static ssize_t addr_instdatatype_show(struct device *dev, (val == TRCACATRn_TYPE_DATA_LOAD_ADDR ? "data_load" : (val == TRCACATRn_TYPE_DATA_STORE_ADDR ? "data_store" : "data_load_store"))); - spin_unlock(&drvdata->spinlock); + return len; } @@ -888,13 +894,13 @@ static ssize_t addr_instdatatype_store(struct device *dev, if (sscanf(buf, "%s", str) != 1) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->addr_idx; if (!strcmp(str, "instr")) /* TYPE, bits[1:0] */ config->addr_acc[idx] &= ~TRCACATRn_TYPE_MASK; - spin_unlock(&drvdata->spinlock); return size; } static DEVICE_ATTR_RW(addr_instdatatype); @@ -908,15 +914,15 @@ static ssize_t addr_single_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - idx = config->addr_idx; - spin_lock(&drvdata->spinlock); - if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE || - config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) { - spin_unlock(&drvdata->spinlock); - return -EPERM; + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->addr_idx; + if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE || + config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) + return -EPERM; + + val = (unsigned long)config->addr_val[idx]; } - val = (unsigned long)config->addr_val[idx]; - spin_unlock(&drvdata->spinlock); + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -932,17 +938,16 @@ static ssize_t addr_single_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->addr_idx; if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE || - config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) { - spin_unlock(&drvdata->spinlock); + config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) return -EPERM; - } config->addr_val[idx] = (u64)val; config->addr_type[idx] = ETM_ADDR_TYPE_SINGLE; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(addr_single); @@ -956,23 +961,21 @@ static ssize_t addr_range_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - idx = config->addr_idx; - if (idx % 2 != 0) { - spin_unlock(&drvdata->spinlock); - return -EPERM; - } - if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE && - config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) || - (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE && - config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) { - spin_unlock(&drvdata->spinlock); - return -EPERM; + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->addr_idx; + if (idx % 2 != 0) + return -EPERM; + + if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE && + config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) || + (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE && + config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) + return -EPERM; + + val1 = (unsigned long)config->addr_val[idx]; + val2 = (unsigned long)config->addr_val[idx + 1]; } - val1 = (unsigned long)config->addr_val[idx]; - val2 = (unsigned long)config->addr_val[idx + 1]; - spin_unlock(&drvdata->spinlock); return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2); } @@ -995,20 +998,17 @@ static ssize_t addr_range_store(struct device *dev, if (val1 > val2) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->addr_idx; - if (idx % 2 != 0) { - spin_unlock(&drvdata->spinlock); + if (idx % 2 != 0) return -EPERM; - } if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE && config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) || (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE && - config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) { - spin_unlock(&drvdata->spinlock); + config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) return -EPERM; - } config->addr_val[idx] = (u64)val1; config->addr_type[idx] = ETM_ADDR_TYPE_RANGE; @@ -1023,7 +1023,6 @@ static ssize_t addr_range_store(struct device *dev, exclude = config->mode & ETM_MODE_EXCLUDE; etm4_set_mode_exclude(drvdata, exclude ? true : false); - spin_unlock(&drvdata->spinlock); return size; } static DEVICE_ATTR_RW(addr_range); @@ -1037,17 +1036,17 @@ static ssize_t addr_start_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - idx = config->addr_idx; + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->addr_idx; - if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE || - config->addr_type[idx] == ETM_ADDR_TYPE_START)) { - spin_unlock(&drvdata->spinlock); - return -EPERM; + if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE || + config->addr_type[idx] == ETM_ADDR_TYPE_START)) { + return -EPERM; + } + + val = (unsigned long)config->addr_val[idx]; } - val = (unsigned long)config->addr_val[idx]; - spin_unlock(&drvdata->spinlock); return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1063,22 +1062,21 @@ static ssize_t addr_start_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->addr_idx; if (!drvdata->nr_addr_cmp) { - spin_unlock(&drvdata->spinlock); return -EINVAL; } if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE || config->addr_type[idx] == ETM_ADDR_TYPE_START)) { - spin_unlock(&drvdata->spinlock); return -EPERM; } config->addr_val[idx] = (u64)val; config->addr_type[idx] = ETM_ADDR_TYPE_START; config->vissctlr |= BIT(idx); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(addr_start); @@ -1092,17 +1090,16 @@ static ssize_t addr_stop_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - idx = config->addr_idx; + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->addr_idx; - if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE || - config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) { - spin_unlock(&drvdata->spinlock); - return -EPERM; - } + if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE || + config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) { + return -EPERM; + } - val = (unsigned long)config->addr_val[idx]; - spin_unlock(&drvdata->spinlock); + val = (unsigned long)config->addr_val[idx]; + } return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1118,22 +1115,21 @@ static ssize_t addr_stop_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->addr_idx; if (!drvdata->nr_addr_cmp) { - spin_unlock(&drvdata->spinlock); return -EINVAL; } if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE || config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) { - spin_unlock(&drvdata->spinlock); return -EPERM; } config->addr_val[idx] = (u64)val; config->addr_type[idx] = ETM_ADDR_TYPE_STOP; config->vissctlr |= BIT(idx + 16); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(addr_stop); @@ -1147,14 +1143,15 @@ static ssize_t addr_ctxtype_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->addr_idx; /* CONTEXTTYPE, bits[3:2] */ val = FIELD_GET(TRCACATRn_CONTEXTTYPE_MASK, config->addr_acc[idx]); len = scnprintf(buf, PAGE_SIZE, "%s\n", val == ETM_CTX_NONE ? "none" : (val == ETM_CTX_CTXID ? "ctxid" : (val == ETM_CTX_VMID ? "vmid" : "all"))); - spin_unlock(&drvdata->spinlock); + return len; } @@ -1172,7 +1169,8 @@ static ssize_t addr_ctxtype_store(struct device *dev, if (sscanf(buf, "%s", str) != 1) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->addr_idx; if (!strcmp(str, "none")) /* start by clearing context type bits */ @@ -1199,7 +1197,7 @@ static ssize_t addr_ctxtype_store(struct device *dev, if (drvdata->numvmidc) config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_VMID; } - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(addr_ctxtype); @@ -1213,11 +1211,12 @@ static ssize_t addr_context_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - idx = config->addr_idx; - /* context ID comparator bits[6:4] */ - val = FIELD_GET(TRCACATRn_CONTEXT_MASK, config->addr_acc[idx]); - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->addr_idx; + /* context ID comparator bits[6:4] */ + val = FIELD_GET(TRCACATRn_CONTEXT_MASK, config->addr_acc[idx]); + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1238,12 +1237,12 @@ static ssize_t addr_context_store(struct device *dev, drvdata->numcidc : drvdata->numvmidc)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); idx = config->addr_idx; /* clear context ID comparator bits[6:4] */ config->addr_acc[idx] &= ~TRCACATRn_CONTEXT_MASK; config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_CONTEXT_MASK); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(addr_context); @@ -1257,10 +1256,11 @@ static ssize_t addr_exlevel_s_ns_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - idx = config->addr_idx; - val = FIELD_GET(TRCACATRn_EXLEVEL_MASK, config->addr_acc[idx]); - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->addr_idx; + val = FIELD_GET(TRCACATRn_EXLEVEL_MASK, config->addr_acc[idx]); + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1279,12 +1279,13 @@ static ssize_t addr_exlevel_s_ns_store(struct device *dev, if (val & ~(TRCACATRn_EXLEVEL_MASK >> __bf_shf(TRCACATRn_EXLEVEL_MASK))) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->addr_idx; /* clear Exlevel_ns & Exlevel_s bits[14:12, 11:8], bit[15] is res0 */ config->addr_acc[idx] &= ~TRCACATRn_EXLEVEL_MASK; config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_EXLEVEL_MASK); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(addr_exlevel_s_ns); @@ -1307,22 +1308,23 @@ static ssize_t addr_cmp_view_show(struct device *dev, int size = 0; bool exclude = false; - spin_lock(&drvdata->spinlock); - idx = config->addr_idx; - addr_v = config->addr_val[idx]; - addr_ctrl = config->addr_acc[idx]; - addr_type = config->addr_type[idx]; - if (addr_type == ETM_ADDR_TYPE_RANGE) { - if (idx & 0x1) { - idx -= 1; - addr_v2 = addr_v; - addr_v = config->addr_val[idx]; - } else { - addr_v2 = config->addr_val[idx + 1]; + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->addr_idx; + addr_v = config->addr_val[idx]; + addr_ctrl = config->addr_acc[idx]; + addr_type = config->addr_type[idx]; + if (addr_type == ETM_ADDR_TYPE_RANGE) { + if (idx & 0x1) { + idx -= 1; + addr_v2 = addr_v; + addr_v = config->addr_val[idx]; + } else { + addr_v2 = config->addr_val[idx + 1]; + } + exclude = config->viiectlr & BIT(idx / 2 + 16); } - exclude = config->viiectlr & BIT(idx / 2 + 16); } - spin_unlock(&drvdata->spinlock); + if (addr_type) { size = scnprintf(buf, PAGE_SIZE, "addr_cmp[%i] %s %#lx", idx, addr_type_names[addr_type], addr_v); @@ -1366,9 +1368,10 @@ static ssize_t vinst_pe_cmp_start_stop_store(struct device *dev, if (!drvdata->nr_pe_cmp) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + config->vipcssctlr = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(vinst_pe_cmp_start_stop); @@ -1402,9 +1405,10 @@ static ssize_t seq_idx_store(struct device *dev, * Use spinlock to ensure index doesn't change while it gets * dereferenced multiple times within a spinlock block elsewhere. */ - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + config->seq_idx = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(seq_idx); @@ -1448,10 +1452,11 @@ static ssize_t seq_event_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - idx = config->seq_idx; - val = config->seq_ctrl[idx]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->seq_idx; + val = config->seq_ctrl[idx]; + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1467,11 +1472,12 @@ static ssize_t seq_event_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->seq_idx; /* Seq control has two masks B[15:8] F[7:0] */ config->seq_ctrl[idx] = val & 0xFFFF; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(seq_event); @@ -1535,9 +1541,10 @@ static ssize_t cntr_idx_store(struct device *dev, * Use spinlock to ensure index doesn't change while it gets * dereferenced multiple times within a spinlock block elsewhere. */ - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + config->cntr_idx = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(cntr_idx); @@ -1551,10 +1558,11 @@ static ssize_t cntrldvr_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - idx = config->cntr_idx; - val = config->cntrldvr[idx]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->cntr_idx; + val = config->cntrldvr[idx]; + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1572,10 +1580,11 @@ static ssize_t cntrldvr_store(struct device *dev, if (val > ETM_CNTR_MAX_VAL) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->cntr_idx; config->cntrldvr[idx] = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(cntrldvr); @@ -1589,10 +1598,11 @@ static ssize_t cntr_val_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - idx = config->cntr_idx; - val = config->cntr_val[idx]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->cntr_idx; + val = config->cntr_val[idx]; + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1610,10 +1620,11 @@ static ssize_t cntr_val_store(struct device *dev, if (val > ETM_CNTR_MAX_VAL) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->cntr_idx; config->cntr_val[idx] = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(cntr_val); @@ -1627,10 +1638,11 @@ static ssize_t cntr_ctrl_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - idx = config->cntr_idx; - val = config->cntr_ctrl[idx]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->cntr_idx; + val = config->cntr_ctrl[idx]; + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1646,10 +1658,11 @@ static ssize_t cntr_ctrl_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->cntr_idx; config->cntr_ctrl[idx] = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(cntr_ctrl); @@ -1687,9 +1700,10 @@ static ssize_t res_idx_store(struct device *dev, * Use spinlock to ensure index doesn't change while it gets * dereferenced multiple times within a spinlock block elsewhere. */ - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + config->res_idx = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(res_idx); @@ -1703,10 +1717,11 @@ static ssize_t res_ctrl_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - idx = config->res_idx; - val = config->res_ctrl[idx]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->res_idx; + val = config->res_ctrl[idx]; + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1722,7 +1737,8 @@ static ssize_t res_ctrl_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->res_idx; /* For odd idx pair inversal bit is RES0 */ if (idx % 2 != 0) @@ -1732,7 +1748,7 @@ static ssize_t res_ctrl_store(struct device *dev, TRCRSCTLRn_INV | TRCRSCTLRn_GROUP_MASK | TRCRSCTLRn_SELECT_MASK); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(res_ctrl); @@ -1761,9 +1777,10 @@ static ssize_t sshot_idx_store(struct device *dev, if (val >= drvdata->nr_ss_cmp) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + config->ss_idx = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(sshot_idx); @@ -1776,9 +1793,10 @@ static ssize_t sshot_ctrl_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - val = config->ss_ctrl[config->ss_idx]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + val = config->ss_ctrl[config->ss_idx]; + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1794,12 +1812,13 @@ static ssize_t sshot_ctrl_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->ss_idx; config->ss_ctrl[idx] = FIELD_PREP(TRCSSCCRn_SAC_ARC_RST_MASK, val); /* must clear bit 31 in related status register on programming */ config->ss_status[idx] &= ~TRCSSCSRn_STATUS; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(sshot_ctrl); @@ -1811,9 +1830,10 @@ static ssize_t sshot_status_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - val = config->ss_status[config->ss_idx]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + val = config->ss_status[config->ss_idx]; + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } static DEVICE_ATTR_RO(sshot_status); @@ -1826,9 +1846,10 @@ static ssize_t sshot_pe_ctrl_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - val = config->ss_pe_cmp[config->ss_idx]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + val = config->ss_pe_cmp[config->ss_idx]; + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1844,12 +1865,13 @@ static ssize_t sshot_pe_ctrl_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->ss_idx; config->ss_pe_cmp[idx] = FIELD_PREP(TRCSSPCICRn_PC_MASK, val); /* must clear bit 31 in related status register on programming */ config->ss_status[idx] &= ~TRCSSCSRn_STATUS; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(sshot_pe_ctrl); @@ -1883,9 +1905,10 @@ static ssize_t ctxid_idx_store(struct device *dev, * Use spinlock to ensure index doesn't change while it gets * dereferenced multiple times within a spinlock block elsewhere. */ - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + config->ctxid_idx = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(ctxid_idx); @@ -1906,10 +1929,11 @@ static ssize_t ctxid_pid_show(struct device *dev, if (task_active_pid_ns(current) != &init_pid_ns) return -EINVAL; - spin_lock(&drvdata->spinlock); - idx = config->ctxid_idx; - val = (unsigned long)config->ctxid_pid[idx]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + idx = config->ctxid_idx; + val = (unsigned long)config->ctxid_pid[idx]; + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1944,10 +1968,11 @@ static ssize_t ctxid_pid_store(struct device *dev, if (kstrtoul(buf, 16, &pid)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + idx = config->ctxid_idx; config->ctxid_pid[idx] = (u64)pid; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(ctxid_pid); @@ -1967,10 +1992,11 @@ static ssize_t ctxid_masks_show(struct device *dev, if (task_active_pid_ns(current) != &init_pid_ns) return -EINVAL; - spin_lock(&drvdata->spinlock); - val1 = config->ctxid_mask0; - val2 = config->ctxid_mask1; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + val1 = config->ctxid_mask0; + val2 = config->ctxid_mask1; + } + return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2); } @@ -2003,7 +2029,8 @@ static ssize_t ctxid_masks_store(struct device *dev, if ((drvdata->numcidc > 4) && (nr_inputs != 2)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + /* * each byte[0..3] controls mask value applied to ctxid * comparator[0..3] @@ -2075,7 +2102,6 @@ static ssize_t ctxid_masks_store(struct device *dev, mask >>= 0x8; } - spin_unlock(&drvdata->spinlock); return size; } static DEVICE_ATTR_RW(ctxid_masks); @@ -2109,9 +2135,10 @@ static ssize_t vmid_idx_store(struct device *dev, * Use spinlock to ensure index doesn't change while it gets * dereferenced multiple times within a spinlock block elsewhere. */ - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + config->vmid_idx = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(vmid_idx); @@ -2131,9 +2158,10 @@ static ssize_t vmid_val_show(struct device *dev, if (!task_is_in_init_pid_ns(current)) return -EINVAL; - spin_lock(&drvdata->spinlock); - val = (unsigned long)config->vmid_val[config->vmid_idx]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + val = (unsigned long)config->vmid_val[config->vmid_idx]; + } + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -2161,9 +2189,10 @@ static ssize_t vmid_val_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + config->vmid_val[config->vmid_idx] = (u64)val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(vmid_val); @@ -2182,10 +2211,11 @@ static ssize_t vmid_masks_show(struct device *dev, if (!task_is_in_init_pid_ns(current)) return -EINVAL; - spin_lock(&drvdata->spinlock); - val1 = config->vmid_mask0; - val2 = config->vmid_mask1; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + val1 = config->vmid_mask0; + val2 = config->vmid_mask1; + } + return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2); } @@ -2217,7 +2247,7 @@ static ssize_t vmid_masks_store(struct device *dev, if ((drvdata->numvmidc > 4) && (nr_inputs != 2)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); /* * each byte[0..3] controls mask value applied to vmid @@ -2290,7 +2320,7 @@ static ssize_t vmid_masks_store(struct device *dev, else mask >>= 0x8; } - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(vmid_masks); diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 9e9165f62e81..366f8f23a3e5 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -989,7 +989,7 @@ struct etmv4_drvdata { struct clk *pclk; void __iomem *base; struct coresight_device *csdev; - spinlock_t spinlock; + raw_spinlock_t spinlock; int cpu; u8 arch; u8 nr_pe; From patchwork Mon Nov 25 09:48:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yeoreum Yun X-Patchwork-Id: 13884760 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 E6DC2D3B7FD for ; Mon, 25 Nov 2024 10:17:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=iYlo1/NurxSLgJe/iRNqYykt64ZIWrcPQtcs8oooGqs=; b=mbD4Xlz4gAWgRAjhRr1g51Gjg+ bccZ0BMIlj9mkrQuf02atsFeB4Dw2EKi52P7ynrcJl8cu4NRbAxFG7RwTOzIxMDhWhnfknVNU/uO1 Km+OiNZH2rTSZj2e16l6qgoPFzpRWBd1q++8FIsk60L1/iWMoUhwpsV0QcMnfkbVr6VVJ0YP/TYOL ppDx7n/BY+IsEf3iGWnRd8imsKNhRMdKqEerurNJvRr1hsyIRXXfVsOm1Fw4MURK3+YPuQxhdgAdB pxzdMOiAV+1PKf09D71lw1EWO0LYttk/SpW6nT5SFWUU4mPtDE7FRTGr97RSnLvAvlnW4NXLFmRL1 YLTHNXbQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFW9t-00000007hnF-3cYK; Mon, 25 Nov 2024 10:17:33 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFVhl-00000007dkc-0Txr for linux-arm-kernel@lists.infradead.org; Mon, 25 Nov 2024 09:48:30 +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 C02D81FCD; Mon, 25 Nov 2024 01:48:58 -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 8CE293F66E; Mon, 25 Nov 2024 01:48:26 -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 3/9] coresight: change coresight_trace_id_map's lock type to raw_spinlock_t Date: Mon, 25 Nov 2024 09:48:10 +0000 Message-Id: <20241125094816.365472-4-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> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241125_014829_241434_439D4E9E X-CRM114-Status: GOOD ( 18.49 ) 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 From: Levi Yun coresight_trace_id_map->lock can be acquired while coresight devices' drvdata_lock. But the drvdata_lock can be raw_spinlock_t (i.e) coresight-etm4x. To address this, change type of coresight_trace_id_map->lock to raw_spinlock_t Signed-off-by: Yeoreum Yun --- drivers/hwtracing/coresight/coresight-core.c | 2 +- .../hwtracing/coresight/coresight-trace-id.c | 93 +++++++++---------- include/linux/coresight.h | 2 +- 3 files changed, 44 insertions(+), 53 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index ea38ecf26fcb..cc2d87b2f248 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1164,7 +1164,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) if (csdev->type == CORESIGHT_DEV_TYPE_SINK || csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) { - spin_lock_init(&csdev->perf_sink_id_map.lock); + raw_spin_lock_init(&csdev->perf_sink_id_map.lock); csdev->perf_sink_id_map.cpu_map = alloc_percpu(atomic_t); if (!csdev->perf_sink_id_map.cpu_map) { kfree(csdev); diff --git a/drivers/hwtracing/coresight/coresight-trace-id.c b/drivers/hwtracing/coresight/coresight-trace-id.c index d98e12cb30ec..1818a353ac5f 100644 --- a/drivers/hwtracing/coresight/coresight-trace-id.c +++ b/drivers/hwtracing/coresight/coresight-trace-id.c @@ -16,7 +16,7 @@ static DEFINE_PER_CPU(atomic_t, id_map_default_cpu_ids) = ATOMIC_INIT(0); static struct coresight_trace_id_map id_map_default = { .cpu_map = &id_map_default_cpu_ids, - .lock = __SPIN_LOCK_UNLOCKED(id_map_default.lock) + .lock = __RAW_SPIN_LOCK_UNLOCKED(id_map_default.lock) }; /* #define TRACE_ID_DEBUG 1 */ @@ -118,50 +118,46 @@ static void coresight_trace_id_free(int id, struct coresight_trace_id_map *id_ma */ static void coresight_trace_id_release_all(struct coresight_trace_id_map *id_map) { - unsigned long flags; int cpu; - spin_lock_irqsave(&id_map->lock, flags); - bitmap_zero(id_map->used_ids, CORESIGHT_TRACE_IDS_MAX); - for_each_possible_cpu(cpu) - atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0); - spin_unlock_irqrestore(&id_map->lock, flags); + scoped_guard(raw_spinlock_irqsave, &id_map->lock) { + bitmap_zero(id_map->used_ids, CORESIGHT_TRACE_IDS_MAX); + for_each_possible_cpu(cpu) + atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0); + } + DUMP_ID_MAP(id_map); } static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map *id_map) { - unsigned long flags; int id; - spin_lock_irqsave(&id_map->lock, flags); - - /* check for existing allocation for this CPU */ - id = _coresight_trace_id_read_cpu_id(cpu, id_map); - if (id) - goto get_cpu_id_out_unlock; - - /* - * Find a new ID. - * - * Use legacy values where possible in the dynamic trace ID allocator to - * allow older tools to continue working if they are not upgraded at the - * same time as the kernel drivers. - * - * If the generated legacy ID is invalid, or not available then the next - * available dynamic ID will be used. - */ - id = coresight_trace_id_alloc_new_id(id_map, - CORESIGHT_LEGACY_CPU_TRACE_ID(cpu), - false); - if (!IS_VALID_CS_TRACE_ID(id)) - goto get_cpu_id_out_unlock; - - /* allocate the new id to the cpu */ - atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), id); + scoped_guard(raw_spinlock_irqsave, &id_map->lock) { + /* check for existing allocation for this CPU */ + id = _coresight_trace_id_read_cpu_id(cpu, id_map); + if (id) + return id; -get_cpu_id_out_unlock: - spin_unlock_irqrestore(&id_map->lock, flags); + /* + * Find a new ID. + * + * Use legacy values where possible in the dynamic trace ID allocator to + * allow older tools to continue working if they are not upgraded at the + * same time as the kernel drivers. + * + * If the generated legacy ID is invalid, or not available then the next + * available dynamic ID will be used. + */ + id = coresight_trace_id_alloc_new_id(id_map, + CORESIGHT_LEGACY_CPU_TRACE_ID(cpu), + false); + if (!IS_VALID_CS_TRACE_ID(id)) + return id; + + /* allocate the new id to the cpu */ + atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), id); + } DUMP_ID_CPU(cpu, id); DUMP_ID_MAP(id_map); @@ -170,7 +166,6 @@ static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map static void _coresight_trace_id_put_cpu_id(int cpu, struct coresight_trace_id_map *id_map) { - unsigned long flags; int id; /* check for existing allocation for this CPU */ @@ -178,25 +173,23 @@ static void _coresight_trace_id_put_cpu_id(int cpu, struct coresight_trace_id_ma if (!id) return; - spin_lock_irqsave(&id_map->lock, flags); - - coresight_trace_id_free(id, id_map); - atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0); + scoped_guard(raw_spinlock_irqsave, &id_map->lock) { + coresight_trace_id_free(id, id_map); + atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0); + } - spin_unlock_irqrestore(&id_map->lock, flags); DUMP_ID_CPU(cpu, id); DUMP_ID_MAP(id_map); } static int coresight_trace_id_map_get_system_id(struct coresight_trace_id_map *id_map) { - unsigned long flags; int id; - spin_lock_irqsave(&id_map->lock, flags); - /* prefer odd IDs for system components to avoid legacy CPU IDS */ - id = coresight_trace_id_alloc_new_id(id_map, 0, true); - spin_unlock_irqrestore(&id_map->lock, flags); + scoped_guard(raw_spinlock_irqsave, &id_map->lock) { + /* prefer odd IDs for system components to avoid legacy CPU IDS */ + id = coresight_trace_id_alloc_new_id(id_map, 0, true); + } DUMP_ID(id); DUMP_ID_MAP(id_map); @@ -205,11 +198,9 @@ static int coresight_trace_id_map_get_system_id(struct coresight_trace_id_map *i static void coresight_trace_id_map_put_system_id(struct coresight_trace_id_map *id_map, int id) { - unsigned long flags; - - spin_lock_irqsave(&id_map->lock, flags); - coresight_trace_id_free(id, id_map); - spin_unlock_irqrestore(&id_map->lock, flags); + scoped_guard(raw_spinlock_irqsave, &id_map->lock) { + coresight_trace_id_free(id, id_map); + } DUMP_ID(id); DUMP_ID_MAP(id_map); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 924b58c343b3..6446ca1f09d8 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -233,7 +233,7 @@ struct coresight_trace_id_map { DECLARE_BITMAP(used_ids, CORESIGHT_TRACE_IDS_MAX); atomic_t __percpu *cpu_map; atomic_t perf_cs_etm_session_active; - spinlock_t lock; + raw_spinlock_t lock; }; /** From patchwork Mon Nov 25 09:48:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yeoreum Yun X-Patchwork-Id: 13884761 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 F28E7D3B7F6 for ; Mon, 25 Nov 2024 10:17:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=jXm5NbqgJpmlUDNgUWgtc/KBChIigHq6d+dXdfLAsOU=; b=0dfE8hmxDZ/GnJDubfPZ4wRBhr Fib27GdUGlc51M29z4hXRQVdpLzHakOTA/67y5AwXgN3QYlgDgmjR3JbYQHhHz2Qcyq7c++Vqn7/P l5eliPITrpgEyIuQeVIgBQw1QgnvzcgCz0ggDbce2U8UaW+PowSo7ahryB+TP5L6+lm+/v9NdHf/i inl4ovorguzEFkQHsMV4QoFD1rQdqh+68v8cx6hZ58JJDqmUj+zkHGyOQLklab+Aj4KH9XbvrEONq M6dr8tG424mINGA60wrDYzLSGFLlaUSHIoleI4MGis60dZrk6DHyy0OTt+8ELRAm92rSlMugW7Zbx 8MPLJxuQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFW9v-00000007hpI-1MIW; Mon, 25 Nov 2024 10:17:35 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFVhn-00000007dlM-3hhW for linux-arm-kernel@lists.infradead.org; Mon, 25 Nov 2024 09:48: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 470201692; Mon, 25 Nov 2024 01:49:01 -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 133A03F66E; Mon, 25 Nov 2024 01:48:28 -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 4/9] coresight-cti: change cti_drvdata spinlock's type to raw_spinlock_t Date: Mon, 25 Nov 2024 09:48:11 +0000 Message-Id: <20241125094816.365472-5-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> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241125_014832_012415_14887E4D X-CRM114-Status: GOOD ( 20.90 ) 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 From: Levi Yun In coresight-cti drivers, cti_drvdata->spinlock can be held during __schedule() by perf_event_task_sched_out()/in(). Since cti_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 cti_drvdata->spinlock in coresight-cti 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-cti-core.c | 65 +++------ .../hwtracing/coresight/coresight-cti-sysfs.c | 135 ++++++++++-------- drivers/hwtracing/coresight/coresight-cti.h | 2 +- 3 files changed, 96 insertions(+), 106 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index d2b5a5718c29..1f7766e9a2ea 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -90,10 +90,9 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) static int cti_enable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; - unsigned long flags; int rc = 0; - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); /* no need to do anything if enabled or unpowered*/ if (config->hw_enabled || !config->hw_powered) @@ -108,7 +107,6 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) config->hw_enabled = true; drvdata->config.enable_req_count++; - spin_unlock_irqrestore(&drvdata->spinlock, flags); return rc; cti_state_unchanged: @@ -116,7 +114,6 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) /* cannot enable due to error */ cti_err_not_enabled: - spin_unlock_irqrestore(&drvdata->spinlock, flags); return rc; } @@ -125,25 +122,20 @@ static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); config->hw_powered = true; /* no need to do anything if no enable request */ if (!drvdata->config.enable_req_count) - goto cti_hp_not_enabled; + return; /* try to claim the device */ if (coresight_claim_device(drvdata->csdev)) - goto cti_hp_not_enabled; + return; cti_write_all_hw_regs(drvdata); config->hw_enabled = true; - spin_unlock(&drvdata->spinlock); return; - - /* did not re-enable due to no claim / no request */ -cti_hp_not_enabled: - spin_unlock(&drvdata->spinlock); } /* disable hardware */ @@ -151,23 +143,20 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; struct coresight_device *csdev = drvdata->csdev; - int ret = 0; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); /* don't allow negative refcounts, return an error */ - if (!drvdata->config.enable_req_count) { - ret = -EINVAL; - goto cti_not_disabled; - } + if (!drvdata->config.enable_req_count) + return -EINVAL; /* check refcount - disable on 0 */ if (--drvdata->config.enable_req_count > 0) - goto cti_not_disabled; + return 0; /* no need to do anything if disabled or cpu unpowered */ if (!config->hw_enabled || !config->hw_powered) - goto cti_not_disabled; + return 0; CS_UNLOCK(drvdata->base); @@ -177,13 +166,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base); - spin_unlock(&drvdata->spinlock); - return ret; - - /* not disabled this call */ -cti_not_disabled: - spin_unlock(&drvdata->spinlock); - return ret; + return 0; } void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value) @@ -198,11 +181,11 @@ void cti_write_intack(struct device *dev, u32 ackval) struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + /* write if enabled */ if (cti_active(config)) cti_write_single_reg(drvdata, CTIINTACK, ackval); - spin_unlock(&drvdata->spinlock); } /* @@ -369,7 +352,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) : CTIOUTEN(trigger_idx)); - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); /* read - modify write - the trigger / channel enable value */ reg_value = direction == CTI_TRIG_IN ? config->ctiinen[trigger_idx] : @@ -388,7 +371,6 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, /* write through if enabled */ if (cti_active(config)) cti_write_single_reg(drvdata, reg_offset, reg_value); - spin_unlock(&drvdata->spinlock); return 0; } @@ -406,7 +388,8 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op, chan_bitmask = BIT(channel_idx); - spin_lock(&drvdata->spinlock); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); + reg_value = config->ctigate; switch (op) { case CTI_GATE_CHAN_ENABLE: @@ -426,7 +409,6 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op, if (cti_active(config)) cti_write_single_reg(drvdata, CTIGATE, reg_value); } - spin_unlock(&drvdata->spinlock); return err; } @@ -445,7 +427,8 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op, chan_bitmask = BIT(channel_idx); - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + reg_value = config->ctiappset; switch (op) { case CTI_CHAN_SET: @@ -473,7 +456,6 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op, if ((err == 0) && cti_active(config)) cti_write_single_reg(drvdata, reg_offset, reg_value); - spin_unlock(&drvdata->spinlock); return err; } @@ -676,7 +658,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu)) return NOTIFY_BAD; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); switch (cmd) { case CPU_PM_ENTER: @@ -703,7 +685,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, if (drvdata->config.enable_req_count) { /* check we can claim the device as we re-power */ if (coresight_claim_device(csdev)) - goto cti_notify_exit; + return notify_res; drvdata->config.hw_enabled = true; cti_write_all_hw_regs(drvdata); @@ -715,8 +697,6 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, break; } -cti_notify_exit: - spin_unlock(&drvdata->spinlock); return notify_res; } @@ -743,11 +723,12 @@ static int cti_dying_cpu(unsigned int cpu) if (!drvdata) return 0; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + drvdata->config.hw_powered = false; if (drvdata->config.hw_enabled) coresight_disclaim_device(drvdata->csdev); - spin_unlock(&drvdata->spinlock); + return 0; } @@ -888,7 +869,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) drvdata->ctidev.ctm_id = 0; INIT_LIST_HEAD(&drvdata->ctidev.trig_cons); - spin_lock_init(&drvdata->spinlock); + raw_spin_lock_init(&drvdata->spinlock); /* initialise CTI driver config values */ cti_set_default_config(dev, drvdata); diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index d25dd2737b49..fa149b94a495 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -84,11 +84,11 @@ static ssize_t enable_show(struct device *dev, bool enabled, powered; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); - spin_lock(&drvdata->spinlock); - enable_req = drvdata->config.enable_req_count; - powered = drvdata->config.hw_powered; - enabled = drvdata->config.hw_enabled; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + enable_req = drvdata->config.enable_req_count; + powered = drvdata->config.hw_powered; + enabled = drvdata->config.hw_enabled; + } if (powered) return sprintf(buf, "%d\n", enabled); @@ -134,9 +134,9 @@ static ssize_t powered_show(struct device *dev, bool powered; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); - spin_lock(&drvdata->spinlock); - powered = drvdata->config.hw_powered; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + powered = drvdata->config.hw_powered; + } return sprintf(buf, "%d\n", powered); } @@ -181,10 +181,10 @@ static ssize_t coresight_cti_reg_show(struct device *dev, u32 val = 0; pm_runtime_get_sync(dev->parent); - spin_lock(&drvdata->spinlock); - if (drvdata->config.hw_powered) - val = readl_relaxed(drvdata->base + cti_attr->off); - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + if (drvdata->config.hw_powered) + val = readl_relaxed(drvdata->base + cti_attr->off); + } pm_runtime_put_sync(dev->parent); return sysfs_emit(buf, "0x%x\n", val); } @@ -202,10 +202,10 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, return -EINVAL; pm_runtime_get_sync(dev->parent); - spin_lock(&drvdata->spinlock); - if (drvdata->config.hw_powered) - cti_write_single_reg(drvdata, cti_attr->off, val); - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + if (drvdata->config.hw_powered) + cti_write_single_reg(drvdata, cti_attr->off, val); + } pm_runtime_put_sync(dev->parent); return size; } @@ -264,17 +264,18 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf, struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); - if ((reg_offset >= 0) && cti_active(config)) { - CS_UNLOCK(drvdata->base); - val = readl_relaxed(drvdata->base + reg_offset); - if (pcached_val) - *pcached_val = val; - CS_LOCK(drvdata->base); - } else if (pcached_val) { - val = *pcached_val; + scoped_guard (raw_spinlock, &drvdata->spinlock) { + if ((reg_offset >= 0) && cti_active(config)) { + CS_UNLOCK(drvdata->base); + val = readl_relaxed(drvdata->base + reg_offset); + if (pcached_val) + *pcached_val = val; + CS_LOCK(drvdata->base); + } else if (pcached_val) { + val = *pcached_val; + } } - spin_unlock(&drvdata->spinlock); + return sprintf(buf, "%#x\n", val); } @@ -293,7 +294,8 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf, if (kstrtoul(buf, 0, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + /* local store */ if (pcached_val) *pcached_val = (u32)val; @@ -301,7 +303,7 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf, /* write through if offset and enabled */ if ((reg_offset >= 0) && cti_active(config)) cti_write_single_reg(drvdata, reg_offset, val); - spin_unlock(&drvdata->spinlock); + return size; } @@ -349,9 +351,10 @@ static ssize_t inout_sel_store(struct device *dev, if (val > (CTIINOUTEN_MAX - 1)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + drvdata->config.ctiinout_sel = val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(inout_sel); @@ -364,10 +367,11 @@ static ssize_t inen_show(struct device *dev, int index; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); - spin_lock(&drvdata->spinlock); - index = drvdata->config.ctiinout_sel; - val = drvdata->config.ctiinen[index]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + index = drvdata->config.ctiinout_sel; + val = drvdata->config.ctiinen[index]; + } + return sprintf(buf, "%#lx\n", val); } @@ -383,14 +387,15 @@ static ssize_t inen_store(struct device *dev, if (kstrtoul(buf, 0, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + index = config->ctiinout_sel; config->ctiinen[index] = val; /* write through if enabled */ if (cti_active(config)) cti_write_single_reg(drvdata, CTIINEN(index), val); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(inen); @@ -403,10 +408,11 @@ static ssize_t outen_show(struct device *dev, int index; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); - spin_lock(&drvdata->spinlock); - index = drvdata->config.ctiinout_sel; - val = drvdata->config.ctiouten[index]; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + index = drvdata->config.ctiinout_sel; + val = drvdata->config.ctiouten[index]; + } + return sprintf(buf, "%#lx\n", val); } @@ -422,14 +428,15 @@ static ssize_t outen_store(struct device *dev, if (kstrtoul(buf, 0, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + index = config->ctiinout_sel; config->ctiouten[index] = val; /* write through if enabled */ if (cti_active(config)) cti_write_single_reg(drvdata, CTIOUTEN(index), val); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(outen); @@ -463,7 +470,7 @@ static ssize_t appclear_store(struct device *dev, if (kstrtoul(buf, 0, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); /* a 1'b1 in appclr clears down the same bit in appset*/ config->ctiappset &= ~val; @@ -471,7 +478,7 @@ static ssize_t appclear_store(struct device *dev, /* write through if enabled */ if (cti_active(config)) cti_write_single_reg(drvdata, CTIAPPCLEAR, val); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_WO(appclear); @@ -487,12 +494,12 @@ static ssize_t apppulse_store(struct device *dev, if (kstrtoul(buf, 0, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); /* write through if enabled */ if (cti_active(config)) cti_write_single_reg(drvdata, CTIAPPPULSE, val); - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_WO(apppulse); @@ -681,9 +688,10 @@ static ssize_t trig_filter_enable_show(struct device *dev, u32 val; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); - spin_lock(&drvdata->spinlock); - val = drvdata->config.trig_filter_enable; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + val = drvdata->config.trig_filter_enable; + } + return sprintf(buf, "%d\n", val); } @@ -697,9 +705,10 @@ static ssize_t trig_filter_enable_store(struct device *dev, if (kstrtoul(buf, 0, &val)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + drvdata->config.trig_filter_enable = !!val; - spin_unlock(&drvdata->spinlock); + return size; } static DEVICE_ATTR_RW(trig_filter_enable); @@ -728,7 +737,7 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev, struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *config = &drvdata->config; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); /* clear the CTI trigger / channel programming registers */ for (i = 0; i < config->nr_trig_max; i++) { @@ -747,7 +756,6 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev, if (cti_active(config)) cti_write_all_hw_regs(drvdata); - spin_unlock(&drvdata->spinlock); return size; } static DEVICE_ATTR_WO(chan_xtrigs_reset); @@ -768,9 +776,10 @@ static ssize_t chan_xtrigs_sel_store(struct device *dev, if (val > (drvdata->config.nr_ctm_channels - 1)) return -EINVAL; - spin_lock(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); + drvdata->config.xtrig_rchan_sel = val; - spin_unlock(&drvdata->spinlock); + return size; } @@ -781,9 +790,9 @@ static ssize_t chan_xtrigs_sel_show(struct device *dev, unsigned long val; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); - spin_lock(&drvdata->spinlock); - val = drvdata->config.xtrig_rchan_sel; - spin_unlock(&drvdata->spinlock); + scoped_guard(raw_spinlock, &drvdata->spinlock) { + val = drvdata->config.xtrig_rchan_sel; + } return sprintf(buf, "%ld\n", val); } @@ -838,12 +847,12 @@ static ssize_t print_chan_list(struct device *dev, unsigned long inuse_bits = 0, chan_mask; /* scan regs to get bitmap of channels in use. */ - spin_lock(&drvdata->spinlock); - for (i = 0; i < config->nr_trig_max; i++) { - inuse_bits |= config->ctiinen[i]; - inuse_bits |= config->ctiouten[i]; + scoped_guard(raw_spinlock, &drvdata->spinlock) { + for (i = 0; i < config->nr_trig_max; i++) { + inuse_bits |= config->ctiinen[i]; + inuse_bits |= config->ctiouten[i]; + } } - spin_unlock(&drvdata->spinlock); /* inverse bits if printing free channels */ if (!inuse) diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index cb9ee616d01f..16e310e7e9d4 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -175,7 +175,7 @@ struct cti_drvdata { void __iomem *base; struct coresight_device *csdev; struct cti_device ctidev; - spinlock_t spinlock; + raw_spinlock_t spinlock; struct cti_config config; struct list_head node; void (*csdev_release)(struct device *dev); From patchwork Mon Nov 25 09:48:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yeoreum Yun X-Patchwork-Id: 13884762 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 CE1FED3B7F8 for ; Mon, 25 Nov 2024 10:17:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=ohDBbX5wykAAdNyCI+XvgU3CimrF19MrDkF4qpXyhuM=; b=4mZkX2mq/hN6vi5wmhSqvgcJpn 9aJx8Ll1hhNOGv5vh8MuXTqNVYOwTqPWGrlCWKTeuSQ5ui7GbEBtkPxTbf6pw/rYoi0Si4jOW0l5p jwlfAKfijefpxXWQmREa0JI9Pwk9cTnmD2JhJbwOD8g4xH1dH5iYyMPcDDjENd5Z0rIvpoK8KtMi+ xkHuc4gabqGzzb+mtfVMrJke2bZXVRVbDWEaYPlr2N+ZNTr7c8fsAzRj+fkyk85xla6d3fVpay5JW 4Il4kxBrDNb/wJMbbnPmJESUrnkAlz9vAgc3HqyeG9ifpCpwoBKRN04z9qWg/XHBDIdaKfcUENFGt K53UQesg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFW9w-00000007hr8-3SLz; Mon, 25 Nov 2024 10:17:37 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFVhq-00000007dmS-1crK for linux-arm-kernel@lists.infradead.org; Mon, 25 Nov 2024 09:48: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 C16821756; Mon, 25 Nov 2024 01:49:03 -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 8DBBF3F66E; Mon, 25 Nov 2024 01:48:31 -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 5/9] coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t Date: Mon, 25 Nov 2024 09:48:12 +0000 Message-Id: <20241125094816.365472-6-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> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241125_014834_509936_67FE38B1 X-CRM114-Status: GOOD ( 19.25 ) 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 From: Levi Yun In coresight-etb10 drivers, etb_drvdata->spinlock can be held during __schedule() by perf_event_task_sched_out()/in(). Since etb_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 etb_drvdata->spinlock in coresight-etb10 drivers, which can be called by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t. Signed-off-by: Yeoreum Yun --- drivers/hwtracing/coresight/coresight-etb10.c | 62 +++++++------------ 1 file changed, 22 insertions(+), 40 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index aea9ac9c4bd0..ec439f8fbc1e 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -84,7 +84,7 @@ struct etb_drvdata { struct clk *atclk; struct coresight_device *csdev; struct miscdevice miscdev; - spinlock_t spinlock; + raw_spinlock_t spinlock; local_t reading; pid_t pid; u8 *buf; @@ -141,56 +141,47 @@ static int etb_enable_hw(struct etb_drvdata *drvdata) static int etb_enable_sysfs(struct coresight_device *csdev) { - int ret = 0; - unsigned long flags; + int ret; struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); /* Don't messup with perf sessions. */ - if (coresight_get_mode(csdev) == CS_MODE_PERF) { - ret = -EBUSY; - goto out; - } + if (coresight_get_mode(csdev) == CS_MODE_PERF) + return -EBUSY; if (coresight_get_mode(csdev) == CS_MODE_DISABLED) { ret = etb_enable_hw(drvdata); if (ret) - goto out; + return ret; coresight_set_mode(csdev, CS_MODE_SYSFS); } csdev->refcnt++; -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return ret; + + return 0; } static int etb_enable_perf(struct coresight_device *csdev, void *data) { - int ret = 0; + int ret; pid_t pid; - unsigned long flags; struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct perf_output_handle *handle = data; struct cs_buffers *buf = etm_perf_sink_config(handle); - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); /* No need to continue if the component is already in used by sysFS. */ - if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) { - ret = -EBUSY; - goto out; - } + if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) + return -EBUSY; /* Get a handle on the pid of the process to monitor */ pid = buf->pid; - if (drvdata->pid != -1 && drvdata->pid != pid) { - ret = -EBUSY; - goto out; - } + if (drvdata->pid != -1 && drvdata->pid != pid) + return -EBUSY; /* * No HW configuration is needed if the sink is already in @@ -198,7 +189,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) */ if (drvdata->pid == pid) { csdev->refcnt++; - goto out; + return 0; } /* @@ -208,7 +199,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) */ ret = etb_set_buffer(csdev, handle); if (ret) - goto out; + return ret; ret = etb_enable_hw(drvdata); if (!ret) { @@ -218,8 +209,6 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) csdev->refcnt++; } -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); return ret; } @@ -350,13 +339,11 @@ static void etb_disable_hw(struct etb_drvdata *drvdata) static int etb_disable(struct coresight_device *csdev) { struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - unsigned long flags; - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); csdev->refcnt--; if (csdev->refcnt) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY; } @@ -366,7 +353,6 @@ static int etb_disable(struct coresight_device *csdev) /* Dissociate from monitored process. */ drvdata->pid = -1; coresight_set_mode(csdev, CS_MODE_DISABLED); - spin_unlock_irqrestore(&drvdata->spinlock, flags); dev_dbg(&csdev->dev, "ETB disabled\n"); return 0; @@ -434,7 +420,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, const u32 *barrier; u32 read_ptr, write_ptr, capacity; u32 status, read_data; - unsigned long offset, to_read = 0, flags; + unsigned long offset, to_read = 0; struct cs_buffers *buf = sink_config; struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -443,11 +429,11 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS; - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); /* Don't do anything if another tracer is using this sink */ if (csdev->refcnt != 1) - goto out; + return 0; __etb_disable_hw(drvdata); CS_UNLOCK(drvdata->base); @@ -565,8 +551,6 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, __etb_enable_hw(drvdata); CS_LOCK(drvdata->base); -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); return to_read; } @@ -585,15 +569,13 @@ static const struct coresight_ops etb_cs_ops = { static void etb_dump(struct etb_drvdata *drvdata) { - unsigned long flags; + guard(raw_spinlock_irqsave)(&drvdata->spinlock); - spin_lock_irqsave(&drvdata->spinlock, flags); if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) { __etb_disable_hw(drvdata); etb_dump_hw(drvdata); __etb_enable_hw(drvdata); } - spin_unlock_irqrestore(&drvdata->spinlock, flags); dev_dbg(&drvdata->csdev->dev, "ETB dumped\n"); } @@ -746,7 +728,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id) drvdata->base = base; desc.access = CSDEV_ACCESS_IOMEM(base); - spin_lock_init(&drvdata->spinlock); + raw_spin_lock_init(&drvdata->spinlock); drvdata->buffer_depth = etb_get_buffer_depth(drvdata); From patchwork Mon Nov 25 09:48:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yeoreum Yun X-Patchwork-Id: 13884759 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 DD406D3B7FC for ; Mon, 25 Nov 2024 10:17:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=59I0/vHTvZdRA/FMZFvzsAbUnl48zuqRPemMMUg6j8U=; b=WxvvqgQdoJ6auWBtcW8TpFtIS2 vZgtkyXaCHww4RKhuCwvo+HNSKgziY1Dj4po2myxvzQgEzumpdd/WXBy4XAPadRYBWasH2g7mjhLm 0naHaLNsYtAgA9ZVg9iFAgdfIc6Ysop31tbte2X7yCrEyu5dSDcnrAGQw1r3OYTDmYwIugbyS2Tda XEE+SsA1JMPaK56S53RxzYCdnaSB+mHIdls9vBepO/nlvmqj0XGNYmcesE4vG61MUbTmj67B0ESpq oPHRYWsLuxXGteiMu63XS0HR6man97pL41wpJlfk4T+vRdmpmdm9xqwguvc2ghjUE0yZHSpQfq3Kz 2bCiZE5w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFW9y-00000007hsg-04jg; Mon, 25 Nov 2024 10:17:38 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFVhs-00000007dnH-2cUQ for linux-arm-kernel@lists.infradead.org; Mon, 25 Nov 2024 09:48:37 +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 470A01FC7; Mon, 25 Nov 2024 01:49:06 -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 138D73F66E; Mon, 25 Nov 2024 01:48:33 -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 6/9] coresight-funnel: change funnel_drvdata spinlock's type to raw_spinlock_t Date: Mon, 25 Nov 2024 09:48:13 +0000 Message-Id: <20241125094816.365472-7-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> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241125_014836_750467_FC20A3D7 X-CRM114-Status: GOOD ( 13.54 ) 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 From: Levi Yun In coresight-funnel drivers, cti_drvdata->spinlock can be held during __schedule() by perf_event_task_sched_out()/in(). Since funnel_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 funnel_drvdata->spinlock in coresight-funnel 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-funnel.c | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 5a819c8970fb..dbc2891a10e1 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -47,7 +47,7 @@ struct funnel_drvdata { struct clk *pclk; struct coresight_device *csdev; unsigned long priority; - spinlock_t spinlock; + raw_spinlock_t spinlock; }; static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) @@ -82,19 +82,18 @@ static int funnel_enable(struct coresight_device *csdev, { int rc = 0; struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - unsigned long flags; bool first_enable = false; - spin_lock_irqsave(&drvdata->spinlock, flags); - if (atomic_read(&in->dest_refcnt) == 0) { - if (drvdata->base) - rc = dynamic_funnel_enable_hw(drvdata, in->dest_port); + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + if (atomic_read(&in->dest_refcnt) == 0) { + if (drvdata->base) + rc = dynamic_funnel_enable_hw(drvdata, in->dest_port); + if (!rc) + first_enable = true; + } if (!rc) - first_enable = true; + atomic_inc(&in->dest_refcnt); } - if (!rc) - atomic_inc(&in->dest_refcnt); - spin_unlock_irqrestore(&drvdata->spinlock, flags); if (first_enable) dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n", @@ -126,16 +125,15 @@ static void funnel_disable(struct coresight_device *csdev, struct coresight_connection *out) { struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - unsigned long flags; bool last_disable = false; - spin_lock_irqsave(&drvdata->spinlock, flags); - if (atomic_dec_return(&in->dest_refcnt) == 0) { - if (drvdata->base) - dynamic_funnel_disable_hw(drvdata, in->dest_port); - last_disable = true; + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + if (atomic_dec_return(&in->dest_refcnt) == 0) { + if (drvdata->base) + dynamic_funnel_disable_hw(drvdata, in->dest_port); + last_disable = true; + } } - spin_unlock_irqrestore(&drvdata->spinlock, flags); if (last_disable) dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n", @@ -266,7 +264,7 @@ static int funnel_probe(struct device *dev, struct resource *res) } dev->platform_data = pdata; - spin_lock_init(&drvdata->spinlock); + raw_spin_lock_init(&drvdata->spinlock); desc.type = CORESIGHT_DEV_TYPE_LINK; desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG; desc.ops = &funnel_cs_ops; From patchwork Mon Nov 25 09:48:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yeoreum Yun X-Patchwork-Id: 13884765 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 A636BD3B7F8 for ; Mon, 25 Nov 2024 10:17:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=WKM08ufpT1EbYfcfX7SQOhTA+w2SBmH+cjuGWd6r0T0=; b=Ajs937mqLsfkVP18SoT7V6D5eh 6HiL21aZH7bK+ZH8FhD+aEa0XyxcAi1Q0b/xnFLL9T5Tw1VoWOxUhyRPBYp7lVbx94vK/p7Lkbz5r C8aIbzoz/IGvHUJIlZhc8DRbwlAMWyajKKn2EWZ+SPpx8XJe6B5cf4X2hSOYUvb0Cnvjrqche84ED 7+hRzGXN0FNQEdD+AV6mboib1iHebvnBrOWfrkOrdl+tnfBLtP+MSYNjDnvzw+MGOtfCnZ0Sly/ak ObXD7+69a4NhntvnVCbYwVT7cGC7AWimbcdmfNtIGhHczUa45sZX2ZC1AbI054DvedufdZHN2bKxO v6f92LYw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFWA0-00000007hwG-29B8; Mon, 25 Nov 2024 10:17:40 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFVhv-00000007do2-0WXT for linux-arm-kernel@lists.infradead.org; Mon, 25 Nov 2024 09:48:40 +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 C146B1756; Mon, 25 Nov 2024 01:49:08 -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 8D8793F66E; Mon, 25 Nov 2024 01:48:36 -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 7/9] coresight-replicator: change replicator_drvdata spinlock's type to raw_spinlock_t Date: Mon, 25 Nov 2024 09:48:14 +0000 Message-Id: <20241125094816.365472-8-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> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241125_014839_252998_5C6D955E X-CRM114-Status: GOOD ( 13.54 ) 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 From: Levi Yun In coresight-replicator drivers, replicator_drvdata->spinlock can be held during __schedule() by perf_event_task_sched_out()/in(). Since replicator_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 replicator_drvdata->spinlock in coresight-replicator drivers, which can be called by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t. Signed-off-by: Yeoreum Yun --- .../coresight/coresight-replicator.c | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 3e55be9c8418..7ff08fb70758 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -41,7 +41,7 @@ struct replicator_drvdata { struct clk *atclk; struct clk *pclk; struct coresight_device *csdev; - spinlock_t spinlock; + raw_spinlock_t spinlock; bool check_idfilter_val; }; @@ -122,20 +122,19 @@ static int replicator_enable(struct coresight_device *csdev, { int rc = 0; struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - unsigned long flags; bool first_enable = false; - spin_lock_irqsave(&drvdata->spinlock, flags); + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { if (atomic_read(&out->src_refcnt) == 0) { - if (drvdata->base) - rc = dynamic_replicator_enable(drvdata, in->dest_port, - out->src_port); + if (drvdata->base) + rc = dynamic_replicator_enable(drvdata, in->dest_port, + out->src_port); + if (!rc) + first_enable = true; + } if (!rc) - first_enable = true; + atomic_inc(&out->src_refcnt); } - if (!rc) - atomic_inc(&out->src_refcnt); - spin_unlock_irqrestore(&drvdata->spinlock, flags); if (first_enable) dev_dbg(&csdev->dev, "REPLICATOR enabled\n"); @@ -176,17 +175,16 @@ static void replicator_disable(struct coresight_device *csdev, struct coresight_connection *out) { struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - unsigned long flags; bool last_disable = false; - spin_lock_irqsave(&drvdata->spinlock, flags); - if (atomic_dec_return(&out->src_refcnt) == 0) { - if (drvdata->base) - dynamic_replicator_disable(drvdata, in->dest_port, - out->src_port); - last_disable = true; + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + if (atomic_dec_return(&out->src_refcnt) == 0) { + if (drvdata->base) + dynamic_replicator_disable(drvdata, in->dest_port, + out->src_port); + last_disable = true; + } } - spin_unlock_irqrestore(&drvdata->spinlock, flags); if (last_disable) dev_dbg(&csdev->dev, "REPLICATOR disabled\n"); @@ -277,7 +275,7 @@ static int replicator_probe(struct device *dev, struct resource *res) } dev->platform_data = pdata; - spin_lock_init(&drvdata->spinlock); + raw_spin_lock_init(&drvdata->spinlock); desc.type = CORESIGHT_DEV_TYPE_LINK; desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT; desc.ops = &replicator_cs_ops; From patchwork Mon Nov 25 09:48:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yeoreum Yun X-Patchwork-Id: 13884764 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 3C023D3B7F5 for ; Mon, 25 Nov 2024 10:17: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:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=zwdG2KjCoa5YAh/+cggXfn4fva4fNtrVZr0O3AYCFYM=; b=34TxuoW+48BNAdJtB/XaZZh8z2 SVdocclCWK3TmpVpLQ22zEZFN9EXzPbnJV4+BB6kFiMayJ3sf5g+CE7Hs1gESSghIW9BMwzqUj15k kCZHzzjDnot+n0JZ+Oy+78tr/uwVSTz1A3wOe4Qnn7OA065dHsajCFj14bmiBCAIesfp77PVbCt0i qBGmUD54b9WjVK7DclS1vEsGKY/bWNiKBLCjUn0/oNcFFpFfjVsHCSuGRXq74LjlB7Jx5u2j4wwnY EBiF+EunmUd08gXuyoGdiQlEcYTouU2dphgCJdSkCuzy0/kxA118JTluAdzTL6NMkYEio4DxdKyH7 ZCJvMNgg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFWA1-00000007hxd-1Nza; Mon, 25 Nov 2024 10:17:41 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFVhx-00000007doc-2WcP for linux-arm-kernel@lists.infradead.org; Mon, 25 Nov 2024 09:48:42 +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 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> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241125_014841_785643_F5372344 X-CRM114-Status: GOOD ( 29.25 ) 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 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/hwtracing/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 resource *res) drvdata->base = base; desc.access = CSDEV_ACCESS_IOMEM(base); - spin_lock_init(&drvdata->spinlock); + raw_spin_lock_init(&drvdata->spinlock); devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); drvdata->config_type = BMVAL(devid, 6, 7); @@ -593,13 +593,12 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) static void tmc_shutdown(struct amba_device *adev) { - unsigned long flags; struct tmc_drvdata *drvdata = amba_get_drvdata(adev); - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); if (coresight_get_mode(drvdata->csdev) == CS_MODE_DISABLED) - goto out; + return; if (drvdata->config_type == 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); } static void __tmc_remove(struct device *dev) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/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_device *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); /* Allocating the memory here while outside of the spinlock */ buf = kzalloc(drvdata->size, GFP_KERNEL); @@ -192,7 +192,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) return -ENOMEM; /* Let's try again */ - spin_lock_irqsave(&drvdata->spinlock, flags); + raw_spin_lock_irqsave(&drvdata->spinlock, flags); } if (drvdata->reading) { @@ -235,7 +235,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) used = false; } out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); /* 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 = 0; pid_t pid; - unsigned long flags; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct perf_output_handle *handle = data; struct cs_buffers *buf = etm_perf_sink_config(handle); - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); + do { ret = -EINVAL; if (drvdata->reading) @@ -296,7 +296,6 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) csdev->refcnt++; } } while (0); - spin_unlock_irqrestore(&drvdata->spinlock, flags); return ret; } @@ -328,31 +327,24 @@ static int tmc_enable_etf_sink(struct coresight_device *csdev, static int tmc_disable_etf_sink(struct coresight_device *csdev) { - unsigned long flags; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - spin_lock_irqsave(&drvdata->spinlock, flags); + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + if (drvdata->reading) + return -EBUSY; - if (drvdata->reading) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return -EBUSY; - } + csdev->refcnt--; + if (csdev->refcnt) + return -EBUSY; - 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) == CS_MODE_DISABLED); + tmc_etb_disable_hw(drvdata); + /* Dissociate from monitored process. */ + drvdata->pid = -1; + coresight_set_mode(csdev, CS_MODE_DISABLED); } - /* Complain if we (somehow) got out of sync */ - WARN_ON_ONCE(coresight_get_mode(csdev) == CS_MODE_DISABLED); - tmc_etb_disable_hw(drvdata); - /* Dissociate from monitored process. */ - drvdata->pid = -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_device *csdev, struct coresight_connection *out) { int ret = 0; - unsigned long flags; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); bool first_enable = false; - spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return -EBUSY; - } - - if (csdev->refcnt == 0) { - ret = tmc_etf_enable_hw(drvdata); - if (!ret) { - coresight_set_mode(csdev, CS_MODE_SYSFS); - first_enable = true; + scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) { + if (drvdata->reading) + return -EBUSY; + + if (csdev->refcnt == 0) { + ret = tmc_etf_enable_hw(drvdata); + if (!ret) { + coresight_set_mode(csdev, CS_MODE_SYSFS); + first_enable = true; + } } + if (!ret) + csdev->refcnt++; } - if (!ret) - csdev->refcnt++; - spin_unlock_irqrestore(&drvdata->spinlock, flags); if (first_enable) dev_dbg(&csdev->dev, "TMC-ETF enabled\n"); @@ -392,23 +381,20 @@ static void tmc_disable_etf_link(struct coresight_device *csdev, struct coresight_connection *in, struct coresight_connection *out) { - unsigned long flags; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); bool last_disable = false; - 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; - csdev->refcnt--; - if (csdev->refcnt == 0) { - tmc_etf_disable_hw(drvdata); - coresight_set_mode(csdev, CS_MODE_DISABLED); - last_disable = true; + csdev->refcnt--; + if (csdev->refcnt == 0) { + tmc_etf_disable_hw(drvdata); + coresight_set_mode(csdev, CS_MODE_DISABLED); + last_disable = true; + } } - spin_unlock_irqrestore(&drvdata->spinlock, flags); if (last_disable) dev_dbg(&csdev->dev, "TMC-ETF disabled\n"); @@ -477,7 +463,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, u32 *buf_ptr; u64 read_ptr, write_ptr; u32 status; - unsigned long offset, to_read = 0, flags; + unsigned long offset, to_read = 0; struct cs_buffers *buf = sink_config; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -488,11 +474,11 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, if (WARN_ON_ONCE(coresight_get_mode(csdev) != CS_MODE_PERF)) return 0; - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); /* Don't do anything if another tracer is using this sink */ if (csdev->refcnt != 1) - goto out; + return 0; CS_UNLOCK(drvdata->base); @@ -584,8 +570,6 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, * is expected by the perf ring buffer. */ CS_LOCK(drvdata->base); -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); return to_read; } @@ -615,56 +599,43 @@ const struct coresight_ops tmc_etf_cs_ops = { int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) { enum tmc_mode mode; - int ret = 0; - unsigned long flags; /* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETB && drvdata->config_type != TMC_CONFIG_TYPE_ETF)) return -EINVAL; - spin_lock_irqsave(&drvdata->spinlock, flags); + guard(raw_spinlock_irqsave)(&drvdata->spinlock); - if (drvdata->reading) { - ret = -EBUSY; - goto out; - } + if (drvdata->reading) + return -EBUSY; /* Don't interfere if operated from Perf */ - if (coresight_get_mode(drvdata->csdev) == CS_MODE_PERF) { - ret = -EINVAL; - goto out; - } + if (coresight_get_mode(drvdata->csdev) == CS_MODE_PERF) + return -EINVAL; /* If drvdata::buf is NULL the trace data has been read already */ - if (drvdata->buf == NULL) { - ret = -EINVAL; - goto out; - } + if (drvdata->buf == NULL) + return -EINVAL; /* Disable the TMC if need be */ if (coresight_get_mode(drvdata->csdev) == 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) { - ret = -EINVAL; - goto out; - } + if (mode != TMC_MODE_CIRCULAR_BUFFER) + return -EINVAL; __tmc_etb_disable_hw(drvdata); } drvdata->reading = true; -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); - return ret; + return 0; } int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) { char *buf = NULL; enum tmc_mode mode; - unsigned long flags; int rc = 0; /* config types are set a boot time and never change */ @@ -672,41 +643,37 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) drvdata->config_type != TMC_CONFIG_TYPE_ETF)) return -EINVAL; - spin_lock_irqsave(&drvdata->spinlock, flags); - - /* Re-enable the TMC if need be */ - if (coresight_get_mode(drvdata->csdev) == 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) { - 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 = __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) == 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) + 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 = __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 = drvdata->buf; + drvdata->buf = NULL; } - } else { - /* - * The ETB/ETF is not tracing and the buffer was just read. - * As such prepare to free the trace buffer. - */ - buf = drvdata->buf; - drvdata->buf = NULL; - } - drvdata->reading = false; - spin_unlock_irqrestore(&drvdata->spinlock, flags); + drvdata->reading = false; + } /* * Free allocated memory outside of the spinlock. There is no need diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/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(struct 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 = READ_ONCE(drvdata->sysfs_buf); if (!sysfs_buf || (sysfs_buf->size != drvdata->size)) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); /* Allocate memory with the locks released */ free_buf = new_buf = tmc_etr_setup_sysfs_buf(drvdata); @@ -1187,7 +1187,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev) return new_buf; /* Let's try again */ - spin_lock_irqsave(&drvdata->spinlock, flags); + raw_spin_lock_irqsave(&drvdata->spinlock, flags); } if (drvdata->reading || coresight_get_mode(csdev) == CS_MODE_PERF) { @@ -1206,7 +1206,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev) } out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); /* Free memory outside the spinlock if need be */ if (free_buf) @@ -1216,35 +1216,31 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev) static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) { - int ret = 0; - unsigned long flags; + int ret; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct etr_buf *sysfs_buf = tmc_etr_get_sysfs_buffer(csdev); if (IS_ERR(sysfs_buf)) return PTR_ERR(sysfs_buf); - 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) == 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) == CS_MODE_SYSFS) { + csdev->refcnt++; + return 0; + } - ret = tmc_etr_enable_hw(drvdata, sysfs_buf); - if (!ret) { - coresight_set_mode(csdev, CS_MODE_SYSFS); - csdev->refcnt++; + ret = tmc_etr_enable_hw(drvdata, sysfs_buf); + if (!ret) { + coresight_set_mode(csdev, CS_MODE_SYSFS); + csdev->refcnt++; + } } -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); - if (!ret) dev_dbg(&csdev->dev, "TMC-ETR enabled\n"); @@ -1557,32 +1553,28 @@ tmc_update_etr_buffer(struct coresight_device *csdev, void *config) { bool lost = false; - unsigned long flags, offset, size = 0; + unsigned long offset, size = 0; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct etr_perf_buffer *etr_perf = config; struct etr_buf *etr_buf = etr_perf->etr_buf; - spin_lock_irqsave(&drvdata->spinlock, flags); - - /* Don't do anything if another tracer is using this sink */ - if (csdev->refcnt != 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 != 1) + goto out; - if (WARN_ON(drvdata->perf_buf != etr_buf)) { - lost = true; - spin_unlock_irqrestore(&drvdata->spinlock, flags); - goto out; - } + if (WARN_ON(drvdata->perf_buf != etr_buf)) { + lost = true; + goto out; + } - CS_UNLOCK(drvdata->base); + CS_UNLOCK(drvdata->base); - tmc_flush_and_stop(drvdata); - tmc_sync_etr_buf(drvdata); + tmc_flush_and_stop(drvdata); + tmc_sync_etr_buf(drvdata); - CS_LOCK(drvdata->base); - spin_unlock_irqrestore(&drvdata->spinlock, flags); + CS_LOCK(drvdata->base); + } lost = etr_buf->full; offset = etr_buf->offset; @@ -1644,33 +1636,27 @@ tmc_update_etr_buffer(struct coresight_device *csdev, static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) { - int rc = 0; + int rc; pid_t pid; - unsigned long flags; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct perf_output_handle *handle = data; struct etr_perf_buffer *etr_perf = etm_perf_sink_config(handle); - 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) == CS_MODE_SYSFS) { - rc = -EBUSY; - goto unlock_out; - } + if (coresight_get_mode(csdev) == CS_MODE_SYSFS) + return -EBUSY; - if (WARN_ON(!etr_perf || !etr_perf->etr_buf)) { - rc = -EINVAL; - goto unlock_out; - } + if (WARN_ON(!etr_perf || !etr_perf->etr_buf)) + return -EINVAL; /* Get a handle on the pid of the session owner */ pid = etr_perf->pid; /* Do not proceed if this device is associated with another session */ - if (drvdata->pid != -1 && drvdata->pid != pid) { - rc = -EBUSY; - goto unlock_out; - } + if (drvdata->pid != -1 && drvdata->pid != pid) + return -EBUSY; /* * 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 == pid) { csdev->refcnt++; - goto unlock_out; + return 0; } rc = 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++; } -unlock_out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); return rc; } @@ -1710,33 +1694,26 @@ static int tmc_enable_etr_sink(struct coresight_device *csdev, static int tmc_disable_etr_sink(struct coresight_device *csdev) { - unsigned long flags; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - 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) == CS_MODE_DISABLED); + tmc_etr_disable_hw(drvdata); + /* Dissociate from monitored process. */ + drvdata->pid = -1; + coresight_set_mode(csdev, CS_MODE_DISABLED); + /* Reset perf specific data */ + drvdata->perf_buf = NULL; } - /* Complain if we (somehow) got out of sync */ - WARN_ON_ONCE(coresight_get_mode(csdev) == CS_MODE_DISABLED); - tmc_etr_disable_hw(drvdata); - /* Dissociate from monitored process. */ - drvdata->pid = -1; - coresight_set_mode(csdev, CS_MODE_DISABLED); - /* Reset perf specific data */ - drvdata->perf_buf = 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 = { int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) { int ret = 0; - unsigned long flags; /* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR)) return -EINVAL; - spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { - ret = -EBUSY; - goto out; - } + guard(raw_spinlock_irqsave)(&drvdata->spinlock); + + if (drvdata->reading) + return -EBUSY; /* * 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 = -EINVAL; - goto out; - } + if (!drvdata->sysfs_buf) + return -EINVAL; /* Disable the TMC if we are trying to read from a running session. */ if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) __tmc_etr_disable_hw(drvdata); drvdata->reading = true; -out: - spin_unlock_irqrestore(&drvdata->spinlock, flags); return ret; } int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) { - unsigned long flags; struct etr_buf *sysfs_buf = NULL; /* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR)) return -EINVAL; - 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) == 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 = drvdata->sysfs_buf; + drvdata->sysfs_buf = NULL; + } - /* RE-enable the TMC if need be */ - if (coresight_get_mode(drvdata->csdev) == 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 = drvdata->sysfs_buf; - drvdata->sysfs_buf = NULL; + drvdata->reading = false; } - drvdata->reading = 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/hwtracing/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 { From patchwork Mon Nov 25 09:48:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yeoreum Yun X-Patchwork-Id: 13884763 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 D7900D3B7FC for ; Mon, 25 Nov 2024 10:17: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:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=oDoI35vgzWYdRkhFYrikjsIy3ZO44dxkmnBmhP1BVms=; b=pCQ7twdE0WTgpLZezsHyIbS+sV jZJWNx90rxuoslSWeCib1sDpcIeQX6Zdw3mM7bej24OUpMwI6AvN4BVSHnBa2M63W9c5SMwFdg5yz w/2f0BcPq7FY6TcZMBmjy7GnLyq6jV45YYwqQkUEBkt2QJUJaulKibMFZXS9lz42LoOxNpKGax4v1 5pny2ykNwbdnKvCnCZ9NlQHhAKAmXcQSJeOgFVnx7gJZVyXrR3mJzEJ0kWcMEQ4wsNKIFU1huawXs hnyizrgGaXqx3CYxHVCuBUJj1rLxUiXqhjxJHK9ZM4WEl8mvEKNnbJF5GOQkrcjEVDrT1NrkuNThy dkppo/Gw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFWA2-00000007hzA-0zYB; Mon, 25 Nov 2024 10:17:42 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tFVi0-00000007dpO-0Rwd for linux-arm-kernel@lists.infradead.org; Mon, 25 Nov 2024 09:48:45 +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 C26FB1756; Mon, 25 Nov 2024 01:49:13 -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 8EF163F66E; Mon, 25 Nov 2024 01:48:41 -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 9/9] coresight/ultrasoc: change cti_drvdata spinlock's type to raw_spinlock_t Date: Mon, 25 Nov 2024 09:48:16 +0000 Message-Id: <20241125094816.365472-10-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> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241125_014844_236117_1622EBF9 X-CRM114-Status: GOOD ( 14.20 ) 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 From: Levi Yun In ultrasoc-smb drivers, smb_drv_data->spinlock can be held during __schedule() by perf_event_task_sched_out()/in(). Since smb__drv_data->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 smb_drv_data->spinlock in ultrasoc-smb drivers, which can be called by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t. Signed-off-by: Yeoreum Yun --- drivers/hwtracing/coresight/ultrasoc-smb.c | 12 ++++++------ drivers/hwtracing/coresight/ultrasoc-smb.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c index ef7f560f0ffa..9ab4aec6955e 100644 --- a/drivers/hwtracing/coresight/ultrasoc-smb.c +++ b/drivers/hwtracing/coresight/ultrasoc-smb.c @@ -98,7 +98,7 @@ static int smb_open(struct inode *inode, struct file *file) struct smb_drv_data *drvdata = container_of(file->private_data, struct smb_drv_data, miscdev); - guard(spinlock)(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); if (drvdata->reading) return -EBUSY; @@ -152,7 +152,7 @@ static int smb_release(struct inode *inode, struct file *file) struct smb_drv_data *drvdata = container_of(file->private_data, struct smb_drv_data, miscdev); - guard(spinlock)(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); drvdata->reading = false; return 0; @@ -245,7 +245,7 @@ static int smb_enable(struct coresight_device *csdev, enum cs_mode mode, struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent); int ret = 0; - guard(spinlock)(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); /* Do nothing, the trace data is reading by other interface now */ if (drvdata->reading) @@ -280,7 +280,7 @@ static int smb_disable(struct coresight_device *csdev) { struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent); - guard(spinlock)(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); if (drvdata->reading) return -EBUSY; @@ -378,7 +378,7 @@ static unsigned long smb_update_buffer(struct coresight_device *csdev, if (!buf) return 0; - guard(spinlock)(&drvdata->spinlock); + guard(raw_spinlock)(&drvdata->spinlock); /* Don't do anything if another tracer is using this sink. */ if (csdev->refcnt != 1) @@ -563,7 +563,7 @@ static int smb_probe(struct platform_device *pdev) smb_reset_buffer(drvdata); platform_set_drvdata(pdev, drvdata); - spin_lock_init(&drvdata->spinlock); + raw_spin_lock_init(&drvdata->spinlock); drvdata->pid = -1; ret = smb_register_sink(pdev, drvdata); diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.h b/drivers/hwtracing/coresight/ultrasoc-smb.h index a91d39cfccb8..c4c111275627 100644 --- a/drivers/hwtracing/coresight/ultrasoc-smb.h +++ b/drivers/hwtracing/coresight/ultrasoc-smb.h @@ -115,7 +115,7 @@ struct smb_drv_data { struct coresight_device *csdev; struct smb_data_buffer sdb; struct miscdevice miscdev; - spinlock_t spinlock; + raw_spinlock_t spinlock; bool reading; pid_t pid; };