Skip to content

Commit 816c698

Browse files
Chunyan Zhangjoergroedel
authored andcommitted
iommu/sprd: Add support for reattaching an existing domain
This IOMMU driver should allow a domain to be attached more than once. If IOMMU is reattaching to the same domain which is attached, there's nothing to be done. If reattching to a previously-used domain, do not alloc DMA buffer again which stores address mapping table to avoid memory leak. Signed-off-by: Chunyan Zhang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 9afea57 commit 816c698

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

drivers/iommu/sprd-iommu.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ enum sprd_iommu_version {
6262
* @eb: gate clock which controls IOMMU access
6363
*/
6464
struct sprd_iommu_device {
65+
struct sprd_iommu_domain *dom;
6566
enum sprd_iommu_version ver;
6667
u32 *prot_page_va;
6768
dma_addr_t prot_page_pa;
@@ -252,15 +253,27 @@ static int sprd_iommu_attach_device(struct iommu_domain *domain,
252253
struct sprd_iommu_domain *dom = to_sprd_domain(domain);
253254
size_t pgt_size = sprd_iommu_pgt_size(domain);
254255

255-
if (dom->sdev)
256-
return -EINVAL;
256+
/* The device is attached to this domain */
257+
if (sdev->dom == dom)
258+
return 0;
257259

258-
dom->pgt_va = dma_alloc_coherent(sdev->dev, pgt_size, &dom->pgt_pa, GFP_KERNEL);
259-
if (!dom->pgt_va)
260-
return -ENOMEM;
260+
/* The first time that domain is attaching to a device */
261+
if (!dom->pgt_va) {
262+
dom->pgt_va = dma_alloc_coherent(sdev->dev, pgt_size, &dom->pgt_pa, GFP_KERNEL);
263+
if (!dom->pgt_va)
264+
return -ENOMEM;
265+
266+
dom->sdev = sdev;
267+
}
261268

262-
dom->sdev = sdev;
269+
sdev->dom = dom;
263270

271+
/*
272+
* One sprd IOMMU serves one client device only, disabled it before
273+
* configure mapping table to avoid access conflict in case other
274+
* mapping table is stored in.
275+
*/
276+
sprd_iommu_hw_en(sdev, false);
264277
sprd_iommu_first_ppn(dom);
265278
sprd_iommu_first_vpn(dom);
266279
sprd_iommu_vpn_range(dom);

0 commit comments

Comments
 (0)