summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCristian Marussi <cristian.marussi@arm.com>2021-09-16 13:33:36 +0300
committerSudeep Holla <sudeep.holla@arm.com>2021-10-06 13:12:45 +0300
commitbf1acf809d5694a942e113dfca6ef076d3904bb4 (patch)
treea1fd86d6981a6b301a6a4cdb2db4877df9a49bb3
parenta14a14595dcade4bf31e50909a6958ed2566c058 (diff)
downloadlinux-bf1acf809d5694a942e113dfca6ef076d3904bb4.tar.xz
firmware: arm_scmi: Add proper barriers to scmi virtio device
Only one single SCMI Virtio device is currently supported by this driver and it is referenced using a static global variable which is initialized once for all during probing and nullified at virtio device removal. Add proper SMP barriers to protect accesses to such device reference to ensure that the initialzation state of such device is correctly observed by all PEs at any time. Return -EBUSY, instead of -EINVAL, and a descriptive error message if more than one SCMI Virtio device is ever found and probed. Link: https://lore.kernel.org/r/20210916103336.7243-3-cristian.marussi@arm.com Cc: "Michael S. Tsirkin" <mst@redhat.com> Cc: Sudeep Holla <sudeep.holla@arm.com> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
-rw-r--r--drivers/firmware/arm_scmi/virtio.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/firmware/arm_scmi/virtio.c b/drivers/firmware/arm_scmi/virtio.c
index f3a1ef9bb2a6..11e8efb71375 100644
--- a/drivers/firmware/arm_scmi/virtio.c
+++ b/drivers/firmware/arm_scmi/virtio.c
@@ -390,8 +390,11 @@ static int scmi_vio_probe(struct virtio_device *vdev)
struct virtqueue *vqs[VIRTIO_SCMI_VQ_MAX_CNT];
/* Only one SCMI VirtiO device allowed */
- if (scmi_vdev)
- return -EINVAL;
+ if (scmi_vdev) {
+ dev_err(dev,
+ "One SCMI Virtio device was already initialized: only one allowed.\n");
+ return -EBUSY;
+ }
have_vq_rx = scmi_vio_have_vq_rx(vdev);
vq_cnt = have_vq_rx ? VIRTIO_SCMI_VQ_MAX_CNT : 1;
@@ -434,7 +437,8 @@ static int scmi_vio_probe(struct virtio_device *vdev)
}
vdev->priv = channels;
- scmi_vdev = vdev;
+ /* Ensure initialized scmi_vdev is visible */
+ smp_store_mb(scmi_vdev, vdev);
return 0;
}
@@ -450,7 +454,8 @@ static void scmi_vio_remove(struct virtio_device *vdev)
*/
vdev->config->reset(vdev);
vdev->config->del_vqs(vdev);
- scmi_vdev = NULL;
+ /* Ensure scmi_vdev is visible as NULL */
+ smp_store_mb(scmi_vdev, NULL);
}
static int scmi_vio_validate(struct virtio_device *vdev)