--- zzzz-none-000/linux-3.10.107/drivers/iommu/tegra-gart.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/iommu/tegra-gart.c 2021-02-04 17:41:59.000000000 +0000 @@ -63,11 +63,21 @@ struct device *dev; }; +struct gart_domain { + struct iommu_domain domain; /* generic domain handle */ + struct gart_device *gart; /* link to gart device */ +}; + static struct gart_device *gart_handle; /* unique for a system */ #define GART_PTE(_pfn) \ (GART_ENTRY_PHYS_ADDR_VALID | ((_pfn) << PAGE_SHIFT)) +static struct gart_domain *to_gart_domain(struct iommu_domain *dom) +{ + return container_of(dom, struct gart_domain, domain); +} + /* * Any interaction between any block on PPSB and a block on APB or AHB * must have these read-back to ensure the APB/AHB bus transaction is @@ -156,20 +166,11 @@ static int gart_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) { - struct gart_device *gart; + struct gart_domain *gart_domain = to_gart_domain(domain); + struct gart_device *gart = gart_domain->gart; struct gart_client *client, *c; int err = 0; - gart = gart_handle; - if (!gart) - return -EINVAL; - domain->priv = gart; - - domain->geometry.aperture_start = gart->iovmm_base; - domain->geometry.aperture_end = gart->iovmm_base + - gart->page_count * GART_PAGE_SIZE - 1; - domain->geometry.force_aperture = true; - client = devm_kzalloc(gart->dev, sizeof(*c), GFP_KERNEL); if (!client) return -ENOMEM; @@ -198,7 +199,8 @@ static void gart_iommu_detach_dev(struct iommu_domain *domain, struct device *dev) { - struct gart_device *gart = domain->priv; + struct gart_domain *gart_domain = to_gart_domain(domain); + struct gart_device *gart = gart_domain->gart; struct gart_client *c; spin_lock(&gart->client_lock); @@ -216,33 +218,55 @@ spin_unlock(&gart->client_lock); } -static int gart_iommu_domain_init(struct iommu_domain *domain) +static struct iommu_domain *gart_iommu_domain_alloc(unsigned type) { - return 0; -} + struct gart_domain *gart_domain; + struct gart_device *gart; -static void gart_iommu_domain_destroy(struct iommu_domain *domain) -{ - struct gart_device *gart = domain->priv; + if (type != IOMMU_DOMAIN_UNMANAGED) + return NULL; + gart = gart_handle; if (!gart) - return; + return NULL; - spin_lock(&gart->client_lock); - if (!list_empty(&gart->client)) { - struct gart_client *c; + gart_domain = kzalloc(sizeof(*gart_domain), GFP_KERNEL); + if (!gart_domain) + return NULL; + + gart_domain->gart = gart; + gart_domain->domain.geometry.aperture_start = gart->iovmm_base; + gart_domain->domain.geometry.aperture_end = gart->iovmm_base + + gart->page_count * GART_PAGE_SIZE - 1; + gart_domain->domain.geometry.force_aperture = true; + + return &gart_domain->domain; +} + +static void gart_iommu_domain_free(struct iommu_domain *domain) +{ + struct gart_domain *gart_domain = to_gart_domain(domain); + struct gart_device *gart = gart_domain->gart; - list_for_each_entry(c, &gart->client, list) - gart_iommu_detach_dev(domain, c->dev); + if (gart) { + spin_lock(&gart->client_lock); + if (!list_empty(&gart->client)) { + struct gart_client *c; + + list_for_each_entry(c, &gart->client, list) + gart_iommu_detach_dev(domain, c->dev); + } + spin_unlock(&gart->client_lock); } - spin_unlock(&gart->client_lock); - domain->priv = NULL; + + kfree(gart_domain); } static int gart_iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t pa, size_t bytes, int prot) { - struct gart_device *gart = domain->priv; + struct gart_domain *gart_domain = to_gart_domain(domain); + struct gart_device *gart = gart_domain->gart; unsigned long flags; unsigned long pfn; @@ -252,7 +276,7 @@ spin_lock_irqsave(&gart->pte_lock, flags); pfn = __phys_to_pfn(pa); if (!pfn_valid(pfn)) { - dev_err(gart->dev, "Invalid page: %08x\n", pa); + dev_err(gart->dev, "Invalid page: %pa\n", &pa); spin_unlock_irqrestore(&gart->pte_lock, flags); return -EINVAL; } @@ -265,7 +289,8 @@ static size_t gart_iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t bytes) { - struct gart_device *gart = domain->priv; + struct gart_domain *gart_domain = to_gart_domain(domain); + struct gart_device *gart = gart_domain->gart; unsigned long flags; if (!gart_iova_range_valid(gart, iova, bytes)) @@ -281,7 +306,8 @@ static phys_addr_t gart_iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova) { - struct gart_device *gart = domain->priv; + struct gart_domain *gart_domain = to_gart_domain(domain); + struct gart_device *gart = gart_domain->gart; unsigned long pte; phys_addr_t pa; unsigned long flags; @@ -295,29 +321,29 @@ pa = (pte & GART_PAGE_MASK); if (!pfn_valid(__phys_to_pfn(pa))) { - dev_err(gart->dev, "No entry for %08llx:%08x\n", - (unsigned long long)iova, pa); + dev_err(gart->dev, "No entry for %08llx:%pa\n", + (unsigned long long)iova, &pa); gart_dump_table(gart); return -EINVAL; } return pa; } -static int gart_iommu_domain_has_cap(struct iommu_domain *domain, - unsigned long cap) +static bool gart_iommu_capable(enum iommu_cap cap) { - return 0; + return false; } -static struct iommu_ops gart_iommu_ops = { - .domain_init = gart_iommu_domain_init, - .domain_destroy = gart_iommu_domain_destroy, +static const struct iommu_ops gart_iommu_ops = { + .capable = gart_iommu_capable, + .domain_alloc = gart_iommu_domain_alloc, + .domain_free = gart_iommu_domain_free, .attach_dev = gart_iommu_attach_dev, .detach_dev = gart_iommu_detach_dev, .map = gart_iommu_map, + .map_sg = default_iommu_map_sg, .unmap = gart_iommu_unmap, .iova_to_phys = gart_iommu_iova_to_phys, - .domain_has_cap = gart_iommu_domain_has_cap, .pgsize_bitmap = GART_IOMMU_PGSIZES, }; @@ -351,7 +377,6 @@ struct gart_device *gart; struct resource *res, *res_remap; void __iomem *gart_regs; - int err; struct device *dev = &pdev->dev; if (gart_handle) @@ -376,8 +401,7 @@ gart_regs = devm_ioremap(dev, res->start, resource_size(res)); if (!gart_regs) { dev_err(dev, "failed to remap GART registers\n"); - err = -ENXIO; - goto fail; + return -ENXIO; } gart->dev = &pdev->dev; @@ -391,47 +415,34 @@ gart->savedata = vmalloc(sizeof(u32) * gart->page_count); if (!gart->savedata) { dev_err(dev, "failed to allocate context save area\n"); - err = -ENOMEM; - goto fail; + return -ENOMEM; } platform_set_drvdata(pdev, gart); do_gart_setup(gart, NULL); gart_handle = gart; - bus_set_iommu(&platform_bus_type, &gart_iommu_ops); - return 0; -fail: - if (gart_regs) - devm_iounmap(dev, gart_regs); - if (gart && gart->savedata) - vfree(gart->savedata); - devm_kfree(dev, gart); - return err; + return 0; } static int tegra_gart_remove(struct platform_device *pdev) { struct gart_device *gart = platform_get_drvdata(pdev); - struct device *dev = gart->dev; writel(0, gart->regs + GART_CONFIG); if (gart->savedata) vfree(gart->savedata); - if (gart->regs) - devm_iounmap(dev, gart->regs); - devm_kfree(dev, gart); gart_handle = NULL; return 0; } -const struct dev_pm_ops tegra_gart_pm_ops = { +static const struct dev_pm_ops tegra_gart_pm_ops = { .suspend = tegra_gart_suspend, .resume = tegra_gart_resume, }; -static struct of_device_id tegra_gart_of_match[] = { +static const struct of_device_id tegra_gart_of_match[] = { { .compatible = "nvidia,tegra20-gart", }, { }, }; @@ -441,7 +452,6 @@ .probe = tegra_gart_probe, .remove = tegra_gart_remove, .driver = { - .owner = THIS_MODULE, .name = "tegra-gart", .pm = &tegra_gart_pm_ops, .of_match_table = tegra_gart_of_match,