* [PATCH v3 8/9] arm: KVM: Enable support for host pmu
From: Punit Agrawal @ 2017-01-10 11:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170110113856.7183-1-punit.agrawal@arm.com>
Add the Kconfig option and Makefile updates to enable the recently added
support for host pmu.
Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Russell King <linux@armlinux.org.uk>
---
arch/arm/kvm/Kconfig | 4 ++++
arch/arm/kvm/Makefile | 1 +
2 files changed, 5 insertions(+)
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 90d0176fb30d..198d16c36220 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -16,6 +16,9 @@ menuconfig VIRTUALIZATION
if VIRTUALIZATION
+config KVM_HOST_PMU
+ bool
+
config KVM
bool "Kernel-based Virtual Machine (KVM) support"
depends on MMU && OF
@@ -30,6 +33,7 @@ config KVM
select SRCU
select MMU_NOTIFIER
select KVM_VFIO
+ select KVM_HOST_PMU if PERF_EVENTS
select HAVE_KVM_EVENTFD
select HAVE_KVM_IRQFD
select HAVE_KVM_IRQCHIP
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index d571243ab4d1..09d358499ce1 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -35,3 +35,4 @@ obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
obj-y += $(KVM)/arm/vgic/vgic-its.o
obj-y += $(KVM)/irqchip.o
obj-y += $(KVM)/arm/arch_timer.o
+obj-$(CONFIG_KVM_HOST_PMU) += $(KVM)/arm/host_pmu.o
--
2.11.0
^ permalink raw reply related
* [PATCH v3 9/9] arm64: KVM: Enable support for the host pmu
From: Punit Agrawal @ 2017-01-10 11:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170110113856.7183-1-punit.agrawal@arm.com>
Add the Kconfig option and Makefile update the enable the recently added
host pmu.
Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/Kconfig | 4 ++++
arch/arm64/kvm/Makefile | 1 +
2 files changed, 5 insertions(+)
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 52cb7ad9b2fd..c147a3077dab 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -16,6 +16,9 @@ menuconfig VIRTUALIZATION
if VIRTUALIZATION
+config KVM_HOST_PMU
+ bool
+
config KVM
bool "Kernel-based Virtual Machine (KVM) support"
depends on OF
@@ -31,6 +34,7 @@ config KVM
select KVM_VFIO
select HAVE_KVM_EVENTFD
select HAVE_KVM_IRQFD
+ select KVM_HOST_PMU if PERF_EVENTS
select KVM_ARM_PMU if HW_PERF_EVENTS
select HAVE_KVM_MSI
select HAVE_KVM_IRQCHIP
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index d50a82a16ff6..3bdac93784e2 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -34,3 +34,4 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/irqchip.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
+kvm-$(CONFIG_KVM_HOST_PMU) += $(KVM)/arm/host_pmu.o
--
2.11.0
^ permalink raw reply related
* [RFC PATCH v3 3/5] ARM: NOMMU: Introduce dma operations for noMMU
From: Vladimir Murzin @ 2017-01-10 11:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <b6ab1436-9a80-a694-e825-b9c23b62add8@arm.com>
On 09/01/17 16:59, Robin Murphy wrote:
> On 09/01/17 16:51, Vladimir Murzin wrote:
>> Hi Robin,
>>
>> On 09/01/17 16:43, Robin Murphy wrote:
>>> Hi Vladimir,
>>>
>>> On 09/01/17 13:47, Vladimir Murzin wrote:
>>>> 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..a5c50fb
>>>> --- /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(dma_addr_t handle, size_t size,
>>>> + enum dma_data_direction dir)
>>>> +{
>>>> + dmac_unmap_area(__va(handle), size, dir);
>>>> +
>>>> + if (dir == DMA_FROM_DEVICE)
>>>> + outer_inv_range(handle, handle + size);
>>>> + else
>>>> + outer_clean_range(handle, handle + size);
>>>> +}
>>>> +
>>>> +static void __dma_page_dev_to_cpu(dma_addr_t handle, size_t size,
>>>> + enum dma_data_direction dir)
>>>> +{
>>>> + if (dir != DMA_TO_DEVICE) {
>>>> + outer_inv_range(handle, handle + size);
>>>> + dmac_unmap_area(__va(handle), size, dir);
>>>> + }
>>>> +}
>>>
>>> Nit: I appreciate that the situation here makes it OK by construction,
>>> but CPU cache maintenance on a DMA address just looks *so* wrong :)
>>> Could we pass either the "virtual" or physical version of the address as
>>> the argument to these helpers so that the code looks less crazy at a glance?
>>
>> Something like bellow?
>>
>> static void __dma_page_dev_to_cpu(dma_addr_t paddr, size_t size,
> ^
> I meant more in terms of this being a const void* or phys_addr_t ;)
>
Fixed locally with "phys_addr_t".
>> enum dma_data_direction dir)
>> {
>> if (dir != DMA_TO_DEVICE) {
>> outer_inv_range(paddr, paddr + size);
>> dmac_unmap_area(__va(paddr), size, dir);
>> }
>>
>> Btw, thanks for having a look!
>
> Otherwise, I think the rest of the series looks OK, thanks for
> respinning it.
I'll wait for a while for more feedback and tests before submitting updated
version.
Cheers
Vladimir
>
> Robin.
>
>> Cheers
>> Vladimir
>>
>>>
>>> Robin.
>>>
>>>> +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);
>>>>
>>>
>>>
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
>
^ permalink raw reply
* [PATCH 1/2] of: base: add support to get the number of cache levels
From: Sudeep Holla @ 2017-01-10 11:41 UTC (permalink / raw)
To: linux-arm-kernel
It is useful to have helper function just to get the number of cache
levels for a given logical cpu. This patch adds the support for the
same.
It will be used on ARM64 platform where the device tree provides the
information for the additional non-architected/transparent/external
last level caches that are not integrated with the processors.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/of/base.c | 22 ++++++++++++++++++++++
include/linux/of.h | 1 +
2 files changed, 23 insertions(+)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index d4bea3c797d6..f7a2b47b3c77 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2268,6 +2268,28 @@ struct device_node *of_find_next_cache_node(const struct device_node *np)
}
/**
+ * of_count_cache_levels - Find the total number of cache levels for the
+ * given logical cpu
+ *
+ * @cpu: cpu number(logical index) for which cache levels is being counted
+ *
+ * Returns the total number of cache levels for the given logical cpu
+ */
+int of_count_cache_levels(unsigned int cpu)
+{
+ int level = 0;
+ struct device_node *np = of_cpu_device_node_get(cpu);
+
+ while (np) {
+ level++;
+ of_node_put(np);
+ np = of_find_next_cache_node(np);
+ }
+
+ return level;
+}
+
+/**
* of_graph_parse_endpoint() - parse common endpoint node properties
* @node: pointer to endpoint device_node
* @endpoint: pointer to the OF endpoint data structure
diff --git a/include/linux/of.h b/include/linux/of.h
index d72f01009297..c8597ae71ff3 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -280,6 +280,7 @@ extern struct device_node *of_get_child_by_name(const struct device_node *node,
/* cache lookup */
extern struct device_node *of_find_next_cache_node(const struct device_node *);
+extern int of_count_cache_levels(unsigned int cpu);
extern struct device_node *of_find_node_with_property(
struct device_node *from, const char *prop_name);
--
2.7.4
^ permalink raw reply related
* [PATCH 2/2] arm64: cacheinfo: add support to override cache levels via device tree
From: Sudeep Holla @ 2017-01-10 11:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484048479-19767-1-git-send-email-sudeep.holla@arm.com>
The cache hierarchy can be identified through Cache Level ID(CLIDR)
architected system register. However in some cases it will provide
only the number of cache levels that are integrated into the processor
itself. In other words, it can't provide any information about the
caches that are external and/or transparent.
Some platforms require to export the information about all such external
caches to the userspace applications via the sysfs interface.
This patch adds support to override the cache levels using device tree
to take such external non-architected caches into account.
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
arch/arm64/kernel/cacheinfo.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c
index 9617301f76b5..fe7738a8c5b1 100644
--- a/arch/arm64/kernel/cacheinfo.c
+++ b/arch/arm64/kernel/cacheinfo.c
@@ -84,7 +84,7 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
static int __init_cache_level(unsigned int cpu)
{
- unsigned int ctype, level, leaves;
+ unsigned int ctype, level, leaves, of_level;
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) {
@@ -97,6 +97,17 @@ static int __init_cache_level(unsigned int cpu)
leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1;
}
+ of_level = of_count_cache_levels(cpu);
+ if (level < of_level) {
+ /*
+ * some external caches not specified in CLIDR_EL1
+ * the information may be available in the device tree
+ * only unified external caches are considered here
+ */
+ leaves += (of_level - level);
+ level = of_level;
+ }
+
this_cpu_ci->num_levels = level;
this_cpu_ci->num_leaves = leaves;
return 0;
--
2.7.4
^ permalink raw reply related
* [PATCH v7 13/19] irqdomain: Add irq domain MSI and MSI_REMAP flags
From: Marc Zyngier @ 2017-01-10 11:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-14-git-send-email-eric.auger@redhat.com>
Hi Eric,
On 09/01/17 13:46, Eric Auger wrote:
> We introduce two new enum values for the irq domain flag:
> - IRQ_DOMAIN_FLAG_MSI indicates the irq domain corresponds to
> an MSI domain
> - IRQ_DOMAIN_FLAG_MSI_REMAP indicates the irq domain has MSI
> remapping capabilities.
>
> Those values will be useful to check all MSI irq domains have
> MSI remapping support when assessing the safety of IRQ assignment
> to a guest.
>
> irq_domain_hierarchical_is_msi_remap() allows to check if an
> irq domain or any parent implements MSI remapping.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v6:
> - add IRQ_DOMAIN_FLAG_MSI as suggested by Marc
> - add irq_domain_is_msi, irq_domain_is_msi_remap and
> irq_domain_hierarchical_is_msi_remap
> ---
> include/linux/irqdomain.h | 35 +++++++++++++++++++++++++++++++++++
> kernel/irq/irqdomain.c | 16 ++++++++++++++++
> 2 files changed, 51 insertions(+)
>
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index ffb8460..bc2f571 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -183,6 +183,12 @@ enum {
> /* Irq domain is an IPI domain with single virq */
> IRQ_DOMAIN_FLAG_IPI_SINGLE = (1 << 3),
>
> + /* Irq domain implements MSIs */
> + IRQ_DOMAIN_FLAG_MSI = (1 << 4),
> +
> + /* Irq domain implements MSI remapping */
> + IRQ_DOMAIN_FLAG_MSI_REMAP = (1 << 5),
> +
> /*
> * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
> * for implementation specific purposes and ignored by the
> @@ -446,6 +452,19 @@ static inline bool irq_domain_is_ipi_single(struct irq_domain *domain)
> {
> return domain->flags & IRQ_DOMAIN_FLAG_IPI_SINGLE;
> }
> +
> +static inline bool irq_domain_is_msi(struct irq_domain *domain)
> +{
> + return domain->flags & IRQ_DOMAIN_FLAG_MSI;
> +}
> +
> +static inline bool irq_domain_is_msi_remap(struct irq_domain *domain)
> +{
> + return domain->flags & IRQ_DOMAIN_FLAG_MSI_REMAP;
> +}
> +
> +extern bool irq_domain_hierarchical_is_msi_remap(struct irq_domain *domain);
> +
> #else /* CONFIG_IRQ_DOMAIN_HIERARCHY */
> static inline void irq_domain_activate_irq(struct irq_data *data) { }
> static inline void irq_domain_deactivate_irq(struct irq_data *data) { }
> @@ -477,6 +496,22 @@ static inline bool irq_domain_is_ipi_single(struct irq_domain *domain)
> {
> return false;
> }
> +
> +static inline bool irq_domain_is_msi(struct irq_domain *domain)
> +{
> + return false;
> +}
> +
> +static inline bool irq_domain_is_msi_remap(struct irq_domain *domain)
> +{
> + return false;
> +}
> +
> +static inline bool
> +irq_domain_hierarchical_is_msi_remap(struct irq_domain *domain)
> +{
> + return false;
> +}
> #endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */
>
> #else /* CONFIG_IRQ_DOMAIN */
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 8c0a0ae..101ee8f 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -1392,6 +1392,22 @@ static void irq_domain_check_hierarchy(struct irq_domain *domain)
> if (domain->ops->alloc)
> domain->flags |= IRQ_DOMAIN_FLAG_HIERARCHY;
> }
> +
> +/**
> + * irq_domain_hierarchical_is_msi_remap - Check if the domain or any
> + * parent has MSI remapping support
> + * @domain: domain pointer
> + */
> +bool irq_domain_hierarchical_is_msi_remap(struct irq_domain *domain)
> +{
> + struct irq_domain *h = domain;
> +
> + for (; h; h = h->parent) {
> + if (irq_domain_is_msi_remap(h))
nit: Why do you need to go via this extra 'h' variable?
for (; domain; domain = domain->parent) {
if (irq_domain_is_msi_remap(domain))
should work just as well.
> + return true;
> + }
> + return false;
> +}
> #else /* CONFIG_IRQ_DOMAIN_HIERARCHY */
> /**
> * irq_domain_get_irq_data - Get irq_data associated with @virq and @domain
>
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [QUESTION] Arm64: Query L3 cache info via DT
From: Sudeep Holla @ 2017-01-10 11:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5874BD6C.7060008@huawei.com>
On 10/01/17 10:54, Tan Xiaojun wrote:
> On 2017/1/10 18:01, Sudeep Holla wrote:
>>
>>
>> On 10/01/17 08:50, Tan Xiaojun wrote:
>>> I add this patch, and test in Hisilicon D02/D03. It can work well.
>>>
>>> I'm sorry to reply so late. I took some time to debug, because I am not familiar with the code.
>>>
>>>> + if (level < of_level) {
>>>> + /*
>>>> + * some external caches not specified in CLIDR_EL1
>>>> + * the information may be available in the device tree
>>>> + * only unified external caches are considered here
>>>> + */
>>>> + level = of_level;
>>>> + leaves += (of_level - level);
>>>
>>> The above two lines need to exchange the location.
>>>
>>
>> Ah crap, sorry for such a silly mistake.
>> I will post proper patch(es) soon.
>>
>
> OK. Wait for your new patch. ^_^
>
Thanks, I have posted the patches[1] and Cc-ed you on them. It would be
good to get Tested-by once you check.
--
Regards,
Sudeep
[1]
http://lists.infradead.org/pipermail/linux-arm-kernel/2017-January/478261.html
^ permalink raw reply
* [PATCH v2] arm64: do not set dma masks that device connection can't handle
From: Will Deacon @ 2017-01-10 11:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483947002-16410-1-git-send-email-nikita.yoush@cogentembedded.com>
On Mon, Jan 09, 2017 at 10:30:02AM +0300, Nikita Yushchenko wrote:
> It is possible that device is capable of 64-bit DMA addresses, and
> device driver tries to set wide DMA mask, but bridge or bus used to
> connect device to the system can't handle wide addresses.
>
> With swiotlb, memory above 4G still can be used by drivers for streaming
> DMA, but *dev->mask and dev->dma_coherent_mask must still keep values
> that hardware handles physically.
>
> This patch enforces that. Based on original version by
> Arnd Bergmann <arnd@arndb.de>, extended with coherent mask hadnling.
>
> Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
> CC: Arnd Bergmann <arnd@arndb.de>
> ---
> Changes since v1:
> - fixed issues noted by Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
> - save mask, not size
> - remove doube empty line
>
> arch/arm64/Kconfig | 3 +++
> arch/arm64/include/asm/device.h | 1 +
> arch/arm64/mm/dma-mapping.c | 51 +++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 55 insertions(+)
I still don't think this patch is general enough. The problem you're seeing
with swiotlb seems to be exactly the same problem reported by Feng Kan over
at:
http://lkml.kernel.org/r/CAL85gmA_SSCwM80TKdkZqEe+S1beWzDEvdki1kpkmUTDRmSP7g at mail.gmail.com
[read on; it was initially thought to be a hardware erratum, but it's
actually the inability to restrict the DMA mask of the endpoint that's
the problem]
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.
Will
^ permalink raw reply
* [PATCH v7 15/19] irqdomain: irq_domain_check_msi_remap
From: Marc Zyngier @ 2017-01-10 11:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-16-git-send-email-eric.auger@redhat.com>
On 09/01/17 13:46, Eric Auger wrote:
> This new function checks whether all MSI irq domains
> implement IRQ remapping. This is useful to understand
> whether VFIO passthrough is safe with respect to interrupts.
>
> On ARM typically an MSI controller can sit downstream
> to the IOMMU without preventing VFIO passthrough.
> As such any assigned device can write into the MSI doorbell.
> In case the MSI controller implements IRQ remapping, assigned
> devices will not be able to trigger interrupts towards the
> host. On the contrary, the assignment must be emphasized as
> unsafe with respect to interrupts.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
> v5 -> v6:
> - use irq_domain_hierarchical_is_msi_remap()
> - comment rewording
>
> v4 -> v5:
> - Handle DOMAIN_BUS_FSL_MC_MSI domains
> - Check parents
> ---
> include/linux/irqdomain.h | 1 +
> kernel/irq/irqdomain.c | 23 +++++++++++++++++++++++
> 2 files changed, 24 insertions(+)
>
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index bc2f571..188eced 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -222,6 +222,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
> void *host_data);
> extern struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec,
> enum irq_domain_bus_token bus_token);
> +extern bool irq_domain_check_msi_remap(void);
> extern void irq_set_default_host(struct irq_domain *host);
> extern int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
> irq_hw_number_t hwirq, int node,
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 101ee8f..fff30cb 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -278,6 +278,29 @@ struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec,
> EXPORT_SYMBOL_GPL(irq_find_matching_fwspec);
>
> /**
> + * irq_domain_check_msi_remap - Check whether all MSI
> + * irq domains implement IRQ remapping
> + */
> +bool irq_domain_check_msi_remap(void)
> +{
> + struct irq_domain *h;
> + bool ret = true;
> +
> + mutex_lock(&irq_domain_mutex);
> + list_for_each_entry(h, &irq_domain_list, link) {
> + if (irq_domain_is_msi(h) &&
> + !irq_domain_hierarchical_is_msi_remap(h)) {
> + ret = false;
> + goto out;
Let's avoid gotos if we can. a break statement will have the same effect
here, and we can drop the label.
> + }
> + }
> +out:
> + mutex_unlock(&irq_domain_mutex);
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(irq_domain_check_msi_remap);
> +
> +/**
> * irq_set_default_host() - Set a "default" irq domain
> * @domain: default domain pointer
> *
>
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH 1/2] of: base: add support to get the number of cache levels
From: Sudeep Holla @ 2017-01-10 11:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484048479-19767-1-git-send-email-sudeep.holla@arm.com>
On 10/01/17 11:41, Sudeep Holla wrote:
> It is useful to have helper function just to get the number of cache
> levels for a given logical cpu. This patch adds the support for the
> same.
>
> It will be used on ARM64 platform where the device tree provides the
> information for the additional non-architected/transparent/external
> last level caches that are not integrated with the processors.
>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
> drivers/of/base.c | 22 ++++++++++++++++++++++
> include/linux/of.h | 1 +
> 2 files changed, 23 insertions(+)
>
I seem to have missed to generate patch after I fixed the build error.
I will send updated version of this patch.
--
Regards,
Sudeep
^ permalink raw reply
* [PATCH v7 16/19] irqchip/gicv3-its: Sets IRQ_DOMAIN_FLAG_MSI_REMAP
From: Marc Zyngier @ 2017-01-10 11:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-17-git-send-email-eric.auger@redhat.com>
Hi Eric,
On 09/01/17 13:46, Eric Auger wrote:
> The GICv3 ITS is MSI remapping capable. Let's advertise
> this property so that VFIO passthrough can assess IRQ safety.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> ---
> drivers/irqchip/irq-gic-v3-its.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 69b040f..9d4fefc 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -1642,6 +1642,7 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
>
> inner_domain->parent = its_parent;
> inner_domain->bus_token = DOMAIN_BUS_NEXUS;
> + inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_REMAP;
> info->ops = &its_msi_domain_ops;
> info->data = its;
> inner_domain->host_data = info;
>
For patches 13 to 16, and provided that you address the couple of nits I
mentioned in reply to patches 13 and 15:
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [RFC PATCH] IOMMU: SMMUv2: Support for Extended Stream ID (16 bit)
From: Aleksey Makarov @ 2017-01-10 11:57 UTC (permalink / raw)
To: linux-arm-kernel
Enable the Extended Stream ID feature when available.
This patch on top of series "[PATCH v7 00/19] KVM PCIe/MSI passthrough
on ARM/ARM64 and IOVA reserved regions" by Eric Auger allows
to passthrough an external PCIe network card on a ThunderX server
successfully.
Without this patch that card caused a warning like
pci 0006:90:00.0: stream ID 0x9000 out of range for SMMU (0x7fff)
during boot.
Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>
---
drivers/iommu/arm-smmu.c | 53 +++++++++++++++++++++++++++++++++---------------
1 file changed, 37 insertions(+), 16 deletions(-)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 13d26009b8e0..d160c12828f4 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -24,6 +24,7 @@
* - v7/v8 long-descriptor format
* - Non-secure access to the SMMU
* - Context fault reporting
+ * - Extended Stream ID (16 bit)
*/
#define pr_fmt(fmt) "arm-smmu: " fmt
@@ -87,6 +88,7 @@
#define sCR0_CLIENTPD (1 << 0)
#define sCR0_GFRE (1 << 1)
#define sCR0_GFIE (1 << 2)
+#define sCR0_EXIDENABLE (1 << 3)
#define sCR0_GCFGFRE (1 << 4)
#define sCR0_GCFGFIE (1 << 5)
#define sCR0_USFCFG (1 << 10)
@@ -126,6 +128,7 @@
#define ID0_NUMIRPT_MASK 0xff
#define ID0_NUMSIDB_SHIFT 9
#define ID0_NUMSIDB_MASK 0xf
+#define ID0_EXIDS (1 << 8)
#define ID0_NUMSMRG_SHIFT 0
#define ID0_NUMSMRG_MASK 0xff
@@ -169,6 +172,7 @@
#define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2))
#define S2CR_CBNDX_SHIFT 0
#define S2CR_CBNDX_MASK 0xff
+#define S2CR_EXIDVALID (1 << 10)
#define S2CR_TYPE_SHIFT 16
#define S2CR_TYPE_MASK 0x3
enum arm_smmu_s2cr_type {
@@ -354,6 +358,7 @@ struct arm_smmu_device {
#define ARM_SMMU_FEAT_FMT_AARCH64_64K (1 << 9)
#define ARM_SMMU_FEAT_FMT_AARCH32_L (1 << 10)
#define ARM_SMMU_FEAT_FMT_AARCH32_S (1 << 11)
+#define ARM_SMMU_FEAT_EXIDS (1 << 12)
u32 features;
#define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
@@ -1051,7 +1056,7 @@ static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx)
struct arm_smmu_smr *smr = smmu->smrs + idx;
u32 reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT;
- if (smr->valid)
+ if (!(smmu->features & ARM_SMMU_FEAT_EXIDS) && smr->valid)
reg |= SMR_VALID;
writel_relaxed(reg, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_SMR(idx));
}
@@ -1063,6 +1068,9 @@ static void arm_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx)
(s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT |
(s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT;
+ if (smmu->features & ARM_SMMU_FEAT_EXIDS && smmu->smrs &&
+ smmu->smrs[idx].valid)
+ reg |= S2CR_EXIDVALID;
writel_relaxed(reg, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_S2CR(idx));
}
@@ -1674,6 +1682,9 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
if (smmu->features & ARM_SMMU_FEAT_VMID16)
reg |= sCR0_VMID16EN;
+ if (smmu->features & ARM_SMMU_FEAT_EXIDS)
+ reg |= sCR0_EXIDENABLE;
+
/* Push the button */
__arm_smmu_tlb_sync(smmu);
writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
@@ -1761,7 +1772,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
"\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);
+ if (smmu->version == ARM_SMMU_V2 && id & ID0_EXIDS) {
+ smmu->features |= ARM_SMMU_FEAT_EXIDS;
+ size = (1 << 16);
+ } else {
+ size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
+ }
smmu->streamid_mask = size - 1;
if (id & ID0_SMS) {
u32 smr;
@@ -1774,20 +1790,25 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
return -ENODEV;
}
- /*
- * SMR.ID bits may not be preserved if the corresponding MASK
- * bits are set, so check each one separately. We can reject
- * masters later if they try to claim IDs outside these masks.
- */
- smr = smmu->streamid_mask << SMR_ID_SHIFT;
- writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
- smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
- smmu->streamid_mask = smr >> SMR_ID_SHIFT;
-
- smr = smmu->streamid_mask << SMR_MASK_SHIFT;
- writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
- smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
- smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT;
+ if (smmu->features & ARM_SMMU_FEAT_EXIDS) {
+ smmu->smr_mask_mask = smmu->streamid_mask;
+ } else {
+ /*
+ * SMR.ID bits may not be preserved if the corresponding
+ * MASK bits are set, so check each one separately.
+ * We can reject masters later if they try to claim IDs
+ * outside these masks.
+ */
+ smr = smmu->streamid_mask << SMR_ID_SHIFT;
+ writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
+ smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
+ smmu->streamid_mask = smr >> SMR_ID_SHIFT;
+
+ smr = smmu->streamid_mask << SMR_MASK_SHIFT;
+ writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
+ smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
+ smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT;
+ }
/* Zero-initialised to mark as invalid */
smmu->smrs = devm_kcalloc(smmu->dev, size, sizeof(*smmu->smrs),
--
2.11.0
^ permalink raw reply related
* [PATCH 1/4] clk: rockchip: add rk3288 isp_in clock ids
From: Jacob Chen @ 2017-01-10 11:59 UTC (permalink / raw)
To: linux-arm-kernel
Add clock-ids for the isp block of the rk3288.
Signed-off-by: Jacob Chen <jacob-chen@iotwrt.com>
---
include/dt-bindings/clock/rk3288-cru.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/dt-bindings/clock/rk3288-cru.h b/include/dt-bindings/clock/rk3288-cru.h
index 9a586e2..08de7de 100644
--- a/include/dt-bindings/clock/rk3288-cru.h
+++ b/include/dt-bindings/clock/rk3288-cru.h
@@ -168,6 +168,7 @@
#define PCLK_WDT 368
#define PCLK_EFUSE256 369
#define PCLK_EFUSE1024 370
+#define PCLK_ISP_IN 371
/* hclk gates */
#define HCLK_GPS 448
--
2.7.4
^ permalink raw reply related
* [PATCH 2/4] clk: rockchip: use rk3288 isp_in clock ids
From: Jacob Chen @ 2017-01-10 11:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484049560-14820-1-git-send-email-jacob-chen@iotwrt.com>
Reference the newly added isp clock-ids in the clock-tree.
Signed-off-by: Jacob Chen <jacob-chen@iotwrt.com>
---
drivers/clk/rockchip/clk-rk3288.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 39af05a..8047cea 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -801,7 +801,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
GATE(0, "pclk_vip_in", "ext_vip", 0, RK3288_CLKGATE_CON(16), 0, GFLAGS),
INVERTER(0, "pclk_vip", "pclk_vip_in", RK3288_CLKSEL_CON(29), 4, IFLAGS),
- GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
+ GATE(PCLK_ISP_IN, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS),
};
--
2.7.4
^ permalink raw reply related
* [PATCH 3/4] clk: rockchip: add rk3288 cif_out clock ids
From: Jacob Chen @ 2017-01-10 11:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484049560-14820-1-git-send-email-jacob-chen@iotwrt.com>
Add clock-ids for the cif block of the rk3288
Signed-off-by: Jacob Chen <jacob-chen@iotwrt.com>
---
include/dt-bindings/clock/rk3288-cru.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/dt-bindings/clock/rk3288-cru.h b/include/dt-bindings/clock/rk3288-cru.h
index 08de7de..128b191 100644
--- a/include/dt-bindings/clock/rk3288-cru.h
+++ b/include/dt-bindings/clock/rk3288-cru.h
@@ -88,6 +88,7 @@
#define SCLK_PVTM_GPU 124
#define SCLK_CRYPTO 125
#define SCLK_MIPIDSI_24M 126
+#define SCLK_CIF_OUT 127
#define SCLK_MAC 151
#define SCLK_MACREF_OUT 152
--
2.7.4
^ permalink raw reply related
* [PATCH 4/4] clk: rockchip: add rk3288 cif_out clock
From: Jacob Chen @ 2017-01-10 11:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484049560-14820-1-git-send-email-jacob-chen@iotwrt.com>
Add the clocks for the cif block of the rk3288
Signed-off-by: Jacob Chen <jacob-chen@iotwrt.com>
---
drivers/clk/rockchip/clk-rk3288.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 8047cea..f071c24 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -192,6 +192,7 @@ PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" };
PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" };
PNAME(mux_uart3_p) = { "uart3_src", "uart3_frac", "xin24m" };
PNAME(mux_uart4_p) = { "uart4_src", "uart4_frac", "xin24m" };
+PNAME(mux_cif_out_p) = { "cif_src", "xin24m" };
PNAME(mux_vip_out_p) = { "vip_src", "xin24m" };
PNAME(mux_mac_p) = { "mac_pll_src", "ext_gmac" };
PNAME(mux_hsadcout_p) = { "hsadc_src", "ext_hsadc" };
@@ -448,6 +449,12 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
RK3288_CLKSEL_CON(6), 14, 2, MFLAGS, 8, 6, DFLAGS,
RK3288_CLKGATE_CON(3), 15, GFLAGS),
+ COMPOSITE_NOGATE(0, "cif_src", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(26), 8, 1, MFLAGS, 9, 5, DFLAGS),
+ COMPOSITE_NODIV(SCLK_CIF_OUT, "sclk_cif_out", mux_cif_out_p, 0,
+ RK3288_CLKSEL_CON(26), 15, 1, MFLAGS,
+ RK3288_CLKGATE_CON(3), 7, GFLAGS),
+
GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0,
RK3288_CLKGATE_CON(5), 12, GFLAGS),
GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0,
--
2.7.4
^ permalink raw reply related
* [PATCH 1/2][UPDATE] of: base: add support to get the number of cache levels
From: Sudeep Holla @ 2017-01-10 12:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484048479-19767-1-git-send-email-sudeep.holla@arm.com>
It is useful to have helper function just to get the number of cache
levels for a given logical cpu. This patch adds the support for the
same.
It will be used on ARM64 platform where the device tree provides the
information for the additional non-architected/transparent/external
last level caches that are not integrated with the processors.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/of/base.c | 23 +++++++++++++++++++++++
include/linux/of.h | 1 +
2 files changed, 24 insertions(+)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index d4bea3c797d6..80e557eca858 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -25,6 +25,7 @@
#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
@@ -2268,6 +2269,28 @@ struct device_node *of_find_next_cache_node(const struct device_node *np)
}
/**
+ * of_count_cache_levels - Find the total number of cache levels for the
+ * given logical cpu
+ *
+ * @cpu: cpu number(logical index) for which cache levels is being counted
+ *
+ * Returns the total number of cache levels for the given logical cpu
+ */
+int of_count_cache_levels(unsigned int cpu)
+{
+ int level = 0;
+ struct device_node *np = of_cpu_device_node_get(cpu);
+
+ while (np) {
+ level++;
+ of_node_put(np);
+ np = of_find_next_cache_node(np);
+ }
+
+ return level;
+}
+
+/**
* of_graph_parse_endpoint() - parse common endpoint node properties
* @node: pointer to endpoint device_node
* @endpoint: pointer to the OF endpoint data structure
diff --git a/include/linux/of.h b/include/linux/of.h
index d72f01009297..c8597ae71ff3 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -280,6 +280,7 @@ extern struct device_node *of_get_child_by_name(const struct device_node *node,
/* cache lookup */
extern struct device_node *of_find_next_cache_node(const struct device_node *);
+extern int of_count_cache_levels(unsigned int cpu);
extern struct device_node *of_find_node_with_property(
struct device_node *from, const char *prop_name);
--
2.7.4
^ permalink raw reply related
* [PATCH] usb: dwc3-exynos fix unspecified suspend clk error handling
From: Bartlomiej Zolnierkiewicz @ 2017-01-10 12:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170110022131.31042-1-shuahkh@osg.samsung.com>
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
> 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 v2 2/2] media: rc: add driver for IR remote receiver on MT7623 SoC
From: kbuild test robot @ 2017-01-10 12:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484039631-25120-3-git-send-email-sean.wang@mediatek.com>
Hi Sean,
[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.10-rc3 next-20170110]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/sean-wang-mediatek-com/Documentation-devicetree-Add-document-bindings-for-mtk-cir/20170110-193357
base: git://linuxtv.org/media_tree.git master
config: x86_64-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
include/linux/compiler.h:253:8: sparse: attribute 'no_sanitize_address': unknown attribute
drivers/media/rc/mtk-cir.c:215:41: sparse: too many arguments for function devm_rc_allocate_device
drivers/media/rc/mtk-cir.c: In function 'mtk_ir_probe':
>> drivers/media/rc/mtk-cir.c:215:11: error: too many arguments to function 'devm_rc_allocate_device'
ir->rc = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW);
^~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/media/rc/mtk-cir.c:22:0:
include/media/rc-core.h:213:16: note: declared here
struct rc_dev *devm_rc_allocate_device(struct device *dev);
^~~~~~~~~~~~~~~~~~~~~~~
sparse warnings: (new ones prefixed by >>)
include/linux/compiler.h:253:8: sparse: attribute 'no_sanitize_address': unknown attribute
>> drivers/media/rc/mtk-cir.c:215:41: sparse: too many arguments for function devm_rc_allocate_device
drivers/media/rc/mtk-cir.c: In function 'mtk_ir_probe':
drivers/media/rc/mtk-cir.c:215:11: error: too many arguments to function 'devm_rc_allocate_device'
ir->rc = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW);
^~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/media/rc/mtk-cir.c:22:0:
include/media/rc-core.h:213:16: note: declared here
struct rc_dev *devm_rc_allocate_device(struct device *dev);
^~~~~~~~~~~~~~~~~~~~~~~
vim +/devm_rc_allocate_device +215 drivers/media/rc/mtk-cir.c
209 ir->base = devm_ioremap_resource(dev, res);
210 if (IS_ERR(ir->base)) {
211 dev_err(dev, "failed to map registers\n");
212 return PTR_ERR(ir->base);
213 }
214
> 215 ir->rc = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW);
216 if (!ir->rc) {
217 dev_err(dev, "failed to allocate device\n");
218 return -ENOMEM;
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 57747 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170110/f8a4befc/attachment-0001.gz>
^ permalink raw reply
* [RFC PATCH 1/5] regulator: Extend the power-management APIs
From: Mark Brown @ 2017-01-10 12:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170110093355.700f8225@bbrezillon>
On Tue, Jan 10, 2017 at 09:33:55AM +0100, Boris Brezillon wrote:
> Mark Brown <broonie@kernel.org> wrote:
> > However it
> > *is* a bit more than just making sure that the device suspend ordering
> > is good (though that's definitely part of it), there will be things
> > kicked off by hardware signalling without software knowing about it.
> Do you have an example, so that I can understand the use case?
Think about how a CPU suspends and signals the PMIC to go into suspend
mode - things signalled by hardware state changes that the hardware does
autonomously.
> > Anything that doesn't affect a hardware supported runtime state probably
> > needs to be split off and handled separately as that's the much more
> > risky bit
> Just to be sure, you mean regulator devices that do not support the
> ->set_suspend_xx() hooks, right?
Yes.
> >, moving changing of suspend mode earlier isn't going to cause
> > too much grief, that patch should just be split out and can probably
> > just go straight in.
> Yes, I just thought it would be clearer to have everything implemented
> in the same function. Since calling ->set_suspend_xx() does not have
> any impact on the runtime state, it can be called whenever we want
> (assuming we can still communicate with the regulator device to
> configure this suspend state).
> But if you prefer to have it split out in 2 different function, with the
> 'set suspend mode' bits called from the regulator_suspend_begin(), I'm
> fine with that.
No, I'm mainly saying that these things should be done in two separate
patches rather than talking about how the end code looks. To a large
extent it does't matter when we apply the hardware supported suspend
modes, they won't take effect while software is running anyway.
> > Requring these functions to be called from every single driver seems
> > like we're doing something wrong - if we're going to do this we should
> > find some way to loop over all regulators and apply any unapplied
> > changes.
> I agree. Actually, I forgot that we had PM ops at the device class
> level. Maybe we could just move these generic ->suspend()/->resume()
> implementation here.
Yeah, I need to check if those class level operations always get run.
> > Batching things up at the end of suspend would also mean that
> > we'd be able to minimise the chances that we get the ordering wrong.
> Unfortunately that's not possible, for the exact same reason calling
> regulator_suspend_prepare() from the platform ->prepare() hook did not
> work for me: at that point, all devices have been suspended, and this
> includes the i2c controller which we're using to communicate with the
> PMIC exposing those regulators.
Do those devices actually get meaningfully suspended on your system, and
even on systems where we do if we are going to use the dependency graphs
we should be able to arrange to do something with that to reorder both
them and the regulators to as near the end of the queue as we can get
tehm - that way we minimise the chances of being bitten by any
unexpressed depdencies (which I expect we have a lot of given how
resistant people are to writing proper DTs).
> 2/ Rely on the device model dependency graph, and enter the suspend
> state when the regulator device is being suspended (this is the
> solution I'm proposing in this patch).
That's future work though (which is happening but still), right now we
know the graph doesn't work properly. It also leaves us more open to
unexpressed dependencies which are
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170110/d6f8b633/attachment.sig>
^ permalink raw reply
* Unhandled level 2 translation fault (11) at 0x000000b8, esr 0x92000046, rpi3 (aarch64)
From: Catalin Marinas @ 2017-01-10 12:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGDbNAC-8w1xytLuzWTMnWLi8=j1ShkwE3CLXQ5q75m_RibCMA@mail.gmail.com>
On Mon, Jan 09, 2017 at 07:06:19PM +0100, Bas van Tiel wrote:
> > I defined STACKSIZE to the kernel's SIGSTKSZ (16384) and it seems to run
> > fine, though I'll leave it longer/overnight (on a Juno board). With the
> > 4K signal stack it was crashing shortly after start.
>
> I tried the STACKSIZE of 16384 for both the RPI3 and the PINEA64 board
> and still see the same behaviour of crashing. Sometimes the process
> is also blocked for a long time before it crashes.
>
> Setting the interval to 200 usec [5 Khz] will help to crash it faster.
>
> To further isolate the issue I will create a kernel module (based on a
> hrtimer) that will sent a periodic signal to the registered process
> and execute the same sighandler logic to check if the problem is still
> there.
I lowered the interval to 100us (it was 100ms in the original file) and
I can indeed trigger segfault easily on Juno. But it doesn't fail in the
same way every time, I sometimes get permission fault, other times bad
frame.
--
Catalin
^ permalink raw reply
* [PATCH] ARM: imx: hide unused variable in #ifdef
From: Arnd Bergmann @ 2017-01-10 12:19 UTC (permalink / raw)
To: linux-arm-kernel
A bugfix added a new local variable that is only used inside of an #ifdef
section, and unused if CONFIG_PERF_EVENTS is disabled:
arch/arm/mach-imx/mmdc.c:63:25: warning: 'cpuhp_mmdc_state' defined but not used [-Wunused-variable]
This moves the variable down inside that same ifdef.
Fixes: a051f220d6b9 ("ARM/imx/mmcd: Fix broken cpu hotplug handling")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/arm/mach-imx/mmdc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
index 699157759120..c03bf28d8bbc 100644
--- a/arch/arm/mach-imx/mmdc.c
+++ b/arch/arm/mach-imx/mmdc.c
@@ -60,7 +60,6 @@
#define to_mmdc_pmu(p) container_of(p, struct mmdc_pmu, pmu)
-static enum cpuhp_state cpuhp_mmdc_state;
static int ddr_type;
struct fsl_mmdc_devtype_data {
@@ -82,6 +81,7 @@ static const struct of_device_id imx_mmdc_dt_ids[] = {
#ifdef CONFIG_PERF_EVENTS
+static enum cpuhp_state cpuhp_mmdc_state;
static DEFINE_IDA(mmdc_ida);
PMU_EVENT_ATTR_STRING(total-cycles, mmdc_pmu_total_cycles, "event=0x00")
--
2.9.0
^ permalink raw reply related
* [PATCH] virtio_mmio: Set DMA masks appropriately
From: Robin Murphy @ 2017-01-10 12:26 UTC (permalink / raw)
To: linux-arm-kernel
Once DMA API usage is enabled, it becomes apparent that virtio-mmio is
inadvertently relying on the default 32-bit DMA mask, which leads to
problems like rapidly exhausting SWIOTLB bounce buffers.
Ensure that we set the appropriate 64-bit DMA mask whenever possible,
with the coherent mask suitably limited for the legacy vring as per
a0be1db4304f ("virtio_pci: Limit DMA mask to 44 bits for legacy virtio
devices").
Reported-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
Fixes: b42111382f0e ("virtio_mmio: Use the DMA API if enabled")
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/virtio/virtio_mmio.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 48bfea91dbca..b5c5d49ca598 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -59,6 +59,7 @@
#define pr_fmt(fmt) "virtio-mmio: " fmt
#include <linux/acpi.h>
+#include <linux/dma-mapping.h>
#include <linux/highmem.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -497,6 +498,7 @@ static int virtio_mmio_probe(struct platform_device *pdev)
struct virtio_mmio_device *vm_dev;
struct resource *mem;
unsigned long magic;
+ int rc;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem)
@@ -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));
+ else if (vm_dev->version == 1)
+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32 + PAGE_SHIFT));
+ if (rc)
+ dev_warn(&pdev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n");
+
platform_set_drvdata(pdev, vm_dev);
return register_virtio_device(&vm_dev->vdev);
--
2.10.2.dirty
^ permalink raw reply related
* [PATCH v5 3/3] drm: zte: add overlay plane support
From: Sean Paul @ 2017-01-10 12:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484011774-18900-4-git-send-email-shawnguo@kernel.org>
On Mon, Jan 9, 2017 at 8:29 PM, Shawn Guo <shawnguo@kernel.org> wrote:
> From: Shawn Guo <shawn.guo@linaro.org>
>
> It enables VOU VL (Video Layer) to support overlay plane with scaling
> function. VL0 has some quirks on scaling support. We choose to skip it
> and only adds VL1 and VL2 into DRM core for now.
>
> Function zx_plane_atomic_disable() gets moved around with no changes to
> save a forward declaration.
>
\o/
Thanks for putting up with me, Shawn, this looks really good :-)
Reviewed-by: Sean Paul <seanpaul@chromium.org>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> ---
> drivers/gpu/drm/zte/zx_plane.c | 301 +++++++++++++++++++++++++++++++++---
> drivers/gpu/drm/zte/zx_plane_regs.h | 51 ++++++
> drivers/gpu/drm/zte/zx_vou.c | 72 ++++++++-
> drivers/gpu/drm/zte/zx_vou_regs.h | 18 +++
> 4 files changed, 413 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
> index 5445eebf830f..6c742993ed9e 100644
> --- a/drivers/gpu/drm/zte/zx_plane.c
> +++ b/drivers/gpu/drm/zte/zx_plane.c
> @@ -30,6 +30,261 @@
> DRM_FORMAT_ARGB4444,
> };
>
> +static const uint32_t vl_formats[] = {
> + DRM_FORMAT_NV12, /* Semi-planar YUV420 */
> + DRM_FORMAT_YUV420, /* Planar YUV420 */
> + DRM_FORMAT_YUYV, /* Packed YUV422 */
> + DRM_FORMAT_YVYU,
> + DRM_FORMAT_UYVY,
> + DRM_FORMAT_VYUY,
> + DRM_FORMAT_YUV444, /* YUV444 8bit */
> + /*
> + * TODO: add formats below that HW supports:
> + * - YUV420 P010
> + * - YUV420 Hantro
> + * - YUV444 10bit
> + */
> +};
> +
> +#define FRAC_16_16(mult, div) (((mult) << 16) / (div))
> +
> +static int zx_vl_plane_atomic_check(struct drm_plane *plane,
> + struct drm_plane_state *plane_state)
> +{
> + struct drm_framebuffer *fb = plane_state->fb;
> + struct drm_crtc *crtc = plane_state->crtc;
> + struct drm_crtc_state *crtc_state;
> + struct drm_rect clip;
> + int min_scale = FRAC_16_16(1, 8);
> + int max_scale = FRAC_16_16(8, 1);
> +
> + if (!crtc || !fb)
> + return 0;
> +
> + crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
> + crtc);
> + if (WARN_ON(!crtc_state))
> + return -EINVAL;
> +
> + /* nothing to check when disabling or disabled */
> + if (!crtc_state->enable)
> + return 0;
> +
> + /* plane must be enabled */
> + if (!plane_state->crtc)
> + return -EINVAL;
> +
> + clip.x1 = 0;
> + clip.y1 = 0;
> + clip.x2 = crtc_state->adjusted_mode.hdisplay;
> + clip.y2 = crtc_state->adjusted_mode.vdisplay;
> +
> + return drm_plane_helper_check_state(plane_state, &clip,
> + min_scale, max_scale,
> + true, true);
> +}
> +
> +static int zx_vl_get_fmt(uint32_t format)
> +{
> + switch (format) {
> + case DRM_FORMAT_NV12:
> + return VL_FMT_YUV420;
> + case DRM_FORMAT_YUV420:
> + return VL_YUV420_PLANAR | VL_FMT_YUV420;
> + case DRM_FORMAT_YUYV:
> + return VL_YUV422_YUYV | VL_FMT_YUV422;
> + case DRM_FORMAT_YVYU:
> + return VL_YUV422_YVYU | VL_FMT_YUV422;
> + case DRM_FORMAT_UYVY:
> + return VL_YUV422_UYVY | VL_FMT_YUV422;
> + case DRM_FORMAT_VYUY:
> + return VL_YUV422_VYUY | VL_FMT_YUV422;
> + case DRM_FORMAT_YUV444:
> + return VL_FMT_YUV444_8BIT;
> + default:
> + WARN_ONCE(1, "invalid pixel format %d\n", format);
> + return -EINVAL;
> + }
> +}
> +
> +static inline void zx_vl_set_update(struct zx_plane *zplane)
> +{
> + void __iomem *layer = zplane->layer;
> +
> + zx_writel_mask(layer + VL_CTRL0, VL_UPDATE, VL_UPDATE);
> +}
> +
> +static inline void zx_vl_rsz_set_update(struct zx_plane *zplane)
> +{
> + zx_writel(zplane->rsz + RSZ_VL_ENABLE_CFG, 1);
> +}
> +
> +static int zx_vl_rsz_get_fmt(uint32_t format)
> +{
> + switch (format) {
> + case DRM_FORMAT_NV12:
> + case DRM_FORMAT_YUV420:
> + return RSZ_VL_FMT_YCBCR420;
> + case DRM_FORMAT_YUYV:
> + case DRM_FORMAT_YVYU:
> + case DRM_FORMAT_UYVY:
> + case DRM_FORMAT_VYUY:
> + return RSZ_VL_FMT_YCBCR422;
> + case DRM_FORMAT_YUV444:
> + return RSZ_VL_FMT_YCBCR444;
> + default:
> + WARN_ONCE(1, "invalid pixel format %d\n", format);
> + return -EINVAL;
> + }
> +}
> +
> +static inline u32 rsz_step_value(u32 src, u32 dst)
> +{
> + u32 val = 0;
> +
> + if (src == dst)
> + val = 0;
> + else if (src < dst)
> + val = RSZ_PARA_STEP((src << 16) / dst);
> + else if (src > dst)
> + val = RSZ_DATA_STEP(src / dst) |
> + RSZ_PARA_STEP(((src << 16) / dst) & 0xffff);
> +
> + return val;
> +}
> +
> +static void zx_vl_rsz_setup(struct zx_plane *zplane, uint32_t format,
> + u32 src_w, u32 src_h, u32 dst_w, u32 dst_h)
> +{
> + void __iomem *rsz = zplane->rsz;
> + u32 src_chroma_w = src_w;
> + u32 src_chroma_h = src_h;
> + u32 fmt;
> +
> + /* Set up source and destination resolution */
> + zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1));
> + zx_writel(rsz + RSZ_DEST_CFG, RSZ_VER(dst_h - 1) | RSZ_HOR(dst_w - 1));
> +
> + /* Configure data format for VL RSZ */
> + fmt = zx_vl_rsz_get_fmt(format);
> + if (fmt >= 0)
> + zx_writel_mask(rsz + RSZ_VL_CTRL_CFG, RSZ_VL_FMT_MASK, fmt);
> +
> + /* Calculate Chroma height and width */
> + if (fmt == RSZ_VL_FMT_YCBCR420) {
> + src_chroma_w = src_w >> 1;
> + src_chroma_h = src_h >> 1;
> + } else if (fmt == RSZ_VL_FMT_YCBCR422) {
> + src_chroma_w = src_w >> 1;
> + }
> +
> + /* Set up Luma and Chroma step registers */
> + zx_writel(rsz + RSZ_VL_LUMA_HOR, rsz_step_value(src_w, dst_w));
> + zx_writel(rsz + RSZ_VL_LUMA_VER, rsz_step_value(src_h, dst_h));
> + zx_writel(rsz + RSZ_VL_CHROMA_HOR, rsz_step_value(src_chroma_w, dst_w));
> + zx_writel(rsz + RSZ_VL_CHROMA_VER, rsz_step_value(src_chroma_h, dst_h));
> +
> + zx_vl_rsz_set_update(zplane);
> +}
> +
> +static void zx_vl_plane_atomic_update(struct drm_plane *plane,
> + struct drm_plane_state *old_state)
> +{
> + struct zx_plane *zplane = to_zx_plane(plane);
> + struct drm_plane_state *state = plane->state;
> + struct drm_framebuffer *fb = state->fb;
> + struct drm_rect *src = &state->src;
> + struct drm_rect *dst = &state->dst;
> + struct drm_gem_cma_object *cma_obj;
> + void __iomem *layer = zplane->layer;
> + void __iomem *hbsc = zplane->hbsc;
> + void __iomem *paddr_reg;
> + dma_addr_t paddr;
> + u32 src_x, src_y, src_w, src_h;
> + u32 dst_x, dst_y, dst_w, dst_h;
> + uint32_t format;
> + u32 fmt;
> + int num_planes;
> + int i;
> +
> + if (!fb)
> + return;
> +
> + format = fb->pixel_format;
> +
> + src_x = src->x1 >> 16;
> + src_y = src->y1 >> 16;
> + src_w = drm_rect_width(src) >> 16;
> + src_h = drm_rect_height(src) >> 16;
> +
> + dst_x = dst->x1;
> + dst_y = dst->y1;
> + dst_w = drm_rect_width(dst);
> + dst_h = drm_rect_height(dst);
> +
> + /* Set up data address registers for Y, Cb and Cr planes */
> + num_planes = drm_format_num_planes(format);
> + paddr_reg = layer + VL_Y;
> + for (i = 0; i < num_planes; i++) {
> + cma_obj = drm_fb_cma_get_gem_obj(fb, i);
> + paddr = cma_obj->paddr + fb->offsets[i];
> + paddr += src_y * fb->pitches[i];
> + paddr += src_x * drm_format_plane_cpp(format, i);
> + zx_writel(paddr_reg, paddr);
> + paddr_reg += 4;
> + }
> +
> + /* Set up source height/width register */
> + zx_writel(layer + VL_SRC_SIZE, GL_SRC_W(src_w) | GL_SRC_H(src_h));
> +
> + /* Set up start position register */
> + zx_writel(layer + VL_POS_START, GL_POS_X(dst_x) | GL_POS_Y(dst_y));
> +
> + /* Set up end position register */
> + zx_writel(layer + VL_POS_END,
> + GL_POS_X(dst_x + dst_w) | GL_POS_Y(dst_y + dst_h));
> +
> + /* Strides of Cb and Cr planes should be identical */
> + zx_writel(layer + VL_STRIDE, LUMA_STRIDE(fb->pitches[0]) |
> + CHROMA_STRIDE(fb->pitches[1]));
> +
> + /* Set up video layer data format */
> + fmt = zx_vl_get_fmt(format);
> + if (fmt >= 0)
> + zx_writel(layer + VL_CTRL1, fmt);
> +
> + /* Always use scaler since it exists (set for not bypass) */
> + zx_writel_mask(layer + VL_CTRL2, VL_SCALER_BYPASS_MODE,
> + VL_SCALER_BYPASS_MODE);
> +
> + zx_vl_rsz_setup(zplane, format, src_w, src_h, dst_w, dst_h);
> +
> + /* Enable HBSC block */
> + zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN);
> +
> + zx_vou_layer_enable(plane);
> +
> + zx_vl_set_update(zplane);
> +}
> +
> +static void zx_plane_atomic_disable(struct drm_plane *plane,
> + struct drm_plane_state *old_state)
> +{
> + struct zx_plane *zplane = to_zx_plane(plane);
> + void __iomem *hbsc = zplane->hbsc;
> +
> + zx_vou_layer_disable(plane);
> +
> + /* Disable HBSC block */
> + zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, 0);
> +}
> +
> +static const struct drm_plane_helper_funcs zx_vl_plane_helper_funcs = {
> + .atomic_check = zx_vl_plane_atomic_check,
> + .atomic_update = zx_vl_plane_atomic_update,
> + .atomic_disable = zx_plane_atomic_disable,
> +};
> +
> static int zx_gl_plane_atomic_check(struct drm_plane *plane,
> struct drm_plane_state *plane_state)
> {
> @@ -97,14 +352,6 @@ static inline void zx_gl_rsz_set_update(struct zx_plane *zplane)
> zx_writel(zplane->rsz + RSZ_ENABLE_CFG, 1);
> }
>
> -void zx_plane_set_update(struct drm_plane *plane)
> -{
> - struct zx_plane *zplane = to_zx_plane(plane);
> -
> - zx_gl_rsz_set_update(zplane);
> - zx_gl_set_update(zplane);
> -}
> -
> static void zx_gl_rsz_setup(struct zx_plane *zplane, u32 src_w, u32 src_h,
> u32 dst_w, u32 dst_h)
> {
> @@ -202,18 +449,6 @@ static void zx_gl_plane_atomic_update(struct drm_plane *plane,
> zx_gl_set_update(zplane);
> }
>
> -static void zx_plane_atomic_disable(struct drm_plane *plane,
> - struct drm_plane_state *old_state)
> -{
> - struct zx_plane *zplane = to_zx_plane(plane);
> - void __iomem *hbsc = zplane->hbsc;
> -
> - zx_vou_layer_disable(plane);
> -
> - /* Disable HBSC block */
> - zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, 0);
> -}
> -
> static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = {
> .atomic_check = zx_gl_plane_atomic_check,
> .atomic_update = zx_gl_plane_atomic_update,
> @@ -235,6 +470,28 @@ static void zx_plane_destroy(struct drm_plane *plane)
> .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> };
>
> +void zx_plane_set_update(struct drm_plane *plane)
> +{
> + struct zx_plane *zplane = to_zx_plane(plane);
> +
> + /* Do nothing if the plane is not enabled */
> + if (!plane->state->crtc)
> + return;
> +
> + switch (plane->type) {
> + case DRM_PLANE_TYPE_PRIMARY:
> + zx_gl_rsz_set_update(zplane);
> + zx_gl_set_update(zplane);
> + break;
> + case DRM_PLANE_TYPE_OVERLAY:
> + zx_vl_rsz_set_update(zplane);
> + zx_vl_set_update(zplane);
> + break;
> + default:
> + WARN_ONCE(1, "unsupported plane type %d\n", plane->type);
> + }
> +}
> +
> static void zx_plane_hbsc_init(struct zx_plane *zplane)
> {
> void __iomem *hbsc = zplane->hbsc;
> @@ -272,7 +529,9 @@ int zx_plane_init(struct drm_device *drm, struct zx_plane *zplane,
> format_count = ARRAY_SIZE(gl_formats);
> break;
> case DRM_PLANE_TYPE_OVERLAY:
> - /* TODO: add video layer (vl) support */
> + helper = &zx_vl_plane_helper_funcs;
> + formats = vl_formats;
> + format_count = ARRAY_SIZE(vl_formats);
> break;
> default:
> return -ENODEV;
> diff --git a/drivers/gpu/drm/zte/zx_plane_regs.h b/drivers/gpu/drm/zte/zx_plane_regs.h
> index 3dde6716a558..65f271aeabed 100644
> --- a/drivers/gpu/drm/zte/zx_plane_regs.h
> +++ b/drivers/gpu/drm/zte/zx_plane_regs.h
> @@ -46,6 +46,37 @@
> #define GL_POS_X(x) (((x) << GL_POS_X_SHIFT) & GL_POS_X_MASK)
> #define GL_POS_Y(x) (((x) << GL_POS_Y_SHIFT) & GL_POS_Y_MASK)
>
> +/* VL registers */
> +#define VL_CTRL0 0x00
> +#define VL_UPDATE BIT(3)
> +#define VL_CTRL1 0x04
> +#define VL_YUV420_PLANAR BIT(5)
> +#define VL_YUV422_SHIFT 3
> +#define VL_YUV422_YUYV (0 << VL_YUV422_SHIFT)
> +#define VL_YUV422_YVYU (1 << VL_YUV422_SHIFT)
> +#define VL_YUV422_UYVY (2 << VL_YUV422_SHIFT)
> +#define VL_YUV422_VYUY (3 << VL_YUV422_SHIFT)
> +#define VL_FMT_YUV420 0
> +#define VL_FMT_YUV422 1
> +#define VL_FMT_YUV420_P010 2
> +#define VL_FMT_YUV420_HANTRO 3
> +#define VL_FMT_YUV444_8BIT 4
> +#define VL_FMT_YUV444_10BIT 5
> +#define VL_CTRL2 0x08
> +#define VL_SCALER_BYPASS_MODE BIT(0)
> +#define VL_STRIDE 0x0c
> +#define LUMA_STRIDE_SHIFT 16
> +#define LUMA_STRIDE_MASK (0xffff << LUMA_STRIDE_SHIFT)
> +#define CHROMA_STRIDE_SHIFT 0
> +#define CHROMA_STRIDE_MASK (0xffff << CHROMA_STRIDE_SHIFT)
> +#define VL_SRC_SIZE 0x10
> +#define VL_Y 0x14
> +#define VL_POS_START 0x30
> +#define VL_POS_END 0x34
> +
> +#define LUMA_STRIDE(x) (((x) << LUMA_STRIDE_SHIFT) & LUMA_STRIDE_MASK)
> +#define CHROMA_STRIDE(x) (((x) << CHROMA_STRIDE_SHIFT) & CHROMA_STRIDE_MASK)
> +
> /* CSC registers */
> #define CSC_CTRL0 0x30
> #define CSC_COV_MODE_SHIFT 16
> @@ -69,6 +100,18 @@
> #define RSZ_DEST_CFG 0x04
> #define RSZ_ENABLE_CFG 0x14
>
> +#define RSZ_VL_LUMA_HOR 0x08
> +#define RSZ_VL_LUMA_VER 0x0c
> +#define RSZ_VL_CHROMA_HOR 0x10
> +#define RSZ_VL_CHROMA_VER 0x14
> +#define RSZ_VL_CTRL_CFG 0x18
> +#define RSZ_VL_FMT_SHIFT 3
> +#define RSZ_VL_FMT_MASK (0x3 << RSZ_VL_FMT_SHIFT)
> +#define RSZ_VL_FMT_YCBCR420 (0x0 << RSZ_VL_FMT_SHIFT)
> +#define RSZ_VL_FMT_YCBCR422 (0x1 << RSZ_VL_FMT_SHIFT)
> +#define RSZ_VL_FMT_YCBCR444 (0x2 << RSZ_VL_FMT_SHIFT)
> +#define RSZ_VL_ENABLE_CFG 0x1c
> +
> #define RSZ_VER_SHIFT 16
> #define RSZ_VER_MASK (0xffff << RSZ_VER_SHIFT)
> #define RSZ_HOR_SHIFT 0
> @@ -77,6 +120,14 @@
> #define RSZ_VER(x) (((x) << RSZ_VER_SHIFT) & RSZ_VER_MASK)
> #define RSZ_HOR(x) (((x) << RSZ_HOR_SHIFT) & RSZ_HOR_MASK)
>
> +#define RSZ_DATA_STEP_SHIFT 16
> +#define RSZ_DATA_STEP_MASK (0xffff << RSZ_DATA_STEP_SHIFT)
> +#define RSZ_PARA_STEP_SHIFT 0
> +#define RSZ_PARA_STEP_MASK (0xffff << RSZ_PARA_STEP_SHIFT)
> +
> +#define RSZ_DATA_STEP(x) (((x) << RSZ_DATA_STEP_SHIFT) & RSZ_DATA_STEP_MASK)
> +#define RSZ_PARA_STEP(x) (((x) << RSZ_PARA_STEP_SHIFT) & RSZ_PARA_STEP_MASK)
> +
> /* HBSC registers */
> #define HBSC_SATURATION 0x00
> #define HBSC_HUE 0x04
> diff --git a/drivers/gpu/drm/zte/zx_vou.c b/drivers/gpu/drm/zte/zx_vou.c
> index 3fb4fc04e693..3056b41df518 100644
> --- a/drivers/gpu/drm/zte/zx_vou.c
> +++ b/drivers/gpu/drm/zte/zx_vou.c
> @@ -112,6 +112,22 @@ struct vou_layer_bits {
> },
> };
>
> +static const struct vou_layer_bits zx_vl_bits[VL_NUM] = {
> + {
> + .enable = OSD_CTRL0_VL0_EN,
> + .chnsel = OSD_CTRL0_VL0_SEL,
> + .clksel = VOU_CLK_VL0_SEL,
> + }, {
> + .enable = OSD_CTRL0_VL1_EN,
> + .chnsel = OSD_CTRL0_VL1_SEL,
> + .clksel = VOU_CLK_VL1_SEL,
> + }, {
> + .enable = OSD_CTRL0_VL2_EN,
> + .chnsel = OSD_CTRL0_VL2_SEL,
> + .clksel = VOU_CLK_VL2_SEL,
> + },
> +};
> +
> struct zx_vou_hw {
> struct device *dev;
> void __iomem *osd;
> @@ -451,6 +467,48 @@ void zx_vou_layer_disable(struct drm_plane *plane)
> zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, 0);
> }
>
> +static void zx_overlay_init(struct drm_device *drm, struct zx_vou_hw *vou)
> +{
> + struct device *dev = vou->dev;
> + struct zx_plane *zplane;
> + int i;
> + int ret;
> +
> + /*
> + * VL0 has some quirks on scaling support which need special handling.
> + * Let's leave it out for now.
> + */
> + for (i = 1; i < VL_NUM; i++) {
> + zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
> + if (!zplane) {
> + DRM_DEV_ERROR(dev, "failed to allocate zplane %d\n", i);
> + return;
> + }
> +
> + zplane->layer = vou->osd + OSD_VL_OFFSET(i);
> + zplane->hbsc = vou->osd + HBSC_VL_OFFSET(i);
> + zplane->rsz = vou->otfppu + RSZ_VL_OFFSET(i);
> + zplane->bits = &zx_vl_bits[i];
> +
> + ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_OVERLAY);
> + if (ret) {
> + DRM_DEV_ERROR(dev, "failed to init overlay %d\n", i);
> + continue;
> + }
> + }
> +}
> +
> +static inline void zx_osd_int_update(struct zx_crtc *zcrtc)
> +{
> + struct drm_crtc *crtc = &zcrtc->crtc;
> + struct drm_plane *plane;
> +
> + vou_chn_set_update(zcrtc);
> +
> + drm_for_each_plane_mask(plane, crtc->dev, crtc->state->plane_mask)
> + zx_plane_set_update(plane);
> +}
> +
> static irqreturn_t vou_irq_handler(int irq, void *dev_id)
> {
> struct zx_vou_hw *vou = dev_id;
> @@ -470,15 +528,11 @@ static irqreturn_t vou_irq_handler(int irq, void *dev_id)
> state = zx_readl(vou->osd + OSD_INT_STA);
> zx_writel(vou->osd + OSD_INT_CLRSTA, state);
>
> - if (state & OSD_INT_MAIN_UPT) {
> - vou_chn_set_update(vou->main_crtc);
> - zx_plane_set_update(vou->main_crtc->primary);
> - }
> + if (state & OSD_INT_MAIN_UPT)
> + zx_osd_int_update(vou->main_crtc);
>
> - if (state & OSD_INT_AUX_UPT) {
> - vou_chn_set_update(vou->aux_crtc);
> - zx_plane_set_update(vou->aux_crtc->primary);
> - }
> + if (state & OSD_INT_AUX_UPT)
> + zx_osd_int_update(vou->aux_crtc);
>
> if (state & OSD_INT_ERROR)
> DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state);
> @@ -648,6 +702,8 @@ static int zx_crtc_bind(struct device *dev, struct device *master, void *data)
> goto disable_ppu_clk;
> }
>
> + zx_overlay_init(drm, vou);
> +
> return 0;
>
> disable_ppu_clk:
> diff --git a/drivers/gpu/drm/zte/zx_vou_regs.h b/drivers/gpu/drm/zte/zx_vou_regs.h
> index f44e7a4ae441..193c1ce01fe7 100644
> --- a/drivers/gpu/drm/zte/zx_vou_regs.h
> +++ b/drivers/gpu/drm/zte/zx_vou_regs.h
> @@ -22,6 +22,15 @@
> #define AUX_HBSC_OFFSET 0x860
> #define AUX_RSZ_OFFSET 0x800
>
> +#define OSD_VL0_OFFSET 0x040
> +#define OSD_VL_OFFSET(i) (OSD_VL0_OFFSET + 0x050 * (i))
> +
> +#define HBSC_VL0_OFFSET 0x760
> +#define HBSC_VL_OFFSET(i) (HBSC_VL0_OFFSET + 0x040 * (i))
> +
> +#define RSZ_VL1_U0 0xa00
> +#define RSZ_VL_OFFSET(i) (RSZ_VL1_U0 + 0x200 * (i))
> +
> /* OSD (GPC_GLOBAL) registers */
> #define OSD_INT_STA 0x04
> #define OSD_INT_CLRSTA 0x08
> @@ -42,6 +51,12 @@
> )
> #define OSD_INT_ENABLE (OSD_INT_ERROR | OSD_INT_AUX_UPT | OSD_INT_MAIN_UPT)
> #define OSD_CTRL0 0x10
> +#define OSD_CTRL0_VL0_EN BIT(13)
> +#define OSD_CTRL0_VL0_SEL BIT(12)
> +#define OSD_CTRL0_VL1_EN BIT(11)
> +#define OSD_CTRL0_VL1_SEL BIT(10)
> +#define OSD_CTRL0_VL2_EN BIT(9)
> +#define OSD_CTRL0_VL2_SEL BIT(8)
> #define OSD_CTRL0_GL0_EN BIT(7)
> #define OSD_CTRL0_GL0_SEL BIT(6)
> #define OSD_CTRL0_GL1_EN BIT(5)
> @@ -146,6 +161,9 @@
> #define VOU_INF_DATA_SEL 0x08
> #define VOU_SOFT_RST 0x14
> #define VOU_CLK_SEL 0x18
> +#define VOU_CLK_VL2_SEL BIT(8)
> +#define VOU_CLK_VL1_SEL BIT(7)
> +#define VOU_CLK_VL0_SEL BIT(6)
> #define VOU_CLK_GL1_SEL BIT(5)
> #define VOU_CLK_GL0_SEL BIT(4)
> #define VOU_CLK_REQEN 0x20
> --
> 1.9.1
>
--
Sean Paul, Software Engineer, Google / Chromium OS
^ permalink raw reply
* [PATCH] arm64: add missing printk newlines
From: Will Deacon @ 2017-01-10 12:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483971216-11781-1-git-send-email-mark.rutland@arm.com>
On Mon, Jan 09, 2017 at 02:13:36PM +0000, Mark Rutland wrote:
> A few printk calls in arm64 omit a trailing newline, even though there
> is no subsequent KERN_CONT printk associated with them, and we actually
> want a newline.
>
> This can result in unrelated lines being appended, rather than appearing
> on a new line. Additionally, timestamp prefixes may appear in-line. This
> makes the logs harder to read than necessary.
>
> Avoid this by adding a trailing newline.
>
> These were found with a shortlist generated by:
>
> $ git grep 'pr\(intk\|_.*\)(.*)' -- arch/arm64 | grep -v pr_fmt | grep -v '\\n"'
>
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> CC: James Morse <james.morse@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> ---
> arch/arm64/kernel/armv8_deprecated.c | 2 +-
> arch/arm64/kernel/hibernate.c | 6 +++---
> 2 files changed, 4 insertions(+), 4 deletions(-)
Applied for 4.11.
Will
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox