From nobody Sun Jun 14 01:38:45 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9E6683E3DBF; Mon, 4 May 2026 16:52:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777913544; cv=none; b=iQQ3aamhCbJTUwR7g/5UTgUfvZbiRDIwiZt9b52FLfz9ZHuA1wFt7/KOf9NezOgHg6bL7j326rLqxHsN3Nm0TbkjWO1UaMKF7kaH6NnqYVb4vWdoITF0eHBqqOy8HhieoIb98PTp8MZVww5i0rJAS5GyErHLsHFtp8v+qhS5E/s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777913544; c=relaxed/simple; bh=OsQUNk3wxQb0nDBmW8OLr73j5WEYyxdcA19bMyj2+dA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UpaJ2SGUR8h7Nt+1mL0Qlyq7zWj19W6DVc61cbxDbf8ZBEm00rJwD21REYCj1xrf4V7sU6DYt6C+fQYaY4DZkNUB/MznQmDZzMJdR389pTTHIxZY94XBcE8MDboZVcu+UoBu1vbsLNxQCtlxNy9qa4RemQAXlJw0kNLvERruQH4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=KeZsY3t0; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="KeZsY3t0" 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 A3BB02573; Mon, 4 May 2026 09:52:14 -0700 (PDT) Received: from pluto.fritz.box (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id B357A3F763; Mon, 4 May 2026 09:52:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1777913540; bh=OsQUNk3wxQb0nDBmW8OLr73j5WEYyxdcA19bMyj2+dA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KeZsY3t0Fek5vretZaMIXranQuza6O7axZROOA1K02YHwalK0o9xZ43eUfxuVLTUl +mU74Un3kbq9w+OnJ84o73IKnVFzXUMnMXHrnSPAeG2gfO9sH73zSGPn01IeMTvQQk +bbe7td6Smg5NbUvL7ri/heoiU8DWWVGyRxfERLw= From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org Cc: sudeep.holla@kernel.org, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, gatien.chevallier@foss.st.com, u.kleine-koenig@baylibre.com, dakr@kernel.org, Cristian Marussi Subject: [PATCH v1 1/3] firmware: arm_scmi: Add transport instance handles Date: Mon, 4 May 2026 17:52:02 +0100 Message-ID: <20260504165204.639499-2-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260504165204.639499-1-cristian.marussi@arm.com> References: <20260504165204.639499-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" SCMI transport drivers are initialized first and then the control is passed to the SCMI core stack: some of these transports are dependent also on some external subsytem which will have to be initialized upfront, before the transport driver itself can be deemed operational. Transport drivers like virtio or optee need a way to defer the core SCMI probing till they are fully initialized and operational and also a way to pass back the device reference to be used as a supplier while building the devlink relations. SCMI transport drivers can be probed multiple times when used in a multiple instance configuration but the capability to carry-on with multiple probes depends on the support provided by the underlying transport driver. This change will also allow for the removal of the frowned-upon trick of registering a platform driver only after the end of the transport drivers porbe to avoid explicit probe deferrals. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/common.h | 59 +++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi= /common.h index 7c9617d080a0..8bb0dd1fe702 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -462,6 +463,28 @@ struct scmi_transport_core_operations { const struct scmi_message_operations *msg; }; =20 +/** + * struct scmi_transport_handle - Transport instance handle + * @supplier_get: A helper to retrieve the device descriptor, identifying = the + * transport driver serving this SCMI instance, which will be + * used as a supplier for the core SCMI driver: returning an + * error here causes the probe sequence to be interrupted and + * return that same error code, so that each transport can decide + * which policy to implement by choosing an appropriate error. + * @supplier_put: A helper to signal that the specified transport supplier= is + * no more being used and it is made available again. + * + * Note that these helpers are needed and provided only by those transports + * whose initialization relies on some other subsystem and whose relations= to + * the core SCMI driver is not tracked by firmware descriptions. + */ +struct scmi_transport_handle { + struct device __must_check *(*supplier_get) + (const struct scmi_transport_handle *th); + void (*supplier_put)(const struct scmi_transport_handle *th, + struct device *dev); +}; + /** * struct scmi_transport - A structure representing a configured transport * @@ -480,25 +503,47 @@ struct scmi_transport { #define DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, __match, __core= _ops)\ static void __tag##_dev_free(void *data) \ { \ + const struct scmi_transport_handle *th; \ struct platform_device *spdev =3D data; \ + struct device *dev =3D &spdev->dev; \ + \ + th =3D device_get_match_data(dev); \ + if (th) { \ + struct scmi_transport *strans; \ + \ + strans =3D dev_get_platdata(dev); \ + if (strans) \ + th->supplier_put(th, strans->supplier); \ + } \ \ platform_device_unregister(spdev); \ } \ \ static int __tag##_probe(struct platform_device *pdev) \ { \ - struct device *dev =3D &pdev->dev; \ - struct platform_device *spdev; \ + struct device *dev =3D &pdev->dev, *supplier; \ + const struct scmi_transport_handle *th; \ struct scmi_transport strans; \ + struct platform_device *spdev; \ int ret; \ \ + supplier =3D dev; \ + th =3D device_get_match_data(dev); \ + if (th) { \ + supplier =3D th->supplier_get(th); \ + if (IS_ERR(supplier)) \ + return PTR_ERR(supplier); \ + } \ + \ spdev =3D platform_device_alloc("arm-scmi", PLATFORM_DEVID_AUTO); \ - if (!spdev) \ - return -ENOMEM; \ + if (!spdev) { \ + ret =3D -ENOMEM; \ + goto err_mem; \ + } \ \ device_set_of_node_from_dev(&spdev->dev, dev); \ \ - strans.supplier =3D dev; \ + strans.supplier =3D supplier; \ memcpy(&strans.desc, &(__desc), sizeof(strans.desc)); \ strans.core_ops =3D &(__core_ops); \ \ @@ -515,6 +560,10 @@ static int __tag##_probe(struct platform_device *pdev)= \ \ err: \ platform_device_put(spdev); \ +err_mem: \ + if (th) \ + th->supplier_put(th, supplier); \ + \ return ret; \ } \ \ --=20 2.53.0 From nobody Sun Jun 14 01:38:45 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 253713E3C5D; Mon, 4 May 2026 16:52:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777913545; cv=none; b=jqZ0n9/6VJ7q8K9ePDkaf40nZWzymI2K5ySiu+BJ975dC7zEXW8P9W7R20ZA3q2X81KuJIqM3gLrhDluAAmglzJ/gCrAOe+/nI+MdWehmnr/tVcWu/0foymWsEQVlKkX1nsaDSheMTBmiraQi50t+KT3DUDuuo7QVpIZN4IXCNU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777913545; c=relaxed/simple; bh=fNj4ckZbgvI8AyVn1FXEnd6VYSCu3WCPkOhkPWudMAs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KAoJdCgiK0Nm3cCjf3U98NKI3NHBoew1hdHpRsMkTCx6/fZIpCB1pkzVC3xEH4n3z9h2Yhufn7fFXgH/ufpUenZ5uRQHy+hIRcoyswj2u95c+l5GFFdDLQlHi89iJ/RpRbEe9NDlEPoOlzk02EEXl7es8FaGywAO69PRyz42Hyk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=JHSLk09o; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="JHSLk09o" 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 297EB25E2; Mon, 4 May 2026 09:52:17 -0700 (PDT) Received: from pluto.fritz.box (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 5E9FE3F763; Mon, 4 May 2026 09:52:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1777913542; bh=fNj4ckZbgvI8AyVn1FXEnd6VYSCu3WCPkOhkPWudMAs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JHSLk09oshm55IFWHj7GAerZcXmxKUJ/5lldZIEtinybxhlnVpFHO9gXv8ihwL5gP 51Kc4yBiAjpK3Ldn81oZRauuMmGpxWpdLeLZWz1IqyRNWdwPniMb1y90mriCCCq1VS UAkSX5hfal9LxL6c5xhJ34Q1kv8Z6OadJARGhzoo= From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org Cc: sudeep.holla@kernel.org, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, gatien.chevallier@foss.st.com, u.kleine-koenig@baylibre.com, dakr@kernel.org, Cristian Marussi Subject: [PATCH v1 2/3] firmware: arm_scmi: virtio: Rework transport probe sequence Date: Mon, 4 May 2026 17:52:03 +0100 Message-ID: <20260504165204.639499-3-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260504165204.639499-1-cristian.marussi@arm.com> References: <20260504165204.639499-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use the new per-instance transport handles helpers to synchronize and optionally defer the core SCMI driver probe up until the transport driver has completely been initialized and it is fully operational as a supplier. Introduce proper module init/exit routines while removing the ugly trick of registering a driver from within the probe sequence of another one, just to avoid to have to deal with probe deferrals. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/transports/virtio.c | 137 +++++++++++++++--- 1 file changed, 120 insertions(+), 17 deletions(-) diff --git a/drivers/firmware/arm_scmi/transports/virtio.c b/drivers/firmwa= re/arm_scmi/transports/virtio.c index 326c4a93e44b..7ff9c31c3a8c 100644 --- a/drivers/firmware/arm_scmi/transports/virtio.c +++ b/drivers/firmware/arm_scmi/transports/virtio.c @@ -4,7 +4,7 @@ * (SCMI). * * Copyright (C) 2020-2022 OpenSynergy. - * Copyright (C) 2021-2024 ARM Ltd. + * Copyright (C) 2021-2026 ARM Ltd. */ =20 /** @@ -17,6 +17,7 @@ * virtqueue. Access to each virtqueue is protected by spinlocks. */ =20 +#include #include #include #include @@ -116,6 +117,79 @@ static struct scmi_transport_core_operations *core; /* Only one SCMI VirtIO device can possibly exist */ static struct virtio_device *scmi_vdev; =20 +/** + * struct scmi_virtio_suppliers - Transport descriptor + * @mtx: A mutex to protect @available + * @available: A reference to an initialized transport device ready to use + * which will cycle through the following 3 states: + * 1. PTR_ERR(-EPROBE_DEFER) at start before transport is ready + * 2. when transport is initialized, ready for use, + * but still unused + * 3. PTR_ERR(-EBUSY) when transport supplier device is in use + * @th: An embedded transport handle object that embeds the helpers + * implementing the above mentioned logic + * + * Note that this transport driver enforces single instance probing. + */ +struct scmi_virtio_suppliers { + /* Protect @available */ + struct mutex mtx; + struct device *available; + const struct scmi_transport_handle th; +}; + +#define to_vsup(t) container_of(t, struct scmi_virtio_suppliers, th) + +static int scmi_virtio_supplier_init(const struct scmi_transport_handle *t= h, + struct device *dev) +{ + struct scmi_virtio_suppliers *vsup =3D to_vsup(th); + + guard(mutex)(&vsup->mtx); + /* Was any transport already registered ? */ + if (!IS_ERR(vsup->available)) + return -EBUSY; + + vsup->available =3D dev; + + return 0; +} + +static struct device * +scmi_virtio_supplier_get(const struct scmi_transport_handle *th) +{ + struct scmi_virtio_suppliers *vsup =3D to_vsup(th); + struct device *supplier; + + guard(mutex)(&vsup->mtx); + supplier =3D vsup->available; + if (!IS_ERR(supplier)) + vsup->available =3D ERR_PTR(-EBUSY); + + return supplier; +} + +static void scmi_virtio_supplier_put(const struct scmi_transport_handle *t= h, + struct device *supplier) +{ + struct scmi_virtio_suppliers *vsup =3D to_vsup(th); + + guard(mutex)(&vsup->mtx); + vsup->available =3D supplier; +} + +static void scmi_virtio_supplier_cleanup(const struct scmi_transport_handl= e *th) +{ + scmi_virtio_supplier_put(th, ERR_PTR(-EPROBE_DEFER)); +} + +static struct scmi_virtio_suppliers scmi_transport_suppliers =3D { + .mtx =3D __MUTEX_INITIALIZER(mutexname), + .available =3D INIT_ERR_PTR(-EPROBE_DEFER), + .th.supplier_get =3D scmi_virtio_supplier_get, + .th.supplier_put =3D scmi_virtio_supplier_put, +}; + static void scmi_vio_channel_ready(struct scmi_vio_channel *vioch, struct scmi_chan_info *cinfo) { @@ -377,7 +451,7 @@ static bool virtio_chan_available(struct device_node *o= f_node, int idx) { struct scmi_vio_channel *channels, *vioch =3D NULL; =20 - if (WARN_ON_ONCE(!scmi_vdev)) + if (!scmi_vdev) return false; =20 channels =3D (struct scmi_vio_channel *)scmi_vdev->priv; @@ -394,6 +468,10 @@ static bool virtio_chan_available(struct device_node *= of_node, int idx) return false; } =20 + dev_dbg(&scmi_vdev->dev, "%s Channel %sAVAILABLE on SCMI Virtio device.\n= ", + idx =3D=3D VIRTIO_SCMI_VQ_TX ? "TX" : "RX", + (vioch && !vioch->cinfo) ? "" : "NOT "); + return vioch && !vioch->cinfo; } =20 @@ -410,7 +488,7 @@ static int virtio_chan_setup(struct scmi_chan_info *cin= fo, struct device *dev, int i; =20 if (!scmi_vdev) - return -EPROBE_DEFER; + return -EINVAL; =20 vioch =3D &((struct scmi_vio_channel *)scmi_vdev->priv)[index]; =20 @@ -460,6 +538,9 @@ static int virtio_chan_setup(struct scmi_chan_info *cin= fo, struct device *dev, =20 scmi_vio_channel_ready(vioch, cinfo); =20 + dev_dbg(&scmi_vdev->dev, "%s Channel SETUP on SCMI Virtio device.\n", + tx ? "TX" : "RX"); + return 0; } =20 @@ -801,7 +882,7 @@ static struct scmi_desc scmi_virtio_desc =3D { }; =20 static const struct of_device_id scmi_of_match[] =3D { - { .compatible =3D "arm,scmi-virtio" }, + { .compatible =3D "arm,scmi-virtio", .data =3D &scmi_transport_suppliers.= th}, { /* Sentinel */ }, }; =20 @@ -864,33 +945,30 @@ static int scmi_vio_probe(struct virtio_device *vdev) sz =3D MSG_TOKEN_MAX; } channels[i].max_msg =3D sz; + dev_dbg(dev, "VQ%d initialized with max_msg: %d\n", i, sz); } =20 vdev->priv =3D channels; + ret =3D scmi_virtio_supplier_init(&scmi_transport_suppliers.th, + &vdev->dev); + if (ret) { + vdev->priv =3D NULL; + vdev->config->del_vqs(vdev); + return ret; + } =20 /* Ensure initialized scmi_vdev is visible */ smp_store_mb(scmi_vdev, vdev); - /* Set device ready */ virtio_device_ready(vdev); =20 - ret =3D platform_driver_register(&scmi_virtio_driver); - if (ret) { - vdev->priv =3D NULL; - vdev->config->del_vqs(vdev); - /* Ensure NULLified scmi_vdev is visible */ - smp_store_mb(scmi_vdev, NULL); - - return ret; - } + dev_dbg(dev, "Probed and initialized SCMI Virtio device.\n"); =20 return 0; } =20 static void scmi_vio_remove(struct virtio_device *vdev) { - platform_driver_unregister(&scmi_virtio_driver); - /* * Once we get here, virtio_chan_free() will have already been called by * the SCMI core for any existing channel and, as a consequence, all the @@ -900,8 +978,10 @@ static void scmi_vio_remove(struct virtio_device *vdev) */ virtio_reset_device(vdev); vdev->config->del_vqs(vdev); + /* Ensure scmi_vdev is visible as NULL */ smp_store_mb(scmi_vdev, NULL); + scmi_virtio_supplier_cleanup(&scmi_transport_suppliers.th); } =20 static int scmi_vio_validate(struct virtio_device *vdev) @@ -936,7 +1016,30 @@ static struct virtio_driver virtio_scmi_driver =3D { .validate =3D scmi_vio_validate, }; =20 -module_virtio_driver(virtio_scmi_driver); +static int __init scmi_transport_virtio_init(void) +{ + int ret; + + ret =3D register_virtio_driver(&virtio_scmi_driver); + if (ret) + return ret; + + ret =3D platform_driver_register(&scmi_virtio_driver); + if (ret) { + unregister_virtio_driver(&virtio_scmi_driver); + return ret; + } + + return ret; +} +module_init(scmi_transport_virtio_init); + +static void __exit scmi_transport_virtio_exit(void) +{ + platform_driver_unregister(&scmi_virtio_driver); + unregister_virtio_driver(&virtio_scmi_driver); +} +module_exit(scmi_transport_virtio_exit); =20 MODULE_AUTHOR("Igor Skalkin "); MODULE_AUTHOR("Peter Hilber "); --=20 2.53.0 From nobody Sun Jun 14 01:38:45 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9C5073E2778; Mon, 4 May 2026 16:52:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777913550; cv=none; b=q1H0jSseBW8fyh8fPrOufkFbVRPmvfQp9laWspizCOzF+wzv7AQMhULHhzqeqskeKI114iQB5GWKGWbZ4mwjmUtyCx600RADL/vUGs77TBg7XPYMyWPulY5zK8oz+1NvMxY7VGAMsBwsPFLNCgDA7dTAW6j/OQbBrgz/tgvNtBM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777913550; c=relaxed/simple; bh=b1TfSp8pJ8Zlwfe8b5wy069zWBg5zqbxvqUZ5fMpVtk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=n4SKToMf9whft1EvbgFCeK2oWmAAYyFZMlYBMso987tRbrba1xAcNCoUT6FVfYVewLeZsBCk+gH108fajoLyGkQ/wDSWc29nxg6G9WZ6aDPZpuS19naXLZeHWLDBqN7yyBbR2R8P9GrnYDLtmLsWUDATwbaHum9Z5x+1kzoeG00= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=aE8ymg7J; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="aE8ymg7J" 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 9DB4E1691; Mon, 4 May 2026 09:52:19 -0700 (PDT) Received: from pluto.fritz.box (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D4C4E3F763; Mon, 4 May 2026 09:52:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1777913545; bh=b1TfSp8pJ8Zlwfe8b5wy069zWBg5zqbxvqUZ5fMpVtk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aE8ymg7J003652yTbbJuowZD3DnZam5JFGJ5kay2wilqWsmGHAkT7hqx9FRPx39/M QnpIn0TS2aAOMVkhdjPcgTplHHeNo9ZO2Nvdfk1GHCXLoueeO8yCW+ouA+3cU+y2Pu +3YqiA4oDaABhYisye+ZwNng56qwYA1QxYpHo4oA= From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org Cc: sudeep.holla@kernel.org, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, gatien.chevallier@foss.st.com, u.kleine-koenig@baylibre.com, dakr@kernel.org, Cristian Marussi Subject: [PATCH v1 3/3] firmware: arm_scmi: optee: Rework transport probe sequence Date: Mon, 4 May 2026 17:52:04 +0100 Message-ID: <20260504165204.639499-4-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260504165204.639499-1-cristian.marussi@arm.com> References: <20260504165204.639499-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use the new per-instance transport handles helpers to synchronize and optionally defer the core SCMI driver probe up until the transport driver has completely been initialized and it is fully operational as a supplier. Introduce proper module init/exit routines while removing the ugly trick of registering a driver from within the probe sequence of another one, just to avoid to have to deal with probe deferrals. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/transports/optee.c | 118 +++++++++++++++++-- 1 file changed, 105 insertions(+), 13 deletions(-) diff --git a/drivers/firmware/arm_scmi/transports/optee.c b/drivers/firmwar= e/arm_scmi/transports/optee.c index 07ae18d5279d..6950089fb659 100644 --- a/drivers/firmware/arm_scmi/transports/optee.c +++ b/drivers/firmware/arm_scmi/transports/optee.c @@ -154,6 +154,79 @@ static struct scmi_transport_core_operations *core; /* There can be only 1 SCMI service in OP-TEE we connect to */ static struct scmi_optee_agent *scmi_optee_private; =20 +/** + * struct scmi_optee_suppliers - Transport descriptor + * @mtx: A mutex to protect @available + * @available: A reference to an initialized transport device ready to use + * which will cycle through the following 3 states: + * 1. PTR_ERR(-EPROBE_DEFER) at start before transport is ready + * 2. when transport is initialized, ready for use, + * but still unused + * 3. PTR_ERR(-EBUSY) when transport supplier device is in use + * @th: An embedded transport handle object that embeds the helpers + * implementing the above mentioned logic + * + * Note that this transport driver enforces single instance probing. + */ +struct scmi_optee_suppliers { + /* Protect @available */ + struct mutex mtx; + struct device *available; + const struct scmi_transport_handle th; +}; + +#define to_osup(t) container_of(t, struct scmi_optee_suppliers, th) + +static int scmi_optee_supplier_init(const struct scmi_transport_handle *th, + struct device *dev) +{ + struct scmi_optee_suppliers *osup =3D to_osup(th); + + guard(mutex)(&osup->mtx); + /* Was any transport already registered ? */ + if (!IS_ERR(osup->available)) + return -EBUSY; + + osup->available =3D dev; + + return 0; +} + +static struct device * +scmi_optee_supplier_get(const struct scmi_transport_handle *th) +{ + struct scmi_optee_suppliers *osup =3D to_osup(th); + struct device *supplier; + + guard(mutex)(&osup->mtx); + supplier =3D osup->available; + if (!IS_ERR(supplier)) + osup->available =3D ERR_PTR(-EBUSY); + + return supplier; +} + +static void scmi_optee_supplier_put(const struct scmi_transport_handle *th, + struct device *supplier) +{ + struct scmi_optee_suppliers *osup =3D to_osup(th); + + guard(mutex)(&osup->mtx); + osup->available =3D supplier; +} + +static void scmi_optee_supplier_cleanup(const struct scmi_transport_handle= *th) +{ + scmi_optee_supplier_put(th, ERR_PTR(-EPROBE_DEFER)); +} + +static struct scmi_optee_suppliers scmi_transport_suppliers =3D { + .mtx =3D __MUTEX_INITIALIZER(mutexname), + .available =3D INIT_ERR_PTR(-EPROBE_DEFER), + .th.supplier_get =3D scmi_optee_supplier_get, + .th.supplier_put =3D scmi_optee_supplier_put, +}; + /* Open a session toward SCMI OP-TEE service with REE_KERNEL identity */ static int open_session(struct scmi_optee_agent *agent, u32 *tee_session) { @@ -522,7 +595,7 @@ static struct scmi_desc scmi_optee_desc =3D { }; =20 static const struct of_device_id scmi_of_match[] =3D { - { .compatible =3D "linaro,scmi-optee" }, + { .compatible =3D "linaro,scmi-optee", .data =3D &scmi_transport_supplier= s.th}, { /* Sentinel */ }, }; =20 @@ -561,15 +634,12 @@ static int scmi_optee_service_probe(struct tee_client= _device *scmi_pta) if (ret) goto err; =20 - /* Ensure agent resources are all visible before scmi_optee_private is */ - smp_mb(); - scmi_optee_private =3D agent; - - ret =3D platform_driver_register(&scmi_optee_driver); - if (ret) { - scmi_optee_private =3D NULL; + ret =3D scmi_optee_supplier_init(&scmi_transport_suppliers.th, agent->dev= ); + if (ret) goto err; - } + + /* Ensure initialized scmi_optee_private is visible */ + smp_store_mb(scmi_optee_private, agent); =20 return 0; =20 @@ -586,13 +656,12 @@ static void scmi_optee_service_remove(struct tee_clie= nt_device *scmi_pta) if (!scmi_optee_private) return; =20 - platform_driver_unregister(&scmi_optee_driver); - if (!list_empty(&scmi_optee_private->channel_list)) return; =20 - /* Ensure cleared reference is visible before resources are released */ + /* Ensure scmi_optee_private is visible as NULL */ smp_store_mb(scmi_optee_private, NULL); + scmi_optee_supplier_cleanup(&scmi_transport_suppliers.th); =20 tee_client_close_context(agent->tee_ctx); } @@ -616,7 +685,30 @@ static struct tee_client_driver scmi_optee_service_dri= ver =3D { }, }; =20 -module_tee_client_driver(scmi_optee_service_driver); +static int __init scmi_transport_optee_init(void) +{ + int ret; + + ret =3D tee_client_driver_register(&scmi_optee_service_driver); + if (ret) + return ret; + + ret =3D platform_driver_register(&scmi_optee_driver); + if (ret) { + tee_client_driver_unregister(&scmi_optee_service_driver); + return ret; + } + + return ret; +} +module_init(scmi_transport_optee_init); + +static void __exit scmi_transport_optee_exit(void) +{ + platform_driver_unregister(&scmi_optee_driver); + tee_client_driver_unregister(&scmi_optee_service_driver); +} +module_exit(scmi_transport_optee_exit); =20 MODULE_AUTHOR("Etienne Carriere "); MODULE_DESCRIPTION("SCMI OPTEE Transport driver"); --=20 2.53.0