Loading drivers/iommu/msm_iommu.c +73 −0 Original line number Original line Diff line number Diff line Loading @@ -371,6 +371,58 @@ static int msm_iommu_domain_config(struct msm_priv *priv) return 0; return 0; } } /* Must be called under msm_iommu_lock */ static struct msm_iommu_dev *find_iommu_for_dev(struct device *dev) { struct msm_iommu_dev *iommu, *ret = NULL; struct msm_iommu_ctx_dev *master; list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) { master = list_first_entry(&iommu->ctx_list, struct msm_iommu_ctx_dev, list); if (master->of_node == dev->of_node) { ret = iommu; break; } } return ret; } static int msm_iommu_add_device(struct device *dev) { struct msm_iommu_dev *iommu; unsigned long flags; int ret = 0; spin_lock_irqsave(&msm_iommu_lock, flags); iommu = find_iommu_for_dev(dev); if (iommu) iommu_device_link(&iommu->iommu, dev); else ret = -ENODEV; spin_unlock_irqrestore(&msm_iommu_lock, flags); return ret; } static void msm_iommu_remove_device(struct device *dev) { struct msm_iommu_dev *iommu; unsigned long flags; spin_lock_irqsave(&msm_iommu_lock, flags); iommu = find_iommu_for_dev(dev); if (iommu) iommu_device_unlink(&iommu->iommu, dev); spin_unlock_irqrestore(&msm_iommu_lock, flags); } static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) { { int ret = 0; int ret = 0; Loading Loading @@ -646,6 +698,8 @@ static struct iommu_ops msm_iommu_ops = { .unmap = msm_iommu_unmap, .unmap = msm_iommu_unmap, .map_sg = default_iommu_map_sg, .map_sg = default_iommu_map_sg, .iova_to_phys = msm_iommu_iova_to_phys, .iova_to_phys = msm_iommu_iova_to_phys, .add_device = msm_iommu_add_device, .remove_device = msm_iommu_remove_device, .pgsize_bitmap = MSM_IOMMU_PGSIZES, .pgsize_bitmap = MSM_IOMMU_PGSIZES, .of_xlate = qcom_iommu_of_xlate, .of_xlate = qcom_iommu_of_xlate, }; }; Loading @@ -653,6 +707,7 @@ static struct iommu_ops msm_iommu_ops = { static int msm_iommu_probe(struct platform_device *pdev) static int msm_iommu_probe(struct platform_device *pdev) { { struct resource *r; struct resource *r; resource_size_t ioaddr; struct msm_iommu_dev *iommu; struct msm_iommu_dev *iommu; int ret, par, val; int ret, par, val; Loading Loading @@ -696,6 +751,7 @@ static int msm_iommu_probe(struct platform_device *pdev) ret = PTR_ERR(iommu->base); ret = PTR_ERR(iommu->base); goto fail; goto fail; } } ioaddr = r->start; iommu->irq = platform_get_irq(pdev, 0); iommu->irq = platform_get_irq(pdev, 0); if (iommu->irq < 0) { if (iommu->irq < 0) { Loading Loading @@ -737,6 +793,23 @@ static int msm_iommu_probe(struct platform_device *pdev) } } list_add(&iommu->dev_node, &qcom_iommu_devices); list_add(&iommu->dev_node, &qcom_iommu_devices); ret = iommu_device_sysfs_add(&iommu->iommu, iommu->dev, NULL, "msm-smmu.%pa", &ioaddr); if (ret) { pr_err("Could not add msm-smmu at %pa to sysfs\n", &ioaddr); goto fail; } iommu_device_set_ops(&iommu->iommu, &msm_iommu_ops); iommu_device_set_fwnode(&iommu->iommu, &pdev->dev.of_node->fwnode); ret = iommu_device_register(&iommu->iommu); if (ret) { pr_err("Could not register msm-smmu at %pa\n", &ioaddr); goto fail; } of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops); of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops); pr_info("device mapped at %p, irq %d with %d ctx banks\n", pr_info("device mapped at %p, irq %d with %d ctx banks\n", Loading drivers/iommu/msm_iommu.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ #define MSM_IOMMU_H #define MSM_IOMMU_H #include <linux/interrupt.h> #include <linux/interrupt.h> #include <linux/iommu.h> #include <linux/clk.h> #include <linux/clk.h> /* Sharability attributes of MSM IOMMU mappings */ /* Sharability attributes of MSM IOMMU mappings */ Loading Loading @@ -68,6 +69,8 @@ struct msm_iommu_dev { struct list_head dom_node; struct list_head dom_node; struct list_head ctx_list; struct list_head ctx_list; DECLARE_BITMAP(context_map, IOMMU_MAX_CBS); DECLARE_BITMAP(context_map, IOMMU_MAX_CBS); struct iommu_device iommu; }; }; /** /** Loading Loading
drivers/iommu/msm_iommu.c +73 −0 Original line number Original line Diff line number Diff line Loading @@ -371,6 +371,58 @@ static int msm_iommu_domain_config(struct msm_priv *priv) return 0; return 0; } } /* Must be called under msm_iommu_lock */ static struct msm_iommu_dev *find_iommu_for_dev(struct device *dev) { struct msm_iommu_dev *iommu, *ret = NULL; struct msm_iommu_ctx_dev *master; list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) { master = list_first_entry(&iommu->ctx_list, struct msm_iommu_ctx_dev, list); if (master->of_node == dev->of_node) { ret = iommu; break; } } return ret; } static int msm_iommu_add_device(struct device *dev) { struct msm_iommu_dev *iommu; unsigned long flags; int ret = 0; spin_lock_irqsave(&msm_iommu_lock, flags); iommu = find_iommu_for_dev(dev); if (iommu) iommu_device_link(&iommu->iommu, dev); else ret = -ENODEV; spin_unlock_irqrestore(&msm_iommu_lock, flags); return ret; } static void msm_iommu_remove_device(struct device *dev) { struct msm_iommu_dev *iommu; unsigned long flags; spin_lock_irqsave(&msm_iommu_lock, flags); iommu = find_iommu_for_dev(dev); if (iommu) iommu_device_unlink(&iommu->iommu, dev); spin_unlock_irqrestore(&msm_iommu_lock, flags); } static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) { { int ret = 0; int ret = 0; Loading Loading @@ -646,6 +698,8 @@ static struct iommu_ops msm_iommu_ops = { .unmap = msm_iommu_unmap, .unmap = msm_iommu_unmap, .map_sg = default_iommu_map_sg, .map_sg = default_iommu_map_sg, .iova_to_phys = msm_iommu_iova_to_phys, .iova_to_phys = msm_iommu_iova_to_phys, .add_device = msm_iommu_add_device, .remove_device = msm_iommu_remove_device, .pgsize_bitmap = MSM_IOMMU_PGSIZES, .pgsize_bitmap = MSM_IOMMU_PGSIZES, .of_xlate = qcom_iommu_of_xlate, .of_xlate = qcom_iommu_of_xlate, }; }; Loading @@ -653,6 +707,7 @@ static struct iommu_ops msm_iommu_ops = { static int msm_iommu_probe(struct platform_device *pdev) static int msm_iommu_probe(struct platform_device *pdev) { { struct resource *r; struct resource *r; resource_size_t ioaddr; struct msm_iommu_dev *iommu; struct msm_iommu_dev *iommu; int ret, par, val; int ret, par, val; Loading Loading @@ -696,6 +751,7 @@ static int msm_iommu_probe(struct platform_device *pdev) ret = PTR_ERR(iommu->base); ret = PTR_ERR(iommu->base); goto fail; goto fail; } } ioaddr = r->start; iommu->irq = platform_get_irq(pdev, 0); iommu->irq = platform_get_irq(pdev, 0); if (iommu->irq < 0) { if (iommu->irq < 0) { Loading Loading @@ -737,6 +793,23 @@ static int msm_iommu_probe(struct platform_device *pdev) } } list_add(&iommu->dev_node, &qcom_iommu_devices); list_add(&iommu->dev_node, &qcom_iommu_devices); ret = iommu_device_sysfs_add(&iommu->iommu, iommu->dev, NULL, "msm-smmu.%pa", &ioaddr); if (ret) { pr_err("Could not add msm-smmu at %pa to sysfs\n", &ioaddr); goto fail; } iommu_device_set_ops(&iommu->iommu, &msm_iommu_ops); iommu_device_set_fwnode(&iommu->iommu, &pdev->dev.of_node->fwnode); ret = iommu_device_register(&iommu->iommu); if (ret) { pr_err("Could not register msm-smmu at %pa\n", &ioaddr); goto fail; } of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops); of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops); pr_info("device mapped at %p, irq %d with %d ctx banks\n", pr_info("device mapped at %p, irq %d with %d ctx banks\n", Loading
drivers/iommu/msm_iommu.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ #define MSM_IOMMU_H #define MSM_IOMMU_H #include <linux/interrupt.h> #include <linux/interrupt.h> #include <linux/iommu.h> #include <linux/clk.h> #include <linux/clk.h> /* Sharability attributes of MSM IOMMU mappings */ /* Sharability attributes of MSM IOMMU mappings */ Loading Loading @@ -68,6 +69,8 @@ struct msm_iommu_dev { struct list_head dom_node; struct list_head dom_node; struct list_head ctx_list; struct list_head ctx_list; DECLARE_BITMAP(context_map, IOMMU_MAX_CBS); DECLARE_BITMAP(context_map, IOMMU_MAX_CBS); struct iommu_device iommu; }; }; /** /** Loading