From nobody Mon Apr 6 22:11:44 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 2E1E83F7862; Tue, 17 Mar 2026 16:58:29 +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=1773766710; cv=none; b=hjk2mEkiZGEsf0XZ+91LBUzdaN0UzqDpfuamIHLZJF+4ANvjC4S6k2MiDLkj7kk0HvoebPHpdD1JtrSKyW9JwXQ7znsIlMHIXCWCBGpepIRtTkzTudsOghxC5mZtH0oECAXpE6UpBbANpF9my9abunN35mSCAgXA8msdDbOkJEc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773766710; c=relaxed/simple; bh=FZjJT8CJ9qsobj/YpSGWK5dtL22WQRznH4sEjarDS7c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TT7KQwZKDyZ3pAxlBdgZS+Oo/Ms2FqOx1HE0VBa6z3o+I0eFZTWpgfBZKWz/LRqdIMyC5bJXroxB/Gj1itGvhfZku1YfRgIJWKq4v5g9GGiqdhFpqII7Hy5ONCh7fmfAZ3feZmpyPob1f5U/r1vBJwHvDNX7sdkxRJVW1OjPhmk= 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; 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 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 BB00F16F2; Tue, 17 Mar 2026 09:58:22 -0700 (PDT) Received: from pluto.guest.local (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id F39633F7BD; Tue, 17 Mar 2026 09:58:25 -0700 (PDT) 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, dan.carpenter@linaro.org, gatien.chevallier@foss.st.com, Cristian Marussi Subject: [RFC PATCH 1/4] firmware: arm_scmi: Add transport instance handle Date: Tue, 17 Mar 2026 16:58:08 +0000 Message-ID: <20260317165811.3352752-2-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260317165811.3352752-1-cristian.marussi@arm.com> References: <20260317165811.3352752-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: such driver can be instantiated and probed multiple times and some of them are part also of some external subsytem which must be initialized upfront before the transport driver can be deemed to be ready for operation. Transport drivers like virtio or optee need a way to defer the core SCMI probing till they are operational and also a way to pass back and forth some sort of transport handle that can be used to identify the transport instance. Add an optional mutexed list shared between the transports and the core to use as such mechanism. Note that this change also allows the removal of the frown-upon trick of registering a platform driver at the end of the probe of the transport driver as an alternative way of probe deferral. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/common.h | 42 +++++++++++++++++++++++++++++- drivers/firmware/arm_scmi/driver.c | 11 ++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi= /common.h index 7c35c95fddba..0a971cf28a44 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include @@ -458,6 +460,31 @@ struct scmi_transport_core_operations { const struct scmi_message_operations *msg; }; =20 +/** + * struct scmi_transport_instance_queue - Transport instance queue descri= ptor + * @mtx: A mutex to protect the list + * @head: A list head to propagate per-instance and transport specific item + * descriptors to the SCMI core in an common way + */ +struct scmi_transport_instance_queue { + /* Protect the list */ + struct mutex mtx; + struct list_head head; +}; + +#define DEFINE_SCMI_TRANSPORT_INSTANCE_QUEUE(_instaq) \ +struct scmi_transport_instance_queue _instaq =3D { \ + __MUTEX_INITIALIZER(_instaq.mtx), \ + LIST_HEAD_INIT(_instaq.head), \ +} + +#define SCMI_TRANSPORT_INSTANCE_REGISTER(_item, _instaq) \ +do { \ + mutex_lock(&_instaq.mtx); \ + list_add_tail(&(_item), &_instaq.head); \ + mutex_unlock(&_instaq.mtx); \ +} while (0) + /** * struct scmi_transport - A structure representing a configured transport * @@ -466,11 +493,13 @@ struct scmi_transport_core_operations { * @desc: Transport descriptor * @core_ops: A pointer to a pointer used by the core SCMI stack to make t= he * core transport operations accessible to the transports. + * @hndl: An optional handle to the initialized transport instance. */ struct scmi_transport { struct device *supplier; struct scmi_desc desc; struct scmi_transport_core_operations **core_ops; + void *hndl; }; =20 #define DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, __match, __core= _ops)\ @@ -483,11 +512,22 @@ static void __tag##_dev_free(void *data) \ \ static int __tag##_probe(struct platform_device *pdev) \ { \ + struct scmi_transport_instance_queue *tq; \ + struct scmi_transport strans =3D {}; \ struct device *dev =3D &pdev->dev; \ struct platform_device *spdev; \ - struct scmi_transport strans; \ int ret; \ \ + tq =3D (void *)device_get_match_data(dev); \ + if (tq) { \ + scoped_guard(mutex, &tq->mtx) { \ + if (list_empty(&tq->head)) \ + return -EPROBE_DEFER; \ + strans.hndl =3D tq->head.next; \ + list_del_init(tq->head.next); \ + } \ + } \ + \ spdev =3D platform_device_alloc("arm-scmi", PLATFORM_DEVID_AUTO); \ if (!spdev) \ return -ENOMEM; \ diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi= /driver.c index 3e76a3204ba4..69361385be61 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -121,6 +121,7 @@ struct scmi_protocol_instance { * @id: A sequence number starting from zero identifying this instance * @dev: Device pointer * @desc: SoC description for this instance + * @thndl: Optional transport instance handle * @version: SCMI revision information containing protocol version, * implementation version and (sub-)vendor identification. * @handle: Instance of SCMI handle to send to clients @@ -151,6 +152,7 @@ struct scmi_info { int id; struct device *dev; const struct scmi_desc *desc; + void *thndl; struct scmi_revision_info version; struct scmi_handle handle; struct scmi_xfers_info tx_minfo; @@ -3115,7 +3117,8 @@ static int scmi_debugfs_raw_mode_setup(struct scmi_in= fo *info) return ret; } =20 -static const struct scmi_desc *scmi_transport_setup(struct device *dev) +static const struct scmi_desc * +scmi_transport_setup(struct device *dev, void **thndl) { struct scmi_transport *trans; int ret; @@ -3162,6 +3165,8 @@ static const struct scmi_desc *scmi_transport_setup(s= truct device *dev) "SCMI System wide atomic threshold set to %u us\n", trans->desc.atomic_threshold); =20 + *thndl =3D trans->hndl; + return &trans->desc; } =20 @@ -3180,6 +3185,7 @@ static void scmi_enable_matching_quirks(struct scmi_i= nfo *info) static int scmi_probe(struct platform_device *pdev) { int ret; + void *thndl; char *err_str =3D "probe failure\n"; struct scmi_handle *handle; const struct scmi_desc *desc; @@ -3188,7 +3194,7 @@ static int scmi_probe(struct platform_device *pdev) struct device *dev =3D &pdev->dev; struct device_node *child, *np =3D dev->of_node; =20 - desc =3D scmi_transport_setup(dev); + desc =3D scmi_transport_setup(dev, &thndl); if (!desc) { err_str =3D "transport invalid\n"; ret =3D -EINVAL; @@ -3205,6 +3211,7 @@ static int scmi_probe(struct platform_device *pdev) =20 info->dev =3D dev; info->desc =3D desc; + info->thndl =3D thndl; info->bus_nb.notifier_call =3D scmi_bus_notifier; info->dev_req_nb.notifier_call =3D scmi_device_request_notifier; INIT_LIST_HEAD(&info->node); --=20 2.53.0 From nobody Mon Apr 6 22:11:44 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7AD0B3F8E04; Tue, 17 Mar 2026 16:58:32 +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=1773766714; cv=none; b=RsEJhuSvQHlToekBiIFZP7ABs7M9zpBjzve9meB0dP23zaAmSucp/B21/yvNMEZveH+FU+Je3vCYBzNh9a4lbzxAS7D8tRQ9aGgSVLL0ZWb+BUY8N67tsUMZ9Utgsvrpc0YFbPo7U9i1H9SUHoNG816MScU3GEe6FWvUPtZ7Frw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773766714; c=relaxed/simple; bh=1d8Msfkb3jXOoz8wXs1x/7DySkB/hmwZ+7h+9lIz2O0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ByH3AS4xyZ+JMYQ+7sgsIsHY5HZjk0pv7zTZx3KOTshqvpXCTui00s2JupBku81ZEpeOEC54uoX2Vfw8eqxps3HfFK92hHiczbdUC9gfnFIFeF5fQWLWUBDX3n6utnGPJeNfrY+UX0y7zZx5zCn4F3Vw0nznfEDb/W+0OP0+Dwc= 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; 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 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 B79D219F6; Tue, 17 Mar 2026 09:58:25 -0700 (PDT) Received: from pluto.guest.local (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3D3403F7BD; Tue, 17 Mar 2026 09:58:29 -0700 (PDT) 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, dan.carpenter@linaro.org, gatien.chevallier@foss.st.com, Cristian Marussi Subject: [RFC PATCH 2/4] firmware: arm_scmi: Propagate transport instance handle Date: Tue, 17 Mar 2026 16:58:09 +0000 Message-ID: <20260317165811.3352752-3-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260317165811.3352752-1-cristian.marussi@arm.com> References: <20260317165811.3352752-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" Propagate down from the SCMI core to the transport channel operations the per-instance handle received by the transport drivers upon the end of their probe. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/common.h | 4 ++-- drivers/firmware/arm_scmi/driver.c | 4 ++-- drivers/firmware/arm_scmi/transports/mailbox.c | 5 +++-- drivers/firmware/arm_scmi/transports/optee.c | 6 ++++-- drivers/firmware/arm_scmi/transports/smc.c | 4 ++-- drivers/firmware/arm_scmi/transports/virtio.c | 6 +++--- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi= /common.h index 0a971cf28a44..2e0116ff8522 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -205,9 +205,9 @@ struct scmi_chan_info { * @poll_done: Callback to poll transfer status */ struct scmi_transport_ops { - bool (*chan_available)(struct device_node *of_node, int idx); + bool (*chan_available)(struct device_node *of_node, int idx, void *hndl); int (*chan_setup)(struct scmi_chan_info *cinfo, struct device *dev, - bool tx); + bool tx, void *hndl); int (*chan_free)(int id, void *p, void *data); unsigned int (*get_max_msg)(struct scmi_chan_info *base_cinfo); int (*send_message)(struct scmi_chan_info *cinfo, diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi= /driver.c index 69361385be61..b6d46fc08795 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -2723,7 +2723,7 @@ static int scmi_chan_setup(struct scmi_info *info, st= ruct device_node *of_node, idx =3D tx ? 0 : 1; idr =3D tx ? &info->tx_idr : &info->rx_idr; =20 - if (!info->desc->ops->chan_available(of_node, idx)) { + if (!info->desc->ops->chan_available(of_node, idx, info->thndl)) { cinfo =3D idr_find(idr, SCMI_PROTOCOL_BASE); if (unlikely(!cinfo)) /* Possible only if platform has no Rx */ return -EINVAL; @@ -2753,7 +2753,7 @@ static int scmi_chan_setup(struct scmi_info *info, st= ruct device_node *of_node, =20 cinfo->id =3D prot_id; cinfo->dev =3D &tdev->dev; - ret =3D info->desc->ops->chan_setup(cinfo, info->dev, tx); + ret =3D info->desc->ops->chan_setup(cinfo, info->dev, tx, info->thndl); if (ret) { of_node_put(of_node); scmi_device_destroy(info->dev, prot_id, name); diff --git a/drivers/firmware/arm_scmi/transports/mailbox.c b/drivers/firmw= are/arm_scmi/transports/mailbox.c index ae0f67e6cc45..cf996724971d 100644 --- a/drivers/firmware/arm_scmi/transports/mailbox.c +++ b/drivers/firmware/arm_scmi/transports/mailbox.c @@ -77,7 +77,8 @@ static void rx_callback(struct mbox_client *cl, void *m) core->shmem->read_header(smbox->shmem), NULL); } =20 -static bool mailbox_chan_available(struct device_node *of_node, int idx) +static bool +mailbox_chan_available(struct device_node *of_node, int idx, void *hndl) { int num_mb; =20 @@ -180,7 +181,7 @@ static int mailbox_chan_validate(struct device *cdev, i= nt *a2p_rx_chan, } =20 static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device = *dev, - bool tx) + bool tx, void *hndl) { const char *desc =3D tx ? "Tx" : "Rx"; struct device *cdev =3D cinfo->dev; diff --git a/drivers/firmware/arm_scmi/transports/optee.c b/drivers/firmwar= e/arm_scmi/transports/optee.c index 07ae18d5279d..ab578152e046 100644 --- a/drivers/firmware/arm_scmi/transports/optee.c +++ b/drivers/firmware/arm_scmi/transports/optee.c @@ -312,7 +312,8 @@ static int invoke_process_msg_channel(struct scmi_optee= _channel *channel, size_t return 0; } =20 -static bool scmi_optee_chan_available(struct device_node *of_node, int idx) +static bool +scmi_optee_chan_available(struct device_node *of_node, int idx, void *hndl) { u32 channel_id; =20 @@ -367,7 +368,8 @@ static int setup_shmem(struct device *dev, struct scmi_= chan_info *cinfo, return setup_dynamic_shmem(dev, channel); } =20 -static int scmi_optee_chan_setup(struct scmi_chan_info *cinfo, struct devi= ce *dev, bool tx) +static int scmi_optee_chan_setup(struct scmi_chan_info *cinfo, struct devi= ce *dev, + bool tx, void *hndl) { struct scmi_optee_channel *channel; uint32_t channel_id; diff --git a/drivers/firmware/arm_scmi/transports/smc.c b/drivers/firmware/= arm_scmi/transports/smc.c index 21abb571e4f2..cb0d9a8f93ca 100644 --- a/drivers/firmware/arm_scmi/transports/smc.c +++ b/drivers/firmware/arm_scmi/transports/smc.c @@ -84,7 +84,7 @@ static irqreturn_t smc_msg_done_isr(int irq, void *data) return IRQ_HANDLED; } =20 -static bool smc_chan_available(struct device_node *of_node, int idx) +static bool smc_chan_available(struct device_node *of_node, int idx, void = *hndl) { struct device_node *np __free(device_node) =3D of_parse_phandle(of_node, "shmem", 0); @@ -130,7 +130,7 @@ static inline void smc_channel_lock_release(struct scmi= _smc *scmi_info) } =20 static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, - bool tx) + bool tx, void *hndl) { struct device *cdev =3D cinfo->dev; unsigned long cap_id =3D ULONG_MAX; diff --git a/drivers/firmware/arm_scmi/transports/virtio.c b/drivers/firmwa= re/arm_scmi/transports/virtio.c index 326c4a93e44b..6e1ce01507a6 100644 --- a/drivers/firmware/arm_scmi/transports/virtio.c +++ b/drivers/firmware/arm_scmi/transports/virtio.c @@ -373,7 +373,7 @@ static unsigned int virtio_get_max_msg(struct scmi_chan= _info *base_cinfo) return vioch->max_msg; } =20 -static bool virtio_chan_available(struct device_node *of_node, int idx) +static bool virtio_chan_available(struct device_node *of_node, int idx, vo= id *hndl) { struct scmi_vio_channel *channels, *vioch =3D NULL; =20 @@ -402,8 +402,8 @@ static void scmi_destroy_tx_workqueue(void *deferred_tx= _wq) destroy_workqueue(deferred_tx_wq); } =20 -static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *= dev, - bool tx) +static int +virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, bool t= x, void *hndl) { struct scmi_vio_channel *vioch; int index =3D tx ? VIRTIO_SCMI_VQ_TX : VIRTIO_SCMI_VQ_RX; --=20 2.53.0 From nobody Mon Apr 6 22:11:44 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 452D73F65F5; Tue, 17 Mar 2026 16:58:35 +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=1773766716; cv=none; b=By0ET4deBgPrARQozknWsfJeYADLxgLiXuoPsR0fykmHFm7hA2sTWGr1QZCfp6olkpoLn87xeIi9eubiTlEP4Ql/ywctNWKF7pudHsGXauZgKVtVx5K4ACQcRbrC1jtsfUk7m8VX3JYiL/i9BVTd6PNWZDy8sinCpSb+TZZkac4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773766716; c=relaxed/simple; bh=FJeN8+7oS17O2ePg8eSJn6wJtjw7rM5PT41uMilIbdM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SZ5R4gBTIEEht52p46S52K89VzdiecKR/QxWjUhqGlWMpRjNeBHz2HawTnH2ao/BHSMnT7NWTlibpKAUj0vufG/iw0JXLPCFTcKvf5DeIBOCdO0gMhmoceySSMz4oTp00L7jIFlzZxuKiy9PUJ0GwfrOgUNI1KsPnchAhN+0v3M= 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; 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 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 995CB1477; Tue, 17 Mar 2026 09:58:28 -0700 (PDT) Received: from pluto.guest.local (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 25C653F7BD; Tue, 17 Mar 2026 09:58:32 -0700 (PDT) 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, dan.carpenter@linaro.org, gatien.chevallier@foss.st.com, Cristian Marussi Subject: [RFC PATCH 3/4] firmware: arm_scmi: virtio: Rework transport probe sequence Date: Tue, 17 Mar 2026 16:58:10 +0000 Message-ID: <20260317165811.3352752-4-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260317165811.3352752-1-cristian.marussi@arm.com> References: <20260317165811.3352752-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 list to synchronize and optionally defer the core SCMI probe up until the transport driver has completely been initialized and is fully operational. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/transports/virtio.c | 93 ++++++++++++------- 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/drivers/firmware/arm_scmi/transports/virtio.c b/drivers/firmwa= re/arm_scmi/transports/virtio.c index 6e1ce01507a6..ee7247081be1 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 /** @@ -113,8 +113,12 @@ struct scmi_vio_msg { =20 static struct scmi_transport_core_operations *core; =20 -/* Only one SCMI VirtIO device can possibly exist */ -static struct virtio_device *scmi_vdev; +struct scmi_virtio_device { + struct virtio_device *vdev; + struct list_head node; +}; + +static DEFINE_SCMI_TRANSPORT_INSTANCE_QUEUE(scmi_available_vdevs); =20 static void scmi_vio_channel_ready(struct scmi_vio_channel *vioch, struct scmi_chan_info *cinfo) @@ -376,24 +380,28 @@ static unsigned int virtio_get_max_msg(struct scmi_ch= an_info *base_cinfo) static bool virtio_chan_available(struct device_node *of_node, int idx, vo= id *hndl) { struct scmi_vio_channel *channels, *vioch =3D NULL; + struct scmi_virtio_device *sdev; =20 - if (WARN_ON_ONCE(!scmi_vdev)) - return false; + sdev =3D list_entry(hndl, struct scmi_virtio_device, node); =20 - channels =3D (struct scmi_vio_channel *)scmi_vdev->priv; + channels =3D (struct scmi_vio_channel *)sdev->vdev->priv; =20 switch (idx) { case VIRTIO_SCMI_VQ_TX: vioch =3D &channels[VIRTIO_SCMI_VQ_TX]; break; case VIRTIO_SCMI_VQ_RX: - if (scmi_vio_have_vq_rx(scmi_vdev)) + if (scmi_vio_have_vq_rx(sdev->vdev)) vioch =3D &channels[VIRTIO_SCMI_VQ_RX]; break; default: return false; } =20 + dev_dbg(&sdev->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 @@ -405,21 +413,20 @@ static void scmi_destroy_tx_workqueue(void *deferred_= tx_wq) static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, bool t= x, void *hndl) { + struct scmi_virtio_device *sdev; struct scmi_vio_channel *vioch; int index =3D tx ? VIRTIO_SCMI_VQ_TX : VIRTIO_SCMI_VQ_RX; int i; =20 - if (!scmi_vdev) - return -EPROBE_DEFER; - - vioch =3D &((struct scmi_vio_channel *)scmi_vdev->priv)[index]; + sdev =3D list_entry(hndl, struct scmi_virtio_device, node); + vioch =3D &((struct scmi_vio_channel *)sdev->vdev->priv)[index]; =20 /* Setup a deferred worker for polling. */ if (tx && !vioch->deferred_tx_wq) { int ret; =20 vioch->deferred_tx_wq =3D - alloc_workqueue(dev_name(&scmi_vdev->dev), + alloc_workqueue(dev_name(&sdev->vdev->dev), WQ_UNBOUND | WQ_FREEZABLE | WQ_SYSFS, 0); if (!vioch->deferred_tx_wq) @@ -460,6 +467,9 @@ virtio_chan_setup(struct scmi_chan_info *cinfo, struct = device *dev, bool tx, voi =20 scmi_vio_channel_ready(vioch, cinfo); =20 + dev_dbg(&sdev->vdev->dev, "%s Channel SETUP on SCMI Virtio device.\n", + tx ? "TX" : "RX"); + return 0; } =20 @@ -801,7 +811,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_available_vdevs}, { /* Sentinel */ }, }; =20 @@ -812,22 +822,20 @@ static int scmi_vio_probe(struct virtio_device *vdev) { struct device *dev =3D &vdev->dev; struct scmi_vio_channel *channels; + struct scmi_virtio_device *sdev; bool have_vq_rx; int vq_cnt; int i; int ret; struct virtqueue *vqs[VIRTIO_SCMI_VQ_MAX_CNT]; =20 - /* Only one SCMI VirtiO device allowed */ - if (scmi_vdev) { - dev_err(dev, - "One SCMI Virtio device was already initialized: only one allowed.\n"); - return -EBUSY; - } - have_vq_rx =3D scmi_vio_have_vq_rx(vdev); vq_cnt =3D have_vq_rx ? VIRTIO_SCMI_VQ_MAX_CNT : 1; =20 + sdev =3D devm_kzalloc(dev, sizeof(*sdev), GFP_KERNEL); + if (!sdev) + return -ENOMEM; + channels =3D devm_kcalloc(dev, vq_cnt, sizeof(*channels), GFP_KERNEL); if (!channels) return -ENOMEM; @@ -864,33 +872,25 @@ static int scmi_vio_probe(struct virtio_device *vdev) sz =3D MSG_TOKEN_MAX; } channels[i].max_msg =3D sz; + dev_info(dev, "VQ%d initialized with max_msg: %d\n", i, sz); } =20 vdev->priv =3D channels; =20 - /* Ensure initialized scmi_vdev is visible */ - smp_store_mb(scmi_vdev, vdev); + /* Ensure initialized vdev is visible */ + smp_store_mb(sdev->vdev, vdev); + SCMI_TRANSPORT_INSTANCE_REGISTER(sdev->node, scmi_available_vdevs); =20 /* 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_info(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 +900,6 @@ 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); } =20 static int scmi_vio_validate(struct virtio_device *vdev) @@ -936,7 +934,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 Mon Apr 6 22:11:44 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 71CD33F99C6; Tue, 17 Mar 2026 16:58:38 +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=1773766720; cv=none; b=FPkP/hlLYV8K+NlKrWjUfAXLEQaR3+JACLVEJ93lkrznLp9bwZ5ObaPra8FvAc1LL3exi2D167cjnC6rLcLywUQme2FpaS7oxxLTmTg4HqnXahHu2YCJ2IfrcztBV/aTny1EUX+2/FPVq9HbsL/NlbBOyE6Y/HveIJI4JLqUNr8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773766720; c=relaxed/simple; bh=ywdl1D3jcs+t+Z6oKbOQIQ/t6256N7Fbicu3G8Pzsg8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CNoziEsz/UBJOZHmYMELjoaW4G6fYqLVhrFloEWoGnEoYwTVpaExTje00Oxttwb9Cv+znp/aSzDj2riNKW1vwkPH5EniX9vvHBRLFvYuT1qA1qbar79YSJuysmPEa0u9nD1EeFIIYqVej1Hk7rDheyymYpPNmsnVoyyxEpq1KJo= 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; 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 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 C34D21477; Tue, 17 Mar 2026 09:58:31 -0700 (PDT) Received: from pluto.guest.local (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 17A803F7BD; Tue, 17 Mar 2026 09:58:34 -0700 (PDT) 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, dan.carpenter@linaro.org, gatien.chevallier@foss.st.com, Cristian Marussi Subject: [RFC PATCH 4/4] firmware: arm_scmi: optee: Rework transport probe sequence Date: Tue, 17 Mar 2026 16:58:11 +0000 Message-ID: <20260317165811.3352752-5-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260317165811.3352752-1-cristian.marussi@arm.com> References: <20260317165811.3352752-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 list to synchronize and optionally defer the core SCMI probe up until the transport driver has completely been initialized and is fully operational. Add also a local xarray to keep track of the association between the tee_client_device and the per-instance agent for the purpose of resource cleanup. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/transports/optee.c | 137 +++++++++++-------- 1 file changed, 79 insertions(+), 58 deletions(-) diff --git a/drivers/firmware/arm_scmi/transports/optee.c b/drivers/firmwar= e/arm_scmi/transports/optee.c index ab578152e046..08f7b2b9b9d6 100644 --- a/drivers/firmware/arm_scmi/transports/optee.c +++ b/drivers/firmware/arm_scmi/transports/optee.c @@ -13,6 +13,7 @@ #include #include #include +#include #include =20 #include "../common.h" @@ -99,6 +100,26 @@ enum scmi_optee_pta_cmd { #define PTA_SCMI_CAPS_MASK (PTA_SCMI_CAPS_SMT_HEADER | \ PTA_SCMI_CAPS_MSG_HEADER) =20 +/** + * struct scmi_optee_agent - OP-TEE transport private data + * + * @dev: Device used for communication with TEE + * @tee_ctx: TEE context used for communication + * @caps: Supported channel capabilities + * @mu: Mutex for protection of @channel_list + * @channel_list: List of all created channels for the agent + * @node: Used to enqueue this agent + */ +struct scmi_optee_agent { + struct device *dev; + struct tee_context *tee_ctx; + u32 caps; + /* Protect channel_list*/ + struct mutex mu; + struct list_head channel_list; + struct list_head node; +}; + /** * struct scmi_optee_channel - Description of an OP-TEE SCMI channel * @@ -115,6 +136,7 @@ enum scmi_optee_pta_cmd { * @io_ops: Transport specific I/O operations * @tee_shm: TEE shared memory handle @req or NULL if using IOMEM shmem * @link: Reference in agent's channel list + * @agent: Reference to the agent owning this channel */ struct scmi_optee_channel { u32 channel_id; @@ -130,29 +152,13 @@ struct scmi_optee_channel { struct scmi_shmem_io_ops *io_ops; struct tee_shm *tee_shm; struct list_head link; -}; - -/** - * struct scmi_optee_agent - OP-TEE transport private data - * - * @dev: Device used for communication with TEE - * @tee_ctx: TEE context used for communication - * @caps: Supported channel capabilities - * @mu: Mutex for protection of @channel_list - * @channel_list: List of all created channels for the agent - */ -struct scmi_optee_agent { - struct device *dev; - struct tee_context *tee_ctx; - u32 caps; - struct mutex mu; - struct list_head channel_list; + struct scmi_optee_agent *agent; }; =20 static struct scmi_transport_core_operations *core; =20 -/* There can be only 1 SCMI service in OP-TEE we connect to */ -static struct scmi_optee_agent *scmi_optee_private; +static DEFINE_XARRAY(scmi_active_agents); +static DEFINE_SCMI_TRANSPORT_INSTANCE_QUEUE(scmi_available_agents); =20 /* Open a session toward SCMI OP-TEE service with REE_KERNEL identity */ static int open_session(struct scmi_optee_agent *agent, u32 *tee_session) @@ -222,7 +228,7 @@ static int get_capabilities(struct scmi_optee_agent *ag= ent) =20 static int get_channel(struct scmi_optee_channel *channel) { - struct device *dev =3D scmi_optee_private->dev; + struct device *dev =3D channel->agent->dev; struct tee_ioctl_invoke_arg arg =3D { }; struct tee_param param[1] =3D { }; unsigned int caps =3D 0; @@ -241,7 +247,7 @@ static int get_channel(struct scmi_optee_channel *chann= el) param[0].u.value.a =3D channel->channel_id; param[0].u.value.b =3D caps; =20 - ret =3D tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param); + ret =3D tee_client_invoke_func(channel->agent->tee_ctx, &arg, param); =20 if (ret || arg.ret) { dev_err(dev, "Can't get channel with caps %#x: %d / %#x\n", caps, ret, a= rg.ret); @@ -268,9 +274,9 @@ static int invoke_process_smt_channel(struct scmi_optee= _channel *channel) param[0].attr =3D TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; param[0].u.value.a =3D channel->channel_id; =20 - ret =3D tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param); + ret =3D tee_client_invoke_func(channel->agent->tee_ctx, &arg, param); if (ret < 0 || arg.ret) { - dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n", + dev_err(channel->agent->dev, "Can't invoke channel %u: %d / %#x\n", channel->channel_id, ret, arg.ret); return -EIO; } @@ -299,9 +305,9 @@ static int invoke_process_msg_channel(struct scmi_optee= _channel *channel, size_t param[2].u.memref.shm =3D channel->tee_shm; param[2].u.memref.size =3D SCMI_SHMEM_MAX_PAYLOAD_SIZE; =20 - ret =3D tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param); + ret =3D tee_client_invoke_func(channel->agent->tee_ctx, &arg, param); if (ret < 0 || arg.ret) { - dev_err(scmi_optee_private->dev, "Can't invoke channel %u: %d / %#x\n", + dev_err(channel->agent->dev, "Can't invoke channel %u: %d / %#x\n", channel->channel_id, ret, arg.ret); return -EIO; } @@ -334,7 +340,8 @@ static int setup_dynamic_shmem(struct device *dev, stru= ct scmi_optee_channel *ch const size_t msg_size =3D SCMI_SHMEM_MAX_PAYLOAD_SIZE; void *shbuf; =20 - channel->tee_shm =3D tee_shm_alloc_kernel_buf(scmi_optee_private->tee_ctx= , msg_size); + channel->tee_shm =3D tee_shm_alloc_kernel_buf(channel->agent->tee_ctx, + msg_size); if (IS_ERR(channel->tee_shm)) { dev_err(channel->cinfo->dev, "shmem allocation failed\n"); return -ENOMEM; @@ -390,17 +397,19 @@ static int scmi_optee_chan_setup(struct scmi_chan_inf= o *cinfo, struct device *de cinfo->transport_info =3D channel; channel->cinfo =3D cinfo; channel->channel_id =3D channel_id; + channel->agent =3D list_entry(hndl, struct scmi_optee_agent, node); mutex_init(&channel->mu); =20 ret =3D setup_shmem(dev, cinfo, channel); if (ret) return ret; =20 - ret =3D open_session(scmi_optee_private, &channel->tee_session); + ret =3D open_session(channel->agent, &channel->tee_session); if (ret) goto err_free_shm; =20 - ret =3D tee_client_system_session(scmi_optee_private->tee_ctx, channel->t= ee_session); + ret =3D tee_client_system_session(channel->agent->tee_ctx, + channel->tee_session); if (ret) dev_warn(dev, "Could not switch to system session, do best effort\n"); =20 @@ -411,14 +420,14 @@ static int scmi_optee_chan_setup(struct scmi_chan_inf= o *cinfo, struct device *de /* Enable polling */ cinfo->no_completion_irq =3D true; =20 - mutex_lock(&scmi_optee_private->mu); - list_add(&channel->link, &scmi_optee_private->channel_list); - mutex_unlock(&scmi_optee_private->mu); + mutex_lock(&channel->agent->mu); + list_add(&channel->link, &channel->agent->channel_list); + mutex_unlock(&channel->agent->mu); =20 return 0; =20 err_close_sess: - close_session(scmi_optee_private, channel->tee_session); + close_session(channel->agent, channel->tee_session); err_free_shm: if (channel->tee_shm) tee_shm_free(channel->tee_shm); @@ -438,11 +447,11 @@ static int scmi_optee_chan_free(int id, void *p, void= *data) if (!channel) return 0; =20 - mutex_lock(&scmi_optee_private->mu); + mutex_lock(&channel->agent->mu); list_del(&channel->link); - mutex_unlock(&scmi_optee_private->mu); + mutex_unlock(&channel->agent->mu); =20 - close_session(scmi_optee_private, channel->tee_session); + close_session(channel->agent, channel->tee_session); =20 if (channel->tee_shm) { tee_shm_free(channel->tee_shm); @@ -524,7 +533,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_available_agents}, { /* Sentinel */ }, }; =20 @@ -538,12 +547,6 @@ static int scmi_optee_service_probe(struct tee_client_= device *scmi_pta) struct tee_context *tee_ctx; int ret; =20 - /* Only one SCMI OP-TEE device allowed */ - if (scmi_optee_private) { - dev_err(dev, "An SCMI OP-TEE device was already initialized: only one al= lowed\n"); - return -EBUSY; - } - tee_ctx =3D tee_client_open_context(NULL, scmi_optee_ctx_match, NULL, NUL= L); if (IS_ERR(tee_ctx)) return -ENODEV; @@ -563,15 +566,14 @@ 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 */ + /* Ensure agent resources are visible */ smp_mb(); - scmi_optee_private =3D agent; - - ret =3D platform_driver_register(&scmi_optee_driver); - if (ret) { - scmi_optee_private =3D NULL; + ret =3D xa_insert(&scmi_active_agents, (unsigned long)scmi_pta, agent, + GFP_KERNEL); + if (ret) goto err; - } + + SCMI_TRANSPORT_INSTANCE_REGISTER(agent->node, scmi_available_agents); =20 return 0; =20 @@ -583,19 +585,15 @@ static int scmi_optee_service_probe(struct tee_client= _device *scmi_pta) =20 static void scmi_optee_service_remove(struct tee_client_device *scmi_pta) { - struct scmi_optee_agent *agent =3D scmi_optee_private; + struct scmi_optee_agent *agent; =20 - if (!scmi_optee_private) + agent =3D xa_erase(&scmi_active_agents, (unsigned long)scmi_pta); + if (!agent) return; =20 - platform_driver_unregister(&scmi_optee_driver); - - if (!list_empty(&scmi_optee_private->channel_list)) + if (!list_empty(&agent->channel_list)) return; =20 - /* Ensure cleared reference is visible before resources are released */ - smp_store_mb(scmi_optee_private, NULL); - tee_client_close_context(agent->tee_ctx); } =20 @@ -618,7 +616,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