From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D972C433F5 for ; Sun, 27 Feb 2022 20:56:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231616AbiB0U5G (ORCPT ); Sun, 27 Feb 2022 15:57:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58746 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230320AbiB0U5B (ORCPT ); Sun, 27 Feb 2022 15:57:01 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E3A9A31222 for ; Sun, 27 Feb 2022 12:56:23 -0800 (PST) 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 AF331106F; Sun, 27 Feb 2022 12:56:23 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 509053F66F; Sun, 27 Feb 2022 12:56:22 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 01/16] firmware: arm_scmi: Simplify scmi_devm_notifier_unregister Date: Sun, 27 Feb 2022 20:55:53 +0000 Message-Id: <20220227205608.30812-2-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Unregistering SCMI notifications using the managed devres interface can be done providing as a reference simply the previously successfully registered notification block since it could have been registered only on one kernel notification_chain: drop any reference to SCMI protocol, events and sources. Devres internal helpers can search for the provided notification block reference and, once found, the associated devres object will already provide the above SCMI references for the event. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/notify.c | 30 ++++-------------------------- include/linux/scmi_protocol.h | 2 -- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi= /notify.c index 0efd20cd9d69..7d0b01b59616 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -1498,17 +1498,12 @@ static int scmi_devm_notifier_register(struct scmi_= device *sdev, static int scmi_devm_notifier_match(struct device *dev, void *res, void *d= ata) { struct scmi_notifier_devres *dres =3D res; - struct scmi_notifier_devres *xres =3D data; + struct notifier_block *nb =3D data; =20 - if (WARN_ON(!dres || !xres)) + if (WARN_ON(!dres || !nb)) return 0; =20 - return dres->proto_id =3D=3D xres->proto_id && - dres->evt_id =3D=3D xres->evt_id && - dres->nb =3D=3D xres->nb && - ((!dres->src_id && !xres->src_id) || - (dres->src_id && xres->src_id && - dres->__src_id =3D=3D xres->__src_id)); + return dres->nb =3D=3D nb; } =20 /** @@ -1516,10 +1511,6 @@ static int scmi_devm_notifier_match(struct device *d= ev, void *res, void *data) * notifier_block for an event * @sdev: A reference to an scmi_device whose embedded struct device is to * be used for devres accounting. - * @proto_id: Protocol ID - * @evt_id: Event ID - * @src_id: Source ID, when NULL register for events coming form ALL possi= ble - * sources * @nb: A standard notifier block to register for the specified event * * Generic devres managed helper to explicitly un-register a notifier_block @@ -1529,25 +1520,12 @@ static int scmi_devm_notifier_match(struct device *= dev, void *res, void *data) * Return: 0 on Success */ static int scmi_devm_notifier_unregister(struct scmi_device *sdev, - u8 proto_id, u8 evt_id, - const u32 *src_id, struct notifier_block *nb) { int ret; - struct scmi_notifier_devres dres; - - dres.handle =3D sdev->handle; - dres.proto_id =3D proto_id; - dres.evt_id =3D evt_id; - if (src_id) { - dres.__src_id =3D *src_id; - dres.src_id =3D &dres.__src_id; - } else { - dres.src_id =3D NULL; - } =20 ret =3D devres_release(&sdev->dev, scmi_devm_release_notifier, - scmi_devm_notifier_match, &dres); + scmi_devm_notifier_match, nb); =20 WARN_ON(ret); =20 diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index b87551f41f9f..b0652f1411b9 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -595,8 +595,6 @@ struct scmi_notify_ops { const u32 *src_id, struct notifier_block *nb); int (*devm_event_notifier_unregister)(struct scmi_device *sdev, - u8 proto_id, u8 evt_id, - const u32 *src_id, struct notifier_block *nb); int (*event_notifier_register)(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9EC66C433EF for ; Sun, 27 Feb 2022 20:56:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231712AbiB0U5L (ORCPT ); Sun, 27 Feb 2022 15:57:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58760 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229482AbiB0U5D (ORCPT ); Sun, 27 Feb 2022 15:57:03 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 811482FFE7 for ; Sun, 27 Feb 2022 12:56:25 -0800 (PST) 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 4D90811FB; Sun, 27 Feb 2022 12:56:25 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E4B5D3F66F; Sun, 27 Feb 2022 12:56:23 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 02/16] firmware: arm_scmi: Make protocols init fail on basic errors Date: Sun, 27 Feb 2022 20:55:54 +0000 Message-Id: <20220227205608.30812-3-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Bail out of protocol initialization routine early when basic information about protocol version and attributes could not be retrieved: failing to act this way can lead to a successfully initialized SCMI protocol which is in fact not functional. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/base.c | 5 ++++- drivers/firmware/arm_scmi/clock.c | 8 ++++++-- drivers/firmware/arm_scmi/perf.c | 10 +++++++--- drivers/firmware/arm_scmi/power.c | 10 +++++++--- drivers/firmware/arm_scmi/reset.c | 10 +++++++--- drivers/firmware/arm_scmi/sensors.c | 4 +++- drivers/firmware/arm_scmi/system.c | 5 ++++- 7 files changed, 38 insertions(+), 14 deletions(-) diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/b= ase.c index f5219334fd3a..ebaef5d320af 100644 --- a/drivers/firmware/arm_scmi/base.c +++ b/drivers/firmware/arm_scmi/base.c @@ -359,7 +359,10 @@ static int scmi_base_protocol_init(const struct scmi_p= rotocol_handle *ph) rev->minor_ver =3D PROTOCOL_REV_MINOR(version); ph->set_priv(ph, rev); =20 - scmi_base_attributes_get(ph); + ret =3D scmi_base_attributes_get(ph); + if (ret) + return ret; + scmi_base_vendor_id_get(ph, false); scmi_base_vendor_id_get(ph, true); scmi_base_implementation_version_get(ph); diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/= clock.c index cf6fed6dec77..e2059d2025a2 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -360,7 +360,9 @@ static int scmi_clock_protocol_init(const struct scmi_p= rotocol_handle *ph) int clkid, ret; struct clock_info *cinfo; =20 - ph->xops->version_get(ph, &version); + ret =3D ph->xops->version_get(ph, &version); + if (ret) + return ret; =20 dev_dbg(ph->dev, "Clock Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); @@ -369,7 +371,9 @@ static int scmi_clock_protocol_init(const struct scmi_p= rotocol_handle *ph) if (!cinfo) return -ENOMEM; =20 - scmi_clock_protocol_attributes_get(ph, cinfo); + ret =3D scmi_clock_protocol_attributes_get(ph, cinfo); + if (ret) + return ret; =20 cinfo->clk =3D devm_kcalloc(ph->dev, cinfo->num_clocks, sizeof(*cinfo->clk), GFP_KERNEL); diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/p= erf.c index f4cd5193b961..e9f68b91580c 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -873,11 +873,13 @@ static const struct scmi_protocol_events perf_protoco= l_events =3D { =20 static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph) { - int domain; + int domain, ret; u32 version; struct scmi_perf_info *pinfo; =20 - ph->xops->version_get(ph, &version); + ret =3D ph->xops->version_get(ph, &version); + if (ret) + return ret; =20 dev_dbg(ph->dev, "Performance Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); @@ -886,7 +888,9 @@ static int scmi_perf_protocol_init(const struct scmi_pr= otocol_handle *ph) if (!pinfo) return -ENOMEM; =20 - scmi_perf_attributes_get(ph, pinfo); + ret =3D scmi_perf_attributes_get(ph, pinfo); + if (ret) + return ret; =20 pinfo->dom_info =3D devm_kcalloc(ph->dev, pinfo->num_domains, sizeof(*pinfo->dom_info), GFP_KERNEL); diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/= power.c index ad2ab080f344..0f0b94f0b624 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -280,11 +280,13 @@ static const struct scmi_protocol_events power_protoc= ol_events =3D { =20 static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph) { - int domain; + int domain, ret; u32 version; struct scmi_power_info *pinfo; =20 - ph->xops->version_get(ph, &version); + ret =3D ph->xops->version_get(ph, &version); + if (ret) + return ret; =20 dev_dbg(ph->dev, "Power Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); @@ -293,7 +295,9 @@ static int scmi_power_protocol_init(const struct scmi_p= rotocol_handle *ph) if (!pinfo) return -ENOMEM; =20 - scmi_power_attributes_get(ph, pinfo); + ret =3D scmi_power_attributes_get(ph, pinfo); + if (ret) + return ret; =20 pinfo->dom_info =3D devm_kcalloc(ph->dev, pinfo->num_domains, sizeof(*pinfo->dom_info), GFP_KERNEL); diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/= reset.c index 9bf2478ec6d1..9cdbd133db10 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -293,11 +293,13 @@ static const struct scmi_protocol_events reset_protoc= ol_events =3D { =20 static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph) { - int domain; + int domain, ret; u32 version; struct scmi_reset_info *pinfo; =20 - ph->xops->version_get(ph, &version); + ret =3D ph->xops->version_get(ph, &version); + if (ret) + return ret; =20 dev_dbg(ph->dev, "Reset Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); @@ -306,7 +308,9 @@ static int scmi_reset_protocol_init(const struct scmi_p= rotocol_handle *ph) if (!pinfo) return -ENOMEM; =20 - scmi_reset_attributes_get(ph, pinfo); + ret =3D scmi_reset_attributes_get(ph, pinfo); + if (ret) + return ret; =20 pinfo->dom_info =3D devm_kcalloc(ph->dev, pinfo->num_domains, sizeof(*pinfo->dom_info), GFP_KERNEL); diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scm= i/sensors.c index cdbb287bd8bc..f37ac9824a87 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -966,7 +966,9 @@ static int scmi_sensors_protocol_init(const struct scmi= _protocol_handle *ph) int ret; struct sensors_info *sinfo; =20 - ph->xops->version_get(ph, &version); + ret =3D ph->xops->version_get(ph, &version); + if (ret) + return ret; =20 dev_dbg(ph->dev, "Sensor Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi= /system.c index e5175ef73b40..cbfc19f7a463 100644 --- a/drivers/firmware/arm_scmi/system.c +++ b/drivers/firmware/arm_scmi/system.c @@ -113,10 +113,13 @@ static const struct scmi_protocol_events system_proto= col_events =3D { =20 static int scmi_system_protocol_init(const struct scmi_protocol_handle *ph) { + int ret; u32 version; struct scmi_system_info *pinfo; =20 - ph->xops->version_get(ph, &version); + ret =3D ph->xops->version_get(ph, &version); + if (ret) + return ret; =20 dev_dbg(ph->dev, "System Power Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4A5BFC433EF for ; Sun, 27 Feb 2022 20:56:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231740AbiB0U5Q (ORCPT ); Sun, 27 Feb 2022 15:57:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231447AbiB0U5E (ORCPT ); Sun, 27 Feb 2022 15:57:04 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 1D5932FFE7 for ; Sun, 27 Feb 2022 12:56:27 -0800 (PST) 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 DEEEF12FC; Sun, 27 Feb 2022 12:56:26 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8359E3F66F; Sun, 27 Feb 2022 12:56:25 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 03/16] firmware: arm_scmi: Add multiple protocols registration support Date: Sun, 27 Feb 2022 20:55:55 +0000 Message-Id: <20220227205608.30812-4-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add the capability for one SCMI driver to register with the core SCMI stack to use multiple SCMI protocols: in such a case the SCMI driver probe function will end up being called once for each registered protocol which have been also found as implemented on the platform. This is especially useful in testing scenarios. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/bus.c | 4 ++-- drivers/firmware/arm_scmi/common.h | 4 ++-- drivers/firmware/arm_scmi/driver.c | 24 ++++++++++++++++++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bu= s.c index f6fe723ab869..e417e84249f2 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -135,7 +135,7 @@ int scmi_driver_register(struct scmi_driver *driver, st= ruct module *owner, if (!driver->probe) return -EINVAL; =20 - retval =3D scmi_protocol_device_request(driver->id_table); + retval =3D scmi_protocol_table_register(driver->id_table); if (retval) return retval; =20 @@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(scmi_driver_register); void scmi_driver_unregister(struct scmi_driver *driver) { driver_unregister(&driver->driver); - scmi_protocol_device_unrequest(driver->id_table); + scmi_protocol_table_unregister(driver->id_table); } EXPORT_SYMBOL_GPL(scmi_driver_unregister); =20 diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi= /common.h index 4fda84bfab42..ffaf74a36b30 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -388,8 +388,8 @@ struct scmi_transport_ops { bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer); }; =20 -int scmi_protocol_device_request(const struct scmi_device_id *id_table); -void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table); +int scmi_protocol_table_register(const struct scmi_device_id *id_table); +void scmi_protocol_table_unregister(const struct scmi_device_id *id_table); struct scmi_device *scmi_child_dev_find(struct device *parent, int prot_id, const char *name); =20 diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi= /driver.c index 4cb9e0ad7af5..8d356d4da0bd 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1771,7 +1771,7 @@ static void scmi_create_protocol_devices(struct devic= e_node *np, * * Return: 0 on Success */ -int scmi_protocol_device_request(const struct scmi_device_id *id_table) +static int scmi_protocol_device_request(const struct scmi_device_id *id_ta= ble) { int ret =3D 0; unsigned int id =3D 0; @@ -1882,6 +1882,17 @@ int scmi_protocol_device_request(const struct scmi_d= evice_id *id_table) return ret; } =20 +int scmi_protocol_table_register(const struct scmi_device_id *id_table) +{ + int ret =3D 0; + const struct scmi_device_id *entry; + + for (entry =3D id_table; entry->name && ret =3D=3D 0; entry++) + ret =3D scmi_protocol_device_request(entry); + + return ret; +} + /** * scmi_protocol_device_unrequest - Helper to unrequest a device * @@ -1896,7 +1907,8 @@ int scmi_protocol_device_request(const struct scmi_de= vice_id *id_table) * that cannot be safely destroyed till the whole SCMI stack is removed. * (unless adding further burden of refcounting.) */ -void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table) +static void +scmi_protocol_device_unrequest(const struct scmi_device_id *id_table) { struct list_head *phead; =20 @@ -1925,6 +1937,14 @@ void scmi_protocol_device_unrequest(const struct scm= i_device_id *id_table) mutex_unlock(&scmi_requested_devices_mtx); } =20 +void scmi_protocol_table_unregister(const struct scmi_device_id *id_table) +{ + const struct scmi_device_id *entry; + + for (entry =3D id_table; entry->name; entry++) + scmi_protocol_device_unrequest(entry); +} + static int scmi_cleanup_txrx_channels(struct scmi_info *info) { int ret; --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 613B3C433EF for ; Sun, 27 Feb 2022 20:56:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231849AbiB0U5Y (ORCPT ); Sun, 27 Feb 2022 15:57:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58824 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231640AbiB0U5G (ORCPT ); Sun, 27 Feb 2022 15:57:06 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B7C653298D for ; Sun, 27 Feb 2022 12:56:28 -0800 (PST) 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 7DF5D1424; Sun, 27 Feb 2022 12:56:28 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 20C7D3F66F; Sun, 27 Feb 2022 12:56:27 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 04/16] firmware: arm_scmi: Add .version_get protocol operation Date: Sun, 27 Feb 2022 20:55:56 +0000 Message-Id: <20220227205608.30812-5-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add new .version_get protocol operation so as to allow interested SCMI driver users to lookup protocol versions implemented by the underlying SCMI platform. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/clock.c | 1 + drivers/firmware/arm_scmi/common.h | 20 ++++++++++++++++++++ drivers/firmware/arm_scmi/perf.c | 1 + drivers/firmware/arm_scmi/power.c | 1 + drivers/firmware/arm_scmi/reset.c | 1 + drivers/firmware/arm_scmi/sensors.c | 1 + drivers/firmware/arm_scmi/system.c | 6 +++++- drivers/firmware/arm_scmi/voltage.c | 1 + include/linux/scmi_protocol.h | 22 ++++++++++++++++++++++ 9 files changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/= clock.c index e2059d2025a2..c19b6bff370d 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -344,6 +344,7 @@ scmi_clock_info_get(const struct scmi_protocol_handle *= ph, u32 clk_id) } =20 static const struct scmi_clk_proto_ops clk_proto_ops =3D { + .version_get =3D scmi_protocol_version_get, .count_get =3D scmi_clock_count_get, .info_get =3D scmi_clock_info_get, .rate_get =3D scmi_clock_rate_get, diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi= /common.h index ffaf74a36b30..e7e9c8c5d48c 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -269,6 +269,26 @@ struct scmi_xfer_ops { struct scmi_xfer *xfer); }; =20 +/** + * scmi_protocol_version_get - Common helper to get protocol version + * + * @ph: A reference to an initialized protocol handle + * + * Exposed as .version_get for each protocol operations, it can be called = by + * SCMI drivers only on initialized protocol instances so it cannot fail. + * + * Return: Protocol version for the specified protocol handle + */ +static inline +unsigned int scmi_protocol_version_get(struct scmi_protocol_handle *ph) +{ + u32 version =3D 0; + + ph->xops->version_get(ph, &version); + + return version; +} + struct scmi_revision_info * scmi_revision_area_get(const struct scmi_protocol_handle *ph); int scmi_handle_put(const struct scmi_handle *handle); diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/p= erf.c index e9f68b91580c..e58490a8d0e7 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -756,6 +756,7 @@ static bool scmi_power_scale_mw_get(const struct scmi_p= rotocol_handle *ph) } =20 static const struct scmi_perf_proto_ops perf_proto_ops =3D { + .version_get =3D scmi_protocol_version_get, .limits_set =3D scmi_perf_limits_set, .limits_get =3D scmi_perf_limits_get, .level_set =3D scmi_perf_level_set, diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/= power.c index 0f0b94f0b624..c14bdb9a9ccd 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -184,6 +184,7 @@ static char *scmi_power_name_get(const struct scmi_prot= ocol_handle *ph, } =20 static const struct scmi_power_proto_ops power_proto_ops =3D { + .version_get =3D scmi_protocol_version_get, .num_domains_get =3D scmi_power_num_domains_get, .name_get =3D scmi_power_name_get, .state_set =3D scmi_power_state_set, diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/= reset.c index 9cdbd133db10..acf83ea361ed 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -196,6 +196,7 @@ scmi_reset_domain_deassert(const struct scmi_protocol_h= andle *ph, u32 domain) } =20 static const struct scmi_reset_proto_ops reset_proto_ops =3D { + .version_get =3D scmi_protocol_version_get, .num_domains_get =3D scmi_reset_num_domains_get, .name_get =3D scmi_reset_name_get, .latency_get =3D scmi_reset_latency_get, diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scm= i/sensors.c index f37ac9824a87..4ee578cf0c23 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -828,6 +828,7 @@ static int scmi_sensor_count_get(const struct scmi_prot= ocol_handle *ph) } =20 static const struct scmi_sensor_proto_ops sensor_proto_ops =3D { + .version_get =3D scmi_protocol_version_get, .count_get =3D scmi_sensor_count_get, .info_get =3D scmi_sensor_info_get, .trip_point_config =3D scmi_sensor_trip_point_config, diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi= /system.c index cbfc19f7a463..90157d7f45bc 100644 --- a/drivers/firmware/arm_scmi/system.c +++ b/drivers/firmware/arm_scmi/system.c @@ -33,6 +33,10 @@ struct scmi_system_info { u32 version; }; =20 +static struct scmi_system_proto_ops system_proto_ops =3D { + .version_get =3D scmi_protocol_version_get, +}; + static int scmi_system_request_notify(const struct scmi_protocol_handle *p= h, bool enable) { @@ -136,7 +140,7 @@ static const struct scmi_protocol scmi_system =3D { .id =3D SCMI_PROTOCOL_SYSTEM, .owner =3D THIS_MODULE, .instance_init =3D &scmi_system_protocol_init, - .ops =3D NULL, + .ops =3D &system_proto_ops, .events =3D &system_protocol_events, }; =20 diff --git a/drivers/firmware/arm_scmi/voltage.c b/drivers/firmware/arm_scm= i/voltage.c index ac08e819088b..c9a7cbdc9164 100644 --- a/drivers/firmware/arm_scmi/voltage.c +++ b/drivers/firmware/arm_scmi/voltage.c @@ -324,6 +324,7 @@ static int scmi_voltage_domains_num_get(const struct sc= mi_protocol_handle *ph) } =20 static struct scmi_voltage_proto_ops voltage_proto_ops =3D { + .version_get =3D scmi_protocol_version_get, .num_domains_get =3D scmi_voltage_domains_num_get, .info_get =3D scmi_voltage_info_get, .config_set =3D scmi_voltage_config_set, diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index b0652f1411b9..c5881d15f7d9 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -65,6 +65,7 @@ struct scmi_protocol_handle; * struct scmi_clk_proto_ops - represents the various operations provided * by SCMI Clock Protocol * + * @version_get: get the protocol version implemented by this SCMI instance * @count_get: get the count of clocks provided by SCMI * @info_get: get the information of the specified clock * @rate_get: request the current clock rate of a clock @@ -73,6 +74,7 @@ struct scmi_protocol_handle; * @disable: disables the specified clock */ struct scmi_clk_proto_ops { + unsigned int (*version_get)(struct scmi_protocol_handle *ph); int (*count_get)(const struct scmi_protocol_handle *ph); =20 const struct scmi_clock_info *(*info_get) @@ -92,6 +94,7 @@ struct scmi_clk_proto_ops { * struct scmi_perf_proto_ops - represents the various operations provided * by SCMI Performance Protocol * + * @version_get: get the protocol version implemented by this SCMI instance * @limits_set: sets limits on the performance level of a domain * @limits_get: gets limits on the performance level of a domain * @level_set: sets the performance level of a domain @@ -111,6 +114,7 @@ struct scmi_clk_proto_ops { * or in some other (abstract) scale */ struct scmi_perf_proto_ops { + unsigned int (*version_get)(struct scmi_protocol_handle *ph); int (*limits_set)(const struct scmi_protocol_handle *ph, u32 domain, u32 max_perf, u32 min_perf); int (*limits_get)(const struct scmi_protocol_handle *ph, u32 domain, @@ -139,12 +143,14 @@ struct scmi_perf_proto_ops { * struct scmi_power_proto_ops - represents the various operations provided * by SCMI Power Protocol * + * @version_get: get the protocol version implemented by this SCMI instance * @num_domains_get: get the count of power domains provided by SCMI * @name_get: gets the name of a power domain * @state_set: sets the power state of a power domain * @state_get: gets the power state of a power domain */ struct scmi_power_proto_ops { + unsigned int (*version_get)(struct scmi_protocol_handle *ph); int (*num_domains_get)(const struct scmi_protocol_handle *ph); char *(*name_get)(const struct scmi_protocol_handle *ph, u32 domain); #define SCMI_POWER_STATE_TYPE_SHIFT 30 @@ -442,6 +448,7 @@ enum scmi_sensor_class { * struct scmi_sensor_proto_ops - represents the various operations provid= ed * by SCMI Sensor Protocol * + * @version_get: get the protocol version implemented by this SCMI instance * @count_get: get the count of sensors provided by SCMI * @info_get: get the information of the specified sensor * @trip_point_config: selects and configures a trip-point of interest @@ -455,6 +462,7 @@ enum scmi_sensor_class { * @config_set: Set sensor current configuration */ struct scmi_sensor_proto_ops { + unsigned int (*version_get)(struct scmi_protocol_handle *ph); int (*count_get)(const struct scmi_protocol_handle *ph); const struct scmi_sensor_info *(*info_get) (const struct scmi_protocol_handle *ph, u32 sensor_id); @@ -475,6 +483,7 @@ struct scmi_sensor_proto_ops { * struct scmi_reset_proto_ops - represents the various operations provided * by SCMI Reset Protocol * + * @version_get: get the protocol version implemented by this SCMI instance * @num_domains_get: get the count of reset domains provided by SCMI * @name_get: gets the name of a reset domain * @latency_get: gets the reset latency for the specified reset domain @@ -483,6 +492,7 @@ struct scmi_sensor_proto_ops { * @deassert: explicitly deassert reset signal of the specified reset doma= in */ struct scmi_reset_proto_ops { + unsigned int (*version_get)(struct scmi_protocol_handle *ph); int (*num_domains_get)(const struct scmi_protocol_handle *ph); char *(*name_get)(const struct scmi_protocol_handle *ph, u32 domain); int (*latency_get)(const struct scmi_protocol_handle *ph, u32 domain); @@ -526,6 +536,7 @@ struct scmi_voltage_info { * struct scmi_voltage_proto_ops - represents the various operations provi= ded * by SCMI Voltage Protocol * + * @version_get: get the protocol version implemented by this SCMI instance * @num_domains_get: get the count of voltage domains provided by SCMI * @info_get: get the information of the specified domain * @config_set: set the config for the specified domain @@ -534,6 +545,7 @@ struct scmi_voltage_info { * @level_get: get the voltage level of the specified domain */ struct scmi_voltage_proto_ops { + unsigned int (*version_get)(struct scmi_protocol_handle *ph); int (*num_domains_get)(const struct scmi_protocol_handle *ph); const struct scmi_voltage_info __must_check *(*info_get) (const struct scmi_protocol_handle *ph, u32 domain_id); @@ -549,6 +561,16 @@ struct scmi_voltage_proto_ops { s32 *volt_uV); }; =20 +/** + * struct scmi_system_proto_ops - represents the various operations provid= ed + * by SCMI System Power Protocol + * + * @version_get: get the protocol version implemented by this SCMI instance + */ +struct scmi_system_proto_ops { + unsigned int (*version_get)(struct scmi_protocol_handle *ph); +}; + /** * struct scmi_notify_ops - represents notifications' operations provided= by * SCMI core --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BAE6FC433EF for ; Sun, 27 Feb 2022 20:56:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231800AbiB0U5S (ORCPT ); Sun, 27 Feb 2022 15:57:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58856 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231660AbiB0U5H (ORCPT ); Sun, 27 Feb 2022 15:57:07 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 5DBC5338A3 for ; Sun, 27 Feb 2022 12:56:30 -0800 (PST) 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 1AB611477; Sun, 27 Feb 2022 12:56:30 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id B39573F66F; Sun, 27 Feb 2022 12:56:28 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 05/16] firmware: arm_scmi: Expose information on configured transport Date: Sun, 27 Feb 2022 20:55:57 +0000 Message-Id: <20220227205608.30812-6-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add a common descriptor to describe transport features and expose it via the SCMI instance handle. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/driver.c | 12 ++++++++++++ include/linux/scmi_protocol.h | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi= /driver.c index 8d356d4da0bd..8c5429529946 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1966,6 +1966,7 @@ static int scmi_probe(struct platform_device *pdev) struct scmi_handle *handle; const struct scmi_desc *desc; struct scmi_info *info; + struct scmi_transport_info *trans; struct device *dev =3D &pdev->dev; struct device_node *child, *np =3D dev->of_node; =20 @@ -2023,6 +2024,17 @@ static int scmi_probe(struct platform_device *pdev) dev_err(dev, "Transport is not polling capable. Atomic mode not supported.\n"); =20 + trans =3D devm_kzalloc(dev, sizeof(*trans), GFP_KERNEL); + if (!trans) + return -ENOMEM; + + of_property_read_string(dev->of_node, "compatible", &trans->compatible); + trans->is_atomic =3D + handle->is_transport_atomic(handle, + &trans->atomic_threshold_us); + trans->max_rx_timeout_ms =3D info->desc->max_rx_timeout_ms; + handle->transport =3D trans; + /* * Trigger SCMI Base protocol initialization. * It's mandatory and won't be ever released/deinit until the diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index c5881d15f7d9..0b024d23a9b3 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -40,6 +40,24 @@ struct scmi_revision_info { char sub_vendor_id[SCMI_MAX_STR_SIZE]; }; =20 +/** + * struct scmi_transport_info - transport related information + * + * @compatible: Transport name picked from compatible string + * @is_atomic: True if the underlying transport can support atomic transac= tions + * and atomic mode is enabled. + * @atomic_threshold_us: Optional system wide DT-configured threshold, exp= ressed + * in microseconds, for atomic operations. + * @max_rx_timeout_ms: configured maximum timeout in milliseconds for comm= and + * replies. + */ +struct scmi_transport_info { + const char *compatible; + bool is_atomic; + unsigned int atomic_threshold_us; + unsigned int max_rx_timeout_ms; +}; + struct scmi_clock_info { char name[SCMI_MAX_STR_SIZE]; unsigned int enable_latency; @@ -633,6 +651,7 @@ struct scmi_notify_ops { * * @dev: pointer to the SCMI device * @version: pointer to the structure containing SCMI version information + * @transport: pointer to the structure containing SCMI transport informat= ion * @devm_protocol_get: devres managed method to acquire a protocol and get= specific * operations and a dedicated protocol handler * @devm_protocol_put: devres managed method to release a protocol @@ -650,6 +669,7 @@ struct scmi_notify_ops { struct scmi_handle { struct device *dev; struct scmi_revision_info *version; + struct scmi_transport_info *transport; =20 const void __must_check * (*devm_protocol_get)(struct scmi_device *sdev, u8 proto, --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05073C433EF for ; Sun, 27 Feb 2022 20:56:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231805AbiB0U5V (ORCPT ); Sun, 27 Feb 2022 15:57:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59062 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231713AbiB0U5N (ORCPT ); Sun, 27 Feb 2022 15:57:13 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id DBEEF3298A for ; Sun, 27 Feb 2022 12:56:31 -0800 (PST) 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 ABF7D14BF; Sun, 27 Feb 2022 12:56:31 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 508483F66F; Sun, 27 Feb 2022 12:56:30 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 06/16] firmware: arm_scmi: Define a common SCMI_MAX_PROTOCOLS value Date: Sun, 27 Feb 2022 20:55:58 +0000 Message-Id: <20220227205608.30812-7-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add a common definition of SCMI_MAX_PROTOCOLS and use it all over the SCMI stack. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/notify.c | 4 +--- include/linux/scmi_protocol.h | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi= /notify.c index 7d0b01b59616..5ccee248c22e 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -94,8 +94,6 @@ #include "common.h" #include "notify.h" =20 -#define SCMI_MAX_PROTO 256 - #define PROTO_ID_MASK GENMASK(31, 24) #define EVT_ID_MASK GENMASK(23, 16) #define SRC_ID_MASK GENMASK(15, 0) @@ -1637,7 +1635,7 @@ int scmi_notification_init(struct scmi_handle *handle) ni->gid =3D gid; ni->handle =3D handle; =20 - ni->registered_protocols =3D devm_kcalloc(handle->dev, SCMI_MAX_PROTO, + ni->registered_protocols =3D devm_kcalloc(handle->dev, SCMI_MAX_PROTOCOLS, sizeof(char *), GFP_KERNEL); if (!ni->registered_protocols) goto err; diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 0b024d23a9b3..63c1d1cc20ff 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -690,8 +690,11 @@ enum scmi_std_protocol { SCMI_PROTOCOL_SENSOR =3D 0x15, SCMI_PROTOCOL_RESET =3D 0x16, SCMI_PROTOCOL_VOLTAGE =3D 0x17, + SCMI_PROTOCOL_LAST =3D 0xff, }; =20 +#define SCMI_MAX_PROTOCOLS (SCMI_PROTOCOL_LAST + 1) + enum scmi_system_events { SCMI_SYSTEM_SHUTDOWN, SCMI_SYSTEM_COLDRESET, --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BCBAEC433F5 for ; Sun, 27 Feb 2022 20:56:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231901AbiB0U52 (ORCPT ); Sun, 27 Feb 2022 15:57:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59100 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231766AbiB0U5O (ORCPT ); Sun, 27 Feb 2022 15:57:14 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id CD8656D192 for ; Sun, 27 Feb 2022 12:56:33 -0800 (PST) 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 9D9241063; Sun, 27 Feb 2022 12:56:33 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E27883F66F; Sun, 27 Feb 2022 12:56:31 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com, Greg Kroah-Hartman , "Rafael J. Wysocki" , Alexander Viro Subject: [RFC PATCH 07/16] debugfs: Add signed versions of debugfs_create_u32/64 helpers Date: Sun, 27 Feb 2022 20:55:59 +0000 Message-Id: <20220227205608.30812-8-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add a few helpers to deal with signed values integers; built on existing debugfs internal helpers as the existing unsigned functions already do. Make the simple_attr_write() internal helper detect the sign of the requested set operation from the related format string: this is needed to be able to properly parse negatively signed input strings. Cc: Greg Kroah-Hartman Cc: "Rafael J. Wysocki" Cc: Alexander Viro Signed-off-by: Cristian Marussi --- Note that in the rest of the series I do NOT need the s64 WRITE/SET operations, that required the more invasive simple_attr_write() change, but it seemed odd to implement a get only debug_create_s32/64 API. --- fs/debugfs/file.c | 74 +++++++++++++++++++++++++++++++++++++++++ fs/libfs.c | 12 +++++-- include/linux/debugfs.h | 4 +++ 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 950c63fa4d0b..5363b12c3dcb 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -556,6 +556,80 @@ void debugfs_create_u64(const char *name, umode_t mode= , struct dentry *parent, } EXPORT_SYMBOL_GPL(debugfs_create_u64); =20 +static int debugfs_s32_set(void *data, u64 val) +{ + *(s32 *)data =3D val; + return 0; +} + +static int debugfs_s32_get(void *data, u64 *val) +{ + *val =3D *(s32 *)data; + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(fops_s32, debugfs_s32_get, debugfs_s32_set, "%lld= \n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_s32_ro, debugfs_s32_get, NULL, "%lld\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_s32_wo, NULL, debugfs_s32_set, "%lld\n"); + +/** + * debugfs_create_s32 - create a debugfs file that is used to read and wri= te an signed 32-bit value + * @name: a pointer to a string containing the name of the file to create. + * @mode: the permission that the file should have + * @parent: a pointer to the parent dentry for this file. This should be a + * directory dentry if set. If this parameter is %NULL, then the + * file will be created in the root of the debugfs filesystem. + * @value: a pointer to the variable that the file should read to and write + * from. + * + * This function creates a file in debugfs with the given name that + * contains the value of the variable @value. If the @mode variable is so + * set, it can be read from, and written to. + */ +void debugfs_create_s32(const char *name, umode_t mode, struct dentry *par= ent, + s32 *value) +{ + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_s32, + &fops_s32_ro, &fops_s32_wo); +} +EXPORT_SYMBOL_GPL(debugfs_create_s32); + +static int debugfs_s64_set(void *data, u64 val) +{ + *(s64 *)data =3D val; + return 0; +} + +static int debugfs_s64_get(void *data, u64 *val) +{ + *val =3D *(s64 *)data; + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(fops_s64, debugfs_s64_get, debugfs_s64_set, "%lld= \n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_s64_ro, debugfs_s64_get, NULL, "%lld\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_s64_wo, NULL, debugfs_s64_set, "%lld\n"); + +/** + * debugfs_create_s64 - create a debugfs file that is used to read and wri= te a signed 64-bit value + * @name: a pointer to a string containing the name of the file to create. + * @mode: the permission that the file should have + * @parent: a pointer to the parent dentry for this file. This should be a + * directory dentry if set. If this parameter is %NULL, then the + * file will be created in the root of the debugfs filesystem. + * @value: a pointer to the variable that the file should read to and write + * from. + * + * This function creates a file in debugfs with the given name that + * contains the value of the variable @value. If the @mode variable is so + * set, it can be read from, and written to. + */ +void debugfs_create_s64(const char *name, umode_t mode, struct dentry *par= ent, + s64 *value) +{ + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_s64, + &fops_s64_ro, &fops_s64_wo); +} +EXPORT_SYMBOL_GPL(debugfs_create_s64); + static int debugfs_ulong_set(void *data, u64 val) { *(unsigned long *)data =3D val; diff --git a/fs/libfs.c b/fs/libfs.c index ba7438ab9371..f5a554ed363b 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -917,8 +917,8 @@ EXPORT_SYMBOL(simple_transaction_release); struct simple_attr { int (*get)(void *, u64 *); int (*set)(void *, u64); - char get_buf[24]; /* enough to store a u64 and "\n\0" */ - char set_buf[24]; + char get_buf[25]; /* enough to store a u64, a sign and "\n\0" */ + char set_buf[25]; void *data; const char *fmt; /* format for read operation */ struct mutex mutex; /* protects access to these buffers */ @@ -1001,6 +1001,7 @@ ssize_t simple_attr_write(struct file *file, const ch= ar __user *buf, unsigned long long val; size_t size; ssize_t ret; + char *_fmt; =20 attr =3D file->private_data; if (!attr->set) @@ -1016,7 +1017,12 @@ ssize_t simple_attr_write(struct file *file, const c= har __user *buf, goto out; =20 attr->set_buf[size] =3D '\0'; - ret =3D kstrtoull(attr->set_buf, 0, &val); + _fmt =3D strchr(attr->fmt, '%'); + /* Deduce signedness from read format string specifier */ + if (_fmt && (strchr(_fmt, 'd') || strchr(_fmt, 'i'))) + ret =3D kstrtoll(attr->set_buf, 0, (long long *)&val); + else + ret =3D kstrtoull(attr->set_buf, 0, &val); if (ret) goto out; ret =3D attr->set(attr->data, val); diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index c869f1e73d75..1b8ea858f261 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -114,6 +114,10 @@ void debugfs_create_u64(const char *name, umode_t mode= , struct dentry *parent, u64 *value); void debugfs_create_ulong(const char *name, umode_t mode, struct dentry *p= arent, unsigned long *value); +void debugfs_create_s32(const char *name, umode_t mode, struct dentry *par= ent, + s32 *value); +void debugfs_create_s64(const char *name, umode_t mode, struct dentry *par= ent, + s64 *value); void debugfs_create_x8(const char *name, umode_t mode, struct dentry *pare= nt, u8 *value); void debugfs_create_x16(const char *name, umode_t mode, struct dentry *par= ent, --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 08862C433EF for ; Sun, 27 Feb 2022 20:57:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231992AbiB0U5l (ORCPT ); Sun, 27 Feb 2022 15:57:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59174 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231845AbiB0U5P (ORCPT ); Sun, 27 Feb 2022 15:57:15 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 8E1C36D854 for ; Sun, 27 Feb 2022 12:56:35 -0800 (PST) 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 5815A106F; Sun, 27 Feb 2022 12:56:35 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D35573F66F; Sun, 27 Feb 2022 12:56:33 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 08/16] firmware: arm_scmi: Add SCMI Testing driver Date: Sun, 27 Feb 2022 20:56:00 +0000 Message-Id: <20220227205608.30812-9-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add an SCMI driver that would expose all of the available SCMI protocol operations and resources under a debugfs rooted at /sys/kernel/debug/scmi, so as to be then able to script generic SCMI testcases simply accessing the available debugfs entries. The aim is to be able to test the Kernel SCMI stack in isolation without the constraints or interferences carried by the original SCMI drivers that by their nature belong and are driven by a number of Kernel subsystems: indeed, if this testing driver is enabled at compilation time, loading of all the other regular SCMI drivers is inhibited. Beside such generic SCMI test driver infrastructure, add also basic support for testing SCMI Clock protocol. Signed-off-by: Cristian Marussi --- Documentation/ABI/testing/debugfs-scmi | 101 ++++++++++++ drivers/firmware/arm_scmi/Kconfig | 12 ++ drivers/firmware/arm_scmi/Makefile | 2 + drivers/firmware/arm_scmi/driver.c | 9 + .../arm_scmi/scmi_test_driver/Makefile | 4 + .../arm_scmi/scmi_test_driver/scmi_test.c | 154 ++++++++++++++++++ .../arm_scmi/scmi_test_driver/test_clocks.c | 139 ++++++++++++++++ .../arm_scmi/scmi_test_driver/test_common.c | 60 +++++++ .../arm_scmi/scmi_test_driver/test_common.h | 76 +++++++++ 9 files changed, 557 insertions(+) create mode 100644 Documentation/ABI/testing/debugfs-scmi create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/Makefile create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_common.c create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_common.h diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/tes= ting/debugfs-scmi new file mode 100644 index 000000000000..85177f3723c8 --- /dev/null +++ b/Documentation/ABI/testing/debugfs-scmi @@ -0,0 +1,101 @@ +What: /sys/kernel/debug/scmi/info/major_ver +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: SCMI protocol stack major version +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/info/minor_ver +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: SCMI protocol stack minor version +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/info/impl_ver +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: SCMI protocol stack (vendor-specific) implementation version +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/info/vendor_id +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: SCMI protocol stack vendor identifier ASCII string +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/info/sub_vendor_id +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: SCMI protocol stack sub_vendor identifier ASCII string +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/info/num_agents +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: Number of detected SCMI agents on the system +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/info/num_protocols +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: Number of detected SCMI protocols implemented on the system +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/transport/compatible +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: Name of the configured underlying SCMI transport identified + using the same compatible strings as defined in the bindings + at Documentation/devicetree/bindings/firmware/arm,scmi.yaml +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/transport/is_atomic +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: A boolen flag that states if the underlying SCMI transport + currently used is configured to support atomic mode of + operation. +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/transport/max_rx_timeout_ms +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: Represents the timeout, as configured in the underlying SCMI + transport, that is enforced while waiting for SCMI synchronous + command replies. +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/transport/atomic_threshold_us +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: System wide threshold optionally used to decide if honour or = not + SCMI atomic transactions requests; its usage is described in + Documentation/devicetree/bindings/firmware/arm,scmi.yaml +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x/version +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: SCMI Protocol 0x version implemented on this system +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x14//info/* +Date: Feb 2022 +KernelVersion: 5.18 +Contact: cristian.marussi@arm.com +Description: SCMI Clock Protocol informational RO data for clock resource + with id : each entry under info/ subdir maps to an equally + named field of struct scmi_clock_info as documented in + include/scmi/protocol.h +Users: KSelftest, Debugging diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/= Kconfig index 7794bd41eaa0..a3726074c89e 100644 --- a/drivers/firmware/arm_scmi/Kconfig +++ b/drivers/firmware/arm_scmi/Kconfig @@ -148,4 +148,16 @@ config ARM_SCMI_POWER_DOMAIN will be called scmi_pm_domain. Note this may needed early in boot before rootfs may be available. =20 +config ARM_SCMI_TEST_DRIVER + tristate "SCMI Testing driver" + depends on (ARM_SCMI_PROTOCOL && DEBUG_FS) || (COMPILE_TEST && OF) + help + This enables support for an SCMI testing driver. + Note that this driver will register as an SCMI driver user for + all SCMI standard protocols and at the same time will inhibit + the registration of any of regular SCMI drivers. + + This driver can also be built as a module. If so, the module + will be called scmi_test_driver. + endmenu diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi= /Makefile index 8d4afadda38c..8382a5da9e39 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -13,6 +13,8 @@ scmi-module-objs :=3D $(scmi-bus-y) $(scmi-driver-y) $(sc= mi-protocols-y) \ obj-$(CONFIG_ARM_SCMI_PROTOCOL) +=3D scmi-module.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) +=3D scmi_pm_domain.o =20 +obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) +=3D scmi_test_driver/ + ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy) # The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a = frame # pointer in Thumb2 mode, which is forcibly enabled by Clang when profiling diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi= /driver.c index 8c5429529946..8c4706b24368 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1782,6 +1782,15 @@ static int scmi_protocol_device_request(const struct= scmi_device_id *id_table) pr_debug("Requesting SCMI device (%s) for protocol %x\n", id_table->name, id_table->protocol_id); =20 +#if IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER) + /* Reject non-testing SCMI drivers */ + if (strncmp(id_table->name, "__scmi_test", strlen("__scmi_test"))) { + pr_warn("SCMI Test driver loaded. Rejecting '%s'/0x%X\n", + id_table->name, id_table->protocol_id); + return -EINVAL; + } +#endif + /* * Search for the matching protocol rdev list and then search * of any existent equally named device...fails if any duplicate found. diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/= firmware/arm_scmi/scmi_test_driver/Makefile new file mode 100644 index 000000000000..6e3ddd177827 --- /dev/null +++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +scmi_test_driver-objs :=3D scmi_test.o test_common.o test_clocks.o +obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) +=3D scmi_test_driver.o + diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drive= rs/firmware/arm_scmi/scmi_test_driver/scmi_test.c new file mode 100644 index 000000000000..f99aa621684c --- /dev/null +++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SCMI Testing Driver. + * + * Copyright (C) 2022 ARM Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_common.h" + +static struct dentry *scmi_dentry, *scmi_info_dentry, *scmi_trans_dentry; +DEFINE_MUTEX(scmi_test_mtx); + +static +int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) =3D { + [SCMI_PROTOCOL_CLOCK] =3D scmi_test_clock_init, +}; + +static void +scmi_debugfs_common_info_create(struct scmi_revision_info *info, + struct dentry *parent) +{ + debugfs_create_u16("major_ver", 0400, parent, &info->major_ver); + debugfs_create_u16("minor_ver", 0400, parent, &info->minor_ver); + debugfs_create_u8("num_protocols", 0400, parent, + &info->num_protocols); + debugfs_create_u8("num_agents", 0400, parent, &info->num_agents); + debugfs_create_x32("impl_ver", 0400, parent, &info->impl_ver); + + debugfs_create_file("vendor_id", 0400, parent, + info->vendor_id, &scmi_test_string_file_fops); + debugfs_create_file("sub_vendor_id", 0400, parent, + info->sub_vendor_id, &scmi_test_string_file_fops); +} + +static void +scmi_debugfs_trans_info_create(struct scmi_transport_info *info, + struct dentry *parent) +{ + debugfs_create_file("compatible", 0400, parent, + (void *)info->compatible, + &scmi_test_string_file_fops); + debugfs_create_bool("is_atomic", 0400, parent, &info->is_atomic); + debugfs_create_u32("atomic_threshold_us", 0400, parent, + &info->atomic_threshold_us); + debugfs_create_u32("max_rx_timeout_ms", 0400, parent, + &info->max_rx_timeout_ms); +} + +static int scmi_testing_probe(struct scmi_device *sdev) +{ + int ret; + const void *ops; + struct scmi_protocol_handle *ph; + const struct scmi_handle *handle =3D sdev->handle; + struct device *dev =3D &sdev->dev; + struct scmi_test_setup *tsp; + char proto_dir[16]; + + if (!handle) + return -ENODEV; + + if (sdev->protocol_id > SCMI_PROTOCOL_LAST || + !scmi_test_init[sdev->protocol_id]) { + dev_warn(dev, "Testing protocol 0x%X NOT supported.\n", + sdev->protocol_id); + return -EINVAL; + } + + ops =3D handle->devm_protocol_get(sdev, sdev->protocol_id, &ph); + if (IS_ERR(ops)) { + dev_err(dev, "Cannot access protocol:0x%X - err:%ld\n", + sdev->protocol_id, PTR_ERR(ops)); + return PTR_ERR(ops); + } + + tsp =3D devm_kzalloc(&sdev->dev, sizeof(*tsp), GFP_KERNEL); + if (!tsp) + return -ENOMEM; + + tsp->sdev =3D sdev; + tsp->ops =3D ops; + tsp->ph =3D ph; + + snprintf(proto_dir, 16, "protocol_0x%02X", sdev->protocol_id); + tsp->parent =3D debugfs_create_dir(proto_dir, scmi_dentry); + if (IS_ERR(tsp->parent)) + return PTR_ERR(tsp->parent); + + ret =3D scmi_test_init[sdev->protocol_id](tsp); + if (ret) + return ret; + + /* Setup common information entries if not already done */ + mutex_lock(&scmi_test_mtx); + if (!scmi_info_dentry) { + scmi_info_dentry =3D debugfs_create_dir("info", scmi_dentry); + if (!IS_ERR(scmi_info_dentry)) + scmi_debugfs_common_info_create(sdev->handle->version, + scmi_info_dentry); + } + + if (!scmi_trans_dentry) { + scmi_trans_dentry =3D + debugfs_create_dir("transport", scmi_dentry); + if (!IS_ERR(scmi_trans_dentry)) + scmi_debugfs_trans_info_create(sdev->handle->transport, + scmi_trans_dentry); + } + mutex_unlock(&scmi_test_mtx); + + return ret; +} + +static const struct scmi_device_id scmi_id_table[] =3D { + { SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" }, + { }, +}; +MODULE_DEVICE_TABLE(scmi, scmi_id_table); + +static struct scmi_driver scmi_testing_driver =3D { + .name =3D "scmi-testing-driver", + .probe =3D scmi_testing_probe, + .id_table =3D scmi_id_table, +}; + +static int __init scmi_testing_driver_init(void) +{ + scmi_dentry =3D debugfs_create_dir("scmi", NULL); + return scmi_driver_register(&scmi_testing_driver, + THIS_MODULE, KBUILD_MODNAME); +} +module_init(scmi_testing_driver_init); + +static void __exit scmi_testing_driver_exit(void) +{ + debugfs_remove_recursive(scmi_dentry); + scmi_driver_unregister(&scmi_testing_driver); +} +module_exit(scmi_testing_driver_exit); + +MODULE_AUTHOR("Cristian Marussi "); +MODULE_DESCRIPTION("ARM SCMI Testing Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_clocks.c new file mode 100644 index 000000000000..3b9e92baa509 --- /dev/null +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SCMI Testing Driver - Clock Protocol + * + * Copyright (C) 2022 ARM Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_common.h" + +/* Clock Proto Test */ +struct scmi_clock_data { + unsigned int version; + int count; + const struct scmi_clock_info **clk_info; +}; + +static ssize_t scmi_test_clock_rates_read(struct file *filp, char __user *= buf, + size_t count, loff_t *ppos) +{ + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + if (!data->used) { + int c; + struct scmi_clock_info *ci =3D filp->f_inode->i_private; + + for (c =3D 0; c < ci->list.num_rates; c++) + data->used +=3D scnprintf(data->buf + data->used, + data->len - data->used, + "%lld ", + ci->list.rates[c]); + + data->used +=3D scnprintf(data->buf + data->used, + data->len - data->used, "\n"); + } + + return simple_read_from_buffer(buf, count, ppos, data->buf, data->used); +} + +static const struct file_operations test_clk_rates_fops =3D { + .open =3D scmi_test_fixed_buffer_open, + .release =3D scmi_test_release, + .read =3D scmi_test_clock_rates_read, +}; + +static void +scmi_test_debugfs_clock_info_create(const struct scmi_clock_info *ci, + struct dentry *top_dentry) +{ + struct dentry *parent; + struct scmi_clock_info *cinfo =3D (struct scmi_clock_info *)ci; + + parent =3D debugfs_create_dir("info", top_dentry); + if (IS_ERR(parent)) + return; + + debugfs_create_file("name", 0400, parent, cinfo->name, + &scmi_test_string_file_fops); + debugfs_create_u32("enable_latency", 0400, parent, + &cinfo->enable_latency); + + debugfs_create_bool("rate_discrete", 0400, parent, + &cinfo->rate_discrete); + + if (cinfo->rate_discrete) { + debugfs_create_u32("num_rates", 0400, parent, + &cinfo->list.num_rates); + debugfs_create_file("rates", 0400, parent, cinfo, + &test_clk_rates_fops); + } else { + debugfs_create_u64("min_rate", 0400, parent, + &cinfo->range.min_rate); + debugfs_create_u64("max_rate", 0400, parent, + &cinfo->range.max_rate); + debugfs_create_u64("step_size", 0400, parent, + &cinfo->range.step_size); + } +} + +int scmi_test_clock_init(struct scmi_test_setup *tsp) +{ + int i; + struct scmi_clock_data *cdata; + const struct scmi_clk_proto_ops *clock_ops; + struct device *dev =3D &tsp->sdev->dev; + + cdata =3D devm_kzalloc(dev, sizeof(*cdata), GFP_KERNEL); + if (!cdata) + return -ENOMEM; + + clock_ops =3D tsp->ops; + cdata->version =3D clock_ops->version_get(tsp->ph); + cdata->count =3D clock_ops->count_get(tsp->ph); + + if (cdata->count <=3D 0) { + dev_err(dev, "number of domains invalid: %d\n", + cdata->count); + return cdata->count ?: -EINVAL; + } + + cdata->clk_info =3D devm_kcalloc(dev, cdata->count, + sizeof(cdata->clk_info), GFP_KERNEL); + if (!cdata->clk_info) + return -ENOMEM; + + for (i =3D 0; i < cdata->count; i++) + cdata->clk_info[i] =3D clock_ops->info_get(tsp->ph, i); + + tsp->priv =3D cdata; + + debugfs_create_x32("version", 0400, tsp->parent, &cdata->version); + + dev_info(dev, "Found %d clock resources.\n", cdata->count); + + for (i =3D 0; i < cdata->count; i++) { + char clock_dir[16]; + struct dentry *clock_dentry; + + snprintf(clock_dir, 16, "%03d", i); + clock_dentry =3D debugfs_create_dir(clock_dir, tsp->parent); + if (!IS_ERR(clock_dentry)) + scmi_test_debugfs_clock_info_create(cdata->clk_info[i], + clock_dentry); + } + + return 0; +} diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_common.c new file mode 100644 index 000000000000..1a4b6aa35095 --- /dev/null +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SCMI Testing Driver. + * + * Copyright (C) 2022 ARM Ltd. + */ + +#include +#include +#include +#include +#include +#include + +#include "test_common.h" + +/* Common File operations */ +int scmi_test_release(struct inode *ino, struct file *filp) +{ + kfree(filp->private_data); + + return 0; +} + +int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp) +{ + struct scmi_test_buffer *data; + + data =3D kzalloc(sizeof(*data) + SCMI_TEST_DEFAULT_BUF_SZ, GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->len =3D SCMI_TEST_DEFAULT_BUF_SZ; + filp->private_data =3D data; + + return 0; +} + +static ssize_t scmi_test_string_file_read(struct file *filp, char __user *= buf, + size_t count, loff_t *ppos) +{ + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + if (!data->used) { + char *str =3D filp->f_inode->i_private; + + data->used =3D scnprintf(data->buf, data->len, "%s\n", str); + } + + return simple_read_from_buffer(buf, count, ppos, data->buf, data->used); +} + +const struct file_operations scmi_test_string_file_fops =3D { + .open =3D scmi_test_fixed_buffer_open, + .release =3D scmi_test_release, + .read =3D scmi_test_string_file_read, +}; diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_common.h new file mode 100644 index 000000000000..1ff5bbc32ae3 --- /dev/null +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * SCMI Testing Driver. + * + * Copyright (C) 2022 ARM Ltd. + */ + +#ifndef __SCMI_TEST_COMMON_H +#define __SCMI_TEST_COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * struct scmi_test_setup - Test protocol setup descriptor + * @parent: A reference to the parent dentry + * @sdev: A reference to the related SCMI device + * @ops: A reference to the protocol ops + * @ph: A reference to the protocol handle to be used with the ops + * @blen: An optional minimum requested buffer length for output data; if = zero + * the output test buffer is allocated of SCMI_TEST_DEFAULT_BUF_SZ bytes. + * @priv: A reference to optional protocol-specific data + * @n_priv: A reference to optional protocol-specific data needed by + * notifications + * + * This descriptor is created and initialized once per protocol in the + * main probe function and passed down to the testing protocol initializat= ion + * functions where can be further customized before being optionally made + * available to the specific debugfs entries via inode i_private reference. + */ +struct scmi_test_setup { + struct dentry *parent; + struct scmi_device *sdev; + const void *ops; + struct scmi_protocol_handle *ph; + size_t blen; + void *priv; + void *n_priv; +}; + +/** + * struct scmi_test_buffer - Output test buffer descriptor + * @id: An optional resource id parsed at open from the debugfs entry name + * @len: Size of the allocated buffer len as pointed by @buf + * @used: Current number of used bytes in @buf + * @buf: Actual buffer for output data: default allocation size (@len), if= not + * otherwise specified in scmi_test_setup.blen, is SCMI_TEST_DEFAULT_BUF_S= Z. + * + * This describes a dynamically allocated output buffer which will be made + * available to each r/w debugfs entry file_operations. + */ +struct scmi_test_buffer { + unsigned int id; + size_t len; + size_t used; +#define SCMI_TEST_DEFAULT_BUF_SZ 64 + unsigned char buf[]; +}; + +extern const struct file_operations scmi_test_string_file_fops; + +int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp); +int scmi_test_release(struct inode *ino, struct file *filp); + +int scmi_test_clock_init(struct scmi_test_setup *tsp); + +#endif /* __SCMI_TEST_COMMON_H */ --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 81ADFC433F5 for ; Sun, 27 Feb 2022 20:57:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231869AbiB0U5d (ORCPT ); Sun, 27 Feb 2022 15:57:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59104 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231761AbiB0U5P (ORCPT ); Sun, 27 Feb 2022 15:57:15 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 39A6B6E360 for ; Sun, 27 Feb 2022 12:56:37 -0800 (PST) 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 EA12C11FB; Sun, 27 Feb 2022 12:56:36 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8D0713F66F; Sun, 27 Feb 2022 12:56:35 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 09/16] firmware: arm_scmi: testing: Add Clock protocol full support Date: Sun, 27 Feb 2022 20:56:01 +0000 Message-Id: <20220227205608.30812-10-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add SCMI Clock protocol testing support exposing SCMI Clock protocol operations under debugfs /sys/kernel/debug/scmi/protocol_0x14//, where the subdirectories represents each a distinct clock resource with ID equal . Signed-off-by: Cristian Marussi --- Documentation/ABI/testing/debugfs-scmi | 56 +++++++ .../arm_scmi/scmi_test_driver/test_clocks.c | 150 +++++++++++++++++- .../arm_scmi/scmi_test_driver/test_common.c | 48 ++++++ .../arm_scmi/scmi_test_driver/test_common.h | 1 + 4 files changed, 254 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/tes= ting/debugfs-scmi index 85177f3723c8..e91c19e7a323 100644 --- a/Documentation/ABI/testing/debugfs-scmi +++ b/Documentation/ABI/testing/debugfs-scmi @@ -99,3 +99,59 @@ Description: SCMI Clock Protocol informational RO data f= or clock resource named field of struct scmi_clock_info as documented in include/scmi/protocol.h Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x14//rate_get_set +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: SCMI Clock Protocol rate get/set operation for clock resource + with id ; a read returns the currently set clock rate value + as a base-10 integer while the write of a base-10 integer sets a + new clock rate value. + Each R/W access invokes the corresponding SCMI Clock protocol + operations and issuing of needed SCMI commands. +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x14//enable +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: SCMI Clock Protocol enable operation for clock resource with = id + ; writing a boolean value causes that specific clock to be + enabled or disabled. + No reference counting is kept: each write access invokes the + corresponding SCMI Clock protocol operations and issuing of + needed SCMI commands. +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x14//enable_atomic_irqs_on +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: SCMI Clock Protocol enable atomic operation for clock resource + with id ; writing a boolean value causes that specific + clock to be enabled or disabled using SCMI transport in polling + mode, if allowed by the underlying SCMI transport. + No reference counting is kept: each write access invokes the + corresponding SCMI Clock protocol operations and issuing of + needed SCMI commands. + Available only if the underlying SCMI transport is atomic + capable (/sys/kernel/debug/scmi/transport/is_atomic is True). +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x14//enable_atomic_irqs_off +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: SCMI Clock Protocol enable atomic operation for clock resource + with id ; writing a boolean value causes that specific + clock to be enabled or disabled using SCMI transport in polling + mode, if allowed by the underlying SCMI transport. + Local IRQs are disabled while the SCMI command transaction is + executed. + No reference counting is kept: each write access invokes the + corresponding SCMI Clock protocol operations and issuing of + needed SCMI commands. + Available only if the underlying SCMI transport is atomic + capable (/sys/kernel/debug/scmi/transport/is_atomic is True). +Users: KSelftest, Debugging diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_clocks.c index 3b9e92baa509..ae5b1af88f60 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c @@ -24,6 +24,139 @@ struct scmi_clock_data { const struct scmi_clock_info **clk_info; }; =20 +static ssize_t scmi_test_clk_rate_get_read(struct file *filp, char __user = *buf, + size_t count, loff_t *ppos) +{ + int ret; + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + if (!data->used) { + u64 rate; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const struct scmi_clk_proto_ops *clock_ops =3D tsp->ops; + + ret =3D clock_ops->rate_get(tsp->ph, data->id, &rate); + if (ret) + return ret; + + data->used =3D scnprintf(data->buf, data->len, "%lld\n", rate); + } + + return simple_read_from_buffer(buf, count, ppos, data->buf, data->used); +} + +static ssize_t scmi_test_clk_rate_get_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + int ret; + u64 rate; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const struct scmi_clk_proto_ops *clock_ops =3D tsp->ops; + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + ret =3D kstrtou64_from_user(buf, count, 10, &rate); + if (ret < 0) + return ret; + + ret =3D clock_ops->rate_set(tsp->ph, data->id, rate); + if (ret) + return ret; + + return count; +} + +static const struct file_operations test_clk_rate_get_set_fops =3D { + .open =3D scmi_test_setup_open, + .release =3D scmi_test_release, + .read =3D scmi_test_clk_rate_get_read, + .write =3D scmi_test_clk_rate_get_write, +}; + +static ssize_t scmi_test_clk_enable_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + bool enabled, irqs_off; + int ret; + unsigned long flags; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const struct scmi_clk_proto_ops *clock_ops =3D tsp->ops; + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + ret =3D kstrtobool_from_user(buf, count, &enabled); + if (ret) + return ret; + + irqs_off =3D !strncmp(filp->f_path.dentry->d_name.name, + "enable_atomic_irqs_off", + strlen("enable_atomic_irqs_off")); + if (irqs_off) + local_irq_save(flags); + + if (enabled) + ret =3D clock_ops->enable_atomic(tsp->ph, data->id); + else + ret =3D clock_ops->disable_atomic(tsp->ph, data->id); + + if (irqs_off) + local_irq_restore(flags); + + if (ret) + return ret; + + return count; +} + +static const struct file_operations test_clk_enable_fops =3D { + .open =3D scmi_test_setup_open, + .release =3D scmi_test_release, + .write =3D scmi_test_clk_enable_write, +}; + +static ssize_t scmi_test_clk_prepare_enable_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + bool enabled; + int ret; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const struct scmi_clk_proto_ops *clock_ops =3D tsp->ops; + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + ret =3D kstrtobool_from_user(buf, count, &enabled); + if (ret) + return ret; + + if (enabled) + ret =3D clock_ops->enable(tsp->ph, data->id); + else + ret =3D clock_ops->disable(tsp->ph, data->id); + + if (ret) + return ret; + + return count; +} + +static const struct file_operations test_clk_prepare_enable_fops =3D { + .open =3D scmi_test_setup_open, + .release =3D scmi_test_release, + .write =3D scmi_test_clk_prepare_enable_write, +}; + static ssize_t scmi_test_clock_rates_read(struct file *filp, char __user *= buf, size_t count, loff_t *ppos) { @@ -130,9 +263,24 @@ int scmi_test_clock_init(struct scmi_test_setup *tsp) =20 snprintf(clock_dir, 16, "%03d", i); clock_dentry =3D debugfs_create_dir(clock_dir, tsp->parent); - if (!IS_ERR(clock_dentry)) + if (!IS_ERR(clock_dentry)) { scmi_test_debugfs_clock_info_create(cdata->clk_info[i], clock_dentry); + debugfs_create_file("rate_get_set", 0600, + clock_dentry, tsp, + &test_clk_rate_get_set_fops); + if (tsp->sdev->handle->transport->is_atomic) { + debugfs_create_file("enable_atomic_irqs_off", + 0200, clock_dentry, tsp, + &test_clk_enable_fops); + debugfs_create_file("enable_atomic_irqs_on", + 0200, clock_dentry, tsp, + &test_clk_enable_fops); + } + debugfs_create_file("enable", 0200, + clock_dentry, tsp, + &test_clk_prepare_enable_fops); + } } =20 return 0; diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_common.c index 1a4b6aa35095..cbe2eec4f2ac 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c @@ -15,6 +15,54 @@ #include "test_common.h" =20 /* Common File operations */ + +/** + * scmi_test_setup_open - A common open helper + * @ino: Related inode reference + * @filp: Related file pointer reference + * + * Expects to receive a struct scmi_test_setup via inode i_private referen= ce and + * then allocate a properly sized buffer; it also tries to parse the parent + * directory name in search for a base10 integer and, if found, stores it = into + * the buffer descriptor @id field: this comes handy since most of the SCMI + * protocol operations and data are bound to some specific SCMI resource i= d and + * the SCMI debugfs directory tree is structured to mirror this layout, so= that, + * as an example, protocol would expose about its res= ource + * with id as: + * + * /sys/kernel/debug/scmi/protocol_0x// + * + * As as result this open would allocate a data buffer, parse the dentry a= nd + * set data->id =3D + * + * Return: 0 on Success + */ +int scmi_test_setup_open(struct inode *ino, struct file *filp) +{ + unsigned int id; + size_t blen; + struct scmi_test_buffer *data; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const char *id_str =3D filp->f_path.dentry->d_parent->d_name.name; + + if (!tsp) + return -EINVAL; + + blen =3D tsp->blen ?: SCMI_TEST_DEFAULT_BUF_SZ; + data =3D kzalloc(sizeof(*data) + blen, GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->len =3D blen; + /* Grab clk ID from debugfs entry naming if any */ + if (!kstrtouint(id_str, 10, &id)) + data->id =3D id; + + filp->private_data =3D data; + + return 0; +} + int scmi_test_release(struct inode *ino, struct file *filp) { kfree(filp->private_data); diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_common.h index 1ff5bbc32ae3..3c64cae9fae9 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h @@ -68,6 +68,7 @@ struct scmi_test_buffer { =20 extern const struct file_operations scmi_test_string_file_fops; =20 +int scmi_test_setup_open(struct inode *ino, struct file *filp); int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp); int scmi_test_release(struct inode *ino, struct file *filp); =20 --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AB994C433F5 for ; Sun, 27 Feb 2022 20:57:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231932AbiB0U5p (ORCPT ); Sun, 27 Feb 2022 15:57:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59272 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231739AbiB0U5S (ORCPT ); Sun, 27 Feb 2022 15:57:18 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B7E0C66F8C for ; Sun, 27 Feb 2022 12:56:38 -0800 (PST) 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 875E012FC; Sun, 27 Feb 2022 12:56:38 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2B9C23F66F; Sun, 27 Feb 2022 12:56:37 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 10/16] firmware: arm_scmi: testing: Add Sensor protocol basic support Date: Sun, 27 Feb 2022 20:56:02 +0000 Message-Id: <20220227205608.30812-11-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add SCMI Sensor protocol testing support exposing SCMI Sensor protocol operations under debugfs /sys/kernel/debug/scmi/protocol_0x15//, where the subdirectories represents each a distinct sensor resource with ID equal . Still without any support for testing SCMI Sensor notifications. Signed-off-by: Cristian Marussi --- Documentation/ABI/testing/debugfs-scmi | 62 +++ .../arm_scmi/scmi_test_driver/Makefile | 2 +- .../arm_scmi/scmi_test_driver/scmi_test.c | 2 + .../arm_scmi/scmi_test_driver/test_common.h | 1 + .../arm_scmi/scmi_test_driver/test_sensors.c | 525 ++++++++++++++++++ 5 files changed, 591 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_sensors= .c diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/tes= ting/debugfs-scmi index e91c19e7a323..72835516dee8 100644 --- a/Documentation/ABI/testing/debugfs-scmi +++ b/Documentation/ABI/testing/debugfs-scmi @@ -155,3 +155,65 @@ Description: SCMI Clock Protocol enable atomic operati= on for clock resource Available only if the underlying SCMI transport is atomic capable (/sys/kernel/debug/scmi/transport/is_atomic is True). Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x15//info/* +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: SCMI Sensor Protocol informational RO data for sensor resource + with id : each entry under info/ subdir maps to an equally + named field of struct scmi_sensor_info as documented in + include/scmi/protocol.h +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x15//reading_get +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: SCMI Sensor Protocol reading_get operation for sensor resource + with id ; a read returns an u64 integer value representing + the current sensor reading. +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x15//reading_get_timestamped +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: SCMI Sensor Protocol reading_get_timestamped operation for se= nsor + resource with id ; a read returns a list of pair of values + in the form :, where the TSTAMP_u64 + represents a timestamp taken by the platform when the sensor + reading was sampled. +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x15//enable +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: SCMI Sensor Protocol enable operation for sensor resource with + id ; a read returns a boolen value representing the current + enable state of the sensor, while writing a boolean value causes + that specific sensor to be enabled or disabled. +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x15//sensor_config +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: SCMI Sensor Protocol config operation for sensor resource with + id ; a read returns a base-16 integer representing the + current sensor configuration as described in the relevant SCMI + specification (SENSOR_CONFIG_GET), while writing a base-16 + integer value sets the sensor configuration as per the relevant + SCMI specification (SENSOR_CONFIG_SET). +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x15//trips//set +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: SCMI Sensor Protocol trip points configuration operation for + sensor resource with id and trip point number ; + writing a base-10 integer value configure and enable trip point + for sensor . +Users: KSelftest, Debugging diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/= firmware/arm_scmi/scmi_test_driver/Makefile index 6e3ddd177827..458883193f31 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile +++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -scmi_test_driver-objs :=3D scmi_test.o test_common.o test_clocks.o +scmi_test_driver-objs :=3D scmi_test.o test_common.o test_clocks.o test_se= nsors.o obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) +=3D scmi_test_driver.o =20 diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drive= rs/firmware/arm_scmi/scmi_test_driver/scmi_test.c index f99aa621684c..04e01dd114c9 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c +++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c @@ -24,6 +24,7 @@ DEFINE_MUTEX(scmi_test_mtx); static int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) =3D { [SCMI_PROTOCOL_CLOCK] =3D scmi_test_clock_init, + [SCMI_PROTOCOL_SENSOR] =3D scmi_test_sensor_init, }; =20 static void @@ -124,6 +125,7 @@ static int scmi_testing_probe(struct scmi_device *sdev) =20 static const struct scmi_device_id scmi_id_table[] =3D { { SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" }, + { SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" }, { }, }; MODULE_DEVICE_TABLE(scmi, scmi_id_table); diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_common.h index 3c64cae9fae9..e02c2521f090 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h @@ -73,5 +73,6 @@ int scmi_test_fixed_buffer_open(struct inode *ino, struct= file *filp); int scmi_test_release(struct inode *ino, struct file *filp); =20 int scmi_test_clock_init(struct scmi_test_setup *tsp); +int scmi_test_sensor_init(struct scmi_test_setup *tsp); =20 #endif /* __SCMI_TEST_COMMON_H */ diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c b/dr= ivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c new file mode 100644 index 000000000000..23206c2bac98 --- /dev/null +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c @@ -0,0 +1,525 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SCMI Testing Driver - Clock Protocol + * + * Copyright (C) 2022 ARM Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_common.h" + +struct scmi_sensor_data { + unsigned int version; + int count; + const struct scmi_sensor_info **sinfo; +}; + +static int scmi_test_sensor_reading_open(struct inode *ino, struct file *f= ilp) +{ + unsigned int id; + size_t blen; + struct scmi_test_buffer *data; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + struct scmi_sensor_data *sdata =3D tsp->priv; + const char *id_str =3D filp->f_path.dentry->d_parent->d_name.name; + + /* Grab clk ID from debugfs entry naming if any */ + if (kstrtouint(id_str, 10, &id)) + return -EINVAL; + + if (!sdata->sinfo[id]->num_axis) + blen =3D SCMI_TEST_DEFAULT_BUF_SZ; + else + blen =3D 48 * sdata->sinfo[id]->num_axis; + + data =3D kzalloc(sizeof(*data) + blen, GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->id =3D id; + data->len =3D blen; + filp->private_data =3D data; + + return 0; +} + +static ssize_t scmi_test_sensor_reading_get(struct file *filp, char __user= *buf, + size_t count, loff_t *ppos) +{ + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + if (!data->used) { + int ret; + bool tstamp_req; + u64 value; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const struct scmi_sensor_proto_ops *sensor_ops =3D tsp->ops; + + tstamp_req =3D !strncmp(filp->f_path.dentry->d_name.name, + "reading_get_timestamped", + strlen("reading_get_timestamped")); + + if (!tstamp_req) { + ret =3D sensor_ops->reading_get(tsp->ph, data->id, + &value); + if (ret) + return ret; + + data->used =3D scnprintf(data->buf, data->len, "%llu\n", + value); + } else { + u8 count; + int i; + struct scmi_sensor_reading *readings; + const struct scmi_sensor_info *sinfo; + struct scmi_sensor_data *sdata =3D tsp->priv; + + sinfo =3D sdata->sinfo[data->id]; + if (!sinfo) + return -EINVAL; + + count =3D sinfo->num_axis ?: 1; + readings =3D kcalloc(count, sizeof(*readings), + GFP_KERNEL); + if (!readings) + return -ENOMEM; + + ret =3D sensor_ops->reading_get_timestamped(tsp->ph, + data->id, + count, + readings); + if (ret) { + kfree(readings); + return ret; + } + + for (i =3D 0; i < count; i++) + data->used +=3D scnprintf(data->buf + data->used, + data->len - data->used, + "%llu:%lld ", + readings[i].timestamp, + readings[i].value); + + data->used +=3D scnprintf(data->buf + data->used, + data->len - data->used, "\n"); + + kfree(readings); + } + } + + return simple_read_from_buffer(buf, count, ppos, data->buf, data->used); +} + +static const struct file_operations test_sensor_reading_get_fops_ro =3D { + .open =3D scmi_test_sensor_reading_open, + .release =3D scmi_test_release, + .read =3D scmi_test_sensor_reading_get, +}; + +static ssize_t scmi_test_sensor_enable_read(struct file *filp, char __user= *buf, + size_t count, loff_t *ppos) +{ + int ret; + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + if (!data->used) { + u32 sensor_config; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const struct scmi_sensor_proto_ops *sensor_ops =3D tsp->ops; + + ret =3D sensor_ops->config_get(tsp->ph, data->id, &sensor_config); + if (ret) + return ret; + + data->used =3D scnprintf(data->buf, data->len, "%lu\n", + SCMI_SENS_CFG_IS_ENABLED(sensor_config)); + } + + return simple_read_from_buffer(buf, count, ppos, data->buf, data->used); +} + +static ssize_t scmi_test_sensor_enable_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + bool enabled; + int ret; + u32 sensor_config; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const struct scmi_sensor_proto_ops *sensor_ops =3D tsp->ops; + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + ret =3D kstrtobool_from_user(buf, count, &enabled); + if (ret) + return ret; + + ret =3D sensor_ops->config_get(tsp->ph, data->id, &sensor_config); + if (ret) + return ret; + + sensor_config &=3D ~SCMI_SENS_CFG_SENSOR_ENABLED_MASK; + sensor_config |=3D FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK, enabled); + + ret =3D sensor_ops->config_set(tsp->ph, data->id, sensor_config); + if (ret) + return ret; + + return count; +} + +static const struct file_operations test_sensor_enable_fops_rw =3D { + .open =3D scmi_test_setup_open, + .release =3D scmi_test_release, + .read =3D scmi_test_sensor_enable_read, + .write =3D scmi_test_sensor_enable_write, +}; + +static ssize_t scmi_test_sensor_config_read(struct file *filp, char __user= *buf, + size_t count, loff_t *ppos) +{ + int ret; + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + if (!data->used) { + u32 sensor_config; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const struct scmi_sensor_proto_ops *sensor_ops =3D tsp->ops; + + ret =3D sensor_ops->config_get(tsp->ph, data->id, &sensor_config); + if (ret) + return ret; + + data->used =3D scnprintf(data->buf, data->len, "0x%X\n", + sensor_config); + } + + return simple_read_from_buffer(buf, count, ppos, data->buf, data->used); +} + +static ssize_t scmi_test_sensor_config_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + int ret; + u32 sensor_config; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const struct scmi_sensor_proto_ops *sensor_ops =3D tsp->ops; + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + ret =3D kstrtou32_from_user(buf, count, 16, &sensor_config); + if (ret) + return ret; + + ret =3D sensor_ops->config_set(tsp->ph, data->id, sensor_config); + if (ret) + return ret; + + return count; +} + +static const struct file_operations test_sensor_config_fops_rw =3D { + .open =3D scmi_test_setup_open, + .release =3D scmi_test_release, + .read =3D scmi_test_sensor_config_read, + .write =3D scmi_test_sensor_config_write, +}; + +static ssize_t scmi_test_sensor_trip_config_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + int ret; + unsigned int sid; + u64 trip_config; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const struct scmi_sensor_proto_ops *sensor_ops =3D tsp->ops; + struct scmi_test_buffer *data =3D filp->private_data; + /* protocol_0x15/008/trips/001/set */ + const char *sid_str =3D + filp->f_path.dentry->d_parent->d_parent->d_parent->d_name.name; + + if (!data || kstrtouint(sid_str, 10, &sid)) + return 0; + + /* Cannot clear !!! Not supported by .trip_point_config */ + ret =3D kstrtou64_from_user(buf, count, 10, &trip_config); + if (ret) + return ret; + + ret =3D sensor_ops->trip_point_config(tsp->ph, sid, + data->id, trip_config); + if (ret) + return ret; + + return count; +} + +static const struct file_operations test_sensor_trip_config_fops =3D { + .open =3D scmi_test_setup_open, + .release =3D scmi_test_release, + .write =3D scmi_test_sensor_trip_config_write, +}; + +static void scmi_test_sensor_trips_debugfs(struct dentry *pdentry, + struct scmi_test_setup *tsp, + unsigned int num_points) +{ + struct dentry *trips_dentry; + + trips_dentry =3D debugfs_create_dir("trips", pdentry); + + if (!IS_ERR(trips_dentry)) { + int i; + + for (i =3D 0; i < num_points; i++) { + char point_dir[16]; + struct dentry *point_dentry; + + snprintf(point_dir, 16, "%03d", i); + point_dentry =3D + debugfs_create_dir(point_dir, trips_dentry); + if (!IS_ERR(point_dentry)) + debugfs_create_file("set", 0200, + point_dentry, tsp, + &test_sensor_trip_config_fops); + } + } +} + +static int scmi_test_sensor_intervals_open(struct inode *ino, struct file = *filp) +{ + size_t ilen; + struct scmi_test_buffer *data; + struct scmi_sensor_intervals_info *i =3D filp->f_inode->i_private; + + /* 65536^-16\n */ + ilen =3D i->count * 16; + data =3D kzalloc(sizeof(*data) + ilen, GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->len =3D ilen; + filp->private_data =3D data; + + return 0; +} + +static ssize_t scmi_test_sensor_intervals_read(struct file *filp, + char __user *buf, + size_t count, loff_t *ppos) +{ + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + if (!data->used) { + int c; + struct scmi_sensor_intervals_info *i =3D filp->f_inode->i_private; + + for (c =3D 0; c < i->count; c++) + data->used +=3D scnprintf(data->buf + data->used, + data->len - data->used, + "%lu^%d ", + SCMI_SENS_INTVL_GET_SECS(i->desc[c]), + SCMI_SENS_INTVL_GET_EXP(i->desc[c])); + + data->used +=3D scnprintf(data->buf + data->used, + data->len - data->used, "\n"); + } + + return simple_read_from_buffer(buf, count, ppos, data->buf, data->used); +} + +static const struct file_operations test_sensor_intervals_fops =3D { + .open =3D scmi_test_sensor_intervals_open, + .release =3D scmi_test_release, + .read =3D scmi_test_sensor_intervals_read, +}; + +static void +scmi_test_debugfs_sensor_info_create(const struct scmi_sensor_info *si, + struct dentry *top_dentry) +{ + struct dentry *parent; + struct scmi_sensor_info *sinfo =3D (struct scmi_sensor_info *)si; + + parent =3D debugfs_create_dir("info", top_dentry); + if (IS_ERR(parent)) + return; + + debugfs_create_u32("type", 0400, parent, &sinfo->type); + debugfs_create_s32("scale", 0400, parent, &sinfo->scale); + debugfs_create_u32("num_trip_points", 0400, parent, + &sinfo->num_trip_points); + debugfs_create_bool("async", 0400, parent, &sinfo->async); + debugfs_create_bool("continuos_updates", 0400, parent, + &sinfo->update); + debugfs_create_bool("timestamped", 0400, parent, + &sinfo->timestamped); + debugfs_create_s32("tstamp_scale", 0400, parent, + &sinfo->tstamp_scale); + + debugfs_create_u32("num_axis", 0400, parent, &sinfo->num_axis); + if (sinfo->num_axis) { + int i; + struct dentry *axes; + + axes =3D debugfs_create_dir("axes", parent); + if (IS_ERR(axes)) + return; + + for (i =3D 0; i < sinfo->num_axis; i++) { + char axis_dir[16]; + struct dentry *axis; + + snprintf(axis_dir, 16, "%03d", i); + axis =3D debugfs_create_dir(axis_dir, axes); + if (IS_ERR(axis)) + return; + + debugfs_create_u32("type", 0400, axis, + &sinfo->axis[i].type); + debugfs_create_s32("scale", 0400, axis, + &sinfo->axis[i].scale); + debugfs_create_file("name", 0400, axis, + sinfo->axis[i].name, + &scmi_test_string_file_fops); + if (sinfo->axis[i].extended_attrs) { + debugfs_create_u32("resolution", 0400, axis, + &sinfo->axis[i].resolution); + debugfs_create_s32("exponent", 0400, axis, + &sinfo->axis[i].exponent); + debugfs_create_s64("min_range", 0400, axis, + &sinfo->axis[i].attrs.min_range); + debugfs_create_s64("max_range", 0400, axis, + &sinfo->axis[i].attrs.max_range); + } + } + } + + if (sinfo->intervals.segmented && sinfo->intervals.count =3D=3D 3) { + debugfs_create_u32("interval_low", 0400, parent, + &sinfo->intervals.desc[SCMI_SENS_INTVL_SEGMENT_LOW]); + debugfs_create_u32("interval_high", 0400, parent, + &sinfo->intervals.desc[SCMI_SENS_INTVL_SEGMENT_HIGH]); + debugfs_create_u32("interval_step", 0400, parent, + &sinfo->intervals.desc[SCMI_SENS_INTVL_SEGMENT_STEP]); + } else { + debugfs_create_file("intervals", 0400, parent, + &sinfo->intervals, + &test_sensor_intervals_fops); + } + + debugfs_create_u32("sensor_config", 0400, parent, + &sinfo->sensor_config); + + debugfs_create_file("name", 0400, parent, sinfo->name, + &scmi_test_string_file_fops); + + if (sinfo->extended_scalar_attrs) { + debugfs_create_u32("sensor_power", 0400, parent, + &sinfo->sensor_power); + debugfs_create_u32("resolution", 0400, parent, + &sinfo->resolution); + debugfs_create_s32("exponent", 0400, parent, + &sinfo->exponent); + debugfs_create_s64("min_range", 0400, parent, + &sinfo->scalar_attrs.min_range); + debugfs_create_s64("max_range", 0400, parent, + &sinfo->scalar_attrs.max_range); + } +} + +int scmi_test_sensor_init(struct scmi_test_setup *tsp) +{ + int i; + struct scmi_sensor_data *sdata; + const struct scmi_sensor_proto_ops *sensor_ops; + struct device *dev =3D &tsp->sdev->dev; + + sdata =3D devm_kzalloc(dev, sizeof(*sdata), GFP_KERNEL); + if (!sdata) + return -ENOMEM; + + sensor_ops =3D tsp->ops; + sdata->version =3D sensor_ops->version_get(tsp->ph); + sdata->count =3D sensor_ops->count_get(tsp->ph); + + if (sdata->count <=3D 0) { + dev_err(dev, "number of domains invalid: %d\n", + sdata->count); + return sdata->count ?: -EINVAL; + } + + sdata->sinfo =3D devm_kcalloc(dev, sdata->count, + sizeof(sdata->sinfo), GFP_KERNEL); + if (!sdata->sinfo) + return -ENOMEM; + + for (i =3D 0; i < sdata->count; i++) + sdata->sinfo[i] =3D sensor_ops->info_get(tsp->ph, i); + + tsp->priv =3D sdata; + debugfs_create_x32("version", 0400, tsp->parent, &sdata->version); + + dev_info(dev, "Found %d sensor resources.\n", sdata->count); + + for (i =3D 0; i < sdata->count; i++) { + char sensor_dir[16]; + struct dentry *sensor_dentry; + + if (!sdata->sinfo[i]) + continue; + + snprintf(sensor_dir, 16, "%03d", i); + sensor_dentry =3D debugfs_create_dir(sensor_dir, tsp->parent); + if (!IS_ERR(sensor_dentry)) { + scmi_test_debugfs_sensor_info_create(sdata->sinfo[i], + sensor_dentry); + debugfs_create_file("reading_get", 0400, + sensor_dentry, tsp, + &test_sensor_reading_get_fops_ro); + debugfs_create_file("reading_get_timestamped", 0400, + sensor_dentry, tsp, + &test_sensor_reading_get_fops_ro); + debugfs_create_file("enable", 0600, + sensor_dentry, tsp, + &test_sensor_enable_fops_rw); + debugfs_create_file("sensor_config", 0600, + sensor_dentry, tsp, + &test_sensor_config_fops_rw); + + if (sdata->sinfo[i]->num_trip_points) + scmi_test_sensor_trips_debugfs(sensor_dentry, + tsp, + sdata->sinfo[i]->num_trip_points); + } + } + + return 0; +} --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F26FFC433EF for ; Sun, 27 Feb 2022 20:57:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232032AbiB0U5u (ORCPT ); Sun, 27 Feb 2022 15:57:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59316 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231778AbiB0U5T (ORCPT ); Sun, 27 Feb 2022 15:57:19 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 560292FFE7 for ; Sun, 27 Feb 2022 12:56:40 -0800 (PST) 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 2601B106F; Sun, 27 Feb 2022 12:56:40 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BD08D3F66F; Sun, 27 Feb 2022 12:56:38 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 11/16] firmware: arm_scmi: Add test driver generic notification helpers Date: Sun, 27 Feb 2022 20:56:03 +0000 Message-Id: <20220227205608.30812-12-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add a few generic helpers to allow the test driver to register a common notifier block and related read routines in order to test notifications when supported by the specific SCMI protocol. Signed-off-by: Cristian Marussi --- .../arm_scmi/scmi_test_driver/test_common.c | 177 ++++++++++++++++++ .../arm_scmi/scmi_test_driver/test_common.h | 28 +++ 2 files changed, 205 insertions(+) diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_common.c index cbe2eec4f2ac..c44fe702196e 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c @@ -14,6 +14,22 @@ =20 #include "test_common.h" =20 +struct scmi_test_setup * +scmi_test_tsp_shallow_copy(struct device *dev, + struct scmi_test_setup *tsp) +{ + struct scmi_test_setup *tsp_copy; + + tsp_copy =3D devm_kzalloc(dev, sizeof(*tsp_copy), GFP_KERNEL); + if (!tsp_copy) + return ERR_PTR(-ENOMEM); + + memcpy(tsp_copy, tsp, sizeof(*tsp_copy)); + tsp_copy->n_priv =3D NULL; + + return tsp_copy; +} + /* Common File operations */ =20 /** @@ -70,6 +86,167 @@ int scmi_test_release(struct inode *ino, struct file *f= ilp) return 0; } =20 +int scmi_test_generic_notif_cb(struct notifier_block *nb, unsigned long ev= ent, + void *data) +{ + struct scmi_test_notif_reports *nrep; + void *d_report; + + nrep =3D container_of(nb, struct scmi_test_notif_reports, notif_nb); + + mutex_lock(&nrep->mtx); + d_report =3D ((u8 *)nrep->reports) + + ((nrep->count % nrep->max_reports) * nrep->report_sz); + memcpy(d_report, data, nrep->report_sz); + nrep->count++; + mutex_unlock(&nrep->mtx); + + return NOTIFY_OK; +} + +static struct scmi_test_notif_reports * +scmi_test_notif_reports_alloc(struct scmi_device *sdev, + size_t report_sz, unsigned int max_reports, + u8 proto_id, u8 evt_id, const u32 *src_id, + notifier_fn_t notif_cb) +{ + int ret; + struct scmi_test_notif_reports *nrep; + struct device *dev =3D &sdev->dev; + const struct scmi_notify_ops *n_ops =3D sdev->handle->notify_ops; + + nrep =3D devm_kzalloc(dev, sizeof(*nrep), GFP_KERNEL); + if (!nrep) + return ERR_PTR(-ENOMEM); + + nrep->reports =3D devm_kcalloc(dev, max_reports, report_sz, GFP_KERNEL); + if (!nrep->reports) { + devm_kfree(dev, nrep); + return ERR_PTR(-ENOMEM); + } + + nrep->proto_id =3D proto_id; + nrep->evt_id =3D evt_id; + if (src_id) + nrep->src_id =3D *src_id; + else + nrep->src_id =3D 0xffffffff; + nrep->report_sz =3D report_sz; + nrep->max_reports =3D max_reports; + mutex_init(&nrep->mtx); + + if (notif_cb) + nrep->notif_nb.notifier_call =3D notif_cb; + else + nrep->notif_nb.notifier_call =3D scmi_test_generic_notif_cb; + + ret =3D n_ops->devm_event_notifier_register(sdev, + proto_id, evt_id, src_id, + &nrep->notif_nb); + if (ret) { + devm_kfree(dev, nrep->reports); + devm_kfree(dev, nrep); + return ERR_PTR(ret); + } + + return nrep; +} + +static int scmi_test_notif_reports_free(struct scmi_device *sdev, + struct scmi_test_notif_reports *nrep) +{ + int ret; + struct device *dev =3D &sdev->dev; + const struct scmi_notify_ops *n_ops =3D sdev->handle->notify_ops; + + if (!nrep) + return -EINVAL; + + ret =3D n_ops->devm_event_notifier_unregister(sdev, &nrep->notif_nb); + if (ret) + return ret; + + devm_kfree(dev, nrep->reports); + devm_kfree(dev, nrep); + + return 0; +} + +int scmi_test_notif_manage(struct scmi_test_setup *tsp, bool enabled, + u8 proto_id, u8 evt_id, const u32 *src_id, + size_t rep_sz, notifier_fn_t notif_cb) +{ + int ret; + + /* For testing allow enable only for one notifier at time */ + if ((enabled && tsp->n_priv) || (!enabled && !tsp->n_priv)) + return -EINVAL; + + if (enabled) { + tsp->n_priv =3D + scmi_test_notif_reports_alloc(tsp->sdev, rep_sz, + SCMI_TEST_MAX_REPORTS, + proto_id, evt_id, + src_id, notif_cb); + if (IS_ERR(tsp->n_priv)) { + ret =3D PTR_ERR(tsp->n_priv); + tsp->n_priv =3D NULL; + return ret; + } + } else { + ret =3D scmi_test_notif_reports_free(tsp->sdev, tsp->n_priv); + if (ret) + return ret; + + tsp->n_priv =3D NULL; + } + + return 0; +} + +ssize_t scmi_test_notif_reports_read(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + struct scmi_test_buffer *data =3D filp->private_data; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + struct scmi_test_notif_reports *nrep =3D tsp->n_priv; + + if (!data || !nrep) + return 0; + + if (!data->used) { + int i, cnt; + + mutex_lock(&nrep->mtx); + cnt =3D nrep->count >=3D nrep->max_reports ? + nrep->max_reports : nrep->count; + for (i =3D 0; i < cnt; i++) { + u8 *rep; + int j; + + data->used +=3D scnprintf(data->buf + data->used, + data->len - data->used, + "[%02u/%02u|%u] - |%02X|%u|%u| =3D Report: ", + i, + nrep->max_reports, nrep->count, + nrep->proto_id, nrep->evt_id, + nrep->src_id); + + rep =3D ((u8 *)nrep->reports) + i * nrep->report_sz; + for (j =3D 0; j < nrep->report_sz; j++) + data->used +=3D scnprintf(data->buf + data->used, + data->len - data->used, + "%02X ", rep[j]); + + data->used +=3D scnprintf(data->buf + data->used, + data->len - data->used, "\n"); + } + mutex_unlock(&nrep->mtx); + } + + return simple_read_from_buffer(buf, count, ppos, data->buf, data->used); +} + int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp) { struct scmi_test_buffer *data; diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_common.h index e02c2521f090..93c05db0ebff 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h @@ -66,8 +66,36 @@ struct scmi_test_buffer { unsigned char buf[]; }; =20 +#define SCMI_TEST_MAX_REPORTS 20 +struct scmi_test_notif_reports { + u8 proto_id; + u8 evt_id; + u32 src_id; + unsigned int max_reports; + size_t report_sz; + void *reports; + unsigned int count; + struct notifier_block notif_nb; + /* Protect access to notification reports */ + struct mutex mtx; +}; + extern const struct file_operations scmi_test_string_file_fops; =20 +int scmi_test_generic_notif_cb(struct notifier_block *nb, unsigned long ev= ent, + void *data); + +int scmi_test_notif_manage(struct scmi_test_setup *tsp, bool enabled, + u8 proto_id, u8 evt_id, const u32 *src_id, + size_t rep_sz, notifier_fn_t notif_cb); + +ssize_t scmi_test_notif_reports_read(struct file *filp, char __user *buf, + size_t count, loff_t *ppos); + +struct scmi_test_setup * +scmi_test_tsp_shallow_copy(struct device *dev, + struct scmi_test_setup *tsp); + int scmi_test_setup_open(struct inode *ino, struct file *filp); int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp); int scmi_test_release(struct inode *ino, struct file *filp); --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7D103C433FE for ; Sun, 27 Feb 2022 20:57:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232058AbiB0U5w (ORCPT ); Sun, 27 Feb 2022 15:57:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59620 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231863AbiB0U5Y (ORCPT ); Sun, 27 Feb 2022 15:57:24 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 1C5E43298A for ; Sun, 27 Feb 2022 12:56:41 -0800 (PST) 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 B755C1063; Sun, 27 Feb 2022 12:56:41 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 5BB753F66F; Sun, 27 Feb 2022 12:56:40 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 12/16] firmware: arm_scmi: Add Sensor notifications testing support Date: Sun, 27 Feb 2022 20:56:04 +0000 Message-Id: <20220227205608.30812-13-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add a few debugfs entry to enable Sensor notifications support, namely continuos sensor updates notifications and sensor trip point events notifications. Signed-off-by: Cristian Marussi --- Documentation/ABI/testing/debugfs-scmi | 50 +++++++++ .../arm_scmi/scmi_test_driver/test_sensors.c | 104 +++++++++++++++++- 2 files changed, 153 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/tes= ting/debugfs-scmi index 72835516dee8..8b3f9a12053d 100644 --- a/Documentation/ABI/testing/debugfs-scmi +++ b/Documentation/ABI/testing/debugfs-scmi @@ -217,3 +217,53 @@ Description: SCMI Sensor Protocol trip points configur= ation operation for writing a base-10 integer value configure and enable trip point for sensor . Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x15//sensor_update_notifs +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: A RW entry to support SENSOR_UPDATE notifications testing. + Writing a true value (Y/y/1) to this entry will trigger the + registration of a common notifier block for the SENSOR_UPDATE + notification as defined in SCMI Sensor Protocol: this common + notifier block starts collecting all the received notification + payload in a circular buffer. + The rate at which such notifications are emitted depends on the + specific update interval currently selected by the resource + at hand using the SENSOR_CONFIG command. + Note that, as per SCMI specification, the related sensor + resource has also to be in an enabled state for the + notifications to be emitted by the platform. + Reading from this entry will return the latest content of the + above mentioned circular buffer. + Writing a false value (N/n/0) to this entry will cause the above + mentioned common notifier block to be unregistered and so + effectively the notification emission to be stopped. + When the notifier is unregistered the notification circular + buffer is cleared empty. + This entry is present only if the related resource has + been advertised as supporting continuos updated notifications. +Users: KSelftest, Debugging + +What: /sys/kernel/debug/scmi/protocol_0x15//sensor_trip_notifs +Date: Feb 2022 +KernelVersion: 5.19 +Contact: cristian.marussi@arm.com +Description: A RW entry to support SENSOR_TRIP_POINT_EVENT notifications + testing. Writing a true value (Y/y/1) to this entry will trigger + the registration of a common notifier block for + SENSOR_TRIP_POINT_EVENT notification as defined in SCMI Sensor + Protocol: this common notifier block starts collecting all the + received notification payload in a circular buffer. + Such notifications will be emitted once the related sensor + resource crosses one of the configured trip point: such trip + point can be cofigured using SENSOR_TRIP_POINT_CONFIG command + and related entries in the SCMI debugfs filesystem. + Reading from this entry will return the latest content of the + above mentioned circular buffer. + Writing a false value (N/n/0) to this entry will cause the above + mentioned common notifier block to be unregistered and so + effectively the notification emission to be stopped. + When the notifier is unregistered the notification circular + buffer is cleared empty. +Users: KSelftest, Debugging diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c b/dr= ivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c index 23206c2bac98..2d610d84390f 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c @@ -284,6 +284,79 @@ static const struct file_operations test_sensor_trip_c= onfig_fops =3D { .write =3D scmi_test_sensor_trip_config_write, }; =20 +static ssize_t scmi_test_sensor_updates_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + bool enabled; + int ret; + u32 src_id; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + struct scmi_test_buffer *data =3D filp->private_data; + + if (!tsp || !data) + return count; + + ret =3D kstrtobool_from_user(buf, count, &enabled); + if (ret) + return ret; + + src_id =3D data->id; + ret =3D scmi_test_notif_manage(tsp, enabled, + SCMI_PROTOCOL_SENSOR, + SCMI_EVENT_SENSOR_UPDATE, &src_id, + sizeof(struct scmi_sensor_update_report), + scmi_test_generic_notif_cb); + if (ret < 0) + return ret; + + return count; +} + +static const struct file_operations test_sensor_updates_fops_rw =3D { + .open =3D scmi_test_setup_open, + .release =3D scmi_test_release, + .read =3D scmi_test_notif_reports_read, + .write =3D scmi_test_sensor_updates_write, +}; + +static ssize_t scmi_test_sensor_trip_point_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + bool enabled; + int ret; + u32 src_id; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + struct scmi_test_buffer *data =3D filp->private_data; + + if (!tsp || !data) + return count; + + ret =3D kstrtobool_from_user(buf, count, &enabled); + if (ret) + return ret; + + src_id =3D data->id; + ret =3D scmi_test_notif_manage(tsp, enabled, + SCMI_PROTOCOL_SENSOR, + SCMI_EVENT_SENSOR_TRIP_POINT_EVENT, + &src_id, + sizeof(struct scmi_sensor_trip_point_report), + scmi_test_generic_notif_cb); + if (ret < 0) + return ret; + + return count; +} + +static const struct file_operations test_sensor_trips_fops_rw =3D { + .open =3D scmi_test_setup_open, + .release =3D scmi_test_release, + .read =3D scmi_test_notif_reports_read, + .write =3D scmi_test_sensor_trip_point_write, +}; + static void scmi_test_sensor_trips_debugfs(struct dentry *pdentry, struct scmi_test_setup *tsp, unsigned int num_points) @@ -514,10 +587,39 @@ int scmi_test_sensor_init(struct scmi_test_setup *tsp) sensor_dentry, tsp, &test_sensor_config_fops_rw); =20 - if (sdata->sinfo[i]->num_trip_points) + if (sdata->sinfo[i]->update) { + struct scmi_test_setup *tsp_copy; + + tsp_copy =3D scmi_test_tsp_shallow_copy(dev, tsp); + if (IS_ERR(tsp_copy)) + return PTR_ERR(tsp_copy); + + /* Bigger dedicated buffer for notifs */ + tsp_copy->blen =3D 4096; + debugfs_create_file("sensor_update_notifs", + 0600, sensor_dentry, + tsp_copy, + &test_sensor_updates_fops_rw); + } + + if (sdata->sinfo[i]->num_trip_points) { + struct scmi_test_setup *tsp_copy; + scmi_test_sensor_trips_debugfs(sensor_dentry, tsp, sdata->sinfo[i]->num_trip_points); + + tsp_copy =3D scmi_test_tsp_shallow_copy(dev, tsp); + if (IS_ERR(tsp_copy)) + return PTR_ERR(tsp_copy); + + /* Bigger dedicated buffer for notifs */ + tsp_copy->blen =3D 4096; + debugfs_create_file("sensor_trip_notifs", + 0600, sensor_dentry, + tsp_copy, + &test_sensor_trips_fops_rw); + } } } =20 --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A2125C433F5 for ; Sun, 27 Feb 2022 20:57:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231894AbiB0U54 (ORCPT ); Sun, 27 Feb 2022 15:57:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59660 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231898AbiB0U5Z (ORCPT ); Sun, 27 Feb 2022 15:57:25 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 754C56D1A0 for ; Sun, 27 Feb 2022 12:56:43 -0800 (PST) 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 56994106F; Sun, 27 Feb 2022 12:56:43 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id ECDA33F66F; Sun, 27 Feb 2022 12:56:41 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 13/16] firmware: arm_scmi: Add testing Power protocol support Date: Sun, 27 Feb 2022 20:56:05 +0000 Message-Id: <20220227205608.30812-14-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" firmware: arm_scmi: Add testing Power protocol support Signed-off-by: Cristian Marussi --- .../arm_scmi/scmi_test_driver/Makefile | 3 +- .../arm_scmi/scmi_test_driver/scmi_test.c | 2 + .../arm_scmi/scmi_test_driver/test_common.h | 1 + .../arm_scmi/scmi_test_driver/test_powers.c | 105 ++++++++++++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/= firmware/arm_scmi/scmi_test_driver/Makefile index 458883193f31..68a3d94a6a88 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile +++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -scmi_test_driver-objs :=3D scmi_test.o test_common.o test_clocks.o test_se= nsors.o +scmi_test_driver-objs :=3D scmi_test.o test_common.o test_clocks.o test_se= nsors.o \ + test_powers.o obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) +=3D scmi_test_driver.o =20 diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drive= rs/firmware/arm_scmi/scmi_test_driver/scmi_test.c index 04e01dd114c9..df0d3e572010 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c +++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c @@ -23,6 +23,7 @@ DEFINE_MUTEX(scmi_test_mtx); =20 static int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) =3D { + [SCMI_PROTOCOL_POWER] =3D scmi_test_power_init, [SCMI_PROTOCOL_CLOCK] =3D scmi_test_clock_init, [SCMI_PROTOCOL_SENSOR] =3D scmi_test_sensor_init, }; @@ -126,6 +127,7 @@ static int scmi_testing_probe(struct scmi_device *sdev) static const struct scmi_device_id scmi_id_table[] =3D { { SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" }, { SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" }, + { SCMI_PROTOCOL_POWER, "__scmi_test-power" }, { }, }; MODULE_DEVICE_TABLE(scmi, scmi_id_table); diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_common.h index 93c05db0ebff..9f3d35ba4477 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h @@ -102,5 +102,6 @@ int scmi_test_release(struct inode *ino, struct file *f= ilp); =20 int scmi_test_clock_init(struct scmi_test_setup *tsp); int scmi_test_sensor_init(struct scmi_test_setup *tsp); +int scmi_test_power_init(struct scmi_test_setup *tsp); =20 #endif /* __SCMI_TEST_COMMON_H */ diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_powers.c new file mode 100644 index 000000000000..5db1662f2dc7 --- /dev/null +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SCMI Testing Driver - Power Protocol + * + * Copyright (C) 2022 ARM Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_common.h" + +struct scmi_power_data { + unsigned int version; + int count; +}; + +static ssize_t scmi_test_power_info_read(struct file *filp, char __user *b= uf, + size_t count, loff_t *ppos) +{ + struct scmi_test_buffer *data =3D filp->private_data; + + if (!data) + return 0; + + if (!data->used) { + u32 pstate; + char *pname; + struct scmi_test_setup *tsp =3D filp->f_inode->i_private; + const struct scmi_power_proto_ops *power_ops =3D tsp->ops; + + pname =3D power_ops->name_get(tsp->ph, data->id); + power_ops->state_get(tsp->ph, data->id, &pstate); + + data->used =3D scnprintf(data->buf, data->len, + "%s -> state:%d\n", + pname, pstate); + } + + if (*ppos >=3D data->used) + return 0; + + if (count > data->used) + count =3D data->used; + + count -=3D copy_to_user(buf, data->buf + *ppos, count); + *ppos +=3D count; + + return count; +} + +static const struct file_operations test_power_info_fops =3D { + .open =3D scmi_test_setup_open, + .release =3D scmi_test_release, + .read =3D scmi_test_power_info_read, +}; + +int scmi_test_power_init(struct scmi_test_setup *tsp) +{ + int i; + struct scmi_power_data *pdata; + const struct scmi_power_proto_ops *power_ops; + struct device *dev =3D &tsp->sdev->dev; + + pdata =3D devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + power_ops =3D tsp->ops; + pdata->version =3D power_ops->version_get(tsp->ph); + pdata->count =3D power_ops->num_domains_get(tsp->ph); + + if (pdata->count <=3D 0) { + dev_err(dev, "number of domains invalid: %d\n", + pdata->count); + return pdata->count ?: -EINVAL; + } + + tsp->priv =3D pdata; + debugfs_create_x32("version", 0400, tsp->parent, &pdata->version); + + dev_info(dev, "Found %d power-domain resources.\n", pdata->count); + + for (i =3D 0; i < pdata->count; i++) { + char power_dir[16]; + struct dentry *power_dentry; + + snprintf(power_dir, 16, "%03d", i); + power_dentry =3D debugfs_create_dir(power_dir, tsp->parent); + if (!IS_ERR(power_dentry)) { + debugfs_create_file("info", 0400, + power_dentry, tsp, + &test_power_info_fops); + } + } + + return 0; +} --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7753BC433FE for ; Sun, 27 Feb 2022 20:57:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230110AbiB0U6B (ORCPT ); Sun, 27 Feb 2022 15:58:01 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59654 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231912AbiB0U52 (ORCPT ); Sun, 27 Feb 2022 15:57:28 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 0BD2F6E2B2 for ; Sun, 27 Feb 2022 12:56:45 -0800 (PST) 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 E786C1063; Sun, 27 Feb 2022 12:56:44 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8C7BD3F66F; Sun, 27 Feb 2022 12:56:43 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 14/16] firmware: arm_scmi: Add testing Voltage protocol support Date: Sun, 27 Feb 2022 20:56:06 +0000 Message-Id: <20220227205608.30812-15-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" firmware: arm_scmi: Add testing Voltage protocol support Signed-off-by: Cristian Marussi --- .../arm_scmi/scmi_test_driver/Makefile | 2 +- .../arm_scmi/scmi_test_driver/scmi_test.c | 2 + .../arm_scmi/scmi_test_driver/test_common.h | 1 + .../arm_scmi/scmi_test_driver/test_voltages.c | 51 +++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_voltage= s.c diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/= firmware/arm_scmi/scmi_test_driver/Makefile index 68a3d94a6a88..3b7df18de250 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile +++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only scmi_test_driver-objs :=3D scmi_test.o test_common.o test_clocks.o test_se= nsors.o \ - test_powers.o + test_powers.o test_voltages.o obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) +=3D scmi_test_driver.o =20 diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drive= rs/firmware/arm_scmi/scmi_test_driver/scmi_test.c index df0d3e572010..2ca9f82c5bf3 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c +++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c @@ -26,6 +26,7 @@ int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_tes= t_setup *) =3D { [SCMI_PROTOCOL_POWER] =3D scmi_test_power_init, [SCMI_PROTOCOL_CLOCK] =3D scmi_test_clock_init, [SCMI_PROTOCOL_SENSOR] =3D scmi_test_sensor_init, + [SCMI_PROTOCOL_VOLTAGE] =3D scmi_test_voltage_init, }; =20 static void @@ -125,6 +126,7 @@ static int scmi_testing_probe(struct scmi_device *sdev) } =20 static const struct scmi_device_id scmi_id_table[] =3D { + { SCMI_PROTOCOL_VOLTAGE, "__scmi_test-voltage" }, { SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" }, { SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" }, { SCMI_PROTOCOL_POWER, "__scmi_test-power" }, diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/dri= vers/firmware/arm_scmi/scmi_test_driver/test_common.h index 9f3d35ba4477..338b65da593f 100644 --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h @@ -102,6 +102,7 @@ int scmi_test_release(struct inode *ino, struct file *f= ilp); =20 int scmi_test_clock_init(struct scmi_test_setup *tsp); int scmi_test_sensor_init(struct scmi_test_setup *tsp); +int scmi_test_voltage_init(struct scmi_test_setup *tsp); int scmi_test_power_init(struct scmi_test_setup *tsp); =20 #endif /* __SCMI_TEST_COMMON_H */ diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c b/d= rivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c new file mode 100644 index 000000000000..ab91080e3a0f --- /dev/null +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SCMI Testing Driver - Voltage Protocol + * + * Copyright (C) 2022 ARM Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_common.h" + +struct scmi_voltage_data { + unsigned int version; + int count; +}; + +int scmi_test_voltage_init(struct scmi_test_setup *tsp) +{ + struct scmi_voltage_data *vdata; + struct device *dev =3D &tsp->sdev->dev; + const struct scmi_voltage_proto_ops *voltage_ops; + + vdata =3D devm_kzalloc(dev, sizeof(*vdata), GFP_KERNEL); + if (!vdata) + return -ENOMEM; + + voltage_ops =3D tsp->ops; + vdata->version =3D voltage_ops->version_get(tsp->ph); + vdata->count =3D voltage_ops->num_domains_get(tsp->ph); + + if (vdata->count <=3D 0) { + dev_err(dev, "number of voltage doms invalid: %d\n", + vdata->count); + return vdata->count ?: -EINVAL; + } + + dev_info(dev, "Found %d voltage resources.\n", vdata->count); + + tsp->priv =3D vdata; + debugfs_create_x32("version", 0400, tsp->parent, &vdata->version); + + return 0; +} --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 752DDC433F5 for ; Sun, 27 Feb 2022 20:57:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231887AbiB0U57 (ORCPT ); Sun, 27 Feb 2022 15:57:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59662 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231919AbiB0U5b (ORCPT ); Sun, 27 Feb 2022 15:57:31 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 9E4F96E4C0 for ; Sun, 27 Feb 2022 12:56:46 -0800 (PST) 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 85A5711FB; Sun, 27 Feb 2022 12:56:46 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2911D3F66F; Sun, 27 Feb 2022 12:56:45 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 15/16] selftests: arm64: Add initial SCMI testcases Date: Sun, 27 Feb 2022 20:56:07 +0000 Message-Id: <20220227205608.30812-16-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" A few initial testcases for Clock and Sensot protocol plus all the test infrastructure, including the test runeer. All of this just an experimental demonstrator. Signed-off-by: Cristian Marussi --- tools/testing/selftests/arm64/Makefile | 2 +- tools/testing/selftests/arm64/scmi/Makefile | 6 + tools/testing/selftests/arm64/scmi/config | 1 + .../arm64/scmi/kselftest_scmi_lib.sh | 118 ++++++++++++++++++ .../selftests/arm64/scmi/run_scmi_tests.sh | 69 ++++++++++ .../testcases/protocol_0x14/clock_enable.sh | 33 +++++ .../protocol_0x14/clock_rate_read.sh | 18 +++ .../protocol_0x14/clock_rate_write.sh | 29 +++++ .../testcases/protocol_0x15/sensor_reading.sh | 17 +++ 9 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/arm64/scmi/Makefile create mode 100644 tools/testing/selftests/arm64/scmi/config create mode 100644 tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh create mode 100755 tools/testing/selftests/arm64/scmi/run_scmi_tests.sh create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0= x14/clock_enable.sh create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0= x14/clock_rate_read.sh create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0= x14/clock_rate_write.sh create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0= x15/sensor_reading.sh diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftes= ts/arm64/Makefile index 1e8d9a8f59df..6648dd8e2173 100644 --- a/tools/testing/selftests/arm64/Makefile +++ b/tools/testing/selftests/arm64/Makefile @@ -4,7 +4,7 @@ ARCH ?=3D $(shell uname -m 2>/dev/null || echo not) =20 ifneq (,$(filter $(ARCH),aarch64 arm64)) -ARM64_SUBTARGETS ?=3D tags signal pauth fp mte bti abi +ARM64_SUBTARGETS ?=3D tags signal pauth fp mte bti abi scmi else ARM64_SUBTARGETS :=3D endif diff --git a/tools/testing/selftests/arm64/scmi/Makefile b/tools/testing/se= lftests/arm64/scmi/Makefile new file mode 100644 index 000000000000..8786d8d4c332 --- /dev/null +++ b/tools/testing/selftests/arm64/scmi/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 + +TEST_PROGS :=3D run_scmi_tests.sh +TEST_FILES :=3D kselftest_scmi_lib.sh testcases/* + +include ../../lib.mk diff --git a/tools/testing/selftests/arm64/scmi/config b/tools/testing/self= tests/arm64/scmi/config new file mode 100644 index 000000000000..161387084a3f --- /dev/null +++ b/tools/testing/selftests/arm64/scmi/config @@ -0,0 +1 @@ +CONFIG_ARM_SCMI_TEST_DRIVER=3Dy diff --git a/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh b/too= ls/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh new file mode 100644 index 000000000000..54d27b5f3e1a --- /dev/null +++ b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh @@ -0,0 +1,118 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +SCMI_TEST_DRV=3D"scmi_test_driver" +TRES=3D(0 0 0) + +ksft_log() +{ + echo -e "[SCMI]: $1" +} + +ksft_skip() +{ + echo -e "[SKIP]: $1" + exit 4 +} + +ksft_pass() +{ + echo -e "[PASS]: $1" +} + +ksft_fail() +{ + echo -e "[FAIL]: $1" + exit 1 +} + +ksft_results() +{ + if [ $# -gt 0 ]; then + local val + local idx + local ret=3D$1 + + case "$ret" in + 0) + idx=3D0 + ;; + 4) + idx=3D1 + ;; + *) + idx=3D2 + ;; + esac + val=3D${TRES[${idx}]} + TRES[$idx]=3D$((val + 1)) + else + ksft_log "Summary - PASS[${TRES[0]}] SKIP[${TRES[1]}] FAIL[${TRES[2]}]" + [ "x${TRES[2]}" !=3D "x0" ] && exit 1 + [ "x${TRES[1]}" !=3D "x0" -a "x${TRES[0]}" =3D=3D "x0" ] && exit 4 + exit 0 + fi +} + +ksft_scmi_run_one() +{ + tcase=3D$1 + + echo "-> Running testcase: $tcase" + + ./$tcase + ret=3D$? + + ksft_results $ret +} + +ksft_scmi_check_fw_version() +{ + local supported=3D$1 + local current=3D"${SCMI_VENDOR}:${SCMI_SUB_VENDOR}" + + if [ "x${current}" !=3D "x${supported}" ]; then + ksft_skip "Current FW('$current') is UNSUPPORTED. Should be '$supported'" + fi +} + +ksft_scmi_transport_is_atomic () +{ + [ "x$SCMI_TRANSPORT_IS_ATOMIC" =3D=3D "xY" ] && return 0 || return 1 +} + +ksft_scmi_protocol_resources_get() +{ + local proto_dir=3D$1 + local resources=3D"" + + for d in ${proto_dir}/*; do + rd=3D"$(basename $d)" + [[ $rd =3D~ [0-9] ]] && resources=3D"$resources $rd" + done + + echo "$resources" +} + +ksft_scmi_value_get() +{ + local syspath=3D$1 + local __retval=3D$2 + local value + + value=3D$(cat $syspath) + [ "x$?" !=3D "x0" ] && ksft_fail "Fail to read $syspath" + + eval $__retval=3D"'$value'" +} + +ksft_scmi_value_set() +{ + local syspath=3D$1 + local value=3D$2 + + echo $value > $syspath + [ "x$?" !=3D "x0" ] && ksft_fail "Fail to write $syspath - err:$?" +} + + diff --git a/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh b/tools/t= esting/selftests/arm64/scmi/run_scmi_tests.sh new file mode 100755 index 000000000000..f372744a4579 --- /dev/null +++ b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +. ./kselftest_scmi_lib.sh + +check_root_privs() +{ + [ x"$(id -u)" !=3D "x0" ] && ksft_skip "You need to be root" +} + +check_scmi_testing_stack() +{ + local debugfs_root=3D$(findmnt -o TARGET -t debugfs | grep -v TARGET) + export SCMI_DEBUGFS_TOPDIR=3D"$debugfs_root/scmi" + + # Try to load module if not builtin + if [ ! -d $SCMI_DEBUGFS_TOPDIR ]; then + modprobe $SCMI_TEST_DRV || ksft_skip "Failed to load $SCMI_TEST_DRV" + [ ! -d $SCMI_DEBUGFS_TOPDIR ] && ksft_skip "SCMI Test stack not found; i= s CONFIG_ARM_SCMI_TEST_DRIVER enabled ?" + fi +} + +setup_scmi_test_env() +{ + local scmi_info_dir=3D"${SCMI_DEBUGFS_TOPDIR}/info/" + + export SCMI_VENDOR=3D"$(cat ${scmi_info_dir}/vendor_id)" + export SCMI_SUB_VENDOR=3D"$(cat ${scmi_info_dir}/sub_vendor_id)" + export SCMI_VERS_MAJ=3D"$(cat ${scmi_info_dir}/major_ver)" + export SCMI_VERS_MIN=3D"$(cat ${scmi_info_dir}/minor_ver)" + export SCMI_VERS_IMPL=3D"$(cat ${scmi_info_dir}/impl_ver)" + + ksft_log "Found stack: $SCMI_VENDOR/$SCMI_SUB_VENDOR ${SCMI_VERS_MAJ}.${S= CMI_VERS_MAJ} - $SCMI_VERS_IMPL" + + SCMI_TEST_PROTOS=3D"" + for p in ${SCMI_DEBUGFS_TOPDIR}/protocol_*; do + SCMI_TEST_PROTOS=3D"${SCMI_TEST_PROTOS} $(basename $p)" + done + + ksft_log "Found testing protocols: $SCMI_TEST_PROTOS" + + export SCMI_TEST_PROTOS + SCMI_TRANSPORT_IS_ATOMIC=3D"N" + [ -d "${SCMI_DEBUGFS_TOPDIR}/transport" ] && + SCMI_TRANSPORT_IS_ATOMIC=3D$(cat "${SCMI_DEBUGFS_TOPDIR}/transport/is_at= omic") + export SCMI_TRANSPORT_IS_ATOMIC +} + +# Setup +check_root_privs + +check_scmi_testing_stack + +setup_scmi_test_env + +# Main +# Run all available tests for the found protocols +# +for proto_dir in $SCMI_TEST_PROTOS; do + [ ! -d $proto_dir ] && ksft_log "$proto_dir tests NOT supported." && cont= inue + export TST_PROTO_DIR=3D"${SCMI_DEBUGFS_TOPDIR}/${proto_dir}" + TST_PROTO_VERSION=3D$(cat ${TST_PROTO_DIR}/version) + ksft_log "Running tests for SCMI $proto_dir ver:$TST_PROTO_VERSION" + for tst in $proto_dir/*; do + ksft_scmi_run_one $tst + done +done + +ksft_results diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clo= ck_enable.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/c= lock_enable.sh new file mode 100755 index 000000000000..4cdf3a097ba7 --- /dev/null +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enab= le.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +. ./kselftest_scmi_lib.sh + +supported_fw=3D"EMU-SCMI-VM:userland" +ksft_scmi_check_fw_version $supported_fw + +clock_enable_disable() { + rname=3D$1 + rdir=3D$2 + clk_op=3D$3 + + ksft_scmi_value_set $rdir/$clk_op Y + ksft_scmi_value_set $rdir/$clk_op N + ksft_log "Clock $rname: $clk_op - ON/OFF ... OK" +} + +resources=3D$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR) +ksft_log "Found Clock resources: $resources" + +for res in $resources;do + resd=3D"$TST_PROTO_DIR/$res" + name=3D"$(cat $resd/info/name)" + + clock_enable_disable $name $resd "enable" + if [ ksft_transport_is_atomic ]; then + clock_enable_disable $name $resd "enable_atomic_irqs_off" + clock_enable_disable $name $resd "enable_atomic_irqs_on" + fi +done + +ksft_pass "$0" diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clo= ck_rate_read.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x1= 4/clock_rate_read.sh new file mode 100755 index 000000000000..88c444fd317d --- /dev/null +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate= _read.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +. ./kselftest_scmi_lib.sh + +resources=3D$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR) +ksft_log "Found Clock resources: $resources" + +for res in $resources;do + resd=3D"$TST_PROTO_DIR/$res" + name=3D"$(cat $resd/info/name)" + val=3D0 + + ksft_scmi_value_get $resd/rate_get_set val + ksft_log "$name READ =3D> $val" +done + +ksft_pass "$0" diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clo= ck_rate_write.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x= 14/clock_rate_write.sh new file mode 100755 index 000000000000..346084ec3812 --- /dev/null +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate= _write.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +. ./kselftest_scmi_lib.sh + +supported_fw=3D"EMU-SCMI-VM:userland" +ksft_scmi_check_fw_version $supported_fw + +resources=3D$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR) +ksft_log "Found Clock resources: $resources" + +for res in $resources;do + resd=3D"$TST_PROTO_DIR/$res" + name=3D"$(cat $resd/info/name)" + val=3D0 + oldval=3D0 + setval=3D0 + + ksft_scmi_value_get $resd/rate_get_set oldval + setval=3D$((oldval + 666)) + + ksft_scmi_value_set $resd/rate_get_set $setval + + ksft_scmi_value_get $resd/rate_get_set val + [ "x$val" !=3D "x$setval" ] && ksft_fail "Set:$setval readback:$val" + ksft_log "$name OK -> read:$oldval set:$setval readback:$val" +done + +ksft_pass "$0" diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sen= sor_reading.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15= /sensor_reading.sh new file mode 100755 index 000000000000..b0f5f6361379 --- /dev/null +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_rea= ding.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +. ./kselftest_scmi_lib.sh + +resources=3D$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR) +ksft_log "Found Sensor resources: $resources" + +for res in $resources;do + resd=3D"$TST_PROTO_DIR/$res" + name=3D"$(cat $resd/info/name)" + val=3D0 + + ksft_scmi_value_get $resd/reading_get val + ksft_log "$name READ =3D> $val" +done + +ksft_pass $0 --=20 2.17.1 From nobody Tue Jun 23 19:25:08 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EC375C433EF for ; Sun, 27 Feb 2022 20:57:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231910AbiB0U6J (ORCPT ); Sun, 27 Feb 2022 15:58:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59622 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231958AbiB0U5c (ORCPT ); Sun, 27 Feb 2022 15:57:32 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 43A586E4F2 for ; Sun, 27 Feb 2022 12:56:48 -0800 (PST) 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 226C41063; Sun, 27 Feb 2022 12:56:48 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BB1263F66F; Sun, 27 Feb 2022 12:56:46 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: sudeep.holla@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, souvik.chakravarty@arm.com, peter.hilber@opensynergy.com, cristian.marussi@arm.com Subject: [RFC PATCH 16/16] [DEBUG]: firmware: arm_scmi: Add Kconfig to allow SCMI Testing driver coexistence Date: Sun, 27 Feb 2022 20:56:08 +0000 Message-Id: <20220227205608.30812-17-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220227205608.30812-1-cristian.marussi@arm.com> References: <20220227205608.30812-1-cristian.marussi@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" firmware: arm_scmi: Add Kconfig to allow SCMI Testing driver coexistence Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/Kconfig | 6 ++++++ drivers/firmware/arm_scmi/driver.c | 15 ++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/= Kconfig index a3726074c89e..c3fc608d5373 100644 --- a/drivers/firmware/arm_scmi/Kconfig +++ b/drivers/firmware/arm_scmi/Kconfig @@ -160,4 +160,10 @@ config ARM_SCMI_TEST_DRIVER This driver can also be built as a module. If so, the module will be called scmi_test_driver. =20 +config ARM_SCMI_TEST_DRIVER_COEXISTENCE + bool "Allow Coexistence of SCMI standard drivers and test driver" + depends on ARM_SCMI_TEST_DRIVER + help + This enables coexistence for concurrent SCMI drievrs and testing driver. + endmenu diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi= /driver.c index 8c4706b24368..ff692c458a0b 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1782,14 +1782,15 @@ static int scmi_protocol_device_request(const struc= t scmi_device_id *id_table) pr_debug("Requesting SCMI device (%s) for protocol %x\n", id_table->name, id_table->protocol_id); =20 -#if IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER) - /* Reject non-testing SCMI drivers */ - if (strncmp(id_table->name, "__scmi_test", strlen("__scmi_test"))) { - pr_warn("SCMI Test driver loaded. Rejecting '%s'/0x%X\n", - id_table->name, id_table->protocol_id); - return -EINVAL; + if (IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER) && + !IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER_COEXISTENCE)) { + /* Reject non-testing SCMI drivers */ + if (strncmp(id_table->name, "__scmi_test", strlen("__scmi_test"))) { + pr_warn("SCMI Test driver loaded. Rejecting driver: '%s'/0x%X\n", + id_table->name, id_table->protocol_id); + return -EBUSY; + } } -#endif =20 /* * Search for the matching protocol rdev list and then search --=20 2.17.1