Commit 72b6f7cd authored by Robin Murphy's avatar Robin Murphy Committed by Joerg Roedel
Browse files

iommu/virtio: Make instance lookup robust



Much like arm-smmu in commit 7d835134 ("iommu/arm-smmu: Make
instance lookup robust"), virtio-iommu appears to have the same issue
where iommu_device_register() makes the IOMMU instance visible to other
API callers (including itself) straight away, but internally the
instance isn't ready to recognise itself for viommu_probe_device() to
work correctly until after viommu_probe() has returned. This matters a
lot more now that bus_iommu_probe() has the DT/VIOT knowledge to probe
client devices the way that was always intended. Tweak the lookup and
initialisation in much the same way as for arm-smmu, to ensure that what
we register is functional and ready to go.

Cc: stable@vger.kernel.org
Fixes: bcb81ac6 ("iommu: Get DT/ACPI parsing into the proper probe path")
Signed-off-by: default avatarRobin Murphy <robin.murphy@arm.com>
Tested-by: default avatarEric Auger <eric.auger@redhat.com>
Link: https://lore.kernel.org/r/308911aaa1f5be32a3a709996c7bd6cf71d30f33.1755190036.git.robin.murphy@arm.com


Signed-off-by: default avatarJoerg Roedel <joerg.roedel@amd.com>
parent 685ca577
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -998,8 +998,7 @@ static void viommu_get_resv_regions(struct device *dev, struct list_head *head)
	iommu_dma_get_resv_regions(dev, head);
}

static const struct iommu_ops viommu_ops;
static struct virtio_driver virtio_iommu_drv;
static const struct bus_type *virtio_bus_type;

static int viommu_match_node(struct device *dev, const void *data)
{
@@ -1008,8 +1007,9 @@ static int viommu_match_node(struct device *dev, const void *data)

static struct viommu_dev *viommu_get_by_fwnode(struct fwnode_handle *fwnode)
{
	struct device *dev = driver_find_device(&virtio_iommu_drv.driver, NULL,
						fwnode, viommu_match_node);
	struct device *dev = bus_find_device(virtio_bus_type, NULL, fwnode,
					     viommu_match_node);

	put_device(dev);

	return dev ? dev_to_virtio(dev)->priv : NULL;
@@ -1160,6 +1160,9 @@ static int viommu_probe(struct virtio_device *vdev)
	if (!viommu)
		return -ENOMEM;

	/* Borrow this for easy lookups later */
	virtio_bus_type = dev->bus;

	spin_lock_init(&viommu->request_lock);
	ida_init(&viommu->domain_ids);
	viommu->dev = dev;
@@ -1229,10 +1232,10 @@ static int viommu_probe(struct virtio_device *vdev)
	if (ret)
		goto err_free_vqs;

	iommu_device_register(&viommu->iommu, &viommu_ops, parent_dev);

	vdev->priv = viommu;

	iommu_device_register(&viommu->iommu, &viommu_ops, parent_dev);

	dev_info(dev, "input address: %u bits\n",
		 order_base_2(viommu->geometry.aperture_end));
	dev_info(dev, "page mask: %#llx\n", viommu->pgsize_bitmap);