diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-15 12:24:14 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-15 12:24:14 -0800 |
commit | a9a16a6d136593c9e6f72e481b2b86ae1d8d1fce (patch) | |
tree | 6a09888cfe1c23c9330dc95f5a83848c51d3e229 /drivers/iommu/mtk_iommu.c | |
parent | d3ea547853852481dc5eba6d4cb13adab1564d0b (diff) | |
parent | 1465f481460cbfc60dc119873099d89a58f9be4f (diff) | |
download | linux-a9a16a6d136593c9e6f72e481b2b86ae1d8d1fce.tar.bz2 |
Merge tag 'iommu-updates-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU updates from Joerg Roedel:
"These changes include:
- support for the ACPI IORT table on ARM systems and patches to make
the ARM-SMMU driver make use of it
- conversion of the Exynos IOMMU driver to device dependency links
and implementation of runtime pm support based on that conversion
- update the Mediatek IOMMU driver to use the new struct
device->iommu_fwspec member
- implementation of dma_map/unmap_resource in the generic ARM
dma-iommu layer
- a number of smaller fixes and improvements all over the place"
* tag 'iommu-updates-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (44 commits)
ACPI/IORT: Make dma masks set-up IORT specific
iommu/amd: Missing error code in amd_iommu_init_device()
iommu/s390: Drop duplicate header pci.h
ACPI/IORT: Introduce iort_iommu_configure
ACPI/IORT: Add single mapping function
ACPI/IORT: Replace rid map type with type mask
iommu/arm-smmu: Add IORT configuration
iommu/arm-smmu: Split probe functions into DT/generic portions
iommu/arm-smmu-v3: Add IORT configuration
iommu/arm-smmu-v3: Split probe functions into DT/generic portions
ACPI/IORT: Add support for ARM SMMU platform devices creation
ACPI/IORT: Add node match function
ACPI: Implement acpi_dma_configure
iommu/arm-smmu-v3: Convert struct device of_node to fwnode usage
iommu/arm-smmu: Convert struct device of_node to fwnode usage
iommu: Make of_iommu_set/get_ops() DT agnostic
ACPI/IORT: Add support for IOMMU fwnode registration
ACPI/IORT: Introduce linker section for IORT entries probing
ACPI: Add FWNODE_ACPI_STATIC fwnode type
iommu/arm-smmu: Set SMTNMB_TLBEN in ACR to enable caching of bypass entries
...
Diffstat (limited to 'drivers/iommu/mtk_iommu.c')
-rw-r--r-- | drivers/iommu/mtk_iommu.c | 85 |
1 files changed, 25 insertions, 60 deletions
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index b12c12d74c33..1479c76ece9e 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -195,14 +195,14 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) static void mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, bool enable) { - struct mtk_iommu_client_priv *head, *cur, *next; struct mtk_smi_larb_iommu *larb_mmu; unsigned int larbid, portid; + struct iommu_fwspec *fwspec = dev->iommu_fwspec; + int i; - head = dev->archdata.iommu; - list_for_each_entry_safe(cur, next, &head->client, client) { - larbid = MTK_M4U_TO_LARB(cur->mtk_m4u_id); - portid = MTK_M4U_TO_PORT(cur->mtk_m4u_id); + for (i = 0; i < fwspec->num_ids; ++i) { + larbid = MTK_M4U_TO_LARB(fwspec->ids[i]); + portid = MTK_M4U_TO_PORT(fwspec->ids[i]); larb_mmu = &data->smi_imu.larb_imu[larbid]; dev_dbg(dev, "%s iommu port: %d\n", @@ -282,14 +282,12 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, struct device *dev) { struct mtk_iommu_domain *dom = to_mtk_domain(domain); - struct mtk_iommu_client_priv *priv = dev->archdata.iommu; - struct mtk_iommu_data *data; + struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv; int ret; - if (!priv) + if (!data) return -ENODEV; - data = dev_get_drvdata(priv->m4udev); if (!data->m4u_dom) { data->m4u_dom = dom; ret = mtk_iommu_domain_finalise(data); @@ -310,13 +308,11 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, static void mtk_iommu_detach_device(struct iommu_domain *domain, struct device *dev) { - struct mtk_iommu_client_priv *priv = dev->archdata.iommu; - struct mtk_iommu_data *data; + struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv; - if (!priv) + if (!data) return; - data = dev_get_drvdata(priv->m4udev); mtk_iommu_config(data, dev, false); } @@ -366,8 +362,8 @@ static int mtk_iommu_add_device(struct device *dev) { struct iommu_group *group; - if (!dev->archdata.iommu) /* Not a iommu client device */ - return -ENODEV; + if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops) + return -ENODEV; /* Not a iommu client device */ group = iommu_group_get_for_dev(dev); if (IS_ERR(group)) @@ -379,44 +375,33 @@ static int mtk_iommu_add_device(struct device *dev) static void mtk_iommu_remove_device(struct device *dev) { - struct mtk_iommu_client_priv *head, *cur, *next; - - head = dev->archdata.iommu; - if (!head) + if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops) return; - list_for_each_entry_safe(cur, next, &head->client, client) { - list_del(&cur->client); - kfree(cur); - } - kfree(head); - dev->archdata.iommu = NULL; - iommu_group_remove_device(dev); + iommu_fwspec_free(dev); } static struct iommu_group *mtk_iommu_device_group(struct device *dev) { - struct mtk_iommu_data *data; - struct mtk_iommu_client_priv *priv; + struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv; - priv = dev->archdata.iommu; - if (!priv) + if (!data) return ERR_PTR(-ENODEV); /* All the client devices are in the same m4u iommu-group */ - data = dev_get_drvdata(priv->m4udev); if (!data->m4u_group) { data->m4u_group = iommu_group_alloc(); if (IS_ERR(data->m4u_group)) dev_err(dev, "Failed to allocate M4U IOMMU group\n"); + } else { + iommu_group_ref_get(data->m4u_group); } return data->m4u_group; } static int mtk_iommu_of_xlate(struct device *dev, struct of_phandle_args *args) { - struct mtk_iommu_client_priv *head, *priv, *next; struct platform_device *m4updev; if (args->args_count != 1) { @@ -425,38 +410,16 @@ static int mtk_iommu_of_xlate(struct device *dev, struct of_phandle_args *args) return -EINVAL; } - if (!dev->archdata.iommu) { + if (!dev->iommu_fwspec->iommu_priv) { /* Get the m4u device */ m4updev = of_find_device_by_node(args->np); if (WARN_ON(!m4updev)) return -EINVAL; - head = kzalloc(sizeof(*head), GFP_KERNEL); - if (!head) - return -ENOMEM; - - dev->archdata.iommu = head; - INIT_LIST_HEAD(&head->client); - head->m4udev = &m4updev->dev; - } else { - head = dev->archdata.iommu; + dev->iommu_fwspec->iommu_priv = platform_get_drvdata(m4updev); } - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - goto err_free_mem; - - priv->mtk_m4u_id = args->args[0]; - list_add_tail(&priv->client, &head->client); - - return 0; - -err_free_mem: - list_for_each_entry_safe(priv, next, &head->client, client) - kfree(priv); - kfree(head); - dev->archdata.iommu = NULL; - return -ENOMEM; + return iommu_fwspec_add_ids(dev, args->args, 1); } static struct iommu_ops mtk_iommu_ops = { @@ -583,17 +546,19 @@ static int mtk_iommu_probe(struct platform_device *pdev) continue; plarbdev = of_find_device_by_node(larbnode); - of_node_put(larbnode); if (!plarbdev) { plarbdev = of_platform_device_create( larbnode, NULL, platform_bus_type.dev_root); - if (!plarbdev) + if (!plarbdev) { + of_node_put(larbnode); return -EPROBE_DEFER; + } } data->smi_imu.larb_imu[i].dev = &plarbdev->dev; - component_match_add(dev, &match, compare_of, larbnode); + component_match_add_release(dev, &match, release_of, + compare_of, larbnode); } platform_set_drvdata(pdev, data); |