Re: [Patch Part3 V5 5/8] iommu/vt-d: Enhance intel_irq_remapping driver to support DMAR unit hotplug
On 2014/9/15 10:20, Yijing Wang wrote: +static void ir_remove_ioapic_hpet_scope(struct intel_iommu *iommu) +{ +int i; -ir_parse_one_hpet_scope(scope, iommu); -} -start += scope-length; -} +for (i = 0; i MAX_HPET_TBS; i++) +if (ir_hpet[i].iommu == iommu) +ir_hpet[i].iommu = NULL; Hi Gerry, why not reset whole ir_hpe and ir_ioapic data struct? Hi Yijing, Thanks for review. Zero is legal for id, bus and devfn in struct ioapic_scope and struct hpet_scope. So we use domain field as a flag to mark entry valid or invalid and only reset iommu field. Regards! Gerry -return 0; +for (i = 0; i MAX_IO_APICS; i++) +if (ir_ioapic[i].iommu == iommu) +ir_ioapic[i].iommu = NULL; } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part3 V5 1/8] iommu/vt-d: Introduce helper function dmar_walk_resources()
On 2014/9/12 17:16, Yijing Wang wrote: On 2014/9/12 10:10, Jiang Liu wrote: Introduce helper function dmar_walk_resources to walk resource entries in DMAR table and ACPI buffer object returned by ACPI _DSM method for IOMMU hot-plug. Signed-off-by: Jiang Liu jiang@linux.intel.com Hi Gerry. some comments below. Hi Yijing, Thanks for review. Please refer inline comments below. --- drivers/iommu/dmar.c| 209 +++ drivers/iommu/intel-iommu.c |4 +- include/linux/dmar.h| 19 ++-- 3 files changed, 122 insertions(+), 110 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 60ab474bfff3..afd46eb9a5de 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -44,6 +44,14 @@ #include irq_remapping.h +typedef int (*dmar_res_handler_t)(struct acpi_dmar_header *, void *); +struct dmar_res_callback { +dmar_res_handler_t cb[ACPI_DMAR_TYPE_RESERVED]; +void*arg[ACPI_DMAR_TYPE_RESERVED]; +boolignore_unhandled; +boolprint_entry; Why do we need a switch to control print ? We will walk DMAR entries several times during hotplug and only want to print once. +}; + +static int dmar_walk_resources(struct acpi_dmar_header *start, size_t len, + struct dmar_res_callback *cb) The name dmar_walk_resources easily make people think this is related with I/O or memory resources. Do you have a better idea of this ? What about dmar_walk_remapping_entry() or dmar_walk_remapping_structure() ? Good suggestion, I like dmar_walk_remapping_entries(). +{ +int ret = 0; +struct acpi_dmar_header *iter, *next; +struct acpi_dmar_header *end = ((void *)start) + len; + +for (iter = start; iter end ret == 0; iter = next) { +next = (void *)iter + iter-length; +if (iter-length == 0) { +/* Avoid looping forever on bad ACPI tables */ +pr_debug(FW_BUG Invalid 0-length structure\n); What about use pr_warn() instead of pr_debug(), pr_debug() default is off. It seems a common practice for BIOS engineer to mark the last entry with zero length. So it will be annoying if we generate this debug message on product kernel. +break; +} else if (next end) { +/* Avoid passing table end */ +pr_warn(FW_BUG record passes table end\n); +ret = -EINVAL; +break; +} + +if (cb-print_entry) +dmar_table_print_dmar_entry(iter); + +if (iter-type = ACPI_DMAR_TYPE_RESERVED) { +/* continue for forward compatibility */ +pr_debug(Unknown DMAR structure type %d\n, + iter-type); Same as above. This is typically caused by new DMAR specification. It will also be annoying too if we also generate this debug message on an newer hardware platform with older linux kernel. +} else if (cb-cb[iter-type]) { +ret = cb-cb[iter-type](iter, cb-arg[iter-type]); +} else if (!cb-ignore_unhandled) { +pr_warn(No handler for DMAR structure type %d\n, +iter-type); +ret = -EINVAL; +} +} + +return ret; +} + +static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar, + struct dmar_res_callback *cb) +{ +return dmar_walk_resources((struct acpi_dmar_header *)(dmar + 1), + dmar-header.length - sizeof(*dmar), cb); +} + /** * parse_dmar_table - parses the DMA reporting table */ @@ -493,9 +554,18 @@ static int __init parse_dmar_table(void) { struct acpi_table_dmar *dmar; -struct acpi_dmar_header *entry_header; int ret = 0; int drhd_count = 0; +struct dmar_res_callback cb = { +.print_entry = true, +.ignore_unhandled = true, +.arg[ACPI_DMAR_TYPE_HARDWARE_UNIT] = drhd_count, +.cb[ACPI_DMAR_TYPE_HARDWARE_UNIT] = dmar_parse_one_drhd, +.cb[ACPI_DMAR_TYPE_RESERVED_MEMORY] = dmar_parse_one_rmrr, +.cb[ACPI_DMAR_TYPE_ROOT_ATS] = dmar_parse_one_atsr, +.cb[ACPI_DMAR_TYPE_HARDWARE_AFFINITY] = dmar_parse_one_rhsa, +.cb[ACPI_DMAR_TYPE_NAMESPACE] = dmar_parse_one_andd, +}; /* * Do it again, earlier dmar_tbl mapping could be mapped with @@ -519,51 +589,10 @@ parse_dmar_table(void) } pr_info(Host address width %d\n, dmar-width + 1); - -entry_header = (struct acpi_dmar_header *)(dmar + 1); -while (((unsigned long)entry_header) -(((unsigned long)dmar) + dmar_tbl-length)) { -/*
Re: [Patch Part3 V5 0/8] Enable support of Intel DMAR device hotplug
On 2014/9/15 15:54, Yijing Wang wrote: I built and boot this series in Huawei RH5885 (Intel(R) Xeon(R) CPU E7- 4807, two IOHs and two IOMMUs), It works fine, IRQ remap and DMA remap are both look good. But because my platform BIOS has no _DSM, so I didn't test the hotplug case yet. Thanks! Yijing. Hi Yijing, Thanks for your great effort to review and test this patch set! Regards! Gerry On 2014/9/12 10:10, Jiang Liu wrote: When hot plugging a descrete IOH or a physical processor with embedded IIO, we need to handle DMAR(or IOMMU) unit in the PCIe host bridge if DMAR is in use. This patch set tries to enhance current DMAR/IOMMU/IR drivers to support hotplug and is based on latest Linus master branch. All prerequisite patches to support DMAR device hotplug have been merged into the mainstream kernel, and this is the last patch set to enable DMAR device hotplug. You may access the patch set at: https://github.com/jiangliu/linux.git iommu/hotplug_v5 This patch set has been tested on Intel development machine. Appreciate any comments and tests. Patch 1-4 enhances DMAR framework to support hotplug Patch 5 enhances Intel interrupt remapping driver to support hotplug Patch 6 enhances error handling in Intel IR driver Patch 7 enhance Intel IOMMU to support hotplug Patch 8 enhance ACPI pci_root driver to handle DMAR units Jiang Liu (8): iommu/vt-d: Introduce helper function dmar_walk_resources() iommu/vt-d: Dynamically allocate and free seq_id for DMAR units iommu/vt-d: Implement DMAR unit hotplug framework iommu/vt-d: Search for ACPI _DSM method for DMAR hotplug iommu/vt-d: Enhance intel_irq_remapping driver to support DMAR unit hotplug iommu/vt-d: Enhance error recovery in function intel_enable_irq_remapping() iommu/vt-d: Enhance intel-iommu driver to support DMAR unit hotplug pci, ACPI, iommu: Enhance pci_root to support DMAR device hotplug drivers/acpi/pci_root.c | 16 +- drivers/iommu/dmar.c| 532 --- drivers/iommu/intel-iommu.c | 297 ++- drivers/iommu/intel_irq_remapping.c | 233 +++ include/linux/dmar.h| 50 +++- 5 files changed, 888 insertions(+), 240 deletions(-) ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part3 V5 5/8] iommu/vt-d: Enhance intel_irq_remapping driver to support DMAR unit hotplug
On 2014/9/16 15:00, Jiang Liu wrote: On 2014/9/15 10:20, Yijing Wang wrote: +static void ir_remove_ioapic_hpet_scope(struct intel_iommu *iommu) +{ + int i; - ir_parse_one_hpet_scope(scope, iommu); - } - start += scope-length; - } + for (i = 0; i MAX_HPET_TBS; i++) + if (ir_hpet[i].iommu == iommu) + ir_hpet[i].iommu = NULL; Hi Gerry, why not reset whole ir_hpe and ir_ioapic data struct? Hi Yijing, Thanks for review. Zero is legal for id, bus and devfn in struct ioapic_scope and struct hpet_scope. So we use domain field as a flag to mark entry valid or invalid and only reset iommu field. Hi Gerry, use iommu field as a flag to mark entry valid may be not safe enough, I found map_hpet_to_ir() and map_ioapic_to_ir() still only check the id field to return the valid iommu. What about this case: E.g. ir_hpet[2].id = N, ir_hpet[2].iommu = NULL, ir_hpet[4].id = N, ir_hpet[4].iommu = iommu; ir_hpet[2] maybe released yet, and the hpet now has been saved in ir_hpet[4], but map_hpet_to_irq() will return the wrong iommu(NULL). static struct intel_iommu *map_hpet_to_ir(u8 hpet_id) { int i; for (i = 0; i MAX_HPET_TBS; i++) if (ir_hpet[i].id == hpet_id) return ir_hpet[i].iommu; return NULL; } Regards! Gerry - return 0; + for (i = 0; i MAX_IO_APICS; i++) + if (ir_ioapic[i].iommu == iommu) + ir_ioapic[i].iommu = NULL; } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ . -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part3 V5 1/8] iommu/vt-d: Introduce helper function dmar_walk_resources()
#include irq_remapping.h +typedef int (*dmar_res_handler_t)(struct acpi_dmar_header *, void *); +struct dmar_res_callback { + dmar_res_handler_t cb[ACPI_DMAR_TYPE_RESERVED]; + void*arg[ACPI_DMAR_TYPE_RESERVED]; + boolignore_unhandled; + boolprint_entry; Why do we need a switch to control print ? We will walk DMAR entries several times during hotplug and only want to print once. Fine, thanks for your explanation. +}; + +static int dmar_walk_resources(struct acpi_dmar_header *start, size_t len, + struct dmar_res_callback *cb) The name dmar_walk_resources easily make people think this is related with I/O or memory resources. Do you have a better idea of this ? What about dmar_walk_remapping_entry() or dmar_walk_remapping_structure() ? Good suggestion, I like dmar_walk_remapping_entries(). +{ + int ret = 0; + struct acpi_dmar_header *iter, *next; + struct acpi_dmar_header *end = ((void *)start) + len; + + for (iter = start; iter end ret == 0; iter = next) { + next = (void *)iter + iter-length; + if (iter-length == 0) { + /* Avoid looping forever on bad ACPI tables */ + pr_debug(FW_BUG Invalid 0-length structure\n); What about use pr_warn() instead of pr_debug(), pr_debug() default is off. It seems a common practice for BIOS engineer to mark the last entry with zero length. So it will be annoying if we generate this debug message on product kernel. OK. + break; + } else if (next end) { + /* Avoid passing table end */ + pr_warn(FW_BUG record passes table end\n); + ret = -EINVAL; + break; + } + + if (cb-print_entry) + dmar_table_print_dmar_entry(iter); + + if (iter-type = ACPI_DMAR_TYPE_RESERVED) { + /* continue for forward compatibility */ + pr_debug(Unknown DMAR structure type %d\n, +iter-type); Same as above. This is typically caused by new DMAR specification. It will also be annoying too if we also generate this debug message on an newer hardware platform with older linux kernel. OK. + } else if (cb-cb[iter-type]) { + ret = cb-cb[iter-type](iter, cb-arg[iter-type]); + } else if (!cb-ignore_unhandled) { + pr_warn(No handler for DMAR structure type %d\n, ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [Patch Part3 V5 5/8] iommu/vt-d: Enhance intel_irq_remapping driver to support DMAR unit hotplug
On 2014/9/16 15:53, Yijing Wang wrote: On 2014/9/16 15:00, Jiang Liu wrote: On 2014/9/15 10:20, Yijing Wang wrote: +static void ir_remove_ioapic_hpet_scope(struct intel_iommu *iommu) +{ + int i; - ir_parse_one_hpet_scope(scope, iommu); - } - start += scope-length; - } + for (i = 0; i MAX_HPET_TBS; i++) + if (ir_hpet[i].iommu == iommu) + ir_hpet[i].iommu = NULL; Hi Gerry, why not reset whole ir_hpe and ir_ioapic data struct? Hi Yijing, Thanks for review. Zero is legal for id, bus and devfn in struct ioapic_scope and struct hpet_scope. So we use domain field as a flag to mark entry valid or invalid and only reset iommu field. Hi Gerry, use iommu field as a flag to mark entry valid may be not safe enough, I found map_hpet_to_ir() and map_ioapic_to_ir() still only check the id field to return the valid iommu. What about this case: E.g. ir_hpet[2].id = N, ir_hpet[2].iommu = NULL, ir_hpet[4].id = N, ir_hpet[4].iommu = iommu; ir_hpet[2] maybe released yet, and the hpet now has been saved in ir_hpet[4], but map_hpet_to_irq() will return the wrong iommu(NULL). Hi Yijing, Good catch, I will enhance map_hpet_to_ir() and map_ioapic_to_ir(). Regards! Gerry static struct intel_iommu *map_hpet_to_ir(u8 hpet_id) { int i; for (i = 0; i MAX_HPET_TBS; i++) if (ir_hpet[i].id == hpet_id) return ir_hpet[i].iommu; return NULL; } Regards! Gerry - return 0; + for (i = 0; i MAX_IO_APICS; i++) + if (ir_ioapic[i].iommu == iommu) + ir_ioapic[i].iommu = NULL; } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ . ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v1 03/21] MSI: Remove the redundant irq_set_chip_data()
arch_teardown_msi_irq() expects to find the msi_chip in the irq chip_data field. As this means drivers don't have any reasonable other possibility to stuff things into this field, I think it would make sense to do the cleanup the other way around: keep the irq_set_chip_data arch_setup_msi_irq() and rip it out of the individual drivers. Hi Lucas, thanks for your review and comments! irq_set_chip_data() should not be placed in MSI core functions, because other arch like x86, use irq_data-chip_data to stores irq_cfg. So how to set the chip_data is arch dependent. And this series is mainly to use MSI chip framework in all platforms. Currently, only ARM platform MSI drivers use the chip_data to store msi_chip, and the drivers call irq_set_chip_data() in their driver already. So I thought we should clean up it in MSI core code. Okay I see your point, so the cleanup done this way is okay. But then this still introduces a problem: arch_teardown_msi_irq() expects to find the msi_chip in the chip_data field, which is okay for all ARM PCI host drivers, but not for other arch MSI chips. You fix this by completely removing arch_teardown_msi_irq() at the end of the series, but this still has the potential to introduce issues for other arches than ARM within the series. So this patch should include a change to replace the line struct msi_chip *chip = irq_get_chip_data(irq); with something that doesn't rely on the msi_chip being in the irq chip_data field. OK, I will update arch_teardown_msi_irq() in this patch, thanks! Thanks! Yijing. Regards, Lucas -- Thanks! Yijing ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 06/18] iommu: exynos: don't read version register on every tlb operation
This patch removes reading of REG_MMU_VERSION register on every tlb operation and caches SYSMMU version in driver's internal data. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- drivers/iommu/exynos-iommu.c | 13 + 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index d037e87a1fe5..73499b05e62e 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -212,6 +212,7 @@ struct sysmmu_drvdata { spinlock_t lock; struct iommu_domain *domain; phys_addr_t pgtable; + int version; }; static bool set_sysmmu_active(struct sysmmu_drvdata *data) @@ -238,11 +239,6 @@ static void sysmmu_unblock(void __iomem *sfrbase) __raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL); } -static unsigned int __raw_sysmmu_version(struct sysmmu_drvdata *data) -{ - return MMU_RAW_VER(__raw_readl(data-sfrbase + REG_MMU_VERSION)); -} - static bool sysmmu_block(void __iomem *sfrbase) { int i = 120; @@ -402,7 +398,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata *data) unsigned int cfg = CFG_LRU | CFG_QOS(15); unsigned int ver; - ver = __raw_sysmmu_version(data); + ver = MMU_RAW_VER(__raw_readl(data-sfrbase + REG_MMU_VERSION)); if (MMU_MAJ_VER(ver) == 3) { if (MMU_MIN_VER(ver) = 2) { cfg |= CFG_FLPDCACHE; @@ -416,6 +412,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata *data) } __raw_writel(cfg, data-sfrbase + REG_MMU_CFG); + data-version = ver; } static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data) @@ -525,7 +522,7 @@ static bool exynos_sysmmu_disable(struct device *dev) static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data, sysmmu_iova_t iova) { - if (__raw_sysmmu_version(data) == MAKE_MMU_VER(3, 3)) + if (data-version == MAKE_MMU_VER(3, 3)) __raw_writel(iova | 0x1, data-sfrbase + REG_MMU_FLUSH_ENTRY); } @@ -574,7 +571,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova, * 1MB page can be cached in one of all sets. * 64KB page can be one of 16 consecutive sets. */ - if (MMU_MAJ_VER(__raw_sysmmu_version(data)) == 2) + if (MMU_MAJ_VER(data-version) == 2) num_inv = min_t(unsigned int, size / PAGE_SIZE, 64); if (sysmmu_block(data-sfrbase)) { -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 04/18] clk: exynos: add missing smmu_g2d clock and update comments
This patch adds missing smmu_g2d clock implementation and updates comment about Exynos4 clocks from 278-282 range. Those clocks are available on all Exynos4 SoC series, so the misleading comment has been removed. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com Acked-by: Tomasz Figa t.f...@samsung.com --- drivers/clk/samsung/clk-exynos4.c | 1 + include/dt-bindings/clock/exynos4.h | 10 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index ac163d7f5bc3..12a7cc3b5953 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1183,6 +1183,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { GATE(CLK_SPI1_ISP, spi1_isp, aclk200, E4X12_GATE_ISP1, 13, CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), GATE(CLK_G2D, g2d, aclk200, GATE_IP_DMC, 23, 0, 0), + GATE(CLK_SMMU_G2D, smmu_g2d, aclk200, GATE_IP_DMC, 24, 0, 0), GATE(CLK_TMU_APBIF, tmu_apbif, aclk100, E4X12_GATE_IP_PERIR, 17, 0, 0), }; diff --git a/include/dt-bindings/clock/exynos4.h b/include/dt-bindings/clock/exynos4.h index 459bd2bd411f..fb9816354079 100644 --- a/include/dt-bindings/clock/exynos4.h +++ b/include/dt-bindings/clock/exynos4.h @@ -115,11 +115,11 @@ #define CLK_SMMU_MFCR 275 #define CLK_G3D276 #define CLK_G2D277 -#define CLK_ROTATOR278 /* Exynos4210 only */ -#define CLK_MDMA 279 /* Exynos4210 only */ -#define CLK_SMMU_G2D 280 /* Exynos4210 only */ -#define CLK_SMMU_ROTATOR 281 /* Exynos4210 only */ -#define CLK_SMMU_MDMA 282 /* Exynos4210 only */ +#define CLK_ROTATOR278 +#define CLK_MDMA 279 +#define CLK_SMMU_G2D 280 +#define CLK_SMMU_ROTATOR 281 +#define CLK_SMMU_MDMA 282 #define CLK_FIMD0 283 #define CLK_MIE0 284 #define CLK_MDNIE0 285 /* Exynos4412 only */ -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 00/18] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem
Hello Everyone, This is yet another attempt to finally make Exynos SYSMMU driver fully integrated with DMA-mapping subsystem. Previous approach is available here: https://lkml.org/lkml/2014/8/5/183 I meantime, there have been a discussion about the way the iommu driver should be integrated with dma-mapping subsystem, which resulted in [RFC PATCH v3 0/7] Introduce automatic DMA configuration for IOMMU masters patches prepared by Will Deacon: http://www.spinics.net/lists/arm-kernel/msg362076.html Those patches removed the need to use bus-specific notifiers for initialization. Main changes since previous version of my patches: 1. rebased onto [RFC PATCH v3 0/7] Introduce automatic DMA configuration for IOMMU masters patches, changed initialization from bus notifiers to DT related callbacks 2. removed support for separate IO address spaces - this will be discussed separately after the basic support gets merged 3. removed support for power domain notifier-based runtime power management - this also will be discussed separately later I hope that the driver with above changes will be easier to be merged to v3.18. Best regards Marek Szyprowski Samsung RD Institute Poland Patch summary: Marek Szyprowski (18): arm: dma-mapping: arm_iommu_attach_device: automatically set max_seg_size arm: exynos: bind power domains earlier, on device creation drm: exynos: detach from default dma-mapping domain on init clk: exynos: add missing smmu_g2d clock and update comments ARM: DTS: Exynos4: add System MMU nodes iommu: exynos: don't read version register on every tlb operation iommu: exynos: remove unused functions iommu: exynos: remove useless spinlock iommu: exynos: refactor function parameters to simplify code iommu: exynos: remove unused functions, part 2 iommu: exynos: remove useless device_add/remove callbacks iommu: exynos: add support for binding more than one sysmmu to master device iommu: exynos: add support for runtime_pm iommu: exynos: rename variables to reflect their purpose iommu: exynos: document internal structures iommu: exynos: remove excessive includes and sort others alphabetically iommu: exynos: init from dt-specific callback instead of initcall iommu: exynos: add callback for initializing devices from device tree arch/arm/boot/dts/exynos4.dtsi| 117 +++ arch/arm/boot/dts/exynos4210.dtsi | 23 ++ arch/arm/boot/dts/exynos4x12.dtsi | 82 + arch/arm/mach-exynos/pm_domains.c | 12 +- arch/arm/mm/dma-mapping.c | 16 + drivers/clk/samsung/clk-exynos4.c | 1 + drivers/gpu/drm/exynos/exynos_drm_iommu.c | 3 + drivers/iommu/exynos-iommu.c | 494 ++ include/dt-bindings/clock/exynos4.h | 10 +- 9 files changed, 483 insertions(+), 275 deletions(-) -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 01/18] arm: dma-mapping: arm_iommu_attach_device: automatically set max_seg_size
If device has no max_seg_size set, we assume that there is no limit and force it to DMA_BIT_MASK(32) to always use contiguous mappings in DMA address space. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- arch/arm/mm/dma-mapping.c | 16 1 file changed, 16 insertions(+) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index bcd5f836f27e..84705e24571b 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -2050,6 +2050,22 @@ int arm_iommu_attach_device(struct device *dev, { int err; + /* +* if device has no max_seg_size set, we assume that there is no limit +* and force it to DMA_BIT_MASK(32) to always use contiguous mappings +* in DMA address space +*/ + if (!dev-dma_parms) { + dev-dma_parms = kzalloc(sizeof(*dev-dma_parms), GFP_KERNEL); + if (!dev-dma_parms) + return -ENOMEM; + } + if (!dev-dma_parms-max_segment_size) { + err = dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + if (err) + return err; + } + err = iommu_attach_device(mapping-domain, dev); if (err) return err; -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 02/18] arm: exynos: bind power domains earlier, on device creation
This patches change initialization time of power domain driver from client device driver bind to device creation. This lets other core drivers to register power domain notifiers before client driver is bound. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- arch/arm/mach-exynos/pm_domains.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index fd76e1b5a471..1d368a26528c 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c @@ -159,13 +159,13 @@ static int exynos_pm_notifier_call(struct notifier_block *nb, struct device *dev = data; switch (event) { - case BUS_NOTIFY_BIND_DRIVER: + case BUS_NOTIFY_ADD_DEVICE: if (dev-of_node) exynos_read_domain_from_dt(dev); break; - case BUS_NOTIFY_UNBOUND_DRIVER: + case BUS_NOTIFY_DEL_DEVICE: exynos_remove_device_from_domain(dev); break; @@ -177,6 +177,13 @@ static struct notifier_block platform_nb = { .notifier_call = exynos_pm_notifier_call, }; +static int exynos_pm_domain_add(struct device *dev, void *priv) +{ + if (dev-of_node) + exynos_read_domain_from_dt(dev); + return 0; +} + static __init int exynos4_pm_init_power_domain(void) { struct platform_device *pdev; @@ -236,6 +243,7 @@ no_clk: } bus_register_notifier(platform_bus_type, platform_nb); + bus_for_each_dev(platform_bus_type, NULL, NULL, exynos_pm_domain_add); return 0; } -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 05/18] ARM: DTS: Exynos4: add System MMU nodes
This patch adds System MMU nodes that are specific to Exynos4210/4x12 series. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- arch/arm/boot/dts/exynos4.dtsi| 117 ++ arch/arm/boot/dts/exynos4210.dtsi | 23 arch/arm/boot/dts/exynos4x12.dtsi | 82 ++ 3 files changed, 222 insertions(+) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index e0278ecbc816..bfc19ec5 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -174,6 +174,7 @@ clock-names = fimc, sclk_fimc; samsung,power-domain = pd_cam; samsung,sysreg = sys_reg; + iommus = sysmmu_fimc0; status = disabled; }; @@ -185,6 +186,7 @@ clock-names = fimc, sclk_fimc; samsung,power-domain = pd_cam; samsung,sysreg = sys_reg; + iommus = sysmmu_fimc1; status = disabled; }; @@ -196,6 +198,7 @@ clock-names = fimc, sclk_fimc; samsung,power-domain = pd_cam; samsung,sysreg = sys_reg; + iommus = sysmmu_fimc2; status = disabled; }; @@ -207,6 +210,7 @@ clock-names = fimc, sclk_fimc; samsung,power-domain = pd_cam; samsung,sysreg = sys_reg; + iommus = sysmmu_fimc3; status = disabled; }; @@ -395,6 +399,8 @@ clocks = clock CLK_MFC; clock-names = mfc; status = disabled; + iommus = sysmmu_mfc_l, sysmmu_mfc_r; + iommu-names = left, right; }; serial_0: serial@1380 { @@ -643,6 +649,117 @@ clock-names = sclk_fimd, fimd; samsung,power-domain = pd_lcd0; samsung,sysreg = sys_reg; + iommus = sysmmu_fimd0; status = disabled; }; + + sysmmu_mfc_l: sysmmu@1362 { + compatible = samsung,exynos-sysmmu; + reg = 0x1362 0x1000; + interrupt-parent = combiner; + interrupts = 5 5; + clock-names = sysmmu, master; + clocks = clock CLK_SMMU_MFCL, clock CLK_MFC; + samsung,power-domain = pd_mfc; + #iommu-cells = 0; + }; + + sysmmu_mfc_r: sysmmu@1363 { + compatible = samsung,exynos-sysmmu; + reg = 0x1363 0x1000; + interrupt-parent = combiner; + interrupts = 5 6; + clock-names = sysmmu, master; + clocks = clock CLK_SMMU_MFCR, clock CLK_MFC; + samsung,power-domain = pd_mfc; + #iommu-cells = 0; + }; + + sysmmu_tv: sysmmu@12E2 { + compatible = samsung,exynos-sysmmu; + reg = 0x12E2 0x1000; + interrupt-parent = combiner; + interrupts = 5 4; + clock-names = sysmmu, master; + clocks = clock CLK_SMMU_TV, clock CLK_MIXER; + samsung,power-domain = pd_tv; + #iommu-cells = 0; + }; + + sysmmu_fimc0: sysmmu@11A2 { + compatible = samsung,exynos-sysmmu; + reg = 0x11A2 0x1000; + interrupt-parent = combiner; + interrupts = 4 2; + clock-names = sysmmu, master; + clocks = clock CLK_SMMU_FIMC0, clock CLK_FIMC0; + samsung,power-domain = pd_cam; + #iommu-cells = 0; + }; + + sysmmu_fimc1: sysmmu@11A3 { + compatible = samsung,exynos-sysmmu; + reg = 0x11A3 0x1000; + interrupt-parent = combiner; + interrupts = 4 3; + clock-names = sysmmu, master; + clocks = clock CLK_SMMU_FIMC1, clock CLK_FIMC1; + samsung,power-domain = pd_cam; + #iommu-cells = 0; + }; + + sysmmu_fimc2: sysmmu@11A4 { + compatible = samsung,exynos-sysmmu; + reg = 0x11A4 0x1000; + interrupt-parent = combiner; + interrupts = 4 4; + clock-names = sysmmu, master; + clocks = clock CLK_SMMU_FIMC2, clock CLK_FIMC2; + samsung,power-domain = pd_cam; + #iommu-cells = 0; + }; + + sysmmu_fimc3: sysmmu@11A5 { + compatible = samsung,exynos-sysmmu; + reg = 0x11A5 0x1000; + interrupt-parent = combiner; + interrupts = 4 5; + clock-names = sysmmu, master; +
[PATCH v2 07/18] iommu: exynos: remove unused functions
This patch removes two unneeded functions, which are not a part of generic IOMMU API and were never used by any other driver. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- drivers/iommu/exynos-iommu.c | 31 --- 1 file changed, 31 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 73499b05e62e..91feeca56abc 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -490,13 +490,6 @@ static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable, return ret; } -int exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable) -{ - BUG_ON(!memblock_is_memory(pgtable)); - - return __exynos_sysmmu_enable(dev, pgtable, NULL); -} - static bool exynos_sysmmu_disable(struct device *dev) { unsigned long flags; @@ -588,30 +581,6 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova, spin_unlock_irqrestore(data-lock, flags); } -void exynos_sysmmu_tlb_invalidate(struct device *dev) -{ - struct exynos_iommu_owner *owner = dev-archdata.iommu; - unsigned long flags; - struct sysmmu_drvdata *data; - - data = dev_get_drvdata(owner-sysmmu); - - spin_lock_irqsave(data-lock, flags); - if (is_sysmmu_active(data)) { - if (!IS_ERR(data-clk_master)) - clk_enable(data-clk_master); - if (sysmmu_block(data-sfrbase)) { - __sysmmu_tlb_invalidate(data-sfrbase); - sysmmu_unblock(data-sfrbase); - } - if (!IS_ERR(data-clk_master)) - clk_disable(data-clk_master); - } else { - dev_dbg(dev, disabled. Skipping TLB invalidation\n); - } - spin_unlock_irqrestore(data-lock, flags); -} - static int __init exynos_sysmmu_probe(struct platform_device *pdev) { int irq, ret; -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 10/18] iommu: exynos: remove unused functions, part 2
After refactoring functions to use pointer to struct sysmmu_drvdata directly, some functions became useless and thus never used, so remove them completely. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- drivers/iommu/exynos-iommu.c | 43 --- 1 file changed, 43 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index ef30890f4069..b271348a4ec1 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -457,49 +457,6 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data, return ret; } -/* __exynos_sysmmu_enable: Enables System MMU - * - * returns -error if an error occurred and System MMU is not enabled, - * 0 if the System MMU has been just enabled and 1 if System MMU was already - * enabled before. - */ -static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable, - struct iommu_domain *domain) -{ - int ret = 0; - unsigned long flags; - struct exynos_iommu_owner *owner = dev-archdata.iommu; - struct sysmmu_drvdata *data; - - BUG_ON(!has_sysmmu(dev)); - - data = dev_get_drvdata(owner-sysmmu); - - ret = __sysmmu_enable(data, pgtable, domain); - if (ret = 0) - data-master = dev; - - return ret; -} - -static bool exynos_sysmmu_disable(struct device *dev) -{ - unsigned long flags; - bool disabled = true; - struct exynos_iommu_owner *owner = dev-archdata.iommu; - struct sysmmu_drvdata *data; - - BUG_ON(!has_sysmmu(dev)); - - data = dev_get_drvdata(owner-sysmmu); - - disabled = __sysmmu_disable(data); - if (disabled) - data-master = NULL; - - return disabled; -} - static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data, sysmmu_iova_t iova) { -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 08/18] iommu: exynos: remove useless spinlock
This patch removes useless spinlocks and other unused members from struct exynos_iommu_owner. There is no point is protecting this structure by spinlock because content of this structure doesn't change and other structures have their own spinlocks. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- drivers/iommu/exynos-iommu.c | 11 --- 1 file changed, 11 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 91feeca56abc..ae2703ed91d8 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -189,9 +189,6 @@ struct exynos_iommu_owner { struct list_head client; /* entry of exynos_iommu_domain.clients */ struct device *dev; struct device *sysmmu; - struct iommu_domain *domain; - void *vmm_data; /* IO virtual memory manager's data */ - spinlock_t lock;/* Lock to preserve consistency of System MMU */ }; struct exynos_iommu_domain { @@ -477,16 +474,12 @@ static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable, BUG_ON(!has_sysmmu(dev)); - spin_lock_irqsave(owner-lock, flags); - data = dev_get_drvdata(owner-sysmmu); ret = __sysmmu_enable(data, pgtable, domain); if (ret = 0) data-master = dev; - spin_unlock_irqrestore(owner-lock, flags); - return ret; } @@ -499,16 +492,12 @@ static bool exynos_sysmmu_disable(struct device *dev) BUG_ON(!has_sysmmu(dev)); - spin_lock_irqsave(owner-lock, flags); - data = dev_get_drvdata(owner-sysmmu); disabled = __sysmmu_disable(data); if (disabled) data-master = NULL; - spin_unlock_irqrestore(owner-lock, flags); - return disabled; } -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 12/18] iommu: exynos: add support for binding more than one sysmmu to master device
This patch adds support for assigning more than one SYSMMU controller to the master device. This has been achieved simply by chaning the struct device pointer in struct exynos_iommu_owner into the list of struct sysmmu_drvdata of all controllers assigned to the given master device. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- drivers/iommu/exynos-iommu.c | 11 +-- 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 1b3f00726cd4..cf36cdecf335 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -186,7 +186,7 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = { /* attached to dev.archdata.iommu of the master device */ struct exynos_iommu_owner { - struct device *sysmmu; + struct list_head clients; }; struct exynos_iommu_domain { @@ -207,6 +207,7 @@ struct sysmmu_drvdata { spinlock_t lock; struct iommu_domain *domain; struct list_head domain_node; + struct list_head owner_node; phys_addr_t pgtable; int version; }; @@ -694,8 +695,7 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain, if (!has_sysmmu(dev)) return -ENODEV; - data = dev_get_drvdata(owner-sysmmu); - if (data) { + list_for_each_entry(data, owner-clients, owner_node) { ret = __sysmmu_enable(data, pagetable, domain); if (ret = 0) { data-master = dev; @@ -723,7 +723,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain, { struct exynos_iommu_domain *priv = domain-priv; phys_addr_t pagetable = virt_to_phys(priv-pgtable); - struct sysmmu_drvdata *data; + struct sysmmu_drvdata *data, *next; unsigned long flags; int found = 0; @@ -731,14 +731,13 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain, return; spin_lock_irqsave(priv-lock, flags); - list_for_each_entry(data, priv-clients, domain_node) { + list_for_each_entry_safe(data, next, priv-clients, domain_node) { if (data-master == dev) { if (__sysmmu_disable(data)) { data-master = NULL; list_del_init(data-domain_node); } found = true; - break; } } spin_unlock_irqrestore(priv-lock, flags); -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 11/18] iommu: exynos: remove useless device_add/remove callbacks
The driver doesn't need to do anything important in device add/remove callbacks, because initialization will be done from device-tree specific callbacks added later. IOMMU groups created by current code were never used. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- drivers/iommu/exynos-iommu.c | 28 1 file changed, 28 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index b271348a4ec1..1b3f00726cd4 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1055,32 +1055,6 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain, return phys; } -static int exynos_iommu_add_device(struct device *dev) -{ - struct iommu_group *group; - int ret; - - group = iommu_group_get(dev); - - if (!group) { - group = iommu_group_alloc(); - if (IS_ERR(group)) { - dev_err(dev, Failed to allocate IOMMU group\n); - return PTR_ERR(group); - } - } - - ret = iommu_group_add_device(group, dev); - iommu_group_put(group); - - return ret; -} - -static void exynos_iommu_remove_device(struct device *dev) -{ - iommu_group_remove_device(dev); -} - static const struct iommu_ops exynos_iommu_ops = { .domain_init = exynos_iommu_domain_init, .domain_destroy = exynos_iommu_domain_destroy, @@ -1089,8 +1063,6 @@ static const struct iommu_ops exynos_iommu_ops = { .map = exynos_iommu_map, .unmap = exynos_iommu_unmap, .iova_to_phys = exynos_iommu_iova_to_phys, - .add_device = exynos_iommu_add_device, - .remove_device = exynos_iommu_remove_device, .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE, }; -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 17/18] iommu: exynos: init from dt-specific callback instead of initcall
This patch introduces IOMMU_OF_DECLARE-based initialization to the driver, which replaces subsys_initcall-based procedure. exynos_iommu_of_setup ensures that each sysmmu controller is probed before its master device. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- drivers/iommu/exynos-iommu.c | 32 +++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 5eb999d7653a..0d304c62956e 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -13,16 +13,21 @@ #endif #include linux/clk.h +#include linux/dma-mapping.h #include linux/err.h #include linux/io.h #include linux/iommu.h #include linux/interrupt.h #include linux/list.h +#include linux/of.h +#include linux/of_iommu.h +#include linux/of_platform.h #include linux/platform_device.h #include linux/pm_runtime.h #include linux/slab.h #include asm/cacheflush.h +#include asm/dma-iommu.h #include asm/pgtable.h typedef u32 sysmmu_iova_t; @@ -1083,6 +1088,8 @@ static const struct iommu_ops exynos_iommu_ops = { .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE, }; +static int init_done; + static int __init exynos_iommu_init(void) { int ret; @@ -1115,6 +1122,8 @@ static int __init exynos_iommu_init(void) goto err_set_iommu; } + init_done = true; + return 0; err_set_iommu: kmem_cache_free(lv2table_kmem_cache, zero_lv2_table); @@ -1124,4 +1133,25 @@ err_reg_driver: kmem_cache_destroy(lv2table_kmem_cache); return ret; } -subsys_initcall(exynos_iommu_init); + +static struct iommu_data exynos_of_data = { + .ops = exynos_iommu_ops, +}; + +static int __init exynos_iommu_of_setup(struct device_node *np) +{ + struct platform_device *pdev; + + if (!init_done) + exynos_iommu_init(); + + pdev = of_platform_device_create(np, NULL, platform_bus_type.dev_root); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + of_iommu_set_data(np, exynos_of_data); + return 0; +} + +IOMMU_OF_DECLARE(exynos_iommu_of, samsung,exynos-sysmmu, +exynos_iommu_of_setup); -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 16/18] iommu: exynos: remove excessive includes and sort others alphabetically
Removed following unused includes: linux/mm.h, linux/errno.h, linux/memblock.h and linux/export.h. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- drivers/iommu/exynos-iommu.c | 14 +- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index a75b06365f97..5eb999d7653a 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -12,19 +12,15 @@ #define DEBUG #endif -#include linux/io.h -#include linux/interrupt.h -#include linux/platform_device.h -#include linux/slab.h -#include linux/pm_runtime.h #include linux/clk.h #include linux/err.h -#include linux/mm.h +#include linux/io.h #include linux/iommu.h -#include linux/errno.h +#include linux/interrupt.h #include linux/list.h -#include linux/memblock.h -#include linux/export.h +#include linux/platform_device.h +#include linux/pm_runtime.h +#include linux/slab.h #include asm/cacheflush.h #include asm/pgtable.h -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 18/18] iommu: exynos: add callback for initializing devices from device tree
This patch adds implementation of of_xlate callback, which prepares masters device for attaching to IOMMU. This callback is called during creating devices from device tree. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- drivers/iommu/exynos-iommu.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 0d304c62956e..6b8fe57d17f2 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1077,6 +1077,33 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain, return phys; } +static int exynos_iommu_of_xlate(struct device *dev, +struct of_phandle_args *spec) +{ + struct exynos_iommu_owner *owner = dev-archdata.iommu; + struct platform_device *sysmmu = of_find_device_by_node(spec-np); + struct sysmmu_drvdata *data; + + if (!sysmmu) + return 0; + + data = platform_get_drvdata(sysmmu); + if (!data) + return 0; + + if (!owner) { + owner = kzalloc(sizeof(*owner), GFP_KERNEL); + if (!owner) + return 0; + + INIT_LIST_HEAD(owner-clients); + dev-archdata.iommu = owner; + } + + list_add_tail(data-owner_node, owner-clients); + return 1; +} + static const struct iommu_ops exynos_iommu_ops = { .domain_init = exynos_iommu_domain_init, .domain_destroy = exynos_iommu_domain_destroy, @@ -1086,6 +1113,7 @@ static const struct iommu_ops exynos_iommu_ops = { .unmap = exynos_iommu_unmap, .iova_to_phys = exynos_iommu_iova_to_phys, .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE, + .of_xlate = exynos_iommu_of_xlate, }; static int init_done; -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 15/18] iommu: exynos: document internal structures
Add a few words of comment to all internal structures used by the driver. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com --- drivers/iommu/exynos-iommu.c | 49 +--- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index ae61d0680b9a..a75b06365f97 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -184,32 +184,49 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = { UNKNOWN FAULT }; -/* attached to dev.archdata.iommu of the master device */ +/* + * This structure is attached to dev.archdata.iommu of the master device + * on device add, contains a list of SYSMMU controllers defined by device tree, + * which are bound to given master device. It is usually referenced by 'owner' + * pointer. + */ struct exynos_iommu_owner { - struct list_head clients; + struct list_head clients; /* list of sysmmu_drvdata.owner_node */ }; +/* + * This structure is stored in -priv field of generic struct iommu_domain, + * contains list of SYSMMU controllers from all master devices, which has been + * attached to this domain and page tables of IO address space defined by this + * domain. It is usually referenced by 'domain' pointer. + */ struct exynos_iommu_domain { - struct list_head clients; /* list of sysmmu_drvdata.node */ + struct list_head clients; /* list of sysmmu_drvdata.domain_node */ sysmmu_pte_t *pgtable; /* lv1 page table, 16KB */ short *lv2entcnt; /* free lv2 entry counter for each section */ - spinlock_t lock; /* lock for this structure */ + spinlock_t lock; /* lock for modyfying list of clients */ spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */ }; +/* + * This structure hold all data of a single SYSMMU controller, this includes + * hw resources like registers and clocks, pointers and list nodes to connect + * it to all other structures, internal state and parameters read from device + * tree. It is usually referenced by 'data' pointer. + */ struct sysmmu_drvdata { - struct device *sysmmu; /* System MMU's device descriptor */ - struct device *master; /* Owner of system MMU */ - void __iomem *sfrbase; - struct clk *clk; - struct clk *clk_master; - int activations; - spinlock_t lock; - struct iommu_domain *domain; - struct list_head domain_node; - struct list_head owner_node; - phys_addr_t pgtable; - int version; + struct device *sysmmu; /* SYSMMU controller device */ + struct device *master; /* master device (owner of given SYSMMU) */ + void __iomem *sfrbase; /* our registers */ + struct clk *clk; /* SYSMMU's clock */ + struct clk *clk_master; /* master's device clock */ + int activations; /* number of calls to sysmmu_enable */ + spinlock_t lock; /* lock for modyfying enable/disable state */ + struct iommu_domain *domain; /* domain we belong to */ + struct list_head domain_node; /* node for domain clients list */ + struct list_head owner_node; /* node for owner clients list */ + phys_addr_t pgtable; /* assigned page table structure */ + int version; /* our version */ }; static bool set_sysmmu_active(struct sysmmu_drvdata *data) -- 1.9.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
RE: [RFC][PATCH] devicetree: Add master-id-bits property to the iommu device
Hi Arnd, -Original Message- From: iommu-boun...@lists.linux-foundation.org [mailto:iommu- boun...@lists.linux-foundation.org] On Behalf Of Arnd Bergmann Sent: Monday, September 15, 2014 10:27 PM To: Sethi Varun-B16395 Cc: mark.rutl...@arm.com; devicet...@vger.kernel.org; swar...@nvidia.com; will.dea...@arm.com; Yoder Stuart-B08248; robh...@kernel.org; iommu@lists.linux-foundation.org; thierry.red...@gmail.com; linux-arm-ker...@lists.infradead.org Subject: Re: [RFC][PATCH] devicetree: Add master-id-bits property to the iommu device On Monday 15 September 2014, Varun Sethi wrote: This seems rather specific to MMU-500. I don't think that most IOMMUs would use the term 'master ID', 'stream ID' or even the general concept, and you don't expand the acronym 'TBU'. I've seen many IOMMUs and I don't even know what that means. TBU refers to the translation buffer unit, which is responsible for caching page translations. In case of translation miss in the cache, translation request is forwarded to the TCU (Translation control unit). The master id forwarded to TCU would also contain the TBU ID. Using the master-id-bits property we can mask out the additional TBU bits at the TCU. This is a cause of concern when we want to share master id for devices which are connected to different TBUs. We have a hot pluggable bus architecture, where a device group can have multiple devices connected to different TBUs. So, we need a mechanism to mask out additional TBIU bits. Ok, I think I understand now Why do you think this is something that is needed to be known at the global level, rather than a property for some individual drivers? In case of Freescale Layerscape SOCs, number of bits used for defining a stream id are specific to a given platform. Are you suggesting that this property should be added to the master device node, rather than the iommu node? Most importantly, I think this needs to be part of the (iommu) device specific binding, not the generic binding that is used for all iommus that may or may not have this concept. I believe in case of the ARM SMMU, it should actually go into the master node as part of the 'iommus' property, because the mask can be different for each master. If your IOMMU has a fixed mask that is used for all devices, that's fine and you can put it into the iommu node itself but document it in the binding for your IOMMU. For hot-pluggable buses, you probably need to have the 'iommus' property in the node that corresponds to the bus controller, and that will have a mask that is used for all devices plugged into it. Can I add a note to the generic binding about representing the mask as a part of the iommus property. This would similar to the note about the dma-ranges -Varun ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [RFC PATCH v3 0/7] Introduce automatic DMA configuration for IOMMU masters
On Tue, Sep 16, 2014 at 12:40:27PM +0100, Robin Murphy wrote: On 12/09/14 17:34, Will Deacon wrote: Here is version three of the RFC I've previously posted here: RFCv1: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-August/283023.html RFCv2: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-September/283752.html Changes since RFCv2 include: - Put the iommu_ops in iommu_data so of_iommu_configure can avoid using the bus_type - Initialise the offset and DMA masks on the dev in of_dma_configure instead of in the arch callback (as this would cause a regression on some architectures) - Added deconfigure/teardown code based on ref counting the iommu_dma_mapping - A bunch of small fixes (_OF_DECLARE, some code shuffling, fix multiple IOMMU parsing) All feedback welcome. Hopefully this is now at a point where people can start looking to port dma-mapping and/or IOMMU drivers to it. What about AMBA devices? Playing with this on Juno and wondering why my PL330 doesn't get any of_xlate callbacks, I see that of_amba_device_create doesn't call of_dma_configure or anything from that path. It's easy to work around by removing the arm,primecell compatible, but that feels pretty dirty. Yeah, that's just a bug in mainline. I'll look at fixing it if you don't beat me to it. Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [RFC PATCH v3 3/7] iommu: add new iommu_ops callback for adding an OF device
On Mon, Sep 15, 2014 at 12:57:38PM +0100, Marek Szyprowski wrote: Hello, Hi Marek, Thanks for looking again at this -- I'll take at look at your exynos series when I'm back in the UK next week. On 2014-09-12 18:34, Will Deacon wrote: This patch adds a new function to the iommu_ops structure to allow an OF device to be added to a specific IOMMU instance using the recently merged generic devicetree binding for IOMMUs. The callback (of_xlate) takes a struct device representing the master and an of_phandle_args representing the IOMMU and the correspondong IDs for the new master. Signed-off-by: Will Deacon will.dea...@arm.com --- include/linux/iommu.h | 5 + 1 file changed, 5 insertions(+) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 4256f3ce1673..821eb0bd9f6c 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -21,6 +21,7 @@ #include linux/errno.h #include linux/err.h +#include linux/of.h #include linux/types.h #include trace/events/iommu.h @@ -140,6 +141,10 @@ struct iommu_ops { /* Get the numer of window per domain */ u32 (*domain_get_windows)(struct iommu_domain *domain); +#ifdef CONFIG_OF_IOMMU + int (*of_xlate)(struct device *dev, struct of_phandle_args *args); +#endif If I understand correctly, this callback is intended to do per-master initialization of the iommu structures required by the given iommu driver (I stored them in dev-archdata.iommu). However I really don't get what is the meaning of the return value. Is it a boolean value? It is used only by of_iommu_configure to check if the parse loop should be terminated... It should probably return 0 on success, 0 otherwise. I'll fix of_iommu_configure to check for 0 and only exit the loop then. The idea is that we don't swizzle the DMA ops for a device to IOMMU ops if of_xlate failed for any of its IDs. Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu