Skip to content

Commit

Permalink
iommu/rockchip: Retire global dma_dev workaround
Browse files Browse the repository at this point in the history
The global dma_dev trick was mostly because the old domain_alloc op
provided no context, so no way to know which IOMMU was to own the
pagetable, or if a suitable one even existed at all. In the new
multi-instance world with domain_alloc_paging this is no longer a
concern - now we know that the given device must be associated with a
valid IOMMU instance which provided the op to call in the first place,
and therefore that instance can and should be the pagetable owner. To
avoid worrying about the lifetime and stability of the rk_domain->iommus
list, and keep the lookups simple and efficient, we'll still stash a
dma_dev pointer, but now it's accurately per-domain.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Tested-by: Quentin Schulz <quentin.schulz@cherry.de>
Tested-by: Dang Huynh <danct12@riseup.net>
Reviewed-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Tested-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Link: https://lore.kernel.org/r/25dc948a7d35c8142c5719ac22bc523f8524d006.1741886382.git.robin.murphy@arm.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Robin Murphy authored and Joerg Roedel committed Mar 20, 2025
1 parent f90aa59 commit dcde1c4
Showing 1 changed file with 13 additions and 21 deletions.
34 changes: 13 additions & 21 deletions drivers/iommu/rockchip-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct rk_iommu_domain {
dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
spinlock_t dt_lock; /* lock for modifying page directory table */
struct device *dma_dev;

struct iommu_domain domain;
};
Expand Down Expand Up @@ -123,7 +124,6 @@ struct rk_iommudata {
struct rk_iommu *iommu;
};

static struct device *dma_dev;
static const struct rk_iommu_ops *rk_ops;
static struct iommu_domain rk_identity_domain;

Expand All @@ -132,7 +132,7 @@ static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
{
size_t size = count * sizeof(u32); /* count of u32 entry */

dma_sync_single_for_device(dma_dev, dma, size, DMA_TO_DEVICE);
dma_sync_single_for_device(dom->dma_dev, dma, size, DMA_TO_DEVICE);
}

static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
Expand Down Expand Up @@ -734,9 +734,9 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);

pt_dma = dma_map_single(dma_dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
if (dma_mapping_error(dma_dev, pt_dma)) {
dev_err(dma_dev, "DMA mapping error while allocating page table\n");
pt_dma = dma_map_single(rk_domain->dma_dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
if (dma_mapping_error(rk_domain->dma_dev, pt_dma)) {
dev_err(rk_domain->dma_dev, "DMA mapping error while allocating page table\n");
iommu_free_page(page_table);
return ERR_PTR(-ENOMEM);
}
Expand Down Expand Up @@ -1051,9 +1051,7 @@ static int rk_iommu_attach_device(struct iommu_domain *domain,
static struct iommu_domain *rk_iommu_domain_alloc_paging(struct device *dev)
{
struct rk_iommu_domain *rk_domain;

if (!dma_dev)
return NULL;
struct rk_iommu *iommu;

rk_domain = kzalloc(sizeof(*rk_domain), GFP_KERNEL);
if (!rk_domain)
Expand All @@ -1068,10 +1066,12 @@ static struct iommu_domain *rk_iommu_domain_alloc_paging(struct device *dev)
if (!rk_domain->dt)
goto err_free_domain;

rk_domain->dt_dma = dma_map_single(dma_dev, rk_domain->dt,
iommu = rk_iommu_from_dev(dev);
rk_domain->dma_dev = iommu->dev;
rk_domain->dt_dma = dma_map_single(rk_domain->dma_dev, rk_domain->dt,
SPAGE_SIZE, DMA_TO_DEVICE);
if (dma_mapping_error(dma_dev, rk_domain->dt_dma)) {
dev_err(dma_dev, "DMA map error for DT\n");
if (dma_mapping_error(rk_domain->dma_dev, rk_domain->dt_dma)) {
dev_err(rk_domain->dma_dev, "DMA map error for DT\n");
goto err_free_dt;
}

Expand Down Expand Up @@ -1105,13 +1105,13 @@ static void rk_iommu_domain_free(struct iommu_domain *domain)
if (rk_dte_is_pt_valid(dte)) {
phys_addr_t pt_phys = rk_ops->pt_address(dte);
u32 *page_table = phys_to_virt(pt_phys);
dma_unmap_single(dma_dev, pt_phys,
dma_unmap_single(rk_domain->dma_dev, pt_phys,
SPAGE_SIZE, DMA_TO_DEVICE);
iommu_free_page(page_table);
}
}

dma_unmap_single(dma_dev, rk_domain->dt_dma,
dma_unmap_single(rk_domain->dma_dev, rk_domain->dt_dma,
SPAGE_SIZE, DMA_TO_DEVICE);
iommu_free_page(rk_domain->dt);

Expand Down Expand Up @@ -1256,14 +1256,6 @@ static int rk_iommu_probe(struct platform_device *pdev)
if (err)
return err;

/*
* Use the first registered IOMMU device for domain to use with DMA
* API, since a domain might not physically correspond to a single
* IOMMU device..
*/
if (!dma_dev)
dma_dev = &pdev->dev;

pm_runtime_enable(dev);

for (i = 0; i < iommu->num_irq; i++) {
Expand Down

0 comments on commit dcde1c4

Please sign in to comment.