mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
firmware: arm_scmi: virtio: Rework transport probe sequence
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 <cristian.marussi@arm.com> Link: https://patch.msgid.link/20260510160527.3537474-4-cristian.marussi@arm.com Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
This commit is contained in:
parent
ab6eb28a47
commit
c08051901a
|
|
@ -4,7 +4,7 @@
|
|||
* (SCMI).
|
||||
*
|
||||
* Copyright (C) 2020-2022 OpenSynergy.
|
||||
* Copyright (C) 2021-2024 ARM Ltd.
|
||||
* Copyright (C) 2021-2026 ARM Ltd.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -116,6 +116,8 @@ static struct scmi_transport_core_operations *core;
|
|||
/* Only one SCMI VirtIO device can possibly exist */
|
||||
static struct virtio_device *scmi_vdev;
|
||||
|
||||
static DEFINE_SCMI_TRANSPORT_SUPPLIER(scmi_virtio_supplier);
|
||||
|
||||
static void scmi_vio_channel_ready(struct scmi_vio_channel *vioch,
|
||||
struct scmi_chan_info *cinfo)
|
||||
{
|
||||
|
|
@ -394,6 +396,10 @@ static bool virtio_chan_available(struct device_node *of_node, int idx)
|
|||
return false;
|
||||
}
|
||||
|
||||
dev_dbg(&scmi_vdev->dev, "%s Channel %sAVAILABLE on SCMI Virtio device.\n",
|
||||
idx == VIRTIO_SCMI_VQ_TX ? "TX" : "RX",
|
||||
(vioch && !vioch->cinfo) ? "" : "NOT ");
|
||||
|
||||
return vioch && !vioch->cinfo;
|
||||
}
|
||||
|
||||
|
|
@ -410,7 +416,7 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
|||
int i;
|
||||
|
||||
if (!scmi_vdev)
|
||||
return -EPROBE_DEFER;
|
||||
return -EINVAL;
|
||||
|
||||
vioch = &((struct scmi_vio_channel *)scmi_vdev->priv)[index];
|
||||
|
||||
|
|
@ -460,6 +466,9 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
|||
|
||||
scmi_vio_channel_ready(vioch, cinfo);
|
||||
|
||||
dev_dbg(&scmi_vdev->dev, "%s Channel SETUP on SCMI Virtio device.\n",
|
||||
tx ? "TX" : "RX");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -801,7 +810,7 @@ static struct scmi_desc scmi_virtio_desc = {
|
|||
};
|
||||
|
||||
static const struct of_device_id scmi_of_match[] = {
|
||||
{ .compatible = "arm,scmi-virtio" },
|
||||
{ .compatible = "arm,scmi-virtio", .data = &scmi_virtio_supplier.th},
|
||||
{ /* Sentinel */ },
|
||||
};
|
||||
|
||||
|
|
@ -864,33 +873,33 @@ static int scmi_vio_probe(struct virtio_device *vdev)
|
|||
sz = MSG_TOKEN_MAX;
|
||||
}
|
||||
channels[i].max_msg = sz;
|
||||
dev_dbg(dev, "VQ%d initialized with max_msg: %d\n", i, sz);
|
||||
}
|
||||
|
||||
vdev->priv = channels;
|
||||
|
||||
/* Ensure initialized scmi_vdev is visible */
|
||||
smp_store_mb(scmi_vdev, vdev);
|
||||
|
||||
/* Set device ready */
|
||||
virtio_device_ready(vdev);
|
||||
|
||||
ret = platform_driver_register(&scmi_virtio_driver);
|
||||
ret = scmi_transport_supplier_put(&scmi_virtio_supplier.th, &vdev->dev);
|
||||
if (ret) {
|
||||
virtio_reset_device(vdev);
|
||||
vdev->priv = 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");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 +909,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_transport_supplier_put(&scmi_virtio_supplier.th, &vdev->dev);
|
||||
}
|
||||
|
||||
static int scmi_vio_validate(struct virtio_device *vdev)
|
||||
|
|
@ -936,7 +947,30 @@ static struct virtio_driver virtio_scmi_driver = {
|
|||
.validate = scmi_vio_validate,
|
||||
};
|
||||
|
||||
module_virtio_driver(virtio_scmi_driver);
|
||||
static int __init scmi_transport_virtio_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = register_virtio_driver(&virtio_scmi_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = 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);
|
||||
|
||||
MODULE_AUTHOR("Igor Skalkin <igor.skalkin@opensynergy.com>");
|
||||
MODULE_AUTHOR("Peter Hilber <peter.hilber@opensynergy.com>");
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user