[PATCH 4.5/20] Docs: dt: document ARM SMMUv3 generic binding usage

2016-09-09 Thread Robin Murphy
Now that we've ratified SMMUv3's use of the generic binding, document it.

CC: Rob Herring 
CC: Mark Rutland 
Signed-off-by: Robin Murphy 
---
 Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt 
b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
index 7b94c88cf2ee..69a694f70bea 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
@@ -27,6 +27,12 @@ the PCIe specification.
   * "cmdq-sync" - CMD_SYNC complete
   * "gerror"- Global Error activated
 
+- #iommu-cells  : See the generic IOMMU binding described in
+devicetree/bindings/iommu/iommu.txt
+  for details. For SMMUv3, must be 1, with each cell
+  describing a single stream ID. All possible stream
+  ID which a device may emit must be described.
+
 ** SMMUv3 optional properties:
 
 - dma-coherent  : Present if DMA operations made by the SMMU (page
@@ -54,6 +60,6 @@ the PCIe specification.
  ;
 interrupt-names = "eventq", "priq", "cmdq-sync", "gerror";
 dma-coherent;
-#iommu-cells = <0>;
+#iommu-cells = <1>;
 msi-parent = <&its 0xff>;
 };
-- 
2.8.1.dirty

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 22/20] iommu/arm-smmu: Fall back to global bypass

2016-09-09 Thread Robin Murphy
Unlike SMMUv2, SMMUv3 has no easy way to bypass unknown stream IDs,
other than allocating and filling in the entire stream table with bypass
entries, which for some configurations would waste *gigabytes* of RAM.
Otherwise, all transactions on unknown stream IDs will simply be aborted
with a C_BAD_STREAMID event.

Rather than render the system unusable in the case of an invalid DT,
avoid enabling the SMMU altogether such that everything bypasses
(though letting the explicit disable_bypass option take precedence).

Signed-off-by: Robin Murphy 
---
 drivers/iommu/arm-smmu-v3.c | 28 +++-
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index be293b5aa896..859b80c83946 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -126,6 +126,9 @@
 #define CR2_RECINVSID  (1 << 1)
 #define CR2_E2H(1 << 0)
 
+#define ARM_SMMU_GBPA  0x44
+#define GBPA_ABORT (1 << 20)
+
 #define ARM_SMMU_IRQ_CTRL  0x50
 #define IRQ_CTRL_EVTQ_IRQEN(1 << 2)
 #define IRQ_CTRL_PRIQ_IRQEN(1 << 1)
@@ -2242,7 +2245,7 @@ static int arm_smmu_device_disable(struct arm_smmu_device 
*smmu)
return ret;
 }
 
-static int arm_smmu_device_reset(struct arm_smmu_device *smmu)
+static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
 {
int ret;
u32 reg, enables;
@@ -2343,8 +2346,14 @@ static int arm_smmu_device_reset(struct arm_smmu_device 
*smmu)
return ret;
}
 
-   /* Enable the SMMU interface */
-   enables |= CR0_SMMUEN;
+
+   /* Enable the SMMU interface, or ensure bypass */
+   if (!bypass || disable_bypass) {
+   enables |= CR0_SMMUEN;
+   } else {
+   reg = readl_relaxed(smmu->base + ARM_SMMU_GBPA);
+   writel_relaxed(reg & ~GBPA_ABORT, smmu->base + ARM_SMMU_GBPA);
+   }
ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
  ARM_SMMU_CR0ACK);
if (ret) {
@@ -2543,6 +2552,15 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev)
struct resource *res;
struct arm_smmu_device *smmu;
struct device *dev = &pdev->dev;
+   bool bypass = true;
+   u32 cells;
+
+   if (of_property_read_u32(dev->of_node, "#iommu-cells", &cells))
+   dev_err(dev, "missing #iommu-cells property\n");
+   else if (cells != 1)
+   dev_err(dev, "invalid #iommu-cells value (%d)\n", cells);
+   else
+   bypass = false;
 
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
if (!smmu) {
@@ -2595,8 +2613,8 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev)
platform_set_drvdata(pdev, smmu);
 
/* Reset the device */
-   ret = arm_smmu_device_reset(smmu);
-   if (ret)
+   ret = arm_smmu_device_reset(smmu, bypass);
+   if (ret || bypass)
return ret;
 
/* And we're up. Go go go! */
-- 
2.8.1.dirty

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 21/20] drm/exynos: Fix iommu_dma_init_domain prototype change

2016-09-09 Thread Robin Murphy
When adding an extra argument to a function, one really should try a bit
harder to catch *all* the callers...

CC: Marek Szyprowski 
CC: Inki Dae 
CC: David Airlie 
CC: dri-de...@lists.freedesktop.org
Signed-off-by: Robin Murphy 

---

Ideally, this should be squashed into "iommu/dma: Avoid PCI host bridge
windows" to avoid potential bisection breakage. Sorry!

 drivers/gpu/drm/exynos/exynos_drm_iommu.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h 
b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
index c8de4913fdbe..87f6b5672e11 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
@@ -66,7 +66,7 @@ static inline int __exynos_iommu_create_mapping(struct 
exynos_drm_private *priv,
if (ret)
goto free_domain;
 
-   ret = iommu_dma_init_domain(domain, start, size);
+   ret = iommu_dma_init_domain(domain, start, size, NULL);
if (ret)
goto put_cookie;
 
-- 
2.8.1.dirty

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v6 00/20] Generic DT bindings for PCI IOMMUs and ARM SMMU

2016-09-09 Thread Will Deacon
Hi Robin,

On Tue, Sep 06, 2016 at 04:33:33PM +0100, Robin Murphy wrote:
> Here's v6 to address last week's comments. For the sake of honesty I've
> left Lorenzo's tested-by off everything I've changed since, and Eric's
> reviewed-by off patch 19 having non-trivially reworked the guts of it.
> 
> Patch 20 is new, but as it's currently a solution waiting for a problem
> as far as we're aware, oughtn't to get in the way; hopefully the rest is
> in good shape for 4.9 now.
> 
> Branch here, based on Will's iommu/devel queue:
> 
> git://linux-arm.org/linux-rm iommu/generic-v6

I'm pretty happy with this (modulo the binding docs update etc we
discussed off list), however I'm seeing an allmodconfig build failure
with this applied. Error below.

Please can you take a look and send a fixup patch?

Cheers,

Will

--->8

In file included from drivers/gpu/drm/exynos/exynos_drm_drv.c:33:0:
drivers/gpu/drm/exynos/exynos_drm_iommu.h: In function 
‘__exynos_iommu_create_mapping’:
drivers/gpu/drm/exynos/exynos_drm_iommu.h:69:8: error: too few arguments to 
function ‘iommu_dma_init_domain’
  ret = iommu_dma_init_domain(domain, start, size);
^
In file included from drivers/gpu/drm/exynos/exynos_drm_iommu.h:53:0,
 from drivers/gpu/drm/exynos/exynos_drm_drv.c:33:
./include/linux/dma-iommu.h:33:5: note: declared here
 int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
 ^
make[4]: *** [drivers/gpu/drm/exynos/exynos_drm_drv.o] Error 1
make[3]: *** [drivers/gpu/drm/exynos] Error 2
make[3]: *** Waiting for unfinished jobs
make[2]: *** [drivers/gpu/drm] Error 2
make[1]: *** [drivers/gpu] Error 2
make[1]: *** Waiting for unfinished jobs
make: *** [drivers] Error 2
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [RFC PATCH v2 13/20] x86: Decrypt trampoline area if memory encryption is active

2016-09-09 Thread Borislav Petkov
On Mon, Aug 22, 2016 at 05:37:57PM -0500, Tom Lendacky wrote:
> When Secure Memory Encryption is enabled, the trampoline area must not
> be encrypted. A cpu running in real mode will not be able to decrypt

s/cpu/CPU/... always :-)

> memory that has been encrypted because it will not be able to use addresses
> with the memory encryption mask.
> 
> Signed-off-by: Tom Lendacky 
> ---
>  arch/x86/realmode/init.c |9 +
>  1 file changed, 9 insertions(+)
> 
> diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
> index 5db706f1..f74925f 100644
> --- a/arch/x86/realmode/init.c
> +++ b/arch/x86/realmode/init.c
> @@ -6,6 +6,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  struct real_mode_header *real_mode_header;
>  u32 *trampoline_cr4_features;
> @@ -130,6 +131,14 @@ static void __init set_real_mode_permissions(void)
>   unsigned long text_start =
>   (unsigned long) __va(real_mode_header->text_start);
>  
> + /*
> +  * If memory encryption is active, the trampoline area will need to
> +  * be in non-encrypted memory in order to bring up other processors

Let's stick with either "unencrypted" - I'd prefer that one - or
"non-encrypted" nomenclature so that there's no distraction. I see both
versions in the patchset.

-- 
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute

2016-09-09 Thread Borislav Petkov
On Mon, Aug 22, 2016 at 05:37:49PM -0500, Tom Lendacky wrote:
> This patch adds support to be change the memory encryption attribute for
> one or more memory pages.
> 
> Signed-off-by: Tom Lendacky 
> ---
>  arch/x86/include/asm/cacheflush.h  |3 +
>  arch/x86/include/asm/mem_encrypt.h |   13 ++
>  arch/x86/mm/mem_encrypt.c  |   43 +
>  arch/x86/mm/pageattr.c |   75 
> 
>  4 files changed, 134 insertions(+)

...

> diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
> index 72c292d..0ba9382 100644
> --- a/arch/x86/mm/pageattr.c
> +++ b/arch/x86/mm/pageattr.c
> @@ -1728,6 +1728,81 @@ int set_memory_4k(unsigned long addr, int numpages)
>   __pgprot(0), 1, 0, NULL);
>  }
>  
> +static int __set_memory_enc_dec(struct cpa_data *cpa)
> +{
> + unsigned long addr;
> + int numpages;
> + int ret;
> +
> + if (*cpa->vaddr & ~PAGE_MASK) {
> + *cpa->vaddr &= PAGE_MASK;
> +
> + /* People should not be passing in unaligned addresses */
> + WARN_ON_ONCE(1);

Let's make this more user-friendly:

if (WARN_ONCE(*cpa->vaddr & ~PAGE_MASK, "Misaligned address: 0x%lx\n", 
*cpa->vaddr))
*cpa->vaddr &= PAGE_MASK;

> + }
> +
> + addr = *cpa->vaddr;
> + numpages = cpa->numpages;
> +
> + /* Must avoid aliasing mappings in the highmem code */
> + kmap_flush_unused();
> + vm_unmap_aliases();
> +
> + ret = __change_page_attr_set_clr(cpa, 1);
> +
> + /* Check whether we really changed something */
> + if (!(cpa->flags & CPA_FLUSHTLB))
> + goto out;
> +
> + /*
> +  * On success we use CLFLUSH, when the CPU supports it to
> +  * avoid the WBINVD.
> +  */
> + if (!ret && static_cpu_has(X86_FEATURE_CLFLUSH))
> + cpa_flush_range(addr, numpages, 1);
> + else
> + cpa_flush_all(1);

So if we fail (ret != 0) we do WBINVD unconditionally even if we don't
have to?

Don't you want this instead:

ret = __change_page_attr_set_clr(cpa, 1);
if (ret)
goto out;

/* Check whether we really changed something */
if (!(cpa->flags & CPA_FLUSHTLB))
goto out;

/*
 * On success we use CLFLUSH, when the CPU supports it to
 * avoid the WBINVD.
 */
if (static_cpu_has(X86_FEATURE_CLFLUSH))
cpa_flush_range(addr, numpages, 1);
else
cpa_flush_all(1);

out:
return ret;
}

?

-- 
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear

2016-09-09 Thread Borislav Petkov
On Mon, Aug 22, 2016 at 05:37:38PM -0500, Tom Lendacky wrote:
> BOOT data (such as EFI related data) is not encyrpted when the system is
> booted and needs to be accessed as non-encrypted.  Add support to the
> early_memremap API to identify the type of data being accessed so that
> the proper encryption attribute can be applied.  Currently, two types
> of data are defined, KERNEL_DATA and BOOT_DATA.
> 
> Signed-off-by: Tom Lendacky 
> ---

...

> diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
> index 031db21..e3bdc5a 100644
> --- a/arch/x86/mm/ioremap.c
> +++ b/arch/x86/mm/ioremap.c
> @@ -419,6 +419,25 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
>   iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
>  }
>  
> +/*
> + * Architecure override of __weak function to adjust the protection 
> attributes
> + * used when remapping memory.
> + */
> +pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
> +  unsigned long size,
> +  enum memremap_owner owner,
> +  pgprot_t prot)
> +{
> + /*
> +  * If memory encryption is enabled and BOOT_DATA is being mapped
> +  * then remove the encryption bit.
> +  */
> + if (_PAGE_ENC && (owner == BOOT_DATA))
> + prot = __pgprot(pgprot_val(prot) & ~_PAGE_ENC);
> +
> + return prot;
> +}
> +

Hmm, so AFAICT, only arch/x86/xen needs KERNEL_DATA and everything else
is BOOT_DATA.

So instead of touching so many files and changing early_memremap(),
why can't you remove _PAGE_ENC by default on x86 and define a specific
early_memremap() for arch/x86/xen/ which you call there?

That would make this patch soo much smaller and the change simpler.

...

> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 5a2631a..f9286c6 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -386,7 +386,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, 
> efi_memory_desc_t *out_md)
>* So just always get our own virtual map on the CPU.
>*
>*/
> - md = early_memremap(p, sizeof (*md));
> + md = early_memremap(p, sizeof (*md), BOOT_DATA);

WARNING: space prohibited between function name and open parenthesis '('
#432: FILE: drivers/firmware/efi/efi.c:389:
+   md = early_memremap(p, sizeof (*md), BOOT_DATA);

Please integrate checkpatch.pl into your workflow so that you can catch
small style nits like this. And don't take its output too seriously... :-)

>   if (!md) {
>   pr_err_once("early_memremap(%pa, %zu) failed.\n",
>   &p, sizeof (*md));
> @@ -501,7 +501,8 @@ int __init efi_config_parse_tables(void *config_tables, 
> int count, int sz,
>   if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
>   efi_properties_table_t *tbl;
>  
> - tbl = early_memremap(efi.properties_table, sizeof(*tbl));
> + tbl = early_memremap(efi.properties_table, sizeof(*tbl),
> +  BOOT_DATA);
>   if (tbl == NULL) {
>   pr_err("Could not map Properties table!\n");
>   return -ENOMEM;
-- 
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible

2016-09-09 Thread Borislav Petkov
On Mon, Aug 22, 2016 at 05:37:23PM -0500, Tom Lendacky wrote:
> Encrypt memory areas in place when possible (e.g. zero page, etc.) so
> that special handling isn't needed afterwards.
> 
> Signed-off-by: Tom Lendacky 
> ---
>  arch/x86/kernel/head64.c |   93 
> --
>  arch/x86/kernel/setup.c  |8 
>  2 files changed, 96 insertions(+), 5 deletions(-)

...

> +int __init early_make_pgtable(unsigned long address)
> +{
> + unsigned long physaddr = address - __PAGE_OFFSET;
> + pmdval_t pmd;
> +
> + pmd = (physaddr & PMD_MASK) + early_pmd_flags;
> +
> + return __early_make_pgtable(address, pmd);
> +}
> +
> +static void __init create_unencrypted_mapping(void *address, unsigned long 
> size)
> +{
> + unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET;
> + pmdval_t pmd_flags, pmd;
> +
> + if (!sme_me_mask)
> + return;
> +
> + /* Clear the encryption mask from the early_pmd_flags */
> + pmd_flags = early_pmd_flags & ~sme_me_mask;
> +
> + do {
> + pmd = (physaddr & PMD_MASK) + pmd_flags;
> + __early_make_pgtable((unsigned long)address, pmd);
> +
> + address += PMD_SIZE;
> + physaddr += PMD_SIZE;
> + size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
> + } while (size);
> +}
> +
> +static void __init __clear_mapping(unsigned long address)

Should be called something with "pmd" in the name as it clears a PMD,
i.e. __clear_pmd_mapping or so.

> +{
> + unsigned long physaddr = address - __PAGE_OFFSET;
> + pgdval_t pgd, *pgd_p;
> + pudval_t pud, *pud_p;
> + pmdval_t *pmd_p;
> +
> + /* Invalid address or early pgt is done ?  */
> + if (physaddr >= MAXMEM ||
> + read_cr3() != __sme_pa_nodebug(early_level4_pgt))
> + return;
> +
> + pgd_p = &early_level4_pgt[pgd_index(address)].pgd;
> + pgd = *pgd_p;
> +
> + if (!pgd)
> + return;
> +
> + /*
> +  * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches
> +  * __early_make_pgtable where the entry was created.
> +  */
> + pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - 
> phys_base);
> + pud_p += pud_index(address);
> + pud = *pud_p;
> +
> + if (!pud)
> + return;
> +
> + pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - 
> phys_base);
> + pmd_p[pmd_index(address)] = 0;
> +}
> +
> +static void __init clear_mapping(void *address, unsigned long size)
> +{
> + if (!sme_me_mask)
> + return;
> +
> + do {
> + __clear_mapping((unsigned long)address);
> +
> + address += PMD_SIZE;
> + size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
> + } while (size);
> +}
> +
> +static void __init sme_memcpy(void *dst, void *src, unsigned long size)
> +{
> + create_unencrypted_mapping(src, size);
> + memcpy(dst, src, size);
> + clear_mapping(src, size);
> +}
> +

In any case, this whole functionality is SME-specific and should be
somewhere in an SME-specific file. arch/x86/mm/mem_encrypt.c or so...

>  /* Don't add a printk in there. printk relies on the PDA which is not 
> initialized 
> yet. */
>  static void __init clear_bss(void)
> @@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data)
>   char * command_line;
>   unsigned long cmd_line_ptr;
>  
> - memcpy(&boot_params, real_mode_data, sizeof boot_params);
> + sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);

checkpatch.pl:

WARNING: sizeof boot_params should be sizeof(boot_params)
#155: FILE: arch/x86/kernel/head64.c:208:
+   sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);

>   sanitize_boot_params(&boot_params);
>   cmd_line_ptr = get_cmd_line_ptr();
>   if (cmd_line_ptr) {
>   command_line = __va(cmd_line_ptr);
> - memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
> + sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
>   }
>  }
>  
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index 1489da8..1fdaa11 100644
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -114,6 +114,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  /*
>   * max_low_pfn_mapped: highest direct mapped pfn under 4GB
> @@ -376,6 +377,13 @@ static void __init reserve_initrd(void)
>   !ramdisk_image || !ramdisk_size)
>   return; /* No initrd provided by bootloader */
>  
> + /*
> +  * This memory is marked encrypted by the kernel but the ramdisk
> +  * was loaded in the clear by the bootloader, so make sure that
> +  * the ramdisk image is encrypted.
> +  */
> + sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image);

What happens if we go and relocate the ramdisk? I.e., the function above
this one: relocate_initrd(). We hav

Re: [PATCH v6.1] iommu/dma: Add support for mapping MSIs

2016-09-09 Thread Marc Zyngier
Hi Robin,

On 07/09/16 10:55, Robin Murphy wrote:
> When an MSI doorbell is located downstream of an IOMMU, attaching
> devices to a DMA ops domain and switching on translation leads to a rude
> shock when their attempt to write to the physical address returned by
> the irqchip driver faults (or worse, writes into some already-mapped
> buffer) and no interrupt is forthcoming.
> 
> Address this by adding a hook for relevant irqchip drivers to call from
> their compose_msi_msg() callback, to swizzle the physical address with
> an appropriatly-mapped IOVA for any device attached to one of our DMA
> ops domains.
> 
> CC: Thomas Gleixner 
> CC: Jason Cooper 
> CC: Marc Zyngier 
> CC: linux-ker...@vger.kernel.org
> Signed-off-by: Robin Murphy 

Thanks for the quick respin.

Acked-by: Marc Zyngier 

M.
-- 
Jazz is not dead. It just smells funny...
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v6.1] iommu/dma: Add support for mapping MSIs

2016-09-09 Thread Thomas Gleixner
On Wed, 7 Sep 2016, Robin Murphy wrote:
> - Rework map_page() helper function plus insane lookup logic into
>   straightforward get_page() helper
> - Use phys_addr_t to further simplify address matching
> - Fix the bit where I neglected to actually round the doorbell
>   address to a page boundary (oops!)
> - Make the locking hardirq-safe to satisfy lockdep

That looks way better.

Acked-by: Thomas Gleixner 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: Stability connection problems in ath9k kernel 4.7

2016-09-09 Thread Valerio Passini
On venerdì 9 settembre 2016 10:38:32 CEST Joerg Roedel wrote:
> Hi Valerio,
> 
> On Thu, Sep 08, 2016 at 09:07:56PM +0200, Valerio Passini wrote:
> > I'm hoping having done it right and I can try your first suggestion, but I
> > really cannot solve this problem by myself: sorry, I have no capabilities
> > in programming in any known and unknown computer language. Surely, I can
> > test all the patches you want and report the results but this is the best
> > I can do. Best regards
> 
> Can you please send me the full dmesg after boot? The Intel-IOMMU is not
> enabled by default, so I want to check if it is either enabled by
> kernel-config or kernel command-line.
> 
> Thanks,
> 
>   Joerg

Hi Joerg,

It is enabled by kernel config. Indeed, unchecking that option makes the 
problem disappearing.

Valerio

Full dmesg as you asked me.
[0.00] microcode: microcode updated early to revision 0x20, date = 
2016-03-16
[0.00] Linux version 4.7.3 (valerio@Automatix) (gcc version 6.2.0 
20160901 (Debian 6.2.0-3) ) #1 SMP PREEMPT Fri Sep 9 16:15:07 CEST 2016
[0.00] Command line: BOOT_IMAGE=/boot/vmlinuz-4.7.3 
root=UUID=917286ea-e4a0-4a3e-9307-102636ba2a20 ro quiet acpi_osi=
[0.00] x86/fpu: xstate_offset[2]:  576, xstate_sizes[2]:  256
[0.00] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point 
registers'
[0.00] x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
[0.00] x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
[0.00] x86/fpu: Enabled xstate features 0x7, context size is 832 
bytes, using 'standard' format.
[0.00] x86/fpu: Using 'eager' FPU context switches.
[0.00] e820: BIOS-provided physical RAM map:
[0.00] BIOS-e820: [mem 0x-0x00057fff] usable
[0.00] BIOS-e820: [mem 0x00058000-0x00058fff] reserved
[0.00] BIOS-e820: [mem 0x00059000-0x0009dfff] usable
[0.00] BIOS-e820: [mem 0x0009e000-0x0009] reserved
[0.00] BIOS-e820: [mem 0x0010-0xb5df7fff] usable
[0.00] BIOS-e820: [mem 0xb5df8000-0xb5dfefff] ACPI NVS
[0.00] BIOS-e820: [mem 0xb5dff000-0xb6719fff] usable
[0.00] BIOS-e820: [mem 0xb671a000-0xb69b7fff] reserved
[0.00] BIOS-e820: [mem 0xb69b8000-0xc6045fff] usable
[0.00] BIOS-e820: [mem 0xc6046000-0xc624] reserved
[0.00] BIOS-e820: [mem 0xc625-0xc6402fff] usable
[0.00] BIOS-e820: [mem 0xc6403000-0xc6b08fff] ACPI NVS
[0.00] BIOS-e820: [mem 0xc6b09000-0xc6f59fff] reserved
[0.00] BIOS-e820: [mem 0xc6f5a000-0xc6ffefff] type 20
[0.00] BIOS-e820: [mem 0xc6fff000-0xc6ff] usable
[0.00] BIOS-e820: [mem 0xc7c0-0xcfdf] reserved
[0.00] BIOS-e820: [mem 0xf800-0xfbff] reserved
[0.00] BIOS-e820: [mem 0xfec0-0xfec00fff] reserved
[0.00] BIOS-e820: [mem 0xfed0-0xfed03fff] reserved
[0.00] BIOS-e820: [mem 0xfed1c000-0xfed1] reserved
[0.00] BIOS-e820: [mem 0xfee0-0xfee00fff] reserved
[0.00] BIOS-e820: [mem 0xff00-0x] reserved
[0.00] BIOS-e820: [mem 0x0001-0x00022f1f] usable
[0.00] NX (Execute Disable) protection: active
[0.00] efi: EFI v2.31 by American Megatrends
[0.00] efi:  ESRT=0xc6f58798  ACPI 2.0=0xc648b000  ACPI=0xc648b000  
SMBIOS=0xc6f58398 
[0.00] esrt: Reserving ESRT space from 0xc6f58798 to 
0xc6f587d0.
[0.00] SMBIOS 2.7 present.
[0.00] DMI: ASUSTeK COMPUTER INC. N551JW/N551JW, BIOS N551JW.207 
08/03/2015
[0.00] e820: update [mem 0x-0x0fff] usable ==> reserved
[0.00] e820: remove [mem 0x000a-0x000f] usable
[0.00] e820: last_pfn = 0x22f200 max_arch_pfn = 0x4
[0.00] MTRR default type: uncachable
[0.00] MTRR fixed ranges enabled:
[0.00]   0-9 write-back
[0.00]   A-E uncachable
[0.00]   F-F write-protect
[0.00] MTRR variable ranges enabled:
[0.00]   0 base 00 mask 7E write-back
[0.00]   1 base 02 mask 7FE000 write-back
[0.00]   2 base 022000 mask 7FF000 write-back
[0.00]   3 base 00E000 mask 7FE000 uncachable
[0.00]   4 base 00D000 mask 7FF000 uncachable
[0.00]   5 base 00C800 mask 7FF800 uncachable
[0.00]   6 base 00C7C0 mask 7FFFC0 uncachable
[0.00]   7 base 022F80 mask 7FFF80 uncachable
[0.00]   8 base 022F40 mask 7FFFC0 uncachable
[0.00]   9 base 022F20 m

[PATCH v5 12/14] drivers: acpi: iort: replace rid map type with type mask

2016-09-09 Thread Lorenzo Pieralisi
IORT tables provide data that allow the kernel to carry out
device ID mappings between endpoints and system components
(eg interrupt controllers, IOMMUs). When the mapping for a
given device ID is carried out, the translation mechanism
is done on a per-subsystem basis rather than a component
subtype (ie the IOMMU kernel layer will look for mappings
from a device to all IORT node types corresponding to IOMMU
components), therefore the corresponding mapping API should
work on a range (ie mask) of IORT node types corresponding
to a common set of components (eg IOMMUs) rather than a
specific node type.

Upgrade the IORT iort_node_map_rid() API to work with a
type mask instead of a single node type so that it can
be used for mappings that span multiple components types
(ie IOMMUs).

Signed-off-by: Lorenzo Pieralisi 
Cc: Hanjun Guo 
Cc: Tomasz Nowicki 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index a12dda9..36ea93e 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -25,6 +25,9 @@
 #include 
 #include 
 
+#define IORT_TYPE_MASK(type)   (1 << (type))
+#define IORT_MSI_TYPE  (1 << ACPI_IORT_NODE_ITS_GROUP)
+
 struct iort_its_msi_chip {
struct list_headlist;
struct fwnode_handle*fw_node;
@@ -283,7 +286,7 @@ static int iort_id_map(struct acpi_iort_id_mapping *map, u8 
type, u32 rid_in,
 
 static struct acpi_iort_node *iort_node_map_rid(struct acpi_iort_node *node,
u32 rid_in, u32 *rid_out,
-   u8 type)
+   u8 type_mask)
 {
u32 rid = rid_in;
 
@@ -292,7 +295,7 @@ static struct acpi_iort_node *iort_node_map_rid(struct 
acpi_iort_node *node,
struct acpi_iort_id_mapping *map;
int i;
 
-   if (node->type == type) {
+   if (IORT_TYPE_MASK(node->type) & type_mask) {
if (rid_out)
*rid_out = rid;
return node;
@@ -365,7 +368,7 @@ u32 iort_msi_map_rid(struct device *dev, u32 req_id)
if (!node)
return req_id;
 
-   iort_node_map_rid(node, req_id, &dev_id, ACPI_IORT_NODE_ITS_GROUP);
+   iort_node_map_rid(node, req_id, &dev_id, IORT_MSI_TYPE);
return dev_id;
 }
 
-- 
2.10.0

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 14/14] drivers: acpi: iort: introduce iort_iommu_configure

2016-09-09 Thread Lorenzo Pieralisi
DT based systems have a generic kernel API to configure IOMMUs
for devices (ie of_iommu_configure()).

On ARM based ACPI systems, the of_iommu_configure() equivalent can
be implemented atop ACPI IORT kernel API, with the corresponding
functions to map device identifiers to IOMMUs and retrieve the
corresponding IOMMU operations necessary for DMA operations set-up.

By relying on the iommu_fwspec generic kernel infrastructure,
implement the IORT based IOMMU configuration for ARM ACPI systems
and hook it up in the ACPI kernel layer that implements DMA
configuration for a device.

Signed-off-by: Lorenzo Pieralisi 
Cc: Hanjun Guo 
Cc: Tomasz Nowicki 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 96 +++
 drivers/acpi/scan.c   |  7 +++-
 include/linux/acpi_iort.h |  6 +++
 3 files changed, 108 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 7c68eb4..55a4ae9 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -19,6 +19,7 @@
 #define pr_fmt(fmt)"ACPI: IORT: " fmt
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,6 +28,8 @@
 
 #define IORT_TYPE_MASK(type)   (1 << (type))
 #define IORT_MSI_TYPE  (1 << ACPI_IORT_NODE_ITS_GROUP)
+#define IORT_IOMMU_TYPE((1 << ACPI_IORT_NODE_SMMU) |   \
+   (1 << ACPI_IORT_NODE_SMMU_V3))
 
 struct iort_its_msi_chip {
struct list_headlist;
@@ -467,6 +470,99 @@ struct irq_domain *iort_get_device_domain(struct device 
*dev, u32 req_id)
return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
+{
+   u32 *rid = data;
+
+   *rid = alias;
+   return 0;
+}
+
+static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
+  struct fwnode_handle *fwnode)
+{
+   int ret = iommu_fwspec_init(dev, fwnode);
+
+   if (!ret)
+   ret = iommu_fwspec_add_ids(dev, &streamid, 1);
+
+   return ret;
+}
+
+static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
+   struct acpi_iort_node *node,
+   u32 streamid)
+{
+   struct fwnode_handle *iort_fwnode = NULL;
+   int ret;
+
+   if (node) {
+   iort_fwnode = iort_get_fwnode(node);
+   if (!iort_fwnode)
+   return NULL;
+
+   ret = arm_smmu_iort_xlate(dev, streamid,
+ iort_fwnode);
+   if (!ret)
+   return fwspec_iommu_get_ops(iort_fwnode);
+   }
+
+   return NULL;
+}
+
+/**
+ * iort_iommu_configure - Set-up IOMMU configuration for a device.
+ *
+ * @dev: device to configure
+ *
+ * Returns: iommu_ops pointer on configuration success
+ *  NULL on configuration failure
+ */
+const struct iommu_ops *iort_iommu_configure(struct device *dev)
+{
+   struct acpi_iort_node *node, *parent;
+   const struct iommu_ops *ops = NULL;
+   u32 streamid = 0;
+
+   if (dev_is_pci(dev)) {
+   struct pci_bus *bus = to_pci_dev(dev)->bus;
+   u32 rid;
+
+   pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
+  &rid);
+
+   node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
+ iort_match_node_callback, &bus->dev);
+   if (!node)
+   return NULL;
+
+   parent = iort_node_map_rid(node, rid, &streamid,
+  IORT_IOMMU_TYPE);
+
+   ops = iort_iommu_xlate(dev, parent, streamid);
+
+   } else {
+   int i = 0;
+
+   node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
+ iort_match_node_callback, dev);
+   if (!node)
+   return NULL;
+
+   parent = iort_node_get_id(node, &streamid,
+ IORT_IOMMU_TYPE, i++);
+
+   while (parent) {
+   ops = iort_iommu_xlate(dev, parent, streamid);
+
+   parent = iort_node_get_id(node, &streamid,
+ IORT_IOMMU_TYPE, i++);
+   }
+   }
+
+   return ops;
+}
+
 static void __init acpi_iort_register_irq(int hwirq, const char *name,
  int trigger,
  struct resource *res)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 9614232..7e56a85 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1377,11 +1378,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device 
*adev)
  */
 

[PATCH v5 13/14] drivers: acpi: iort: add single mapping function

2016-09-09 Thread Lorenzo Pieralisi
The current IORT id mapping API requires components to provide
an input requester ID (a Bus-Device-Function (BDF) identifier for
PCI devices) to translate an input identifier to an output
identifier through an IORT range mapping.

Named components do not have an identifiable source ID therefore
their respective input/output mapping can only be defined in
IORT tables through single mappings, that provide a translation
that does not require any input identifier.

Current IORT interface for requester id mappings (iort_node_map_rid())
is not suitable for components that do not provide a requester id,
so it cannot be used for IORT named components.

Add an interface to the IORT API to enable retrieval of id
by allowing an indexed walk of the single mappings array for
a given component, therefore completing the IORT mapping API.

Signed-off-by: Lorenzo Pieralisi 
Cc: Hanjun Guo 
Cc: Tomasz Nowicki 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 39 +++
 1 file changed, 39 insertions(+)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 36ea93e..7c68eb4 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -284,6 +284,45 @@ static int iort_id_map(struct acpi_iort_id_mapping *map, 
u8 type, u32 rid_in,
return 0;
 }
 
+static
+struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
+   u32 *id_out, u8 type_mask,
+   int index)
+{
+   struct acpi_iort_node *parent;
+   struct acpi_iort_id_mapping *map;
+
+   if (!node->mapping_offset || !node->mapping_count ||
+index >= node->mapping_count)
+   return NULL;
+
+   map = ACPI_ADD_PTR(struct acpi_iort_id_mapping, node,
+  node->mapping_offset);
+
+   /* Firmware bug! */
+   if (!map->output_reference) {
+   pr_err(FW_BUG "[node %p type %d] ID map has NULL parent 
reference\n",
+  node, node->type);
+   return NULL;
+   }
+
+   parent = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
+  map->output_reference);
+
+   if (!(IORT_TYPE_MASK(parent->type) & type_mask))
+   return NULL;
+
+   if (map[index].flags & ACPI_IORT_ID_SINGLE_MAPPING) {
+   if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT ||
+   node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX) {
+   *id_out = map[index].output_base;
+   return parent;
+   }
+   }
+
+   return NULL;
+}
+
 static struct acpi_iort_node *iort_node_map_rid(struct acpi_iort_node *node,
u32 rid_in, u32 *rid_out,
u8 type_mask)
-- 
2.10.0

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 10/14] drivers: iommu: arm-smmu: split probe functions into DT/generic portions

2016-09-09 Thread Lorenzo Pieralisi
Current ARM SMMU probe functions intermingle HW and DT probing
in the initialization functions to detect and programme the ARM SMMU
driver features. In order to allow probing the ARM SMMU with other
firmwares than DT, this patch splits the ARM SMMU init functions into
DT and HW specific portions so that other FW interfaces (ie ACPI) can
reuse the HW probing functions and skip the DT portion accordingly.

This patch implements no functional change, only code reshuffling.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Robin Murphy 
---
 drivers/iommu/arm-smmu.c | 65 +---
 1 file changed, 39 insertions(+), 26 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index d453c55..bdb4e26 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1665,7 +1665,7 @@ static int arm_smmu_device_cfg_probe(struct 
arm_smmu_device *smmu)
unsigned long size;
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
u32 id;
-   bool cttw_dt, cttw_reg;
+   bool cttw_reg, cttw_fw = smmu->features & ARM_SMMU_FEAT_COHERENT_WALK;
int i;
 
dev_notice(smmu->dev, "probing hardware configuration...\n");
@@ -1710,20 +1710,17 @@ static int arm_smmu_device_cfg_probe(struct 
arm_smmu_device *smmu)
 
/*
 * In order for DMA API calls to work properly, we must defer to what
-* the DT says about coherency, regardless of what the hardware claims.
+* the FW says about coherency, regardless of what the hardware claims.
 * Fortunately, this also opens up a workaround for systems where the
 * ID register value has ended up configured incorrectly.
 */
-   cttw_dt = of_dma_is_coherent(smmu->dev->of_node);
cttw_reg = !!(id & ID0_CTTW);
-   if (cttw_dt)
-   smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
-   if (cttw_dt || cttw_reg)
+   if (cttw_fw || cttw_reg)
dev_notice(smmu->dev, "\t%scoherent table walk\n",
-  cttw_dt ? "" : "non-");
-   if (cttw_dt != cttw_reg)
+  cttw_fw ? "" : "non-");
+   if (cttw_fw != cttw_reg)
dev_notice(smmu->dev,
-  "\t(IDR0.CTTW overridden by dma-coherent 
property)\n");
+  "\t(IDR0.CTTW overridden by FW configuration)\n");
 
/* Max. number of entries we have for stream matching/indexing */
size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
@@ -1904,15 +1901,25 @@ static const struct of_device_id arm_smmu_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
 
-static int arm_smmu_device_dt_probe(struct platform_device *pdev)
+static int arm_smmu_device_dt_probe(struct platform_device *pdev,
+   struct arm_smmu_device *smmu)
 {
const struct arm_smmu_match_data *data;
-   struct resource *res;
-   struct arm_smmu_device *smmu;
struct device *dev = &pdev->dev;
-   int num_irqs, i, err;
bool legacy_binding;
 
+   if (of_property_read_u32(dev->of_node, "#global-interrupts",
+&smmu->num_global_irqs)) {
+   dev_err(dev, "missing #global-interrupts property\n");
+   return -ENODEV;
+   }
+
+   data = of_device_get_match_data(dev);
+   smmu->version = data->version;
+   smmu->model = data->model;
+
+   parse_driver_options(smmu);
+
legacy_binding = of_find_property(dev->of_node, "mmu-masters", NULL);
if (legacy_binding && !using_generic_binding) {
pr_notice("deprecated \"mmu-masters\" DT property in use; DMA 
API support unavailable\n");
@@ -1924,6 +1931,19 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev)
return -ENODEV;
}
 
+   if (of_dma_is_coherent(smmu->dev->of_node))
+   smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
+
+   return 0;
+}
+
+static int arm_smmu_device_probe(struct platform_device *pdev)
+{
+   struct resource *res;
+   struct arm_smmu_device *smmu;
+   struct device *dev = &pdev->dev;
+   int num_irqs, i, err;
+
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
if (!smmu) {
dev_err(dev, "failed to allocate arm_smmu_device\n");
@@ -1931,9 +1951,10 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev)
}
smmu->dev = dev;
 
-   data = of_device_get_match_data(dev);
-   smmu->version = data->version;
-   smmu->model = data->model;
+   err = arm_smmu_device_dt_probe(pdev, smmu);
+
+   if (err)
+   return err;
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
smmu->base = devm_ioremap_resource(dev, res);
@@ -1941,12 +1962,6 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev)
return PTR_ERR(smmu->base);
 

[PATCH v5 06/14] drivers: acpi: implement acpi_dma_configure

2016-09-09 Thread Lorenzo Pieralisi
On DT based systems, the of_dma_configure() API implements DMA
configuration for a given device. On ACPI systems an API equivalent to
of_dma_configure() is missing which implies that it is currently not
possible to set-up DMA operations for devices through the ACPI generic
kernel layer.

This patch fills the gap by introducing acpi_dma_configure/deconfigure()
calls that for now are just wrappers around arch_setup_dma_ops() and
arch_teardown_dma_ops() and also updates ACPI and PCI core code to use
the newly introduced acpi_dma_configure/acpi_dma_deconfigure functions.

The DMA range size passed to arch_setup_dma_ops() is sized according
to the device coherent_dma_mask (starting at address 0x0), mirroring the
DT probing path behaviour when a dma-ranges property is not provided
for the device being probed; this changes the current arch_setup_dma_ops()
call parameters in the ACPI probing case, but since arch_setup_dma_ops()
is a NOP on all architectures but ARM/ARM64 this patch does not change
the current kernel behaviour on them.

Signed-off-by: Lorenzo Pieralisi 
Acked-by: Bjorn Helgaas  [pci]
Cc: Bjorn Helgaas 
Cc: Robin Murphy 
Cc: Tomasz Nowicki 
Cc: Joerg Roedel 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/glue.c |  4 ++--
 drivers/acpi/scan.c | 24 
 drivers/pci/probe.c |  3 +--
 include/acpi/acpi_bus.h |  2 ++
 include/linux/acpi.h|  5 +
 5 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 5ea5dc2..f8d6564 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -227,8 +227,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device 
*acpi_dev)
 
attr = acpi_get_dma_attr(acpi_dev);
if (attr != DEV_DMA_NOT_SUPPORTED)
-   arch_setup_dma_ops(dev, 0, 0, NULL,
-  attr == DEV_DMA_COHERENT);
+   acpi_dma_configure(dev, attr);
 
acpi_physnode_link_name(physical_node_name, node_id);
retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
@@ -251,6 +250,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device 
*acpi_dev)
return 0;
 
  err:
+   acpi_dma_deconfigure(dev);
ACPI_COMPANION_SET(dev, NULL);
put_device(dev);
put_device(&acpi_dev->dev);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e878fc7..9614232 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1370,6 +1370,30 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device 
*adev)
return DEV_DMA_NON_COHERENT;
 }
 
+/**
+ * acpi_dma_configure - Set-up DMA configuration for the device.
+ * @dev: The pointer to the device
+ * @attr: device dma attributes
+ */
+void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
+{
+   /*
+* Assume dma valid range starts at 0 and covers the whole
+* coherent_dma_mask.
+*/
+   arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
+  attr == DEV_DMA_COHERENT);
+}
+
+/**
+ * acpi_dma_deconfigure - Tear-down DMA configuration for the device.
+ * @dev: The pointer to the device
+ */
+void acpi_dma_deconfigure(struct device *dev)
+{
+   arch_teardown_dma_ops(dev);
+}
+
 static void acpi_init_coherency(struct acpi_device *adev)
 {
unsigned long long cca = 0;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 93f280d..e96d482 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1734,8 +1734,7 @@ static void pci_dma_configure(struct pci_dev *dev)
if (attr == DEV_DMA_NOT_SUPPORTED)
dev_warn(&dev->dev, "DMA not supported.\n");
else
-   arch_setup_dma_ops(&dev->dev, 0, 0, NULL,
-  attr == DEV_DMA_COHERENT);
+   acpi_dma_configure(&dev->dev, attr);
}
 
pci_put_host_bridge_device(bridge);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index c1a524d..4242c31 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -573,6 +573,8 @@ struct acpi_pci_root {
 
 bool acpi_dma_supported(struct acpi_device *adev);
 enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
+void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr);
+void acpi_dma_deconfigure(struct device *dev);
 
 struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
   u64 address, bool check_children);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index c5eaf2f..05d4e48 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -729,6 +729,11 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct 
acpi_device *adev)
return DEV_DMA_NOT_SUPPORTED;
 }
 
+static inline void acpi_dma_configure(struct device *dev,
+ enum dev_dma_attr attr) { }
+
+static inline void acpi_dma_deconfigure(

[PATCH v5 08/14] drivers: iommu: arm-smmu-v3: split probe functions into DT/generic portions

2016-09-09 Thread Lorenzo Pieralisi
Current ARM SMMUv3 probe functions intermingle HW and DT probing in the
initialization functions to detect and programme the ARM SMMU v3 driver
features. In order to allow probing the ARM SMMUv3 with other firmwares
than DT, this patch splits the ARM SMMUv3 init functions into DT and HW
specific portions so that other FW interfaces (ie ACPI) can reuse the HW
probing functions and skip the DT portion accordingly.

This patch implements no functional change, only code reshuffling.

Signed-off-by: Lorenzo Pieralisi 
Acked-by: Will Deacon 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Robin Murphy 
Cc: Joerg Roedel 
---
 drivers/iommu/arm-smmu-v3.c | 34 ++
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index a7e9de9..dbc21e3 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2361,10 +2361,10 @@ static int arm_smmu_device_reset(struct arm_smmu_device 
*smmu)
return 0;
 }
 
-static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
+static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 {
u32 reg;
-   bool coherent;
+   bool coherent = smmu->features & ARM_SMMU_FEAT_COHERENCY;
 
/* IDR0 */
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
@@ -2416,13 +2416,9 @@ static int arm_smmu_device_probe(struct arm_smmu_device 
*smmu)
smmu->features |= ARM_SMMU_FEAT_HYP;
 
/*
-* The dma-coherent property is used in preference to the ID
+* The coherency feature as set by FW is used in preference to the ID
 * register, but warn on mismatch.
 */
-   coherent = of_dma_is_coherent(smmu->dev->of_node);
-   if (coherent)
-   smmu->features |= ARM_SMMU_FEAT_COHERENCY;
-
if (!!(reg & IDR0_COHACC) != coherent)
dev_warn(smmu->dev, "IDR0.COHACC overridden by dma-coherent 
property (%s)\n",
 coherent ? "true" : "false");
@@ -2543,7 +2539,18 @@ static int arm_smmu_device_probe(struct arm_smmu_device 
*smmu)
return 0;
 }
 
-static int arm_smmu_device_dt_probe(struct platform_device *pdev)
+static int arm_smmu_device_dt_probe(struct platform_device *pdev,
+   struct arm_smmu_device *smmu)
+{
+   parse_driver_options(smmu);
+
+   if (of_dma_is_coherent(smmu->dev->of_node))
+   smmu->features |= ARM_SMMU_FEAT_COHERENCY;
+
+   return 0;
+}
+
+static int arm_smmu_device_probe(struct platform_device *pdev)
 {
int irq, ret;
struct resource *res;
@@ -2585,10 +2592,13 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev)
if (irq > 0)
smmu->gerr_irq = irq;
 
-   parse_driver_options(smmu);
+   ret = arm_smmu_device_dt_probe(pdev, smmu);
+
+   if (ret)
+   return ret;
 
/* Probe the h/w */
-   ret = arm_smmu_device_probe(smmu);
+   ret = arm_smmu_device_hw_probe(smmu);
if (ret)
return ret;
 
@@ -2606,7 +2616,7 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev)
return ret;
 
/* And we're up. Go go go! */
-   of_iommu_set_ops(dev->of_node, &arm_smmu_ops);
+   fwspec_iommu_set_ops(&dev->of_node->fwnode, &arm_smmu_ops);
 #ifdef CONFIG_PCI
pci_request_acs();
ret = bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
@@ -2640,7 +2650,7 @@ static struct platform_driver arm_smmu_driver = {
.name   = "arm-smmu-v3",
.of_match_table = of_match_ptr(arm_smmu_of_match),
},
-   .probe  = arm_smmu_device_dt_probe,
+   .probe  = arm_smmu_device_probe,
.remove = arm_smmu_device_remove,
 };
 
-- 
2.10.0

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 11/14] drivers: iommu: arm-smmu: add IORT configuration

2016-09-09 Thread Lorenzo Pieralisi
In ACPI bases systems, in order to be able to create platform
devices and initialize them for ARM SMMU components, the IORT
kernel implementation requires a set of static functions to be
used by the IORT kernel layer to configure platform devices for
ARM SMMU components.

Add static configuration functions to the IORT kernel layer for
the ARM SMMU components, so that the ARM SMMU driver can
initialize its respective platform device by relying on the IORT
kernel infrastructure and by adding a corresponding ACPI device
early probe section entry.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Robin Murphy 
Cc: Joerg Roedel 
---
 drivers/acpi/arm64/iort.c |  81 
 drivers/iommu/arm-smmu.c  | 131 +-
 include/linux/acpi_iort.h |   3 ++
 3 files changed, 213 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index a2ad102..a12dda9 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -514,6 +514,78 @@ static bool __init arm_smmu_v3_is_coherent(struct 
acpi_iort_node *node)
return smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE;
 }
 
+static int __init arm_smmu_count_resources(struct acpi_iort_node *node)
+{
+   struct acpi_iort_smmu *smmu;
+   int num_irqs;
+   u64 *glb_irq;
+
+   /* Retrieve SMMU specific data */
+   smmu = (struct acpi_iort_smmu *)node->node_data;
+
+   glb_irq = ACPI_ADD_PTR(u64, node, smmu->global_interrupt_offset);
+   if (!IORT_IRQ_MASK(glb_irq[1])) /* 0 means not implemented */
+   num_irqs = 1;
+   else
+   num_irqs = 2;
+
+   num_irqs += smmu->context_interrupt_count;
+
+   return num_irqs + 1;
+}
+
+static void __init arm_smmu_init_resources(struct resource *res,
+  struct acpi_iort_node *node)
+{
+   struct acpi_iort_smmu *smmu;
+   int i, hw_irq, trigger, num_res = 0;
+   u64 *ctx_irq, *glb_irq;
+
+   /* Retrieve SMMU specific data */
+   smmu = (struct acpi_iort_smmu *)node->node_data;
+
+   res[num_res].start = smmu->base_address;
+   res[num_res].end = smmu->base_address + smmu->span - 1;
+   res[num_res].flags = IORESOURCE_MEM;
+   num_res++;
+
+   glb_irq = ACPI_ADD_PTR(u64, node, smmu->global_interrupt_offset);
+   /* Global IRQs */
+   hw_irq = IORT_IRQ_MASK(glb_irq[0]);
+   trigger = IORT_IRQ_TRIGGER_MASK(glb_irq[0]);
+
+   acpi_iort_register_irq(hw_irq, "arm-smmu-global", trigger,
+&res[num_res++]);
+
+   /* Global IRQs */
+   hw_irq = IORT_IRQ_MASK(glb_irq[1]);
+   if (hw_irq) {
+   trigger = IORT_IRQ_TRIGGER_MASK(glb_irq[1]);
+   acpi_iort_register_irq(hw_irq, "arm-smmu-global", trigger,
+&res[num_res++]);
+   }
+
+   /* Context IRQs */
+   ctx_irq = ACPI_ADD_PTR(u64, node, smmu->context_interrupt_offset);
+   for (i = 0; i < smmu->context_interrupt_count; i++) {
+   hw_irq = IORT_IRQ_MASK(ctx_irq[i]);
+   trigger = IORT_IRQ_TRIGGER_MASK(ctx_irq[i]);
+
+   acpi_iort_register_irq(hw_irq, "arm-smmu-context", trigger,
+  &res[num_res++]);
+   }
+}
+
+static bool __init arm_smmu_is_coherent(struct acpi_iort_node *node)
+{
+   struct acpi_iort_smmu *smmu;
+
+   /* Retrieve SMMU specific data */
+   smmu = (struct acpi_iort_smmu *)node->node_data;
+
+   return smmu->flags & ACPI_IORT_SMMU_COHERENT_WALK;
+}
+
 struct iort_iommu_config {
const char *name;
int (*iommu_init)(struct acpi_iort_node *node);
@@ -530,12 +602,21 @@ static const struct iort_iommu_config 
iort_arm_smmu_v3_cfg __initconst = {
.iommu_init_resources = arm_smmu_v3_init_resources
 };
 
+static const struct iort_iommu_config iort_arm_smmu_cfg __initconst = {
+   .name = "arm-smmu",
+   .iommu_is_coherent = arm_smmu_is_coherent,
+   .iommu_count_resources = arm_smmu_count_resources,
+   .iommu_init_resources = arm_smmu_init_resources
+};
+
 static __init
 const struct iort_iommu_config *iort_get_iommu_cfg(struct acpi_iort_node *node)
 {
switch (node->type) {
case ACPI_IORT_NODE_SMMU_V3:
return &iort_arm_smmu_v3_cfg;
+   case ACPI_IORT_NODE_SMMU:
+   return &iort_arm_smmu_cfg;
default:
return NULL;
}
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index bdb4e26..a4d3030 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -28,6 +28,8 @@
 
 #define pr_fmt(fmt) "arm-smmu: " fmt
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -1901,6 +1903,71 @@ static const struct of_device_id arm_smmu_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
 
+#ifdef CONFIG_ACPI
+static int acpi_smmu_get_data(u32 model, u32 *version,

[PATCH v5 05/14] drivers: iommu: make iommu_fwspec OF agnostic

2016-09-09 Thread Lorenzo Pieralisi
The iommu_fwspec structure, used to hold per device iommu configuration
data is not OF specific and therefore can be moved to a generic
and OF independent compilation unit.

In particular, the iommu_fwspec handling hinges on the device_node
pointer to identify the IOMMU device associated with the iommu_fwspec
structure, that is easily converted to a more generic fwnode_handle
pointer that can cater for OF and non-OF (ie ACPI) systems.

Create the files and related Kconfig entry to decouple iommu_fwspec
structure from the OF iommu kernel layer.

Given that the current iommu_fwspec implementation relies on
the arch specific struct device.archdata.iommu field in its
implementation, by making the code standalone and independent
of the OF layer this patch makes sure that the iommu_fwspec
kernel code can be selected only on arches implementing the
struct device.archdata.iommu field by adding an explicit
arch dependency in its config entry.

Current drivers using the iommu_fwspec for streamid translation
are converted to the new iommu_fwspec API by simply converting
the device_node to its fwnode_handle pointer.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Robin Murphy 
Cc: Joerg Roedel 
---
 drivers/iommu/Kconfig|   4 ++
 drivers/iommu/Makefile   |   1 +
 drivers/iommu/arm-smmu-v3.c  |  16 --
 drivers/iommu/arm-smmu.c |  17 +++---
 drivers/iommu/iommu-fwspec.c | 126 +++
 drivers/iommu/of_iommu.c |  93 
 include/linux/iommu-fwspec.h |  70 
 include/linux/of_iommu.h |  38 -
 8 files changed, 234 insertions(+), 131 deletions(-)
 create mode 100644 drivers/iommu/iommu-fwspec.c
 create mode 100644 include/linux/iommu-fwspec.h

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 101cb17..873bd41 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -70,6 +70,10 @@ config OF_IOMMU
 config HAVE_IOMMU_FWSPEC
bool
 
+config IOMMU_FWSPEC
+   def_bool y
+   depends on IOMMU_API
+
 # IOMMU-agnostic DMA-mapping layer
 config IOMMU_DMA
bool
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 195f7b9..bbbc6d6 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
+obj-$(CONFIG_IOMMU_FWSPEC) += iommu-fwspec.o
 obj-$(CONFIG_OF_IOMMU) += of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index be293b5..a7e9de9 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1720,13 +1721,18 @@ static struct platform_driver arm_smmu_driver;
 
 static int arm_smmu_match_node(struct device *dev, void *data)
 {
-   return dev->of_node == data;
+   struct fwnode_handle *fwnode;
+
+   fwnode = dev->of_node ? &dev->of_node->fwnode : dev->fwnode;
+
+   return fwnode == data;
 }
 
-static struct arm_smmu_device *arm_smmu_get_by_node(struct device_node *np)
+static struct arm_smmu_device *
+arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode)
 {
struct device *dev = driver_find_device(&arm_smmu_driver.driver, NULL,
-   np, arm_smmu_match_node);
+   fwnode, arm_smmu_match_node);
put_device(dev);
return dev ? dev_get_drvdata(dev) : NULL;
 }
@@ -1762,7 +1768,7 @@ static int arm_smmu_add_device(struct device *dev)
master = fwspec->iommu_priv;
smmu = master->smmu;
} else {
-   smmu = arm_smmu_get_by_node(fwspec->iommu_np);
+   smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
if (!smmu)
return -ENODEV;
master = kzalloc(sizeof(*master), GFP_KERNEL);
@@ -1874,7 +1880,7 @@ out_unlock:
 
 static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
 {
-   int ret = iommu_fwspec_init(dev, args->np);
+   int ret = iommu_fwspec_init(dev, &args->np->fwnode);
 
if (!ret)
ret = iommu_fwspec_add_ids(dev, &args->args[0], 1);
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 2e20cdc..d453c55 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -517,7 +517,7 @@ static int arm_smmu_register_legacy_master(struct device 
*dev,
it.cur_count = 1;
}
 
-   err = iommu_fwspec_init(dev, smmu_dev->of_node);
+   err = iommu_fwspec_init(dev, &smmu_dev->of_node->fwnode);
if (err)
return err;
 
@@ -1368,1

[PATCH v5 09/14] drivers: iommu: arm-smmu-v3: add IORT configuration

2016-09-09 Thread Lorenzo Pieralisi
In ACPI bases systems, in order to be able to create platform
devices and initialize them for ARM SMMU v3 components, the IORT
kernel implementation requires a set of static functions to be
used by the IORT kernel layer to configure platform devices for
ARM SMMU v3 components.

Add static configuration functions to the IORT kernel layer for
the ARM SMMU v3 components, so that the ARM SMMU v3 driver can
initialize its respective platform device by relying on the IORT
kernel infrastructure and by adding a corresponding ACPI device
early probe section entry.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Robin Murphy 
Cc: Joerg Roedel 
---
 drivers/acpi/arm64/iort.c   | 103 +++-
 drivers/iommu/arm-smmu-v3.c |  95 +++-
 2 files changed, 195 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index e0a9b16..a2ad102 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -425,6 +425,95 @@ struct irq_domain *iort_get_device_domain(struct device 
*dev, u32 req_id)
return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+static void __init acpi_iort_register_irq(int hwirq, const char *name,
+ int trigger,
+ struct resource *res)
+{
+   int irq = acpi_register_gsi(NULL, hwirq, trigger,
+   ACPI_ACTIVE_HIGH);
+
+   if (irq < 0) {
+   pr_err("could not register gsi hwirq %d name [%s]\n", hwirq,
+ name);
+   return;
+   }
+
+   res->start = irq;
+   res->end = irq;
+   res->flags = IORESOURCE_IRQ;
+   res->name = name;
+}
+
+static int __init arm_smmu_v3_count_resources(struct acpi_iort_node *node)
+{
+   struct acpi_iort_smmu_v3 *smmu;
+   /* Always present mem resource */
+   int num_res = 1;
+
+   /* Retrieve SMMUv3 specific data */
+   smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+   if (smmu->event_gsiv)
+   num_res++;
+
+   if (smmu->pri_gsiv)
+   num_res++;
+
+   if (smmu->gerr_gsiv)
+   num_res++;
+
+   if (smmu->sync_gsiv)
+   num_res++;
+
+   return num_res;
+}
+
+static void __init arm_smmu_v3_init_resources(struct resource *res,
+ struct acpi_iort_node *node)
+{
+   struct acpi_iort_smmu_v3 *smmu;
+   int num_res = 0;
+
+   /* Retrieve SMMUv3 specific data */
+   smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+   res[num_res].start = smmu->base_address;
+   res[num_res].end = smmu->base_address + SZ_128K - 1;
+   res[num_res].flags = IORESOURCE_MEM;
+
+   num_res++;
+
+   if (smmu->event_gsiv)
+   acpi_iort_register_irq(smmu->event_gsiv, "eventq",
+  ACPI_EDGE_SENSITIVE,
+  &res[num_res++]);
+
+   if (smmu->pri_gsiv)
+   acpi_iort_register_irq(smmu->pri_gsiv, "priq",
+  ACPI_EDGE_SENSITIVE,
+  &res[num_res++]);
+
+   if (smmu->gerr_gsiv)
+   acpi_iort_register_irq(smmu->gerr_gsiv, "gerror",
+  ACPI_EDGE_SENSITIVE,
+  &res[num_res++]);
+
+   if (smmu->sync_gsiv)
+   acpi_iort_register_irq(smmu->sync_gsiv, "cmdq-sync",
+  ACPI_EDGE_SENSITIVE,
+  &res[num_res++]);
+}
+
+static bool __init arm_smmu_v3_is_coherent(struct acpi_iort_node *node)
+{
+   struct acpi_iort_smmu_v3 *smmu;
+
+   /* Retrieve SMMUv3 specific data */
+   smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+   return smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE;
+}
+
 struct iort_iommu_config {
const char *name;
int (*iommu_init)(struct acpi_iort_node *node);
@@ -434,10 +523,22 @@ struct iort_iommu_config {
 struct acpi_iort_node *node);
 };
 
+static const struct iort_iommu_config iort_arm_smmu_v3_cfg __initconst = {
+   .name = "arm-smmu-v3",
+   .iommu_is_coherent = arm_smmu_v3_is_coherent,
+   .iommu_count_resources = arm_smmu_v3_count_resources,
+   .iommu_init_resources = arm_smmu_v3_init_resources
+};
+
 static __init
 const struct iort_iommu_config *iort_get_iommu_cfg(struct acpi_iort_node *node)
 {
-   return NULL;
+   switch (node->type) {
+   case ACPI_IORT_NODE_SMMU_V3:
+   return &iort_arm_smmu_v3_cfg;
+   default:
+   return NULL;
+   }
 }
 
 /**
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index dbc21e3..9463f3f 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b

[PATCH v5 07/14] drivers: acpi: iort: add support for ARM SMMU platform devices creation

2016-09-09 Thread Lorenzo Pieralisi
In ARM ACPI systems, IOMMU components are specified through static
IORT table entries. In order to create platform devices for the
corresponding ARM SMMU components, IORT kernel code should be made
able to parse IORT table entries and create platform devices
dynamically.

This patch adds the generic IORT infrastructure required to create
platform devices for ARM SMMUs.

ARM SMMU versions have different resources requirement therefore this
patch also introduces an IORT specific structure (ie iort_iommu_config)
that contains hooks (to be defined when the corresponding ARM SMMU
driver support is added to the kernel) to be used to define the
platform devices names, init the IOMMUs, count their resources and
finally initialize them.

Signed-off-by: Lorenzo Pieralisi 
Cc: Hanjun Guo 
Cc: Tomasz Nowicki 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 131 ++
 1 file changed, 131 insertions(+)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index b89b3d3..e0a9b16 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 struct iort_its_msi_chip {
@@ -424,6 +425,135 @@ struct irq_domain *iort_get_device_domain(struct device 
*dev, u32 req_id)
return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+struct iort_iommu_config {
+   const char *name;
+   int (*iommu_init)(struct acpi_iort_node *node);
+   bool (*iommu_is_coherent)(struct acpi_iort_node *node);
+   int (*iommu_count_resources)(struct acpi_iort_node *node);
+   void (*iommu_init_resources)(struct resource *res,
+struct acpi_iort_node *node);
+};
+
+static __init
+const struct iort_iommu_config *iort_get_iommu_cfg(struct acpi_iort_node *node)
+{
+   return NULL;
+}
+
+/**
+ * iort_add_smmu_platform_device() - Allocate a platform device for SMMU
+ * @fwnode: IORT node associated fwnode handle
+ * @node: Pointer to SMMU ACPI IORT node
+ *
+ * Returns: 0 on success, <0 failure
+ */
+static int __init iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
+   struct acpi_iort_node *node)
+{
+   struct platform_device *pdev;
+   struct resource *r;
+   enum dev_dma_attr attr;
+   int ret, count;
+   const struct iort_iommu_config *ops = iort_get_iommu_cfg(node);
+
+   if (!ops)
+   return -ENODEV;
+
+   pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO);
+   if (!pdev)
+   return PTR_ERR(pdev);
+
+   count = ops->iommu_count_resources(node);
+
+   r = kcalloc(count, sizeof(*r), GFP_KERNEL);
+   if (!r) {
+   ret = -ENOMEM;
+   goto dev_put;
+   }
+
+   ops->iommu_init_resources(r, node);
+
+   ret = platform_device_add_resources(pdev, r, count);
+   /*
+* Resources are duplicated in platform_device_add_resources,
+* free their allocated memory
+*/
+   kfree(r);
+
+   if (ret)
+   goto dev_put;
+
+   /*
+* Add a copy of IORT node pointer to platform_data to
+* be used to retrieve IORT data information.
+*/
+   ret = platform_device_add_data(pdev, &node, sizeof(node));
+   if (ret)
+   goto dev_put;
+
+   pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
+   if (!pdev->dev.dma_mask) {
+   ret = -ENOMEM;
+   goto dev_put;
+   }
+
+   pdev->dev.fwnode = fwnode;
+
+   /*
+* Set default dma mask value for the table walker,
+* to be overridden on probing with correct value.
+*/
+   *pdev->dev.dma_mask = DMA_BIT_MASK(32);
+   pdev->dev.coherent_dma_mask = *pdev->dev.dma_mask;
+
+   attr = ops->iommu_is_coherent(node) ?
+DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT;
+
+   /* Configure DMA for the page table walker */
+   acpi_dma_configure(&pdev->dev, attr);
+
+   ret = platform_device_add(pdev);
+   if (ret)
+   goto dma_deconfigure;
+
+   return 0;
+
+dma_deconfigure:
+   acpi_dma_deconfigure(&pdev->dev);
+   kfree(pdev->dev.dma_mask);
+
+dev_put:
+   platform_device_put(pdev);
+
+   return ret;
+}
+
+static acpi_status __init iort_match_iommu_callback(struct acpi_iort_node 
*node,
+   void *context)
+{
+   int ret;
+   struct fwnode_handle *fwnode;
+
+   fwnode = iort_get_fwnode(node);
+
+   if (!fwnode)
+   return AE_NOT_FOUND;
+
+   ret = iort_add_smmu_platform_device(fwnode, node);
+   if (ret) {
+   pr_err("Error in platform device creation\n");
+   return AE_ERROR;
+   }
+
+   return AE_OK;
+}
+
+static void __init iort_smmu_init(void)
+{
+   iort_scan_node(ACPI_IORT_NODE_SMMU, iort_m

[PATCH v5 04/14] drivers: acpi: iort: add support for IOMMU fwnode registration

2016-09-09 Thread Lorenzo Pieralisi
The ACPI IORT table provide entries for IOMMU (aka SMMU in ARM world)
components that allow creating the kernel data structures required to
probe and initialize the IOMMU devices.

This patch provides support in the IORT kernel code to register IOMMU
components and their respective fwnode.

Signed-off-by: Lorenzo Pieralisi 
Reviewed-by: Hanjun Guo 
Cc: Hanjun Guo 
Cc: Tomasz Nowicki 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 65 +++
 include/linux/acpi_iort.h |  9 +++
 2 files changed, 74 insertions(+)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 4cbeb707..b89b3d3 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -20,7 +20,9 @@
 
 #include 
 #include 
+#include 
 #include 
+#include 
 
 struct iort_its_msi_chip {
struct list_headlist;
@@ -28,6 +30,69 @@ struct iort_its_msi_chip {
u32 translation_id;
 };
 
+struct iort_fwnode {
+   struct list_head list;
+   struct acpi_iort_node *iort_node;
+   struct fwnode_handle *fwnode;
+};
+static LIST_HEAD(iort_fwnode_list);
+static DEFINE_SPINLOCK(iort_fwnode_lock);
+
+/**
+ * iort_set_fwnode() - Create iort_fwnode and use it to register
+ *iommu data in the iort_fwnode_list
+ *
+ * @node: IORT table node associated with the IOMMU
+ * @fwnode: fwnode associated with the IORT node
+ *
+ * Returns: 0 on success
+ *  <0 on failure
+ */
+int iort_set_fwnode(struct acpi_iort_node *iort_node,
+   struct fwnode_handle *fwnode)
+{
+   struct iort_fwnode *np;
+
+   np = kzalloc(sizeof(struct iort_fwnode), GFP_ATOMIC);
+
+   if (WARN_ON(!np))
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(&np->list);
+   np->iort_node = iort_node;
+   np->fwnode = fwnode;
+
+   spin_lock(&iort_fwnode_lock);
+   list_add_tail(&np->list, &iort_fwnode_list);
+   spin_unlock(&iort_fwnode_lock);
+
+   return 0;
+}
+
+/**
+ * iort_get_fwnode() - Retrieve fwnode associated with an IORT node
+ *
+ * @node: IORT table node to be looked-up
+ *
+ * Returns: fwnode_handle pointer on success, NULL on failure
+*/
+struct fwnode_handle *iort_get_fwnode(struct acpi_iort_node *node)
+{
+   struct iort_fwnode *curr;
+   struct fwnode_handle *fwnode = NULL;
+
+   spin_lock(&iort_fwnode_lock);
+   list_for_each_entry(curr, &iort_fwnode_list, list) {
+   if (curr->iort_node == node) {
+   fwnode = curr->fwnode;
+   break;
+   }
+   }
+   spin_unlock(&iort_fwnode_lock);
+
+   return fwnode;
+}
+
 typedef acpi_status (*iort_find_node_callback)
(struct acpi_iort_node *node, void *context);
 
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index d16fdda..c851646 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -30,6 +30,9 @@ struct fwnode_handle *iort_find_domain_token(int trans_id);
 void acpi_iort_init(void);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
+int iort_set_fwnode(struct acpi_iort_node *iort_node,
+   struct fwnode_handle *fwnode);
+struct fwnode_handle *iort_get_fwnode(struct acpi_iort_node *node);
 #else
 static inline void acpi_iort_init(void) { }
 static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
@@ -37,6 +40,12 @@ static inline u32 iort_msi_map_rid(struct device *dev, u32 
req_id)
 static inline struct irq_domain *iort_get_device_domain(struct device *dev,
u32 req_id)
 { return NULL; }
+static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
+ struct fwnode_handle *fwnode)
+{ return -ENODEV; }
+static inline
+struct fwnode_handle *iort_get_fwnode(struct acpi_iort_node *node)
+{ return NULL; }
 #endif
 
 #define IORT_ACPI_DECLARE(name, table_id, fn)  \
-- 
2.10.0

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 00/14] ACPI IORT ARM SMMU support

2016-09-09 Thread Lorenzo Pieralisi
This patch series is v5 of a previous posting:

https://lkml.org/lkml/2016/8/15/394

v4 -> v5
- Added SMMUv1/v2 support
- Rebased against v4.8-rc5 and dependencies series
- Consolidated IORT platform devices creation

v3 -> v4
- Added single mapping API (for IORT named components)
- Fixed arm_smmu_iort_xlate() return value
- Reworked fwnode registration and platform device creation
  ordering to fix probe ordering dependencies
- Added code to keep device_node ref count with new iommu
  fwspec API
- Added patch to make iommu_fwspec arch agnostic
- Dropped RFC status
- Rebased against v4.8-rc2

v2 -> v3
- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
- Added back reliance on ACPI early probing infrastructure
- Patch[1-3] merged through other dependent series
- Added back IOMMU fwnode generalization
- Move SMMU v3 static functions configuration to IORT code
- Implemented generic IOMMU fwspec API
- Added code to implement fwnode platform device look-up

v1 -> v2:
- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
- Removed IOMMU fwnode generalization
- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
  owing to patch series dependencies [1]
- Moved platform device creation logic to IORT code to
  generalize its usage for ARM SMMU v1-v2-v3 components
- Removed reliance on ACPI early device probing
- Created IORT specific iommu_xlate() translation hook leaving
  OF code unchanged according to v1 reviews

The ACPI IORT table provides information that allows instantiating
ARM SMMU devices and carrying out id mappings between components on
ARM based systems (devices, IOMMUs, interrupt controllers).

http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf

Building on basic IORT support, available through [2],
this patchset enables ARM SMMUs support on ACPI systems.

Most of the code is aimed at building the required generic ACPI
infrastructure to create and enable IOMMU components and to bring
the IOMMU infrastructure for ACPI on par with DT, which is going to
make future ARM SMMU components easier to integrate.

PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
  It is required to attach a fwnode identifier to platform
  devices allocated/detected through IORT tables entries;
  IOMMU devices have to have an identifier to look them up
  eg IOMMU core layer carrying out id translation. This can be
  done through a fwnode_handle (ie IOMMU platform devices created
  out of IORT tables are not ACPI devices hence they can't be
  allocated as such, otherwise they would have a fwnode_handle of
  type FWNODE_ACPI).

PATCH (2) Add kernel infrastructure to make the struct iommu_fwspec
  handling arch agnostic and generic.

PATCH (3) makes use of the ACPI early probing API to add a linker script
  section for probing devices via IORT ACPI kernel code.

PATCH (4) provides IORT support for registering IOMMU IORT node through
  their fwnode handle.

PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
  system by creating a generic IOMMU fwspec kernel layer.

PATCH (6) implements the of_dma_configure() API in ACPI world -
  acpi_dma_configure() - and patches PCI and ACPI core code to
  start making use of it.

PATCH (7) creates the kernel infrastructure required to create ARM SMMU
  platform devices for IORT nodes.

PATCH (8) refactors the ARM SMMU v3 driver so that the init functions are
  split in a way that groups together code that probes through DT
  and code that carries out HW registers FW agnostic probing, in
  preparation for adding the ACPI probing path.

PATCH (9) Building on patch (7), it adds ARM SMMU v3 IORT IOMMU
  operations to create and probe ARM SMMU v3 components.

PATCH (10) refactors the ARM SMMU v1/v2 driver so that the init functions
   are split in a way that groups together code that probes
   through DT and code that carries out HW registers FW agnostic
   probing, in preparation for adding the ACPI probing path.

PATCH (11) Building on patch (7), it adds ARM SMMU v1/v2 IORT IOMMU
   operations to create and probe ARM SMMU v1/v2 components.

PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
   instead of a single type so that the translation API can
   be used on a range of components.

PATCH (13) Add IORT API to carry out id mappings for components that do
   do not have an input identifier/RIDs (ie named components).

PATCH (14) provides IORT infrastructure to carry out IOMMU configuration
   for devices and hook it up to the previously introduced ACP

[PATCH v5 02/14] drivers: iommu: implement arch_{set/get}_iommu_fwspec API

2016-09-09 Thread Lorenzo Pieralisi
The iommu fwspec configuration mechanism currently relies on
the arch specific struct dev_archdata.iommu member to stash
the struct iommu_fwspec pointer set-up for streamid translation.

The struct dev_archdata.iommu member is arch specific and is not present
on all arches that make use of the struct iommu_fwspec infrastructure,
hence an arch specific kernel API is required to set-up and retrieve
struct iommu_fwspec pointers safely from generic iommu code, hiding
the arch specific details.

Implement the arch_{set/get}_iommu_fwspec() generic kernel infrastructure
and add the ARM/ARM64 back-end implementations.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Rob Herring 
Cc: Robin Murphy 
Cc: Joerg Roedel 
Cc: "Rafael J. Wysocki" 
---
 arch/arm/Kconfig  |  1 +
 arch/arm/include/asm/iommu-fwspec.h   | 30 ++
 arch/arm64/Kconfig|  1 +
 arch/arm64/include/asm/iommu-fwspec.h | 30 ++
 drivers/iommu/Kconfig |  3 +++
 drivers/iommu/of_iommu.c  | 14 +++---
 include/linux/of_iommu.h  | 10 ++
 7 files changed, 82 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm/include/asm/iommu-fwspec.h
 create mode 100644 arch/arm64/include/asm/iommu-fwspec.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a9c4e48..e84f62e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -59,6 +59,7 @@ config ARM
select HAVE_GENERIC_DMA_COHERENT
select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || 
CPU_V7))
select HAVE_IDE if PCI || ISA || PCMCIA
+   select HAVE_IOMMU_FWSPEC if IOMMU_API
select HAVE_IRQ_TIME_ACCOUNTING
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZ4
diff --git a/arch/arm/include/asm/iommu-fwspec.h 
b/arch/arm/include/asm/iommu-fwspec.h
new file mode 100644
index 000..2e87d8b
--- /dev/null
+++ b/arch/arm/include/asm/iommu-fwspec.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+#ifndef __ASM_IOMMU_FWSPEC_H
+#define __ASM_IOMMU_FWSPEC_H
+
+static inline void arch_set_iommu_fwspec(struct device *dev,
+struct iommu_fwspec *fwspec)
+{
+   dev->archdata.iommu = fwspec;
+}
+
+static inline struct iommu_fwspec *arch_get_iommu_fwspec(struct device *dev)
+{
+   return dev->archdata.iommu;
+}
+#endif
+
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index bc3f00f..10c9b3d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -83,6 +83,7 @@ config ARM64
select HAVE_GCC_PLUGINS
select HAVE_GENERIC_DMA_COHERENT
select HAVE_HW_BREAKPOINT if PERF_EVENTS
+   select HAVE_IOMMU_FWSPEC if IOMMU_API
select HAVE_IRQ_TIME_ACCOUNTING
select HAVE_MEMBLOCK
select HAVE_MEMBLOCK_NODE_MAP if NUMA
diff --git a/arch/arm64/include/asm/iommu-fwspec.h 
b/arch/arm64/include/asm/iommu-fwspec.h
new file mode 100644
index 000..2e87d8b
--- /dev/null
+++ b/arch/arm64/include/asm/iommu-fwspec.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+#ifndef __ASM_IOMMU_FWSPEC_H
+#define __ASM_IOMMU_FWSPEC_H
+
+static inline void arch_set_iommu_fwspec(struct device *dev,
+struct iommu_fwspec *fwspec)
+{
+   dev->archdata.iommu = fwspec;
+}
+
+static inline struct iommu_fwspec *arch_get_iommu_fwspec(struct device *dev)
+{
+   return dev->archdata.iommu;
+}
+#endif
+
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 8ee54d7..101cb17 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -67,6 +67,9 @@ config OF_IOMMU
def_bool y
depends on OF && IOMMU_API
 
+config HAVE_IOMMU_FWSPEC
+   bool
+
 # IOMMU-agnostic DMA-mapping layer
 config IOM

[PATCH v5 03/14] drivers: acpi: iort: introduce linker section for IORT entries probing

2016-09-09 Thread Lorenzo Pieralisi
Since commit e647b532275b ("ACPI: Add early device probing
infrastructure") the kernel has gained the infrastructure that allows
adding linker script section entries to execute ACPI driver callbacks
(ie probe routines) for all subsystems that register a table entry
in the respective kernel section (eg clocksource, irqchip).

Since ARM IOMMU devices data is described through IORT tables when
booting with ACPI, the ARM IOMMU drivers must be made able to hook ACPI
callback routines that are called to probe IORT entries and initialize
the respective IOMMU devices.

To avoid adding driver specific hooks into IORT table initialization
code (breaking therefore code modularity - ie ACPI IORT code must be made
aware of ARM SMMU drivers ACPI init callbacks), this patch adds code
that allows ARM SMMU drivers to take advantage of the ACPI early probing
infrastructure, so that they can add linker script section entries
containing drivers callback to be executed on IORT tables detection.

Since IORT nodes are differentiated by a type, the callback routines
can easily parse the IORT table entries, check the IORT nodes and
carry out some actions whenever the IORT node type associated with
the driver specific callback is matched.

Signed-off-by: Lorenzo Pieralisi 
Reviewed-by: Hanjun Guo 
Cc: Tomasz Nowicki 
Cc: "Rafael J. Wysocki" 
Cc: Marc Zyngier 
---
 drivers/acpi/arm64/iort.c | 3 +++
 include/asm-generic/vmlinux.lds.h | 1 +
 include/linux/acpi_iort.h | 3 +++
 3 files changed, 7 insertions(+)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index a6fba4d..4cbeb707 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -367,5 +367,8 @@ void __init acpi_iort_init(void)
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
const char *msg = acpi_format_exception(status);
pr_err("Failed to get table, %s\n", msg);
+   return;
}
+
+   acpi_probe_device_table(iort);
 }
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 2456397..7ee4e0c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -546,6 +546,7 @@
IRQCHIP_OF_MATCH_TABLE()\
ACPI_PROBE_TABLE(irqchip)   \
ACPI_PROBE_TABLE(clksrc)\
+   ACPI_PROBE_TABLE(iort)  \
EARLYCON_TABLE()
 
 #define INIT_TEXT  \
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 0e32dac..d16fdda 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -39,4 +39,7 @@ static inline struct irq_domain 
*iort_get_device_domain(struct device *dev,
 { return NULL; }
 #endif
 
+#define IORT_ACPI_DECLARE(name, table_id, fn)  \
+   ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn)
+
 #endif /* __ACPI_IORT_H__ */
-- 
2.10.0

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 01/14] drivers: iommu: add FWNODE_IOMMU fwnode type

2016-09-09 Thread Lorenzo Pieralisi
On systems booting with a device tree, every struct device is
associated with a struct device_node, that represents its DT
representation. The device node can be used in generic kernel
contexts (eg IRQ translation, IOMMU streamid mapping), to
retrieve the properties associated with the device and carry
out kernel operation accordingly. Owing to the 1:1 relationship
between the device and its device_node, the device_node can also
be used as a look-up token for the device (eg looking up a device
through its device_node), to retrieve the device in kernel paths
where the device_node is available.

On systems booting with ACPI, the same abstraction provided by
the device_node is required to provide look-up functionality.

Therefore, mirroring the approach implemented in the IRQ domain
kernel layer, this patch adds an additional fwnode type FWNODE_IOMMU.

This patch also implements a glue kernel layer that allows to
allocate/free FWNODE_IOMMU fwnode_handle structures and associate
them with IOMMU devices.

Signed-off-by: Lorenzo Pieralisi 
Reviewed-by: Hanjun Guo 
Cc: Joerg Roedel 
Cc: "Rafael J. Wysocki" 
---
 include/linux/fwnode.h |  1 +
 include/linux/iommu.h  | 25 +
 2 files changed, 26 insertions(+)

diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 8516717..6e10050 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -19,6 +19,7 @@ enum fwnode_type {
FWNODE_ACPI_DATA,
FWNODE_PDATA,
FWNODE_IRQCHIP,
+   FWNODE_IOMMU,
 };
 
 struct fwnode_handle {
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index a35fb8b..6456528 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -38,6 +38,7 @@ struct bus_type;
 struct device;
 struct iommu_domain;
 struct notifier_block;
+struct fwnode_handle;
 
 /* iommu fault flags */
 #define IOMMU_FAULT_READ   0x0
@@ -543,4 +544,28 @@ static inline void iommu_device_unlink(struct device *dev, 
struct device *link)
 
 #endif /* CONFIG_IOMMU_API */
 
+/* IOMMU fwnode handling */
+static inline bool is_fwnode_iommu(struct fwnode_handle *fwnode)
+{
+   return fwnode && fwnode->type == FWNODE_IOMMU;
+}
+
+static inline struct fwnode_handle *iommu_alloc_fwnode(void)
+{
+   struct fwnode_handle *fwnode;
+
+   fwnode = kzalloc(sizeof(struct fwnode_handle), GFP_KERNEL);
+   fwnode->type = FWNODE_IOMMU;
+
+   return fwnode;
+}
+
+static inline void iommu_free_fwnode(struct fwnode_handle *fwnode)
+{
+   if (WARN_ON(!is_fwnode_iommu(fwnode)))
+   return;
+
+   kfree(fwnode);
+}
+
 #endif /* __LINUX_IOMMU_H */
-- 
2.10.0

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] iommu/arm-smmu: Disable interrupts whilst holding the cmdq lock

2016-09-09 Thread Jean-Philippe Brucker
Hi Will,

On 09/09/16 14:50, Will Deacon wrote:
> The cmdq lock is taken whenever we issue comments into the command queue,

s/comments/commands/

> which can occur in IRQ context (as a result if unmap) or in process

s/if/of/

> context (as a result of a threaded IRQ handler or device probe).
> 
> This can lead to a theoretical deadlock if the interrupt handler
> performing the unmap hits whilst the lock is taken, so explicitly use
> the {irqsave,irqrestore} spin_lock accessors for the cmdq lock.
> 
> Signed-off-by: Will Deacon 

Works for me and keeps lockdep quiet, so FWIW

Tested-by: Jean-Philippe Brucker 

> ---
>  drivers/iommu/arm-smmu-v3.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
> index c040e246bc59..5db6931c715c 100644
> --- a/drivers/iommu/arm-smmu-v3.c
> +++ b/drivers/iommu/arm-smmu-v3.c
> @@ -893,6 +893,7 @@ static void arm_smmu_cmdq_issue_cmd(struct 
> arm_smmu_device *smmu,
>   struct arm_smmu_cmdq_ent *ent)
>  {
>   u64 cmd[CMDQ_ENT_DWORDS];
> + unsigned long flags;
>   bool wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV);
>   struct arm_smmu_queue *q = &smmu->cmdq.q;
>  
> @@ -902,7 +903,7 @@ static void arm_smmu_cmdq_issue_cmd(struct 
> arm_smmu_device *smmu,
>   return;
>   }
>  
> - spin_lock(&smmu->cmdq.lock);
> + spin_lock_irqsave(&smmu->cmdq.lock, flags);
>   while (queue_insert_raw(q, cmd) == -ENOSPC) {
>   if (queue_poll_cons(q, false, wfe))
>   dev_err_ratelimited(smmu->dev, "CMDQ timeout\n");
> @@ -910,7 +911,7 @@ static void arm_smmu_cmdq_issue_cmd(struct 
> arm_smmu_device *smmu,
>  
>   if (ent->opcode == CMDQ_OP_CMD_SYNC && queue_poll_cons(q, true, wfe))
>   dev_err_ratelimited(smmu->dev, "CMD_SYNC timeout\n");
> - spin_unlock(&smmu->cmdq.lock);
> + spin_unlock_irqrestore(&smmu->cmdq.lock, flags);
>  }
>  
>  /* Context descriptor manipulation functions */
> 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH] iommu/arm-smmu: Disable interrupts whilst holding the cmdq lock

2016-09-09 Thread Will Deacon
The cmdq lock is taken whenever we issue comments into the command queue,
which can occur in IRQ context (as a result if unmap) or in process
context (as a result of a threaded IRQ handler or device probe).

This can lead to a theoretical deadlock if the interrupt handler
performing the unmap hits whilst the lock is taken, so explicitly use
the {irqsave,irqrestore} spin_lock accessors for the cmdq lock.

Signed-off-by: Will Deacon 
---
 drivers/iommu/arm-smmu-v3.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index c040e246bc59..5db6931c715c 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -893,6 +893,7 @@ static void arm_smmu_cmdq_issue_cmd(struct arm_smmu_device 
*smmu,
struct arm_smmu_cmdq_ent *ent)
 {
u64 cmd[CMDQ_ENT_DWORDS];
+   unsigned long flags;
bool wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV);
struct arm_smmu_queue *q = &smmu->cmdq.q;
 
@@ -902,7 +903,7 @@ static void arm_smmu_cmdq_issue_cmd(struct arm_smmu_device 
*smmu,
return;
}
 
-   spin_lock(&smmu->cmdq.lock);
+   spin_lock_irqsave(&smmu->cmdq.lock, flags);
while (queue_insert_raw(q, cmd) == -ENOSPC) {
if (queue_poll_cons(q, false, wfe))
dev_err_ratelimited(smmu->dev, "CMDQ timeout\n");
@@ -910,7 +911,7 @@ static void arm_smmu_cmdq_issue_cmd(struct arm_smmu_device 
*smmu,
 
if (ent->opcode == CMDQ_OP_CMD_SYNC && queue_poll_cons(q, true, wfe))
dev_err_ratelimited(smmu->dev, "CMD_SYNC timeout\n");
-   spin_unlock(&smmu->cmdq.lock);
+   spin_unlock_irqrestore(&smmu->cmdq.lock, flags);
 }
 
 /* Context descriptor manipulation functions */
-- 
2.1.4

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCH 4/8] of: dma: Split of_configure_dma() into mask and ops configuration

2016-09-09 Thread Sricharan
Hi Magnus,

>On Tue, Aug 9, 2016 at 7:49 AM, Sricharan R  wrote:
>> From: Laurent Pinchart 
>>
>> The of_configure_dma() function configures both the DMA masks and ops.
>> Moving DMA ops configuration to probe time would thus also delay
>> configuration of the DMA masks, which might not be safe. To avoid issues
>> split the configuration in two to allow keeping masks configuration at
>> device add time and move ops configuration to device probe time.
>
>Hi Sricharan, Laurent, everyone,
>
>I'm currently having a look at this series. Want to give it a spin
>with the IPMMU driver, however it takes a bit of time to wrap around
>my head on init ordering issues with both OF method and standard
>platform device setup on two different architectures...
>
>FWIW, here's some cosmetic feedback for this patch to begin with:
>
>In the patch title and commit message you probably want to do perform
>a s/of_configure_dma()/of_dma_configure()/g.
>
  Ya, that right.
 Thanks for having a look. I am going to post V2 shortly
  Infact on the next post, this split patch won't be there.

 Also, there is a bug in this series which missed before posting,
 https://patchwork.kernel.org/patch/9269913/


Regards,
 Sricharan
 

>> Signed-off-by: Laurent Pinchart 
>> ---
>>  drivers/of/device.c   | 48 
>> ++-
>>  drivers/of/platform.c |  6 --
>>  drivers/pci/probe.c   |  3 ++-
>>  include/linux/of_device.h | 11 +--
>>  4 files changed, 50 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/of/device.c b/drivers/of/device.c
>> index 1c843e2..e1fad50 100644
>> --- a/drivers/of/device.c
>> +++ b/drivers/of/device.c
>> @@ -71,7 +71,7 @@ int of_device_add(struct platform_device *ofdev)
>>  }
>>
>>  /**
>> - * of_dma_configure - Setup DMA configuration
>> + * of_dma_configure - Setup DMA masks and offset
>>   * @dev:   Device to apply DMA configuration
>>   * @np:Pointer to OF node having DMA configuration
>>   *
>
>The hunk above should be "of_dma_configure_masks" to make the
>documentation match the function name.
>
>> @@ -82,13 +82,11 @@ int of_device_add(struct platform_device *ofdev)
>>   * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
>>   * to fix up DMA configuration.
>>   */
>> -void of_dma_configure(struct device *dev, struct device_node *np)
>> +void of_dma_configure_masks(struct device *dev, struct device_node *np)
>>  {
>> -   u64 dma_addr, paddr, size;
>> -   int ret;
>> -   bool coherent;
>> +   u64 dma_addr, paddr, size, range_mask;
>> unsigned long offset;
>> -   const struct iommu_ops *iommu;
>> +   int ret;
>>
>> /*
>>  * Set default coherent_dma_mask to 32 bit.  Drivers are expected to
>
>Thanks,
>
>/ magnus
>
>___
>linux-arm-kernel mailing list
>linux-arm-ker...@lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: Stability connection problems in ath9k kernel 4.7

2016-09-09 Thread Joerg Roedel
Hi Valerio,

On Thu, Sep 08, 2016 at 09:07:56PM +0200, Valerio Passini wrote:
> I'm hoping having done it right and I can try your first suggestion, but I
> really cannot solve this problem by myself: sorry, I have no capabilities in
> programming in any known and unknown computer language. Surely, I can test all
> the patches you want and report the results but this is the best I can do. 
> Best
> regards

Can you please send me the full dmesg after boot? The Intel-IOMMU is not
enabled by default, so I want to check if it is either enabled by
kernel-config or kernel command-line.

Thanks,

Joerg


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu