Skip to contentSkip to conversation

Add support for ARM SMMU architectures 1 and 2

PATCH Superseded Will Deacon 9 participants 49 messages Jun 10, 2013 – Jun 28, 2013 2 messages not in the archive

Subsystems (7)

v1 of 12 Superseded Latest is v12 →

lore
Share & tools
lore
#0 lore raw

cover Add support for ARM SMMU architectures 1 and 2

Hi all,

This patch series adds support for ARM's SMMU architectures 1 and 2 to Linux. It has been tested with models of MMU-400 (AArch32) and MMU-500 (AArch32 and AArch64) coupled with four PL330s doing memory-to-memory DMA.

The first six patches are preparatory and fix problems that I encountered whilst trying to use both the ARM IOMMU API and the PL330 driver. The remaining patches add the device-tree binding, previously discussed at:

http://lists.infradead.org/pipermail/linux-arm-kernel/2013-April/160663.html
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-April/162945.html

as well as the driver implementation and an update to the MAINTAINERS file.

The driver is written only with single-stage (possibly stage 2), LPAE, non-secure translation in mind. Nested translation may of course be added later via KVM, but that will require some changes to the core IOMMU API in Linux. Both arm and arm64 are supported, as well as chained SMMUs, although we only install our translation in the SMMU furthest from the device. We're also currently limited in our IPA size, due to input size restrictions at stage 2. This can be resolved later by munging about in the page table allocation code, where we currently re-use parts of the CPU page table helpers.

Read and write protection is supported as far as the pte formats allow (i.e. no write-only at stage-1) and memory attributes are either normal, non-cacheable (default) or normal, cacheable, write-back, write-allocate. TLB broadcasting is not used for either ASIDs (since we don't support user tables for DMA in Linux) or VMIDs (which are instead used to tag address spaces in order to limit the scope of TLB invalidation operations).

Both 4k and 64k (AArch64 only) pages are supported, with the contiguous hint bit being used in the pte entries for mappings that allow it.

Support for stream-indexing and non-coherent table walking is provided, but untested.

All comments welcome,

Will

Will Deacon (9):
dma: pl330: rip out broken, redundant ID probing
dma: pl330: use dma_addr_t for describing bus addresses
ARM: dma-mapping: convert DMA direction into IOMMU protection
attributes
ARM: dma-mapping: NULLify dev->archdata.mapping pointer on detach
arm64: pgtable: use pte_index instead of __pte_index
arm64: device: add iommu pointer to device archdata
documentation: iommu: add description of ARM System MMU binding
iommu: add support for ARM Ltd. System MMU architecture
MAINTAINERS: add entry for ARM system MMU driver

 .../devicetree/bindings/iommu/arm,smmu.txt         |   70 +
 MAINTAINERS                                        |    6 +
 arch/arm/mm/dma-mapping.c                          |   20 +-
 arch/arm64/include/asm/device.h                    |    3 +
 arch/arm64/include/asm/pgtable.h                   |    4 +-
 drivers/dma/pl330.c                                |   29 +-
 drivers/iommu/Kconfig                              |   13 +
 drivers/iommu/Makefile                             |    1 +
 drivers/iommu/arm-smmu.c                           | 1965 ++++++++++++++++++++
 9 files changed, 2081 insertions(+), 30 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iommu/arm,smmu.txt
 create mode 100644 drivers/iommu/arm-smmu.c
Signature · 1 line
1.8.2.2
#1 lore raw

PATCH 1/9 dma: pl330: rip out broken, redundant ID probing

The PL330 driver probes the peripheral and primecell IDs of the device to make sure that it is indeed an AMBA PL330. However, it does this by making byte accesses to a device mapping of the word-aligned ID registers, which is either UNPREDICTABLE or generates an alignment fault (depending on the presence of the virtualisation extensions).

Rather than fix this code, we can actually rip most of it out and let the AMBA bus driver correctly do the probing for us.

Cc Jassi Brar <[email protected]>
Cc Vinod Koul <[email protected]>
---
 drivers/dma/pl330.c | 27 +++------------------------
 1 file changed, 3 insertions(+), 24 deletions(-)
drivers/dma/pl330.c +3 -24
index 24e0754..22e2a8f 100644
@@ -157,7 +157,6 @@ enum pl330_reqtype {
 #define PERIPH_REV_R0P0		0
 #define PERIPH_REV_R1P0		1
 #define PERIPH_REV_R1P1		2
-#define PCELL_ID		0xff0
 
 #define CR0_PERIPH_REQ_SET	(1 << 0)
 #define CR0_BOOT_EN_SET		(1 << 1)
@@ -193,8 +192,6 @@ enum pl330_reqtype {
 #define INTEG_CFG		0x0
 #define PERIPH_ID_VAL		((PART << 0) | (DESIGNER << 12))
 
-#define PCELL_ID_VAL		0xb105f00d
-
 #define PL330_STATE_STOPPED		(1 << 0)
 #define PL330_STATE_EXECUTING		(1 << 1)
 #define PL330_STATE_WFE			(1 << 2)
@@ -292,7 +289,6 @@ static unsigned cmd_line;
 /* Populated by the PL330 core driver for DMA API driver's info */
 struct pl330_config {
 	u32	periph_id;
-	u32	pcell_id;
 #define DMAC_MODE_NS	(1 << 0)
 	unsigned int	mode;
 	unsigned int	data_bus_width:10; /* In number of bits */
@@ -650,19 +646,6 @@ static inline bool _manager_ns(struct pl330_thread *thrd)
 	return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false;
 }
 
-static inline u32 get_id(struct pl330_info *pi, u32 off)
-{
-	void __iomem *regs = pi->base;
-	u32 id = 0;
-
-	id |= (readb(regs + off + 0x0) << 0);
-	id |= (readb(regs + off + 0x4) << 8);
-	id |= (readb(regs + off + 0x8) << 16);
-	id |= (readb(regs + off + 0xc) << 24);
-
-	return id;
-}
-
 static inline u32 get_revision(u32 periph_id)
 {
 	return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK;
@@ -1986,9 +1969,6 @@ static void read_dmac_config(struct pl330_info *pi)
 	pi->pcfg.num_events = val;
 
 	pi->pcfg.irq_ns = readl(regs + CR3);
-
-	pi->pcfg.periph_id = get_id(pi, PERIPH_ID);
-	pi->pcfg.pcell_id = get_id(pi, PCELL_ID);
 }
 
 static inline void _reset_thread(struct pl330_thread *thrd)
@@ -2098,10 +2078,8 @@ static int pl330_add(struct pl330_info *pi)
 	regs = pi->base;
 
 	/* Check if we can handle this DMAC */
-	if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL
-	   || get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
-		dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
-			get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID));
+	if ((pi->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) {
+		dev_err(pi->dev, "PERIPH_ID 0x%x !\n", pi->pcfg.periph_id);
 		return -EINVAL;
 	}
 
@@ -2922,6 +2900,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	if (ret)
 		return ret;
 
+	pi->pcfg.periph_id = adev->periphid;
 	ret = pl330_add(pi);
 	if (ret)
 		goto probe_err1;
Signature · 1 line
1.8.2.2

A message that is not in the archive (sent off-list or not yet received): 1370889285-22799-2-git-send-email-will.deacon-5wv7dgnIgG8@public.gmane.org

#3 lore raw

Re: [PATCH 1/9] dma: pl330: rip out broken, redundant ID probing

Quoted 10 lines · Will Deacon

The PL330 driver probes the peripheral and primecell IDs of the device to make sure that it is indeed an AMBA PL330. However, it does this by making byte accesses to a device mapping of the word-aligned ID registers, which is either UNPREDICTABLE or generates an alignment fault (depending on the presence of the virtualisation extensions).

Rather than fix this code, we can actually rip most of it out and let the AMBA bus driver correctly do the probing for us.

#4 lore raw

PATCH 1/9 dma: pl330: rip out broken, redundant ID probing

In reply to Will Deacon
Quoted 9 lines · Will Deacon

The PL330 driver probes the peripheral and primecell IDs of the device to make sure that it is indeed an AMBA PL330. However, it does this by making byte accesses to a device mapping of the word-aligned ID registers, which is either UNPREDICTABLE or generates an alignment fault (depending on the presence of the virtualisation extensions).

Rather than fix this code, we can actually rip most of it out and let the AMBA bus driver correctly do the probing for us.

#5 lore raw

PATCH 1/9 dma: pl330: rip out broken, redundant ID probing

Quoted 11 lines · Jassi Brar
Quoted 9 lines · Will Deacon

The PL330 driver probes the peripheral and primecell IDs of the device to make sure that it is indeed an AMBA PL330. However, it does this by making byte accesses to a device mapping of the word-aligned ID registers, which is either UNPREDICTABLE or generates an alignment fault (depending on the presence of the virtualisation extensions).

Rather than fix this code, we can actually rip most of it out and let the AMBA bus driver correctly do the probing for us.

Thanks for the acks Jassi!

Will

#6 lore raw

PATCH 1/9 dma: pl330: rip out broken, redundant ID probing

In reply to Will Deacon
Quoted 6 lines · Will Deacon

The PL330 driver probes the peripheral and primecell IDs of the device to make sure that it is indeed an AMBA PL330. However, it does this by making byte accesses to a device mapping of the word-aligned ID registers, which is either UNPREDICTABLE or generates an alignment fault (depending on the presence of the virtualisation extensions).

Quoted 6 lines

Rather than fix this code, we can actually rip most of it out and let the AMBA bus driver correctly do the probing for us.

Cc Jassi Brar <[email protected]>
Cc Vinod Koul <[email protected]>

Right, device drivers shouldn't be cosing their own primecell ID parser.

Quoted 92 lines
---
 drivers/dma/pl330.c | 27 +++------------------------
 1 file changed, 3 insertions(+), 24 deletions(-)
drivers/dma/pl330.c +3 -24
index 24e0754..22e2a8f 100644
@@ -157,7 +157,6 @@ enum pl330_reqtype {
 #define PERIPH_REV_R0P0		0
 #define PERIPH_REV_R1P0		1
 #define PERIPH_REV_R1P1		2
-#define PCELL_ID		0xff0
 
 #define CR0_PERIPH_REQ_SET	(1 << 0)
 #define CR0_BOOT_EN_SET		(1 << 1)
@@ -193,8 +192,6 @@ enum pl330_reqtype {
 #define INTEG_CFG		0x0
 #define PERIPH_ID_VAL		((PART << 0) | (DESIGNER << 12))
 
-#define PCELL_ID_VAL		0xb105f00d
-
 #define PL330_STATE_STOPPED		(1 << 0)
 #define PL330_STATE_EXECUTING		(1 << 1)
 #define PL330_STATE_WFE			(1 << 2)
@@ -292,7 +289,6 @@ static unsigned cmd_line;
 /* Populated by the PL330 core driver for DMA API driver's info */
 struct pl330_config {
 	u32	periph_id;
-	u32	pcell_id;
 #define DMAC_MODE_NS	(1 << 0)
 	unsigned int	mode;
 	unsigned int	data_bus_width:10; /* In number of bits */
@@ -650,19 +646,6 @@ static inline bool _manager_ns(struct pl330_thread *thrd)
 	return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false;
 }
 
-static inline u32 get_id(struct pl330_info *pi, u32 off)
-{
-	void __iomem *regs = pi->base;
-	u32 id = 0;
-
-	id |= (readb(regs + off + 0x0) << 0);
-	id |= (readb(regs + off + 0x4) << 8);
-	id |= (readb(regs + off + 0x8) << 16);
-	id |= (readb(regs + off + 0xc) << 24);
-
-	return id;
-}
-
 static inline u32 get_revision(u32 periph_id)
 {
 	return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK;
@@ -1986,9 +1969,6 @@ static void read_dmac_config(struct pl330_info *pi)
 	pi->pcfg.num_events = val;
 
 	pi->pcfg.irq_ns = readl(regs + CR3);
-
-	pi->pcfg.periph_id = get_id(pi, PERIPH_ID);
-	pi->pcfg.pcell_id = get_id(pi, PCELL_ID);
 }
 
 static inline void _reset_thread(struct pl330_thread *thrd)
@@ -2098,10 +2078,8 @@ static int pl330_add(struct pl330_info *pi)
 	regs = pi->base;
 
 	/* Check if we can handle this DMAC */
-	if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL
-	   || get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
-		dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
-			get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID));
+	if ((pi->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) {
+		dev_err(pi->dev, "PERIPH_ID 0x%x !\n", pi->pcfg.periph_id);
 		return -EINVAL;
 	}
 
@@ -2922,6 +2900,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	if (ret)
 		return ret;
 
+	pi->pcfg.periph_id = adev->periphid;
 	ret = pl330_add(pi);
 	if (ret)
 		goto probe_err1;
Signature · 7 lines
1.8.2.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 2 lines
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies, Ltd.
Applied
#7 lore raw

PATCH 1/9 dma: pl330: rip out broken, redundant ID probing

In reply to Will Deacon
Quoted 6 lines · Will Deacon

The PL330 driver probes the peripheral and primecell IDs of the device to make sure that it is indeed an AMBA PL330. However, it does this by making byte accesses to a device mapping of the word-aligned ID registers, which is either UNPREDICTABLE or generates an alignment fault (depending on the presence of the virtualisation extensions).

Quoted 6 lines

Rather than fix this code, we can actually rip most of it out and let the AMBA bus driver correctly do the probing for us.

Cc Jassi Brar <[email protected]>
Cc Vinod Koul <[email protected]>

Applied, thanks

--
~Vinod

Quoted 87 lines
---
 drivers/dma/pl330.c | 27 +++------------------------
 1 file changed, 3 insertions(+), 24 deletions(-)
drivers/dma/pl330.c +3 -24
index 24e0754..22e2a8f 100644
@@ -157,7 +157,6 @@ enum pl330_reqtype {
 #define PERIPH_REV_R0P0		0
 #define PERIPH_REV_R1P0		1
 #define PERIPH_REV_R1P1		2
-#define PCELL_ID		0xff0
 
 #define CR0_PERIPH_REQ_SET	(1 << 0)
 #define CR0_BOOT_EN_SET		(1 << 1)
@@ -193,8 +192,6 @@ enum pl330_reqtype {
 #define INTEG_CFG		0x0
 #define PERIPH_ID_VAL		((PART << 0) | (DESIGNER << 12))
 
-#define PCELL_ID_VAL		0xb105f00d
-
 #define PL330_STATE_STOPPED		(1 << 0)
 #define PL330_STATE_EXECUTING		(1 << 1)
 #define PL330_STATE_WFE			(1 << 2)
@@ -292,7 +289,6 @@ static unsigned cmd_line;
 /* Populated by the PL330 core driver for DMA API driver's info */
 struct pl330_config {
 	u32	periph_id;
-	u32	pcell_id;
 #define DMAC_MODE_NS	(1 << 0)
 	unsigned int	mode;
 	unsigned int	data_bus_width:10; /* In number of bits */
@@ -650,19 +646,6 @@ static inline bool _manager_ns(struct pl330_thread *thrd)
 	return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false;
 }
 
-static inline u32 get_id(struct pl330_info *pi, u32 off)
-{
-	void __iomem *regs = pi->base;
-	u32 id = 0;
-
-	id |= (readb(regs + off + 0x0) << 0);
-	id |= (readb(regs + off + 0x4) << 8);
-	id |= (readb(regs + off + 0x8) << 16);
-	id |= (readb(regs + off + 0xc) << 24);
-
-	return id;
-}
-
 static inline u32 get_revision(u32 periph_id)
 {
 	return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK;
@@ -1986,9 +1969,6 @@ static void read_dmac_config(struct pl330_info *pi)
 	pi->pcfg.num_events = val;
 
 	pi->pcfg.irq_ns = readl(regs + CR3);
-
-	pi->pcfg.periph_id = get_id(pi, PERIPH_ID);
-	pi->pcfg.pcell_id = get_id(pi, PCELL_ID);
 }
 
 static inline void _reset_thread(struct pl330_thread *thrd)
@@ -2098,10 +2078,8 @@ static int pl330_add(struct pl330_info *pi)
 	regs = pi->base;
 
 	/* Check if we can handle this DMAC */
-	if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL
-	   || get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
-		dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
-			get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID));
+	if ((pi->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) {
+		dev_err(pi->dev, "PERIPH_ID 0x%x !\n", pi->pcfg.periph_id);
 		return -EINVAL;
 	}
 
@@ -2922,6 +2900,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	if (ret)
 		return ret;
 
+	pi->pcfg.periph_id = adev->periphid;
 	ret = pl330_add(pi);
 	if (ret)
 		goto probe_err1;
Signature · 1 line
1.8.2.2
#8 lore raw

PATCH 2/9 dma: pl330: use dma_addr_t for describing bus addresses

In reply to Will Deacon

The microcode bus address (pl330_dmac.mcode_bus) is currently a u32, which fails to compile when building on a system with 64-bit bus addresses.

This patch uses dma_addr_t to represent the address instead.

Cc Jassi Brar <[email protected]>
Cc Vinod Koul <[email protected]>
---
 drivers/dma/pl330.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/pl330.c +1 -1
index 22e2a8f..f1bc593 100644
@@ -501,7 +501,7 @@ struct pl330_dmac {
 	/* Maximum possible events/irqs */
 	int			events[32];
 	/* BUS address of MicroCode buffer */
-	u32			mcode_bus;
+	dma_addr_t		mcode_bus;
 	/* CPU address of MicroCode buffer */
 	void			*mcode_cpu;
 	/* List of all Channel threads */
Signature · 1 line
1.8.2.2

A message that is not in the archive (sent off-list or not yet received): 1370889285-22799-3-git-send-email-will.deacon-5wv7dgnIgG8@public.gmane.org

#10 lore raw

Re: [PATCH 2/9] dma: pl330: use dma_addr_t for describing bus addresses

Quoted 33 lines · Will Deacon

The microcode bus address (pl330_dmac.mcode_bus) is currently a u32, which fails to compile when building on a system with 64-bit bus addresses.

This patch uses dma_addr_t to represent the address instead.

Cc Jassi Brar <[email protected]>
Cc Vinod Koul <[email protected]>
---
 drivers/dma/pl330.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/pl330.c +1 -2
index 22e2a8f..f1bc593 100644
@@ -501,7 +501,7 @@ struct pl330_dmac {
        /* Maximum possible events/irqs */
        int                     events[32];
        /* BUS address of MicroCode buffer */
-       u32                     mcode_bus;
+       dma_addr_t              mcode_bus;
        /* CPU address of MicroCode buffer */
        void                    *mcode_cpu;
        /* List of all Channel threads */
--

1.8.2.2

Signature · 3 lines
Linaro.org │ Open source software for ARM SoCs | Follow Linaro
http://facebook.com/pages/Linaro/155974581091106  -
http://twitter.com/#!/linaroorg - http://linaro.org/linaro-blog
Applied
#11 lore raw

PATCH 2/9 dma: pl330: use dma_addr_t for describing bus addresses

Quoted 6 lines · Jassi Brar
Quoted 4 lines · Will Deacon

The microcode bus address (pl330_dmac.mcode_bus) is currently a u32, which fails to compile when building on a system with 64-bit bus addresses.

Quoted 8 lines
Quoted 8 lines

This patch uses dma_addr_t to represent the address instead.

Cc Jassi Brar <[email protected]>
Cc Vinod Koul <[email protected]>

Applied, thanks

--
~Vinod

Quoted 27 lines
Quoted 21 lines
---
 drivers/dma/pl330.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/pl330.c +1 -2
index 22e2a8f..f1bc593 100644
@@ -501,7 +501,7 @@ struct pl330_dmac {
        /* Maximum possible events/irqs */
        int                     events[32];
        /* BUS address of MicroCode buffer */
-       u32                     mcode_bus;
+       dma_addr_t              mcode_bus;
        /* CPU address of MicroCode buffer */
        void                    *mcode_cpu;
        /* List of all Channel threads */
--

1.8.2.2

Signature · 3 lines
Linaro.org ? Open source software for ARM SoCs | Follow Linaro
http://facebook.com/pages/Linaro/155974581091106  -
http://twitter.com/#!/linaroorg - http://linaro.org/linaro-blog
#12 lore raw

PATCH 2/9 dma: pl330: use dma_addr_t for describing bus addresses

In reply to Will Deacon
Quoted 6 lines · Will Deacon

The microcode bus address (pl330_dmac.mcode_bus) is currently a u32, which fails to compile when building on a system with 64-bit bus addresses.

This patch uses dma_addr_t to represent the address instead.

#13 lore raw

PATCH 2/9 dma: pl330: use dma_addr_t for describing bus addresses

In reply to Will Deacon
Quoted 9 lines · Will Deacon

The microcode bus address (pl330_dmac.mcode_bus) is currently a u32, which fails to compile when building on a system with 64-bit bus addresses.

This patch uses dma_addr_t to represent the address instead.

Cc Jassi Brar <[email protected]>
Cc Vinod Koul <[email protected]>
Quoted 24 lines
---
 drivers/dma/pl330.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/pl330.c +1 -1
index 22e2a8f..f1bc593 100644
@@ -501,7 +501,7 @@ struct pl330_dmac {
 	/* Maximum possible events/irqs */
 	int			events[32];
 	/* BUS address of MicroCode buffer */
-	u32			mcode_bus;
+	dma_addr_t		mcode_bus;
 	/* CPU address of MicroCode buffer */
 	void			*mcode_cpu;
 	/* List of all Channel threads */
Signature · 6 lines
1.8.2.2

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss at lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss
Signature · 2 lines
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies, Ltd.
#14 lore raw

PATCH 3/9 ARM: dma-mapping: convert DMA direction into IOMMU protection attributes

In reply to Will Deacon

IOMMU mappings take a prot parameter, identifying the protection bits to enforce on the newly created mapping (READ or WRITE). The ARM dma-mapping framework currently just passes 0 as the prot argument, resulting in faulting mappings.

This patch infers the protection attributes based on the direction of the DMA transfer.

Cc Marek Szyprowski <[email protected]>
---
 arch/arm/mm/dma-mapping.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)
arch/arm/mm/dma-mapping.c +16 -2
index 6fb80cf..d119de7 100644
@@ -1636,13 +1636,27 @@ static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p
 {
 	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
 	dma_addr_t dma_addr;
-	int ret, len = PAGE_ALIGN(size + offset);
+	int ret, prot, len = PAGE_ALIGN(size + offset);
 
 	dma_addr = __alloc_iova(mapping, len);
 	if (dma_addr == DMA_ERROR_CODE)
 		return dma_addr;
 
-	ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, 0);
+	switch (dir) {
+	case DMA_BIDIRECTIONAL:
+		prot = IOMMU_READ | IOMMU_WRITE;
+		break;
+	case DMA_TO_DEVICE:
+		prot = IOMMU_READ;
+		break;
+	case DMA_FROM_DEVICE:
+		prot = IOMMU_WRITE;
+		break;
+	default:
+		prot = 0;
+	}
+
+	ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, prot);
 	if (ret < 0)
 		goto fail;
 
Signature · 1 line
1.8.2.2
#15 lore raw

PATCH 3/9 ARM: dma-mapping: convert DMA direction into IOMMU protection attributes

Hello,

Quoted 10 lines · Will Deacon

IOMMU mappings take a prot parameter, identifying the protection bits to enforce on the newly created mapping (READ or WRITE). The ARM dma-mapping framework currently just passes 0 as the prot argument, resulting in faulting mappings.

This patch infers the protection attributes based on the direction of the DMA transfer.

Cc Marek Szyprowski <[email protected]>

Thanks for fixing this issue. Could I take this patch to my dma-mapping tree with other dma-mapping changes I've collected recently or do you want my ack and push it via other tree?

Quoted 28 lines
---
  arch/arm/mm/dma-mapping.c | 18 ++++++++++++++++--
  1 file changed, 16 insertions(+), 2 deletions(-)
arch/arm/mm/dma-mapping.c +9 -2
index 6fb80cf..d119de7 100644
@@ -1636,13 +1636,27 @@ static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p
  {
  	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
  	dma_addr_t dma_addr;
-	int ret, len = PAGE_ALIGN(size + offset);
+	int ret, prot, len = PAGE_ALIGN(size + offset);
 
  	dma_addr = __alloc_iova(mapping, len);
  	if (dma_addr == DMA_ERROR_CODE)
  		return dma_addr;
 
-	ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, 0);
+	switch (dir) {
+	case DMA_BIDIRECTIONAL:
+		prot = IOMMU_READ | IOMMU_WRITE;
+		break;
+	case DMA_TO_DEVICE:
+		prot = IOMMU_READ;
+		break;
+	case DMA_FROM_DEVICE:

arch/arm/mm/dma-mapping.c static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p · line 1662

Quoted 10 lines
arch/arm/mm/dma-mapping.c +7 -0
+		prot = IOMMU_WRITE;
+		break;
+	default:
+		prot = 0;
+	}
+
+	ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, prot);
  	if (ret < 0)
  		goto fail;
 

Best regards

Signature · 2 lines
Marek Szyprowski
Samsung R&D Institute Poland
#16 lore raw

PATCH 3/9 ARM: dma-mapping: convert DMA direction into IOMMU protection attributes

Quoted 1 line · Marek Szyprowski

Hello,

Hi Marek,

Quoted 9 lines · Will Deacon
Quoted 8 lines

IOMMU mappings take a prot parameter, identifying the protection bits to enforce on the newly created mapping (READ or WRITE). The ARM dma-mapping framework currently just passes 0 as the prot argument, resulting in faulting mappings.

This patch infers the protection attributes based on the direction of the DMA transfer.

Quoted 6 lines
Quoted 2 lines
Cc Marek Szyprowski <[email protected]>

Thanks for fixing this issue. Could I take this patch to my dma-mapping tree with other dma-mapping changes I've collected recently or do you want my ack and push it via other tree?

Please, feel free to take it via the dma-mapping tree! That's probably the best route for it and there's nothing that really depends on it anyway.

Cheers,

Will

#17 lore raw

PATCH 3/9 ARM: dma-mapping: convert DMA direction into IOMMU protection attributes

Hello,

Quoted 17 lines · Will Deacon
Quoted 1 line · Marek Szyprowski

Hello,

Hi Marek,

Quoted 12 lines · Will Deacon
Quoted 10 lines

IOMMU mappings take a prot parameter, identifying the protection bits to enforce on the newly created mapping (READ or WRITE). The ARM dma-mapping framework currently just passes 0 as the prot argument, resulting in faulting mappings.

This patch infers the protection attributes based on the direction of the DMA transfer.

Cc Marek Szyprowski <[email protected]>
Quoted 6 lines
Quoted 3 lines

Thanks for fixing this issue. Could I take this patch to my dma-mapping tree with other dma-mapping changes I've collected recently or do you want my ack and push it via other tree?

Please, feel free to take it via the dma-mapping tree! That's probably the best route for it and there's nothing that really depends on it anyway.

Ok, thank I will put it on my tree. Thanks for your patches!

Best regards

Signature · 2 lines
Marek Szyprowski
Samsung R&D Institute Poland
#18 lore raw

PATCH 3/9 ARM: dma-mapping: convert DMA direction into IOMMU protection attributes

In reply to Will Deacon

Hi Will,

On Mon, 10 Jun 2013 20:34:39 +0200
Will Deacon <[email protected]> wrote:
...

Quoted 17 lines
arch/arm/mm/dma-mapping.c +6 -2
@@ -1636,13 +1636,27 @@ static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p
 {
 	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
 	dma_addr_t dma_addr;
-	int ret, len = PAGE_ALIGN(size + offset);
+	int ret, prot, len = PAGE_ALIGN(size + offset);
 
 	dma_addr = __alloc_iova(mapping, len);
 	if (dma_addr == DMA_ERROR_CODE)
 		return dma_addr;
 
-	ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, 0);
+	switch (dir) {
+	case DMA_BIDIRECTIONAL:
+		prot = IOMMU_READ | IOMMU_WRITE;
+		break;
+	case DMA_TO_DEVICE:

arch/arm/mm/dma-mapping.c static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p · line 1659

Quoted 10 lines
arch/arm/mm/dma-mapping.c +10 -0
+		prot = IOMMU_READ;
+		break;
+	case DMA_FROM_DEVICE:
+		prot = IOMMU_WRITE;
+		break;
+	default:
+		prot = 0;
+	}
+
+	ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, prot);

Do we need similar changes for map_sg case as well? They still passes '0' as prot.

#19 lore raw

PATCH 3/9 ARM: dma-mapping: convert DMA direction into IOMMU protection attributes

Quoted 1 line · Hiroshi Doyu

Hi Will,

Hi Hiroshi,

Quoted 24 lines

On Mon, 10 Jun 2013 20:34:39 +0200
Will Deacon <[email protected]> wrote:
...

Quoted 21 lines
arch/arm/mm/dma-mapping.c +10 -2
@@ -1636,13 +1636,27 @@ static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p
 {
 	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
 	dma_addr_t dma_addr;
-	int ret, len = PAGE_ALIGN(size + offset);
+	int ret, prot, len = PAGE_ALIGN(size + offset);
 
 	dma_addr = __alloc_iova(mapping, len);
 	if (dma_addr == DMA_ERROR_CODE)
 		return dma_addr;
 
-	ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, 0);
+	switch (dir) {
+	case DMA_BIDIRECTIONAL:
+		prot = IOMMU_READ | IOMMU_WRITE;
+		break;
+	case DMA_TO_DEVICE:
+		prot = IOMMU_READ;
+		break;
+	case DMA_FROM_DEVICE:
+		prot = IOMMU_WRITE;
Quoted 8 lines

arch/arm/mm/dma-mapping.c static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p · line 1659

Quoted 6 lines
arch/arm/mm/dma-mapping.c +6 -0
+		break;
+	default:
+		prot = 0;
+	}
+
+	ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, prot);

Do we need similar changes for map_sg case as well? They still passes '0' as prot.

Yes, we could use the same trick there (probably worth moving the logic into a helper function for translating dma_data_direction into IOMMU_* values).

There are also iommu_map calls when allocating DMA buffers, but I think 0 is the right thing to pass there (i.e. no permission until pages have been explicitly mapped). Although, to be honest, I don't see why we need to map the buffer at all when we allocate it.

Will

#20 lore raw

PATCH 3/9 ARM: dma-mapping: convert DMA direction into IOMMU protection attributes

Will Deacon <[email protected]> wrote @ Tue, 25 Jun 2013 13:37:14 +0200:
...

Quoted 9 lines
Quoted 1 line

Do we need similar changes for map_sg case as well? They still passes '0' as prot.

Yes, we could use the same trick there (probably worth moving the logic into a helper function for translating dma_data_direction into IOMMU_* values).

There are also iommu_map calls when allocating DMA buffers, but I think 0 is the right thing to pass there (i.e. no permission until pages have been explicitly mapped). Although, to be honest, I don't see why we need to map the buffer at all when we allocate it.

Yes, I thought too. I have a patch for that as below. If you like, I'll rebase and send for merge with the one which changes dma-mapping.c.

Quoted 1 line

From 699e6bd4fef86383d197775486b47bcbdc594f4a Mon Sep 17 00:00:00 2001

From: Hiroshi Doyu <[email protected]>
Date: Tue, 25 Jun 2013 13:43:29 +0300
Subject: [PATCH 1/2] iommu/core: convert DMA direction into IOMMU protection
attributes

Introduce a new function to convert DMA direction into IOMMU protection attributes.

---
 include/linux/iommu.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
include/linux/iommu.h +15 -0
index 00af00f..ce3be78 100644
@@ -21,11 +21,26 @@
 
 #include <linux/errno.h>
 #include <linux/types.h>
+#include <linux/dma-direction.h>
 
 #define IOMMU_READ	(1)
 #define IOMMU_WRITE	(2)
 #define IOMMU_CACHE	(4) /* DMA cache coherency */
 
+static inline int to_iommu_prot(enum dma_data_direction dir)
+{
+	switch (dir) {
+	case DMA_BIDIRECTIONAL:
+		return IOMMU_READ | IOMMU_WRITE;
+	case DMA_TO_DEVICE:
+		return IOMMU_READ;
+	case DMA_FROM_DEVICE:
+		return IOMMU_WRITE;
+	default:
+		return 0;
+	}
+}
+
 struct iommu_ops;
 struct iommu_group;
 struct bus_type;
Signature · 1 line
1.8.1.5
#21 lore raw

PATCH 3/9 ARM: dma-mapping: convert DMA direction into IOMMU protection attributes

Quoted 7 lines · Hiroshi Doyu

Will Deacon <[email protected]> wrote @ Tue, 25 Jun 2013 13:37:14 +0200:
...

Quoted 5 lines
Quoted 1 line

Do we need similar changes for map_sg case as well? They still passes '0' as prot.

Yes, we could use the same trick there (probably worth moving the logic into a helper function for translating dma_data_direction into IOMMU_* values).

Quoted 8 lines
Quoted 4 lines

There are also iommu_map calls when allocating DMA buffers, but I think 0 is the right thing to pass there (i.e. no permission until pages have been explicitly mapped). Although, to be honest, I don't see why we need to map the buffer at all when we allocate it.

Yes, I thought too. I have a patch for that as below. If you like, I'll rebase and send for merge with the one which changes dma-mapping.c.

Yes, please send the series and I'll take a look. Marek's already picked up my original patch, so it's better if you can base against a stable branch from him.

Will

#22 lore raw

PATCH 4/9 ARM: dma-mapping: NULLify dev->archdata.mapping pointer on detach

In reply to Will Deacon

The current code only clobbers a local variable, so the device is left with a stale mapping pointer.

---
 arch/arm/mm/dma-mapping.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mm/dma-mapping.c +1 -1
index d119de7..10282db 100644
@@ -1921,7 +1921,7 @@ void arm_iommu_detach_device(struct device *dev)
 
 	iommu_detach_device(mapping->domain, dev);
 	kref_put(&mapping->kref, release_iommu_mapping);
-	mapping = NULL;
+	dev->archdata.mapping = NULL;
 	set_dma_ops(dev, NULL);
 
 	pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev));
Signature · 1 line
1.8.2.2
#23 lore raw

PATCH 4/9 ARM: dma-mapping: NULLify dev->archdata.mapping pointer on detach

Hi Will,

Will Deacon <[email protected]> wrote @ Mon, 10 Jun 2013 20:34:40 +0200:

Quoted 2 lines

The current code only clobbers a local variable, so the device is left with a stale mapping pointer.

True. This's my bad. Thanks.

#24 lore raw

PATCH 4/9 ARM: dma-mapping: NULLify dev->archdata.mapping pointer on detach

Quoted 8 lines · Hiroshi Doyu

Hi Will,

Will Deacon <[email protected]> wrote @ Mon, 10 Jun 2013 20:34:40 +0200:

Quoted 2 lines

The current code only clobbers a local variable, so the device is left with a stale mapping pointer.

True. This's my bad. Thanks.

That's alright, it's easy to fix. Mind if I add your ack please?

Will

#25 lore raw

PATCH 4/9 ARM: dma-mapping: NULLify dev->archdata.mapping pointer on detach

Quoted 11 lines · On Tue, 11 Jun 2013 10:50:15 +0200 Will Deacon <[email protected]> wrote:
Quoted 8 lines · Hiroshi Doyu

Hi Will,

Will Deacon <[email protected]> wrote @ Mon, 10 Jun 2013 20:34:40 +0200:

Quoted 2 lines

The current code only clobbers a local variable, so the device is left with a stale mapping pointer.

True. This's my bad. Thanks.

That's alright, it's easy to fix. Mind if I add your ack please?

Feel free to add: Acked-by: Hiroshi Doyu <[email protected]>

#26 lore raw

PATCH 4/9 ARM: dma-mapping: NULLify dev->archdata.mapping pointer on detach

Hello,

Quoted 8 lines · Hiroshi Doyu
Quoted 5 lines · On Tue, 11 Jun 2013 10:50:15 +0200 Will Deacon <[email protected]> wrote:
Quoted 4 lines · Hiroshi Doyu

Hi Will,

Will Deacon <[email protected]> wrote @ Mon, 10 Jun 2013 20:34:40 +0200:

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

The current code only clobbers a local variable, so the device is left with a stale mapping pointer.

True. This's my bad. Thanks.

That's alright, it's easy to fix. Mind if I add your ack please?

Feel free to add: Acked-by: Hiroshi Doyu <[email protected]>

Thanks for spotting the bug. I've taked the patch to my dma-mapping tree.

Best regards

Signature · 2 lines
Marek Szyprowski
Samsung R&D Institute Poland
#27 lore raw

PATCH 5/9 arm64: pgtable: use pte_index instead of __pte_index

In reply to Will Deacon

pte_index is a useful helper outside of arch/arm64, for things like the ARM SMMU driver, so rename __pte_index to pte_index to be consistent with both arch/arm/ and also the definitions of pmd_index and pgd_index.

Cc Catalin Marinas <[email protected]>
---
 arch/arm64/include/asm/pgtable.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/include/asm/pgtable.h +2 -2
index e333a24..b93bc23 100644
@@ -119,7 +119,7 @@ extern struct page *empty_zero_page;
 #define pte_none(pte)		(!pte_val(pte))
 #define pte_clear(mm,addr,ptep)	set_pte(ptep, __pte(0))
 #define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))
-#define pte_offset_kernel(dir,addr)	(pmd_page_vaddr(*(dir)) + __pte_index(addr))
+#define pte_offset_kernel(dir,addr)	(pmd_page_vaddr(*(dir)) + pte_index(addr))
 
 #define pte_offset_map(dir,addr)	pte_offset_kernel((dir), (addr))
 #define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir), (addr))
@@ -263,7 +263,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 #endif
 
 /* Find an entry in the third-level page table.. */
-#define __pte_index(addr)	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_index(addr)		(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
Signature · 1 line
1.8.2.2
#28 lore raw

PATCH 6/9 arm64: device: add iommu pointer to device archdata

In reply to Will Deacon

When using an IOMMU for device mappings, it is necessary to keep a pointer between the device and the IOMMU to which it is attached in order to obtain the correct IOMMU when attaching the device to a domain.

This patch adds an iommu pointer to the dev_archdata structure, in a similar manner to other architectures (ARM, PowerPC, x86, ...).

Cc Catalin Marinas <[email protected]>
---
 arch/arm64/include/asm/device.h | 3 +++
 1 file changed, 3 insertions(+)
arch/arm64/include/asm/device.h +3 -0
index 07dd743..01fac31 100644
@@ -18,6 +18,9 @@
 
 struct dev_archdata {
 	struct dma_map_ops *dma_ops;
+#ifdef CONFIG_IOMMU_API
+	void *iommu; /* private IOMMU data */
+#endif
 	struct dma_iommu_mapping	*mapping;
 };
 
Signature · 1 line
1.8.2.2
#29 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

In reply to Will Deacon

This patch adds a description of the device tree binding for the ARM System MMU architecture.

Cc Rob Herring <[email protected]>
Cc Andreas Herrmann <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 .../devicetree/bindings/iommu/arm,smmu.txt         | 70 ++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iommu/arm,smmu.txt
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +70 -0
new file mode 100644
index 0000000..e34c6cd
@@ -0,0 +1,70 @@
+* ARM System MMU Architecture Implementation
+
+ARM SoCs may contain an implementation of the ARM System Memory
+Management Unit Architecture, which can be used to provide 1 or 2 stages
+of address translation to bus masters external to the CPU.
+
+The SMMU may also raise interrupts in response to various fault
+conditions.
+
+** System MMU required properties:
+
+- compatible    : Should be one of:
+
+                        "arm,smmu-v1"
+                        "arm,smmu-v2"
+                        "arm,mmu-400"
+                        "arm,mmu-500"
+
+                  depending on the particular implementation and/or the
+                  version of the architecture implemented.
+
+- reg           : Base address and size of the SMMU.
+
+- #global-interrupts : The number of global interrupts exposed by the
+                       device.
+
+- interrupts    : Interrupt list, with the first #global-irqs entries
+                  corresponding to the global interrupts and any
+                  following entries corresponding to context interrupts,
+                  specified in order of their indexing by the SMMU.
+
+                  For SMMUv2 implementations, there must be exactly one
+                  interrupt per context bank. In the case of a single,
+                  combined interrupt, it must be listed multiple times.
+
+- mmu-masters   : A list of phandles to device nodes representing bus
+                  masters for which the SMMU can provide a translation
+                  and their corresponding StreamIDs (see example below).
+                  Each device node linked from this list must have a
+                  "#stream-id-cells" property, indicating the number of
+                  StreamIDs associated with it.
+
+** System MMU optional properties:
+
+- smmu-parent   : When multiple SMMUs are chained together, this
+                  property can be used to provide a phandle to the
+                  parent SMMU (that is the next SMMU on the path going
+                  from the mmu-masters towards memory) node for this
+                  SMMU.
+
+Example:
+
+        smmu {
+                compatible = "arm,smmu-v1";
+                reg = <0xba5e0000 0x10000>;
+                #global-interrupts = <2>;
+                interrupts = <0 32 4>,
+                             <0 33 4>,
+                             <0 34 4>, /* This is the first context interrupt */
+                             <0 35 4>,
+                             <0 36 4>,
+                             <0 37 4>;
+
+                /*
+                 * Two DMA controllers, the first with two StreamIDs (0xd01d
+                 * and 0xd01e) and the second with only one (0xd11c).
+                 */
+                mmu-masters = <&dma0 0xd01d 0xd01e>,
+                              <&dma1 0xd11c>;
+        };
Signature · 1 line
1.8.2.2
#30 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

Quoted 7 lines · Will Deacon

This patch adds a description of the device tree binding for the ARM System MMU architecture.

Cc Rob Herring <[email protected]>
Cc Andreas Herrmann <[email protected]>
Cc Joerg Roedel <[email protected]>
Quoted 88 lines
---
 .../devicetree/bindings/iommu/arm,smmu.txt         | 70 ++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iommu/arm,smmu.txt
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +70 -0
new file mode 100644
index 0000000..e34c6cd
@@ -0,0 +1,70 @@
+* ARM System MMU Architecture Implementation
+
+ARM SoCs may contain an implementation of the ARM System Memory
+Management Unit Architecture, which can be used to provide 1 or 2 stages
+of address translation to bus masters external to the CPU.
+
+The SMMU may also raise interrupts in response to various fault
+conditions.
+
+** System MMU required properties:
+
+- compatible    : Should be one of:
+
+                        "arm,smmu-v1"
+                        "arm,smmu-v2"
+                        "arm,mmu-400"
+                        "arm,mmu-500"
+
+                  depending on the particular implementation and/or the
+                  version of the architecture implemented.
+
+- reg           : Base address and size of the SMMU.
+
+- #global-interrupts : The number of global interrupts exposed by the
+                       device.
+
+- interrupts    : Interrupt list, with the first #global-irqs entries
+                  corresponding to the global interrupts and any
+                  following entries corresponding to context interrupts,
+                  specified in order of their indexing by the SMMU.
+
+                  For SMMUv2 implementations, there must be exactly one
+                  interrupt per context bank. In the case of a single,
+                  combined interrupt, it must be listed multiple times.
+
+- mmu-masters   : A list of phandles to device nodes representing bus
+                  masters for which the SMMU can provide a translation
+                  and their corresponding StreamIDs (see example below).
+                  Each device node linked from this list must have a
+                  "#stream-id-cells" property, indicating the number of
+                  StreamIDs associated with it.
+
+** System MMU optional properties:
+
+- smmu-parent   : When multiple SMMUs are chained together, this
+                  property can be used to provide a phandle to the
+                  parent SMMU (that is the next SMMU on the path going
+                  from the mmu-masters towards memory) node for this
+                  SMMU.
+
+Example:
+
+        smmu {
+                compatible = "arm,smmu-v1";
+                reg = <0xba5e0000 0x10000>;
+                #global-interrupts = <2>;
+                interrupts = <0 32 4>,
+                             <0 33 4>,
+                             <0 34 4>, /* This is the first context interrupt */
+                             <0 35 4>,
+                             <0 36 4>,
+                             <0 37 4>;
+
+                /*
+                 * Two DMA controllers, the first with two StreamIDs (0xd01d
+                 * and 0xd01e) and the second with only one (0xd11c).
+                 */
+                mmu-masters = <&dma0 0xd01d 0xd01e>,
+                              <&dma1 0xd11c>;
+        };
Signature · 6 lines
1.8.2.2

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss at lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss
Signature · 2 lines
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies, Ltd.
maintainer
#31 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

In reply to Will Deacon
Quoted 2 lines · Will Deacon

This patch adds a description of the device tree binding for the ARM System MMU architecture.

Interesting, will this be a common driver to replace existing ARM IOMMU drivers or is it a common driver for ARM IOMMUs found in future chips?

Documentation/devicetree/bindings/iommu/arm,smmu.txt line 49

Quoted 5 lines

+- smmu-parent : When multiple SMMUs are chained together, this

Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +4 -0
+                  property can be used to provide a phandle to the
+                  parent SMMU (that is the next SMMU on the path going
+                  from the mmu-masters towards memory) node for this
+                  SMMU.

What happens when SMMUs are chained? Will the second SMMU seeing the DMA just pass it through or is it translated again?

Thanks,

Joerg

#32 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

Hi Joerg,

Quoted 6 lines · Joerg Roedel
Quoted 2 lines · Will Deacon

This patch adds a description of the device tree binding for the ARM System MMU architecture.

Interesting, will this be a common driver to replace existing ARM IOMMU drivers or is it a common driver for ARM IOMMUs found in future chips?

This is a common driver that will support any IOMMUs compatible with v1 or v2 of the ARM SMMU architecture. Currently, that includes SMMUs known informatively as MMU-400, MMU-401 and MMU-500. I had a look at the other IOMMU drivers in the kernel and they seem to be driving incompatible IOMMUs, so I don't see how this driver can replace those.

However, we'll hopefully see ARM SMMU-compatible devices turning up soon (I know of many SoCs in development that are looking at them).

Quoted 8 lines

Documentation/devicetree/bindings/iommu/arm,smmu.txt line 49

Quoted 5 lines

+- smmu-parent : When multiple SMMUs are chained together, this

Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +4 -0
+                  property can be used to provide a phandle to the
+                  parent SMMU (that is the next SMMU on the path going
+                  from the mmu-masters towards memory) node for this
+                  SMMU.

What happens when SMMUs are chained? Will the second SMMU seeing the DMA just pass it through or is it translated again?

Chaining is really horrible and exists as a hack to support virtualisation using two separate SMMUs, where neither of them can support nested translation.

The current driver just programs the translation in the SMMU nearest the device, then sets the other SMMU into `bypass' mode (it was simple enough to generalise the chain to contain an arbitrary number of SMMUs, so the driver can actually deal with any number of the things). In theory (and if we extended the IOMMU API to distinguish between guest and host mappings -- something which I plan to look at in the future), KVM could install mappings in the second SMMU, but I think we should draw a line in the sand and mandate support for nested translation for KVM.

The only thing to take care of is that the SMMUs in the chain don't silently truncate addresses.

Will

maintainer
#33 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

Hi Will,

Quoted 8 lines · Will Deacon

This is a common driver that will support any IOMMUs compatible with v1 or v2 of the ARM SMMU architecture. Currently, that includes SMMUs known informatively as MMU-400, MMU-401 and MMU-500. I had a look at the other IOMMU drivers in the kernel and they seem to be driving incompatible IOMMUs, so I don't see how this driver can replace those.

However, we'll hopefully see ARM SMMU-compatible devices turning up soon (I know of many SoCs in development that are looking at them).

That sounds great. So in the future there will be a single driver for most future SOCs. This is a real improvement over the current situation.

Quoted 1 line

From NVidia is another driver with 'smmu' in its name, is that one also

incompatible?

Quoted 3 lines

Chaining is really horrible and exists as a hack to support virtualisation using two separate SMMUs, where neither of them can support nested translation.

I see, thanks for the explanation.

Joerg

#34 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

Quoted 7 lines · Joerg Roedel
Quoted 6 lines · Will Deacon

This is a common driver that will support any IOMMUs compatible with v1 or v2 of the ARM SMMU architecture. Currently, that includes SMMUs known informatively as MMU-400, MMU-401 and MMU-500. I had a look at the other IOMMU drivers in the kernel and they seem to be driving incompatible IOMMUs, so I don't see how this driver can replace those.

Quoted 8 lines
Quoted 2 lines

However, we'll hopefully see ARM SMMU-compatible devices turning up soon (I know of many SoCs in development that are looking at them).

That sounds great. So in the future there will be a single driver for most future SOCs. This is a real improvement over the current situation.

From NVidia is another driver with 'smmu' in its name, is that one also incompatible?

Yup. I even checked with Stephen Warren before I started my driver, just in case :)

Will

#35 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

In reply to Will Deacon
Quoted 36 lines · Will Deacon

This patch adds a description of the device tree binding for the ARM System MMU architecture.

Cc Rob Herring <[email protected]>
Cc Andreas Herrmann <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 .../devicetree/bindings/iommu/arm,smmu.txt         | 70 ++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iommu/arm,smmu.txt
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +18 -0
new file mode 100644
index 0000000..e34c6cd
@@ -0,0 +1,70 @@
+* ARM System MMU Architecture Implementation
+
+ARM SoCs may contain an implementation of the ARM System Memory
+Management Unit Architecture, which can be used to provide 1 or 2 stages
+of address translation to bus masters external to the CPU.
+
+The SMMU may also raise interrupts in response to various fault
+conditions.
+
+** System MMU required properties:
+
+- compatible    : Should be one of:
+
+                        "arm,smmu-v1"
+                        "arm,smmu-v2"
+                        "arm,mmu-400"
+                        "arm,mmu-500"
+

Documentation/devicetree/bindings/iommu/arm,smmu.txt line 28

Quoted 10 lines
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +10 -0
+                  depending on the particular implementation and/or the
+                  version of the architecture implemented.
+
+- reg           : Base address and size of the SMMU.
+
+- #global-interrupts : The number of global interrupts exposed by the
+                       device.
+
+- interrupts    : Interrupt list, with the first #global-irqs entries
+                  corresponding to the global interrupts

It seems like we don't have enough information here. It's not enough
for the OS to know that there are 2, 4, etc global interrupts, no? It needs
to know which hardware interrupt each corresponds to. That kind of
stuff is normally defined in the device binding.

What is it that determines the number of global interrupts?

Quoted 4 lines

and any

Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +3 -0
+                  following entries corresponding to context interrupts,
+                  specified in order of their indexing by the SMMU.
+

Documentation/devicetree/bindings/iommu/arm,smmu.txt line 41

Quoted 10 lines
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +10 -0
+                  For SMMUv2 implementations, there must be exactly one
+                  interrupt per context bank. In the case of a single,
+                  combined interrupt, it must be listed multiple times.
+
+- mmu-masters   : A list of phandles to device nodes representing bus
+                  masters for which the SMMU can provide a translation
+                  and their corresponding StreamIDs (see example below).
+                  Each device node linked from this list must have a
+                  "#stream-id-cells" property, indicating the number of
+                  StreamIDs associated with it.

So to find a the SMMU for a given device, I walk up the bus hierarchy until I find an SMMU?

Documentation/devicetree/bindings/iommu/arm,smmu.txt line 49

Quoted 7 lines
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +7 -0
+** System MMU optional properties:
+
+- smmu-parent   : When multiple SMMUs are chained together, this
+                  property can be used to provide a phandle to the
+                  parent SMMU (that is the next SMMU on the path going
+                  from the mmu-masters towards memory) node for this
+                  SMMU.

Why is an explicit phandle link needed here when you don't need a
smmu-parent phandle in each mmu-master? Won't walking the bus
hierarchy identify the parent SMMU if things are chained?

Thanks,

Stuart Yoder
Freescale Semiconductor

#36 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

Hi Stuart,

Quoted 41 lines · Stuart Yoder
Quoted 24 lines · Will Deacon
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +18 -0
new file mode 100644
index 0000000..e34c6cd
@@ -0,0 +1,70 @@
+* ARM System MMU Architecture Implementation
+
+ARM SoCs may contain an implementation of the ARM System Memory
+Management Unit Architecture, which can be used to provide 1 or 2 stages
+of address translation to bus masters external to the CPU.
+
+The SMMU may also raise interrupts in response to various fault
+conditions.
+
+** System MMU required properties:
+
+- compatible    : Should be one of:
+
+                        "arm,smmu-v1"
+                        "arm,smmu-v2"
+                        "arm,mmu-400"
+                        "arm,mmu-500"
+

Documentation/devicetree/bindings/iommu/arm,smmu.txt line 28

Quoted 10 lines
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +10 -0
+                  depending on the particular implementation and/or the
+                  version of the architecture implemented.
+
+- reg           : Base address and size of the SMMU.
+
+- #global-interrupts : The number of global interrupts exposed by the
+                       device.
+
+- interrupts    : Interrupt list, with the first #global-irqs entries
+                  corresponding to the global interrupts

It seems like we don't have enough information here. It's not enough
for the OS to know that there are 2, 4, etc global interrupts, no? It needs
to know which hardware interrupt each corresponds to. That kind of
stuff is normally defined in the device binding.

Quoted 1 line

What is it that determines the number of global interrupts?

I'd suggest looking at the driver I posted to get a gist of how the parsing code works, but suffice to say that we describe both the number of interrupts and the actual interrupt numbers here.

Quoted 9 lines

Documentation/devicetree/bindings/iommu/arm,smmu.txt line 41

Quoted 6 lines
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +6 -0
+- mmu-masters   : A list of phandles to device nodes representing bus
+                  masters for which the SMMU can provide a translation
+                  and their corresponding StreamIDs (see example below).
+                  Each device node linked from this list must have a
+                  "#stream-id-cells" property, indicating the number of
+                  StreamIDs associated with it.

So to find a the SMMU for a given device, I walk up the bus hierarchy until I find an SMMU?

Again, the code is better than any explanation I can give here, but we basically construct a tree of masters for each SMMU in the system based on the mmu-masters property, which we can later search.

Quoted 11 lines

Documentation/devicetree/bindings/iommu/arm,smmu.txt line 49

Quoted 7 lines
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +7 -0
+** System MMU optional properties:
+
+- smmu-parent   : When multiple SMMUs are chained together, this
+                  property can be used to provide a phandle to the
+                  parent SMMU (that is the next SMMU on the path going
+                  from the mmu-masters towards memory) node for this
+                  SMMU.

Why is an explicit phandle link needed here when you don't need a
smmu-parent phandle in each mmu-master? Won't walking the bus
hierarchy identify the parent SMMU if things are chained?

What bus hierarchy? If I have two SMMU device nodes, how do I infer any topological information without an explicit linkage?

Will

#37 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

Quoted 44 lines · Will Deacon

Hi Stuart,

Quoted 41 lines · Stuart Yoder
Quoted 24 lines · Will Deacon
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +18 -0
new file mode 100644
index 0000000..e34c6cd
@@ -0,0 +1,70 @@
+* ARM System MMU Architecture Implementation
+
+ARM SoCs may contain an implementation of the ARM System Memory
+Management Unit Architecture, which can be used to provide 1 or 2 stages
+of address translation to bus masters external to the CPU.
+
+The SMMU may also raise interrupts in response to various fault
+conditions.
+
+** System MMU required properties:
+
+- compatible    : Should be one of:
+
+                        "arm,smmu-v1"
+                        "arm,smmu-v2"
+                        "arm,mmu-400"
+                        "arm,mmu-500"
+

Documentation/devicetree/bindings/iommu/arm,smmu.txt line 28

Quoted 10 lines
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +10 -0
+                  depending on the particular implementation and/or the
+                  version of the architecture implemented.
+
+- reg           : Base address and size of the SMMU.
+
+- #global-interrupts : The number of global interrupts exposed by the
+                       device.
+
+- interrupts    : Interrupt list, with the first #global-irqs entries
+                  corresponding to the global interrupts

It seems like we don't have enough information here. It's not enough
for the OS to know that there are 2, 4, etc global interrupts, no? It needs
to know which hardware interrupt each corresponds to. That kind of
stuff is normally defined in the device binding.

Quoted 5 lines
Quoted 1 line

What is it that determines the number of global interrupts?

I'd suggest looking at the driver I posted to get a gist of how the parsing code works, but suffice to say that we describe both the number of interrupts and the actual interrupt numbers here.

I understand that the number of interrupts and actual interrupt numbers are described here, but was referring to the _meaning_ of the interrupt
numbers. A binding for a device with 2 interrupts, a TX and RX would
normally identify which interrupt specifier is for TX and which is for RX.

Based on your code, the 2 global interrupts seem to be the secure and non-secure fault interrupts...which your driver does not differentiate. However, the device tree is describing hardware and you can't assume that all drivers don't care which is which.

So, I would suggest that the binding identify which interrupt specifier is secure and which is non-secure.

If there are other interrupts added in the future like the performance interrupt the definition could be expanded to add that.

But a question.... why do you need the #global-interrupts property
at all? Is the number of "global" interrupts really implementation dependent?
Does't a specific compatible string imply the number of interrupts that there actually are?

Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +6 -0
+- mmu-masters   : A list of phandles to device nodes representing bus
+                  masters for which the SMMU can provide a translation
+                  and their corresponding StreamIDs (see example below).
+                  Each device node linked from this list must have a
+                  "#stream-id-cells" property, indicating the number of
+                  StreamIDs associated with it.
Quoted 6 lines
Quoted 2 lines

So to find a the SMMU for a given device, I walk up the bus hierarchy until I find an SMMU?

Again, the code is better than any explanation I can give here, but we basically construct a tree of masters for each SMMU in the system based on the mmu-masters property, which we can later search.

I see.

Quoted 12 lines
Quoted 11 lines

Documentation/devicetree/bindings/iommu/arm,smmu.txt line 49

Quoted 7 lines
Documentation/devicetree/bindings/iommu/arm,smmu.txt new file +7 -0
+** System MMU optional properties:
+
+- smmu-parent   : When multiple SMMUs are chained together, this
+                  property can be used to provide a phandle to the
+                  parent SMMU (that is the next SMMU on the path going
+                  from the mmu-masters towards memory) node for this
+                  SMMU.

Why is an explicit phandle link needed here when you don't need a
smmu-parent phandle in each mmu-master? Won't walking the bus
hierarchy identify the parent SMMU if things are chained?

Quoted 2 lines

What bus hierarchy? If I have two SMMU device nodes, how do I infer any topological information without an explicit linkage?

I really don't know anything about SMMU chaining, but am inferring what
this might look like. Does the "child" SMMU look just like another
mmu-master to the parent? If so, why not just use the mmu-masters
property to establish the relationship.

I just found it a bit strange that the relationship between I/O mmu-masters is defined from parent SMMU node pointing to the device, and the relationship between a 'child' SMMU and a parent is established
in the other direction. Not a big deal.

Stuart

#38 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

Quoted 10 lines · Stuart Yoder
Quoted 3 lines · Will Deacon

I'd suggest looking at the driver I posted to get a gist of how the parsing code works, but suffice to say that we describe both the number of interrupts and the actual interrupt numbers here.

I understand that the number of interrupts and actual interrupt numbers are described here, but was referring to the _meaning_ of the interrupt
numbers. A binding for a device with 2 interrupts, a TX and RX would
normally identify which interrupt specifier is for TX and which is for RX.

Quoted 4 lines

Based on your code, the 2 global interrupts seem to be the secure and non-secure fault interrupts...which your driver does not differentiate. However, the device tree is describing hardware and you can't assume that all drivers don't care which is which.

Currently, the driver only works when Linux is running as non-secure, which is becoming more and more common since it is required to be able to make use of hyp mode.

There are actually two global interrupts for SMMUv1 and SMMUv2, which correspond to configuration faults and `other' global faults.

Quoted 2 lines

If there are other interrupts added in the future like the performance interrupt the definition could be expanded to add that.

PMU interrupts would like have a separate property, since the PMU would be driven by a largely independent piece of code.

Quoted 4 lines

But a question.... why do you need the #global-interrupts property
at all? Is the number of "global" interrupts really implementation dependent?
Does't a specific compatible string imply the number of interrupts that there actually are?

Integrators have a nasty habit of ORing interrupts together or not wiring them at all and I don't want to be caught out by that.

Quoted 7 lines
Quoted 2 lines

What bus hierarchy? If I have two SMMU device nodes, how do I infer any topological information without an explicit linkage?

I really don't know anything about SMMU chaining, but am inferring what
this might look like. Does the "child" SMMU look just like another
mmu-master to the parent? If so, why not just use the mmu-masters
property to establish the relationship.

No, the child SMMU does not look like a master. It can remaster upstream StreamIDs, for example.

Will

#39 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

Quoted 16 lines · Will Deacon
Quoted 10 lines · Stuart Yoder
Quoted 3 lines · Will Deacon

I'd suggest looking at the driver I posted to get a gist of how the parsing code works, but suffice to say that we describe both the number of interrupts and the actual interrupt numbers here.

I understand that the number of interrupts and actual interrupt numbers are described here, but was referring to the _meaning_ of the interrupt
numbers. A binding for a device with 2 interrupts, a TX and RX would
normally identify which interrupt specifier is for TX and which is for RX.

Quoted 4 lines

Based on your code, the 2 global interrupts seem to be the secure and non-secure fault interrupts...which your driver does not differentiate. However, the device tree is describing hardware and you can't assume that all drivers don't care which is which.

Quoted 6 lines

Currently, the driver only works when Linux is running as non-secure, which is becoming more and more common since it is required to be able to make use of hyp mode.

There are actually two global interrupts for SMMUv1 and SMMUv2, which correspond to configuration faults and `other' global faults.

So, why don't we define which interrupt is which in this binding? ...e.g. "The first
interrupt specifier is for the configuration access fault interrupt, the second interrupt specifier is for other global faults."

How else is software supposed to know which interrupt corresponds to what event.

Thanks,
Stuart

#40 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

Quoted 21 lines · Stuart Yoder
Quoted 20 lines · Will Deacon
Quoted 10 lines · Stuart Yoder
Quoted 3 lines · Will Deacon

I'd suggest looking at the driver I posted to get a gist of how the parsing code works, but suffice to say that we describe both the number of interrupts and the actual interrupt numbers here.

I understand that the number of interrupts and actual interrupt numbers are described here, but was referring to the _meaning_ of the interrupt
numbers. A binding for a device with 2 interrupts, a TX and RX would
normally identify which interrupt specifier is for TX and which is for RX.

Quoted 4 lines

Based on your code, the 2 global interrupts seem to be the secure and non-secure fault interrupts...which your driver does not differentiate. However, the device tree is describing hardware and you can't assume that all drivers don't care which is which.

Currently, the driver only works when Linux is running as non-secure, which is becoming more and more common since it is required to be able to make use of hyp mode.

Quoted 7 lines
Quoted 2 lines

There are actually two global interrupts for SMMUv1 and SMMUv2, which correspond to configuration faults and `other' global faults.

So, why don't we define which interrupt is which in this binding? ...e.g. "The first
interrupt specifier is for the configuration access fault interrupt, the second interrupt specifier is for other global faults."

Well, first of all, they're both global interrupts and the handler will have to go and access exactly the same registers to deal with the fault, so you don't really gain anything.

However, the main reason is that you need to be able to handle:

(1) Only one of the interrupts is routed to the interrupt controller
(2) The interrupts are ORd into a single line

Quoted 2 lines

How else is software supposed to know which interrupt corresponds to what event.

It really doesn't care. It can't, otherwise we break in the above situations.

Will

#41 lore raw

PATCH 7/9 documentation: iommu: add description of ARM System MMU binding

Quoted 25 lines · Will Deacon
Quoted 24 lines · Stuart Yoder
Quoted 22 lines · Will Deacon
Quoted 10 lines · Stuart Yoder
Quoted 3 lines · Will Deacon

I'd suggest looking at the driver I posted to get a gist of how the parsing code works, but suffice to say that we describe both the number of interrupts and the actual interrupt numbers here.

I understand that the number of interrupts and actual interrupt numbers are described here, but was referring to the _meaning_ of the interrupt
numbers. A binding for a device with 2 interrupts, a TX and RX would
normally identify which interrupt specifier is for TX and which is for RX.

Quoted 4 lines

Based on your code, the 2 global interrupts seem to be the secure and non-secure fault interrupts...which your driver does not differentiate. However, the device tree is describing hardware and you can't assume that all drivers don't care which is which.

Currently, the driver only works when Linux is running as non-secure, which is becoming more and more common since it is required to be able to make use of hyp mode.

There are actually two global interrupts for SMMUv1 and SMMUv2, which correspond to configuration faults and `other' global faults.

Quoted 8 lines
Quoted 4 lines

So, why don't we define which interrupt is which in this binding? ...e.g. "The first
interrupt specifier is for the configuration access fault interrupt, the second interrupt specifier is for other global faults."

Well, first of all, they're both global interrupts and the handler will have to go and access exactly the same registers to deal with the fault, so you don't really gain anything.

It should be up to the OS to handle 2 interrupts the same, not something

Quoted 4 lines

However, the main reason is that you need to be able to handle:

(1) Only one of the interrupts is routed to the interrupt controller
(2) The interrupts are ORd into a single line

That's a particular SoC implementation, no? It shouldn't dictate the SMMU binding.

If they are ORed then the interrupt controller can't distinguish them and both interrupt specifiers should have the _same_ interrupt number:

+ #global-interrupts = <2>;
+ interrupts = <0 32 4>,
+ <0 32 4>,

(...or perhaps only define 1 global interrupt-- interrupt 32)

If an implementation chose to not OR them, then they will have different interrupt numbers and need to be distinguished:

+ #global-interrupts = <2>;
+ interrupts = <0 32 4>,
+ <0 33 4>,

...and in that case the binding needs to differentiate which is which.

Stuart

#42 lore raw

PATCH 8/9 iommu: add support for ARM Ltd. System MMU architecture

In reply to Will Deacon

This patch adds support for SMMUs implementing the ARM System MMU architecture versions 1 or 2. Both arm and arm64 are supported, although the v7s descriptor format is not used.

Cc Rob Herring <[email protected]>
Cc Andreas Herrmann <[email protected]>
Cc Olav Haugan <[email protected]>
Cc Joerg Roedel <[email protected]>
---
 drivers/iommu/Kconfig    |   13 +
 drivers/iommu/Makefile   |    1 +
 drivers/iommu/arm-smmu.c | 1965 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1979 insertions(+)
 create mode 100644 drivers/iommu/arm-smmu.c
drivers/iommu/Kconfig +13 -0
index c332fb9..957cfd4 100644
@@ -261,4 +261,17 @@ config SHMOBILE_IOMMU_L1SIZE
 	default 256 if SHMOBILE_IOMMU_ADDRSIZE_64MB
 	default 128 if SHMOBILE_IOMMU_ADDRSIZE_32MB
 
+config ARM_SMMU
+	bool "ARM Ltd. System MMU (SMMU) Support"
+	depends on ARM64 || (ARM_LPAE && OF)
+	select IOMMU_API
+	select ARM_DMA_USE_IOMMU if ARM
+	help
+	  Support for implementations of the ARM System MMU architecture
+	  versions 1 and 2. The driver supports both v7l and v8l table
+	  formats with 4k and 64k page sizes.
+
+	  Say Y here if your SoC includes an IOMMU device implementing
+	  the ARM SMMU architecture.
+
 endif # IOMMU_SUPPORT
drivers/iommu/Makefile +1 -0
index ef0e520..bbe7041 100644
@@ -3,6 +3,7 @@ obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
+obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
 obj-$(CONFIG_DMAR_TABLE) += dmar.o
 obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
drivers/iommu/arm-smmu.c new file +1965 -0

1,965 lines not on this page · raw message

Signature · 1 line
1.8.2.2
maintainer
#43 lore raw

PATCH 8/9 iommu: add support for ARM Ltd. System MMU architecture

Hi Will,

Quoted 9 lines · Will Deacon

This patch adds support for SMMUs implementing the ARM System MMU architecture versions 1 or 2. Both arm and arm64 are supported, although the v7s descriptor format is not used.

Cc Rob Herring <[email protected]>
Cc Andreas Herrmann <[email protected]>
Cc Olav Haugan <[email protected]>
Cc Joerg Roedel <[email protected]>

A few general questions:

How have you tested this code? Has it been run on real hardware? What were the results?

The code looks good and clean in general, minus a few places mentioned below were I have questions and/or suggestions:

drivers/iommu/arm-smmu.c line 485

Quoted 10 lines
drivers/iommu/arm-smmu.c new file +10 -0
+static struct arm_smmu_device *find_parent_smmu(struct arm_smmu_device *smmu)
+{
+	struct arm_smmu_device *parent, *tmp;
+
+	if (!smmu->parent_of_node)
+		return NULL;
+
+	list_for_each_entry_safe(parent, tmp, &arm_smmu_devices, list)
+		if (parent->dev->of_node == smmu->parent_of_node)
+			return parent;

Why do you need the _safe variant here? You are not changing the list in this loop so you should be fine with list_for_each_entry().

Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+
+	dev_warn(smmu->dev,
+		 "Failed to find SMMU parent despite parent in DT\n");
+	return NULL;
+}

drivers/iommu/arm-smmu.c line 539

Quoted 10 lines
drivers/iommu/arm-smmu.c new file +9 -0
 
+/* Wait for any pending TLB invalidations to complete */
+static void arm_smmu_tlb_sync(struct arm_smmu_device *smmu)
+{
+	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
+
+	writel_relaxed(0, gr0_base + ARM_SMMU_GR0_sTLBGSYNC);
+	while (readl_relaxed(gr0_base + ARM_SMMU_GR0_sTLBGSTATUS)
+	       & sTLBGSTATUS_GSACTIVE)
+		cpu_relax();

Other IOMMU drivers have a timeout for this loop and report an error when the state does not change. I think this makes sense here too so that the kernel will not just stop spinning in that loop if something goes wrong but prints an error instead.

drivers/iommu/arm-smmu.c line 1162

Quoted 13 lines
drivers/iommu/arm-smmu.c new file +13 -0
+}
+static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr,
+				   size_t size)
+{
+	unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
+
+	/*
+	 * If the SMMU can't walk tables in the CPU caches, treat them
+	 * like non-coherent DMA...
+	 */
+	if (!(smmu->features & ARM_SMMU_FEAT_COHERENT_WALK))
+		dma_map_page(smmu->dev, virt_to_page(addr), offset, size,
+			     DMA_TO_DEVICE);

Why can you call into DMA-API here? A DMA-API implementation may call back into this IOMMU driver, no? So this looks a little bit like a layering violation.

Quoted 9 lines
drivers/iommu/arm-smmu.c new file +8 -0
+}
 
+static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
+			phys_addr_t paddr, size_t size, int flags)
+{
+	struct arm_smmu_domain *smmu_domain = domain->priv;
+	struct arm_smmu_device *smmu = smmu_domain->leaf_smmu;
+
+	if (!smmu_domain || !smmu)

drivers/iommu/arm-smmu.c line 1404

Quoted 10 lines
drivers/iommu/arm-smmu.c new file +10 -0
+		return -ENODEV;
+
+	/*
+	 * Check for silent address truncation up the SMMU chain.
+	 */
+	do {
+		phys_addr_t output_mask = (1ULL << smmu->s2_output_size) - 1;
+		if ((phys_addr_t)iova & ~output_mask)
+			return -ERANGE;
+	} while ((smmu = find_parent_smmu(smmu)));

This looks a bit too expensive to have in the map path. How about saving something like an effective_output_mask (or output_size) which contains the logical OR of every mask up the path? This would make this check a lot cheaper.

Quoted 4 lines
drivers/iommu/arm-smmu.c new file +4 -0
+
+	return arm_smmu_create_mapping(smmu_domain, iova, paddr, size, flags);
+}
+

drivers/iommu/arm-smmu.c line 1418

Quoted 10 lines
drivers/iommu/arm-smmu.c new file +10 -0
+static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
+			     size_t size)
+{
+	int ret;
+	struct arm_smmu_domain *smmu_domain = domain->priv;
+	struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
+	struct arm_smmu_device *smmu = root_cfg->smmu;
+	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
+
+	ret = arm_smmu_create_mapping(smmu_domain, iova, 0, size, 0);

Since this function does also unmapping, how about renaming it to arm_smmu_handle_mapping(). The 'create' part in there is misleading.

drivers/iommu/arm-smmu.c line 1485

Quoted 11 lines
drivers/iommu/arm-smmu.c new file +11 -0
+	writel_relaxed(root_cfg->vmid, gr0_base + ARM_SMMU_GR0_TLBIVMID);
+	arm_smmu_tlb_sync(smmu);
+	return ret ? ret : size;
+}
+static int arm_smmu_add_device(struct device *dev)
+{
+	struct arm_smmu_device *child, *parent, *smmu;
+	struct arm_smmu_device *tmp[2];
+	struct arm_smmu_master *master = NULL;
+
+	list_for_each_entry_safe(parent, tmp[0], &arm_smmu_devices, list) {

Again, why do you use the _safe variant, you do not seem to change the lists traversed here.

Quoted 31 lines
drivers/iommu/arm-smmu.c new file +31 -0
+		smmu = parent;
+
+		/* Try to find a child of the current SMMU. */
+		list_for_each_entry_safe(child, tmp[1], &arm_smmu_devices, list) {
+			if (child->parent_of_node == parent->dev->of_node) {
+				/* Does the child sit above our master? */
+				master = find_smmu_master(child, dev->of_node);
+				if (master) {
+					smmu = NULL;
+					break;
+				}
+			}
+		}
+
+		/* We found some children, so keep searching. */
+		if (!smmu) {
+			master = NULL;
+			continue;
+		}
+
+		master = find_smmu_master(smmu, dev->of_node);
+		if (master)
+			break;
+	}
+
+	if (!master)
+		return -ENODEV;
+
+	dev->archdata.iommu = smmu;
+	return 0;
+}
#44 lore raw

PATCH 8/9 iommu: add support for ARM Ltd. System MMU architecture

Quoted 1 line · Joerg Roedel

Hi Will,

Hi Joerg,

First, thanks for looking at this patch. I really appreciate it.

Quoted 11 lines · Will Deacon
Quoted 9 lines

This patch adds support for SMMUs implementing the ARM System MMU architecture versions 1 or 2. Both arm and arm64 are supported, although the v7s descriptor format is not used.

Cc Rob Herring <[email protected]>
Cc Andreas Herrmann <[email protected]>
Cc Olav Haugan <[email protected]>
Cc Joerg Roedel <[email protected]>
Quoted 4 lines

A few general questions:

How have you tested this code? Has it been run on real hardware? What were the results?

I've only tested it with software models, however they are fairly sophisticated and provide *lots* of tunables, so you can test different configurations which don't actually exist in hardware yet. You also get a tonne of trace output, so you can inspect things like page table walking and TLB filling to make sure the driver is setting things up as you planned.

I have also tested on MMU-400 (AArch32) and MMU-500 (both AArch32 and AArch64, with 4k and 64k pages in the latter case) models. The setup I used was 4 PL330 DMA controllers driven by dmatest.ko, which I hacked to call into the ARM dma-mapping API to create a separate domain for each controller.

The results were that the memory-to-memory DMA didn't show any corruption. I also managed to tickle access faults by messing around with the permissions, then remap the buffers and resume the transfers.

Quoted 2 lines

The code looks good and clean in general, minus a few places mentioned below were I have questions and/or suggestions:

Cheers, responses inline.

Quoted 5 lines
Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+static struct arm_smmu_device *find_parent_smmu(struct arm_smmu_device *smmu)
+{
+	struct arm_smmu_device *parent, *tmp;
+
+	if (!smmu->parent_of_node)
Quoted 8 lines

drivers/iommu/arm-smmu.c line 485

Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+		return NULL;
+
+	list_for_each_entry_safe(parent, tmp, &arm_smmu_devices, list)
+		if (parent->dev->of_node == smmu->parent_of_node)
+			return parent;

Why do you need the _safe variant here? You are not changing the list in this loop so you should be fine with list_for_each_entry().

For a system with multiple SMMUs (regardless of chaining), couldn't this code run in parallel with probing of another SMMU (which has to add to the arm_smmu_devices list)? The same applies for device removal, which could perhaps be driven from some power-managment code.

Quoted 6 lines
Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+
+	dev_warn(smmu->dev,
+		 "Failed to find SMMU parent despite parent in DT\n");
+	return NULL;
+}
Quoted 14 lines

drivers/iommu/arm-smmu.c line 539

Quoted 9 lines
drivers/iommu/arm-smmu.c new file +9 -0
+/* Wait for any pending TLB invalidations to complete */
+static void arm_smmu_tlb_sync(struct arm_smmu_device *smmu)
+{
+	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
+
+	writel_relaxed(0, gr0_base + ARM_SMMU_GR0_sTLBGSYNC);
+	while (readl_relaxed(gr0_base + ARM_SMMU_GR0_sTLBGSTATUS)
+	       & sTLBGSTATUS_GSACTIVE)
+		cpu_relax();

Other IOMMU drivers have a timeout for this loop and report an error when the state does not change. I think this makes sense here too so that the kernel will not just stop spinning in that loop if something goes wrong but prints an error instead.

Good idea, I'll add that.

Quoted 9 lines
Quoted 9 lines
drivers/iommu/arm-smmu.c new file +9 -0
+}
+static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr,
+				   size_t size)
+{
+	unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
+
+	/*
+	 * If the SMMU can't walk tables in the CPU caches, treat them
+	 * like non-coherent DMA...
Quoted 8 lines

drivers/iommu/arm-smmu.c line 1162

Quoted 4 lines
drivers/iommu/arm-smmu.c new file +4 -0
+	 */
+	if (!(smmu->features & ARM_SMMU_FEAT_COHERENT_WALK))
+		dma_map_page(smmu->dev, virt_to_page(addr), offset, size,
+			     DMA_TO_DEVICE);

Why can you call into DMA-API here? A DMA-API implementation may call back into this IOMMU driver, no? So this looks a little bit like a layering violation.

So this is subtle, and the comment could probably do with more explanation.

The problem is that the SMMU hardware page table walker might not be able to snoop the CPU caches. This means that after writing page table entries on the CPU, we have to flush them *all* the way out to main memory, so the SMMU can pick them up. There are only two other places I can think of where we have to do something like this in Linux:

(1) In the bowels of CPU suspend, where we may need to clean all of our caches prior to shutdown. This is all hidden away in low-level arch code.

(2) When dealing with non-coherent DMA, since we have to transfer buffer ownership between the CPU and the device. There is an API for this.

so, in fact, non-coherent DMA is a perfect fit for what we're trying to achieve with the SMMU page tables! I admit it looks odd, but it can't possibly go recursive because the master in question is a page-table walker, rather than anything backed by a struct device.

Quoted 16 lines
Quoted 16 lines
drivers/iommu/arm-smmu.c new file +15 -0
+}
 
+static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
+			phys_addr_t paddr, size_t size, int flags)
+{
+	struct arm_smmu_domain *smmu_domain = domain->priv;
+	struct arm_smmu_device *smmu = smmu_domain->leaf_smmu;
+
+	if (!smmu_domain || !smmu)
+		return -ENODEV;
+
+	/*
+	 * Check for silent address truncation up the SMMU chain.
+	 */
+	do {
+		phys_addr_t output_mask = (1ULL << smmu->s2_output_size) - 1;
Quoted 8 lines

drivers/iommu/arm-smmu.c line 1404

Quoted 3 lines
drivers/iommu/arm-smmu.c new file +3 -0
+		if ((phys_addr_t)iova & ~output_mask)
+			return -ERANGE;
+	} while ((smmu = find_parent_smmu(smmu)));

This looks a bit too expensive to have in the map path. How about saving something like an effective_output_mask (or output_size) which contains the logical OR of every mask up the path? This would make this check a lot cheaper.

As mentioned in the DT binding thread, it's rare that this loop would execute more than once, and largely inconceivable that it would execute more than twice, so I don't know how much we need to worry about the cost.

Quoted 9 lines
Quoted 9 lines
drivers/iommu/arm-smmu.c new file +9 -0
+
+	return arm_smmu_create_mapping(smmu_domain, iova, paddr, size, flags);
+}
+
+static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
+			     size_t size)
+{
+	int ret;
+	struct arm_smmu_domain *smmu_domain = domain->priv;
Quoted 8 lines

drivers/iommu/arm-smmu.c line 1418

Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+	struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
+	struct arm_smmu_device *smmu = root_cfg->smmu;
+	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
+
+	ret = arm_smmu_create_mapping(smmu_domain, iova, 0, size, 0);

Since this function does also unmapping, how about renaming it to arm_smmu_handle_mapping(). The 'create' part in there is misleading.

Yep, that's a hangover from when I originally had separate functions. Will fix,

Quoted 6 lines
Quoted 6 lines
drivers/iommu/arm-smmu.c new file +6 -0
+	writel_relaxed(root_cfg->vmid, gr0_base + ARM_SMMU_GR0_TLBIVMID);
+	arm_smmu_tlb_sync(smmu);
+	return ret ? ret : size;
+}
+static int arm_smmu_add_device(struct device *dev)
+{
Quoted 8 lines

drivers/iommu/arm-smmu.c line 1485

Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+	struct arm_smmu_device *child, *parent, *smmu;
+	struct arm_smmu_device *tmp[2];
+	struct arm_smmu_master *master = NULL;
+
+	list_for_each_entry_safe(parent, tmp[0], &arm_smmu_devices, list) {

Again, why do you use the _safe variant, you do not seem to change the lists traversed here.

Same reasoning as above. Happy to remove it if it's not actually required...

Cheers again,

Will

maintainer
#45 lore raw

PATCH 8/9 iommu: add support for ARM Ltd. System MMU architecture

Quoted 3 lines · Will Deacon

The results were that the memory-to-memory DMA didn't show any corruption. I also managed to tickle access faults by messing around with the permissions, then remap the buffers and resume the transfers.

That sounds pretty conclusive. So when real hardware shows up it should work reasonably well.

Quoted 14 lines
Quoted 5 lines
Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+static struct arm_smmu_device *find_parent_smmu(struct arm_smmu_device *smmu)
+{
+	struct arm_smmu_device *parent, *tmp;
+
+	if (!smmu->parent_of_node)
Quoted 8 lines

drivers/iommu/arm-smmu.c line 485

Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+		return NULL;
+
+	list_for_each_entry_safe(parent, tmp, &arm_smmu_devices, list)
+		if (parent->dev->of_node == smmu->parent_of_node)
+			return parent;

Why do you need the _safe variant here? You are not changing the list in this loop so you should be fine with list_for_each_entry().

Quoted 4 lines

For a system with multiple SMMUs (regardless of chaining), couldn't this code run in parallel with probing of another SMMU (which has to add to the arm_smmu_devices list)? The same applies for device removal, which could perhaps be driven from some power-managment code.

Well, the '_safe' does not mean it is safe from concurrent list manipulations. If you want to protect from that you still need a lock. The '_safe' variant only allows to remove the current element from the list while traversing it.

Quoted 11 lines
Quoted 10 lines

drivers/iommu/arm-smmu.c line 1404

Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+	do {
+		phys_addr_t output_mask = (1ULL << smmu->s2_output_size) - 1;
+		if ((phys_addr_t)iova & ~output_mask)
+			return -ERANGE;
+	} while ((smmu = find_parent_smmu(smmu)));

This looks a bit too expensive to have in the map path. How about saving something like an effective_output_mask (or output_size) which contains the logical OR of every mask up the path? This would make this check a lot cheaper.

Quoted 3 lines

As mentioned in the DT binding thread, it's rare that this loop would execute more than once, and largely inconceivable that it would execute more than twice, so I don't know how much we need to worry about the cost.

But still, this code is a challenge for the branch-predictor, plus the additional function calls to find_parent_smmu(). I still think it is worth to optimize this away. The map function is supposed to be a fast-path function.

Joerg

#46 lore raw

PATCH 8/9 iommu: add support for ARM Ltd. System MMU architecture

Quoted 7 lines · Joerg Roedel
Quoted 3 lines · Will Deacon

The results were that the memory-to-memory DMA didn't show any corruption. I also managed to tickle access faults by messing around with the permissions, then remap the buffers and resume the transfers.

That sounds pretty conclusive. So when real hardware shows up it should work reasonably well.

Fingers crossed. Of course, as I get to run on real RTL I'll address any issues that might crop up.

Quoted 19 lines
Quoted 14 lines
Quoted 5 lines
Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+static struct arm_smmu_device *find_parent_smmu(struct arm_smmu_device *smmu)
+{
+	struct arm_smmu_device *parent, *tmp;
+
+	if (!smmu->parent_of_node)
Quoted 8 lines

drivers/iommu/arm-smmu.c line 485

Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+		return NULL;
+
+	list_for_each_entry_safe(parent, tmp, &arm_smmu_devices, list)
+		if (parent->dev->of_node == smmu->parent_of_node)
+			return parent;

Why do you need the _safe variant here? You are not changing the list in this loop so you should be fine with list_for_each_entry().

Quoted 4 lines

For a system with multiple SMMUs (regardless of chaining), couldn't this code run in parallel with probing of another SMMU (which has to add to the arm_smmu_devices list)? The same applies for device removal, which could perhaps be driven from some power-managment code.

Quoted 4 lines

Well, the '_safe' does not mean it is safe from concurrent list manipulations. If you want to protect from that you still need a lock. The '_safe' variant only allows to remove the current element from the list while traversing it.

Damn, I was hoping to avoid locking on the map path. In fact, this is a good argument to go with your suggestion below (otherwise I'd need to use reader/writer locks which seem to be frowned on).

Quoted 11 lines
Quoted 11 lines
Quoted 10 lines

drivers/iommu/arm-smmu.c line 1404

Quoted 5 lines
drivers/iommu/arm-smmu.c new file +5 -0
+	do {
+		phys_addr_t output_mask = (1ULL << smmu->s2_output_size) - 1;
+		if ((phys_addr_t)iova & ~output_mask)
+			return -ERANGE;
+	} while ((smmu = find_parent_smmu(smmu)));

This looks a bit too expensive to have in the map path. How about saving something like an effective_output_mask (or output_size) which contains the logical OR of every mask up the path? This would make this check a lot cheaper.

Quoted 8 lines
Quoted 3 lines

As mentioned in the DT binding thread, it's rare that this loop would execute more than once, and largely inconceivable that it would execute more than twice, so I don't know how much we need to worry about the cost.

But still, this code is a challenge for the branch-predictor, plus the additional function calls to find_parent_smmu(). I still think it is worth to optimize this away. The map function is supposed to be a fast-path function.

Yes, the locking I'd need to introduce in find_parent_smmu seals the deal. I'll have a go at constructing the mask statically for each SMMU (although I think I want to use logical AND rather than OR).

Cheers,

Will

maintainer
#47 lore raw

PATCH 8/9 iommu: add support for ARM Ltd. System MMU architecture

Quoted 3 lines · Will Deacon

Damn, I was hoping to avoid locking on the map path. In fact, this is a good argument to go with your suggestion below (otherwise I'd need to use reader/writer locks which seem to be frowned on).

You should look into using rcu-lists instead. You still need a lock, but only when you actually manipulating the lists. For traversing them it is sufficient to take the rcu_read_lock() which has very low overhead.

Joerg

#48 lore raw

PATCH 8/9 iommu: add support for ARM Ltd. System MMU architecture

Quoted 8 lines · Joerg Roedel
Quoted 3 lines · Will Deacon

Damn, I was hoping to avoid locking on the map path. In fact, this is a good argument to go with your suggestion below (otherwise I'd need to use reader/writer locks which seem to be frowned on).

You should look into using rcu-lists instead. You still need a lock, but only when you actually manipulating the lists. For traversing them it is sufficient to take the rcu_read_lock() which has very low overhead.

Indeed, I'd got RCU-protected lists mixed up with the _safe iterators. However, if I construct a compound output_mask as you suggest, all the locking is on the slow path (add/attach of devices) so it's no longer an issue.

I'll post a v2 next week.

Will

#49 lore raw

PATCH 9/9 MAINTAINERS: add entry for ARM system MMU driver

In reply to Will Deacon

Add myself as maintainer for the ARM system MMU driver.

---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)
MAINTAINERS +6 -0
index 250dc97..84df4bd 100644
@@ -1310,6 +1310,12 @@ T:	git git://git.xilinx.com/linux-xlnx.git
 S:	Supported
 F:	arch/arm/mach-zynq/
 
+ARM SMMU DRIVER
+M:	Will Deacon <[email protected]>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	drivers/iommu/arm-smmu.c
+
 ARM64 PORT (AARCH64 ARCHITECTURE)
 M:	Catalin Marinas <[email protected]>
 M:	Will Deacon <[email protected]>
Signature · 1 line
1.8.2.2
#50 lore raw

PATCH 9/9 MAINTAINERS: add entry for ARM system MMU driver

Quoted 3 lines · Will Deacon

Add myself as maintainer for the ARM system MMU driver.

Quoted 29 lines
---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)
MAINTAINERS +6 -0
index 250dc97..84df4bd 100644
@@ -1310,6 +1310,12 @@ T:	git git://git.xilinx.com/linux-xlnx.git
 S:	Supported
 F:	arch/arm/mach-zynq/
 
+ARM SMMU DRIVER
+M:	Will Deacon <[email protected]>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	drivers/iommu/arm-smmu.c
+
 ARM64 PORT (AARCH64 ARCHITECTURE)
 M:	Catalin Marinas <[email protected]>
 M:	Will Deacon <[email protected]>
Signature · 7 lines
1.8.2.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 2 lines
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies, Ltd.