[PATCH v2 3/5] dma-direct: Turn zone_dma_bits default value into a define

2020-10-10 Thread Nicolas Saenz Julienne
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

2020-10-10 Thread Nicolas Saenz Julienne
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()

2020-10-10 Thread Nicolas Saenz Julienne
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()

2020-10-10 Thread Nicolas Saenz Julienne
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

2020-10-10 Thread Nicolas Saenz Julienne
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

2020-10-10 Thread Nicolas Saenz Julienne
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

2020-10-10 Thread Catalin Marinas
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

2020-10-10 Thread Nicolas Saenz Julienne
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

2020-10-10 Thread Ard Biesheuvel
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

2020-10-10 Thread FelixCuioc
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

2020-10-10 Thread FelixCuioc
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

2020-10-10 Thread FelixCuioc
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

2020-10-10 Thread Yong Wu
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:
> >   -