[PATCH v2 3/5] dma-direct: Turn zone_dma_bits default value into a define
So as for architecture code to set their own default values when relevant. Signed-off-by: Nicolas Saenz Julienne --- Note: This is not really needed, but I think it nicer having architectures use this than setting zone_dma_bits in a random place in arch code. That said, I'll hapily edit it out if you don't agree. include/linux/dma-direct.h | 3 +++ kernel/dma/direct.c| 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h index 18aade195884..e433d90cbacf 100644 --- a/include/linux/dma-direct.h +++ b/include/linux/dma-direct.h @@ -12,6 +12,9 @@ #include #include +#ifndef ZONE_DMA_BITS_DEFAULT +#define ZONE_DMA_BITS_DEFAULT 24 +#endif extern unsigned int zone_dma_bits; /* diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c index 06c111544f61..c0d97f536e93 100644 --- a/kernel/dma/direct.c +++ b/kernel/dma/direct.c @@ -20,7 +20,7 @@ * it for entirely different regions. In that case the arch code needs to * override the variable below for dma-direct to work properly. */ -unsigned int zone_dma_bits __ro_after_init = 24; +unsigned int zone_dma_bits __ro_after_init = ZONE_DMA_BITS_DEFAULT; static inline dma_addr_t phys_to_dma_direct(struct device *dev, phys_addr_t phys) -- 2.28.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 4/5] arm64: mm: Dynamically resize zone_dma_bits based on system's constraints
With the help of of_dma_safe_phys_limit() we can get the topmost physical address accessible for DMA to the whole system and use that information to properly setup zone_dma_bits. Signed-off-by: Nicolas Saenz Julienne --- arch/arm64/include/asm/processor.h | 1 + arch/arm64/mm/init.c | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index fce8cbecd6bc..c09d3f1a9a6b 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -97,6 +97,7 @@ extern phys_addr_t arm64_dma_phys_limit; #define ARCH_LOW_ADDRESS_LIMIT (arm64_dma_phys_limit - 1) +#define ZONE_DMA_BITS_DEFAULT 32 struct debug_info { #ifdef CONFIG_HAVE_HW_BREAKPOINT diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 0eca5865dcb1..5934df93bf4d 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -42,8 +42,6 @@ #include #include -#define ARM64_ZONE_DMA_BITS30 - /* * We need to be able to catch inadvertent references to memstart_addr * that occur (potentially in generic code) before arm64_memblock_init() @@ -196,7 +194,8 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) unsigned long max_zone_pfns[MAX_NR_ZONES] = {0}; #ifdef CONFIG_ZONE_DMA - zone_dma_bits = ARM64_ZONE_DMA_BITS; + zone_dma_bits = min(zone_dma_bits, + (unsigned int)ilog2(of_dma_safe_phys_limit())); if (IS_ENABLED(CONFIG_ACPI)) { extern unsigned int acpi_iort_get_zone_dma_size(void); -- 2.28.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 1/5] arm64: mm: Move zone_dma_bits initialization into zone_sizes_init()
There no use for initializing it earlier in arm64_memblock_init(). Signed-off-by: Nicolas Saenz Julienne --- arch/arm64/mm/init.c | 9 +++-- 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index f6902a2b4ea6..0eca5865dcb1 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -196,14 +196,16 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) unsigned long max_zone_pfns[MAX_NR_ZONES] = {0}; #ifdef CONFIG_ZONE_DMA + zone_dma_bits = ARM64_ZONE_DMA_BITS; + if (IS_ENABLED(CONFIG_ACPI)) { extern unsigned int acpi_iort_get_zone_dma_size(void); zone_dma_bits = min(zone_dma_bits, acpi_iort_get_zone_dma_size()); - arm64_dma_phys_limit = max_zone_phys(zone_dma_bits); } + arm64_dma_phys_limit = max_zone_phys(zone_dma_bits); max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit); #endif #ifdef CONFIG_ZONE_DMA32 @@ -394,11 +396,6 @@ void __init arm64_memblock_init(void) early_init_fdt_scan_reserved_mem(); - if (IS_ENABLED(CONFIG_ZONE_DMA)) { - zone_dma_bits = ARM64_ZONE_DMA_BITS; - arm64_dma_phys_limit = max_zone_phys(ARM64_ZONE_DMA_BITS); - } - if (IS_ENABLED(CONFIG_ZONE_DMA32)) arm64_dma32_phys_limit = max_zone_phys(32); else -- 2.28.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 2/5] of/address: Introduce of_dma_lower_bus_limit()
The function provides the CPU physical address addressable by the most constrained bus in the system. It might be useful in order to dynamically set up memory zones during boot. Signed-off-by: Nicolas Saenz Julienne --- drivers/of/address.c | 34 ++ include/linux/of.h | 7 +++ 2 files changed, 41 insertions(+) diff --git a/drivers/of/address.c b/drivers/of/address.c index eb9ab4f1e80b..755e97b65096 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -1024,6 +1024,40 @@ int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map) } #endif /* CONFIG_HAS_DMA */ +/** + * of_dma_safe_phys_limit - Get system wide DMA safe address space + * + * Gets the CPU physical address limit for safe DMA addressing system wide by + * searching for the most constraining dma-range. Otherwise it returns ~0ULL. + */ +u64 __init of_dma_safe_phys_limit(void) +{ + struct device_node *np = NULL; + struct of_range_parser parser; + const __be32 *ranges = NULL; + u64 phys_dma_limit = ~0ULL; + struct of_range range; + int len; + + for_each_of_allnodes(np) { + dma_addr_t cpu_end = 0; + + ranges = of_get_property(np, "dma-ranges", ); + if (!ranges || !len) + continue; + + of_dma_range_parser_init(, np); + for_each_of_range(, ) + if (range.cpu_addr + range.size > cpu_end) + cpu_end = range.cpu_addr + range.size; + + if (phys_dma_limit > cpu_end) + phys_dma_limit = cpu_end; + } + + return phys_dma_limit; +} + /** * of_dma_is_coherent - Check if device is coherent * @np:device node diff --git a/include/linux/of.h b/include/linux/of.h index 481ec0467285..958c64cffa92 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -558,6 +558,8 @@ int of_map_id(struct device_node *np, u32 id, const char *map_name, const char *map_mask_name, struct device_node **target, u32 *id_out); +u64 of_dma_safe_phys_limit(void); + #else /* CONFIG_OF */ static inline void of_core_init(void) @@ -995,6 +997,11 @@ static inline int of_map_id(struct device_node *np, u32 id, return -EINVAL; } +static inline u64 of_dma_safe_phys_limit(void) +{ + return ~0ULL; +} + #define of_match_ptr(_ptr) NULL #define of_match_node(_matches, _node) NULL #endif /* CONFIG_OF */ -- 2.28.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 0/5] arm64: Default to 32-bit wide ZONE_DMA
I realized this morning after reading Ard's patch fixing the same issue in ACPI that we can move the zone_dma_bits initialization later in the init process. This permits the use of OF to parse dma-ranges in the system. Something we though we couldn't do on previous iterations of this. The series sits on top of Ard's patch "arm64: mm: set ZONE_DMA size based on early IORT scan." --- Original cover letter Using two distinct DMA zones turned out to be problematic. Here's an attempt go back to a saner default. I tested this on both a RPi4 and QEMU. --- Changes since v1: - Parse dma-ranges instead of using machine compatible string Nicolas Saenz Julienne (5): arm64: mm: Move zone_dma_bits initialization into zone_sizes_init() of/address: Introduce of_dma_lower_bus_limit() dma-direct: Turn zone_dma_bits default value into a define arm64: mm: Dynamically resize zone_dma_bits based on system's constraints mm: Update DMA zones description arch/arm64/include/asm/processor.h | 1 + arch/arm64/mm/init.c | 12 --- drivers/of/address.c | 34 ++ include/linux/dma-direct.h | 3 +++ include/linux/mmzone.h | 5 +++-- include/linux/of.h | 7 ++ kernel/dma/direct.c| 2 +- 7 files changed, 53 insertions(+), 11 deletions(-) -- 2.28.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 5/5] mm: Update DMA zones description
The default behavior for arm64 changed, so reflect that. Signed-off-by: Nicolas Saenz Julienne Acked-by: Catalin Marinas --- include/linux/mmzone.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index fb3bf696c05e..4ee2306351b9 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -363,8 +363,9 @@ enum zone_type { * - arm only uses ZONE_DMA, the size, up to 4G, may vary depending on *the specific device. * -* - arm64 has a fixed 1G ZONE_DMA and ZONE_DMA32 for the rest of the -*lower 4G. +* - arm64 uses a single 4GB ZONE_DMA, except on the Raspberry Pi 4, +*in which ZONE_DMA covers the first GB and ZONE_DMA32 the rest of +*the lower 4GB. * * - powerpc only uses ZONE_DMA, the size, up to 2G, may vary *depending on the specific device. -- 2.28.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/4] of/fdt: Update zone_dma_bits when running in bcm2711
On Sat, Oct 10, 2020 at 12:53:19PM +0200, Nicolas Saenz Julienne wrote: > On Sat, 2020-10-10 at 12:36 +0200, Ard Biesheuvel wrote: > > On Fri, 9 Oct 2020 at 19:10, Catalin Marinas > > wrote: > > > On Fri, Oct 09, 2020 at 06:23:06PM +0200, Ard Biesheuvel wrote: > > > > On Fri, 9 Oct 2020 at 17:24, Lorenzo Pieralisi > > > > wrote: > > > > > We can move this check to IORT code and call it from arm64 if it > > > > > can be made to work. > > > > > > > > Finding the smallest value in the IORT, and assigning it to > > > > zone_dma_bits if it is < 32 should be easy. But as I understand it, > > > > having these separate DMA and DMA32 zones is what breaks kdump, no? So > > > > how is this going to fix the underlying issue? > > > > > > If zone_dma_bits is 32, ZONE_DMA32 disappears into ZONE_DMA (GFP_DMA32 > > > allocations fall back to ZONE_DMA). > > > > > > kdump wants DMA-able memory and, without a 30-bit ZONE_DMA, that would > > > be the bottom 32-bit. With the introduction of ZONE_DMA, this suddenly > > > became 1GB. We could change kdump to allocate ZONE_DMA32 but this one > > > may also be small as it lost 1GB to ZONE_DMA. However, the kdump kernel > > > would need to be rebuilt without ZONE_DMA since it won't have any. IIRC > > > (it's been a while since I looked), the kdump allocation couldn't span > > > multiple zones. > > > > > > In a separate thread, we try to fix kdump to use allocations above 4G as > > > a fallback but this only fixes platforms with enough RAM (and maybe it's > > > only those platforms that care about kdump). > > > > > > > One thing that strikes me as odd is that we are applying the same > > shifting logic to ZONE_DMA as we are applying to ZONE_DMA32, i.e., if > > DRAM starts outside of the zone, it is shifted upwards. > > > > On a typical ARM box, this gives me > > > > [0.00] Zone ranges: > > [0.00] DMA [mem 0x8000-0xbfff] > > [0.00] DMA32[mem 0xc000-0x] > > [0.00] Normal [mem 0x0001-0x000f] > > > > i.e., the 30-bit addressable range has bit 31 set, which is weird. > > Yes I agree it's weird, and IMO plain useless. I sent a series this summer to > address this[1], which ultimately triggered the discussion we're having right > now. I don't mind assuming that ZONE_DMA is always from pfn 0 (i.e. no dma_offset for such constrained devices). But if ZONE_DMA32 is squeezed out with ZONE_DMA extended to 4GB, it should allow non-zero upper 32 bits. IIRC we do have SoCs with RAM starting above 4GB. However, your patch didn't completely solve the problem for non-RPi4 platforms as there's hardware with RAM starting at 0 that doesn't need the 1GB ZONE_DMA. We may end up with a combination of the two approaches. > Although with with your latest patch and the DT counterpart, we should be OK. > It would be weird for a HW description to define DMA constraints that are > impossible to reach on that system. I don't remember the difficulties with parsing a DT early for inferring the ZONE_DMA requirements. Could we not check the dma-ranges property in the soc node? I can see bcm2711.dtsi defines a 30-bit address range. We are not interested in the absolute physical/bus addresses, just the size to check whether it's smaller than 32-bit. > > I wonder if it wouldn't be better (and less problematic in the general > > case) to drop this logic for ZONE_DMA, and simply let it remain empty > > unless there is really some memory there. > > From my experience, you can't have empty ZONE_DMA when enabled. Empty > ZONE_DMA32 is OK though. Although I'm sure it's something that can be changed. Indeed, because we still have GFP_DMA around which can't fall back to ZONE_DMA32 (well, unless CONFIG_ZONE_DMA is disabled). -- Catalin ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/4] of/fdt: Update zone_dma_bits when running in bcm2711
On Sat, 2020-10-10 at 12:36 +0200, Ard Biesheuvel wrote: > On Fri, 9 Oct 2020 at 19:10, Catalin Marinas wrote: > > On Fri, Oct 09, 2020 at 06:23:06PM +0200, Ard Biesheuvel wrote: > > > On Fri, 9 Oct 2020 at 17:24, Lorenzo Pieralisi > > > wrote: > > > > We can move this check to IORT code and call it from arm64 if it > > > > can be made to work. > > > > > > Finding the smallest value in the IORT, and assigning it to > > > zone_dma_bits if it is < 32 should be easy. But as I understand it, > > > having these separate DMA and DMA32 zones is what breaks kdump, no? So > > > how is this going to fix the underlying issue? > > > > If zone_dma_bits is 32, ZONE_DMA32 disappears into ZONE_DMA (GFP_DMA32 > > allocations fall back to ZONE_DMA). > > > > kdump wants DMA-able memory and, without a 30-bit ZONE_DMA, that would > > be the bottom 32-bit. With the introduction of ZONE_DMA, this suddenly > > became 1GB. We could change kdump to allocate ZONE_DMA32 but this one > > may also be small as it lost 1GB to ZONE_DMA. However, the kdump kernel > > would need to be rebuilt without ZONE_DMA since it won't have any. IIRC > > (it's been a while since I looked), the kdump allocation couldn't span > > multiple zones. > > > > In a separate thread, we try to fix kdump to use allocations above 4G as > > a fallback but this only fixes platforms with enough RAM (and maybe it's > > only those platforms that care about kdump). > > > > One thing that strikes me as odd is that we are applying the same > shifting logic to ZONE_DMA as we are applying to ZONE_DMA32, i.e., if > DRAM starts outside of the zone, it is shifted upwards. > > On a typical ARM box, this gives me > > [0.00] Zone ranges: > [0.00] DMA [mem 0x8000-0xbfff] > [0.00] DMA32[mem 0xc000-0x] > [0.00] Normal [mem 0x0001-0x000f] > > i.e., the 30-bit addressable range has bit 31 set, which is weird. Yes I agree it's weird, and IMO plain useless. I sent a series this summer to address this[1], which ultimately triggered the discussion we're having right now. Although with with your latest patch and the DT counterpart, we should be OK. It would be weird for a HW description to define DMA constraints that are impossible to reach on that system. > I wonder if it wouldn't be better (and less problematic in the general > case) to drop this logic for ZONE_DMA, and simply let it remain empty > unless there is really some memory there. From my experience, you can't have empty ZONE_DMA when enabled. Empty ZONE_DMA32 is OK though. Although I'm sure it's something that can be changed. Regards, Nicolas [1] https://lkml.org/lkml/2020/8/19/1022 signature.asc Description: This is a digitally signed message part ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/4] of/fdt: Update zone_dma_bits when running in bcm2711
On Fri, 9 Oct 2020 at 19:10, Catalin Marinas wrote: > > On Fri, Oct 09, 2020 at 06:23:06PM +0200, Ard Biesheuvel wrote: > > On Fri, 9 Oct 2020 at 17:24, Lorenzo Pieralisi > > wrote: > > > We can move this check to IORT code and call it from arm64 if it > > > can be made to work. > > > > Finding the smallest value in the IORT, and assigning it to > > zone_dma_bits if it is < 32 should be easy. But as I understand it, > > having these separate DMA and DMA32 zones is what breaks kdump, no? So > > how is this going to fix the underlying issue? > > If zone_dma_bits is 32, ZONE_DMA32 disappears into ZONE_DMA (GFP_DMA32 > allocations fall back to ZONE_DMA). > > kdump wants DMA-able memory and, without a 30-bit ZONE_DMA, that would > be the bottom 32-bit. With the introduction of ZONE_DMA, this suddenly > became 1GB. We could change kdump to allocate ZONE_DMA32 but this one > may also be small as it lost 1GB to ZONE_DMA. However, the kdump kernel > would need to be rebuilt without ZONE_DMA since it won't have any. IIRC > (it's been a while since I looked), the kdump allocation couldn't span > multiple zones. > > In a separate thread, we try to fix kdump to use allocations above 4G as > a fallback but this only fixes platforms with enough RAM (and maybe it's > only those platforms that care about kdump). > One thing that strikes me as odd is that we are applying the same shifting logic to ZONE_DMA as we are applying to ZONE_DMA32, i.e., if DRAM starts outside of the zone, it is shifted upwards. On a typical ARM box, this gives me [0.00] Zone ranges: [0.00] DMA [mem 0x8000-0xbfff] [0.00] DMA32[mem 0xc000-0x] [0.00] Normal [mem 0x0001-0x000f] i.e., the 30-bit addressable range has bit 31 set, which is weird. I wonder if it wouldn't be better (and less problematic in the general case) to drop this logic for ZONE_DMA, and simply let it remain empty unless there is really some memory there. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 0/2] Add support for ACPI device in RMRR
BIOS allocate reserved memory ranges that may be DMA targets. BIOS may report each such reserved memory region through the RMRR structures,along with the devices that requires access to the specified reserved memory region. The purpose of this series is to achieve ACPI device in RMRR access reserved memory.Therefore,it is necessary to increase the analysis of acpi device in RMRR and establish a mapping for this device. The first patch adds interfaces for detecting ACPI device in RMRR and in order to distinguish it from pci device, some interface functions are modified. The second patch adds support for probing ACPI device in RMRR. In probe_acpi_namespace_devices(),add support for direct mapping of ACPI device and add support for physical node of acpi device to be NULL. v2->v3: - Add the blank line between functions. - Make dmar_acpi_insert_dev_scope() bool,change the 1/0 to true/false and add a comment explaining. - Delete unused initialization. - if dmar_acpi_insert_dev_scope() always returns zero,will not call dmar_rmrr_add_acpi_dev(). - Use a proper error code. - Use if(!pdev). - Use goto unlock instead of mutex_unlock(). FelixCuioc (2): iommu/vt-d:Add support for detecting ACPI device in RMRR iommu/vt-d:Add support for probing ACPI device in RMRR drivers/iommu/intel/dmar.c | 76 + drivers/iommu/intel/iommu.c | 52 - drivers/iommu/iommu.c | 6 +++ include/linux/dmar.h| 12 +- include/linux/iommu.h | 2 + 5 files changed, 113 insertions(+), 35 deletions(-) -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 2/2] iommu/vt-d:Add support for probing ACPI device in RMRR
After acpi device in RMRR is detected,it is necessary to establish a mapping for these devices. In acpi_device_create_direct_mappings(),create a mapping for the acpi device in RMRR. Add a helper to achieve the acpi namespace device can access the RMRR region. Signed-off-by: FelixCuioc --- drivers/iommu/intel/iommu.c | 29 + drivers/iommu/iommu.c | 6 ++ include/linux/iommu.h | 2 ++ 3 files changed, 37 insertions(+) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 594b2f29c043..a0fe867aa1f5 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -4844,6 +4844,21 @@ static int __init platform_optin_force_iommu(void) return 1; } +static int acpi_device_create_direct_mappings(struct device *pn_dev, struct device *acpi_device) +{ + struct iommu_group *group; + + acpi_device->bus->iommu_ops = _iommu_ops; + group = iommu_group_get(pn_dev); + if (!group) { + pr_warn("ACPI name space devices create direct mappings wrong!\n"); + return -EINVAL; + } + __acpi_device_create_direct_mappings(group, acpi_device); + + return 0; +} + static int __init probe_acpi_namespace_devices(void) { struct dmar_drhd_unit *drhd; @@ -4858,6 +4873,7 @@ static int __init probe_acpi_namespace_devices(void) struct acpi_device_physical_node *pn; struct iommu_group *group; struct acpi_device *adev; + struct device *pn_dev = NULL; if (dev->bus != _bus_type) continue; @@ -4868,6 +4884,7 @@ static int __init probe_acpi_namespace_devices(void) >physical_node_list, node) { group = iommu_group_get(pn->dev); if (group) { + pn_dev = pn->dev; iommu_group_put(group); continue; } @@ -4876,7 +4893,19 @@ static int __init probe_acpi_namespace_devices(void) ret = iommu_probe_device(pn->dev); if (ret) break; + pn_dev = pn->dev; + } + if (!pn_dev) { + dev->bus->iommu_ops = _iommu_ops; + ret = iommu_probe_device(dev); + if (ret) { + pr_err("acpi_device probe fail! ret:%d\n", ret); + goto unlock; + } + goto unlock; } + ret = acpi_device_create_direct_mappings(pn_dev, dev); +unlock: mutex_unlock(>physical_node_lock); if (ret) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 6d847027d35e..ffd470297ea6 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain, return false; } +void __acpi_device_create_direct_mappings(struct iommu_group *group, struct device *acpi_device) +{ + iommu_create_device_direct_mappings(group, acpi_device); +} +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings); + /** * iommu_group_add_device - add a device to an iommu group * @group: the group into which to add the device (reference should be held) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 82876f682367..bfc46e538c29 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -516,6 +516,8 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr) extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags); +extern void __acpi_device_create_direct_mappings(struct iommu_group *group, +struct device *acpi_device); static inline void iommu_flush_iotlb_all(struct iommu_domain *domain) { -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 1/2] iommu/vt-d:Add support for detecting ACPI device in RMRR
Some ACPI devices need to issue dma requests to access the reserved memory area.BIOS uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices. This patch add support for detecting ACPI devices in RMRR. Signed-off-by: FelixCuioc --- drivers/iommu/intel/dmar.c | 76 + drivers/iommu/intel/iommu.c | 23 ++- include/linux/dmar.h| 12 +- 3 files changed, 76 insertions(+), 35 deletions(-) diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c index 54d790f75824..5ebe317280a6 100644 --- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus, } /* Return: > 0 if match found, 0 if no match found, < 0 if error happens */ -int dmar_insert_dev_scope(struct dmar_pci_notify_info *info, +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info, void *start, void*end, u16 segment, struct dmar_dev_scope *devices, int devices_cnt) @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct dmar_pci_notify_info *info) drhd = container_of(dmaru->hdr, struct acpi_dmar_hardware_unit, header); - ret = dmar_insert_dev_scope(info, (void *)(drhd + 1), + ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1), ((void *)drhd) + drhd->header.length, dmaru->segment, dmaru->devices, dmaru->devices_cnt); @@ -697,47 +697,59 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev) return dmaru; } -static void __init dmar_acpi_insert_dev_scope(u8 device_number, - struct acpi_device *adev) +/* Return: > 0 if match found, 0 if no match found */ +bool dmar_acpi_insert_dev_scope(u8 device_number, + struct acpi_device *adev, + void *start, void *end, + struct dmar_dev_scope *devices, + int devices_cnt) { - struct dmar_drhd_unit *dmaru; - struct acpi_dmar_hardware_unit *drhd; struct acpi_dmar_device_scope *scope; struct device *tmp; int i; struct acpi_dmar_pci_path *path; + for (; start < end; start += scope->length) { + scope = start; + if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE) + continue; + if (scope->enumeration_id != device_number) + continue; + path = (void *)(scope + 1); + for_each_dev_scope(devices, devices_cnt, i, tmp) + if (tmp == NULL) { + devices[i].bus = scope->bus; + devices[i].devfn = PCI_DEVFN(path->device, path->function); + rcu_assign_pointer(devices[i].dev, + get_device(>dev)); + return true; + } + WARN_ON(i >= devices_cnt); + } + return false; +} + +static int dmar_acpi_bus_add_dev(u8 device_number, struct acpi_device *adev) +{ + struct dmar_drhd_unit *dmaru; + struct acpi_dmar_hardware_unit *drhd; + int ret; + for_each_drhd_unit(dmaru) { drhd = container_of(dmaru->hdr, struct acpi_dmar_hardware_unit, header); + ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1), + ((void *)drhd)+drhd->header.length, + dmaru->devices, dmaru->devices_cnt); + if (ret) + break; + } + if (ret > 0) + ret = dmar_rmrr_add_acpi_dev(device_number, adev); - for (scope = (void *)(drhd + 1); -(unsigned long)scope < ((unsigned long)drhd) + drhd->header.length; -scope = ((void *)scope) + scope->length) { - if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE) - continue; - if (scope->enumeration_id != device_number) - continue; + return ret; - path = (void *)(scope + 1); - pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n", - dev_name(>dev), dmaru->reg_base_addr, - scope->bus, path->device, path->function); - for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp) -
Re: [PATCH v3 02/24] dt-bindings: memory: mediatek: Convert SMI to DT schema
On Tue, 2020-10-06 at 09:15 +0200, Krzysztof Kozlowski wrote: > On Tue, 6 Oct 2020 at 06:27, Yong Wu wrote: > > > > On Fri, 2020-10-02 at 13:08 +0200, Krzysztof Kozlowski wrote: > > > On Wed, Sep 30, 2020 at 03:06:25PM +0800, Yong Wu wrote: > > > > Convert MediaTek SMI to DT schema. > > > > > > > > Signed-off-by: Yong Wu > > > > --- > > > > .../mediatek,smi-common.txt | 49 - > > > > .../mediatek,smi-common.yaml | 100 ++ > > > > .../memory-controllers/mediatek,smi-larb.txt | 49 - > > > > .../memory-controllers/mediatek,smi-larb.yaml | 91 > > > > 4 files changed, 191 insertions(+), 98 deletions(-) > > > > delete mode 100644 > > > > Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt > > > > create mode 100644 > > > > Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml > > > > delete mode 100644 > > > > Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt > > > > create mode 100644 > > > > Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml > > ... > > > > +properties: > > > > + compatible: > > > > +oneOf: > > > > + - enum: > > > > + - mediatek,mt2701-smi-common > > > > + - mediatek,mt2712-smi-common > > > > + - mediatek,mt6779-smi-common > > > > + - mediatek,mt8173-smi-common > > > > + - mediatek,mt8183-smi-common > > > > + > > > > + - description: for mt7623 > > > > +items: > > > > + - const: mediatek,mt7623-smi-common > > > > + - const: mediatek,mt2701-smi-common > > > > + > > > > + reg: > > > > +maxItems: 1 > > > > + > > > > + clocks: > > > > +description: | > > > > + apb and smi are mandatory. the async is only for generation 1 > > > > smi HW. > > > > + gals(global async local sync) also is optional, here is the list > > > > which > > > > + require gals: mt6779 and mt8183. > > > > +minItems: 2 > > > > +maxItems: 4 > > > > +items: > > > > + - description: apb is Advanced Peripheral Bus clock, It's the > > > > clock for > > > > + setting the register. > > > > + - description: smi is the clock for transfer data and command. > > > > + - description: async is asynchronous clock, it help transform > > > > the smi clock > > > > + into the emi clock domain. > > > > + - description: gals0 is the path0 clock of gals. > > > > + - description: gals1 is the path1 clock of gals. > > > > + > > > > + clock-names: > > > > +oneOf: > > > > + - items: > > > > + - const: apb > > > > + - const: smi > > > > + - items: > > > > + - const: apb > > > > + - const: smi > > > > + - const: async > > > > + - items: > > > > + - const: apb > > > > + - const: smi > > > > + - const: gals0 > > > > + - const: gals1 > > > > > > Similarly to my comment to other properties, this requirement per > > > compatible should be part of the schema within 'if-then'. > > > > I'm not so familiar with this format. Do this has "if-then-'else > > if'-then-else"? > > These are mutually exclusive conditions, so you can skip else: > - if-then > - if-then > - if-then > It will be more readable then stacking 'if' under 'else' Thanks. I will use something like this: anyOf: - if: #gen1 hw then: use apb/smi/async clocks - if: #gen2 hw that has gals. then: use apb/smi/gals0/gals1 clocks else: # gen2 hw that doesn't have gals. use apb/smi clocks. > > > > > I tried below instead of the clocks segment above: > > > > === > > if: > > properties: > > compatible: > > Missing contains. Just take an example from some existing schema. Like the example you gave below (Documentation/devicetree/bindings/clock/idt,versaclock5.yaml), It also doesn't have "contains" in "if". I guess it is unnecessary if there is only one compatible string. it may be necessary when it has backward compatible string. > > > enum: > > - mediatek,mt6779-smi-common > > - mediatek,mt8183-smi-common > > > > then: > > properties: > > clock: > > items: > > - description: apb is the clock for setting the register.. > > - description: smi is the clock for transfer data and command. > > - description: gals0 is the path0 clock of gals(global async > > local sync). > > - description: gals1 is the path1 clock of gals. > > clock-names: > > items: > > - const: apb > > - const: smi > > - const: gals0 > > - const: gals1 > > else: > > if: > > properties: > > compatible: > > contains: > > enum: > > - mediatek,mt2701-smi-common > > > > then: > > properties: > > clocks: > > items: > > -