Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1358151 > unrolled thread
| Started by | Magnus Damm <magnus.damm@gmail.com> |
|---|---|
| First post | 2016-03-15 18:10 +0100 |
| Last post | 2016-03-15 18:10 +0100 |
| Articles | 4 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH 00/04] iommu/ipmmu-vmsa: IPMMU CONFIG_IOMMU_DMA update Magnus Damm <magnus.damm@gmail.com> - 2016-03-15 18:10 +0100
[PATCH 03/04] iommu/ipmmu-vmsa: Break out domain allocation code Magnus Damm <magnus.damm@gmail.com> - 2016-03-15 18:10 +0100
[PATCH 02/04] iommu/ipmmu-vmsa: Break out utlb parsing code Magnus Damm <magnus.damm@gmail.com> - 2016-03-15 18:10 +0100
[PATCH 04/04] iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops Magnus Damm <magnus.damm@gmail.com> - 2016-03-15 18:10 +0100
| From | Magnus Damm <magnus.damm@gmail.com> |
|---|---|
| Date | 2016-03-15 18:10 +0100 |
| Subject | [PATCH 00/04] iommu/ipmmu-vmsa: IPMMU CONFIG_IOMMU_DMA update |
| Message-ID | <rd0DM-4Yj-3@gated-at.bofh.it> |
iommu/ipmmu-vmsa: IPMMU CONFIG_IOMMU_DMA update [PATCH 01/04] iommu/ipmmu-vmsa: 32-bit ARM may have CONFIG_IOMMU_DMA=y [PATCH 02/04] iommu/ipmmu-vmsa: Break out utlb parsing code [PATCH 03/04] iommu/ipmmu-vmsa: Break out domain allocation code [PATCH 04/04] iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops This series updates the IPMMU driver with CONFIG_IOMMU_DMA=y support which is present in mainline for 64-bit ARM while experimental support has been posted for 32-bit ARM thanks to Marek Szyprowski: [RFC 0/3] Unify IOMMU-based DMA-mapping code for ARM and ARM64 Most of the patches in this series based on code earlier included in the series below but has been reworked to also fit on 32-bit ARM: [PATCH/RFC 00/10] iommu/ipmmu-vmsa: Experimental r8a7795 support Signed-off-by: Magnus Damm <damm+renesas@opensource.se> --- Built on top of next-20160315 Depends on [PATCH v2 00/04] iommu/ipmmu-vmsa: IPMMU multi-arch update V2 drivers/iommu/ipmmu-vmsa.c | 238 ++++++++++++++++++++++++++++++++------------ 1 file changed, 174 insertions(+), 64 deletions(-)
[toc] | [next] | [standalone]
| From | Magnus Damm <magnus.damm@gmail.com> |
|---|---|
| Date | 2016-03-15 18:10 +0100 |
| Subject | [PATCH 03/04] iommu/ipmmu-vmsa: Break out domain allocation code |
| Message-ID | <rd0DN-4Yj-35@gated-at.bofh.it> |
| In reply to | #1358151 |
From: Magnus Damm <damm+renesas@opensource.se>
Break out the domain allocation code into a separate function.
This is preparation for future code sharing.
Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---
drivers/iommu/ipmmu-vmsa.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
--- 0014/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2015-12-14 19:23:22.210513000 +0900
@@ -457,13 +457,10 @@ static irqreturn_t ipmmu_domain_irq(int
* IOMMU Operations
*/
-static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
+static struct iommu_domain *__ipmmu_domain_alloc(unsigned type)
{
struct ipmmu_vmsa_domain *domain;
- if (type != IOMMU_DOMAIN_UNMANAGED)
- return NULL;
-
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
if (!domain)
return NULL;
@@ -473,6 +470,14 @@ static struct iommu_domain *ipmmu_domain
return &domain->io_domain;
}
+static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
+{
+ if (type != IOMMU_DOMAIN_UNMANAGED)
+ return NULL;
+
+ return __ipmmu_domain_alloc(type);
+}
+
static void ipmmu_domain_free(struct iommu_domain *io_domain)
{
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
[toc] | [prev] | [next] | [standalone]
| From | Magnus Damm <magnus.damm@gmail.com> |
|---|---|
| Date | 2016-03-15 18:10 +0100 |
| Subject | [PATCH 02/04] iommu/ipmmu-vmsa: Break out utlb parsing code |
| Message-ID | <rd0DN-4Yj-33@gated-at.bofh.it> |
| In reply to | #1358151 |
From: Magnus Damm <damm+renesas@opensource.se>
Break out the utlb parsing code and dev_data allocation into a
separate function. This is preparation for future code sharing.
Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---
drivers/iommu/ipmmu-vmsa.c | 125 ++++++++++++++++++++++++--------------------
1 file changed, 70 insertions(+), 55 deletions(-)
--- 0008/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2016-03-15 21:08:20.180513000 +0900
@@ -619,6 +619,69 @@ static int ipmmu_find_utlbs(struct ipmmu
return 0;
}
+static int ipmmu_init_platform_device(struct device *dev,
+ struct iommu_group *group)
+{
+ struct ipmmu_vmsa_archdata *archdata;
+ struct ipmmu_vmsa_device *mmu;
+ unsigned int *utlbs;
+ unsigned int i;
+ int num_utlbs;
+ int ret = -ENODEV;
+
+ /* Find the master corresponding to the device. */
+
+ num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
+ "#iommu-cells");
+ if (num_utlbs < 0)
+ return -ENODEV;
+
+ utlbs = kcalloc(num_utlbs, sizeof(*utlbs), GFP_KERNEL);
+ if (!utlbs)
+ return -ENOMEM;
+
+ spin_lock(&ipmmu_devices_lock);
+
+ list_for_each_entry(mmu, &ipmmu_devices, list) {
+ ret = ipmmu_find_utlbs(mmu, dev, utlbs, num_utlbs);
+ if (!ret) {
+ /*
+ * TODO Take a reference to the MMU to protect
+ * against device removal.
+ */
+ break;
+ }
+ }
+
+ spin_unlock(&ipmmu_devices_lock);
+
+ if (ret < 0)
+ goto error;
+
+ for (i = 0; i < num_utlbs; ++i) {
+ if (utlbs[i] >= mmu->num_utlbs) {
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+
+ archdata = kzalloc(sizeof(*archdata), GFP_KERNEL);
+ if (!archdata) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ archdata->mmu = mmu;
+ archdata->utlbs = utlbs;
+ archdata->num_utlbs = num_utlbs;
+ dev->archdata.iommu = archdata;
+ return 0;
+
+error:
+ kfree(utlbs);
+ return ret;
+}
+
#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
static int ipmmu_map_attach(struct device *dev, struct ipmmu_vmsa_device *mmu)
{
@@ -675,13 +738,8 @@ static inline void ipmmu_release_mapping
static int ipmmu_add_device(struct device *dev)
{
- struct ipmmu_vmsa_archdata *archdata;
- struct ipmmu_vmsa_device *mmu;
- struct iommu_group *group = NULL;
- unsigned int *utlbs;
- unsigned int i;
- int num_utlbs;
- int ret = -ENODEV;
+ struct iommu_group *group;
+ int ret;
if (dev->archdata.iommu) {
dev_warn(dev, "IOMMU driver already assigned to device %s\n",
@@ -689,42 +747,6 @@ static int ipmmu_add_device(struct devic
return -EINVAL;
}
- /* Find the master corresponding to the device. */
-
- num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
- "#iommu-cells");
- if (num_utlbs < 0)
- return -ENODEV;
-
- utlbs = kcalloc(num_utlbs, sizeof(*utlbs), GFP_KERNEL);
- if (!utlbs)
- return -ENOMEM;
-
- spin_lock(&ipmmu_devices_lock);
-
- list_for_each_entry(mmu, &ipmmu_devices, list) {
- ret = ipmmu_find_utlbs(mmu, dev, utlbs, num_utlbs);
- if (!ret) {
- /*
- * TODO Take a reference to the MMU to protect
- * against device removal.
- */
- break;
- }
- }
-
- spin_unlock(&ipmmu_devices_lock);
-
- if (ret < 0)
- return -ENODEV;
-
- for (i = 0; i < num_utlbs; ++i) {
- if (utlbs[i] >= mmu->num_utlbs) {
- ret = -EINVAL;
- goto error;
- }
- }
-
/* Create a device group and add the device to it. */
group = iommu_group_alloc();
if (IS_ERR(group)) {
@@ -742,27 +764,20 @@ static int ipmmu_add_device(struct devic
goto error;
}
- archdata = kzalloc(sizeof(*archdata), GFP_KERNEL);
- if (!archdata) {
- ret = -ENOMEM;
+ ret = ipmmu_init_platform_device(dev, group);
+ if (ret < 0) {
+ dev_err(dev, "Failed to init platform device\n");
goto error;
}
- archdata->mmu = mmu;
- archdata->utlbs = utlbs;
- archdata->num_utlbs = num_utlbs;
- dev->archdata.iommu = archdata;
-
- ret = ipmmu_map_attach(dev, mmu);
+ ret = ipmmu_map_attach(dev, ((struct ipmmu_vmsa_archdata *)
+ dev->archdata.iommu)->mmu);
if (ret < 0)
goto error;
return 0;
error:
- kfree(dev->archdata.iommu);
- kfree(utlbs);
-
dev->archdata.iommu = NULL;
if (!IS_ERR_OR_NULL(group))
[toc] | [prev] | [next] | [standalone]
| From | Magnus Damm <magnus.damm@gmail.com> |
|---|---|
| Date | 2016-03-15 18:10 +0100 |
| Subject | [PATCH 04/04] iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops |
| Message-ID | <rd0DO-4Yj-41@gated-at.bofh.it> |
| In reply to | #1358151 |
From: Magnus Damm <damm+renesas@opensource.se>
Introduce a new set of iommu_ops suitable for 64-bit ARM
as well as 32-bit ARM when CONFIG_IOMMU_DMA=y. The ->of_xlate()
callback is needed by the code exported by of_iommu.h and
it is wrapped in #ifdefs to also compile of x86_64.
Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---
drivers/iommu/ipmmu-vmsa.c | 94 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 92 insertions(+), 2 deletions(-)
--- 0011/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2016-03-16 01:35:06.990513000 +0900
@@ -10,6 +10,7 @@
#include <linux/bitmap.h>
#include <linux/delay.h>
+#include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/export.h>
@@ -804,7 +805,7 @@ static void ipmmu_remove_device(struct d
dev->archdata.iommu = NULL;
}
-static const struct iommu_ops ipmmu_ops = {
+static const struct iommu_ops __maybe_unused ipmmu_ops = {
.domain_alloc = ipmmu_domain_alloc,
.domain_free = ipmmu_domain_free,
.attach_dev = ipmmu_attach_device,
@@ -818,6 +819,92 @@ static const struct iommu_ops ipmmu_ops
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
};
+static struct iommu_domain *ipmmu_domain_alloc_dma(unsigned type)
+{
+ struct iommu_domain *io_domain;
+
+ if (type != IOMMU_DOMAIN_DMA)
+ return NULL;
+
+ io_domain = __ipmmu_domain_alloc(type);
+ if (io_domain)
+ iommu_get_dma_cookie(io_domain);
+
+ return io_domain;
+}
+
+static void ipmmu_domain_free_dma(struct iommu_domain *io_domain)
+{
+ iommu_put_dma_cookie(io_domain);
+ ipmmu_domain_free(io_domain);
+}
+
+static int ipmmu_add_device_dma(struct device *dev)
+{
+ struct iommu_group *group;
+
+ /* only accept devices with iommus property */
+ if (of_count_phandle_with_args(dev->of_node, "iommus",
+ "#iommu-cells") < 0)
+ return -ENODEV;
+
+ group = iommu_group_get_for_dev(dev);
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+
+ return 0;
+}
+
+static void ipmmu_remove_device_dma(struct device *dev)
+{
+ iommu_group_remove_device(dev);
+}
+
+static struct iommu_group *ipmmu_device_group_dma(struct device *dev)
+{
+ struct iommu_group *group;
+ int ret;
+
+ group = generic_device_group(dev);
+ if (IS_ERR(group))
+ return group;
+
+ ret = ipmmu_init_platform_device(dev, group);
+ if (ret) {
+ iommu_group_put(group);
+ group = ERR_PTR(ret);
+ }
+
+ return group;
+}
+
+#ifdef CONFIG_OF_IOMMU
+static int ipmmu_of_xlate_dma(struct device *dev,
+ struct of_phandle_args *spec)
+{
+ /* dummy callback to satisfy of_iommu_configure() */
+ return 0;
+}
+#endif
+
+static const struct iommu_ops __maybe_unused ipmmu_ops_dma = {
+ .domain_alloc = ipmmu_domain_alloc_dma,
+ .domain_free = ipmmu_domain_free_dma,
+ .attach_dev = ipmmu_attach_device,
+ .detach_dev = ipmmu_detach_device,
+ .map = ipmmu_map,
+ .unmap = ipmmu_unmap,
+ .map_sg = default_iommu_map_sg,
+ .iova_to_phys = ipmmu_iova_to_phys,
+ .add_device = ipmmu_add_device_dma,
+ .remove_device = ipmmu_remove_device_dma,
+ .device_group = ipmmu_device_group_dma,
+ .pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
+#ifdef CONFIG_OF_IOMMU
+ .of_xlate = ipmmu_of_xlate_dma,
+#endif
+};
+
/* -----------------------------------------------------------------------------
* Probe/remove and init
*/
@@ -929,14 +1016,17 @@ static struct platform_driver ipmmu_driv
static int __init ipmmu_init(void)
{
+ const struct iommu_ops *ops;
int ret;
ret = platform_driver_register(&ipmmu_driver);
if (ret < 0)
return ret;
+ ops = IS_ENABLED(CONFIG_IOMMU_DMA) ? &ipmmu_ops_dma : &ipmmu_ops;
+
if (!iommu_present(&platform_bus_type))
- bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+ bus_set_iommu(&platform_bus_type, ops);
return 0;
}
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web