Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fcc34cd
iommu: Resolve fwspec ops automatically
rmurphy-arm Jul 2, 2024
f0dcb96
ACPI: Retire acpi_iommu_fwspec_ops()
rmurphy-arm Jul 2, 2024
57ac26a
OF: Simplify of_iommu_configure()
rmurphy-arm Jul 2, 2024
9a9e122
iommu: Remove iommu_fwspec ops
rmurphy-arm Jul 2, 2024
8e6dee0
iommu: Unexport iommu_fwspec_free()
rmurphy-arm Feb 27, 2025
cd44695
iommu: Handle race with default domain setup
rmurphy-arm Feb 28, 2025
5a95d34
iommu: Resolve ops in iommu_init_device()
rmurphy-arm Feb 28, 2025
65c2c98
iommu: Keep dev->iommu state consistent
rmurphy-arm Feb 28, 2025
62f9ac8
iommu: Get DT/ACPI parsing into the proper probe path
rmurphy-arm Feb 28, 2025
3a9a427
iommu: Add iommu_paging_domain_alloc() interface
LuBaolu Jun 10, 2024
c83b3cb
iommufd: Use iommu_paging_domain_alloc()
LuBaolu Jun 10, 2024
555ae2e
vfio/type1: Use iommu_paging_domain_alloc()
LuBaolu Jun 10, 2024
2348206
vhost-vdpa: Use iommu_paging_domain_alloc()
LuBaolu Jun 10, 2024
e5cf575
drm/msm: Use iommu_paging_domain_alloc()
LuBaolu Jun 10, 2024
f938d3c
wifi: ath10k: Use iommu_paging_domain_alloc()
LuBaolu Jun 10, 2024
200c289
wifi: ath11k: Use iommu_paging_domain_alloc()
LuBaolu Jun 10, 2024
0d8ee51
drm/nouveau/tegra: Use iommu_paging_domain_alloc()
LuBaolu Sep 2, 2024
e5ab717
gpu: host1x: Use iommu_paging_domain_alloc()
LuBaolu Aug 12, 2024
ed6deff
media: nvidia: tegra: Use iommu_paging_domain_alloc()
LuBaolu Aug 12, 2024
cb1fed7
media: venus: firmware: Use iommu_paging_domain_alloc()
LuBaolu Aug 12, 2024
17fb814
remoteproc: Use iommu_paging_domain_alloc()
LuBaolu Aug 12, 2024
76030d6
soc: fsl: qbman: Use iommu_paging_domain_alloc()
LuBaolu Aug 12, 2024
b04b910
RDMA/usnic: Use iommu_paging_domain_alloc()
LuBaolu Jun 10, 2024
4a3d529
drm/rockchip: Use iommu_paging_domain_alloc()
LuBaolu Sep 2, 2024
90fa067
drm/tegra: Use iommu_paging_domain_alloc()
LuBaolu Sep 2, 2024
22ebd85
iommu: Remove iommu_present()
LuBaolu Oct 9, 2024
40283c7
iommu: Remove iommu_domain_alloc()
LuBaolu Oct 9, 2024
db91f2e
iommu: Don't warn prematurely about dodgy probes
rmurphy-arm Mar 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions drivers/acpi/arm64/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ void acpi_arch_dma_setup(struct device *dev)
else
end = (1ULL << 32) - 1;

if (dev->dma_range_map) {
dev_dbg(dev, "dma_range_map already set\n");
return;
}

ret = acpi_dma_get_range(dev, &map);
if (!ret && map) {
end = dma_range_map_max(map);
Expand Down
19 changes: 5 additions & 14 deletions drivers/acpi/arm64/iort.c
Original file line number Diff line number Diff line change
Expand Up @@ -1318,30 +1318,21 @@ static bool iort_pci_rc_supports_canwbs(struct acpi_iort_node *node)
static int iort_iommu_xlate(struct device *dev, struct acpi_iort_node *node,
u32 streamid)
{
const struct iommu_ops *ops;
struct fwnode_handle *iort_fwnode;

if (!node)
/* If there's no SMMU driver at all, give up now */
if (!node || !iort_iommu_driver_enabled(node->type))
return -ENODEV;

iort_fwnode = iort_get_fwnode(node);
if (!iort_fwnode)
return -ENODEV;

/*
* If the ops look-up fails, this means that either
* the SMMU drivers have not been probed yet or that
* the SMMU drivers are not built in the kernel;
* Depending on whether the SMMU drivers are built-in
* in the kernel or not, defer the IOMMU configuration
* or just abort it.
* If the SMMU drivers are enabled but not loaded/probed
* yet, this will defer.
*/
ops = iommu_ops_from_fwnode(iort_fwnode);
if (!ops)
return iort_iommu_driver_enabled(node->type) ?
-EPROBE_DEFER : -ENODEV;

return acpi_iommu_fwspec_init(dev, streamid, iort_fwnode, ops);
return acpi_iommu_fwspec_init(dev, streamid, iort_fwnode);
}

struct iort_pci_alias_info {
Expand Down
44 changes: 8 additions & 36 deletions drivers/acpi/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1619,37 +1619,24 @@ int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map)

#ifdef CONFIG_IOMMU_API
int acpi_iommu_fwspec_init(struct device *dev, u32 id,
struct fwnode_handle *fwnode,
const struct iommu_ops *ops)
struct fwnode_handle *fwnode)
{
int ret = iommu_fwspec_init(dev, fwnode, ops);
int ret = iommu_fwspec_init(dev, fwnode);

if (!ret)
ret = iommu_fwspec_add_ids(dev, &id, 1);

return ret;
}

static inline const struct iommu_ops *acpi_iommu_fwspec_ops(struct device *dev)
{
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);

return fwspec ? fwspec->ops : NULL;
}

static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)
{
int err;
const struct iommu_ops *ops;

/* Serialise to make dev->iommu stable under our potential fwspec */
mutex_lock(&iommu_probe_device_lock);
/*
* If we already translated the fwspec there is nothing left to do,
* return the iommu_ops.
*/
ops = acpi_iommu_fwspec_ops(dev);
if (ops) {
/* If we already translated the fwspec there is nothing left to do */
if (dev_iommu_fwspec_get(dev)) {
mutex_unlock(&iommu_probe_device_lock);
return 0;
}
Expand All @@ -1659,30 +1646,13 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)
err = viot_iommu_configure(dev);
mutex_unlock(&iommu_probe_device_lock);

/*
* If we have reason to believe the IOMMU driver missed the initial
* iommu_probe_device() call for dev, replay it to get things in order.
*/
if (!err && dev->bus)
err = iommu_probe_device(dev);

/* Ignore all other errors apart from EPROBE_DEFER */
if (err == -EPROBE_DEFER) {
return err;
} else if (err) {
dev_dbg(dev, "Adding to IOMMU failed: %d\n", err);
return -ENODEV;
}
if (!acpi_iommu_fwspec_ops(dev))
return -ENODEV;
return 0;
return err;
}

#else /* !CONFIG_IOMMU_API */

int acpi_iommu_fwspec_init(struct device *dev, u32 id,
struct fwnode_handle *fwnode,
const struct iommu_ops *ops)
struct fwnode_handle *fwnode)
{
return -ENODEV;
}
Expand Down Expand Up @@ -1715,6 +1685,8 @@ int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr,
ret = acpi_iommu_configure_id(dev, input_id);
if (ret == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (ret)
dev_dbg(dev, "Adding to IOMMU failed: %d\n", ret);

/*
* Historically this routine doesn't fail driver probing due to errors
Expand Down
11 changes: 2 additions & 9 deletions drivers/acpi/viot.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,21 +307,14 @@ void __init acpi_viot_init(void)
static int viot_dev_iommu_init(struct device *dev, struct viot_iommu *viommu,
u32 epid)
{
const struct iommu_ops *ops;

if (!viommu)
if (!viommu || !IS_ENABLED(CONFIG_VIRTIO_IOMMU))
return -ENODEV;

/* We're not translating ourself */
if (device_match_fwnode(dev, viommu->fwnode))
return -EINVAL;

ops = iommu_ops_from_fwnode(viommu->fwnode);
if (!ops)
return IS_ENABLED(CONFIG_VIRTIO_IOMMU) ?
-EPROBE_DEFER : -ENODEV;

return acpi_iommu_fwspec_init(dev, epid, viommu->fwnode, ops);
return acpi_iommu_fwspec_init(dev, epid, viommu->fwnode);
}

static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data)
Expand Down
3 changes: 2 additions & 1 deletion drivers/amba/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,8 @@ static int amba_dma_configure(struct device *dev)
ret = acpi_dma_configure(dev, attr);
}

if (!ret && !drv->driver_managed_dma) {
/* @drv may not be valid when we're called from the IOMMU layer */
if (!ret && dev->driver && !drv->driver_managed_dma) {
ret = iommu_device_use_default_domain(dev);
if (ret)
arch_teardown_dma_ops(dev);
Expand Down
3 changes: 2 additions & 1 deletion drivers/base/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -1457,7 +1457,8 @@ static int platform_dma_configure(struct device *dev)
ret = acpi_dma_configure(dev, attr);
}

if (!ret && !drv->driver_managed_dma) {
/* @drv may not be valid when we're called from the IOMMU layer */
if (!ret && dev->driver && !drv->driver_managed_dma) {
ret = iommu_device_use_default_domain(dev);
if (ret)
arch_teardown_dma_ops(dev);
Expand Down
3 changes: 2 additions & 1 deletion drivers/bus/fsl-mc/fsl-mc-bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ static int fsl_mc_dma_configure(struct device *dev)
else
ret = acpi_dma_configure_id(dev, DEV_DMA_COHERENT, &input_id);

if (!ret && !mc_drv->driver_managed_dma) {
/* @mc_drv may not be valid when we're called from the IOMMU layer */
if (!ret && dev->driver && !mc_drv->driver_managed_dma) {
ret = iommu_device_use_default_domain(dev);
if (ret)
arch_teardown_dma_ops(dev);
Expand Down
3 changes: 2 additions & 1 deletion drivers/cdx/cdx.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ static int cdx_dma_configure(struct device *dev)
return ret;
}

if (!ret && !cdx_drv->driver_managed_dma) {
/* @cdx_drv may not be valid when we're called from the IOMMU layer */
if (!ret && dev->driver && !cdx_drv->driver_managed_dma) {
ret = iommu_device_use_default_domain(dev);
if (ret)
arch_teardown_dma_ops(dev);
Expand Down
7 changes: 5 additions & 2 deletions drivers/gpu/drm/msm/msm_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,10 +407,13 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
struct msm_iommu *iommu;
int ret;

domain = iommu_domain_alloc(dev->bus);
if (!domain)
if (!device_iommu_mapped(dev))
return NULL;

domain = iommu_paging_domain_alloc(dev);
if (IS_ERR(domain))
return ERR_CAST(domain);

iommu_set_pgtable_quirks(domain, quirks);

iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
mutex_init(&tdev->iommu.mutex);

if (device_iommu_mapped(dev)) {
tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type);
if (!tdev->iommu.domain)
tdev->iommu.domain = iommu_paging_domain_alloc(dev);
if (IS_ERR(tdev->iommu.domain))
goto error;

/*
Expand Down
10 changes: 7 additions & 3 deletions drivers/gpu/drm/rockchip/rockchip_drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,17 @@ static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
struct rockchip_drm_private *private = drm_dev->dev_private;
struct iommu_domain_geometry *geometry;
u64 start, end;
int ret;

if (IS_ERR_OR_NULL(private->iommu_dev))
return 0;

private->domain = iommu_domain_alloc(private->iommu_dev->bus);
if (!private->domain)
return -ENOMEM;
private->domain = iommu_paging_domain_alloc(private->iommu_dev);
if (IS_ERR(private->domain)) {
ret = PTR_ERR(private->domain);
private->domain = NULL;
return ret;
}

geometry = &private->domain->geometry;
start = geometry->aperture_start;
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/tegra/drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,7 @@ static bool host1x_drm_wants_iommu(struct host1x_device *dev)

static int host1x_drm_probe(struct host1x_device *dev)
{
struct device *dma_dev = dev->dev.parent;
struct tegra_drm *tegra;
struct drm_device *drm;
int err;
Expand All @@ -1148,8 +1149,8 @@ static int host1x_drm_probe(struct host1x_device *dev)
goto put;
}

if (host1x_drm_wants_iommu(dev) && iommu_present(&platform_bus_type)) {
tegra->domain = iommu_domain_alloc(&platform_bus_type);
if (host1x_drm_wants_iommu(dev) && device_iommu_mapped(dma_dev)) {
tegra->domain = iommu_paging_domain_alloc(dma_dev);
if (!tegra->domain) {
err = -ENOMEM;
goto free;
Expand Down
7 changes: 4 additions & 3 deletions drivers/gpu/host1x/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,10 @@ static struct iommu_domain *host1x_iommu_attach(struct host1x *host)
if (err < 0)
goto put_group;

host->domain = iommu_domain_alloc(&platform_bus_type);
if (!host->domain) {
err = -ENOMEM;
host->domain = iommu_paging_domain_alloc(host->dev);
if (IS_ERR(host->domain)) {
err = PTR_ERR(host->domain);
host->domain = NULL;
goto put_cache;
}

Expand Down
6 changes: 3 additions & 3 deletions drivers/infiniband/hw/usnic/usnic_uiom.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,11 +443,11 @@ struct usnic_uiom_pd *usnic_uiom_alloc_pd(struct device *dev)
if (!pd)
return ERR_PTR(-ENOMEM);

pd->domain = domain = iommu_domain_alloc(dev->bus);
if (!domain) {
pd->domain = domain = iommu_paging_domain_alloc(dev);
if (IS_ERR(domain)) {
usnic_err("Failed to allocate IOMMU domain");
kfree(pd);
return ERR_PTR(-ENOMEM);
return ERR_CAST(domain);
}

iommu_set_fault_handler(pd->domain, usnic_uiom_dma_fault, NULL);
Expand Down
4 changes: 1 addition & 3 deletions drivers/iommu/arm/arm-smmu/arm-smmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,7 @@ static int arm_smmu_register_legacy_master(struct device *dev,
it.cur_count = 1;
}

err = iommu_fwspec_init(dev, &smmu_dev->of_node->fwnode,
&arm_smmu_ops);
err = iommu_fwspec_init(dev, NULL);
if (err)
return err;

Expand Down Expand Up @@ -1471,7 +1470,6 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
out_cfg_free:
kfree(cfg);
out_free:
iommu_fwspec_free(dev);
return ERR_PTR(ret);
}

Expand Down
11 changes: 11 additions & 0 deletions drivers/iommu/iommu-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,20 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev)
return dev->iommu->iommu_dev->ops;
}

void dev_iommu_free(struct device *dev);

const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode);

static inline const struct iommu_ops *iommu_fwspec_ops(struct iommu_fwspec *fwspec)
{
return iommu_ops_from_fwnode(fwspec ? fwspec->iommu_fwnode : NULL);
}

int iommu_group_replace_domain(struct iommu_group *group,
struct iommu_domain *new_domain);

void iommu_fwspec_free(struct device *dev);

int iommu_device_register_bus(struct iommu_device *iommu,
const struct iommu_ops *ops, struct bus_type *bus,
struct notifier_block *nb);
Expand Down
Loading
Loading