From nobody Fri Sep 25 08:00:10 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 666ED4A4F11 for ; Tue, 15 Sep 2026 11:34:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472097; cv=none; b=gTu1I1Hm/xMz0EgdGMOsEuafol/USQciXE7GSxRiABEGqDhpMOf9zedQkNsQvgK866hu/Q51EF/LCGbCYD5SIwmNFeWlUtz3/Wrav1gPoRpZLkWLqoPORB8EitRTb0XMAFC22e6dDAs7ZLShcLCqYIFOdC2mS4LabQqdI3Dgi0I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472097; c=relaxed/simple; bh=9SznDYuGT8UWvy+LroM0/n7oks7pIldiC5cYN/ie6lc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=H/PjGfFwNHHpo6sRTLCHMRNdpbLXxD0f2tCKr8hJQJQHybzhucquWrNtwB+dgpBmU3DwSsM1nXyWEgKr2AnaypwK7lJVd0TO27m7HDqIeT8e6ra12rbIZRZMiVG++wOcZN4khH/4LrQ/DMfGLo23QupbZSvEddllvaHWLJGKUmo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=EJxeykuK; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="EJxeykuK" 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 5CD9C169E; Tue, 15 Sep 2026 04:34:48 -0700 (PDT) Received: from e129823.arm.com (e129823.arm.com [10.2.213.3]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3AC9C3F86F; Tue, 15 Sep 2026 04:34:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1789472091; bh=9SznDYuGT8UWvy+LroM0/n7oks7pIldiC5cYN/ie6lc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=EJxeykuKGZuefAoOIcnscNFcZbufrNIAnvNt/ygyPFdWqrXkYpB147dLaBlyIUMdC DF4gMURNpzWzMQz8DIE9bsyAgX5oeiujiznZMjNjXzrxsChNJUJqS3AkRwrsnEoK7C +bn3xSqoxgLIBsVaFJ2TSmGLyVEAIYfOP/wkF1/Y= From: Yeoreum Yun Date: Tue, 15 Sep 2026 12:34:36 +0100 Subject: [PATCH v11 1/9] coresight: etm4x: prohibit modifying ss_status and cntr_val while session is enabled Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-separate_etm_cfg_v2-v11-1-d2b258d51747@arm.com> References: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> In-Reply-To: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> To: Mike Leach , James Clark , Leo Yan , Greg Kroah-Hartman , Mathieu Poirier , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev Cc: Suzuki K Poulose , Alexander Shishkin , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Yeoreum Yun X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1606; i=yeoreum.yun@arm.com; h=from:subject:message-id; bh=9SznDYuGT8UWvy+LroM0/n7oks7pIldiC5cYN/ie6lc=; b=owEB7QES/pANAwAKAW3Vw9FaxTEzAcsmYgBqqS1TkdhDSHPwJcx/vmPdcKKHXF1J3vojEq0VJ Av5CLspdxKJAbMEAAEKAB0WIQQtg+CS3QUzuFh1pJ1t1cPRWsUxMwUCaqktUwAKCRBt1cPRWsUx Mw3xDAC2MZUtn9trX+mcrq3sX6onUAcMm+eNJV/vk+uyxqJclKUiPMK5N1Ru8xJJCy06oLvKNyO nQLYyrs3pMj+xtDncgt2YaeKUaPHBDydamhBBvSHeEImhXehkwph1XVXGWywu2PY580EM8681ka hm9MytsXjIc9AZBfXY6Zge0HOdFsDo5ZXwxxAex8ch5TP+AqUkk1OQJUb1hvUfXM5KVTvDHV0Zq GPi/mciXValWE+s4dgBzl4B7DNI+I161WyVk1mqs+XCm8gXIXcjjo3KX5rtGWEKkWYYsqwBnLTV tiEeqO/dUTChORNpnINZjK67p2JXe3ERj16KFpW+d4TplTFHhpXLrSGzLGA0XQShNMUKD4JCC/t xzFp761FweGV2y+9P+2hHQrUDWO8c+KtPxI35w2j3e0hTDMT/8nIAPsb7hBTn+lykszrD9vm63p 7Zfdy6cydalTrkHcYODmCpfcIJsiG4Y5yw3He5KjNPzxDZyx5JAaDDLjrPh8ltsLUuLew= X-Developer-Key: i=yeoreum.yun@arm.com; a=openpgp; fpr=2D83E092DD0533B85875A49D6DD5C3D15AC53133 ss_status and cntr_val are overwritten with the values read from the corresponding registers by etm4_disable_hw() when the session is disabled. This means that any changes to these values made while the session is enabled would be lost when the session is disabled. Therefore, prohibit modifying ss_status and cntr_val while the session is enabled. Signed-off-by: Yeoreum Yun Tested-by: Leo Yan --- drivers/hwtracing/coresight/coresight-etm4x-sysfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/= hwtracing/coresight/coresight-etm4x-sysfs.c index cc6cdd3ae29d5..8d73248b840a6 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -1613,6 +1613,8 @@ static ssize_t cntr_val_store(struct device *dev, return -EINVAL; if (val > ETM_CNTR_MAX_VAL) return -EINVAL; + if (coresight_get_mode(drvdata->csdev)) + return -EBUSY; =20 raw_spin_lock(&drvdata->spinlock); idx =3D config->cntr_idx; @@ -1797,6 +1799,8 @@ static ssize_t sshot_ctrl_store(struct device *dev, =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; + if (coresight_get_mode(drvdata->csdev)) + return -EBUSY; =20 raw_spin_lock(&drvdata->spinlock); idx =3D config->ss_idx; @@ -1847,6 +1851,8 @@ static ssize_t sshot_pe_ctrl_store(struct device *dev, =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; + if (coresight_get_mode(drvdata->csdev)) + return -EBUSY; =20 raw_spin_lock(&drvdata->spinlock); idx =3D config->ss_idx; --=20 2.43.0 From nobody Fri Sep 25 08:00:10 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8841E4A13BE for ; Tue, 15 Sep 2026 11:34:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472098; cv=none; b=n3cYIzTDi8PctRG0/lLRQFrpn+ozAHNhdCq0H4n00qjMDkpLCgLup0budxGk9zgx+cC6yLlpF0pg2D0/OKElBsyuYLddXInh2jcX7O367zIocG2pDdAImwBebLT4pR4gz71HMa0ivBOu0FnTVu61bPqvmKW5FQEa2spu1sIy6Ds= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472098; c=relaxed/simple; bh=OY9M4kkCabp+bV4ooKfCZXYd5uvoGme47JFL/fchmm8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pFW9thJw0L922SgjKp11xEOSYiesVI66+cBdrTNKwJ+83lhznuTCb/Ale8px7PzqDjnRRo3TboZ+vN7JQlbdglFM8qDBCRrCKvykOLp1uSB5ySgBtePDzdjJe+AXYqTGKMHB9VRVcmTKOtI645gTU/X5l6R0yYyEHZwkLfg48xA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=PFL3l9JB; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="PFL3l9JB" 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 5B5D21BD0; Tue, 15 Sep 2026 04:34:50 -0700 (PDT) Received: from e129823.arm.com (e129823.arm.com [10.2.213.3]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3D2AD3F86F; Tue, 15 Sep 2026 04:34:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1789472093; bh=OY9M4kkCabp+bV4ooKfCZXYd5uvoGme47JFL/fchmm8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=PFL3l9JBUgxUIxK2x05P+HdgTK88s1Tfe5qipYp9uXSOuU0fXAOKOrBrZBEIfkoYU IYAbT1gL1IHrNUncP5pQgoj7TaQrepwRUyYa5nUU0B2MeuzLBke03UWQXzre+jrcqS /POJl+B7DLSnizqbHN2UqmRA5W1/n+oYwNhPRutI= From: Yeoreum Yun Date: Tue, 15 Sep 2026 12:34:37 +0100 Subject: [PATCH v11 2/9] coresight: etm3x: prohibit modifying cntr_val and reset while session is enabled Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-separate_etm_cfg_v2-v11-2-d2b258d51747@arm.com> References: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> In-Reply-To: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> To: Mike Leach , James Clark , Leo Yan , Greg Kroah-Hartman , Mathieu Poirier , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev Cc: Suzuki K Poulose , Alexander Shishkin , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Yeoreum Yun X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1369; i=yeoreum.yun@arm.com; h=from:subject:message-id; bh=OY9M4kkCabp+bV4ooKfCZXYd5uvoGme47JFL/fchmm8=; b=owEB7QES/pANAwAKAW3Vw9FaxTEzAcsmYgBqqS1TmYIRhSMz5EhthjcSwJUaxwuP8BpyV1qsT UcrhEL1dwaJAbMEAAEKAB0WIQQtg+CS3QUzuFh1pJ1t1cPRWsUxMwUCaqktUwAKCRBt1cPRWsUx MzeNDAC7pg2DnobJUGrqYeiX7Jh3wLOoJOfPfXcMFQ6ikhLAt+4WFTQI/IpZouq+NTJXtAb6KZU B7sAyTKTyBpN0KfTsjozkMko6ZUgc7k97C+l/rYSdFf0Q214QI8QlQUMKslSiaWeCGWv1uk9cjD ZrPDmdRQKDOJzy7cwYWQTWuaR3fO4BNa0Gv4fYMaTfmrfCWaXQpY1ewGkcZyTioRUEcT3aKU0J6 QincnIEvrKBxXPErZA72fbOuMtJHnieyAjRlvpQWm5lWjUIAm4tDXRaJtY2qLn1Qmmdgypjv41G MtWWPPsPTgJRyfTzEAAIeaVIEeg/8MC+KSaCMFXQtd51OdHSlHPr8tZ5OW1N0DpY7BjHOcadCO7 vL6AOfh1egSer4UoD9eRcyehAXXqUFzUfbXef30MKxuBAFLtaTJCLeFR8ifE1vFSzVZYbnaoj1B pz+7bB6Kr2VVI8ZmId5ef113VnfGdMkzFByoGrZ0ywTsBbFc92ZYnbzTwRcbJSAw826gM= X-Developer-Key: i=yeoreum.yun@arm.com; a=openpgp; fpr=2D83E092DD0533B85875A49D6DD5C3D15AC53133 cntr_val are overwritten with the values read from the corresponding registers by etm_disable_hw() when the session is disabled. This means that any changes to this value made while the session is enabled would be lost when the session is disabled. Also, reset shouldn't be called while session is enabled. Therefore, prohibit modifying cntr_val and reset while the session is enabl= ed. Signed-off-by: Yeoreum Yun Reviewed-by: Mike Leach Tested-by: Leo Yan --- drivers/hwtracing/coresight/coresight-etm3x-sysfs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/= hwtracing/coresight/coresight-etm3x-sysfs.c index b3c67e96a82a4..d4846d6364945 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c @@ -74,6 +74,8 @@ static ssize_t reset_store(struct device *dev, ret =3D kstrtoul(buf, 16, &val); if (ret) return ret; + if (coresight_get_mode(drvdata->csdev)) + return -EBUSY; =20 if (val) { spin_lock(&drvdata->spinlock); @@ -744,6 +746,8 @@ static ssize_t cntr_val_store(struct device *dev, ret =3D kstrtoul(buf, 16, &val); if (ret) return ret; + if (coresight_get_mode(drvdata->csdev)) + return -EBUSY; =20 spin_lock(&drvdata->spinlock); config->cntr_val[config->cntr_idx] =3D val; --=20 2.43.0 From nobody Fri Sep 25 08:00:10 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CE6EF4C7538 for ; Tue, 15 Sep 2026 11:34:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472101; cv=none; b=bytCgm1qicLfU/D/9Pyhe7nNrPhqwjjYPW/QI85S1jvAlsXSc3OtYTOBOh7Hx3nxbFgpbwH1HbWOAy42zJy/0XhcDl1X6Cz5UN0qLz/l2+bVG5KD5xnJNt08hkBhCIhcyCY6h60CiP30u8wlR/6bpEnGPnOPTWgU16GUOdkc2uc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472101; c=relaxed/simple; bh=HFYTQP323JtBTvg1BVTZADAyiBCtU9wB5UWOCz0TQ2k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gduY/j944fdY8IvtwEvW+5FRJkKWIX14ZiwjYKIaEzRL6/wBkeZK6Co4ymW95K6DJQptxRCSDtUEgBTa1wHKkPAImp9vKAYxeUlDfNX2AI+GkMb+AH0j7ukoO/vw3wrMUN7wnS9KuG4VMlwgBTnNwbaL1ixzIDpa4Hr7hZUaBvo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=a/7x0Vwt; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="a/7x0Vwt" 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 7811B153B; Tue, 15 Sep 2026 04:34:52 -0700 (PDT) Received: from e129823.arm.com (e129823.arm.com [10.2.213.3]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3E2F73F86F; Tue, 15 Sep 2026 04:34:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1789472096; bh=HFYTQP323JtBTvg1BVTZADAyiBCtU9wB5UWOCz0TQ2k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=a/7x0Vwthruy45AieNT2n99DxaxySUvBlEjTKzW6MCv59nYS5CXnUNlZ1kdNy9vlp tZrDeOWZQ+ArC2eCJOeeuUao2V7e+c7HDMAdVbIEW48edOVNFUVMisrbh8z7cdkEJi BMhTvgx+SAiDmvIgwJ9+WueaWOq19LcGKYkIz7qU= From: Yeoreum Yun Date: Tue, 15 Sep 2026 12:34:38 +0100 Subject: [PATCH v11 3/9] coresight: etm4x: fix inconsistencies with sysfs configuration Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-separate_etm_cfg_v2-v11-3-d2b258d51747@arm.com> References: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> In-Reply-To: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> To: Mike Leach , James Clark , Leo Yan , Greg Kroah-Hartman , Mathieu Poirier , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev Cc: Suzuki K Poulose , Alexander Shishkin , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Yeoreum Yun X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=18252; i=yeoreum.yun@arm.com; h=from:subject:message-id; bh=HFYTQP323JtBTvg1BVTZADAyiBCtU9wB5UWOCz0TQ2k=; b=owEB7QES/pANAwAKAW3Vw9FaxTEzAcsmYgBqqS1Ui4G31UbZIJdnjmYP/A6ZVc/7zKgzzxNpW uugJKTLLfyJAbMEAAEKAB0WIQQtg+CS3QUzuFh1pJ1t1cPRWsUxMwUCaqktVAAKCRBt1cPRWsUx M/+WC/9fYTudurXyEJ1xVpxxNhu1HCf92B3jxMjAguNcoj+aJu5QXWrTWSsoYYnoPxBxSyxBuHW /76wJdA9EiMlpSCgSoC0F0Lpxtdm142Mon0Yd5vhiEo7uXkxEStHvr4oUZBDgv+8C/rCg/pGfZl M4YVr2yrsx1nv66EeE3BbgwXfyIkT7oHwxyiP4RCYolktdlzDXena8BgJohGR++DMkOZn2LwvYF +uViX0VNaY+GWgRAeieWiWSKp8mGSl0lkF1xnn1JfBsoXCIVqUxX+td5SxCBc/SOBTb6bUDM6M5 DNDiDrgpUJYJkV9HqCrGx4S0JplJxT7Cg1jQ2zLAqEtzS/1FEPaeVhjIx4A7MO3fTXLpkbbS+i2 8KIafa+M07rbQgK9XnlgBYmjh7lgEvhy163cxsDyLUyec/jKJjkdBPvFvXg5G7g79f7srqWJwjS 9bNzW6XqbCGZgnNawf7t3lZTcTntRTQOHe1qgQVz8kztiGgmoXAB0BvvKTMOb7122slzs= X-Developer-Key: i=yeoreum.yun@arm.com; a=openpgp; fpr=2D83E092DD0533B85875A49D6DD5C3D15AC53133 The current ETM4x configuration via sysfs can lead to several inconsistencies: - If the configuration is modified via sysfs while a perf session is active, the running configuration may differ before a sched-out and after a subsequent sched-in. - If a perf session and a sysfs session enable tracing concurrently, the configuration from configfs may become corrupted. - There is a risk of corrupting drvdata->config if a perf session enables tracing while cscfg_csdev_disable_active_config() is being handled in etm4_disable_sysfs(). To resolve these issues, separate the configuration into: - active_config: the configuration applied to the current session - config: the configuration set via sysfs Additionally: - Apply the configuration from configfs after taking the appropriate mode. - Since active_config and related fields are accessed only by the local C= PU in etm4_enable/disable_sysfs_smp_call() (similar to perf enable/disable= ), remove the lock/unlock from the sysfs enable/disable path and startup/dying_cpu except when to access config fields. As the active_config is used for cfg-configfs, etmv4 doesn't need to set its lock for the cfg-configfs since the active_config is proceted by cs_mode otherwise it would make a possible cpu-stall when it get interrupt while setting the sysfs configuration. Therefore, set the drv_spinlock for cfg-configfs as NULL and let the cfg-configfs disable irq without grap drv_spinlock when it is NULL. Fixes: 54ff892b76c6 ("coresight: etm4x: splitting struct etmv4_drvdata") Signed-off-by: Yeoreum Yun Tested-by: Leo Yan --- drivers/hwtracing/coresight/coresight-config.c | 18 ++-- drivers/hwtracing/coresight/coresight-config.h | 22 ++++ drivers/hwtracing/coresight/coresight-etm4x-cfg.c | 13 ++- drivers/hwtracing/coresight/coresight-etm4x-core.c | 118 ++++++++++++-----= ---- .../hwtracing/coresight/coresight-etm4x-sysfs.c | 6 +- drivers/hwtracing/coresight/coresight-etm4x.h | 4 +- 6 files changed, 113 insertions(+), 68 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtra= cing/coresight/coresight-config.c index 4f72ae71b696e..0e296289f286d 100644 --- a/drivers/hwtracing/coresight/coresight-config.c +++ b/drivers/hwtracing/coresight/coresight-config.c @@ -73,13 +73,12 @@ static void cscfg_init_reg_param(struct cscfg_feature_c= sdev *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; =20 - raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags); - for (i =3D 0; i < feat_csdev->nr_regs; i++) - cscfg_set_reg(&feat_csdev->regs_csdev[i]); - raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags); + scoped_guard(feat_csdev_lock, feat_csdev) { + for (i =3D 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; @@ -88,13 +87,12 @@ static int cscfg_set_on_enable(struct cscfg_feature_csd= ev *feat_csdev) /* copy back values from the driver locations referenced in cscfg_reg_csde= v */ static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev) { - unsigned long flags; int i; =20 - raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags); - for (i =3D 0; i < feat_csdev->nr_regs; i++) - cscfg_save_reg(&feat_csdev->regs_csdev[i]); - raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags); + scoped_guard(feat_csdev_lock, feat_csdev) { + for (i =3D 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/hwtra= cing/coresight/coresight-config.h index 90fd937d3bd83..ae6295e308131 100644 --- a/drivers/hwtracing/coresight/coresight-config.h +++ b/drivers/hwtracing/coresight/coresight-config.h @@ -7,6 +7,7 @@ #ifndef _CORESIGHT_CORESIGHT_CONFIG_H #define _CORESIGHT_CORESIGHT_CONFIG_H =20 +#include #include #include =20 @@ -259,4 +260,25 @@ void cscfg_csdev_disable_config(struct cscfg_config_cs= dev *config_csdev); /* reset a feature to default values */ void cscfg_reset_feat(struct cscfg_feature_csdev *feat_csdev); =20 +#define feat_csdev_lock(feat_csdev, flags) \ + do { \ + raw_spinlock_t *__lock =3D feat_csdev->drv_spinlock; \ + typecheck(unsigned long, flags); \ + if (__lock) \ + raw_spin_lock_irqsave(__lock, flags); \ + } while (0) + +#define feat_csdev_unlock(feat_csdev, flags) \ + do { \ + raw_spinlock_t *__lock =3D feat_csdev->drv_spinlock; \ + typecheck(unsigned long, flags); \ + if (__lock) \ + raw_spin_unlock_irqrestore(__lock, flags); \ + } while (0) + +DEFINE_LOCK_GUARD_1(feat_csdev_lock, struct cscfg_feature_csdev, + feat_csdev_lock(_T->lock, _T->flags), + feat_csdev_unlock(_T->lock, _T->flags), + unsigned long flags) + #endif /* _CORESIGHT_CORESIGHT_CONFIG_H */ diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c b/drivers/hw= tracing/coresight/coresight-etm4x-cfg.c index e1a59b4345052..d24f533c623d0 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c @@ -47,7 +47,7 @@ static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *= drvdata, struct cscfg_regval_csdev *reg_csdev, u32 offset) { int err =3D -EINVAL, idx; - struct etmv4_config *drvcfg =3D &drvdata->config; + struct etmv4_config *drvcfg =3D &drvdata->active_config; u32 off_mask; =20 if (((offset >=3D TRCEVENTCTL0R) && (offset <=3D TRCVIPCSSCTLR)) || @@ -154,11 +154,14 @@ static int etm4_cfg_load_feature(struct coresight_dev= ice *csdev, int i =3D 0, err =3D 0; =20 /* - * essential we set the device spinlock - this is used in the generic - * programming routines when copying values into the drvdata structures - * via the pointers setup in etm4_cfg_map_reg_offset(). + * drvdata structure of etm4 for configfs is active_config and + * this active_config is protected with csdev->mode by restricting + * access to active_config after mode changed to PERF or SYSFS. + * + * Therefore, it doesn't need to protected with etmv4_drvdata->spinlock + * to feature applying and set the NULL. */ - feat_csdev->drv_spinlock =3D &drvdata->spinlock; + feat_csdev->drv_spinlock =3D NULL; =20 /* process the register descriptions */ for (i =3D 0; i < feat_csdev->nr_regs && !err; i++) { diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/h= wtracing/coresight/coresight-etm4x-core.c index 2247ad55d4442..2df7f592bb5cf 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -239,6 +239,7 @@ void etm4_release_trace_id(struct etmv4_drvdata *drvdat= a) struct etm4_enable_arg { struct etmv4_drvdata *drvdata; struct coresight_path *path; + struct etmv4_config config; int rc; }; =20 @@ -264,10 +265,11 @@ static void etm4x_prohibit_trace(struct etmv4_drvdata= *drvdata) static u64 etm4x_get_kern_user_filter(struct etmv4_drvdata *drvdata) { u64 trfcr =3D drvdata->trfcr; + struct etmv4_config *config =3D &drvdata->active_config; =20 - if (drvdata->config.mode & ETM_MODE_EXCL_KERN) + if (config->mode & ETM_MODE_EXCL_KERN) trfcr &=3D ~TRFCR_EL1_ExTRE; - if (drvdata->config.mode & ETM_MODE_EXCL_USER) + if (config->mode & ETM_MODE_EXCL_USER) trfcr &=3D ~TRFCR_EL1_E0TRE; =20 return trfcr; @@ -275,7 +277,7 @@ static u64 etm4x_get_kern_user_filter(struct etmv4_drvd= ata *drvdata) =20 /* * etm4x_allow_trace - Allow CPU tracing in the respective ELs, - * as configured by the drvdata->config.mode for the current + * as configured by the drvdata->active_config.mode for the current * session. Even though we have TRCVICTLR bits to filter the * trace in the ELs, it doesn't prevent the ETM from generating * a packet (e.g, TraceInfo) that might contain the addresses from @@ -286,12 +288,13 @@ static u64 etm4x_get_kern_user_filter(struct etmv4_dr= vdata *drvdata) static void etm4x_allow_trace(struct etmv4_drvdata *drvdata) { u64 trfcr, guest_trfcr; + struct etmv4_config *config =3D &drvdata->active_config; =20 /* If the CPU doesn't support FEAT_TRF, nothing to do */ if (!drvdata->trfcr) return; =20 - if (drvdata->config.mode & ETM_MODE_EXCL_HOST) + if (config->mode & ETM_MODE_EXCL_HOST) trfcr =3D drvdata->trfcr & ~(TRFCR_EL1_ExTRE | TRFCR_EL1_E0TRE); else trfcr =3D etm4x_get_kern_user_filter(drvdata); @@ -299,7 +302,7 @@ static void etm4x_allow_trace(struct etmv4_drvdata *drv= data) write_trfcr(trfcr); =20 /* Set filters for guests and pass to KVM */ - if (drvdata->config.mode & ETM_MODE_EXCL_GUEST) + if (config->mode & ETM_MODE_EXCL_GUEST) guest_trfcr =3D drvdata->trfcr & ~(TRFCR_EL1_ExTRE | TRFCR_EL1_E0TRE); else guest_trfcr =3D etm4x_get_kern_user_filter(drvdata); @@ -492,7 +495,7 @@ static int etm4_enable_trace_unit(struct etmv4_drvdata = *drvdata) static int etm4_enable_hw(struct etmv4_drvdata *drvdata) { int i, rc; - struct etmv4_config *config =3D &drvdata->config; + struct etmv4_config *config =3D &drvdata->active_config; struct coresight_device *csdev =3D drvdata->csdev; struct device *etm_dev =3D &csdev->dev; struct csdev_access *csa =3D &csdev->access; @@ -612,27 +615,44 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvda= ta) static void etm4_enable_sysfs_smp_call(void *info) { struct etm4_enable_arg *arg =3D info; + struct etmv4_drvdata *drvdata; struct coresight_device *csdev; + unsigned long cfg_hash; + int preset; =20 if (WARN_ON(!arg)) return; =20 - csdev =3D arg->drvdata->csdev; - if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) { - /* Someone is already using the tracer */ - arg->rc =3D -EBUSY; - return; + drvdata =3D arg->drvdata; + csdev =3D drvdata->csdev; + + drvdata->active_config =3D arg->config; + + /* enable any config activated by configfs */ + cscfg_config_sysfs_get_active_cfg(&cfg_hash, &preset); + if (cfg_hash) { + arg->rc =3D cscfg_csdev_enable_active_config(csdev, + cfg_hash, + preset); + if (arg->rc) + return; } =20 - arg->rc =3D etm4_enable_hw(arg->drvdata); + drvdata->trcid =3D arg->path->trace_id; =20 - /* The tracer didn't start */ + /* Tracer will never be paused in sysfs mode */ + drvdata->paused =3D false; + + arg->rc =3D etm4_enable_hw(drvdata); if (arg->rc) { - coresight_set_mode(csdev, CS_MODE_DISABLED); + cscfg_csdev_disable_active_config(csdev); return; } =20 + drvdata->sticky_enable =3D true; csdev->path =3D arg->path; + + return; } =20 /* @@ -669,7 +689,7 @@ static int etm4_config_timestamp_event(struct etmv4_drv= data *drvdata, { int ctridx; int rselector; - struct etmv4_config *config =3D &drvdata->config; + struct etmv4_config *config =3D &drvdata->active_config; =20 /* No point in trying if we don't have at least one counter */ if (!drvdata->nr_cntr) @@ -752,7 +772,7 @@ static int etm4_parse_event_config(struct coresight_dev= ice *csdev, { int ret =3D 0; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); - struct etmv4_config *config =3D &drvdata->config; + struct etmv4_config *config =3D &drvdata->active_config; struct perf_event_attr max_timestamp =3D { .ATTR_CFG_FLD_timestamp_CFG =3D U64_MAX, }; @@ -919,46 +939,36 @@ static int etm4_enable_sysfs(struct coresight_device = *csdev, struct coresight_pa { struct etmv4_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); struct etm4_enable_arg arg =3D { }; - unsigned long cfg_hash; - int ret, preset; + int ret; =20 - /* enable any config activated by configfs */ - cscfg_config_sysfs_get_active_cfg(&cfg_hash, &preset); - if (cfg_hash) { - ret =3D cscfg_csdev_enable_active_config(csdev, cfg_hash, preset); - if (ret) { - etm4_release_trace_id(drvdata); - return ret; - } + if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) { + /* Someone is already using the tracer */ + return -EBUSY; } =20 - raw_spin_lock(&drvdata->spinlock); - - drvdata->trcid =3D path->trace_id; - - /* Tracer will never be paused in sysfs mode */ - drvdata->paused =3D false; - /* * Executing etm4_enable_hw on the cpu whose ETM is being enabled * ensures that register writes occur when cpu is powered. */ arg.drvdata =3D drvdata; arg.path =3D path; + + scoped_guard(raw_spinlock, &drvdata->spinlock) { + arg.config =3D drvdata->config; + } + ret =3D smp_call_function_single(drvdata->cpu, etm4_enable_sysfs_smp_call, &arg, 1); if (!ret) ret =3D arg.rc; - if (!ret) - drvdata->sticky_enable =3D true; - - if (ret) + if (!ret) { + dev_dbg(&csdev->dev, "ETM tracing enabled\n"); + } else { etm4_release_trace_id(drvdata); + /* The tracer didn't start */ + coresight_set_mode(csdev, CS_MODE_DISABLED); + } =20 - raw_spin_unlock(&drvdata->spinlock); - - if (!ret) - dev_dbg(&csdev->dev, "ETM tracing enabled\n"); return ret; } =20 @@ -1044,7 +1054,7 @@ static void etm4_disable_trace_unit(struct etmv4_drvd= ata *drvdata) static void etm4_disable_hw(struct etmv4_drvdata *drvdata) { u32 control; - struct etmv4_config *config =3D &drvdata->config; + struct etmv4_config *config =3D &drvdata->active_config; struct coresight_device *csdev =3D drvdata->csdev; struct csdev_access *csa =3D &csdev->access; int i; @@ -1086,8 +1096,9 @@ static void etm4_disable_sysfs_smp_call(void *info) =20 etm4_disable_hw(drvdata); =20 + cscfg_csdev_disable_active_config(drvdata->csdev); + drvdata->csdev->path =3D NULL; - coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); } =20 static int etm4_disable_perf(struct coresight_device *csdev, @@ -1130,8 +1141,9 @@ static int etm4_disable_perf(struct coresight_device = *csdev, static void etm4_disable_sysfs(struct coresight_device *csdev) { struct etmv4_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); - - raw_spin_lock(&drvdata->spinlock); + struct etmv4_config *config =3D &drvdata->config; + const struct etmv4_config *active_config =3D &drvdata->active_config; + int i; =20 /* * Executing etm4_disable_hw on the cpu whose ETM is being disabled @@ -1140,9 +1152,17 @@ static void etm4_disable_sysfs(struct coresight_devi= ce *csdev) smp_call_function_single(drvdata->cpu, etm4_disable_sysfs_smp_call, drvdata, 1); =20 - raw_spin_unlock(&drvdata->spinlock); + /* + * Userspace may read ss_status and cntr_val through sysfs after + * the sysfs-session has been disabled. + */ + for (i =3D 0; i < drvdata->nr_ss_cmp; i++) + config->ss_status[i] =3D active_config->ss_status[i]; =20 - cscfg_csdev_disable_active_config(csdev); + for (i =3D 0; i < drvdata->nr_cntr; i++) + config->cntr_val[i] =3D active_config->cntr_val[i]; + + coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); =20 /* * we only release trace IDs when resetting sysfs. @@ -1690,7 +1710,7 @@ static void etm4_set_default(struct etmv4_config *con= fig) static int etm4_get_next_comparator(struct etmv4_drvdata *drvdata, u32 typ= e) { int nr_comparator, index =3D 0; - struct etmv4_config *config =3D &drvdata->config; + struct etmv4_config *config =3D &drvdata->active_config; =20 /* * nr_addr_cmp holds the number of comparator _pair_, so time 2 @@ -1731,7 +1751,7 @@ static int etm4_set_event_filters(struct etmv4_drvdat= a *drvdata, { int i, comparator, ret =3D 0; u64 address; - struct etmv4_config *config =3D &drvdata->config; + struct etmv4_config *config =3D &drvdata->active_config; struct etm_filters *filters =3D event->hw.addr_filters; =20 if (!filters) diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/= hwtracing/coresight/coresight-etm4x-sysfs.c index 8d73248b840a6..f64c0acebc701 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -1613,7 +1613,7 @@ static ssize_t cntr_val_store(struct device *dev, return -EINVAL; if (val > ETM_CNTR_MAX_VAL) return -EINVAL; - if (coresight_get_mode(drvdata->csdev)) + if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_SYSFS) return -EBUSY; =20 raw_spin_lock(&drvdata->spinlock); @@ -1799,7 +1799,7 @@ static ssize_t sshot_ctrl_store(struct device *dev, =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (coresight_get_mode(drvdata->csdev)) + if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_SYSFS) return -EBUSY; =20 raw_spin_lock(&drvdata->spinlock); @@ -1851,7 +1851,7 @@ static ssize_t sshot_pe_ctrl_store(struct device *dev, =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (coresight_get_mode(drvdata->csdev)) + if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_SYSFS) return -EBUSY; =20 raw_spin_lock(&drvdata->spinlock); diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtrac= ing/coresight/coresight-etm4x.h index df9e0748d71ec..c33700711154d 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -1019,7 +1019,8 @@ struct etmv4_save_state { * allows tracing at all ELs. We don't want to compute this * at runtime, due to the additional setting of TRFCR_CX when * in EL2. Otherwise, 0. - * @config: structure holding configuration parameters. + * @active_config: structure holding current applied configuration. + * @config: structure holding sysfs mode configuration. * @save_state: State to be preserved across power loss * @skip_power_up: Indicates if an implementation can skip powering up * the trace unit. @@ -1077,6 +1078,7 @@ struct etmv4_drvdata { bool skip_power_up : 1; bool paused : 1; u64 trfcr; + struct etmv4_config active_config; struct etmv4_config config; struct etmv4_save_state *save_state; DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX); --=20 2.43.0 From nobody Fri Sep 25 08:00:10 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 74D794C77CE for ; Tue, 15 Sep 2026 11:35:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472107; cv=none; b=KtwH8NTZ9pTgV5P69tix07KLHu+6eKTpFGMo/q+H2+PY15EW4eMintN6Srr4hBhYd87kfJd7wM/nlgSfUpkhYmPwBNpCYHJdclAcxC2HB3OWCqJ1V7g//a+RzTJfxLObTAABi6T1G+Mu/UxPnnAmP8AkasimFegb8ik8KKwVYH0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472107; c=relaxed/simple; bh=e0rclFqMC0eAmxpUWaIU2Q1JqHHqdj9jdGG9lzmKhpw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eyD2KxRvNpBkBeHswx4rkx6zxY+JlKSjGgjZcGWuj7mwW7+IUtaWZQvFVZOskeylFVGt08BGV0ENTjGbs2oOV3PlhAnjilwZe1tPttArpzh5kHiXb2sSq1mSHs1ASD7LCdP7Dqtc3Of+1EpnkGcKe/bCR2r+odoERHH0c8QiH7E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=L4PTubeP; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="L4PTubeP" 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 7AEE9169E; Tue, 15 Sep 2026 04:34:54 -0700 (PDT) Received: from e129823.arm.com (e129823.arm.com [10.2.213.3]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 5889F3F86F; Tue, 15 Sep 2026 04:34:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1789472098; bh=e0rclFqMC0eAmxpUWaIU2Q1JqHHqdj9jdGG9lzmKhpw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=L4PTubePCr9JPAdADoVQuxyO1CBj0prkCgSgoG9cAboSS9xnvJjCi8gWMEHCIsPD7 OfeLyNuh/P9NL+QOvKnhz7lpD6SD3R+NFZVSpkNgT8m71nzYXDdF5S6w8o+KAi/fDo dvLqtE6ofKi4JVBfJNNSLduNxfkOYhKXrcrs9frg= From: Yeoreum Yun Date: Tue, 15 Sep 2026 12:34:39 +0100 Subject: [PATCH v11 4/9] coresight: etm3x: fix inconsistencies with sysfs configuration Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-separate_etm_cfg_v2-v11-4-d2b258d51747@arm.com> References: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> In-Reply-To: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> To: Mike Leach , James Clark , Leo Yan , Greg Kroah-Hartman , Mathieu Poirier , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev Cc: Suzuki K Poulose , Alexander Shishkin , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Yeoreum Yun X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=11685; i=yeoreum.yun@arm.com; h=from:subject:message-id; bh=e0rclFqMC0eAmxpUWaIU2Q1JqHHqdj9jdGG9lzmKhpw=; b=owEB7QES/pANAwAKAW3Vw9FaxTEzAcsmYgBqqS1Uc2TxvZc8KYfEMM/S5lHKT39Oe4w67Yy34 TF7zAtVBQyJAbMEAAEKAB0WIQQtg+CS3QUzuFh1pJ1t1cPRWsUxMwUCaqktVAAKCRBt1cPRWsUx M5b/DACopfpIlq30vG/jViSDbt0NtmxfgYWF05bbaDGR6Ay61xmxG7LlE5WTxW1DLBdSeZPFw2r 9WNIdj+h/0zEfRYRVTkq2swTx+c8aXDY9SGuPGoefc4GS9krw3VvfXSkKkq3PyOjxcSezYd2tNY bkU6aq1MVvhXoikukBjvkqtm6HPQMER/0zFkE+GeDWU7qnZdf8IktbyLdR/5aHo6hAAeAKKJX7p q1O0kI48h1+ELh8sultqg1NkgvfCZJ/QxOqN7xfqGjIafyCgJRqg9Ar2d0r7PiNVHFK1cpEM+Ni rLJxx7tkefHpl3viZjmpHHFmAGecYwM3s7to+er3jgCUfl+bERyJHvYqBLWBVySmRLCsE9FeLUG 03THX3eocYPmRZKUNO4lI/TfWteEsss/mC+SLVEk6ZOlBq+rGo8Zed2f7SMXMvIMc6lgPew/nul ASdE9TrO0hOHz+isD2s9no2qjtnFfM0h7bPGuU745JSvA5yfG9IUVMKMWrAaL7VonvJ14= X-Developer-Key: i=yeoreum.yun@arm.com; a=openpgp; fpr=2D83E092DD0533B85875A49D6DD5C3D15AC53133 The current ETM3x configuration via sysfs can lead to the following inconsistencies: - If a configuration is modified via sysfs while a perf session is active, the running configuration may differ between before a sched-out and after a subsequent sched-in. To resolve these issues, separate the configuration into: - active_config: the configuration applied to the current session - config: the configuration set via sysfs Additionally: - Since active_config and related fields are accessed only by the local C= PU in etm_enable/disable_sysfs_smp_call() (similar to perf enable/disable), remove the lock/unlock from the sysfs enable/disable path and starting/dying_cpu path except when to access config fields only. - Some of sysfs interface read etm register directly. To reduce lock scope while the etm_enable_hw()/etm_disable_hw(), handle it via IPI so that registers could be read from on proper CPU. Fixes: 1925a470ce69 ("coresight: etm3x: splitting struct etm_drvdata") Signed-off-by: Yeoreum Yun Tested-by: Leo Yan --- drivers/hwtracing/coresight/coresight-etm.h | 4 +- drivers/hwtracing/coresight/coresight-etm3x-core.c | 68 ++++++++++-------- .../hwtracing/coresight/coresight-etm3x-sysfs.c | 80 +++++++++++++++---= ---- 3 files changed, 100 insertions(+), 52 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracin= g/coresight/coresight-etm.h index 1d753cca29439..f3796162168d4 100644 --- a/drivers/hwtracing/coresight/coresight-etm.h +++ b/drivers/hwtracing/coresight/coresight-etm.h @@ -226,7 +226,8 @@ struct etm_config { * @etmccr: value of register ETMCCR. * @etmccer: value of register ETMCCER. * @traceid: value of the current ID for this component. - * @config: structure holding configuration parameters. + * @active_config: structure holding current running configuration. + * @config: structure holding sysfs mode configuration. */ struct etm_drvdata { struct csdev_access csa; @@ -248,6 +249,7 @@ struct etm_drvdata { u32 etmccr; u32 etmccer; u32 traceid; + struct etm_config active_config; struct etm_config config; }; =20 diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/h= wtracing/coresight/coresight-etm3x-core.c index 862ad0786699c..fd76a57e5f861 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c @@ -308,7 +308,7 @@ void etm_config_trace_mode(struct etm_config *config) static int etm_parse_event_config(struct etm_drvdata *drvdata, struct perf_event *event) { - struct etm_config *config =3D &drvdata->config; + struct etm_config *config =3D &drvdata->active_config; struct perf_event_attr *attr =3D &event->attr; u8 ts_level; =20 @@ -367,7 +367,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) { int i, rc; u32 etmcr; - struct etm_config *config =3D &drvdata->config; + struct etm_config *config =3D &drvdata->active_config; struct coresight_device *csdev =3D drvdata->csdev; =20 CS_UNLOCK(drvdata->csa.base); @@ -442,32 +442,30 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) struct etm_enable_arg { struct etm_drvdata *drvdata; struct coresight_path *path; + struct etm_config config; int rc; }; =20 static void etm_enable_sysfs_smp_call(void *info) { struct etm_enable_arg *arg =3D info; + struct etm_drvdata *drvdata; struct coresight_device *csdev; =20 if (WARN_ON(!arg)) return; =20 - csdev =3D arg->drvdata->csdev; - if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) { - /* Someone is already using the tracer */ - arg->rc =3D -EBUSY; - return; - } + drvdata =3D arg->drvdata; + csdev =3D drvdata->csdev; =20 - arg->rc =3D etm_enable_hw(arg->drvdata); + drvdata->active_config =3D arg->config; + drvdata->traceid =3D arg->path->trace_id; =20 - /* The tracer didn't start */ - if (arg->rc) { - coresight_set_mode(csdev, CS_MODE_DISABLED); + arg->rc =3D etm_enable_hw(arg->drvdata); + if (arg->rc) return; - } =20 + drvdata->sticky_enable =3D true; csdev->path =3D arg->path; } =20 @@ -512,9 +510,10 @@ static int etm_enable_sysfs(struct coresight_device *c= sdev, struct coresight_pat struct etm_enable_arg arg =3D { }; int ret; =20 - spin_lock(&drvdata->spinlock); - - drvdata->traceid =3D path->trace_id; + if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) { + /* Someone is already using the tracer */ + return -EBUSY; + } =20 /* * Configure the ETM only if the CPU is online. If it isn't online @@ -523,23 +522,27 @@ static int etm_enable_sysfs(struct coresight_device *= csdev, struct coresight_pat if (cpu_online(drvdata->cpu)) { arg.drvdata =3D drvdata; arg.path =3D path; + + scoped_guard(spinlock, &drvdata->spinlock) { + arg.config =3D drvdata->config; + } + ret =3D smp_call_function_single(drvdata->cpu, etm_enable_sysfs_smp_call, &arg, 1); if (!ret) ret =3D arg.rc; - if (!ret) - drvdata->sticky_enable =3D true; } else { ret =3D -ENODEV; } =20 - if (ret) + if (!ret) { + dev_dbg(&csdev->dev, "ETM tracing enabled\n"); + } else { etm_release_trace_id(drvdata); + /* The tracer didn't start */ + coresight_set_mode(csdev, CS_MODE_DISABLED); + } =20 - spin_unlock(&drvdata->spinlock); - - if (!ret) - dev_dbg(&csdev->dev, "ETM tracing enabled\n"); return ret; } =20 @@ -565,7 +568,7 @@ static int etm_enable(struct coresight_device *csdev, s= truct perf_event *event, static void etm_disable_hw(struct etm_drvdata *drvdata) { int i; - struct etm_config *config =3D &drvdata->config; + struct etm_config *config =3D &drvdata->active_config; struct coresight_device *csdev =3D drvdata->csdev; =20 CS_UNLOCK(drvdata->csa.base); @@ -593,7 +596,6 @@ static void etm_disable_sysfs_smp_call(void *info) etm_disable_hw(drvdata); =20 drvdata->csdev->path =3D NULL; - coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); } =20 static void etm_disable_perf(struct coresight_device *csdev) @@ -630,8 +632,9 @@ static void etm_disable_perf(struct coresight_device *c= sdev) static void etm_disable_sysfs(struct coresight_device *csdev) { struct etm_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); - - spin_lock(&drvdata->spinlock); + struct etm_config *config =3D &drvdata->config; + const struct etm_config *active_config =3D &drvdata->active_config; + int i; =20 /* * Executing etm_disable_hw on the cpu whose ETM is being disabled @@ -640,7 +643,14 @@ static void etm_disable_sysfs(struct coresight_device = *csdev) smp_call_function_single(drvdata->cpu, etm_disable_sysfs_smp_call, drvdata, 1); =20 - spin_unlock(&drvdata->spinlock); + /* + * Userspace may read seq_curr_state and cntr_val through sysfs + * after the sysfs-session has been disabled. + */ + for (i =3D 0; i < drvdata->nr_cntr; i++) + config->cntr_val[i] =3D active_config->cntr_val[i]; + + config->seq_curr_state =3D active_config->seq_curr_state; =20 /* * we only release trace IDs when resetting sysfs. @@ -649,6 +659,8 @@ static void etm_disable_sysfs(struct coresight_device *= csdev) * prior trace id allocation method */ =20 + coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); + dev_dbg(&csdev->dev, "ETM tracing disabled\n"); } =20 diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/= hwtracing/coresight/coresight-etm3x-sysfs.c index d4846d6364945..2c8c129228589 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c @@ -6,10 +6,48 @@ =20 #include #include +#include #include #include "coresight-etm.h" #include "coresight-priv.h" =20 +struct etm_readl_cslocked_arg { + struct etm_drvdata *drvdata; + u32 off; + unsigned long *val; +}; + +static void etm_readl_cslocked_smp_call(void *info) +{ + struct etm_readl_cslocked_arg *arg =3D info; + + CS_UNLOCK(arg->drvdata->csa.base); + *arg->val =3D etm_readl(arg->drvdata, arg->off); + CS_LOCK(arg->drvdata->csa.base); +} + +static int etm_readl_cslocked(struct etm_drvdata *drvdata, u32 off, + unsigned long *val) +{ + int ret; + struct etm_readl_cslocked_arg arg; + + ret =3D pm_runtime_get_sync(drvdata->csdev->dev.parent); + if (ret < 0) + goto out; + + arg.drvdata =3D drvdata; + arg.off =3D off; + arg.val =3D val; + + ret =3D smp_call_function_single(drvdata->cpu, + etm_readl_cslocked_smp_call, + (void *)&arg, 1); +out: + pm_runtime_put(drvdata->csdev->dev.parent); + return ret; +} + static ssize_t nr_addr_cmp_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -45,18 +83,13 @@ static DEVICE_ATTR_RO(nr_ctxid_cmp); static ssize_t etmsr_show(struct device *dev, struct device_attribute *attr, char *buf) { - unsigned long flags, val; + int ret; + unsigned long val; struct etm_drvdata *drvdata =3D dev_get_drvdata(dev->parent); =20 - pm_runtime_get_sync(dev->parent); - spin_lock_irqsave(&drvdata->spinlock, flags); - CS_UNLOCK(drvdata->csa.base); - - val =3D etm_readl(drvdata, ETMSR); - - CS_LOCK(drvdata->csa.base); - spin_unlock_irqrestore(&drvdata->spinlock, flags); - pm_runtime_put(dev->parent); + ret =3D etm_readl_cslocked(drvdata, ETMSR, &val); + if (ret) + return ret; =20 return sprintf(buf, "%#lx\n", val); } @@ -74,7 +107,7 @@ static ssize_t reset_store(struct device *dev, ret =3D kstrtoul(buf, 16, &val); if (ret) return ret; - if (coresight_get_mode(drvdata->csdev)) + if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_SYSFS) return -EBUSY; =20 if (val) { @@ -719,7 +752,9 @@ static DEVICE_ATTR_RW(cntr_rld_event); static ssize_t cntr_val_show(struct device *dev, struct device_attribute *attr, char *buf) { + int ret; u32 val; + unsigned long val2; struct etm_drvdata *drvdata =3D dev_get_drvdata(dev->parent); struct etm_config *config =3D &drvdata->config; =20 @@ -728,7 +763,10 @@ static ssize_t cntr_val_show(struct device *dev, val =3D config->cntr_val[config->cntr_idx]; spin_unlock(&drvdata->spinlock); } else { - val =3D etm_readl(drvdata, ETMCNTVRn(config->cntr_idx)); + ret =3D etm_readl_cslocked(drvdata, ETMCNTVRn(config->cntr_idx), &val2); + if (ret) + return ret; + val =3D val2; } =20 return sysfs_emit(buf, "%#x\n", val); @@ -746,7 +784,7 @@ static ssize_t cntr_val_store(struct device *dev, ret =3D kstrtoul(buf, 16, &val); if (ret) return ret; - if (coresight_get_mode(drvdata->csdev)) + if (coresight_get_mode(drvdata->csdev) =3D=3D CS_MODE_SYSFS) return -EBUSY; =20 spin_lock(&drvdata->spinlock); @@ -934,7 +972,8 @@ static DEVICE_ATTR_RW(seq_13_event); static ssize_t seq_curr_state_show(struct device *dev, struct device_attribute *attr, char *buf) { - unsigned long val, flags; + int ret; + unsigned long val; struct etm_drvdata *drvdata =3D dev_get_drvdata(dev->parent); struct etm_config *config =3D &drvdata->config; =20 @@ -943,15 +982,10 @@ static ssize_t seq_curr_state_show(struct device *dev, goto out; } =20 - pm_runtime_get_sync(dev->parent); - spin_lock_irqsave(&drvdata->spinlock, flags); - - CS_UNLOCK(drvdata->csa.base); - val =3D (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK); - CS_LOCK(drvdata->csa.base); - - spin_unlock_irqrestore(&drvdata->spinlock, flags); - pm_runtime_put(dev->parent); + ret =3D etm_readl_cslocked(drvdata, ETMSQR, &val); + if (ret) + return ret; + val &=3D ETM_SQR_MASK; out: return sprintf(buf, "%#lx\n", val); } --=20 2.43.0 From nobody Fri Sep 25 08:00:10 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CD28A4C8C4D for ; Tue, 15 Sep 2026 11:35:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472109; cv=none; b=jPU9S6Nm20V5UBwl3xONYB2mr9KdLqZIxetppJMlvGzX+iLmAqffo69o3llXLhlOwpG1/ahhyfHI4vSVU8pCTQtWWgyAIU9u5plXThlrFAyXuFbPqXexeJtDIedz5tjYS9XBBLrRtAxC//P5cTqCE8MYAY1vI+B2irE2UPYEuxk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472109; c=relaxed/simple; bh=Duw0rbqzZc0OG8KYw+ZvnTS3Mf0PkCHjPT/8/o374fg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HwGaZ/PkqVK5FbMtdWfvr5p1n4T4JPGOVzabeINSIG8Ylwf6Xhiuhygp2TIE30oscFug+Z9kA1tEPs2vuFKttGW5F8lfdOk2rdnXDIQSpIWXgXSHA8ULhi0xQNT+isUF4H+6YpY89I2R+VplCvCzitTYx3NLuXJg8usitS+/8No= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=ubQaglxN; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="ubQaglxN" 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 79B321764; Tue, 15 Sep 2026 04:34:56 -0700 (PDT) Received: from e129823.arm.com (e129823.arm.com [10.2.213.3]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 5A0013F86F; Tue, 15 Sep 2026 04:34:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1789472100; bh=Duw0rbqzZc0OG8KYw+ZvnTS3Mf0PkCHjPT/8/o374fg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ubQaglxNXq4qNU8MsaS0WgAY7sdhdrjBgFc54fGQ0OrluhnLKBaWrylQfo/jiFnOj noaCyq0eRwTI7ktPwU2JZ+dbAYLSiiB1p6qza0czBveoqQT4okS0EUFt91E/3RQ4XE O4L7lbnZvkOXwlA4PMkk+LR5hSGdRkrLz5W8pcMg= From: Yeoreum Yun Date: Tue, 15 Sep 2026 12:34:40 +0100 Subject: [PATCH v11 5/9] coresight: etm3x: remove redundant cpu online check on etm_enable_sysfs() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-separate_etm_cfg_v2-v11-5-d2b258d51747@arm.com> References: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> In-Reply-To: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> To: Mike Leach , James Clark , Leo Yan , Greg Kroah-Hartman , Mathieu Poirier , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev Cc: Suzuki K Poulose , Alexander Shishkin , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Yeoreum Yun X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1656; i=yeoreum.yun@arm.com; h=from:subject:message-id; bh=Duw0rbqzZc0OG8KYw+ZvnTS3Mf0PkCHjPT/8/o374fg=; b=owEB7QES/pANAwAKAW3Vw9FaxTEzAcsmYgBqqS1VxtLGhlN+N1BuP+VZSI9LLtuZwzXMSFhzD cJm06wmiq+JAbMEAAEKAB0WIQQtg+CS3QUzuFh1pJ1t1cPRWsUxMwUCaqktVQAKCRBt1cPRWsUx M5oHC/4obvV3deG87NX18PbEDGugKhTfIn9gqv6fz9NhXM6HyIrjXjD4DVK5XxGFiK2eVM7oaGi eEa/pbQCBgm2S+CPk8T1XIS6+vOB3BHyVJ6OTbkBdqotTI9HQPm8DJdZb/j7kVJSwFYuuitU2dJ m7ZRUbgW7EUFDcPi1w+x6kgeP46rumS88EmFqFx5j55B4QebBdzrRTsfpchABb7WCz1seXzMIN4 zKnTnPOyxkVfTAlztZYbnIZ0Afn+DnEdG1t7rvAbRw7I+KgN6oMmRx3YnyXoe+HiT1hLg6P0DWZ Pu86gmKAp9GHYZcyf5XCwqR31IbloZvfF90Lm1hche/se+SGXnmlGRQGImUfA+Uc8k5kD2prFW+ 8kyenPOI1xeDXrsLwDQ9ngwKpTQFswEoB+Xj7Ccv1AYRJhcnLiWPnqGOT9hGvUuvz/j0vDrurXW nMqI9GZ3PoqkzKRX0eDL9QncIxTm/jlioe1ChJVwykjqsDhc7Wy6vYcwv2HNI41Eku+TA= X-Developer-Key: i=yeoreum.yun@arm.com; a=openpgp; fpr=2D83E092DD0533B85875A49D6DD5C3D15AC53133 cpu online() check is done in coresight_validate_source_sysfs() already. and smp_call_function_single() will fail when cpu is offline. Therefore, remove redundant check in etm_enable_sysfs(). Signed-off-by: Yeoreum Yun Reviewed-by: Mike Leach Tested-by: Leo Yan --- drivers/hwtracing/coresight/coresight-etm3x-core.c | 26 +++++++++---------= ---- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/h= wtracing/coresight/coresight-etm3x-core.c index fd76a57e5f861..12bb38dc596e7 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c @@ -515,25 +515,19 @@ static int etm_enable_sysfs(struct coresight_device *= csdev, struct coresight_pat return -EBUSY; } =20 - /* - * Configure the ETM only if the CPU is online. If it isn't online - * hw configuration will take place on the local CPU during bring up. - */ - if (cpu_online(drvdata->cpu)) { - arg.drvdata =3D drvdata; - arg.path =3D path; + arg.drvdata =3D drvdata; + arg.path =3D path; =20 - scoped_guard(spinlock, &drvdata->spinlock) { - arg.config =3D drvdata->config; - } + scoped_guard(spinlock, &drvdata->spinlock) { + arg.config =3D drvdata->config; + } =20 - ret =3D smp_call_function_single(drvdata->cpu, - etm_enable_sysfs_smp_call, &arg, 1); - if (!ret) - ret =3D arg.rc; - } else { + ret =3D smp_call_function_single(drvdata->cpu, + etm_enable_sysfs_smp_call, &arg, 1); + if (!ret) + ret =3D arg.rc; + else ret =3D -ENODEV; - } =20 if (!ret) { dev_dbg(&csdev->dev, "ETM tracing enabled\n"); --=20 2.43.0 From nobody Fri Sep 25 08:00:10 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9E40C4A5C4C for ; Tue, 15 Sep 2026 11:35:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472114; cv=none; b=Kof8Y64LkNS/+QeN3a7YTlTPk7rC65KzMW0T1Wv/hGulGelC3k6wyW4zJJ6lWIOcetutWZ+oCZE15oRZ//NoZuD8SxyFZviN+AYyRRGzHEF/sE/t4moBTLi6KEQORZClNI+zrkm9v7sEFaPJZXVjEo61ajykzMdcMHH3ZFTDzFs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472114; c=relaxed/simple; bh=A9FwRVgDfZlBo+vhdOUfqu4L6MqVlpNBTjdp7Iq5FSU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hMYS0vT7XX9VzlczWxcsGE8p9BysBVKI7KwudjyASIU6+t6WCuUWyajlaeuqcM05Q8ZsisLIL64prOv/a/tiWu+R/fU25O4rmpuXwes1Oj1BUdFi8rFJCf8UZWEwpAKmlZ8pRpr9+jwPHuPGXXhFH+juh2Eo729OrQDI0d6w/qo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=FpBiFx4g; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="FpBiFx4g" 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 9230D153B; Tue, 15 Sep 2026 04:34:58 -0700 (PDT) Received: from e129823.arm.com (e129823.arm.com [10.2.213.3]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 5C3FC3F86F; Tue, 15 Sep 2026 04:35:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1789472102; bh=A9FwRVgDfZlBo+vhdOUfqu4L6MqVlpNBTjdp7Iq5FSU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=FpBiFx4gvp/BIu+RM2kLC3JrzNQSC/KdKf5ffF6TYdUTLesW1WIer/SjElU1iGCKY 7TjmrJcvFE5Bih+S86v4ra5RmCHWiJkpXXfmh32NTF9gMHUj1XX9g7+IYtSuxhKKtA QxtPXxboB0gEqxTuF9SqK3tS9+KdRKZrAJKOK/y4= From: Yeoreum Yun Date: Tue, 15 Sep 2026 12:34:41 +0100 Subject: [PATCH v11 6/9] coresight: etm4x: introduce struct etm4_caps Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-separate_etm_cfg_v2-v11-6-d2b258d51747@arm.com> References: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> In-Reply-To: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> To: Mike Leach , James Clark , Leo Yan , Greg Kroah-Hartman , Mathieu Poirier , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev Cc: Suzuki K Poulose , Alexander Shishkin , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Yeoreum Yun X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=67893; i=yeoreum.yun@arm.com; h=from:subject:message-id; bh=A9FwRVgDfZlBo+vhdOUfqu4L6MqVlpNBTjdp7Iq5FSU=; b=owEB7QES/pANAwAKAW3Vw9FaxTEzAcsmYgBqqS1VdfzJu8ikahfb/WRq/JG41ub4TmvecpwU2 orUyEgcTtyJAbMEAAEKAB0WIQQtg+CS3QUzuFh1pJ1t1cPRWsUxMwUCaqktVQAKCRBt1cPRWsUx M/KQC/9PRKt5ZsUx8yli67jC0efEuEa4EeXXgzGfcohi5gZB0tbXAlwJDR/hWnfIhy/pEQavpE2 E+N/TtbKZJeXQaCd7XHJ3DvBJp/GPe2i098h3QDSgWh9gyiHaGLNskbVNTxHQXOl1MMLmWmKe1b FDC5t0LHMC/eqyDOXN+MsGNW7uGF2GlJ8o6BpBK04Y5sNIXu1WZh/876iwQHsG4SSU4JwHiRqNC Odul5xAfnnGUlDvBU/IyDx0osH7OBmWu/xDhNM0gxZtrmQ66HYgRXPGKhpwwAWxpEmcYEZl++nN 1qF1nolRj5apmPpVWxEm4lW8UTKRRaSChjcy4HLX/4mfJWssAChk9SkN6j6FP6ke1KGEEYAGUaO PIkVZU9EP+3p2w4u7JQaOzWw5BRAp/y17VRJukyJ1GbF1V/pMfnAdZgmP+32wrb2BC0P69SJiA1 u4iVeXCU7uvTbmlyvYgVW85pCtVLR8b8hMvCI7lU83nMntFvBlE4BDNlC00CWtoaP0LzQ= X-Developer-Key: i=yeoreum.yun@arm.com; a=openpgp; fpr=2D83E092DD0533B85875A49D6DD5C3D15AC53133 Introduce struct etm4_caps to describe ETMv4 capabilities and move capabilities information into it. Reviewed-by: Leo Yan Signed-off-by: Yeoreum Yun Reviewed-bY: Mike LEach Tested-by: Leo Yan --- drivers/hwtracing/coresight/coresight-etm4x-core.c | 244 +++++++++++------= ---- .../hwtracing/coresight/coresight-etm4x-sysfs.c | 192 +++++++++------- drivers/hwtracing/coresight/coresight-etm4x.h | 180 ++++++++------- 3 files changed, 336 insertions(+), 280 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/h= wtracing/coresight/coresight-etm4x-core.c index 2df7f592bb5cf..70a5c0b4fad1c 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -92,8 +92,9 @@ static int etm4_probe_cpu(unsigned int cpu); */ static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n) { - return (n < drvdata->nr_ss_cmp) && - drvdata->nr_pe_cmp && + const struct etmv4_caps *caps =3D &drvdata->caps; + + return (n < caps->nr_ss_cmp) && caps->nr_pe_cmp && (drvdata->config.ss_status[n] & TRCSSCSRn_PC); } =20 @@ -164,17 +165,20 @@ static void ete_sysreg_write(u64 val, u32 offset, boo= l _relaxed, bool _64bit) static void etm_detect_os_lock(struct etmv4_drvdata *drvdata, struct csdev_access *csa) { + struct etmv4_caps *caps =3D &drvdata->caps; u32 oslsr =3D etm4x_relaxed_read32(csa, TRCOSLSR); =20 - drvdata->os_lock_model =3D ETM_OSLSR_OSLM(oslsr); + caps->os_lock_model =3D ETM_OSLSR_OSLM(oslsr); } =20 static void etm_write_os_lock(struct etmv4_drvdata *drvdata, struct csdev_access *csa, u32 val) { + const struct etmv4_caps *caps =3D &drvdata->caps; + val =3D !!val; =20 - switch (drvdata->os_lock_model) { + switch (caps->os_lock_model) { case ETM_OSLOCK_PRESENT: etm4x_relaxed_write32(csa, val, TRCOSLAR); break; @@ -183,7 +187,7 @@ static void etm_write_os_lock(struct etmv4_drvdata *drv= data, break; default: pr_warn_once("CPU%d: Unsupported Trace OSLock model: %x\n", - smp_processor_id(), drvdata->os_lock_model); + smp_processor_id(), caps->os_lock_model); fallthrough; case ETM_OSLOCK_NI: return; @@ -495,6 +499,7 @@ static int etm4_enable_trace_unit(struct etmv4_drvdata = *drvdata) static int etm4_enable_hw(struct etmv4_drvdata *drvdata) { int i, rc; + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->active_config; struct coresight_device *csdev =3D drvdata->csdev; struct device *etm_dev =3D &csdev->dev; @@ -526,14 +531,14 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvda= ta) if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 1)) dev_err(etm_dev, "timeout while waiting for Idle Trace Status\n"); - if (drvdata->nr_pe) + if (caps->nr_pe) etm4x_relaxed_write32(csa, config->pe_sel, TRCPROCSELR); etm4x_relaxed_write32(csa, config->cfg, TRCCONFIGR); /* nothing specific implemented */ etm4x_relaxed_write32(csa, 0x0, TRCAUXCTLR); etm4x_relaxed_write32(csa, config->eventctrl0, TRCEVENTCTL0R); etm4x_relaxed_write32(csa, config->eventctrl1, TRCEVENTCTL1R); - if (drvdata->stallctl) + if (caps->stallctl) etm4x_relaxed_write32(csa, config->stall_ctrl, TRCSTALLCTLR); etm4x_relaxed_write32(csa, config->ts_ctrl, TRCTSCTLR); etm4x_relaxed_write32(csa, config->syncfreq, TRCSYNCPR); @@ -543,18 +548,18 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvda= ta) etm4x_relaxed_write32(csa, config->vinst_ctrl, TRCVICTLR); etm4x_relaxed_write32(csa, config->viiectlr, TRCVIIECTLR); etm4x_relaxed_write32(csa, config->vissctlr, TRCVISSCTLR); - if (drvdata->nr_pe_cmp) + if (caps->nr_pe_cmp) etm4x_relaxed_write32(csa, config->vipcssctlr, TRCVIPCSSCTLR); =20 - for (i =3D 0; i < drvdata->nr_seq_ctrls; i++) + for (i =3D 0; i < caps->nr_seq_ctrls; i++) etm4x_relaxed_write32(csa, config->seq_ctrl[i], TRCSEQEVRn(i)); - if (drvdata->nrseqstate) { + if (caps->nrseqstate) { etm4x_relaxed_write32(csa, config->seq_rst, TRCSEQRSTEVR); etm4x_relaxed_write32(csa, config->seq_state, TRCSEQSTR); } - if (drvdata->numextinsel) + if (caps->numextinsel) etm4x_relaxed_write32(csa, config->ext_inp, TRCEXTINSELR); - for (i =3D 0; i < drvdata->nr_cntr; i++) { + for (i =3D 0; i < caps->nr_cntr; i++) { etm4x_relaxed_write32(csa, config->cntrldvr[i], TRCCNTRLDVRn(i)); etm4x_relaxed_write32(csa, config->cntr_ctrl[i], TRCCNTCTLRn(i)); etm4x_relaxed_write32(csa, config->cntr_val[i], TRCCNTVRn(i)); @@ -564,10 +569,10 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvda= ta) * Resource selector pair 0 is always implemented and reserved. As * such start at 2. */ - for (i =3D 2; i < drvdata->nr_resource * 2; i++) + for (i =3D 2; i < caps->nr_resource * 2; i++) etm4x_relaxed_write32(csa, config->res_ctrl[i], TRCRSCTLRn(i)); =20 - for (i =3D 0; i < drvdata->nr_ss_cmp; i++) { + for (i =3D 0; i < caps->nr_ss_cmp; i++) { /* always clear status bit on restart if using single-shot */ if (config->ss_ctrl[i] || config->ss_pe_cmp[i]) config->ss_status[i] &=3D ~TRCSSCSRn_STATUS; @@ -576,23 +581,23 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvda= ta) if (etm4x_sspcicrn_present(drvdata, i)) etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i)); } - for (i =3D 0; i < drvdata->nr_addr_cmp * 2; i++) { + for (i =3D 0; i < caps->nr_addr_cmp * 2; i++) { etm4x_relaxed_write64(csa, config->addr_val[i], TRCACVRn(i)); etm4x_relaxed_write64(csa, config->addr_acc[i], TRCACATRn(i)); } - for (i =3D 0; i < drvdata->numcidc; i++) + for (i =3D 0; i < caps->numcidc; i++) etm4x_relaxed_write64(csa, config->ctxid_pid[i], TRCCIDCVRn(i)); etm4x_relaxed_write32(csa, config->ctxid_mask0, TRCCIDCCTLR0); - if (drvdata->numcidc > 4) + if (caps->numcidc > 4) etm4x_relaxed_write32(csa, config->ctxid_mask1, TRCCIDCCTLR1); =20 - for (i =3D 0; i < drvdata->numvmidc; i++) + for (i =3D 0; i < caps->numvmidc; i++) etm4x_relaxed_write64(csa, config->vmid_val[i], TRCVMIDCVRn(i)); etm4x_relaxed_write32(csa, config->vmid_mask0, TRCVMIDCCTLR0); - if (drvdata->numvmidc > 4) + if (caps->numvmidc > 4) etm4x_relaxed_write32(csa, config->vmid_mask1, TRCVMIDCCTLR1); =20 - if (!drvdata->skip_power_up) { + if (!caps->skip_power_up) { u32 trcpdcr =3D etm4x_relaxed_read32(csa, TRCPDCR); =20 /* @@ -689,19 +694,20 @@ static int etm4_config_timestamp_event(struct etmv4_d= rvdata *drvdata, { int ctridx; int rselector; + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->active_config; =20 /* No point in trying if we don't have at least one counter */ - if (!drvdata->nr_cntr) + if (!caps->nr_cntr) return -EINVAL; =20 /* Find a counter that hasn't been initialised */ - for (ctridx =3D 0; ctridx < drvdata->nr_cntr; ctridx++) + for (ctridx =3D 0; ctridx < caps->nr_cntr; ctridx++) if (config->cntr_val[ctridx] =3D=3D 0) break; =20 /* All the counters have been configured already, bail out */ - if (ctridx =3D=3D drvdata->nr_cntr) { + if (ctridx =3D=3D caps->nr_cntr) { pr_debug("%s: no available counter found\n", __func__); return -ENOSPC; } @@ -717,11 +723,11 @@ static int etm4_config_timestamp_event(struct etmv4_d= rvdata *drvdata, * ETMIDR4 gives the number of resource selector _pairs_, hence multiply * by 2. */ - for (rselector =3D 2; rselector < drvdata->nr_resource * 2; rselector++) + for (rselector =3D 2; rselector < caps->nr_resource * 2; rselector++) if (!config->res_ctrl[rselector]) break; =20 - if (rselector =3D=3D drvdata->nr_resource * 2) { + if (rselector =3D=3D caps->nr_resource * 2) { pr_debug("%s: no available resource selector found\n", __func__); return -ENOSPC; @@ -772,6 +778,7 @@ static int etm4_parse_event_config(struct coresight_dev= ice *csdev, { int ret =3D 0; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->active_config; struct perf_event_attr max_timestamp =3D { .ATTR_CFG_FLD_timestamp_CFG =3D U64_MAX, @@ -810,8 +817,8 @@ static int etm4_parse_event_config(struct coresight_dev= ice *csdev, cc_threshold =3D ATTR_CFG_GET_FLD(attr, cc_threshold); if (!cc_threshold) cc_threshold =3D ETM_CYC_THRESHOLD_DEFAULT; - if (cc_threshold < drvdata->ccitmin) - cc_threshold =3D drvdata->ccitmin; + if (cc_threshold < caps->ccitmin) + cc_threshold =3D caps->ccitmin; config->ccctlr =3D cc_threshold; } =20 @@ -859,13 +866,13 @@ static int etm4_parse_event_config(struct coresight_d= evice *csdev, } =20 /* return stack - enable if selected and supported */ - if (ATTR_CFG_GET_FLD(attr, retstack) && drvdata->retstack) + if (ATTR_CFG_GET_FLD(attr, retstack) && caps->retstack) /* bit[12], Return stack enable bit */ config->cfg |=3D TRCCONFIGR_RS; =20 /* branch broadcast - enable if selected and supported */ if (ATTR_CFG_GET_FLD(attr, branch_broadcast)) { - if (!drvdata->trcbb) { + if (!caps->trcbb) { /* * Missing BB support could cause silent decode errors * so fail to open if it's not supported. @@ -1054,6 +1061,7 @@ static void etm4_disable_trace_unit(struct etmv4_drvd= ata *drvdata) static void etm4_disable_hw(struct etmv4_drvdata *drvdata) { u32 control; + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->active_config; struct coresight_device *csdev =3D drvdata->csdev; struct csdev_access *csa =3D &csdev->access; @@ -1062,7 +1070,7 @@ static void etm4_disable_hw(struct etmv4_drvdata *drv= data) etm4_cs_unlock(drvdata, csa); etm4_disable_arch_specific(drvdata); =20 - if (!drvdata->skip_power_up) { + if (!caps->skip_power_up) { /* power can be removed from the trace unit now */ control =3D etm4x_relaxed_read32(csa, TRCPDCR); control &=3D ~TRCPDCR_PU; @@ -1072,13 +1080,13 @@ static void etm4_disable_hw(struct etmv4_drvdata *d= rvdata) etm4_disable_trace_unit(drvdata); =20 /* read the status of the single shot comparators */ - for (i =3D 0; i < drvdata->nr_ss_cmp; i++) { + for (i =3D 0; i < caps->nr_ss_cmp; i++) { config->ss_status[i] =3D etm4x_relaxed_read32(csa, TRCSSCSRn(i)); } =20 /* read back the current counter values */ - for (i =3D 0; i < drvdata->nr_cntr; i++) { + for (i =3D 0; i < caps->nr_cntr; i++) { config->cntr_val[i] =3D etm4x_relaxed_read32(csa, TRCCNTVRn(i)); } @@ -1141,6 +1149,7 @@ static int etm4_disable_perf(struct coresight_device = *csdev, static void etm4_disable_sysfs(struct coresight_device *csdev) { struct etmv4_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; const struct etmv4_config *active_config =3D &drvdata->active_config; int i; @@ -1156,10 +1165,10 @@ static void etm4_disable_sysfs(struct coresight_dev= ice *csdev) * Userspace may read ss_status and cntr_val through sysfs after * the sysfs-session has been disabled. */ - for (i =3D 0; i < drvdata->nr_ss_cmp; i++) + for (i =3D 0; i < caps->nr_ss_cmp; i++) config->ss_status[i] =3D active_config->ss_status[i]; =20 - for (i =3D 0; i < drvdata->nr_cntr; i++) + for (i =3D 0; i < caps->nr_cntr; i++) config->cntr_val[i] =3D active_config->cntr_val[i]; =20 coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); @@ -1373,7 +1382,7 @@ static struct midr_range etm_wrong_ccitmin_cpus[] =3D= { {}, }; =20 -static void etm4_fixup_wrong_ccitmin(struct etmv4_drvdata *drvdata) +static void etm4_fixup_wrong_ccitmin(struct etmv4_caps *caps) { /* * Erratum affected cpus will read 256 as the minimum @@ -1383,8 +1392,8 @@ static void etm4_fixup_wrong_ccitmin(struct etmv4_drv= data *drvdata) * this problem. */ if (is_midr_in_range_list(etm_wrong_ccitmin_cpus)) { - if (drvdata->ccitmin =3D=3D 256) - drvdata->ccitmin =3D 4; + if (caps->ccitmin =3D=3D 256) + caps->ccitmin =3D 4; } } =20 @@ -1397,11 +1406,13 @@ static void etm4_init_arch_data(void *info) u32 etmidr5; struct etm4_init_arg *init_arg =3D info; struct etmv4_drvdata *drvdata; + struct etmv4_caps *caps; struct csdev_access *csa; struct device *dev =3D init_arg->dev; int i; =20 drvdata =3D dev_get_drvdata(init_arg->dev); + caps =3D &drvdata->caps; csa =3D init_arg->csa; =20 /* @@ -1414,7 +1425,7 @@ static void etm4_init_arch_data(void *info) =20 if (!csa->io_mem || fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up")) - drvdata->skip_power_up =3D true; + caps->skip_power_up =3D true; =20 /* Detect the support for OS Lock before we actually use it */ etm_detect_os_lock(drvdata, csa); @@ -1429,71 +1440,71 @@ static void etm4_init_arch_data(void *info) etmidr0 =3D etm4x_relaxed_read32(csa, TRCIDR0); =20 /* INSTP0, bits[2:1] P0 tracing support field */ - drvdata->instrp0 =3D !!(FIELD_GET(TRCIDR0_INSTP0_MASK, etmidr0) =3D=3D 0b= 11); + caps->instrp0 =3D !!(FIELD_GET(TRCIDR0_INSTP0_MASK, etmidr0) =3D=3D 0b11); /* TRCBB, bit[5] Branch broadcast tracing support bit */ - drvdata->trcbb =3D !!(etmidr0 & TRCIDR0_TRCBB); + caps->trcbb =3D !!(etmidr0 & TRCIDR0_TRCBB); /* TRCCOND, bit[6] Conditional instruction tracing support bit */ - drvdata->trccond =3D !!(etmidr0 & TRCIDR0_TRCCOND); + caps->trccond =3D !!(etmidr0 & TRCIDR0_TRCCOND); /* TRCCCI, bit[7] Cycle counting instruction bit */ - drvdata->trccci =3D !!(etmidr0 & TRCIDR0_TRCCCI); + caps->trccci =3D !!(etmidr0 & TRCIDR0_TRCCCI); /* RETSTACK, bit[9] Return stack bit */ - drvdata->retstack =3D !!(etmidr0 & TRCIDR0_RETSTACK); + caps->retstack =3D !!(etmidr0 & TRCIDR0_RETSTACK); /* NUMEVENT, bits[11:10] Number of events field */ - drvdata->nr_event =3D FIELD_GET(TRCIDR0_NUMEVENT_MASK, etmidr0); + caps->nr_event =3D FIELD_GET(TRCIDR0_NUMEVENT_MASK, etmidr0); /* QSUPP, bits[16:15] Q element support field */ - drvdata->q_support =3D FIELD_GET(TRCIDR0_QSUPP_MASK, etmidr0); - if (drvdata->q_support) - drvdata->q_filt =3D !!(etmidr0 & TRCIDR0_QFILT); + caps->q_support =3D FIELD_GET(TRCIDR0_QSUPP_MASK, etmidr0); + if (caps->q_support) + caps->q_filt =3D !!(etmidr0 & TRCIDR0_QFILT); /* TSSIZE, bits[28:24] Global timestamp size field */ - drvdata->ts_size =3D FIELD_GET(TRCIDR0_TSSIZE_MASK, etmidr0); + caps->ts_size =3D FIELD_GET(TRCIDR0_TSSIZE_MASK, etmidr0); =20 /* maximum size of resources */ etmidr2 =3D etm4x_relaxed_read32(csa, TRCIDR2); /* CIDSIZE, bits[9:5] Indicates the Context ID size */ - drvdata->ctxid_size =3D FIELD_GET(TRCIDR2_CIDSIZE_MASK, etmidr2); + caps->ctxid_size =3D FIELD_GET(TRCIDR2_CIDSIZE_MASK, etmidr2); /* VMIDSIZE, bits[14:10] Indicates the VMID size */ - drvdata->vmid_size =3D FIELD_GET(TRCIDR2_VMIDSIZE_MASK, etmidr2); + caps->vmid_size =3D FIELD_GET(TRCIDR2_VMIDSIZE_MASK, etmidr2); /* CCSIZE, bits[28:25] size of the cycle counter in bits minus 12 */ - drvdata->ccsize =3D FIELD_GET(TRCIDR2_CCSIZE_MASK, etmidr2); + caps->ccsize =3D FIELD_GET(TRCIDR2_CCSIZE_MASK, etmidr2); =20 etmidr3 =3D etm4x_relaxed_read32(csa, TRCIDR3); /* CCITMIN, bits[11:0] minimum threshold value that can be programmed */ - drvdata->ccitmin =3D FIELD_GET(TRCIDR3_CCITMIN_MASK, etmidr3); - etm4_fixup_wrong_ccitmin(drvdata); + caps->ccitmin =3D FIELD_GET(TRCIDR3_CCITMIN_MASK, etmidr3); + etm4_fixup_wrong_ccitmin(caps); =20 /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */ - drvdata->s_ex_level =3D FIELD_GET(TRCIDR3_EXLEVEL_S_MASK, etmidr3); - drvdata->config.s_ex_level =3D drvdata->s_ex_level; + caps->s_ex_level =3D FIELD_GET(TRCIDR3_EXLEVEL_S_MASK, etmidr3); + drvdata->config.s_ex_level =3D caps->s_ex_level; /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */ - drvdata->ns_ex_level =3D FIELD_GET(TRCIDR3_EXLEVEL_NS_MASK, etmidr3); + caps->ns_ex_level =3D FIELD_GET(TRCIDR3_EXLEVEL_NS_MASK, etmidr3); /* * TRCERR, bit[24] whether a trace unit can trace a * system error exception. */ - drvdata->trc_error =3D !!(etmidr3 & TRCIDR3_TRCERR); + caps->trc_error =3D !!(etmidr3 & TRCIDR3_TRCERR); /* SYNCPR, bit[25] implementation has a fixed synchronization period? */ - drvdata->syncpr =3D !!(etmidr3 & TRCIDR3_SYNCPR); + caps->syncpr =3D !!(etmidr3 & TRCIDR3_SYNCPR); /* STALLCTL, bit[26] is stall control implemented? */ - drvdata->stallctl =3D !!(etmidr3 & TRCIDR3_STALLCTL); + caps->stallctl =3D !!(etmidr3 & TRCIDR3_STALLCTL); /* SYSSTALL, bit[27] implementation can support stall control? */ - drvdata->sysstall =3D !!(etmidr3 & TRCIDR3_SYSSTALL); + caps->sysstall =3D !!(etmidr3 & TRCIDR3_SYSSTALL); /* * NUMPROC - the number of PEs available for tracing, 5bits * =3D TRCIDR3.bits[13:12]bits[30:28] * bits[4:3] =3D TRCIDR3.bits[13:12] (since etm-v4.2, otherwise RES0) * bits[3:0] =3D TRCIDR3.bits[30:28] */ - drvdata->nr_pe =3D (FIELD_GET(TRCIDR3_NUMPROC_HI_MASK, etmidr3) << 3) | - FIELD_GET(TRCIDR3_NUMPROC_LO_MASK, etmidr3); + caps->nr_pe =3D (FIELD_GET(TRCIDR3_NUMPROC_HI_MASK, etmidr3) << 3) | + FIELD_GET(TRCIDR3_NUMPROC_LO_MASK, etmidr3); /* NOOVERFLOW, bit[31] is trace overflow prevention supported */ - drvdata->nooverflow =3D !!(etmidr3 & TRCIDR3_NOOVERFLOW); + caps->nooverflow =3D !!(etmidr3 & TRCIDR3_NOOVERFLOW); =20 /* number of resources trace unit supports */ etmidr4 =3D etm4x_relaxed_read32(csa, TRCIDR4); /* NUMACPAIRS, bits[0:3] number of addr comparator pairs for tracing */ - drvdata->nr_addr_cmp =3D FIELD_GET(TRCIDR4_NUMACPAIRS_MASK, etmidr4); + caps->nr_addr_cmp =3D FIELD_GET(TRCIDR4_NUMACPAIRS_MASK, etmidr4); /* NUMPC, bits[15:12] number of PE comparator inputs for tracing */ - drvdata->nr_pe_cmp =3D FIELD_GET(TRCIDR4_NUMPC_MASK, etmidr4); + caps->nr_pe_cmp =3D FIELD_GET(TRCIDR4_NUMPC_MASK, etmidr4); /* * NUMRSPAIR, bits[19:16] * The number of resource pairs conveyed by the HW starts at 0, i.e a @@ -1504,43 +1515,43 @@ static void etm4_init_arch_data(void *info) * the default TRUE and FALSE resource selectors are omitted. * Otherwise for values 0x1 and above the number is N + 1 as per v4.2. */ - drvdata->nr_resource =3D FIELD_GET(TRCIDR4_NUMRSPAIR_MASK, etmidr4); - if ((drvdata->arch < ETM_ARCH_V4_3) || (drvdata->nr_resource > 0)) - drvdata->nr_resource +=3D 1; + caps->nr_resource =3D FIELD_GET(TRCIDR4_NUMRSPAIR_MASK, etmidr4); + if ((drvdata->arch < ETM_ARCH_V4_3) || (caps->nr_resource > 0)) + caps->nr_resource +=3D 1; /* * NUMSSCC, bits[23:20] the number of single-shot * comparator control for tracing. Read any status regs as these * also contain RO capability data. */ - drvdata->nr_ss_cmp =3D FIELD_GET(TRCIDR4_NUMSSCC_MASK, etmidr4); - for (i =3D 0; i < drvdata->nr_ss_cmp; i++) { + caps->nr_ss_cmp =3D FIELD_GET(TRCIDR4_NUMSSCC_MASK, etmidr4); + for (i =3D 0; i < caps->nr_ss_cmp; i++) { drvdata->config.ss_status[i] =3D etm4x_relaxed_read32(csa, TRCSSCSRn(i)); } /* NUMCIDC, bits[27:24] number of Context ID comparators for tracing */ - drvdata->numcidc =3D FIELD_GET(TRCIDR4_NUMCIDC_MASK, etmidr4); + caps->numcidc =3D FIELD_GET(TRCIDR4_NUMCIDC_MASK, etmidr4); /* NUMVMIDC, bits[31:28] number of VMID comparators for tracing */ - drvdata->numvmidc =3D FIELD_GET(TRCIDR4_NUMVMIDC_MASK, etmidr4); + caps->numvmidc =3D FIELD_GET(TRCIDR4_NUMVMIDC_MASK, etmidr4); =20 etmidr5 =3D etm4x_relaxed_read32(csa, TRCIDR5); /* NUMEXTIN, bits[8:0] number of external inputs implemented */ - drvdata->nr_ext_inp =3D FIELD_GET(TRCIDR5_NUMEXTIN_MASK, etmidr5); - drvdata->numextinsel =3D FIELD_GET(TRCIDR5_NUMEXTINSEL_MASK, etmidr5); + caps->nr_ext_inp =3D FIELD_GET(TRCIDR5_NUMEXTIN_MASK, etmidr5); + caps->numextinsel =3D FIELD_GET(TRCIDR5_NUMEXTINSEL_MASK, etmidr5); /* TRACEIDSIZE, bits[21:16] indicates the trace ID width */ - drvdata->trcid_size =3D FIELD_GET(TRCIDR5_TRACEIDSIZE_MASK, etmidr5); + caps->trcid_size =3D FIELD_GET(TRCIDR5_TRACEIDSIZE_MASK, etmidr5); /* ATBTRIG, bit[22] implementation can support ATB triggers? */ - drvdata->atbtrig =3D !!(etmidr5 & TRCIDR5_ATBTRIG); + caps->atbtrig =3D !!(etmidr5 & TRCIDR5_ATBTRIG); /* * LPOVERRIDE, bit[23] implementation supports * low-power state override */ - drvdata->lpoverride =3D (etmidr5 & TRCIDR5_LPOVERRIDE) && (!drvdata->skip= _power_up); + caps->lpoverride =3D (etmidr5 & TRCIDR5_LPOVERRIDE) && (!caps->skip_power= _up); /* NUMSEQSTATE, bits[27:25] number of sequencer states implemented */ - drvdata->nrseqstate =3D FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5); - if (drvdata->nrseqstate) - drvdata->nr_seq_ctrls =3D ETM_MAX_SEQ_TRANSITIONS; + caps->nrseqstate =3D FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5); + if (caps->nrseqstate) + caps->nr_seq_ctrls =3D ETM_MAX_SEQ_TRANSITIONS; /* NUMCNTR, bits[30:28] number of counters available for tracing */ - drvdata->nr_cntr =3D FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5); + caps->nr_cntr =3D FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5); =20 coresight_clear_self_claim_tag_unlocked(csa); etm4_cs_lock(drvdata, csa); @@ -1716,7 +1727,7 @@ static int etm4_get_next_comparator(struct etmv4_drvd= ata *drvdata, u32 type) * nr_addr_cmp holds the number of comparator _pair_, so time 2 * for the total number of comparators. */ - nr_comparator =3D drvdata->nr_addr_cmp * 2; + nr_comparator =3D drvdata->caps.nr_addr_cmp * 2; =20 /* Go through the tally of comparators looking for a free one. */ while (index < nr_comparator) { @@ -1873,6 +1884,7 @@ static int etm4_cpu_save(struct coresight_device *csd= ev) { int i, ret =3D 0; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_save_state *state; struct csdev_access *csa; struct device *etm_dev; @@ -1905,57 +1917,56 @@ static int etm4_cpu_save(struct coresight_device *c= sdev) =20 state =3D drvdata->save_state; =20 - if (drvdata->nr_pe) + if (caps->nr_pe) state->trcprocselr =3D etm4x_read32(csa, TRCPROCSELR); state->trcconfigr =3D etm4x_read32(csa, TRCCONFIGR); state->trcauxctlr =3D etm4x_read32(csa, TRCAUXCTLR); state->trceventctl0r =3D etm4x_read32(csa, TRCEVENTCTL0R); state->trceventctl1r =3D etm4x_read32(csa, TRCEVENTCTL1R); - if (drvdata->stallctl) + if (caps->stallctl) state->trcstallctlr =3D etm4x_read32(csa, TRCSTALLCTLR); state->trctsctlr =3D etm4x_read32(csa, TRCTSCTLR); state->trcsyncpr =3D etm4x_read32(csa, TRCSYNCPR); state->trcccctlr =3D etm4x_read32(csa, TRCCCCTLR); state->trcbbctlr =3D etm4x_read32(csa, TRCBBCTLR); state->trctraceidr =3D etm4x_read32(csa, TRCTRACEIDR); - if (drvdata->q_filt) + if (caps->q_filt) state->trcqctlr =3D etm4x_read32(csa, TRCQCTLR); =20 state->trcvictlr =3D etm4x_read32(csa, TRCVICTLR); state->trcviiectlr =3D etm4x_read32(csa, TRCVIIECTLR); state->trcvissctlr =3D etm4x_read32(csa, TRCVISSCTLR); - if (drvdata->nr_pe_cmp) + if (caps->nr_pe_cmp) state->trcvipcssctlr =3D etm4x_read32(csa, TRCVIPCSSCTLR); =20 - for (i =3D 0; i < drvdata->nr_seq_ctrls; i++) + for (i =3D 0; i < caps->nr_seq_ctrls; i++) state->trcseqevr[i] =3D etm4x_read32(csa, TRCSEQEVRn(i)); - - if (drvdata->nrseqstate) { + if (caps->nrseqstate) { state->trcseqrstevr =3D etm4x_read32(csa, TRCSEQRSTEVR); state->trcseqstr =3D etm4x_read32(csa, TRCSEQSTR); } =20 - if (drvdata->numextinsel) + if (caps->numextinsel) state->trcextinselr =3D etm4x_read32(csa, TRCEXTINSELR); =20 - for (i =3D 0; i < drvdata->nr_cntr; i++) { + for (i =3D 0; i < caps->nr_cntr; i++) { state->trccntrldvr[i] =3D etm4x_read32(csa, TRCCNTRLDVRn(i)); state->trccntctlr[i] =3D etm4x_read32(csa, TRCCNTCTLRn(i)); state->trccntvr[i] =3D etm4x_read32(csa, TRCCNTVRn(i)); } =20 /* Resource selector pair 0 is reserved */ - for (i =3D 2; i < drvdata->nr_resource * 2; i++) + for (i =3D 2; i < caps->nr_resource * 2; i++) state->trcrsctlr[i] =3D etm4x_read32(csa, TRCRSCTLRn(i)); =20 - for (i =3D 0; i < drvdata->nr_ss_cmp; i++) { + for (i =3D 0; i < caps->nr_ss_cmp; i++) { state->trcssccr[i] =3D etm4x_read32(csa, TRCSSCCRn(i)); state->trcsscsr[i] =3D etm4x_read32(csa, TRCSSCSRn(i)); if (etm4x_sspcicrn_present(drvdata, i)) state->trcsspcicr[i] =3D etm4x_read32(csa, TRCSSPCICRn(i)); } =20 - for (i =3D 0; i < drvdata->nr_addr_cmp * 2; i++) { + for (i =3D 0; i < caps->nr_addr_cmp * 2; i++) { state->trcacvr[i] =3D etm4x_read64(csa, TRCACVRn(i)); state->trcacatr[i] =3D etm4x_read64(csa, TRCACATRn(i)); } @@ -1967,23 +1978,23 @@ static int etm4_cpu_save(struct coresight_device *c= sdev) * unit") of ARM IHI 0064D. */ =20 - for (i =3D 0; i < drvdata->numcidc; i++) + for (i =3D 0; i < caps->numcidc; i++) state->trccidcvr[i] =3D etm4x_read64(csa, TRCCIDCVRn(i)); =20 - for (i =3D 0; i < drvdata->numvmidc; i++) + for (i =3D 0; i < caps->numvmidc; i++) state->trcvmidcvr[i] =3D etm4x_read64(csa, TRCVMIDCVRn(i)); =20 state->trccidcctlr0 =3D etm4x_read32(csa, TRCCIDCCTLR0); - if (drvdata->numcidc > 4) + if (caps->numcidc > 4) state->trccidcctlr1 =3D etm4x_read32(csa, TRCCIDCCTLR1); =20 state->trcvmidcctlr0 =3D etm4x_read32(csa, TRCVMIDCCTLR0); - if (drvdata->numvmidc > 4) + if (caps->numvmidc > 4) state->trcvmidcctlr1 =3D etm4x_read32(csa, TRCVMIDCCTLR1); =20 state->trcclaimset =3D etm4x_read32(csa, TRCCLAIMCLR); =20 - if (!drvdata->skip_power_up) + if (!caps->skip_power_up) state->trcpdcr =3D etm4x_read32(csa, TRCPDCR); =20 /* wait for TRCSTATR.IDLE to go up */ @@ -2000,7 +2011,7 @@ static int etm4_cpu_save(struct coresight_device *csd= ev) * potentially save power on systems that respect the TRCPDCR_PU * despite requesting software to save/restore state. */ - if (!drvdata->skip_power_up) + if (!caps->skip_power_up) etm4x_relaxed_write32(csa, (state->trcpdcr & ~TRCPDCR_PU), TRCPDCR); out: @@ -2012,83 +2023,84 @@ static void etm4_cpu_restore(struct coresight_devic= e *csdev) { int i; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_save_state *state =3D drvdata->save_state; struct csdev_access *csa =3D &drvdata->csdev->access; =20 etm4_cs_unlock(drvdata, csa); etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET); =20 - if (drvdata->nr_pe) + if (caps->nr_pe) etm4x_relaxed_write32(csa, state->trcprocselr, TRCPROCSELR); etm4x_relaxed_write32(csa, state->trcconfigr, TRCCONFIGR); etm4x_relaxed_write32(csa, state->trcauxctlr, TRCAUXCTLR); etm4x_relaxed_write32(csa, state->trceventctl0r, TRCEVENTCTL0R); etm4x_relaxed_write32(csa, state->trceventctl1r, TRCEVENTCTL1R); - if (drvdata->stallctl) + if (caps->stallctl) etm4x_relaxed_write32(csa, state->trcstallctlr, TRCSTALLCTLR); etm4x_relaxed_write32(csa, state->trctsctlr, TRCTSCTLR); etm4x_relaxed_write32(csa, state->trcsyncpr, TRCSYNCPR); etm4x_relaxed_write32(csa, state->trcccctlr, TRCCCCTLR); etm4x_relaxed_write32(csa, state->trcbbctlr, TRCBBCTLR); etm4x_relaxed_write32(csa, state->trctraceidr, TRCTRACEIDR); - if (drvdata->q_filt) + if (caps->q_filt) etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR); =20 etm4x_relaxed_write32(csa, state->trcvictlr, TRCVICTLR); etm4x_relaxed_write32(csa, state->trcviiectlr, TRCVIIECTLR); etm4x_relaxed_write32(csa, state->trcvissctlr, TRCVISSCTLR); - if (drvdata->nr_pe_cmp) + if (caps->nr_pe_cmp) etm4x_relaxed_write32(csa, state->trcvipcssctlr, TRCVIPCSSCTLR); =20 - for (i =3D 0; i < drvdata->nr_seq_ctrls; i++) + for (i =3D 0; i < caps->nr_seq_ctrls; i++) etm4x_relaxed_write32(csa, state->trcseqevr[i], TRCSEQEVRn(i)); =20 - if (drvdata->nrseqstate) { + if (caps->nrseqstate) { etm4x_relaxed_write32(csa, state->trcseqrstevr, TRCSEQRSTEVR); etm4x_relaxed_write32(csa, state->trcseqstr, TRCSEQSTR); } - if (drvdata->numextinsel) + if (caps->numextinsel) etm4x_relaxed_write32(csa, state->trcextinselr, TRCEXTINSELR); =20 - for (i =3D 0; i < drvdata->nr_cntr; i++) { + for (i =3D 0; i < caps->nr_cntr; i++) { etm4x_relaxed_write32(csa, state->trccntrldvr[i], TRCCNTRLDVRn(i)); etm4x_relaxed_write32(csa, state->trccntctlr[i], TRCCNTCTLRn(i)); etm4x_relaxed_write32(csa, state->trccntvr[i], TRCCNTVRn(i)); } =20 /* Resource selector pair 0 is reserved */ - for (i =3D 2; i < drvdata->nr_resource * 2; i++) + for (i =3D 2; i < caps->nr_resource * 2; i++) etm4x_relaxed_write32(csa, state->trcrsctlr[i], TRCRSCTLRn(i)); =20 - for (i =3D 0; i < drvdata->nr_ss_cmp; i++) { + for (i =3D 0; i < caps->nr_ss_cmp; i++) { etm4x_relaxed_write32(csa, state->trcssccr[i], TRCSSCCRn(i)); etm4x_relaxed_write32(csa, state->trcsscsr[i], TRCSSCSRn(i)); if (etm4x_sspcicrn_present(drvdata, i)) etm4x_relaxed_write32(csa, state->trcsspcicr[i], TRCSSPCICRn(i)); } =20 - for (i =3D 0; i < drvdata->nr_addr_cmp * 2; i++) { + for (i =3D 0; i < caps->nr_addr_cmp * 2; i++) { etm4x_relaxed_write64(csa, state->trcacvr[i], TRCACVRn(i)); etm4x_relaxed_write64(csa, state->trcacatr[i], TRCACATRn(i)); } =20 - for (i =3D 0; i < drvdata->numcidc; i++) + for (i =3D 0; i < caps->numcidc; i++) etm4x_relaxed_write64(csa, state->trccidcvr[i], TRCCIDCVRn(i)); =20 - for (i =3D 0; i < drvdata->numvmidc; i++) + for (i =3D 0; i < caps->numvmidc; i++) etm4x_relaxed_write64(csa, state->trcvmidcvr[i], TRCVMIDCVRn(i)); =20 etm4x_relaxed_write32(csa, state->trccidcctlr0, TRCCIDCCTLR0); - if (drvdata->numcidc > 4) + if (caps->numcidc > 4) etm4x_relaxed_write32(csa, state->trccidcctlr1, TRCCIDCCTLR1); =20 etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR0); - if (drvdata->numvmidc > 4) + if (caps->numvmidc > 4) etm4x_relaxed_write32(csa, state->trcvmidcctlr1, TRCVMIDCCTLR1); =20 etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET); =20 - if (!drvdata->skip_power_up) + if (!caps->skip_power_up) etm4x_relaxed_write32(csa, state->trcpdcr, TRCPDCR); =20 /* diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/= hwtracing/coresight/coresight-etm4x-sysfs.c index f64c0acebc701..f6d053f73264c 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -62,8 +62,9 @@ static ssize_t nr_pe_cmp_show(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; =20 - val =3D drvdata->nr_pe_cmp; + val =3D caps->nr_pe_cmp; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } static DEVICE_ATTR_RO(nr_pe_cmp); @@ -74,8 +75,9 @@ static ssize_t nr_addr_cmp_show(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; =20 - val =3D drvdata->nr_addr_cmp; + val =3D caps->nr_addr_cmp; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } static DEVICE_ATTR_RO(nr_addr_cmp); @@ -86,8 +88,9 @@ static ssize_t nr_cntr_show(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; =20 - val =3D drvdata->nr_cntr; + val =3D caps->nr_cntr; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } static DEVICE_ATTR_RO(nr_cntr); @@ -98,8 +101,9 @@ static ssize_t nr_ext_inp_show(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; =20 - val =3D drvdata->nr_ext_inp; + val =3D caps->nr_ext_inp; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } static DEVICE_ATTR_RO(nr_ext_inp); @@ -110,8 +114,9 @@ static ssize_t numcidc_show(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; =20 - val =3D drvdata->numcidc; + val =3D caps->numcidc; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } static DEVICE_ATTR_RO(numcidc); @@ -122,8 +127,9 @@ static ssize_t numvmidc_show(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; =20 - val =3D drvdata->numvmidc; + val =3D caps->numvmidc; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } static DEVICE_ATTR_RO(numvmidc); @@ -134,8 +140,9 @@ static ssize_t nrseqstate_show(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; =20 - val =3D drvdata->nrseqstate; + val =3D caps->nrseqstate; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } static DEVICE_ATTR_RO(nrseqstate); @@ -146,8 +153,9 @@ static ssize_t nr_resource_show(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; =20 - val =3D drvdata->nr_resource; + val =3D caps->nr_resource; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } static DEVICE_ATTR_RO(nr_resource); @@ -158,8 +166,9 @@ static ssize_t nr_ss_cmp_show(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; =20 - val =3D drvdata->nr_ss_cmp; + val =3D caps->nr_ss_cmp; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } static DEVICE_ATTR_RO(nr_ss_cmp); @@ -171,6 +180,7 @@ static ssize_t reset_store(struct device *dev, int i; unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) @@ -200,7 +210,7 @@ static ssize_t reset_store(struct device *dev, config->stall_ctrl =3D 0x0; =20 /* Reset trace synchronization period to 2^8 =3D 256 bytes*/ - if (drvdata->syncpr =3D=3D false) + if (!caps->syncpr) config->syncfreq =3D 0x8; =20 /* @@ -209,7 +219,7 @@ static ssize_t reset_store(struct device *dev, * each trace run. */ config->vinst_ctrl =3D FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01); - if (drvdata->nr_addr_cmp > 0) { + if (caps->nr_addr_cmp > 0) { config->mode |=3D ETM_MODE_VIEWINST_STARTSTOP; /* SSSTATUS, bit[9] */ config->vinst_ctrl |=3D TRCVICTLR_SSSTATUS; @@ -223,7 +233,7 @@ static ssize_t reset_store(struct device *dev, config->vipcssctlr =3D 0x0; =20 /* Disable seq events */ - for (i =3D 0; i < drvdata->nr_seq_ctrls; i++) + for (i =3D 0; i < caps->nr_seq_ctrls; i++) config->seq_ctrl[i] =3D 0x0; config->seq_rst =3D 0x0; config->seq_state =3D 0x0; @@ -232,38 +242,38 @@ static ssize_t reset_store(struct device *dev, config->ext_inp =3D 0x0; =20 config->cntr_idx =3D 0x0; - for (i =3D 0; i < drvdata->nr_cntr; i++) { + for (i =3D 0; i < caps->nr_cntr; i++) { config->cntrldvr[i] =3D 0x0; config->cntr_ctrl[i] =3D 0x0; config->cntr_val[i] =3D 0x0; } =20 config->res_idx =3D 0x0; - for (i =3D 2; i < 2 * drvdata->nr_resource; i++) + for (i =3D 2; i < 2 * caps->nr_resource; i++) config->res_ctrl[i] =3D 0x0; =20 config->ss_idx =3D 0x0; - for (i =3D 0; i < drvdata->nr_ss_cmp; i++) { + for (i =3D 0; i < caps->nr_ss_cmp; i++) { config->ss_ctrl[i] =3D 0x0; config->ss_pe_cmp[i] =3D 0x0; } =20 config->addr_idx =3D 0x0; - for (i =3D 0; i < drvdata->nr_addr_cmp * 2; i++) { + for (i =3D 0; i < caps->nr_addr_cmp * 2; i++) { config->addr_val[i] =3D 0x0; config->addr_acc[i] =3D 0x0; config->addr_type[i] =3D ETM_ADDR_TYPE_NONE; } =20 config->ctxid_idx =3D 0x0; - for (i =3D 0; i < drvdata->numcidc; i++) + for (i =3D 0; i < caps->numcidc; i++) config->ctxid_pid[i] =3D 0x0; =20 config->ctxid_mask0 =3D 0x0; config->ctxid_mask1 =3D 0x0; =20 config->vmid_idx =3D 0x0; - for (i =3D 0; i < drvdata->numvmidc; i++) + for (i =3D 0; i < caps->numvmidc; i++) config->vmid_val[i] =3D 0x0; config->vmid_mask0 =3D 0x0; config->vmid_mask1 =3D 0x0; @@ -297,6 +307,7 @@ static ssize_t mode_store(struct device *dev, { unsigned long val, mode; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) @@ -305,7 +316,7 @@ static ssize_t mode_store(struct device *dev, raw_spin_lock(&drvdata->spinlock); config->mode =3D val & ETMv4_MODE_ALL; =20 - if (drvdata->instrp0 =3D=3D true) { + if (caps->instrp0) { /* start by clearing instruction P0 field */ config->cfg &=3D ~TRCCONFIGR_INSTP0_LOAD_STORE; if (config->mode & ETM_MODE_LOAD) @@ -323,45 +334,44 @@ static ssize_t mode_store(struct device *dev, } =20 /* bit[3], Branch broadcast mode */ - if ((config->mode & ETM_MODE_BB) && (drvdata->trcbb =3D=3D true)) + if ((config->mode & ETM_MODE_BB) && (caps->trcbb)) config->cfg |=3D TRCCONFIGR_BB; else config->cfg &=3D ~TRCCONFIGR_BB; =20 /* bit[4], Cycle counting instruction trace bit */ if ((config->mode & ETMv4_MODE_CYCACC) && - (drvdata->trccci =3D=3D true)) + (caps->trccci =3D=3D true)) config->cfg |=3D TRCCONFIGR_CCI; else config->cfg &=3D ~TRCCONFIGR_CCI; =20 /* bit[6], Context ID tracing bit */ - if ((config->mode & ETMv4_MODE_CTXID) && (drvdata->ctxid_size)) + if ((config->mode & ETMv4_MODE_CTXID) && (caps->ctxid_size)) config->cfg |=3D TRCCONFIGR_CID; else config->cfg &=3D ~TRCCONFIGR_CID; =20 - if ((config->mode & ETM_MODE_VMID) && (drvdata->vmid_size)) + if ((config->mode & ETM_MODE_VMID) && (caps->vmid_size)) config->cfg |=3D TRCCONFIGR_VMID; else config->cfg &=3D ~TRCCONFIGR_VMID; =20 /* bits[10:8], Conditional instruction tracing bit */ mode =3D ETM_MODE_COND(config->mode); - if (drvdata->trccond =3D=3D true) { + if (caps->trccond) { config->cfg &=3D ~TRCCONFIGR_COND_MASK; config->cfg |=3D mode << __bf_shf(TRCCONFIGR_COND_MASK); } =20 /* bit[11], Global timestamp tracing bit */ - if ((config->mode & ETMv4_MODE_TIMESTAMP) && (drvdata->ts_size)) + if ((config->mode & ETMv4_MODE_TIMESTAMP) && (caps->ts_size)) config->cfg |=3D TRCCONFIGR_TS; else config->cfg &=3D ~TRCCONFIGR_TS; =20 /* bit[12], Return stack enable bit */ - if ((config->mode & ETM_MODE_RETURNSTACK) && - (drvdata->retstack =3D=3D true)) + if ((config->mode & ETM_MODE_RETURNSTACK) && (caps->retstack)) config->cfg |=3D TRCCONFIGR_RS; else config->cfg &=3D ~TRCCONFIGR_RS; @@ -375,31 +385,29 @@ static ssize_t mode_store(struct device *dev, * Always set the low bit for any requested mode. Valid combos are * 0b00, 0b01 and 0b11. */ - if (mode && drvdata->q_support) + if (mode && caps->q_support) config->cfg |=3D TRCCONFIGR_QE_W_COUNTS; /* * if supported, Q elements with and without instruction * counts are enabled */ - if ((mode & BIT(1)) && (drvdata->q_support & BIT(1))) + if ((mode & BIT(1)) && (caps->q_support & BIT(1))) config->cfg |=3D TRCCONFIGR_QE_WO_COUNTS; =20 /* bit[11], AMBA Trace Bus (ATB) trigger enable bit */ - if ((config->mode & ETM_MODE_ATB_TRIGGER) && - (drvdata->atbtrig =3D=3D true)) + if ((config->mode & ETM_MODE_ATB_TRIGGER) && (caps->atbtrig)) config->eventctrl1 |=3D TRCEVENTCTL1R_ATB; else config->eventctrl1 &=3D ~TRCEVENTCTL1R_ATB; =20 /* bit[12], Low-power state behavior override bit */ - if ((config->mode & ETM_MODE_LPOVERRIDE) && - (drvdata->lpoverride =3D=3D true)) + if ((config->mode & ETM_MODE_LPOVERRIDE) && (caps->lpoverride)) config->eventctrl1 |=3D TRCEVENTCTL1R_LPOVERRIDE; else config->eventctrl1 &=3D ~TRCEVENTCTL1R_LPOVERRIDE; =20 /* bit[8], Instruction stall bit */ - if ((config->mode & ETM_MODE_ISTALL_EN) && (drvdata->stallctl =3D=3D true= )) + if ((config->mode & ETM_MODE_ISTALL_EN) && (caps->stallctl)) config->stall_ctrl |=3D TRCSTALLCTLR_ISTALL; else config->stall_ctrl &=3D ~TRCSTALLCTLR_ISTALL; @@ -411,8 +419,7 @@ static ssize_t mode_store(struct device *dev, config->stall_ctrl &=3D ~TRCSTALLCTLR_INSTPRIORITY; =20 /* bit[13], Trace overflow prevention bit */ - if ((config->mode & ETM_MODE_NOOVERFLOW) && - (drvdata->nooverflow =3D=3D true)) + if ((config->mode & ETM_MODE_NOOVERFLOW) && (caps->nooverflow)) config->stall_ctrl |=3D TRCSTALLCTLR_NOOVERFLOW; else config->stall_ctrl &=3D ~TRCSTALLCTLR_NOOVERFLOW; @@ -430,8 +437,7 @@ static ssize_t mode_store(struct device *dev, config->vinst_ctrl &=3D ~TRCVICTLR_TRCRESET; =20 /* bit[11], Whether a trace unit must trace a system error exception */ - if ((config->mode & ETM_MODE_TRACE_ERR) && - (drvdata->trc_error =3D=3D true)) + if ((config->mode & ETM_MODE_TRACE_ERR) && (caps->trc_error)) config->vinst_ctrl |=3D TRCVICTLR_TRCERR; else config->vinst_ctrl &=3D ~TRCVICTLR_TRCERR; @@ -463,13 +469,14 @@ static ssize_t pe_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; =20 raw_spin_lock(&drvdata->spinlock); - if (val > drvdata->nr_pe) { + if (val > caps->nr_pe) { raw_spin_unlock(&drvdata->spinlock); return -EINVAL; } @@ -498,13 +505,14 @@ static ssize_t event_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; =20 raw_spin_lock(&drvdata->spinlock); - switch (drvdata->nr_event) { + switch (caps->nr_event) { case 0x0: /* EVENT0, bits[7:0] */ config->eventctrl0 =3D val & 0xFF; @@ -547,6 +555,7 @@ static ssize_t event_instren_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) @@ -555,7 +564,7 @@ static ssize_t event_instren_store(struct device *dev, raw_spin_lock(&drvdata->spinlock); /* start by clearing all instruction event enable bits */ config->eventctrl1 &=3D ~TRCEVENTCTL1R_INSTEN_MASK; - switch (drvdata->nr_event) { + switch (caps->nr_event) { case 0x0: /* generate Event element for event 1 */ config->eventctrl1 |=3D val & TRCEVENTCTL1R_INSTEN_1; @@ -603,11 +612,12 @@ static ssize_t event_ts_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (!drvdata->ts_size) + if (!caps->ts_size) return -EINVAL; =20 config->ts_ctrl =3D val & ETMv4_EVENT_MASK; @@ -633,11 +643,12 @@ static ssize_t syncfreq_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (drvdata->syncpr =3D=3D true) + if (caps->syncpr) return -EINVAL; =20 config->syncfreq =3D val & ETMv4_SYNC_MASK; @@ -663,6 +674,7 @@ static ssize_t cyc_threshold_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) @@ -670,7 +682,7 @@ static ssize_t cyc_threshold_store(struct device *dev, =20 /* mask off max threshold before checking min value */ val &=3D ETM_CYC_THRESHOLD_MASK; - if (val < drvdata->ccitmin) + if (val < caps->ccitmin) return -EINVAL; =20 config->ccctlr =3D val; @@ -696,13 +708,14 @@ static ssize_t bb_ctrl_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (drvdata->trcbb =3D=3D false) + if (!caps->trcbb) return -EINVAL; - if (!drvdata->nr_addr_cmp) + if (!caps->nr_addr_cmp) return -EINVAL; =20 /* @@ -768,6 +781,7 @@ static ssize_t s_exlevel_vinst_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) @@ -777,7 +791,7 @@ static ssize_t s_exlevel_vinst_store(struct device *dev, /* clear all EXLEVEL_S bits */ config->vinst_ctrl &=3D ~TRCVICTLR_EXLEVEL_S_MASK; /* enable instruction tracing for corresponding exception level */ - val &=3D drvdata->s_ex_level; + val &=3D caps->s_ex_level; config->vinst_ctrl |=3D val << __bf_shf(TRCVICTLR_EXLEVEL_S_MASK); raw_spin_unlock(&drvdata->spinlock); return size; @@ -803,6 +817,7 @@ static ssize_t ns_exlevel_vinst_store(struct device *de= v, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) @@ -812,7 +827,7 @@ static ssize_t ns_exlevel_vinst_store(struct device *de= v, /* clear EXLEVEL_NS bits */ config->vinst_ctrl &=3D ~TRCVICTLR_EXLEVEL_NS_MASK; /* enable instruction tracing for corresponding exception level */ - val &=3D drvdata->ns_ex_level; + val &=3D caps->ns_ex_level; config->vinst_ctrl |=3D val << __bf_shf(TRCVICTLR_EXLEVEL_NS_MASK); raw_spin_unlock(&drvdata->spinlock); return size; @@ -837,11 +852,12 @@ static ssize_t addr_idx_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (val >=3D drvdata->nr_addr_cmp * 2) + if (val >=3D caps->nr_addr_cmp * 2) return -EINVAL; =20 /* @@ -1060,6 +1076,7 @@ static ssize_t addr_start_store(struct device *dev, u8 idx; unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) @@ -1067,7 +1084,7 @@ static ssize_t addr_start_store(struct device *dev, =20 raw_spin_lock(&drvdata->spinlock); idx =3D config->addr_idx; - if (!drvdata->nr_addr_cmp) { + if (!caps->nr_addr_cmp) { raw_spin_unlock(&drvdata->spinlock); return -EINVAL; } @@ -1115,6 +1132,7 @@ static ssize_t addr_stop_store(struct device *dev, u8 idx; unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) @@ -1122,7 +1140,7 @@ static ssize_t addr_stop_store(struct device *dev, =20 raw_spin_lock(&drvdata->spinlock); idx =3D config->addr_idx; - if (!drvdata->nr_addr_cmp) { + if (!caps->nr_addr_cmp) { raw_spin_unlock(&drvdata->spinlock); return -EINVAL; } @@ -1167,6 +1185,7 @@ static ssize_t addr_ctxtype_store(struct device *dev, u8 idx; char str[10] =3D ""; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (strlen(buf) >=3D 10) @@ -1181,13 +1200,13 @@ static ssize_t addr_ctxtype_store(struct device *de= v, config->addr_acc[idx] &=3D ~TRCACATRn_CONTEXTTYPE_MASK; else if (!strcmp(str, "ctxid")) { /* 0b01 The trace unit performs a Context ID */ - if (drvdata->numcidc) { + if (caps->numcidc) { config->addr_acc[idx] |=3D TRCACATRn_CONTEXTTYPE_CTXID; config->addr_acc[idx] &=3D ~TRCACATRn_CONTEXTTYPE_VMID; } } else if (!strcmp(str, "vmid")) { /* 0b10 The trace unit performs a VMID */ - if (drvdata->numvmidc) { + if (caps->numvmidc) { config->addr_acc[idx] &=3D ~TRCACATRn_CONTEXTTYPE_CTXID; config->addr_acc[idx] |=3D TRCACATRn_CONTEXTTYPE_VMID; } @@ -1196,9 +1215,9 @@ static ssize_t addr_ctxtype_store(struct device *dev, * 0b11 The trace unit performs a Context ID * comparison and a VMID */ - if (drvdata->numcidc) + if (caps->numcidc) config->addr_acc[idx] |=3D TRCACATRn_CONTEXTTYPE_CTXID; - if (drvdata->numvmidc) + if (caps->numvmidc) config->addr_acc[idx] |=3D TRCACATRn_CONTEXTTYPE_VMID; } raw_spin_unlock(&drvdata->spinlock); @@ -1230,14 +1249,15 @@ static ssize_t addr_context_store(struct device *de= v, u8 idx; unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if ((drvdata->numcidc <=3D 1) && (drvdata->numvmidc <=3D 1)) + if ((caps->numcidc <=3D 1) && (caps->numvmidc <=3D 1)) return -EINVAL; - if (val >=3D (drvdata->numcidc >=3D drvdata->numvmidc ? - drvdata->numcidc : drvdata->numvmidc)) + if (val >=3D (caps->numcidc >=3D caps->numvmidc ? + caps->numcidc : caps->numvmidc)) return -EINVAL; =20 raw_spin_lock(&drvdata->spinlock); @@ -1348,9 +1368,10 @@ static ssize_t vinst_pe_cmp_start_stop_show(struct d= evice *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 - if (!drvdata->nr_pe_cmp) + if (!caps->nr_pe_cmp) return -EINVAL; val =3D config->vipcssctlr; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); @@ -1361,11 +1382,12 @@ static ssize_t vinst_pe_cmp_start_stop_store(struct= device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (!drvdata->nr_pe_cmp) + if (!caps->nr_pe_cmp) return -EINVAL; =20 raw_spin_lock(&drvdata->spinlock); @@ -1393,13 +1415,14 @@ static ssize_t seq_idx_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 - if (!drvdata->nr_seq_ctrls) + if (!caps->nr_seq_ctrls) return -ENOTSUPP; if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (val >=3D drvdata->nr_seq_ctrls) + if (val >=3D caps->nr_seq_ctrls) return -EINVAL; =20 /* @@ -1431,11 +1454,12 @@ static ssize_t seq_state_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (val >=3D drvdata->nrseqstate) + if (val >=3D caps->nrseqstate) return -EINVAL; =20 config->seq_state =3D val; @@ -1498,11 +1522,12 @@ static ssize_t seq_reset_event_store(struct device = *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (!(drvdata->nrseqstate)) + if (!(caps->nrseqstate)) return -EINVAL; =20 config->seq_rst =3D val & ETMv4_EVENT_MASK; @@ -1528,11 +1553,12 @@ static ssize_t cntr_idx_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (val >=3D drvdata->nr_cntr) + if (val >=3D caps->nr_cntr) return -EINVAL; =20 /* @@ -1678,6 +1704,7 @@ static ssize_t res_idx_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) @@ -1686,7 +1713,7 @@ static ssize_t res_idx_store(struct device *dev, * Resource selector pair 0 is always implemented and reserved, * namely an idx with 0 and 1 is illegal. */ - if ((val < 2) || (val >=3D 2 * drvdata->nr_resource)) + if ((val < 2) || (val >=3D 2 * caps->nr_resource)) return -EINVAL; =20 /* @@ -1760,11 +1787,12 @@ static ssize_t sshot_idx_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (val >=3D drvdata->nr_ss_cmp) + if (val >=3D caps->nr_ss_cmp) return -EINVAL; =20 raw_spin_lock(&drvdata->spinlock); @@ -1882,11 +1910,12 @@ static ssize_t ctxid_idx_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (val >=3D drvdata->numcidc) + if (val >=3D caps->numcidc) return -EINVAL; =20 /* @@ -1930,6 +1959,7 @@ static ssize_t ctxid_pid_store(struct device *dev, u8 idx; unsigned long pid; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 /* @@ -1949,7 +1979,7 @@ static ssize_t ctxid_pid_store(struct device *dev, * ctxid comparator is implemented and ctxid is greater than 0 bits * in length */ - if (!drvdata->ctxid_size || !drvdata->numcidc) + if (!caps->ctxid_size || !caps->numcidc) return -EINVAL; if (kstrtoul(buf, 16, &pid)) return -EINVAL; @@ -1991,6 +2021,7 @@ static ssize_t ctxid_masks_store(struct device *dev, u8 i, j, maskbyte; unsigned long val1, val2, mask; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; int nr_inputs; =20 @@ -2006,11 +2037,11 @@ static ssize_t ctxid_masks_store(struct device *dev, * ctxid comparator is implemented and ctxid is greater than 0 bits * in length */ - if (!drvdata->ctxid_size || !drvdata->numcidc) + if (!caps->ctxid_size || !caps->numcidc) return -EINVAL; /* one mask if <=3D 4 comparators, two for up to 8 */ nr_inputs =3D sscanf(buf, "%lx %lx", &val1, &val2); - if ((drvdata->numcidc > 4) && (nr_inputs !=3D 2)) + if ((caps->numcidc > 4) && (nr_inputs !=3D 2)) return -EINVAL; =20 raw_spin_lock(&drvdata->spinlock); @@ -2018,7 +2049,7 @@ static ssize_t ctxid_masks_store(struct device *dev, * each byte[0..3] controls mask value applied to ctxid * comparator[0..3] */ - switch (drvdata->numcidc) { + switch (caps->numcidc) { case 0x1: /* COMP0, bits[7:0] */ config->ctxid_mask0 =3D val1 & 0xFF; @@ -2065,7 +2096,7 @@ static ssize_t ctxid_masks_store(struct device *dev, * of ctxid comparator0 value (corresponding to byte 0) register. */ mask =3D config->ctxid_mask0; - for (i =3D 0; i < drvdata->numcidc; i++) { + for (i =3D 0; i < caps->numcidc; i++) { /* mask value of corresponding ctxid comparator */ maskbyte =3D mask & ETMv4_EVENT_MASK; /* @@ -2108,11 +2139,12 @@ static ssize_t vmid_idx_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 if (kstrtoul(buf, 16, &val)) return -EINVAL; - if (val >=3D drvdata->numvmidc) + if (val >=3D caps->numvmidc) return -EINVAL; =20 /* @@ -2153,6 +2185,7 @@ static ssize_t vmid_val_store(struct device *dev, { unsigned long val; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; =20 /* @@ -2166,7 +2199,7 @@ static ssize_t vmid_val_store(struct device *dev, * only implemented when vmid tracing is enabled, i.e. at least one * vmid comparator is implemented and at least 8 bit vmid size */ - if (!drvdata->vmid_size || !drvdata->numvmidc) + if (!caps->vmid_size || !caps->numvmidc) return -EINVAL; if (kstrtoul(buf, 16, &val)) return -EINVAL; @@ -2206,6 +2239,7 @@ static ssize_t vmid_masks_store(struct device *dev, u8 i, j, maskbyte; unsigned long val1, val2, mask; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->config; int nr_inputs; =20 @@ -2220,11 +2254,11 @@ static ssize_t vmid_masks_store(struct device *dev, * only implemented when vmid tracing is enabled, i.e. at least one * vmid comparator is implemented and at least 8 bit vmid size */ - if (!drvdata->vmid_size || !drvdata->numvmidc) + if (!caps->vmid_size || !caps->numvmidc) return -EINVAL; /* one mask if <=3D 4 comparators, two for up to 8 */ nr_inputs =3D sscanf(buf, "%lx %lx", &val1, &val2); - if ((drvdata->numvmidc > 4) && (nr_inputs !=3D 2)) + if ((caps->numvmidc > 4) && (nr_inputs !=3D 2)) return -EINVAL; =20 raw_spin_lock(&drvdata->spinlock); @@ -2233,7 +2267,7 @@ static ssize_t vmid_masks_store(struct device *dev, * each byte[0..3] controls mask value applied to vmid * comparator[0..3] */ - switch (drvdata->numvmidc) { + switch (caps->numvmidc) { case 0x1: /* COMP0, bits[7:0] */ config->vmid_mask0 =3D val1 & 0xFF; @@ -2281,7 +2315,7 @@ static ssize_t vmid_masks_store(struct device *dev, * of vmid comparator0 value (corresponding to byte 0) register. */ mask =3D config->vmid_mask0; - for (i =3D 0; i < drvdata->numvmidc; i++) { + for (i =3D 0; i < caps->numvmidc; i++) { /* mask value of corresponding vmid comparator */ maskbyte =3D mask & ETMv4_EVENT_MASK; /* diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtrac= ing/coresight/coresight-etm4x.h index c33700711154d..ffde48b6b41b2 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -813,6 +813,97 @@ enum etm_impdef_type { ETM4_IMPDEF_FEATURE_MAX, }; =20 +/** + * struct etmv4_caps - specifics ETM capabilities + * @nr_pe: The number of processing entity available for tracing. + * @nr_pe_cmp: The number of processing entity comparator inputs that are + * available for tracing. + * @nr_addr_cmp:Number of pairs of address comparators available + * as found in ETMIDR4 0-3. + * @nr_cntr: Number of counters as found in ETMIDR5 bit 28-30. + * @nr_ext_inp: Number of external input. + * @numcidc: Number of contextID comparators. + * @numextinsel: Number of external input selector resources. + * @numvmidc: Number of VMID comparators. + * @nrseqstate: The number of sequencer states that are implemented. + * @nr_seq_ctrls: The number of sequence state transition control register= s. + * @nr_event: Indicates how many events the trace unit support. + * @nr_resource:The number of resource selection pairs available for traci= ng. + * @nr_ss_cmp: Number of single-shot comparator controls that are availabl= e. + * @trcid_size: Indicates the trace ID width. + * @ts_size: Global timestamp size field. + * @ctxid_size: Size of the context ID field to consider. + * @vmid_size: Size of the VM ID comparator to consider. + * @ccsize: Indicates the size of the cycle counter in bits. + * @ccitmin: minimum value that can be programmed in + * @s_ex_level: In secure state, indicates whether instruction tracing is + * supported for the corresponding Exception level. + * @ns_ex_level:In non-secure state, indicates whether instruction tracing= is + * supported for the corresponding Exception level. + * @q_support: Q element support characteristics. + * @os_lock_model: OSLock model. + * @instrp0: Tracing of load and store instructions + * as P0 elements is supported. + * @q_filt: Q element filtering support, if Q elements are supported. + * @trcbb: Indicates if the trace unit supports branch broadcast tracing. + * @trccond: If the trace unit supports conditional + * instruction tracing. + * @retstack: Indicates if the implementation supports a return stack. + * @trccci: Indicates if the trace unit supports cycle counting + * for instruction. + * @trc_error: Whether a trace unit can trace a system + * error exception. + * @syncpr: Indicates if an implementation has a fixed + * synchronization period. + * @stallctl: If functionality that prevents trace unit buffer overflows + * is available. + * @sysstall: Does the system support stall control of the PE? + * @nooverflow: Indicate if overflow prevention is supported. + * @atbtrig: If the implementation can support ATB triggers + * @lpoverride: If the implementation can support low-power state over. + * @skip_power_up: Indicates if an implementation can skip powering up + * the trace unit. + */ +struct etmv4_caps { + u8 nr_pe; + u8 nr_pe_cmp; + u8 nr_addr_cmp; + u8 nr_cntr; + u8 nr_ext_inp; + u8 numcidc; + u8 numextinsel; + u8 numvmidc; + u8 nrseqstate; + u8 nr_seq_ctrls; + u8 nr_event; + u8 nr_resource; + u8 nr_ss_cmp; + u8 trcid_size; + u8 ts_size; + u8 ctxid_size; + u8 vmid_size; + u8 ccsize; + u16 ccitmin; + u8 s_ex_level; + u8 ns_ex_level; + u8 q_support; + u8 os_lock_model; + bool instrp0 : 1; + bool q_filt : 1; + bool trcbb : 1; + bool trccond : 1; + bool retstack : 1; + bool trccci : 1; + bool trc_error : 1; + bool syncpr : 1; + bool stallctl : 1; + bool sysstall : 1; + bool nooverflow : 1; + bool atbtrig : 1; + bool lpoverride : 1; + bool skip_power_up : 1; +}; + /** * struct etmv4_config - configuration information related to an ETMv4 * @mode: Controls various modes supported by this ETM. @@ -820,8 +911,8 @@ enum etm_impdef_type { * @cfg: Controls the tracing options. * @eventctrl0: Controls the tracing of arbitrary events. * @eventctrl1: Controls the behavior of the events that @event_ctrl0 sele= cts. - * @stallctl: If functionality that prevents trace unit buffer overflows - * is available. + * @stall_ctrl: Enables trace unit functionality that prevents trace + * unit buffer overflows. * @ts_ctrl: Controls the insertion of global timestamps in the * trace streams. * @syncfreq: Controls how often trace synchronization requests occur. @@ -967,54 +1058,11 @@ struct etmv4_save_state { * @mode: This tracer's mode, i.e sysFS, Perf or disabled. * @cpu: The cpu this component is affined to. * @arch: ETM architecture version. - * @nr_pe: The number of processing entity available for tracing. - * @nr_pe_cmp: The number of processing entity comparator inputs that are - * available for tracing. - * @nr_addr_cmp:Number of pairs of address comparators available - * as found in ETMIDR4 0-3. - * @nr_cntr: Number of counters as found in ETMIDR5 bit 28-30. - * @nr_ext_inp: Number of external input. - * @numcidc: Number of contextID comparators. - * @numvmidc: Number of VMID comparators. - * @nrseqstate: The number of sequencer states that are implemented. - * @nr_seq_ctrls: The number of sequence state transition control register= s. - * @nr_event: Indicates how many events the trace unit support. - * @nr_resource:The number of resource selection pairs available for traci= ng. - * @nr_ss_cmp: Number of single-shot comparator controls that are availabl= e. + * @caps: ETM capabilities. * @trcid: value of the current ID for this component. - * @trcid_size: Indicates the trace ID width. - * @ts_size: Global timestamp size field. - * @ctxid_size: Size of the context ID field to consider. - * @vmid_size: Size of the VM ID comparator to consider. - * @ccsize: Indicates the size of the cycle counter in bits. - * @ccitmin: minimum value that can be programmed in - * @s_ex_level: In secure state, indicates whether instruction tracing is - * supported for the corresponding Exception level. - * @ns_ex_level:In non-secure state, indicates whether instruction tracing= is - * supported for the corresponding Exception level. * @sticky_enable: true if ETM base configuration has been done. * @boot_enable:True if we should start tracing at boot time. * @os_unlock: True if access to management registers is allowed. - * @instrp0: Tracing of load and store instructions - * as P0 elements is supported. - * @q_filt: Q element filtering support, if Q elements are supported. - * @trcbb: Indicates if the trace unit supports branch broadcast tracing. - * @trccond: If the trace unit supports conditional - * instruction tracing. - * @retstack: Indicates if the implementation supports a return stack. - * @trccci: Indicates if the trace unit supports cycle counting - * for instruction. - * @q_support: Q element support characteristics. - * @trc_error: Whether a trace unit can trace a system - * error exception. - * @syncpr: Indicates if an implementation has a fixed - * synchronization period. - * @stall_ctrl: Enables trace unit functionality that prevents trace - * unit buffer overflows. - * @sysstall: Does the system support stall control of the PE? - * @nooverflow: Indicate if overflow prevention is supported. - * @atbtrig: If the implementation can support ATB triggers - * @lpoverride: If the implementation can support low-power state over. * @trfcr: If the CPU supports FEAT_TRF, value of the TRFCR_ELx that * allows tracing at all ELs. We don't want to compute this * at runtime, due to the additional setting of TRFCR_CX when @@ -1022,8 +1070,6 @@ struct etmv4_save_state { * @active_config: structure holding current applied configuration. * @config: structure holding sysfs mode configuration. * @save_state: State to be preserved across power loss - * @skip_power_up: Indicates if an implementation can skip powering up - * the trace unit. * @paused: Indicates if the trace unit is paused. * @arch_features: Bitmap of arch features of etmv4 devices. */ @@ -1035,47 +1081,11 @@ struct etmv4_drvdata { raw_spinlock_t spinlock; int cpu; u8 arch; - u8 nr_pe; - u8 nr_pe_cmp; - u8 nr_addr_cmp; - u8 nr_cntr; - u8 nr_ext_inp; - u8 numcidc; - u8 numextinsel; - u8 numvmidc; - u8 nrseqstate; - u8 nr_seq_ctrls; - u8 nr_event; - u8 nr_resource; - u8 nr_ss_cmp; + struct etmv4_caps caps; u8 trcid; - u8 trcid_size; - u8 ts_size; - u8 ctxid_size; - u8 vmid_size; - u8 ccsize; - u16 ccitmin; - u8 s_ex_level; - u8 ns_ex_level; - u8 q_support; - u8 os_lock_model; bool sticky_enable : 1; bool boot_enable : 1; bool os_unlock : 1; - bool instrp0 : 1; - bool q_filt : 1; - bool trcbb : 1; - bool trccond : 1; - bool retstack : 1; - bool trccci : 1; - bool trc_error : 1; - bool syncpr : 1; - bool stallctl : 1; - bool sysstall : 1; - bool nooverflow : 1; - bool atbtrig : 1; - bool lpoverride : 1; - bool skip_power_up : 1; bool paused : 1; u64 trfcr; struct etmv4_config active_config; --=20 2.43.0 From nobody Fri Sep 25 08:00:10 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5D8254C4F78 for ; Tue, 15 Sep 2026 11:35:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472113; cv=none; b=CfjozH0pKIkP0K7ozoKryEPViV/d1pFhyIfFe/HMOsBTk+aoEgi1VM5CHakXpy9DgBo/bCxEl3MUFR1Ya4woyYofmux2eA37KhcpSejZwlVN+L1pJcPUEo+Fx+Vmjxb+YvOG2jQ9G3ajKRWr4yAIK7ATmgk9zq7K/ZFYg1aw+xE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472113; c=relaxed/simple; bh=/cDs6W9clgGEJzYLEVGX54ETwHYxrQIEKSpVe7Q1eX8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BcXejCAbW5YLzjDSo5EbAUl9L14psQRtdGFzCQD16pZ6V2hbiaAuzGNdzD/Egy+7pyQ0nP4WVf06Uu/Sm9GM0t8aK2EYMZb/Qo40c7vxmxGQca8YkE954ONYoIyILLGXkLSjKMkJjnl1FnyUzj1ecSYx6uAH6de92BvAoO9W11c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=HJKSxgn7; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="HJKSxgn7" 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 99A641BD0; Tue, 15 Sep 2026 04:35:00 -0700 (PDT) Received: from e129823.arm.com (e129823.arm.com [10.2.213.3]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7731F3F86F; Tue, 15 Sep 2026 04:35:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1789472104; bh=/cDs6W9clgGEJzYLEVGX54ETwHYxrQIEKSpVe7Q1eX8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=HJKSxgn7EATQ7E8Rub8VXNoo1+Ar4TS/UB6sgDNdETj+AfiDXTxRboifykm/y+LLs kl2AzFj28mMTC9KHGAT4IC+E8dojrIXDmlUhLYxozGSRt+HpGiP7fJKBZQZYiKtO+C ND/OAQT5pWdsT5kzDc9nzIZVZY0ql3ivZXccs9lA= From: Yeoreum Yun Date: Tue, 15 Sep 2026 12:34:42 +0100 Subject: [PATCH v11 7/9] coresight: etm4x: exclude ss_status from drvdata->config Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-separate_etm_cfg_v2-v11-7-d2b258d51747@arm.com> References: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> In-Reply-To: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> To: Mike Leach , James Clark , Leo Yan , Greg Kroah-Hartman , Mathieu Poirier , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev Cc: Suzuki K Poulose , Alexander Shishkin , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Yeoreum Yun X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=7976; i=yeoreum.yun@arm.com; h=from:subject:message-id; bh=/cDs6W9clgGEJzYLEVGX54ETwHYxrQIEKSpVe7Q1eX8=; b=owEB7QES/pANAwAKAW3Vw9FaxTEzAcsmYgBqqS1WxjEJEpOcbL8MfhWcuYW83ZdHIUltZLnri zPrdO1zpmuJAbMEAAEKAB0WIQQtg+CS3QUzuFh1pJ1t1cPRWsUxMwUCaqktVgAKCRBt1cPRWsUx M8W9DACqhq+k3udBWQGOiBekdLI/Ex2hXvfxHCvvvzRYn4fkNisVVk4co2jqbPGAvL8Z1vKZiEs ky5M4KsThAIPcPK7HCFgsElCFdPBnODydp+JOLxlj+iBhQt90GtdkzTDX3m44BkSvKLcl6WayvC P5onDrK3czwT5efmd5PU7AK0tBOe6aVss7x7M20+bARUx7w9tpMkmHtkQ2MGZD5DQaXoLYl1tUr N2YGw/PE9RKQBhpDahVwlf5drG/GYNu6r4YzsZ7EzO8gMRuNMz5ARvCy+jGVZvKkUlbBWBGMQdB 21s1nCuQdZ4wmaU4FNC8y+nBAWKNM26AdRIdE8IffSd2vqneOgNEUchSfedsLiHNWiIbieJR/y0 ujeOOFR+B77/E8mmNk4KVA8Ozk0ghE+hJDtEF4lvN/t94gqahNpDJxPyXTjtDAf3xJgWElUf6ZD Lh5VtAM7Mt2bII2sUzWUdlF1LoKmvSMZ98z5/xc9FXXBCKL0OIFS8AUip9qMGdgVRBQFc= X-Developer-Key: i=yeoreum.yun@arm.com; a=openpgp; fpr=2D83E092DD0533B85875A49D6DD5C3D15AC53133 The purpose of TRCSSCSRn register is to show status of the corresponding Single-shot Comparator Control and input supports. That means writable field's purpose for reset or restore from idle status not for configuration. Therefore, exclude ss_status from drvdata->config and move it to drvdata. Before this patch, clearing the PENDING and STATUS bits when enabling a perf session could trigger multiple single-shot events within the same session. This issue will be addressed in a future patch; this patch intentionally preserves the existing behavior. Reviewed-by: Leo Yan Signed-off-by: Yeoreum Yun Tested-by: Leo Yan --- drivers/hwtracing/coresight/coresight-etm4x-cfg.c | 1 - drivers/hwtracing/coresight/coresight-etm4x-core.c | 20 +++++++++--------= --- drivers/hwtracing/coresight/coresight-etm4x-sysfs.c | 10 +++++----- drivers/hwtracing/coresight/coresight-etm4x.h | 7 ++++++- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c b/drivers/hw= tracing/coresight/coresight-etm4x-cfg.c index d24f533c623d0..098aabd2b922c 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c @@ -86,7 +86,6 @@ static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *= drvdata, off_mask =3D (offset & GENMASK(11, 5)); do { CHECKREGIDX(TRCSSCCRn(0), ss_ctrl, idx, off_mask); - CHECKREGIDX(TRCSSCSRn(0), ss_status, idx, off_mask); CHECKREGIDX(TRCSSPCICRn(0), ss_pe_cmp, idx, off_mask); } while (0); } else if ((offset >=3D TRCCIDCVRn(0)) && (offset <=3D TRCVMIDCVRn(7))) { diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/h= wtracing/coresight/coresight-etm4x-core.c index 70a5c0b4fad1c..9de0c268ff954 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -95,7 +95,7 @@ static bool etm4x_sspcicrn_present(struct etmv4_drvdata *= drvdata, int n) const struct etmv4_caps *caps =3D &drvdata->caps; =20 return (n < caps->nr_ss_cmp) && caps->nr_pe_cmp && - (drvdata->config.ss_status[n] & TRCSSCSRn_PC); + (drvdata->ss_status[n] & TRCSSCSRn_PC); } =20 u64 etm4x_sysreg_read(u32 offset, bool _relaxed, bool _64bit) @@ -573,11 +573,11 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvda= ta) etm4x_relaxed_write32(csa, config->res_ctrl[i], TRCRSCTLRn(i)); =20 for (i =3D 0; i < caps->nr_ss_cmp; i++) { - /* always clear status bit on restart if using single-shot */ + /* always clear status and pending bits on restart if using single-shot = */ if (config->ss_ctrl[i] || config->ss_pe_cmp[i]) - config->ss_status[i] &=3D ~TRCSSCSRn_STATUS; + drvdata->ss_status[i] &=3D ~(TRCSSCSRn_STATUS | TRCSSCSRn_PENDING); etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i)); - etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i)); + etm4x_relaxed_write32(csa, drvdata->ss_status[i], TRCSSCSRn(i)); if (etm4x_sspcicrn_present(drvdata, i)) etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i)); } @@ -1081,7 +1081,7 @@ static void etm4_disable_hw(struct etmv4_drvdata *drv= data) =20 /* read the status of the single shot comparators */ for (i =3D 0; i < caps->nr_ss_cmp; i++) { - config->ss_status[i] =3D + drvdata->ss_status[i] =3D etm4x_relaxed_read32(csa, TRCSSCSRn(i)); } =20 @@ -1162,12 +1162,9 @@ static void etm4_disable_sysfs(struct coresight_devi= ce *csdev) drvdata, 1); =20 /* - * Userspace may read ss_status and cntr_val through sysfs after + * Userspace may read cntr_val through sysfs after * the sysfs-session has been disabled. */ - for (i =3D 0; i < caps->nr_ss_cmp; i++) - config->ss_status[i] =3D active_config->ss_status[i]; - for (i =3D 0; i < caps->nr_cntr; i++) config->cntr_val[i] =3D active_config->cntr_val[i]; =20 @@ -1525,8 +1522,9 @@ static void etm4_init_arch_data(void *info) */ caps->nr_ss_cmp =3D FIELD_GET(TRCIDR4_NUMSSCC_MASK, etmidr4); for (i =3D 0; i < caps->nr_ss_cmp; i++) { - drvdata->config.ss_status[i] =3D - etm4x_relaxed_read32(csa, TRCSSCSRn(i)); + drvdata->ss_status[i] =3D etm4x_relaxed_read32(csa, TRCSSCSRn(i)); + drvdata->ss_status[i] &=3D (TRCSSCSRn_PC | TRCSSCSRn_DV | + TRCSSCSRn_DA | TRCSSCSRn_INST); } /* NUMCIDC, bits[27:24] number of Context ID comparators for tracing */ caps->numcidc =3D FIELD_GET(TRCIDR4_NUMCIDC_MASK, etmidr4); diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/= hwtracing/coresight/coresight-etm4x-sysfs.c index f6d053f73264c..50ef2e957300f 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -1833,8 +1833,8 @@ static ssize_t sshot_ctrl_store(struct device *dev, raw_spin_lock(&drvdata->spinlock); idx =3D config->ss_idx; config->ss_ctrl[idx] =3D FIELD_PREP(TRCSSCCRn_SAC_ARC_RST_MASK, val); - /* must clear bit 31 in related status register on programming */ - config->ss_status[idx] &=3D ~TRCSSCSRn_STATUS; + /* must clear bit 31 and 30 in related status register on programming */ + drvdata->ss_status[idx] &=3D ~(TRCSSCSRn_STATUS | TRCSSCSRn_PENDING); raw_spin_unlock(&drvdata->spinlock); return size; } @@ -1848,7 +1848,7 @@ static ssize_t sshot_status_show(struct device *dev, struct etmv4_config *config =3D &drvdata->config; =20 raw_spin_lock(&drvdata->spinlock); - val =3D config->ss_status[config->ss_idx]; + val =3D drvdata->ss_status[config->ss_idx]; raw_spin_unlock(&drvdata->spinlock); return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } @@ -1885,8 +1885,8 @@ static ssize_t sshot_pe_ctrl_store(struct device *dev, raw_spin_lock(&drvdata->spinlock); idx =3D config->ss_idx; config->ss_pe_cmp[idx] =3D FIELD_PREP(TRCSSPCICRn_PC_MASK, val); - /* must clear bit 31 in related status register on programming */ - config->ss_status[idx] &=3D ~TRCSSCSRn_STATUS; + /* must clear bit 31 and 30 in related status register on programming */ + drvdata->ss_status[idx] &=3D ~(TRCSSCSRn_STATUS | TRCSSCSRn_PENDING); raw_spin_unlock(&drvdata->spinlock); return size; } diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtrac= ing/coresight/coresight-etm4x.h index ffde48b6b41b2..8c1c1364b1c44 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -213,6 +213,7 @@ #define TRCACATRn_EXLEVEL_MASK GENMASK(14, 8) =20 #define TRCSSCSRn_STATUS BIT(31) +#define TRCSSCSRn_PENDING BIT(30) #define TRCSSCCRn_SAC_ARC_RST_MASK GENMASK(24, 0) =20 #define TRCSSPCICRn_PC_MASK GENMASK(7, 0) @@ -730,6 +731,9 @@ static inline u32 etm4_res_sel_pair(u8 res_sel_idx) #define ETM_DEFAULT_ADDR_COMP 0 =20 #define TRCSSCSRn_PC BIT(3) +#define TRCSSCSRn_DV BIT(2) +#define TRCSSCSRn_DA BIT(1) +#define TRCSSCSRn_INST BIT(0) =20 /* PowerDown Control Register bits */ #define TRCPDCR_PU BIT(3) @@ -980,7 +984,6 @@ struct etmv4_config { u32 res_ctrl[ETM_MAX_RES_SEL]; /* TRCRSCTLRn */ u8 ss_idx; u32 ss_ctrl[ETM_MAX_SS_CMP]; - u32 ss_status[ETM_MAX_SS_CMP]; u32 ss_pe_cmp[ETM_MAX_SS_CMP]; u8 addr_idx; u64 addr_val[ETM_MAX_SINGLE_ADDR_CMP]; @@ -1071,6 +1074,7 @@ struct etmv4_save_state { * @config: structure holding sysfs mode configuration. * @save_state: State to be preserved across power loss * @paused: Indicates if the trace unit is paused. + * @ss_status: The status of the corresponding single-shot comparator. * @arch_features: Bitmap of arch features of etmv4 devices. */ struct etmv4_drvdata { @@ -1091,6 +1095,7 @@ struct etmv4_drvdata { struct etmv4_config active_config; struct etmv4_config config; struct etmv4_save_state *save_state; + u32 ss_status[ETM_MAX_SS_CMP]; DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX); }; =20 --=20 2.43.0 From nobody Fri Sep 25 08:00:10 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 14833496D4F for ; Tue, 15 Sep 2026 11:35:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472114; cv=none; b=rFwfpgTbsq8ja5Fl5cljAWGqwWDhE1XYdxgXYchbqhMOR7U9aylUeR8RpccygBzs9wMvjXpLI/thYwyJStC3doebi+kCkO0sImoreN43py3vhSrqDd66gEqol5RGEQMzdC2O5VodkKO2ADlqWwqoHPKCW7C5iV4FxGlrXGRznfI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472114; c=relaxed/simple; bh=zO7pbNNdvVY9biP0avSl3GlDcgZXaeVSDchAt+brQzk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oDqrJa6hL/ZJEma0chNQoTK6upCJRPA3j/0wrACP8b+UsNdzlvYUYhv4nkwt7DB2BCiH6kQ6qTtT242D6F8Trr48NqHOwnPdP8oQTAGHFWgf3T7QB7QfJDEDkNhJp//6ET+hWWyHbZDWnOtrwaBGPYQb+PJVf+JsglhUrlscZi4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=W1pmFuKq; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="W1pmFuKq" 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 9606D1D70; Tue, 15 Sep 2026 04:35:02 -0700 (PDT) Received: from e129823.arm.com (e129823.arm.com [10.2.213.3]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 797F53F86F; Tue, 15 Sep 2026 04:35:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1789472106; bh=zO7pbNNdvVY9biP0avSl3GlDcgZXaeVSDchAt+brQzk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=W1pmFuKqVIujO72GYkWJsAU8PafO8pxi07iqmeM6y0JjdjU/UYTSRnlZE1lECX3FM x32tMQqlakrW5XQDcRRYlkszZe6yG2EdlG2YenUr+zDj9ajhLCvY0HHpbLaDdNBTHu 3BZZhK5z/xBndjkz806OOE7XeFs5PK2HMhfFmWo8= From: Yeoreum Yun Date: Tue, 15 Sep 2026 12:34:43 +0100 Subject: [PATCH v11 8/9] coresight: etm4x: remove s_ex_level from config Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-separate_etm_cfg_v2-v11-8-d2b258d51747@arm.com> References: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> In-Reply-To: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> To: Mike Leach , James Clark , Leo Yan , Greg Kroah-Hartman , Mathieu Poirier , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev Cc: Suzuki K Poulose , Alexander Shishkin , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Yeoreum Yun X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=10153; i=yeoreum.yun@arm.com; h=from:subject:message-id; bh=zO7pbNNdvVY9biP0avSl3GlDcgZXaeVSDchAt+brQzk=; b=owEB7QES/pANAwAKAW3Vw9FaxTEzAcsmYgBqqS1WdPEiP3LYiv2KdGayqx1uYtxVjqNVSD1ZH 130nVCNWy6JAbMEAAEKAB0WIQQtg+CS3QUzuFh1pJ1t1cPRWsUxMwUCaqktVgAKCRBt1cPRWsUx M632DADJxeBDu3iG8qQB/Gf113sreIiwivBF+67UuJ0zv5Eo4RaaIPrnYO3ZSWZW8MB5zc9Vijq famJVesGT+q5g9Q2tk4brztquNo8OHkaJWXPg7YdaDGCW6Xxw/H4YheuNn8loPWF2iY7mcziiJ8 bNhcW2TaxI+bf0DzgeRj4sYa/QCXdRqzX5Zl84REvsG5RJBSq9vkrRV6YREPjkZfBJjIc3hW52k 2MdUta4LA97fWpKsttzLDhNQTLLHXSrKwQT/GHGXBilC/V7UBvUAYNyElUpGAYy6tKh6a+BowMr Z+NhTl6s7bQr2qvx8yy4njjZRw0aJ5OaZOk33UwGZ0now/oK1SXZZbzVWOP54qhbKOyU8OoRjsk b4O0dZu381wxh5D+2FkdQtz0PbBs9ZQiAbzaOP9zBU5+Q0v18n4Lrw4/mxFiZkWOwKHXrMtOBrQ nQfAwsNm67TXB9TwA5Mt2hA2WNraUhGmHYXZGq9V1a4gJLJpL6Xonx8Tgscaj1XtBt5x8= X-Developer-Key: i=yeoreum.yun@arm.com; a=openpgp; fpr=2D83E092DD0533B85875A49D6DD5C3D15AC53133 s_ex_level is a hardware capability rather than a configurable parameter. As such, it should not be stored in the configuration structure. Remove s_ex_level from the config structure and pass etm4_caps to the functions that need to access this capability. Signed-off-by: Yeoreum Yun Reviewed-by: Mike Leach Tested-by: Leo Yan --- drivers/hwtracing/coresight/coresight-etm4x-core.c | 58 +++++++++++++-----= ---- .../hwtracing/coresight/coresight-etm4x-sysfs.c | 2 +- drivers/hwtracing/coresight/coresight-etm4x.h | 5 +- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/h= wtracing/coresight/coresight-etm4x-core.c index 9de0c268ff954..e484e12572732 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -66,10 +66,12 @@ MODULE_PARM_DESC(pm_save_enable, "Save/restore state on power down: 1 =3D never, 2 =3D self-hosted. MMIO a= nd DT only."); =20 static struct etmv4_drvdata *etmdrvdata[NR_CPUS]; -static void etm4_set_default_config(struct etmv4_config *config); +static void etm4_set_default_config(struct etmv4_config *config, + const struct etmv4_caps *caps); static int etm4_set_event_filters(struct etmv4_drvdata *drvdata, struct perf_event *event); -static u64 etm4_get_access_type(struct etmv4_config *config); +static u64 etm4_get_access_type(struct etmv4_config *config, + const struct etmv4_caps *caps); =20 static enum cpuhp_state hp_online; =20 @@ -803,7 +805,7 @@ static int etm4_parse_event_config(struct coresight_dev= ice *csdev, config->mode |=3D ETM_MODE_EXCL_GUEST; =20 /* Always start from the default config */ - etm4_set_default_config(config); + etm4_set_default_config(config, caps); =20 /* Configure filters specified on the perf cmd line, if any. */ ret =3D etm4_set_event_filters(drvdata, event); @@ -1471,7 +1473,6 @@ static void etm4_init_arch_data(void *info) =20 /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */ caps->s_ex_level =3D FIELD_GET(TRCIDR3_EXLEVEL_S_MASK, etmidr3); - drvdata->config.s_ex_level =3D caps->s_ex_level; /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */ caps->ns_ex_level =3D FIELD_GET(TRCIDR3_EXLEVEL_NS_MASK, etmidr3); /* @@ -1556,19 +1557,22 @@ static void etm4_init_arch_data(void *info) cpu_detect_trace_filtering(drvdata); } =20 -static u32 etm4_get_victlr_access_type(struct etmv4_config *config) +static u32 etm4_get_victlr_access_type(struct etmv4_config *config, + const struct etmv4_caps *caps) { - return etm4_get_access_type(config) << __bf_shf(TRCVICTLR_EXLEVEL_MASK); + return etm4_get_access_type(config, caps) << __bf_shf(TRCVICTLR_EXLEVEL_M= ASK); } =20 /* Set ELx trace filter access in the TRCVICTLR register */ -static void etm4_set_victlr_access(struct etmv4_config *config) +static void etm4_set_victlr_access(struct etmv4_config *config, + const struct etmv4_caps *caps) { config->vinst_ctrl &=3D ~TRCVICTLR_EXLEVEL_MASK; - config->vinst_ctrl |=3D etm4_get_victlr_access_type(config); + config->vinst_ctrl |=3D etm4_get_victlr_access_type(config, caps); } =20 -static void etm4_set_default_config(struct etmv4_config *config) +static void etm4_set_default_config(struct etmv4_config *config, + const struct etmv4_caps *caps) { /* disable all events tracing */ config->eventctrl0 =3D 0x0; @@ -1587,7 +1591,7 @@ static void etm4_set_default_config(struct etmv4_conf= ig *config) config->vinst_ctrl =3D FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01); =20 /* TRCVICTLR::EXLEVEL_NS:EXLEVELS: Set kernel / user filtering */ - etm4_set_victlr_access(config); + etm4_set_victlr_access(config, caps); } =20 static u64 etm4_get_ns_access_type(struct etmv4_config *config) @@ -1619,21 +1623,24 @@ static u64 etm4_get_ns_access_type(struct etmv4_con= fig *config) * This must be shifted to the corresponding register field * for usage. */ -static u64 etm4_get_access_type(struct etmv4_config *config) +static u64 etm4_get_access_type(struct etmv4_config *config, + const struct etmv4_caps *caps) { /* All Secure exception levels are excluded from the trace */ - return etm4_get_ns_access_type(config) | (u64)config->s_ex_level; + return etm4_get_ns_access_type(config) | (u64)caps->s_ex_level; } =20 -static u64 etm4_get_comparator_access_type(struct etmv4_config *config) +static u64 etm4_get_comparator_access_type(struct etmv4_config *config, + const struct etmv4_caps *caps) { - return etm4_get_access_type(config) << TRCACATR_EXLEVEL_SHIFT; + return etm4_get_access_type(config, caps) << TRCACATR_EXLEVEL_SHIFT; } =20 static void etm4_set_comparator_filter(struct etmv4_config *config, + const struct etmv4_caps *caps, u64 start, u64 stop, int comparator) { - u64 access_type =3D etm4_get_comparator_access_type(config); + u64 access_type =3D etm4_get_comparator_access_type(config, caps); =20 /* First half of default address comparator */ config->addr_val[comparator] =3D start; @@ -1664,11 +1671,12 @@ static void etm4_set_comparator_filter(struct etmv4= _config *config, } =20 static void etm4_set_start_stop_filter(struct etmv4_config *config, + const struct etmv4_caps *caps, u64 address, int comparator, enum etm_addr_type type) { int shift; - u64 access_type =3D etm4_get_comparator_access_type(config); + u64 access_type =3D etm4_get_comparator_access_type(config, caps); =20 /* Configure the comparator */ config->addr_val[comparator] =3D address; @@ -1700,7 +1708,8 @@ static void etm4_set_default_filter(struct etmv4_conf= ig *config) config->vissctlr =3D 0x0; } =20 -static void etm4_set_default(struct etmv4_config *config) +static void etm4_set_default(struct etmv4_config *config, + const struct etmv4_caps *caps) { if (WARN_ON_ONCE(!config)) return; @@ -1712,7 +1721,7 @@ static void etm4_set_default(struct etmv4_config *con= fig) * full instruction trace - with a default filter for trace all * achieved by having no filtering. */ - etm4_set_default_config(config); + etm4_set_default_config(config, caps); etm4_set_default_filter(config); } =20 @@ -1760,6 +1769,7 @@ static int etm4_set_event_filters(struct etmv4_drvdat= a *drvdata, { int i, comparator, ret =3D 0; u64 address; + const struct etmv4_caps *caps =3D &drvdata->caps; struct etmv4_config *config =3D &drvdata->active_config; struct etm_filters *filters =3D event->hw.addr_filters; =20 @@ -1789,7 +1799,7 @@ static int etm4_set_event_filters(struct etmv4_drvdat= a *drvdata, =20 switch (type) { case ETM_ADDR_TYPE_RANGE: - etm4_set_comparator_filter(config, + etm4_set_comparator_filter(config, caps, filter->start_addr, filter->stop_addr, comparator); @@ -1810,7 +1820,7 @@ static int etm4_set_event_filters(struct etmv4_drvdat= a *drvdata, filter->stop_addr); =20 /* Configure comparator */ - etm4_set_start_stop_filter(config, address, + etm4_set_start_stop_filter(config, caps, address, comparator, type); =20 /* @@ -1846,7 +1856,8 @@ static int etm4_set_event_filters(struct etmv4_drvdat= a *drvdata, return ret; } =20 -void etm4_config_trace_mode(struct etmv4_config *config) +void etm4_config_trace_mode(struct etmv4_config *config, + const struct etmv4_caps *caps) { u32 mode; =20 @@ -1860,7 +1871,7 @@ void etm4_config_trace_mode(struct etmv4_config *conf= ig) if (!(mode & ETM_MODE_EXCL_KERN) && !(mode & ETM_MODE_EXCL_USER)) return; =20 - etm4_set_victlr_access(config); + etm4_set_victlr_access(config, caps); } =20 static int etm4_online_cpu(unsigned int cpu) @@ -2172,6 +2183,7 @@ static int etm4_add_coresight_dev(struct etm4_init_ar= g *init_arg) struct coresight_platform_data *pdata =3D NULL; struct device *dev =3D init_arg->dev; struct etmv4_drvdata *drvdata =3D dev_get_drvdata(dev); + const struct etmv4_caps *caps =3D &drvdata->caps; struct coresight_desc desc =3D { 0 }; u8 major, minor; char *type_name; @@ -2201,7 +2213,7 @@ static int etm4_add_coresight_dev(struct etm4_init_ar= g *init_arg) if (!desc.name) return -ENOMEM; =20 - etm4_set_default(&drvdata->config); + etm4_set_default(&drvdata->config, caps); =20 if (etm4x_always_pm_save(dev, init_arg->csa)) pm_save =3D true; diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/= hwtracing/coresight/coresight-etm4x-sysfs.c index 50ef2e957300f..d826033d52e24 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -443,7 +443,7 @@ static ssize_t mode_store(struct device *dev, config->vinst_ctrl &=3D ~TRCVICTLR_TRCERR; =20 if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER)) - etm4_config_trace_mode(config); + etm4_config_trace_mode(config, caps); =20 raw_spin_unlock(&drvdata->spinlock); =20 diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtrac= ing/coresight/coresight-etm4x.h index 8c1c1364b1c44..f252da868b6de 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -955,7 +955,6 @@ struct etmv4_caps { * @vmid_mask0: VM ID comparator mask for comparator 0-3. * @vmid_mask1: VM ID comparator mask for comparator 4-7. * @ext_inp: External input selection. - * @s_ex_level: Secure ELs where tracing is supported. */ struct etmv4_config { u64 mode; @@ -998,7 +997,6 @@ struct etmv4_config { u32 vmid_mask0; u32 vmid_mask1; u32 ext_inp; - u8 s_ex_level; }; =20 /** @@ -1116,7 +1114,8 @@ enum etm_addr_ctxtype { }; =20 extern const struct attribute_group *coresight_etmv4_groups[]; -void etm4_config_trace_mode(struct etmv4_config *config); +void etm4_config_trace_mode(struct etmv4_config *config, + const struct etmv4_caps *caps); =20 u64 etm4x_sysreg_read(u32 offset, bool _relaxed, bool _64bit); void etm4x_sysreg_write(u64 val, u32 offset, bool _relaxed, bool _64bit); --=20 2.43.0 From nobody Fri Sep 25 08:00:10 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id AD762476CDD for ; Tue, 15 Sep 2026 11:35:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472114; cv=none; b=YX58rV+qXKEgQyjRS8iBkZeEAMBTQLbizFOtSfgv7SeGDx1meyaLYmmav0WnN+/UtrChM9tMfX/aC3+IiiZBFuz/op9PGGRgKVUTj1oF9bNPaIylFayfaMl91viyWse+Seat05xJuMnRiZhLYEZa3+MyEO2nMRld8yaK/wbbx50= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789472114; c=relaxed/simple; bh=9vFo4hnMR5+AhjFk+/52PTzwWoe1InzOlQNdEDD6ER4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Pvl1fjxWwq4SMPzwVF6tPPc/WrQ4hQFBSvn+7VLlQJ7PL4zj9yEKllMnKV+9SA5UyZNeOc5pzhxtzs7l4C2kP6LCWmdzkGtmf5HMQrcXXsKI1v0Vy+k2qUPVm2bv+WPgxHy/06j4Z4BWSI2TWbQsTBFiM8bexPkUR1hckVceXCg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=ub37UzNg; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="ub37UzNg" 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 97503169E; Tue, 15 Sep 2026 04:35:04 -0700 (PDT) Received: from e129823.arm.com (e129823.arm.com [10.2.213.3]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7A3953F86F; Tue, 15 Sep 2026 04:35:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1789472108; bh=9vFo4hnMR5+AhjFk+/52PTzwWoe1InzOlQNdEDD6ER4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ub37UzNgGwyYp4BbSNjAUyKUl81v+Z6f0YwVQysu7HJhjUy51h2hnSRhhY2zQa1Gw oFTo+cgfbcS0I2AwlEAlQ2ZWCEEOgC8pe69UfwUTb1wStAqrmk7SeHT91lOZAGnGKX fIFMI7aue7Uiovmnv817lxMtd7K+n8POLzuTRAMA= From: Yeoreum Yun Date: Tue, 15 Sep 2026 12:34:44 +0100 Subject: [PATCH v11 9/9] coresight: etm3x: introduce struct etm_caps Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-separate_etm_cfg_v2-v11-9-d2b258d51747@arm.com> References: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> In-Reply-To: <20260915-separate_etm_cfg_v2-v11-0-d2b258d51747@arm.com> To: Mike Leach , James Clark , Leo Yan , Greg Kroah-Hartman , Mathieu Poirier , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev Cc: Suzuki K Poulose , Alexander Shishkin , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Yeoreum Yun X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=13802; i=yeoreum.yun@arm.com; h=from:subject:message-id; bh=9vFo4hnMR5+AhjFk+/52PTzwWoe1InzOlQNdEDD6ER4=; b=owEB7QES/pANAwAKAW3Vw9FaxTEzAcsmYgBqqS1XS8HWKXiLmQhnTp4AEpQjud/CX5MjcBq8U XtEnfMBWjiJAbMEAAEKAB0WIQQtg+CS3QUzuFh1pJ1t1cPRWsUxMwUCaqktVwAKCRBt1cPRWsUx M9I+C/9jdwg+q6bJMzx0xB58MQgBBEZtjiKhSw1vWSITDIrIHb/O0pptRecvfXq3V22sErBzq4U Gr+oosAlU7H4aII7t5ETEyoAA7COXic7XKQVip2k01G95aXsU+6WvX3+KrsCIg1W6bFt8GJOAGf HSb94OaIgJdZY/RfuSTq83CeR91YKBVsRNc+7+Cw/05Gtu0GKSu0cHrFsH98ylGzb1xHaSOqe9a Ox9Svsd71v/yQJbBYq7MuNeuivLxkudc8vQ95PdBb1AwLoF6D9jiQsE2d5UOe7MEafwV4fFs2a3 pIJK6mfBE5EXeH0sUhMr4310X7/0iRVLKUMxBBwhYXcbgpLTFeYcBiQ+ZJCnhbgh8f/ZM29sxF0 +8Ibosp+WBhDLukxRj/r1BzQLlHkZK/GcEVOD9Ius5sg60WxgdIeSnhfKHHqmXidRPCmsLQb+ls aodS6RAVo55MBP2iRteFngV7nVgeY09uhoXLjBO1w4QD/wKhUGWwM2Y+BjS/hhYlGZ1ms= X-Developer-Key: i=yeoreum.yun@arm.com; a=openpgp; fpr=2D83E092DD0533B85875A49D6DD5C3D15AC53133 Introduce struct etm_caps to describe ETMv3 capabilities and move capabilities information into it. Since drvdata->etmccr and drvdata->etmccer are used to check whether it supports fifofull logic and timestamping, remove etmccr and etmccer field from drvdata and add relevant fields in etm_caps structure. Signed-off-by: Yeoreum Yun Reviewed-by: Mike Leach Tested-by: Leo Yan --- drivers/hwtracing/coresight/coresight-etm.h | 42 +++++++++++++-----= ---- drivers/hwtracing/coresight/coresight-etm3x-core.c | 42 +++++++++++++-----= ---- .../hwtracing/coresight/coresight-etm3x-sysfs.c | 24 ++++++++----- 3 files changed, 66 insertions(+), 42 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracin= g/coresight/coresight-etm.h index f3796162168d4..cb5f18dcdd974 100644 --- a/drivers/hwtracing/coresight/coresight-etm.h +++ b/drivers/hwtracing/coresight/coresight-etm.h @@ -140,6 +140,30 @@ ETM_ADD_COMP_0 | \ ETM_EVENT_NOT_A) =20 +/** + * struct etm_caps - specifics ETM capabilities + * @port_size: port size as reported by ETMCR bit 4-6 and 21. + * @nr_addr_cmp:Number of pairs of address comparators as found in ETMCCR. + * @nr_cntr: Number of counters as found in ETMCCR bit 13-15. + * @nr_ext_inp: Number of external input as found in ETMCCR bit 17-19. + * @nr_ext_out: Number of external output as found in ETMCCR bit 20-22. + * @nr_ctxid_cmp: Number of contextID comparators as found in ETMCCR bit 2= 4-25. + * @fifofull: FIFOFULL logic is present. + * @timestamp: Timestamping is implemented. + * @retstack: Return stack is implemented. + */ +struct etm_caps { + int port_size; + u8 nr_addr_cmp; + u8 nr_cntr; + u8 nr_ext_inp; + u8 nr_ext_out; + u8 nr_ctxid_cmp; + bool fifofull : 1; + bool timestamp : 1; + bool retstack : 1; +}; + /** * struct etm_config - configuration information related to an ETM * @mode: controls various modes supported by this ETM/PTM. @@ -212,19 +236,12 @@ struct etm_config { * @csdev: component vitals needed by the framework. * @spinlock: only one at a time pls. * @cpu: the cpu this component is affined to. - * @port_size: port size as reported by ETMCR bit 4-6 and 21. * @arch: ETM/PTM version number. + * @caps: ETM capabilities. * @use_cpu14: true if management registers need to be accessed via CP14. * @sticky_enable: true if ETM base configuration has been done. * @boot_enable:true if we should start tracing at boot time. * @os_unlock: true if access to management registers is allowed. - * @nr_addr_cmp:Number of pairs of address comparators as found in ETMCCR. - * @nr_cntr: Number of counters as found in ETMCCR bit 13-15. - * @nr_ext_inp: Number of external input as found in ETMCCR bit 17-19. - * @nr_ext_out: Number of external output as found in ETMCCR bit 20-22. - * @nr_ctxid_cmp: Number of contextID comparators as found in ETMCCR bit 2= 4-25. - * @etmccr: value of register ETMCCR. - * @etmccer: value of register ETMCCER. * @traceid: value of the current ID for this component. * @active_config: structure holding current running configuration. * @config: structure holding sysfs mode configuration. @@ -235,19 +252,12 @@ struct etm_drvdata { struct coresight_device *csdev; spinlock_t spinlock; int cpu; - int port_size; u8 arch; + struct etm_caps caps; bool use_cp14; bool sticky_enable; bool boot_enable; bool os_unlock; - u8 nr_addr_cmp; - u8 nr_cntr; - u8 nr_ext_inp; - u8 nr_ext_out; - u8 nr_ctxid_cmp; - u32 etmccr; - u32 etmccer; u32 traceid; struct etm_config active_config; struct etm_config config; diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/h= wtracing/coresight/coresight-etm3x-core.c index 12bb38dc596e7..79c7cbe2084de 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c @@ -308,6 +308,7 @@ void etm_config_trace_mode(struct etm_config *config) static int etm_parse_event_config(struct etm_drvdata *drvdata, struct perf_event *event) { + const struct etm_caps *caps =3D &drvdata->caps; struct etm_config *config =3D &drvdata->active_config; struct perf_event_attr *attr =3D &event->attr; u8 ts_level; @@ -356,8 +357,7 @@ static int etm_parse_event_config(struct etm_drvdata *d= rvdata, * has ret stack) on the same SoC. So only enable when it can be honored * - trace will still continue normally otherwise. */ - if (ATTR_CFG_GET_FLD(attr, retstack) && - (drvdata->etmccer & ETMCCER_RETSTACK)) + if (ATTR_CFG_GET_FLD(attr, retstack) && (caps->retstack)) config->ctrl |=3D ETMCR_RETURN_STACK; =20 return 0; @@ -367,6 +367,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) { int i, rc; u32 etmcr; + const struct etm_caps *caps =3D &drvdata->caps; struct etm_config *config =3D &drvdata->active_config; struct coresight_device *csdev =3D drvdata->csdev; =20 @@ -388,7 +389,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) etmcr =3D etm_readl(drvdata, ETMCR); /* Clear setting from a previous run if need be */ etmcr &=3D ~ETM3X_SUPPORTED_OPTIONS; - etmcr |=3D drvdata->port_size; + etmcr |=3D caps->port_size; etmcr |=3D ETMCR_ETM_EN; etm_writel(drvdata, config->ctrl | etmcr, ETMCR); etm_writel(drvdata, config->trigger_event, ETMTRIGGER); @@ -396,11 +397,11 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) etm_writel(drvdata, config->enable_event, ETMTEEVR); etm_writel(drvdata, config->enable_ctrl1, ETMTECR1); etm_writel(drvdata, config->fifofull_level, ETMFFLR); - for (i =3D 0; i < drvdata->nr_addr_cmp; i++) { + for (i =3D 0; i < caps->nr_addr_cmp; i++) { etm_writel(drvdata, config->addr_val[i], ETMACVRn(i)); etm_writel(drvdata, config->addr_acctype[i], ETMACTRn(i)); } - for (i =3D 0; i < drvdata->nr_cntr; i++) { + for (i =3D 0; i < caps->nr_cntr; i++) { etm_writel(drvdata, config->cntr_rld_val[i], ETMCNTRLDVRn(i)); etm_writel(drvdata, config->cntr_event[i], ETMCNTENRn(i)); etm_writel(drvdata, config->cntr_rld_event[i], @@ -414,9 +415,9 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) etm_writel(drvdata, config->seq_32_event, ETMSQ32EVR); etm_writel(drvdata, config->seq_13_event, ETMSQ13EVR); etm_writel(drvdata, config->seq_curr_state, ETMSQR); - for (i =3D 0; i < drvdata->nr_ext_out; i++) + for (i =3D 0; i < caps->nr_ext_out; i++) etm_writel(drvdata, ETM_DEFAULT_EVENT_VAL, ETMEXTOUTEVRn(i)); - for (i =3D 0; i < drvdata->nr_ctxid_cmp; i++) + for (i =3D 0; i < caps->nr_ctxid_cmp; i++) etm_writel(drvdata, config->ctxid_pid[i], ETMCIDCVRn(i)); etm_writel(drvdata, config->ctxid_mask, ETMCIDCMR); etm_writel(drvdata, config->sync_freq, ETMSYNCFR); @@ -562,6 +563,7 @@ static int etm_enable(struct coresight_device *csdev, s= truct perf_event *event, static void etm_disable_hw(struct etm_drvdata *drvdata) { int i; + const struct etm_caps *caps =3D &drvdata->caps; struct etm_config *config =3D &drvdata->active_config; struct coresight_device *csdev =3D drvdata->csdev; =20 @@ -571,7 +573,7 @@ static void etm_disable_hw(struct etm_drvdata *drvdata) /* Read back sequencer and counters for post trace analysis */ config->seq_curr_state =3D (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK); =20 - for (i =3D 0; i < drvdata->nr_cntr; i++) + for (i =3D 0; i < caps->nr_cntr; i++) config->cntr_val[i] =3D etm_readl(drvdata, ETMCNTVRn(i)); =20 etm_set_pwrdwn(drvdata); @@ -626,6 +628,7 @@ static void etm_disable_perf(struct coresight_device *c= sdev) static void etm_disable_sysfs(struct coresight_device *csdev) { struct etm_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); + const struct etm_caps *caps =3D &drvdata->caps; struct etm_config *config =3D &drvdata->config; const struct etm_config *active_config =3D &drvdata->active_config; int i; @@ -641,7 +644,7 @@ static void etm_disable_sysfs(struct coresight_device *= csdev) * Userspace may read seq_curr_state and cntr_val through sysfs * after the sysfs-session has been disabled. */ - for (i =3D 0; i < drvdata->nr_cntr; i++) + for (i =3D 0; i < caps->nr_cntr; i++) config->cntr_val[i] =3D active_config->cntr_val[i]; =20 config->seq_curr_state =3D active_config->seq_curr_state; @@ -726,7 +729,9 @@ static void etm_init_arch_data(void *info) { u32 etmidr; u32 etmccr; + u32 etmccer; struct etm_drvdata *drvdata =3D info; + struct etm_caps *caps =3D &drvdata->caps; =20 /* Make sure all registers are accessible */ etm_os_unlock(drvdata); @@ -751,16 +756,19 @@ static void etm_init_arch_data(void *info) /* Find all capabilities */ etmidr =3D etm_readl(drvdata, ETMIDR); drvdata->arch =3D BMVAL(etmidr, 4, 11); - drvdata->port_size =3D etm_readl(drvdata, ETMCR) & PORT_SIZE_MASK; + caps->port_size =3D etm_readl(drvdata, ETMCR) & PORT_SIZE_MASK; + + etmccer =3D etm_readl(drvdata, ETMCCER); + caps->timestamp =3D !!(etmccer & ETMCCER_TIMESTAMP); + caps->retstack =3D !!(etmccer & ETMCCER_RETSTACK); =20 - drvdata->etmccer =3D etm_readl(drvdata, ETMCCER); etmccr =3D etm_readl(drvdata, ETMCCR); - drvdata->etmccr =3D etmccr; - drvdata->nr_addr_cmp =3D BMVAL(etmccr, 0, 3) * 2; - drvdata->nr_cntr =3D BMVAL(etmccr, 13, 15); - drvdata->nr_ext_inp =3D BMVAL(etmccr, 17, 19); - drvdata->nr_ext_out =3D BMVAL(etmccr, 20, 22); - drvdata->nr_ctxid_cmp =3D BMVAL(etmccr, 24, 25); + caps->fifofull =3D !!(etmccr & ETMCCR_FIFOFULL); + caps->nr_addr_cmp =3D BMVAL(etmccr, 0, 3) * 2; + caps->nr_cntr =3D BMVAL(etmccr, 13, 15); + caps->nr_ext_inp =3D BMVAL(etmccr, 17, 19); + caps->nr_ext_out =3D BMVAL(etmccr, 20, 22); + caps->nr_ctxid_cmp =3D BMVAL(etmccr, 24, 25); =20 coresight_clear_self_claim_tag_unlocked(&drvdata->csa); etm_set_pwrdwn(drvdata); diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/= hwtracing/coresight/coresight-etm3x-sysfs.c index 2c8c129228589..36d4673537930 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c @@ -53,8 +53,9 @@ static ssize_t nr_addr_cmp_show(struct device *dev, { unsigned long val; struct etm_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etm_caps *caps =3D &drvdata->caps; =20 - val =3D drvdata->nr_addr_cmp; + val =3D caps->nr_addr_cmp; return sprintf(buf, "%#lx\n", val); } static DEVICE_ATTR_RO(nr_addr_cmp); @@ -63,8 +64,9 @@ static ssize_t nr_cntr_show(struct device *dev, struct device_attribute *attr, char *buf) { unsigned long val; struct etm_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etm_caps *caps =3D &drvdata->caps; =20 - val =3D drvdata->nr_cntr; + val =3D caps->nr_cntr; return sprintf(buf, "%#lx\n", val); } static DEVICE_ATTR_RO(nr_cntr); @@ -75,7 +77,7 @@ static ssize_t nr_ctxid_cmp_show(struct device *dev, unsigned long val; struct etm_drvdata *drvdata =3D dev_get_drvdata(dev->parent); =20 - val =3D drvdata->nr_ctxid_cmp; + val =3D drvdata->caps.nr_ctxid_cmp; return sprintf(buf, "%#lx\n", val); } static DEVICE_ATTR_RO(nr_ctxid_cmp); @@ -115,7 +117,7 @@ static ssize_t reset_store(struct device *dev, memset(config, 0, sizeof(struct etm_config)); config->mode =3D ETM_MODE_EXCLUDE; config->trigger_event =3D ETM_DEFAULT_EVENT_VAL; - for (i =3D 0; i < drvdata->nr_addr_cmp; i++) { + for (i =3D 0; i < drvdata->caps.nr_addr_cmp; i++) { config->addr_type[i] =3D ETM_ADDR_TYPE_NONE; } =20 @@ -146,6 +148,7 @@ static ssize_t mode_store(struct device *dev, int ret; unsigned long val; struct etm_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etm_caps *caps =3D &drvdata->caps; struct etm_config *config =3D &drvdata->config; =20 ret =3D kstrtoul(buf, 16, &val); @@ -166,7 +169,7 @@ static ssize_t mode_store(struct device *dev, config->ctrl &=3D ~ETMCR_CYC_ACC; =20 if (config->mode & ETM_MODE_STALL) { - if (!(drvdata->etmccr & ETMCCR_FIFOFULL)) { + if (!caps->fifofull) { dev_warn(dev, "stall mode not supported\n"); ret =3D -EINVAL; goto err_unlock; @@ -176,7 +179,7 @@ static ssize_t mode_store(struct device *dev, config->ctrl &=3D ~ETMCR_STALL_MODE; =20 if (config->mode & ETM_MODE_TIMESTAMP) { - if (!(drvdata->etmccer & ETMCCER_TIMESTAMP)) { + if (!caps->timestamp) { dev_warn(dev, "timestamp not supported\n"); ret =3D -EINVAL; goto err_unlock; @@ -321,13 +324,14 @@ static ssize_t addr_idx_store(struct device *dev, int ret; unsigned long val; struct etm_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etm_caps *caps =3D &drvdata->caps; struct etm_config *config =3D &drvdata->config; =20 ret =3D kstrtoul(buf, 16, &val); if (ret) return ret; =20 - if (val >=3D drvdata->nr_addr_cmp) + if (val >=3D caps->nr_addr_cmp) return -EINVAL; =20 /* @@ -624,13 +628,14 @@ static ssize_t cntr_idx_store(struct device *dev, int ret; unsigned long val; struct etm_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etm_caps *caps =3D &drvdata->caps; struct etm_config *config =3D &drvdata->config; =20 ret =3D kstrtoul(buf, 16, &val); if (ret) return ret; =20 - if (val >=3D drvdata->nr_cntr) + if (val >=3D caps->nr_cntr) return -EINVAL; /* * Use spinlock to ensure index doesn't change while it gets @@ -1030,13 +1035,14 @@ static ssize_t ctxid_idx_store(struct device *dev, int ret; unsigned long val; struct etm_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + const struct etm_caps *caps =3D &drvdata->caps; struct etm_config *config =3D &drvdata->config; =20 ret =3D kstrtoul(buf, 16, &val); if (ret) return ret; =20 - if (val >=3D drvdata->nr_ctxid_cmp) + if (val >=3D caps->nr_ctxid_cmp) return -EINVAL; =20 /* --=20 2.43.0