Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] usb: dwc3-exynos fix unspecified suspend clk error handling
From: Shuah Khan @ 2017-01-10 14:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2e4a5e53-6603-13b8-0302-dc8093978013@osg.samsung.com>

On 01/10/2017 07:16 AM, Shuah Khan wrote:
> On 01/10/2017 05:05 AM, Bartlomiej Zolnierkiewicz wrote:
>>
>> Hi,
>>
>> On Monday, January 09, 2017 07:21:31 PM Shuah Khan wrote:
>>> Fix dwc3_exynos_probe() to call clk_prepare_enable() only when suspend
>>> clock is specified. Call clk_disable_unprepare() from remove and probe
>>> error path only when susp_clk has been set from remove and probe error
>>> paths.
>>
>> It is legal to call clk_prepare_enable() and clk_disable_unprepare()
>> for NULL clock.  Also your patch changes susp_clk handling while
>> leaves axius_clk handling (which also can be NULL) untouched.
>>
>> Do you actually see some runtime problem with the current code?
>>
>> If not then the patch should probably be dropped.
>>
>> Best regards,
>> --
>> Bartlomiej Zolnierkiewicz
>> Samsung R&D Institute Poland
>> Samsung Electronics
> 
> Hi Bartlomiej,
> 
> I am seeing the "no suspend clk specified" message in dmesg.
> After that it sets the exynos->susp_clk = NULL and starts
> calling clk_prepare_enable(exynos->susp_clk);
> 
> That can't be good. If you see the logic right above this
> one for exynos->clk, it returns error and fails the probe.
> This this case it doesn't, but tries to use null susp_clk.
> 
> I believe this patch is necessary.

Let me clarify this a bit further. Since we already know
susp_clk is null, with this patch we can avoid extra calls
to clk_prepare_enable() and clk_disable_unprepare().

One can say, it also adds extra checks, hence I will let you
decide one way or the other. :)

thanks,
-- Shuah

> 
> thanks,
> -- Shuah
> 
>>
>>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>>> ---
>>>  drivers/usb/dwc3/dwc3-exynos.c | 10 ++++++----
>>>  1 file changed, 6 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
>>> index e27899b..f97a3d7 100644
>>> --- a/drivers/usb/dwc3/dwc3-exynos.c
>>> +++ b/drivers/usb/dwc3/dwc3-exynos.c
>>> @@ -131,8 +131,8 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
>>>  	if (IS_ERR(exynos->susp_clk)) {
>>>  		dev_info(dev, "no suspend clk specified\n");
>>>  		exynos->susp_clk = NULL;
>>> -	}
>>> -	clk_prepare_enable(exynos->susp_clk);
>>> +	} else
>>> +		clk_prepare_enable(exynos->susp_clk);
>>>  
>>>  	if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) {
>>>  		exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
>>> @@ -196,7 +196,8 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
>>>  	regulator_disable(exynos->vdd33);
>>>  err2:
>>>  	clk_disable_unprepare(exynos->axius_clk);
>>> -	clk_disable_unprepare(exynos->susp_clk);
>>> +	if (exynos->susp_clk)
>>> +		clk_disable_unprepare(exynos->susp_clk);
>>>  	clk_disable_unprepare(exynos->clk);
>>>  	return ret;
>>>  }
>>> @@ -210,7 +211,8 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
>>>  	platform_device_unregister(exynos->usb3_phy);
>>>  
>>>  	clk_disable_unprepare(exynos->axius_clk);
>>> -	clk_disable_unprepare(exynos->susp_clk);
>>> +	if (exynos->susp_clk)
>>> +		clk_disable_unprepare(exynos->susp_clk);
>>>  	clk_disable_unprepare(exynos->clk);
>>>  
>>>  	regulator_disable(exynos->vdd33);
>>
> 

^ permalink raw reply

* [PATCH v4 7/9] arm64: cpufeature: Track user visible fields
From: Suzuki K Poulose @ 2017-01-10 14:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170110142427.GA23051@e104818-lin.cambridge.arm.com>

On 10/01/17 14:24, Catalin Marinas wrote:
> On Mon, Jan 09, 2017 at 05:28:30PM +0000, Suzuki K. Poulose wrote:
>> Changes since V3:
>>  - Mark ID_AA64ISAR0_EL1:RDM visible
> [...]
>>  static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
>> -	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64ISAR0_RDM_SHIFT, 4, 0),
>> -	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_ATOMICS_SHIFT, 4, 0),
>> -	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_CRC32_SHIFT, 4, 0),
>> -	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA2_SHIFT, 4, 0),
>> -	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA1_SHIFT, 4, 0),
>> -	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_AES_SHIFT, 4, 0),
>> +	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR0_RDM_SHIFT, 4, 0),
>
> As I said in an earlier reply, I'd like the RDM exposing to come
> together with a patch presenting the corresponding HWCAP bit. But it's
> fine by me if you add the HWCAP separately from this patch, in which
> case my ack still stands.

Catalin,

Yes, I have a separate patch for that.

Thanks
Suzuki

^ permalink raw reply

* [PATCH v4 7/9] arm64: cpufeature: Track user visible fields
From: Catalin Marinas @ 2017-01-10 14:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483982912-27215-8-git-send-email-suzuki.poulose@arm.com>

On Mon, Jan 09, 2017 at 05:28:30PM +0000, Suzuki K. Poulose wrote:
> Changes since V3:
>  - Mark ID_AA64ISAR0_EL1:RDM visible
[...]
>  static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
> -	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64ISAR0_RDM_SHIFT, 4, 0),
> -	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_ATOMICS_SHIFT, 4, 0),
> -	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_CRC32_SHIFT, 4, 0),
> -	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA2_SHIFT, 4, 0),
> -	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA1_SHIFT, 4, 0),
> -	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_AES_SHIFT, 4, 0),
> +	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR0_RDM_SHIFT, 4, 0),

As I said in an earlier reply, I'd like the RDM exposing to come
together with a patch presenting the corresponding HWCAP bit. But it's
fine by me if you add the HWCAP separately from this patch, in which
case my ack still stands.

-- 
Catalin

^ permalink raw reply

* [PATCH 2/3 v2] iio: adc: break out common code from SPMI VADC
From: jic23 at kernel.org @ 2017-01-10 14:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdZUk6UUN2ACXp0S1RW7k2M5t5X5N_0mJQeo_UTEa4H=9w@mail.gmail.com>

On 10.01.2017 08:54, Linus Walleij wrote:
> On Fri, Dec 30, 2016 at 8:01 PM, Jonathan Cameron <jic23@kernel.org> 
> wrote:
>> On 15/12/16 22:48, Linus Walleij wrote:
>>> The SPMI VADC and the earlier XOADC share a subset of
>>> common code, so to be able to use the same code in both
>>> drivers, we break out a separate file with the common code,
>>> prefix exported functions that are no longer static with
>>> qcom_* and bake an object qcom-vadc.o that contains both
>>> files: qcom-vadc-common.o and qcom-spmi-vadc.o.
>>> 
>>> Cc: linux-arm-kernel at lists.infradead.org
>>> Cc: linux-arm-msm at vger.kernel.org
>>> Cc: Ivan T. Ivanov <iivanov.xz@gmail.com>
>>> Cc: Andy Gross <andy.gross@linaro.org>
>>> Cc: Bjorn Andersson <bjorn.andersson@linaro.org>
>>> Cc: Stephen Boyd <sboyd@codeaurora.org>
>>> Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
>>> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
>> 
>> Looks superficially fine, but I'm guessing will need a respin
>> as we have a fair bit of new stuff (and a couple of fixes) going
>> through this driver at the moment.
>> 
>> All but the two fixes I posted a few mins ago are in my testing
>> branch and should go to Greg once I have confirmed testing on
>> those two fixes.
> 
> I looked at the git and "testing"
> contains a top commit named "guessing" fixing some 64bit
> artithmetic (which looks correct) in the driver, shall I simply
> rebase on top of that and hope for the best? :)
I'm an idiot and pushed out the wrong branch.  Will fix up when
I get home and push one with a sensible patch title!
(It'll be the same content though - feel free to Ack that if
you like ;)

Not my best half asleep patch writing ;)

Jonathan
> 
> Yours,
> Linus Walleij
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [RFC PATCH v4 5/5] ARM: dma-mapping: Remove traces of NOMMU code
From: Vladimir Murzin @ 2017-01-10 14:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484057925-23586-1-git-send-email-vladimir.murzin@arm.com>

DMA operations for NOMMU case have been just factored out into
separate compilation unit, so don't keep dead code.

Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
---
 arch/arm/mm/dma-mapping.c | 26 ++------------------------
 1 file changed, 2 insertions(+), 24 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index ab77100..d8a755b 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -344,8 +344,6 @@ static void __dma_free_buffer(struct page *page, size_t size)
 	}
 }
 
-#ifdef CONFIG_MMU
-
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
 				     pgprot_t prot, struct page **ret_page,
 				     const void *caller, bool want_vaddr,
@@ -646,22 +644,6 @@ static inline pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot)
 	return prot;
 }
 
-#define nommu() 0
-
-#else	/* !CONFIG_MMU */
-
-#define nommu() 1
-
-#define __get_dma_pgprot(attrs, prot)				__pgprot(0)
-#define __alloc_remap_buffer(dev, size, gfp, prot, ret, c, wv)	NULL
-#define __alloc_from_pool(size, ret_page)			NULL
-#define __alloc_from_contiguous(dev, size, prot, ret, c, wv, coherent_flag)	NULL
-#define __free_from_pool(cpu_addr, size)			do { } while (0)
-#define __free_from_contiguous(dev, page, cpu_addr, size, wv)	do { } while (0)
-#define __dma_free_remap(cpu_addr, size)			do { } while (0)
-
-#endif	/* CONFIG_MMU */
-
 static void *__alloc_simple_buffer(struct device *dev, size_t size, gfp_t gfp,
 				   struct page **ret_page)
 {
@@ -803,7 +785,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 
 	if (cma)
 		buf->allocator = &cma_allocator;
-	else if (nommu() || is_coherent)
+	else if (is_coherent)
 		buf->allocator = &simple_allocator;
 	else if (allowblock)
 		buf->allocator = &remap_allocator;
@@ -852,8 +834,7 @@ static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
 		 unsigned long attrs)
 {
-	int ret = -ENXIO;
-#ifdef CONFIG_MMU
+	int ret;
 	unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 	unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
 	unsigned long pfn = dma_to_pfn(dev, dma_addr);
@@ -868,7 +849,6 @@ static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 				      vma->vm_end - vma->vm_start,
 				      vma->vm_page_prot);
 	}
-#endif	/* CONFIG_MMU */
 
 	return ret;
 }
@@ -887,9 +867,7 @@ int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
 		 unsigned long attrs)
 {
-#ifdef CONFIG_MMU
 	vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
-#endif	/* CONFIG_MMU */
 	return __arm_dma_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
 }
 
-- 
2.0.0

^ permalink raw reply related

* [RFC PATCH v4 4/5] ARM: NOMMU: Set ARM_DMA_MEM_BUFFERABLE for M-class cpus
From: Vladimir Murzin @ 2017-01-10 14:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484057925-23586-1-git-send-email-vladimir.murzin@arm.com>

Now, we have dedicated non-cacheable region for consistent DMA
operations. However, that region can still be marked as bufferable by
MPU, so it'd be safer to have barriers by default.

Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
---
 arch/arm/mm/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 0b79f12..64a1465c 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -1029,7 +1029,7 @@ config ARM_L1_CACHE_SHIFT
 
 config ARM_DMA_MEM_BUFFERABLE
 	bool "Use non-cacheable memory for DMA" if (CPU_V6 || CPU_V6K) && !CPU_V7
-	default y if CPU_V6 || CPU_V6K || CPU_V7
+	default y if CPU_V6 || CPU_V6K || CPU_V7 || CPU_V7M
 	help
 	  Historically, the kernel has used strongly ordered mappings to
 	  provide DMA coherent memory.  With the advent of ARMv7, mapping
-- 
2.0.0

^ permalink raw reply related

* [RFC PATCH v4 3/5] ARM: NOMMU: Introduce dma operations for noMMU
From: Vladimir Murzin @ 2017-01-10 14:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484057925-23586-1-git-send-email-vladimir.murzin@arm.com>

R/M classes of cpus can have memory covered by MPU which in turn might
configure RAM as Normal i.e. bufferable and cacheable. It breaks
dma_alloc_coherent() and friends, since data can stuck in caches now
or be buffered.

This patch factors out DMA support for NOMMU configuration into
separate entity which provides dedicated dma_ops. We have to handle
there several cases:
- configurations with MMU/MPU setup
- configurations without MMU/MPU setup
- special case for M-class, since caches and MPU there are optional

In general we rely on default DMA area for coherent allocations or/and
per-device memory reserves suitable for coherent DMA, so if such
regions are set coherent allocations go from there.

In case MPU/MPU was not setup we fallback to normal page allocator for
DMA memory allocation.

In case we run M-class cpus, for configuration without cache support
(like Cortex-M3/M4) dma operations are forced to be coherent and wired
with dma-noop (such decision is made based on cacheid global
variable); however, if caches are detected there and no DMA coherent
region is given (either default or per-device), dma is disallowed even
MPU is not set - it is because M-class implement system memory map
which defines part of address space as Normal memory.

Reported-by: Alexandre Torgue <alexandre.torgue@st.com>
Reported-by: Andras Szemzo <sza@esh.hu>
Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
---
 arch/arm/include/asm/dma-mapping.h |   3 +-
 arch/arm/mm/Makefile               |   5 +-
 arch/arm/mm/dma-mapping-nommu.c    | 252 +++++++++++++++++++++++++++++++++++++
 3 files changed, 256 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/mm/dma-mapping-nommu.c

diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index bf02dbd..559faad 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -20,7 +20,8 @@ static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)
 {
 	if (dev && dev->archdata.dma_ops)
 		return dev->archdata.dma_ops;
-	return &arm_dma_ops;
+
+	return IS_ENABLED(CONFIG_MMU) ? &arm_dma_ops : &dma_noop_ops;
 }
 
 static inline struct dma_map_ops *get_dma_ops(struct device *dev)
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 2ac7988..5796357 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -2,9 +2,8 @@
 # Makefile for the linux arm-specific parts of the memory manager.
 #
 
-obj-y				:= dma-mapping.o extable.o fault.o init.o \
-				   iomap.o
-
+obj-y				:= extable.o fault.o init.o iomap.o
+obj-y				+= dma-mapping$(MMUEXT).o
 obj-$(CONFIG_MMU)		+= fault-armv.o flush.o idmap.o ioremap.o \
 				   mmap.o pgd.o mmu.o pageattr.o
 
diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c
new file mode 100644
index 0000000..76f00c9
--- /dev/null
+++ b/arch/arm/mm/dma-mapping-nommu.c
@@ -0,0 +1,252 @@
+/*
+ *  Based on linux/arch/arm/mm/dma-mapping.c
+ *
+ *  Copyright (C) 2000-2004 Russell King
+ *
+ * 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.
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+
+#include <asm/cachetype.h>
+#include <asm/cacheflush.h>
+#include <asm/outercache.h>
+#include <asm/cp15.h>
+
+#include "dma.h"
+
+/*
+ *  dma_noop_ops is used if
+ *   - MMU/MPU is off
+ *   - cpu is v7m w/o cache support
+ *   - device is coherent
+ *  otherwise arm_nommu_dma_ops is used.
+ *
+ *  arm_nommu_dma_ops rely on consistent DMA memory (please, refer to
+ *  [1] on how to declare such memory).
+ *
+ *  [1] Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
+ */
+
+static void *arm_nommu_dma_alloc(struct device *dev, size_t size,
+				 dma_addr_t *dma_handle, gfp_t gfp,
+				 unsigned long attrs)
+
+{
+	struct dma_map_ops *ops = &dma_noop_ops;
+
+	/*
+	 * We are here because:
+	 * - no consistent DMA region has been defined, so we can't
+	 *   continue.
+	 * - there is no space left in consistent DMA region, so we
+	 *   only can fallback to generic allocator if we are
+	 *   advertised that consistency is not required.
+	 */
+
+	if (attrs & DMA_ATTR_NON_CONSISTENT)
+		return ops->alloc(dev, size, dma_handle, gfp, attrs);
+
+	WARN_ON_ONCE(1);
+	return NULL;
+}
+
+static void arm_nommu_dma_free(struct device *dev, size_t size,
+			       void *cpu_addr, dma_addr_t dma_addr,
+			       unsigned long attrs)
+{
+	struct dma_map_ops *ops = &dma_noop_ops;
+
+	if (attrs & DMA_ATTR_NON_CONSISTENT)
+		ops->free(dev, size, cpu_addr, dma_addr, attrs);
+
+	WARN_ON_ONCE(1);
+	return;
+}
+
+static int arm_nommu_dma_mmap(struct device *dev, struct vm_area_struct *vma,
+			      void *cpu_addr, dma_addr_t dma_addr, size_t size,
+			      unsigned long attrs)
+{
+	struct dma_map_ops *ops = &dma_noop_ops;
+	int ret;
+
+	if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
+		return ret;
+
+	if (attrs & DMA_ATTR_NON_CONSISTENT)
+		return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
+
+	WARN_ON_ONCE(1);
+	return -ENXIO;
+}
+
+static void __dma_page_cpu_to_dev(phys_addr_t paddr, size_t size,
+				  enum dma_data_direction dir)
+{
+	dmac_map_area(__va(paddr), size, dir);
+
+	if (dir == DMA_FROM_DEVICE)
+		outer_inv_range(paddr, paddr + size);
+	else
+		outer_clean_range(paddr, paddr + size);
+}
+
+static void __dma_page_dev_to_cpu(phys_addr_t paddr, size_t size,
+				  enum dma_data_direction dir)
+{
+	if (dir != DMA_TO_DEVICE) {
+		outer_inv_range(paddr, paddr + size);
+		dmac_unmap_area(__va(paddr), size, dir);
+	}
+}
+
+static dma_addr_t arm_nommu_dma_map_page(struct device *dev, struct page *page,
+					 unsigned long offset, size_t size,
+					 enum dma_data_direction dir,
+					 unsigned long attrs)
+{
+	dma_addr_t handle = page_to_phys(page) + offset;
+
+	__dma_page_cpu_to_dev(handle, size, dir);
+
+	return handle;
+}
+
+static void arm_nommu_dma_unmap_page(struct device *dev, dma_addr_t handle,
+				     size_t size, enum dma_data_direction dir,
+				     unsigned long attrs)
+{
+	__dma_page_dev_to_cpu(handle, size, dir);
+}
+
+
+static int arm_nommu_dma_map_sg(struct device *dev, struct scatterlist *sgl,
+				int nents, enum dma_data_direction dir,
+				unsigned long attrs)
+{
+	int i;
+	struct scatterlist *sg;
+
+	for_each_sg(sgl, sg, nents, i) {
+		sg_dma_address(sg) = sg_phys(sg);
+		sg_dma_len(sg) = sg->length;
+		__dma_page_cpu_to_dev(sg_dma_address(sg), sg_dma_len(sg), dir);
+	}
+
+	return nents;
+}
+
+static void arm_nommu_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
+				   int nents, enum dma_data_direction dir,
+				   unsigned long attrs)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nents, i)
+		__dma_page_dev_to_cpu(sg_dma_address(sg), sg_dma_len(sg), dir);
+}
+
+static void arm_nommu_dma_sync_single_for_device(struct device *dev,
+		dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+	__dma_page_cpu_to_dev(handle, size, dir);
+}
+
+static void arm_nommu_dma_sync_single_for_cpu(struct device *dev,
+		dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+	__dma_page_cpu_to_dev(handle, size, dir);
+}
+
+static void arm_nommu_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
+					     int nents, enum dma_data_direction dir)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nents, i)
+		__dma_page_cpu_to_dev(sg_dma_address(sg), sg_dma_len(sg), dir);
+}
+
+static void arm_nommu_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
+					  int nents, enum dma_data_direction dir)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nents, i)
+		__dma_page_dev_to_cpu(sg_dma_address(sg), sg_dma_len(sg), dir);
+}
+
+struct dma_map_ops arm_nommu_dma_ops = {
+	.alloc			= arm_nommu_dma_alloc,
+	.free			= arm_nommu_dma_free,
+	.mmap			= arm_nommu_dma_mmap,
+	.map_page		= arm_nommu_dma_map_page,
+	.unmap_page		= arm_nommu_dma_unmap_page,
+	.map_sg			= arm_nommu_dma_map_sg,
+	.unmap_sg		= arm_nommu_dma_unmap_sg,
+	.sync_single_for_device	= arm_nommu_dma_sync_single_for_device,
+	.sync_single_for_cpu	= arm_nommu_dma_sync_single_for_cpu,
+	.sync_sg_for_device	= arm_nommu_dma_sync_sg_for_device,
+	.sync_sg_for_cpu	= arm_nommu_dma_sync_sg_for_cpu,
+};
+EXPORT_SYMBOL(arm_nommu_dma_ops);
+
+static struct dma_map_ops *arm_nommu_get_dma_map_ops(bool coherent)
+{
+	return coherent ? &dma_noop_ops : &arm_nommu_dma_ops;
+}
+
+void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
+			const struct iommu_ops *iommu, bool coherent)
+{
+	struct dma_map_ops *dma_ops;
+
+	if (IS_ENABLED(CONFIG_CPU_V7M)) {
+		/*
+		 * Cache support for v7m is optional, so can be treated as
+		 * coherent if no cache has been detected. Note that it is not
+		 * enough to check if MPU is in use or not since in absense of
+		 * MPU system memory map is used.
+		 */
+		dev->archdata.dma_coherent = (cacheid) ? coherent : true;
+	} else {
+		/*
+		 * Assume coherent DMA in case MMU/MPU has not been set up.
+		 */
+		dev->archdata.dma_coherent = (get_cr() & CR_M) ? coherent : true;
+	}
+
+	dma_ops = arm_nommu_get_dma_map_ops(dev->archdata.dma_coherent);
+
+	set_dma_ops(dev, dma_ops);
+}
+
+void arch_teardown_dma_ops(struct device *dev)
+{
+}
+
+int dma_supported(struct device *dev, u64 mask)
+{
+	return 1;
+}
+
+EXPORT_SYMBOL(dma_supported);
+
+#define PREALLOC_DMA_DEBUG_ENTRIES	4096
+
+static int __init dma_debug_do_init(void)
+{
+	dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+	return 0;
+}
+core_initcall(dma_debug_do_init);
-- 
2.0.0

^ permalink raw reply related

* [RFC PATCH v4 2/5] drivers: dma-coherent: Introduce default DMA pool
From: Vladimir Murzin @ 2017-01-10 14:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484057925-23586-1-git-send-email-vladimir.murzin@arm.com>

This patch introduces default coherent DMA pool similar to default CMA
area concept. To keep other users safe code kept under CONFIG_ARM.

Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Suggested-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
---
 .../bindings/reserved-memory/reserved-memory.txt   |  3 ++
 drivers/base/dma-coherent.c                        | 59 +++++++++++++++++++---
 2 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
index 3da0ebd..16291f2 100644
--- a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
+++ b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
@@ -68,6 +68,9 @@ Linux implementation note:
 - If a "linux,cma-default" property is present, then Linux will use the
   region for the default pool of the contiguous memory allocator.
 
+- If a "linux,dma-default" property is present, then Linux will use the
+  region for the default pool of the consistent DMA allocator.
+
 Device node references to reserved memory
 -----------------------------------------
 Regions in the /reserved-memory node may be referenced by other device
diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c
index 640a7e6..b52ba27 100644
--- a/drivers/base/dma-coherent.c
+++ b/drivers/base/dma-coherent.c
@@ -18,6 +18,15 @@ struct dma_coherent_mem {
 	spinlock_t	spinlock;
 };
 
+static struct dma_coherent_mem *dma_coherent_default_memory __ro_after_init;
+
+static inline struct dma_coherent_mem *dev_get_coherent_memory(struct device *dev)
+{
+	if (dev && dev->dma_mem)
+		return dev->dma_mem;
+	return dma_coherent_default_memory;
+}
+
 static bool dma_init_coherent_memory(
 	phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags,
 	struct dma_coherent_mem **mem)
@@ -83,6 +92,9 @@ static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
 static int dma_assign_coherent_memory(struct device *dev,
 				      struct dma_coherent_mem *mem)
 {
+	if (!dev)
+		return -ENODEV;
+
 	if (dev->dma_mem)
 		return -EBUSY;
 
@@ -161,15 +173,12 @@ EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
 int dma_alloc_from_coherent(struct device *dev, ssize_t size,
 				       dma_addr_t *dma_handle, void **ret)
 {
-	struct dma_coherent_mem *mem;
+	struct dma_coherent_mem *mem = dev_get_coherent_memory(dev);
 	int order = get_order(size);
 	unsigned long flags;
 	int pageno;
 	int dma_memory_map;
 
-	if (!dev)
-		return 0;
-	mem = dev->dma_mem;
 	if (!mem)
 		return 0;
 
@@ -223,7 +232,7 @@ EXPORT_SYMBOL(dma_alloc_from_coherent);
  */
 int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
 {
-	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+	struct dma_coherent_mem *mem = dev_get_coherent_memory(dev);
 
 	if (mem && vaddr >= mem->virt_base && vaddr <
 		   (mem->virt_base + (mem->size << PAGE_SHIFT))) {
@@ -257,7 +266,7 @@ EXPORT_SYMBOL(dma_release_from_coherent);
 int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
 			   void *vaddr, size_t size, int *ret)
 {
-	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+	struct dma_coherent_mem *mem = dev_get_coherent_memory(dev);
 
 	if (mem && vaddr >= mem->virt_base && vaddr + size <=
 		   (mem->virt_base + (mem->size << PAGE_SHIFT))) {
@@ -287,6 +296,8 @@ EXPORT_SYMBOL(dma_mmap_from_coherent);
 #include <linux/of_fdt.h>
 #include <linux/of_reserved_mem.h>
 
+static struct reserved_mem *dma_reserved_default_memory __initdata;
+
 static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
 {
 	struct dma_coherent_mem *mem = rmem->priv;
@@ -307,7 +318,8 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
 static void rmem_dma_device_release(struct reserved_mem *rmem,
 				    struct device *dev)
 {
-	dev->dma_mem = NULL;
+	if (dev)
+		dev->dma_mem = NULL;
 }
 
 static const struct reserved_mem_ops rmem_dma_ops = {
@@ -327,6 +339,12 @@ static int __init rmem_dma_setup(struct reserved_mem *rmem)
 		pr_err("Reserved memory: regions without no-map are not yet supported\n");
 		return -EINVAL;
 	}
+
+	if (of_get_flat_dt_prop(node, "linux,dma-default", NULL)) {
+		WARN(dma_reserved_default_memory,
+		     "Reserved memory: region for default DMA coherent area is redefined\n");
+		dma_reserved_default_memory = rmem;
+	}
 #endif
 
 	rmem->ops = &rmem_dma_ops;
@@ -334,5 +352,32 @@ static int __init rmem_dma_setup(struct reserved_mem *rmem)
 		&rmem->base, (unsigned long)rmem->size / SZ_1M);
 	return 0;
 }
+
+static int __init dma_init_reserved_memory(void)
+{
+	const struct reserved_mem_ops *ops;
+	int ret;
+
+	if (!dma_reserved_default_memory)
+		return -ENOMEM;
+
+	ops = dma_reserved_default_memory->ops;
+
+	/*
+	 * We rely on rmem_dma_device_init() does not propagate error of
+	 * dma_assign_coherent_memory() for "NULL" device.
+	 */
+	ret = ops->device_init(dma_reserved_default_memory, NULL);
+
+	if (!ret) {
+		dma_coherent_default_memory = dma_reserved_default_memory->priv;
+		pr_info("DMA: default coherent area is set\n");
+	}
+
+	return ret;
+}
+
+core_initcall(dma_init_reserved_memory);
+
 RESERVEDMEM_OF_DECLARE(dma, "shared-dma-pool", rmem_dma_setup);
 #endif
-- 
2.0.0

^ permalink raw reply related

* [RFC PATCH v4 1/5] dma: Add simple dma_noop_mmap
From: Vladimir Murzin @ 2017-01-10 14:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484057925-23586-1-git-send-email-vladimir.murzin@arm.com>

This patch adds a simple implementation of mmap to dma_noop_ops.

Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
---
 lib/dma-noop.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/lib/dma-noop.c b/lib/dma-noop.c
index 3d766e7..96638a1 100644
--- a/lib/dma-noop.c
+++ b/lib/dma-noop.c
@@ -64,6 +64,26 @@ static int dma_noop_supported(struct device *dev, u64 mask)
 	return 1;
 }
 
+static int dma_noop_mmap(struct device *dev, struct vm_area_struct *vma,
+			 void *cpu_addr, dma_addr_t dma_addr, size_t size,
+			 unsigned long attrs)
+{
+	unsigned long user_count = vma_pages(vma);
+	unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+	unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr));
+	unsigned long off = vma->vm_pgoff;
+	int ret = -ENXIO;
+
+	if (off < count && user_count <= (count - off)) {
+		ret = remap_pfn_range(vma, vma->vm_start,
+				      pfn + off,
+				      user_count << PAGE_SHIFT,
+				      vma->vm_page_prot);
+	}
+
+	return ret;
+}
+
 struct dma_map_ops dma_noop_ops = {
 	.alloc			= dma_noop_alloc,
 	.free			= dma_noop_free,
@@ -71,6 +91,7 @@ struct dma_map_ops dma_noop_ops = {
 	.map_sg			= dma_noop_map_sg,
 	.mapping_error		= dma_noop_mapping_error,
 	.dma_supported		= dma_noop_supported,
+	.mmap			= dma_noop_mmap,
 };
 
 EXPORT_SYMBOL(dma_noop_ops);
-- 
2.0.0

^ permalink raw reply related

* [RFC PATCH v4 0/5] ARM: Fix dma_alloc_coherent() and friends for NOMMU
From: Vladimir Murzin @ 2017-01-10 14:18 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

It seem that addition of cache support for M-class cpus uncovered
latent bug in DMA usage. NOMMU memory model has been treated as being
always consistent; however, for R/M classes of cpu memory can be
covered by MPU which in turn might configure RAM as Normal
i.e. bufferable and cacheable. It breaks dma_alloc_coherent() and
friends, since data can stuck in caches now or be buffered.

This patch set is trying to address the issue by providing region of
memory suitable for consistent DMA operations. It is supposed that
such region is marked by MPU as non-cacheable. Robin suggested to
advertise such memory as reserved shared-dma-pool, rather then using
homebrew command line option, and extend dma-coherent to provide
default DMA area in the similar way as it is done for CMA (PATCH
2/5). It allows us to offload all bookkeeping on generic coherent DMA
framework, and it is seems that it might be reused by other
architectures like c6x and blackfin.

Dedicated DMA region is required for cases other than:
 - MMU/MPU is off
 - cpu is v7m w/o cache support
 - device is coherent

In case one of the above conditions is true dma operations are forced
to be coherent and wired with dma_noop_ops.

To make life easier NOMMU dma operations are kept in separate
compilation unit.

Since the issue was reported in the same time as Benjamin sent his
patch [1] to allow mmap for NOMMU, his case is also addressed in this
series (PATCH 1/5 and PATCH 3/5).

Thanks!

[1] http://www.armlinux.org.uk/developer/patches/viewpatch.php?id=8633/1

Vladimir Murzin (5):
  dma: Add simple dma_noop_mmap
  drivers: dma-coherent: Introduce default DMA pool
  ARM: NOMMU: Introduce dma operations for noMMU
  ARM: NOMMU: Set ARM_DMA_MEM_BUFFERABLE for M-class cpus
  ARM: dma-mapping: Remove traces of NOMMU code

 .../bindings/reserved-memory/reserved-memory.txt   |   3 +
 arch/arm/include/asm/dma-mapping.h                 |   3 +-
 arch/arm/mm/Kconfig                                |   2 +-
 arch/arm/mm/Makefile                               |   5 +-
 arch/arm/mm/dma-mapping-nommu.c                    | 252 +++++++++++++++++++++
 arch/arm/mm/dma-mapping.c                          |  26 +--
 drivers/base/dma-coherent.c                        |  59 ++++-
 lib/dma-noop.c                                     |  21 ++
 8 files changed, 335 insertions(+), 36 deletions(-)
 create mode 100644 arch/arm/mm/dma-mapping-nommu.c

-- 
2.0.0

^ permalink raw reply

* [PATCH v7 19/19] iommu/arm-smmu: Do not advertise IOMMU_CAP_INTR_REMAP anymore
From: Will Deacon @ 2017-01-10 14:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483969570-3154-20-git-send-email-eric.auger@redhat.com>

On Mon, Jan 09, 2017 at 01:46:10PM +0000, Eric Auger wrote:
> IOMMU_CAP_INTR_REMAP has been advertised in arm-smmu(-v3) although
> on ARM this property is not attached to the IOMMU but rather is
> implemented in the MSI controller (GICv3 ITS).
> 
> Now vfio_iommu_type1 checks MSI remapping capability at MSI controller
> level, let's correct this.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> ---
>  drivers/iommu/arm-smmu-v3.c | 2 --
>  drivers/iommu/arm-smmu.c    | 2 --
>  2 files changed, 4 deletions(-)

Dependent on the previous two VFIO patches:

Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply

* [PATCH v7 12/19] iommu/arm-smmu-v3: Implement reserved region get/put callbacks
From: Will Deacon @ 2017-01-10 14:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483969570-3154-13-git-send-email-eric.auger@redhat.com>

On Mon, Jan 09, 2017 at 01:46:03PM +0000, Eric Auger wrote:
> iommu/arm-smmu: Implement reserved region get/put callbacks
> 
> The get() populates the list with the MSI IOVA reserved window.
> 
> At the moment an arbitray MSI IOVA window is set at 0x8000000
> of size 1MB. This will allow to report those info in iommu-group
> sysfs.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 
> v4: creation
> ---
>  drivers/iommu/arm-smmu-v3.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)

Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply

* [PATCH v2] arm64: do not set dma masks that device connection can't handle
From: Robin Murphy @ 2017-01-10 14:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <6116278.nQQUSuo3l4@wuerfel>

On 10/01/17 13:42, Arnd Bergmann wrote:
> On Tuesday, January 10, 2017 1:25:12 PM CET Robin Murphy wrote:
>> On 10/01/17 12:47, Nikita Yushchenko wrote:
>>>> The point here is that an IOMMU doesn't solve your issue, and the
>>>> IOMMU-backed DMA ops need the same treatment. In light of that, it really
>>>> feels to me like the DMA masks should be restricted in of_dma_configure
>>>> so that the parent mask is taken into account there, rather than hook
>>>> into each set of DMA ops to intercept set_dma_mask. We'd still need to
>>>> do something to stop dma_set_mask widening the mask if it was restricted
>>>> by of_dma_configure, but I think Robin (cc'd) was playing with that.
>>>
>>> What issue "IOMMU doesn't solve"?
>>>
>>> Issue I'm trying to address is - inconsistency within swiotlb
>>> dma_map_ops, where (1) any wide mask is silently accepted, but (2) then
>>> mask is used to decide if bounce buffers are needed or not. This
>>> inconsistency causes NVMe+R-Car cobmo not working (and breaking memory
>>> instead).
>>
>> The fundamental underlying problem is the "any wide mask is silently
>> accepted" part, and that applies equally to IOMMU ops as well.
> 
> It's a much rarer problem for the IOMMU case though, because it only
> impacts devices that are restricted to addressing of less than 32-bits.
> 
> If you have an IOMMU enabled, the dma-mapping interface does not care
> if the device can do wider than 32 bit addressing, as it will never
> hand out IOVAs above 0xffffffff.

I can assure you that it will - we constrain allocations to the
intersection of the IOMMU domain aperture (normally the IOMMU's physical
input address width) and the given device's DMA mask. If both of those
are >32 bits then >32-bit IOVAs will fall out. For the arm64/common
implementation I have prototyped a copy of the x86 optimisation which
always first tries to get 32-bit IOVAs for PCI devices, but even then it
can start returning higher addresses if the 32-bit space fills up.

>>> I just can't think out what similar issue iommu can have.
>>> Do you mean that in iommu case, mask also must not be set to whatever
>>> wider than initial value? Why? What is the use of mask in iommu case? Is
>>> there any real case when iommu can't address all memory existing in the
>>> system?
>>
>> There's a very subtle misunderstanding there - the DMA mask does not
>> describe the memory a device can address, it describes the range of
>> addresses the device is capable of generating. Yes, in the non-IOMMU
>> case they are equivalent, but once you put an IOMMU in between, the
>> problem is merely shifted from "what range of physical addresses can
>> this device access" to "what range of IOVAs is valid to give to this
>> device" - the fact that those IOVAs can map to any underlying physical
>> address only obviates the need for any bouncing at the memory end; it
>> doesn't remove the fact that the device has a hardware addressing
>> limitation which needs to be accommodated.
>>
>> The thread Will linked to describes that equivalent version of your
>> problem - the IOMMU gives the device 48-bit addresses which get
>> erroneously truncated because it doesn't know that only 42 bits are
>> actually wired up. That situation still requires the device's DMA mask
>> to correctly describe its addressing capability just as yours does.
> 
> That problem should only impact virtual machines which have a guest
> bus address space covering more than 42 bits of physical RAM, whereas
> the problem we have with swiotlb is for the dma-mapping interface.

As above, it impacts DMA API use for anything whose addressing
capability is narrower than the IOMMU's reported input size and whose
driver is able to blindly set a too-big DMA mask. It just happens to be
the case that the stars line up on most systems, and for 32-bit devices
who keep the default DMA mask.

I actually have a third variation of this problem involving a PCI root
complex which *could* drive full-width (40-bit) addresses, but won't,
due to the way its PCI<->AXI interface is programmed. That would require
even more complicated dma-ranges handling to describe the windows of
valid physical addresses which it *will* pass, so I'm not pressing the
issue - let's just get the basic DMA mask case fixed first.

>>> With this direction, semantics of dma mask becomes even more
>>> questionable. I'd say dma_mask is candidate for removal (or to move to
>>> swiotlb's or iommu's local area)
>>
>> We still need a way for drivers to communicate a device's probed
>> addressing capability to SWIOTLB, so there's always going to have to be
>> *some* sort of public interface. Personally, the change in semantics I'd
>> like to see is to make dma_set_mask() only fail if DMA is entirely
>> disallowed - in the normal case it would always succeed, but the DMA API
>> implementation would be permitted to set a smaller mask than requested
>> (this is effectively what the x86 IOMMU ops do already).
> 
> With swiotlb enabled, it only needs to fail if the mask does not contain
> the swiotlb bounce buffer area, either because the start of RAM is outside
> of the mask, or the bounce area has been allocated at the end of ZONE_DMA
> and the mask is smaller than ZONE_DMA.

Agreed, I'd managed to overlook that specific case, but I'd be inclined
to consider "impossible" a subset of "disallowed" still :)

Robin.

^ permalink raw reply

* [PATCH v7 11/19] iommu/arm-smmu: Implement reserved region get/put callbacks
From: Will Deacon @ 2017-01-10 14:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483969570-3154-12-git-send-email-eric.auger@redhat.com>

On Mon, Jan 09, 2017 at 01:46:02PM +0000, Eric Auger wrote:
> The get() populates the list with the MSI IOVA reserved window.
> 
> At the moment an arbitray MSI IOVA window is set at 0x8000000
> of size 1MB. This will allow to report those info in iommu-group
> sysfs.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 
> v3 -> v4:
> - do not handle PCI host bridge windows anymore
> - encode prot
> 
> RFC v2 -> v3:
> - use existing get/put_resv_regions
> 
> RFC v1 -> v2:
> - use defines for MSI IOVA base and length
> ---
>  drivers/iommu/arm-smmu.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)

Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply

* [PATCH] usb: dwc3-exynos fix unspecified suspend clk error handling
From: Shuah Khan @ 2017-01-10 14:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1641038.u0riMiuGF5@amdc3058>

On 01/10/2017 05:05 AM, Bartlomiej Zolnierkiewicz wrote:
> 
> Hi,
> 
> On Monday, January 09, 2017 07:21:31 PM Shuah Khan wrote:
>> Fix dwc3_exynos_probe() to call clk_prepare_enable() only when suspend
>> clock is specified. Call clk_disable_unprepare() from remove and probe
>> error path only when susp_clk has been set from remove and probe error
>> paths.
> 
> It is legal to call clk_prepare_enable() and clk_disable_unprepare()
> for NULL clock.  Also your patch changes susp_clk handling while
> leaves axius_clk handling (which also can be NULL) untouched.
> 
> Do you actually see some runtime problem with the current code?
> 
> If not then the patch should probably be dropped.
> 
> Best regards,
> --
> Bartlomiej Zolnierkiewicz
> Samsung R&D Institute Poland
> Samsung Electronics

Hi Bartlomiej,

I am seeing the "no suspend clk specified" message in dmesg.
After that it sets the exynos->susp_clk = NULL and starts
calling clk_prepare_enable(exynos->susp_clk);

That can't be good. If you see the logic right above this
one for exynos->clk, it returns error and fails the probe.
This this case it doesn't, but tries to use null susp_clk.

I believe this patch is necessary.

thanks,
-- Shuah

> 
>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>> ---
>>  drivers/usb/dwc3/dwc3-exynos.c | 10 ++++++----
>>  1 file changed, 6 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
>> index e27899b..f97a3d7 100644
>> --- a/drivers/usb/dwc3/dwc3-exynos.c
>> +++ b/drivers/usb/dwc3/dwc3-exynos.c
>> @@ -131,8 +131,8 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
>>  	if (IS_ERR(exynos->susp_clk)) {
>>  		dev_info(dev, "no suspend clk specified\n");
>>  		exynos->susp_clk = NULL;
>> -	}
>> -	clk_prepare_enable(exynos->susp_clk);
>> +	} else
>> +		clk_prepare_enable(exynos->susp_clk);
>>  
>>  	if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) {
>>  		exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
>> @@ -196,7 +196,8 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
>>  	regulator_disable(exynos->vdd33);
>>  err2:
>>  	clk_disable_unprepare(exynos->axius_clk);
>> -	clk_disable_unprepare(exynos->susp_clk);
>> +	if (exynos->susp_clk)
>> +		clk_disable_unprepare(exynos->susp_clk);
>>  	clk_disable_unprepare(exynos->clk);
>>  	return ret;
>>  }
>> @@ -210,7 +211,8 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
>>  	platform_device_unregister(exynos->usb3_phy);
>>  
>>  	clk_disable_unprepare(exynos->axius_clk);
>> -	clk_disable_unprepare(exynos->susp_clk);
>> +	if (exynos->susp_clk)
>> +		clk_disable_unprepare(exynos->susp_clk);
>>  	clk_disable_unprepare(exynos->clk);
>>  
>>  	regulator_disable(exynos->vdd33);
> 

^ permalink raw reply

* [PATCH v7 00/19] KVM PCIe/MSI passthrough on ARM/ARM64 and IOVA reserved regions
From: Will Deacon @ 2017-01-10 14:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170110140924.GC1318@8bytes.org>

On Tue, Jan 10, 2017 at 03:09:24PM +0100, Joerg Roedel wrote:
> On Mon, Jan 09, 2017 at 01:45:51PM +0000, Eric Auger wrote:
> > Eric Auger (17):
> >   iommu: Rename iommu_dm_regions into iommu_resv_regions
> >   iommu: Add a new type field in iommu_resv_region
> >   iommu: iommu_alloc_resv_region
> >   iommu: Only map direct mapped regions
> >   iommu: iommu_get_group_resv_regions
> >   iommu: Implement reserved_regions iommu-group sysfs file
> >   iommu/vt-d: Implement reserved region get/put callbacks
> >   iommu/amd: Declare MSI and HT regions as reserved IOVA regions
> >   iommu/arm-smmu: Implement reserved region get/put callbacks
> >   iommu/arm-smmu-v3: Implement reserved region get/put callbacks
> 
> IOMMU patches look good, what is the plan to merge this? I'd like to
> take the IOMMU patches and can provide a branch for someone else to base
> the rest on.

I'm perfectly happy with this going through you. In fact, I suspect you
could take the whole series once Marc is happy with the few remaining
irq domain niggles (which are really minor at this point).

That just leaves the VFIO bits -- Alex, are you happy with those now?
If not, we can hold off on the last three patches for the time being.

Will

^ permalink raw reply

* [PATCH V2 0/2] kexec-tools: arm64: Enable D-cache in purgatory
From: James Morse @ 2017-01-10 14:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <e44d0ede-a116-f0cf-15db-07bf75856f07@redhat.com>

Hi Pratyush,

On 06/01/17 03:31, Pratyush Anand wrote:
> Any feedback/review comment on it?

I started going through this last week, I hope to get back to it later this
week. (I also need to learn/remember how some of the kexec-tools stuff works).


Thanks,

James

^ permalink raw reply

* [PATCH] virtio_mmio: Set DMA masks appropriately
From: Arnd Bergmann @ 2017-01-10 14:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <c62753e7-2530-6e23-5a6c-77cf8bc92860@arm.com>

On Tuesday, January 10, 2017 1:44:37 PM CET Robin Murphy wrote:
> On 10/01/17 13:15, Arnd Bergmann wrote:
> > On Tuesday, January 10, 2017 12:26:01 PM CET Robin Murphy wrote:
> >> @@ -548,6 +550,14 @@ static int virtio_mmio_probe(struct platform_device *pdev)
> >>         if (vm_dev->version == 1)
> >>                 writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
> >>  
> >> +       rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
> >> +       if (rc)
> >> +               rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
> > 
> > You don't seem to do anything different when 64-bit DMA is unsupported.
> > How do you prevent the use of kernel buffers that are above the first 4G
> > here?
> 
> That's the token "give up and rely on SWIOTLB/IOMMU" point, which as we
> already know won't necessarily work very well (because it's already the
> situation without this patch), but is still arguably better than
> nothing. As I've just replied elsewhere, I personally hate this idiom,
> but it's the done thing given the current DMA mask API.

Ah, I think I understand now. This is actually unrelated to SWIOTLB, which
should always succeed, but it is used on some architectures (x86, and
sparc in particular) to control whether the iommu is allowed to hand
out IOVA above 32-bit. Sorry for assuming in my earlier mail that all
IOMMUs only do 32-bit VA addressing in the dma-mapping API.

The related case on PowerPC is that DMA_BIT_MASK(64) has a special
meaning of bypassing the IOMMU entirely to optimize for performance.
Again that should not fail, but it will switch the dma_map_ops between
iommu and direct, using the IOMMU only when the device can't address
the entire space.

> >> +       else if (vm_dev->version == 1)
> >> +               dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32 + PAGE_SHIFT));
> > 
> > Why is this limitation only for the coherent mask?
> 
> AIUI, the "32-bit pointers to pages" limitation of legacy virtio only
> applies to the location of the vring itself, which is allocated via
> dma_alloc_coherent - the descriptors themselves hold full 64-bit
> addresses pointing at the actual data, which is mapped using streaming
> DMA. It relies on the API guarantee that if we've managed to set a
> 64-bit streaming mask, then setting a smaller coherent mask cannot fail
> (DMA-API-HOWTO.txt:257)
> 
> This is merely an amalgamation of the logic already in place for
> virtio-pci, I just skimped on duplicating all the rationale (I know
> there's a mail thread somewhere I could probably dig up).

Ok, got it.

	Arnd

^ permalink raw reply

* [PATCH v7 00/19] KVM PCIe/MSI passthrough on ARM/ARM64 and IOVA reserved regions
From: Joerg Roedel @ 2017-01-10 14:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483969570-3154-1-git-send-email-eric.auger@redhat.com>

On Mon, Jan 09, 2017 at 01:45:51PM +0000, Eric Auger wrote:
> Eric Auger (17):
>   iommu: Rename iommu_dm_regions into iommu_resv_regions
>   iommu: Add a new type field in iommu_resv_region
>   iommu: iommu_alloc_resv_region
>   iommu: Only map direct mapped regions
>   iommu: iommu_get_group_resv_regions
>   iommu: Implement reserved_regions iommu-group sysfs file
>   iommu/vt-d: Implement reserved region get/put callbacks
>   iommu/amd: Declare MSI and HT regions as reserved IOVA regions
>   iommu/arm-smmu: Implement reserved region get/put callbacks
>   iommu/arm-smmu-v3: Implement reserved region get/put callbacks

IOMMU patches look good, what is the plan to merge this? I'd like to
take the IOMMU patches and can provide a branch for someone else to base
the rest on.


	Joerg

^ permalink raw reply

* [PATCH 2/5] drivers: mmc: sunxi: limit A64 MMC2 to 8K DMA buffer
From: Maxime Ripard @ 2017-01-10 14:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87b26848-4f86-f2d2-3f82-db0937c572e2@arm.com>

On Thu, Jan 05, 2017 at 11:33:28PM +0000, Andr? Przywara wrote:
> On 05/01/17 17:57, Maxime Ripard wrote:
> > Hi Rob,
> > 
> > On Wed, Jan 04, 2017 at 08:07:50AM -0600, Rob Herring wrote:
> >> On Mon, Jan 02, 2017 at 11:03:43PM +0000, Andre Przywara wrote:
> >>> From: Maxime Ripard <maxime.ripard@free-electrons.com>
> >>>
> >>> Unlike the A64 user manual reports, the third MMC controller on the
> >>> A64 (and the only one capable of 8-bit HS400 eMMC transfers) has a
> >>> DMA buffer size limit of 8KB (much like the very old Allwinner SoCs).
> >>> This does not affect the other two controllers, so introduce a new
> >>> DT compatible string to let the driver use different settings for that
> >>> particular device. This will also help to enable the high-speed transfer
> >>> modes of that controller later.
> >>>
> >>> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> >>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> >>> ---
> >>>  Documentation/devicetree/bindings/mmc/sunxi-mmc.txt | 1 +
> >>>  drivers/mmc/host/sunxi-mmc.c                        | 7 +++++++
> >>>  2 files changed, 8 insertions(+)
> >>
> >> Acked-by: Rob Herring <robh@kernel.org>
> > 
> > Some kind of a digression on this: we have three MMC controllers on
> > this SoC. Like this patch shows, the third one is clearly different,
> > and supports both more modes, a wider bus, and specific quirks. We
> > need a new compatible for this one, everything's perfect.
> > 
> > However, the other two are mostly the same, but seems to need
> > different tuning parameters to get more performances out of the
> > controller (but this is unclear yet). How do we usually deal with
> > that?
> 
> I guess you wanted to hear Rob's opinion ;-), but "get more performance"
> sounds like we add one (or more) properties to tune those values.
> If I get this right, it works with default values, but is sub-optimal?

That would be my understanding too, at least, it works in a decent way
without fiddling with those parameters.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170110/89d2fcdd/attachment.sig>

^ permalink raw reply

* [RFC PATCH v3 0/5] ARM: Fix dma_alloc_coherent() and friends for NOMMU
From: Vladimir Murzin @ 2017-01-10 14:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CA+M3ks5+e=gJsC+XGT7SDXZ=DROAs4Yk4jyKpOwT02PUCoLq_A@mail.gmail.com>

On 10/01/17 13:13, Benjamin Gaignard wrote:
> 2017-01-09 14:47 GMT+01:00 Vladimir Murzin <vladimir.murzin@arm.com>:
>> Hi,
>>
>> It seem that addition of cache support for M-class cpus uncovered
>> latent bug in DMA usage. NOMMU memory model has been treated as being
>> always consistent; however, for R/M classes of cpu memory can be
>> covered by MPU which in turn might configure RAM as Normal
>> i.e. bufferable and cacheable. It breaks dma_alloc_coherent() and
>> friends, since data can stuck in caches now or be buffered.
>>
>> This patch set is trying to address the issue by providing region of
>> memory suitable for consistent DMA operations. It is supposed that
>> such region is marked by MPU as non-cacheable. Robin suggested to
>> advertise such memory as reserved shared-dma-pool, rather then using
>> homebrew command line option, and extend dma-coherent to provide
>> default DMA area in the similar way as it is done for CMA (PATCH
>> 2/5). It allows us to offload all bookkeeping on generic coherent DMA
>> framework, and it is seems that it might be reused by other
>> architectures like c6x and blackfin.
>>
>> Dedicated DMA region is required for cases other than:
>>  - MMU/MPU is off
>>  - cpu is v7m w/o cache support
>>  - device is coherent
>>
>> In case one of the above conditions is true dma operations are forced
>> to be coherent and wired with dma_noop_ops.
>>
>> To make life easier NOMMU dma operations are kept in separate
>> compilation unit.
>>
>> Since the issue was reported in the same time as Benjamin sent his
>> patch [1] to allow mmap for NOMMU, his case is also addressed in this
>> series (PATCH 1/5 and PATCH 3/5).
>>
>> @Benjamin I've tested that mmap is working with amba-clcd and following
>> hack on top:
>>
>> diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
>> index 76c1ad9..64465c9 100644
>> --- a/drivers/video/fbdev/core/fbmem.c
>> +++ b/drivers/video/fbdev/core/fbmem.c
>> @@ -1492,6 +1492,24 @@ __releases(&info->lock)
>>         return 0;
>>  }
>>
>> +static unsigned fb_capabilities(struct file *file)
>> +{
>> +       return NOMMU_MAP_DIRECT | NOMMU_MAP_READ | NOMMU_MAP_WRITE;
>> +}
>> +
>> +static unsigned long get_fb_unmapped_area(struct file *filp,
>> +                                  unsigned long addr, unsigned long len,
>> +                                  unsigned long pgoff, unsigned long flags)
>> +{
>> +       struct fb_info * const info = filp->private_data;
>> +       unsigned long fb_size = PAGE_ALIGN(info->fix.smem_len);
>> +
>> +       if (pgoff > fb_size || len > fb_size - pgoff)
>> +               return -EINVAL;
>> +
>> +       return (unsigned long)info->screen_base + pgoff;
>> +}
>> +
>>  static const struct file_operations fb_fops = {
>>         .owner =        THIS_MODULE,
>>         .read =         fb_read,
>> @@ -1503,13 +1521,12 @@ static const struct file_operations fb_fops = {
>>         .mmap =         fb_mmap,
>>         .open =         fb_open,
>>         .release =      fb_release,
>> -#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
>>         .get_unmapped_area = get_fb_unmapped_area,
>> -#endif
>>  #ifdef CONFIG_FB_DEFERRED_IO
>>         .fsync =        fb_deferred_io_fsync,
>>  #endif
>>         .llseek =       default_llseek,
>> +       .mmap_capabilities = fb_capabilities,
>>  };
>>
>>  struct class *fb_class;
>>
>> I can see that fb-test-app updates display and addresses returnend with
>> dma_alloc_cohernet() and mmap() are the same.
> 
> I have push get_fb_unmapped_area() function in fbmem last week:
> https://cgit.freedesktop.org/drm/drm-misc/commit/?id=82f42e4cc164ed486c9e2b1b74e65b176830d947
> and to the same in drm/kms part:
> https://cgit.freedesktop.org/drm/drm-misc/commit/?id=62a0d98a188cc4ebd8ea54b37d274ec20465e464
> all this work without need to change mmap_capabilities.
> 
> Other noMMU architectures don't need to change mmap_capabilities
> function to make fbmem works.
> I would like to understand how they do before push for this new function.
> It sound like it is an ARM Cortex M specific needs with your new implementation.
> 
> If we can't avoid using mmap_capabilities we will have to put it (at
> least) in fbmem, drm/kms and v4l2.

I've just tried with your fbmem patch only and it still working, display is
updated with what fb-test-app draws. Anyway, my point was that mmap
implementation introduced with these patches works for me and it'd be nice to
know if it works for you as well ;)

Meanwhile, Andras pointed out that fix from v2->v3 was missed, so I'm
resubmitting v4 shortly.

Cheers
Vladimir

> 
> Benjamin
> 
>> Thanks!
>>
>> [1] http://www.armlinux.org.uk/developer/patches/viewpatch.php?id=8633/1
>>
>> Vladimir Murzin (5):
>>   dma: Add simple dma_noop_mmap
>>   drivers: dma-coherent: Introduce default DMA pool
>>   ARM: NOMMU: Introduce dma operations for noMMU
>>   ARM: NOMMU: Set ARM_DMA_MEM_BUFFERABLE for M-class cpus
>>   ARM: dma-mapping: Remove traces of NOMMU code
>>
>>  .../bindings/reserved-memory/reserved-memory.txt   |   3 +
>>  arch/arm/include/asm/dma-mapping.h                 |   3 +-
>>  arch/arm/mm/Kconfig                                |   2 +-
>>  arch/arm/mm/Makefile                               |   5 +-
>>  arch/arm/mm/dma-mapping-nommu.c                    | 252 +++++++++++++++++++++
>>  arch/arm/mm/dma-mapping.c                          |  26 +--
>>  drivers/base/dma-coherent.c                        |  59 ++++-
>>  lib/dma-noop.c                                     |  21 ++
>>  8 files changed, 335 insertions(+), 36 deletions(-)
>>  create mode 100644 arch/arm/mm/dma-mapping-nommu.c
>>
>> --
>> 2.0.0
>>
> 
> 
> 

^ permalink raw reply

* [PATCH v2] arm64: do not set dma masks that device connection can't handle
From: Nikita Yushchenko @ 2017-01-10 14:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <11daacde-5399-039f-80a3-01d7bd13e9e8@arm.com>

>> What issue "IOMMU doesn't solve"?
>>
>> Issue I'm trying to address is - inconsistency within swiotlb
>> dma_map_ops, where (1) any wide mask is silently accepted, but (2) then
>> mask is used to decide if bounce buffers are needed or not. This
>> inconsistency causes NVMe+R-Car cobmo not working (and breaking memory
>> instead).
> 
> The fundamental underlying problem is the "any wide mask is silently
> accepted" part, and that applies equally to IOMMU ops as well.

Is just posted version better?

It should cover iommu case as well.

Nikita

^ permalink raw reply

* [PATCH] arm64: avoid increasing DMA masks above what hardware supports
From: Nikita Yushchenko @ 2017-01-10 14:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <11daacde-5399-039f-80a3-01d7bd13e9e8@arm.com>

There are cases when device supports wide DMA addresses wider than
device's connection supports.

In this case driver sets DMA mask based on knowledge of device
capabilities. That must succeed to allow drivers to initialize.

However, swiotlb or iommu still need knowledge about actual device
capabilities. To avoid breakage, actual mask must not be set wider than
device connection allows.

Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Robin Murphy <robin.murphy@arm.com>
CC: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/Kconfig                   |  3 +++
 arch/arm64/include/asm/device.h      |  1 +
 arch/arm64/include/asm/dma-mapping.h |  3 +++
 arch/arm64/mm/dma-mapping.c          | 43 ++++++++++++++++++++++++++++++++++++
 4 files changed, 50 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 1117421..afb2c08 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -216,6 +216,9 @@ config NEED_DMA_MAP_STATE
 config NEED_SG_DMA_LENGTH
 	def_bool y
 
+config ARCH_HAS_DMA_SET_COHERENT_MASK
+	def_bool y
+
 config SMP
 	def_bool y
 
diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h
index 243ef25..a57e7bb 100644
--- a/arch/arm64/include/asm/device.h
+++ b/arch/arm64/include/asm/device.h
@@ -22,6 +22,7 @@ struct dev_archdata {
 	void *iommu;			/* private IOMMU data */
 #endif
 	bool dma_coherent;
+	u64 parent_dma_mask;
 };
 
 struct pdev_archdata {
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index ccea82c..eab36d2 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -51,6 +51,9 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
 			const struct iommu_ops *iommu, bool coherent);
 #define arch_setup_dma_ops	arch_setup_dma_ops
 
+#define HAVE_ARCH_DMA_SET_MASK 1
+extern int dma_set_mask(struct device *dev, u64 dma_mask);
+
 #ifdef CONFIG_IOMMU_DMA
 void arch_teardown_dma_ops(struct device *dev);
 #define arch_teardown_dma_ops	arch_teardown_dma_ops
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index e040827..7b1bb87 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -203,6 +203,37 @@ static void __dma_free(struct device *dev, size_t size,
 	__dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs);
 }
 
+int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	const struct dma_map_ops *ops = get_dma_ops(dev);
+
+	if (mask > dev->archdata.parent_dma_mask)
+		mask = dev->archdata.parent_dma_mask;
+
+	if (ops->set_dma_mask)
+		return ops->set_dma_mask(dev, mask);
+
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+
+	*dev->dma_mask = mask;
+	return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
+int dma_set_coherent_mask(struct device *dev, u64 mask)
+{
+	if (mask > dev->archdata.parent_dma_mask)
+		mask = dev->archdata.parent_dma_mask;
+
+	if (!dma_supported(dev, mask))
+		return -EIO;
+
+	dev->coherent_dma_mask = mask;
+	return 0;
+}
+EXPORT_SYMBOL(dma_set_coherent_mask);
+
 static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
 				     unsigned long offset, size_t size,
 				     enum dma_data_direction dir,
@@ -958,6 +989,18 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
 	if (!dev->archdata.dma_ops)
 		dev->archdata.dma_ops = &swiotlb_dma_ops;
 
+	/*
+	 * we don't yet support buses that have a non-zero mapping.
+	 *  Let's hope we won't need it
+	 */
+	WARN_ON(dma_base != 0);
+
+	/*
+	 * Whatever the parent bus can set. A device must not set
+	 * a DMA mask larger than this.
+	 */
+	dev->archdata.parent_dma_mask = size - 1;
+
 	dev->archdata.dma_coherent = coherent;
 	__iommu_setup_dma_ops(dev, dma_base, size, iommu);
 }
-- 
2.1.4

^ permalink raw reply related

* [PATCH v2 2/2] media: rc: add driver for IR remote receiver on MT7623 SoC
From: Sean Wang @ 2017-01-10 13:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170110110943.GA24889@gofer.mess.org>

On Tue, 2017-01-10 at 11:09 +0000, Sean Young wrote:

> > +#include <linux/clk.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/module.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/reset.h>
> > +#include <media/rc-core.h>
> > +
> > +#define MTK_IR_DEV KBUILD_MODNAME
> 
> You could remove this #define and just use KBUILD_MODNAME

I preferred to use MTK_IR_DEV internally that helps
renaming in the future if necessary.
>  
> > +
> > +/* Register to enable PWM and IR */
> > +#define MTK_CONFIG_HIGH_REG       0x0c
> > +/* Enable IR pulse width detection */
> > +#define MTK_PWM_EN		  BIT(13)
> > +/* Enable IR hardware function */
> > +#define MTK_IR_EN		  BIT(0)
> > +
> > +/* Register to setting sample period */
> > +#define MTK_CONFIG_LOW_REG        0x10
> > +/* Field to set sample period */
> > +#define CHK_PERIOD		  DIV_ROUND_CLOSEST(MTK_IR_SAMPLE,  \
> > +						    MTK_IR_CLK_PERIOD)
> > +#define MTK_CHK_PERIOD            (((CHK_PERIOD) << 8) & (GENMASK(20, 8)))
> > +#define MTK_CHK_PERIOD_MASK	  (GENMASK(20, 8))
> > +
> > +/* Register to clear state of state machine */
> > +#define MTK_IRCLR_REG             0x20
> > +/* Bit to restart IR receiving */
> > +#define MTK_IRCLR		  BIT(0)
> > +
> > +/* Register containing pulse width data */
> > +#define MTK_CHKDATA_REG(i)        (0x88 + 4 * (i))
> > +#define MTK_WIDTH_MASK		  (GENMASK(7, 0))
> > +
> > +/* Register to enable IR interrupt */
> > +#define MTK_IRINT_EN_REG          0xcc
> > +/* Bit to enable interrupt */
> > +#define MTK_IRINT_EN		  BIT(0)
> > +
> > +/* Register to ack IR interrupt */
> > +#define MTK_IRINT_CLR_REG         0xd0
> > +/* Bit to clear interrupt status */
> > +#define MTK_IRINT_CLR		  BIT(0)
> > +
> > +/* Maximum count of samples */
> > +#define MTK_MAX_SAMPLES		  0xff
> > +/* Indicate the end of IR message */
> > +#define MTK_IR_END(v, p)	  ((v) == MTK_MAX_SAMPLES && (p) == 0)
> > +/* Number of registers to record the pulse width */
> > +#define MTK_CHKDATA_SZ		  17
> > +/* Source clock frequency */
> > +#define MTK_IR_BASE_CLK		  273000000
> > +/* Frequency after IR internal divider */
> > +#define MTK_IR_CLK_FREQ		  (MTK_IR_BASE_CLK / 4)

> > +static irqreturn_t mtk_ir_irq(int irqno, void *dev_id)
> > +{
> > +	struct mtk_ir *ir = dev_id;
> > +	u8  wid = 0;
> > +	u32 i, j, val;
> > +	DEFINE_IR_RAW_EVENT(rawir);
> > +
> > +	mtk_irq_disable(ir, MTK_IRINT_EN);
> 
> The kernel guarantees that calls to the interrupt handler are serialised,
> no need to disable the interrupt in the handler.

agreed. I will save the mtk irq disable/enable and retest again.


> > +
> > +	/* Reset decoder state machine */
> > +	ir_raw_event_reset(ir->rc);
> 
> Not needed.


two reasons I added the line here

1) 
I thought it is possible the decoder goes to the
middle state when getting the data not belonged
to the protocol. If so, that would cause the decoding
fails in the next time receiving the valid protocol data.

2) 
the mtk hardware register always contains the start of 
IR message. So force to sync the state between 
HW and ir-core.



> > +
> > +	/* First message must be pulse */
> > +	rawir.pulse = false;
> 
> pulse = true?

becasue of rawir.pulse = !rawir.pulse does as below
so the initial value is set as false.

> > +
> > +	/* Handle all pulse and space IR controller captures */
> > +	for (i = 0 ; i < MTK_CHKDATA_SZ ; i++) {
> > +		val = mtk_r32(ir, MTK_CHKDATA_REG(i));
> > +		dev_dbg(ir->dev, "@reg%d=0x%08x\n", i, val);
> > +
> > +		for (j = 0 ; j < 4 ; j++) {
> > +			wid = (val & (MTK_WIDTH_MASK << j * 8)) >> j * 8;
> > +			rawir.pulse = !rawir.pulse;
> > +			rawir.duration = wid * (MTK_IR_SAMPLE + 1);
> > +			ir_raw_event_store_with_filter(ir->rc, &rawir);
> > +		}
> 
> In v1 you would break out of the loop if the ir message was shorter, but
> now you are always passing on 68 pulses and spaces. Is that right?

as I asked in the previous mail list as below i copied from it, so i
made some changes ...

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
> I had another question. I found multiple and same IR messages being
> received when using SONY remote controller. Should driver needs to
> report each message or only one of these to the upper layer ?

In general the driver shouldn't try to change any IR message, this
should be done in rc-core if necessary.

rc-core should handle this correctly. If the same key is received twice
within IR_KEYPRESS_TIMEOUT (250ms) then it not reported to the input
layer.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

for example:
the 68 pulse/spaces might contains 2.x IR messages when I
pressed one key on SONY remote control. 

the v1 proposed is passing only one IR message into ir-core ; 
the v2 done is passing all IR messages even including the last
incomplete message into ir-core. 

But I was still afraid the state machine can't  go back to initial state
after receiving these incomplete data. 

So the ir_raw_event_reset() call in the beginning of ISR seems becoming
more important.

> > +	}
> > +
> > +	/* The maximum number of edges the IR controller can
> > +	 * hold is MTK_CHKDATA_SZ * 4. So if received IR messages
> > +	 * is over the limit, the last incomplete IR message would
> > +	 * be appended trailing space and still would be sent into
> > +	 * ir-rc-raw to decode. That helps it is possible that it
> > +	 * has enough information to decode a scancode even if the
> > +	 * trailing end of the message is missing.
> > +	 */
> > +	if (!MTK_IR_END(wid, rawir.pulse)) {
> > +		rawir.pulse = false;
> > +		rawir.duration = MTK_MAX_SAMPLES * (MTK_IR_SAMPLE + 1);
> > +		ir_raw_event_store_with_filter(ir->rc, &rawir);
> > +	}
> > +
> > +	ir_raw_event_handle(ir->rc);
> > +
> > +	/* Restart controller for the next receive */
> > +	mtk_w32_mask(ir, 0x1, MTK_IRCLR, MTK_IRCLR_REG);
> > +
> > +	/* Clear interrupt status */
> > +	mtk_w32_mask(ir, 0x1, MTK_IRINT_CLR, MTK_IRINT_CLR_REG);
> > +
> > +	/* Enable interrupt */
> > +	mtk_irq_enable(ir, MTK_IRINT_EN);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int mtk_ir_probe(struct platform_device *pdev)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct device_node *dn = dev->of_node;
> > +	struct resource *res;
> > +	struct mtk_ir *ir;
> > +	u32 val;
> > +	int ret = 0;
> > +	const char *map_name;
> > +
> > +	ir = devm_kzalloc(dev, sizeof(struct mtk_ir), GFP_KERNEL);
> > +	if (!ir)
> > +		return -ENOMEM;
> > +
> > +	ir->dev = dev;
> > +
> > +	if (!of_device_is_compatible(dn, "mediatek,mt7623-cir"))
> > +		return -ENODEV;
> > +
> > +	ir->clk = devm_clk_get(dev, "clk");
> > +	if (IS_ERR(ir->clk)) {
> > +		dev_err(dev, "failed to get a ir clock.\n");
> > +		return PTR_ERR(ir->clk);
> > +	}
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	ir->base = devm_ioremap_resource(dev, res);
> > +	if (IS_ERR(ir->base)) {
> > +		dev_err(dev, "failed to map registers\n");
> > +		return PTR_ERR(ir->base);
> > +	}
> > +
> > +	ir->rc = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW);
> > +	if (!ir->rc) {
> > +		dev_err(dev, "failed to allocate device\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	ir->rc->priv = ir;
> > +	ir->rc->input_name = MTK_IR_DEV;
> > +	ir->rc->input_phys = MTK_IR_DEV "/input0";
> > +	ir->rc->input_id.bustype = BUS_HOST;
> > +	ir->rc->input_id.vendor = 0x0001;
> > +	ir->rc->input_id.product = 0x0001;
> > +	ir->rc->input_id.version = 0x0001;
> > +	map_name = of_get_property(dn, "linux,rc-map-name", NULL);
> > +	ir->rc->map_name = map_name ?: RC_MAP_EMPTY;
> > +	ir->rc->dev.parent = dev;
> > +	ir->rc->driver_name = MTK_IR_DEV;
> > +	ir->rc->allowed_protocols = RC_BIT_ALL;
> > +	ir->rc->rx_resolution = MTK_IR_SAMPLE;
> > +	ir->rc->timeout = MTK_MAX_SAMPLES * (MTK_IR_SAMPLE + 1);
> > +
> > +	ret = devm_rc_register_device(dev, ir->rc);
> 
> Here you do devm_rc_register_device()

does it have problem ?


> > +	if (ret) {
> > +		dev_err(dev, "failed to register rc device\n");
> > +		return ret;
> > +	}
> > +
> > +	platform_set_drvdata(pdev, ir);
> > +
> > +	ir->irq = platform_get_irq(pdev, 0);
> > +	if (ir->irq < 0) {
> > +		dev_err(dev, "no irq resource\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	/* Enable interrupt after proper hardware
> > +	 * setup and IRQ handler registration
> > +	 */
> > +	if (clk_prepare_enable(ir->clk)) {
> > +		dev_err(dev, "try to enable ir_clk failed\n");
> > +		ret = -EINVAL;
> > +		goto exit_clkdisable_clk;
> > +	}
> > +
> > +	mtk_irq_disable(ir, MTK_IRINT_EN);
> > +
> > +	ret = devm_request_irq(dev, ir->irq, mtk_ir_irq, 0, MTK_IR_DEV, ir);
> > +	if (ret) {
> > +		dev_err(dev, "failed request irq\n");
> > +		goto exit_clkdisable_clk;
> > +	}
> > +
> > +	/* Enable IR and PWM */
> > +	val = mtk_r32(ir, MTK_CONFIG_HIGH_REG);
> > +	val |= MTK_PWM_EN | MTK_IR_EN;
> > +	mtk_w32(ir, val, MTK_CONFIG_HIGH_REG);
> > +
> > +	/* Setting sample period */
> > +	mtk_w32_mask(ir, MTK_CHK_PERIOD, MTK_CHK_PERIOD_MASK,
> > +		     MTK_CONFIG_LOW_REG);
> > +
> > +	mtk_irq_enable(ir, MTK_IRINT_EN);
> > +
> > +	dev_info(dev, "Initialized MT7623 IR driver, sample period = %luus\n",
> > +		 DIV_ROUND_CLOSEST(MTK_IR_SAMPLE, 1000));
> > +
> > +	return 0;
> > +
> > +exit_clkdisable_clk:
> > +	clk_disable_unprepare(ir->clk);
> > +
> > +	return ret;
> > +}
> > +
> > +static int mtk_ir_remove(struct platform_device *pdev)
> > +{
> > +	struct mtk_ir *ir = platform_get_drvdata(pdev);
> > +
> > +	/* Avoid contention between remove handler and
> > +	 * IRQ handler so that disabling IR interrupt and
> > +	 * waiting for pending IRQ handler to complete
> > +	 */
> > +	mtk_irq_disable(ir, MTK_IRINT_EN);
> > +	synchronize_irq(ir->irq);
> > +
> > +	clk_disable_unprepare(ir->clk);
> > +
> > +	rc_unregister_device(ir->rc);
> 
> Yet here you explicitly call rc_unregister_device(). Since it was registered
> with the devm call, this call is not needed and will lead to double frees etc

bug :( .  I will fix it ..

> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id mtk_ir_match[] = {
> > +	{ .compatible = "mediatek,mt7623-cir" },
> > +	{},
> > +};
> > +MODULE_DEVICE_TABLE(of, mtk_ir_match);
> > +
> > +static struct platform_driver mtk_ir_driver = {
> > +	.probe          = mtk_ir_probe,
> > +	.remove         = mtk_ir_remove,
> > +	.driver = {
> > +		.name = MTK_IR_DEV,
> > +		.of_match_table = mtk_ir_match,
> > +	},
> > +};
> > +
> > +module_platform_driver(mtk_ir_driver);
> > +
> > +MODULE_DESCRIPTION("Mediatek IR Receiver Controller Driver");
> > +MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
> > +MODULE_LICENSE("GPL");
> > -- 
> > 2.7.4
> > 

^ permalink raw reply

* [PATCH 0/4] video: ARM CLCD: add support of an optional GPIO to enable panel
From: Vladimir Murzin @ 2017-01-10 13:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <252ad888-fa9d-695a-58ed-46806e4374fd@mleia.com>

Hi Vladimir,

On 07/01/17 23:32, Vladimir Zapolskiy wrote:
> On 01/02/2017 04:22 PM, Russell King - ARM Linux wrote:
>> On Fri, Dec 30, 2016 at 09:23:59AM +0100, Linus Walleij wrote:
>>> On Wed, Dec 21, 2016 at 4:27 AM, Vladimir Zapolskiy <vz@mleia.com> wrote:
>>>
>>>> The changeset contains a number of cleanups, changed semantics of
>>>> init_panel() callback, which allows to simplify getting of panel
>>>> properties from panel device tree node, and a handling of optional
>>>> "enable-gpios" panel property, the latter is described in
>>>> display/panel/panel-dpi.txt device tree binding documentation, but
>>>> it has been unsupported by the ARM CLCD driver.
>>>>
>>>> Vladimir Zapolskiy (4):
>>>>   video: ARM CLCD: sort included headers out alphabetically
>>>>   video: ARM CLCD: use panel device node for panel initialization
>>>>   video: ARM CLCD: use panel device node for getting backlight and mode
>>>>   video: ARM CLCD: add support of an optional GPIO to enable panel
>>>
>>> As you may have seen Tomi has stepped down as FBDEV maintainer and
>>> this subsystem is now orphaned.
>>>
>>> I guess Andrew Morton merges patches for it in this case, he usually does.
>>>
>>> But what we should actually do is create a new DRM driver for CLCD
>>> in drivers/gpu/drm/arm/clcd*
>>>
>>> It's maybe not a small undertaking :(
>>>
>>> But in case you're interested in the job, I will pitch in and test the result
>>> on all ARM reference designs plus Nomadik.
>>
>> A DRM driver for it would probably be a good idea, but dealing with all
>> the weird and wonderful connection arrangements may not be that easy...
>>
> 
> Linus, Russell,
> 
> I've immediately encountered a problem while porting the driver to DRM,
> because LPC18xx/LPC43xx SoCs are powered by Cortex-M3/M4 cores and DRM
> framework has build and runtime dependencies on MMU.

+Benjamin

In another thread Benjamin pointed at patch [1] in drm/kms part for noMMU.

[1] https://cgit.freedesktop.org/drm/drm-misc/commit/?id=62a0d98a188cc4ebd8ea54b37d274ec20465e464

Cheers
Vladimir

> 
> That said, in short term I would expect a continuation of support for
> the legacy CLCD framebuffer driver, which works fine on MMU-less SoCs.
> 
> --
> With best wishes,
> Vladimir
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox