* [PATCH v2 3/5] arm: decompressor: define a new zImage tag
From: Łukasz Stelmach @ 2020-06-02 16:17 UTC (permalink / raw)
To: Russell King, Masahiro Yamada, Nick Desaulniers, Thomas Gleixner,
Enrico Weigelt, Kees Cook, Ingo Molnar, Ben Dooks,
linux-arm-kernel, linux-kernel
Cc: AKASHI Takahiro, Marek Szyprowski, Łukasz Stelmach,
Bartlomiej Zolnierkiewicz
In-Reply-To: <20200602161731.23033-1-l.stelmach@samsung.com>
Add DCSZ tag which holds dynamic memory (stack, bss, malloc pool)
requirements of the decompressor code.
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
---
arch/arm/boot/compressed/vmlinux.lds.S | 9 ++++++++-
arch/arm/include/asm/image.h | 3 +++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S
index 308e9cd6a897..d15c1269eb5d 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.S
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -39,6 +39,11 @@ SECTIONS
LONG(ARM_ZIMAGE_MAGIC3)
LONG(ZIMAGE_MAGIC(__piggy_size_addr - _start))
LONG(ZIMAGE_MAGIC(_kernel_bss_size))
+ LONG(ZIMAGE_MAGIC(3))
+ LONG(ARM_ZIMAGE_MAGIC4)
+ LONG(ZIMAGE_MAGIC((_end - __bss_start) +
+ (_stack_end - _stack_start) +
+ MALLOC_SIZE))
LONG(0)
_table_end = .;
}
@@ -108,10 +113,12 @@ SECTIONS
. = BSS_START;
__bss_start = .;
.bss : { *(.bss) }
+ . = ALIGN(8); /* the stack must be 64-bit aligned and adjoin bss */
_end = .;
- . = ALIGN(8); /* the stack must be 64-bit aligned */
+ _stack_start = .;
.stack : { *(.stack) }
+ _stack_end = .;
PROVIDE(__pecoff_data_size = ALIGN(512) - ADDR(.data));
PROVIDE(__pecoff_end = ALIGN(512));
diff --git a/arch/arm/include/asm/image.h b/arch/arm/include/asm/image.h
index d5c18a0f6a34..55b51faa6b7e 100644
--- a/arch/arm/include/asm/image.h
+++ b/arch/arm/include/asm/image.h
@@ -15,6 +15,7 @@
#define ARM_ZIMAGE_MAGIC1 ZIMAGE_MAGIC(0x016f2818)
#define ARM_ZIMAGE_MAGIC2 (0x45454545)
#define ARM_ZIMAGE_MAGIC3 ZIMAGE_MAGIC(0x5a534c4b)
+#define ARM_ZIMAGE_MAGIC4 ZIMAGE_MAGIC(0x5a534344)
#ifndef __ASSEMBLY__
@@ -40,6 +41,8 @@ struct arm_zimage_tag {
__le32 size_ptr;
__le32 bss_size;
} krnl_size;
+#define ZIMAGE_TAG_ZIMAGE_MEM ARM_ZIMAGE_MAGIC4
+ __le32 zimage_mem;
} u;
};
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v2 0/5] kexec_file_load() for arm
From: Łukasz Stelmach @ 2020-06-02 16:17 UTC (permalink / raw)
To: Russell King, Masahiro Yamada, Nick Desaulniers, Thomas Gleixner,
Enrico Weigelt, Kees Cook, Ingo Molnar, Ben Dooks,
linux-arm-kernel, linux-kernel
Cc: AKASHI Takahiro, Marek Szyprowski, Łukasz Stelmach,
Bartlomiej Zolnierkiewicz
In-Reply-To: <20200601142754.26139-1-l.stelmach@samsung.com>
The following series of patches provides implementation of the
kexec_file_load() system call form the arm architecture. zImage and uImage
(legacy format) files are supported. Like on arm64, there is no
possibility of loading a new DTB and the currently loaded is reused.
Changes in v2:
- add CONFIG_KEXEC_FILE_UIMAGE for optional uImage support
- MALLOC_SIZE as a define instead of a symbol
- DCSZ tag holds combined dynamic memory requirements (bss+stack+malloc)
- use union for a single tag structure
- copyright notice includes Russell King
Łukasz Stelmach (5):
arm: decompressor: set malloc pool size for the decompressor
arm: add image header definitions
arm: decompressor: define a new zImage tag
arm: Add kexec_image_info
arm: kexec_file: load zImage or uImage, initrd and dtb
arch/arm/Kconfig | 25 +++
arch/arm/boot/compressed/Makefile | 7 +-
arch/arm/boot/compressed/head.S | 9 +-
arch/arm/boot/compressed/vmlinux.lds.S | 22 +--
arch/arm/include/asm/image.h | 77 +++++++++
arch/arm/include/asm/kexec.h | 14 ++
arch/arm/kernel/Makefile | 5 +-
arch/arm/kernel/kexec_uimage.c | 80 ++++++++++
arch/arm/kernel/kexec_zimage.c | 194 +++++++++++++++++++++++
arch/arm/kernel/machine_kexec.c | 39 ++++-
arch/arm/kernel/machine_kexec_file.c | 211 +++++++++++++++++++++++++
11 files changed, 662 insertions(+), 21 deletions(-)
create mode 100644 arch/arm/include/asm/image.h
create mode 100644 arch/arm/kernel/kexec_uimage.c
create mode 100644 arch/arm/kernel/kexec_zimage.c
create mode 100644 arch/arm/kernel/machine_kexec_file.c
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v2 4/5] arm: Add kexec_image_info
From: Łukasz Stelmach @ 2020-06-02 16:17 UTC (permalink / raw)
To: Russell King, Masahiro Yamada, Nick Desaulniers, Thomas Gleixner,
Enrico Weigelt, Kees Cook, Ingo Molnar, Ben Dooks,
linux-arm-kernel, linux-kernel
Cc: AKASHI Takahiro, Marek Szyprowski, Łukasz Stelmach,
Bartlomiej Zolnierkiewicz
In-Reply-To: <20200602161731.23033-1-l.stelmach@samsung.com>
Add kexec_image_info to print detailed information about a kexec image.
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
---
arch/arm/kernel/machine_kexec.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index 76300f3813e8..c10a2dfd53d1 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -31,6 +31,32 @@ extern unsigned long kexec_boot_atags;
static atomic_t waiting_for_crash_ipi;
+/**
+ * kexec_image_info - For debugging output.
+ */
+#define kexec_image_info(_i) _kexec_image_info(__func__, __LINE__, _i)
+static void _kexec_image_info(const char *func, int line,
+ const struct kimage *kimage)
+{
+ unsigned long i;
+
+ pr_debug("%s:%d:\n", func, line);
+ pr_debug(" kexec kimage info:\n");
+ pr_debug(" type: %d\n", kimage->type);
+ pr_debug(" start: %lx\n", kimage->start);
+ pr_debug(" head: %lx\n", kimage->head);
+ pr_debug(" nr_segments: %lu\n", kimage->nr_segments);
+
+ for (i = 0; i < kimage->nr_segments; i++) {
+ pr_debug(" segment[%lu]: %08lx - %08lx, 0x%x bytes, %lu pages\n",
+ i,
+ kimage->segment[i].mem,
+ kimage->segment[i].mem + kimage->segment[i].memsz,
+ kimage->segment[i].memsz,
+ kimage->segment[i].memsz / PAGE_SIZE);
+ }
+}
+
/*
* Provide a dummy crash_notes definition while crash dump arrives to arm.
* This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
@@ -42,6 +68,8 @@ int machine_kexec_prepare(struct kimage *image)
__be32 header;
int i, err;
+ kexec_image_info(image);
+
image->arch.kernel_r2 = image->start - KEXEC_ARM_ZIMAGE_OFFSET
+ KEXEC_ARM_ATAGS_OFFSET;
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v2 1/5] arm: decompressor: set malloc pool size for the decompressor
From: Łukasz Stelmach @ 2020-06-02 16:17 UTC (permalink / raw)
To: Russell King, Masahiro Yamada, Nick Desaulniers, Thomas Gleixner,
Enrico Weigelt, Kees Cook, Ingo Molnar, Ben Dooks,
linux-arm-kernel, linux-kernel
Cc: AKASHI Takahiro, Marek Szyprowski, Łukasz Stelmach,
Bartlomiej Zolnierkiewicz
In-Reply-To: <20200602161731.23033-1-l.stelmach@samsung.com>
Move the definition of malloc pool size of the decompressor to
a single place. This value will be exposed later for kexec_file loader.
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
---
arch/arm/boot/compressed/Makefile | 7 +++++--
arch/arm/boot/compressed/head.S | 6 ++++--
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 9c11e7490292..c4195651e371 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -7,7 +7,9 @@
OBJS =
-AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
+MALLOC_SIZE =0x10000
+
+AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) -DMALLOC_SIZE=$(MALLOC_SIZE)
HEAD = head.o
OBJS += misc.o decompress.o
ifeq ($(CONFIG_DEBUG_UNCOMPRESS),y)
@@ -68,7 +70,8 @@ ZTEXTADDR := 0
ZBSSADDR := ALIGN(8)
endif
-CPPFLAGS_vmlinux.lds := -DTEXT_START="$(ZTEXTADDR)" -DBSS_START="$(ZBSSADDR)"
+CPPFLAGS_vmlinux.lds := -DTEXT_START="$(ZTEXTADDR)" -DBSS_START="$(ZBSSADDR)" \
+ -DMALLOC_SIZE="$(MALLOC_SIZE)"
compress-$(CONFIG_KERNEL_GZIP) = gzip
compress-$(CONFIG_KERNEL_LZO) = lzo
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index e8e1c866e413..55758264e776 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -309,7 +309,8 @@ restart: adr r0, LC0
#ifndef CONFIG_ZBOOT_ROM
/* malloc space is above the relocated stack (64k max) */
add sp, sp, r0
- add r10, sp, #0x10000
+ mov r10, #MALLOC_SIZE
+ add r10, r10, sp
#else
/*
* With ZBOOT_ROM the bss/stack is non relocatable,
@@ -623,7 +624,8 @@ not_relocated: mov r0, #0
*/
mov r0, r4
mov r1, sp @ malloc space above stack
- add r2, sp, #0x10000 @ 64k max
+ mov r2, #MALLOC_SIZE @ 64k max
+ add r2, r2, sp
mov r3, r7
bl decompress_kernel
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v2 5/5] arm: kexec_file: load zImage or uImage, initrd and dtb
From: Łukasz Stelmach @ 2020-06-02 16:17 UTC (permalink / raw)
To: Russell King, Masahiro Yamada, Nick Desaulniers, Thomas Gleixner,
Enrico Weigelt, Kees Cook, Ingo Molnar, Ben Dooks,
linux-arm-kernel, linux-kernel
Cc: AKASHI Takahiro, Marek Szyprowski, Łukasz Stelmach,
Bartlomiej Zolnierkiewicz
In-Reply-To: <20200602161731.23033-1-l.stelmach@samsung.com>
This is kexec_file_load implementation for ARM. It loads zImage and
initrd from file descripters and resuses DTB.
Most code is derived from arm64 kexec_file_load implementation
and from kexec-tools.
Cc: AKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
---
arch/arm/Kconfig | 25 ++++
arch/arm/include/asm/image.h | 26 ++++
arch/arm/include/asm/kexec.h | 14 ++
arch/arm/kernel/Makefile | 5 +-
arch/arm/kernel/kexec_uimage.c | 80 ++++++++++
arch/arm/kernel/kexec_zimage.c | 194 ++++++++++++++++++++++++
arch/arm/kernel/machine_kexec.c | 11 +-
arch/arm/kernel/machine_kexec_file.c | 211 +++++++++++++++++++++++++++
8 files changed, 561 insertions(+), 5 deletions(-)
create mode 100644 arch/arm/kernel/kexec_uimage.c
create mode 100644 arch/arm/kernel/kexec_zimage.c
create mode 100644 arch/arm/kernel/machine_kexec_file.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c77c93c485a0..c592c58e78f1 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1917,6 +1917,31 @@ config KEXEC
is properly shutdown, so do not be surprised if this code does not
initially work for you.
+config KEXEC_FILE
+ bool "Kexec file based system call (EXPERIMENTAL)"
+ depends on (!SMP || PM_SLEEP_SMP)
+ depends on USE_OF
+ select KEXEC_CORE
+ select CRC32
+ help
+ This is new version of kexec system call. This system call is
+ file based and takes file descriptors as system call argument
+ for kernel and initramfs as opposed to list of segments as
+ accepted by previous system call.
+
+ The kernel to be loaded MUST support Flattened Device Tree
+ (selected with CONFIG_USE_OF).
+
+config KEXEC_FILE_UIMAGE
+ bool "Load legacy uImage files with kexec_file_load() (EXPERIMENTAL)"
+ depends on KEXEC_FILE
+ default n
+ help
+ This options enables support for the legacy uImage files as
+ created by mkimage. These are not the new FIT files.
+
+ If unsure say N.
+
config ATAGS_PROC
bool "Export atags in procfs"
depends on ATAGS && KEXEC
diff --git a/arch/arm/include/asm/image.h b/arch/arm/include/asm/image.h
index 55b51faa6b7e..596b32952958 100644
--- a/arch/arm/include/asm/image.h
+++ b/arch/arm/include/asm/image.h
@@ -8,8 +8,13 @@
(((x) >> 8) & 0x0000ff00) | \
(((x) << 8) & 0x00ff0000) | \
(((x) << 24) & 0xff000000))
+#define UIMAGE_MAGIC(x) (x)
#else
#define ZIMAGE_MAGIC(x) (x)
+#define UIMAGE_MAGIC(x) ((((x) >> 24) & 0x000000ff) | \
+ (((x) >> 8) & 0x0000ff00) | \
+ (((x) << 8) & 0x00ff0000) | \
+ (((x) << 24) & 0xff000000))
#endif
#define ARM_ZIMAGE_MAGIC1 ZIMAGE_MAGIC(0x016f2818)
@@ -17,6 +22,12 @@
#define ARM_ZIMAGE_MAGIC3 ZIMAGE_MAGIC(0x5a534c4b)
#define ARM_ZIMAGE_MAGIC4 ZIMAGE_MAGIC(0x5a534344)
+#define ARM_UIMAGE_MAGIC UIMAGE_MAGIC(0x27051956)
+#define ARM_UIMAGE_NAME_LEN 32
+#define ARM_UIMAGE_TYPE_KERNEL 2
+#define ARM_UIMAGE_TYPE_KERNEL_NOLOAD 14
+#define ARM_UIMAGE_ARCH_ARM 2
+
#ifndef __ASSEMBLY__
#include <linux/types.h>
@@ -33,6 +44,21 @@ struct arm_zimage_header {
__le32 extension_tag_offset;
};
+struct arm_uimage_header {
+ __be32 magic;
+ __be32 hdr_crc;
+ __be32 time;
+ __be32 size;
+ __be32 load;
+ __be32 entry;
+ __be32 crc;
+ __u8 os;
+ __u8 arch;
+ __u8 type;
+ __u8 comp;
+ __u8 name[ARM_UIMAGE_NAME_LEN];
+};
+
struct arm_zimage_tag {
struct tag_header hdr;
union {
diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h
index 22751b5b5735..fda35afa7195 100644
--- a/arch/arm/include/asm/kexec.h
+++ b/arch/arm/include/asm/kexec.h
@@ -83,6 +83,20 @@ static inline struct page *boot_pfn_to_page(unsigned long boot_pfn)
}
#define boot_pfn_to_page boot_pfn_to_page
+#ifdef CONFIG_KEXEC_FILE
+
+extern const struct kexec_file_ops kexec_zimage_ops;
+extern const struct kexec_file_ops kexec_uimage_ops;
+
+struct kimage;
+
+extern int load_other_segments(struct kimage *image,
+ unsigned long kernel_load_addr, unsigned long kernel_size,
+ char *initrd, unsigned long initrd_len,
+ unsigned long initrd_offset, char *cmdline);
+
+#endif /* CONFIG_KEXEC_FILE */
+
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_KEXEC */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 89e5d864e923..453ecf7305e2 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -3,6 +3,7 @@
# Makefile for the linux kernel.
#
+CFLAGS_kexec_zimage.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET)
AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
@@ -56,7 +57,9 @@ obj-$(CONFIG_FUNCTION_TRACER) += entry-ftrace.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o patch.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o patch.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_zimage.o
+obj-$(CONFIG_KEXEC_FILE_UIMAGE) += kexec_uimage.o
# Main staffs in KPROBES are in arch/arm/probes/ .
obj-$(CONFIG_KPROBES) += patch.o insn.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
diff --git a/arch/arm/kernel/kexec_uimage.c b/arch/arm/kernel/kexec_uimage.c
new file mode 100644
index 000000000000..47033574e24e
--- /dev/null
+++ b/arch/arm/kernel/kexec_uimage.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Kexec uImage loader
+ *
+ * Copyright (C) 2020 Samsung Electronics
+ * Author: Łukasz Stelmach <l.stelmach@samsung.com>
+ */
+
+#define pr_fmt(fmt) "kexec_file(uImage): " fmt
+
+#include <asm/image.h>
+#include <linux/crc32.h>
+#include <linux/err.h>
+#include <linux/kexec.h>
+
+#define crc32_ones(crc, buf, len) \
+ (crc32(crc ^ 0xffffffff, buf, len) ^ 0xffffffff)
+
+static int uimage_probe(const char *uimage_buf, unsigned long uimage_len)
+{
+ const struct arm_uimage_header *h =
+ (struct arm_uimage_header *) uimage_buf;
+ struct arm_uimage_header uhdr;
+ unsigned long zoff = sizeof(struct arm_uimage_header);
+ uint32_t crc;
+
+ if (h->magic != ARM_UIMAGE_MAGIC)
+ return -EINVAL;
+
+ if (h->type != ARM_UIMAGE_TYPE_KERNEL &&
+ h->type != ARM_UIMAGE_TYPE_KERNEL_NOLOAD){
+ pr_debug("Invalid image type: %d\n", h->type);
+ return -EINVAL;
+ }
+
+ if (h->arch != ARM_UIMAGE_ARCH_ARM) {
+ pr_debug("Invalidy image arch: %d\n", h->arch);
+ return -EINVAL;
+ }
+
+ memcpy((char *)&uhdr, h, sizeof(uhdr));
+ crc = be32_to_cpu(uhdr.hdr_crc);
+ uhdr.hdr_crc = 0;
+
+ if (crc32_ones(0, (char *)&uhdr, sizeof(uhdr)) != crc) {
+ pr_debug("Corrupt header, CRC do not match\n");
+ return -EINVAL;
+ }
+
+ crc = be32_to_cpu(uhdr.crc);
+ if (crc32_ones(0, uimage_buf + zoff, uimage_len - zoff) != crc) {
+ pr_debug("Corrupt zImage, CRC do not match\n");
+ return -EINVAL;
+ }
+
+ return kexec_zimage_ops.probe(uimage_buf + zoff,
+ uimage_len - zoff);
+}
+
+static void *uimage_load(struct kimage *image,
+ char *uimage, unsigned long uimage_len,
+ char *initrd, unsigned long initrd_len,
+ char *cmdline, unsigned long cmdline_len)
+{
+ const struct arm_uimage_header *h =
+ (struct arm_uimage_header *) uimage;
+ unsigned long zimage_offset = sizeof(struct arm_uimage_header);
+
+ pr_debug("Loading uImage");
+ return kexec_zimage_ops.load(image,
+ uimage + zimage_offset,
+ uimage_len - zimage_offset,
+ initrd, initrd_len,
+ cmdline, cmdline_len);
+}
+
+const struct kexec_file_ops kexec_uimage_ops = {
+ .probe = uimage_probe,
+ .load = uimage_load,
+};
diff --git a/arch/arm/kernel/kexec_zimage.c b/arch/arm/kernel/kexec_zimage.c
new file mode 100644
index 000000000000..586b623ed91d
--- /dev/null
+++ b/arch/arm/kernel/kexec_zimage.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Kexec zImage loader
+ *
+ * Copyright (C) 2016-2018 Russel King
+ * Copyright (C) 2020 Samsung Electronics
+ * Authors:
+ * Łukasz Stelmach <l.stelmach@samsung.com>
+ * Russell King <rmk+kernel@armlinux.org.uk>
+ */
+
+#define pr_fmt(fmt) "kexec_file(zImage): " fmt
+
+#include <asm/image.h>
+#include <asm/unaligned.h>
+#include <linux/err.h>
+#include <linux/kexec.h>
+#include <linux/memblock.h>
+
+#define byte_size(t) ((t)->hdr.size << 2)
+
+/*
+ * This function and several pieces below have been taken from
+ * kexec-tools/kexec/arch/arm/kexec-zImage-arm.c
+ */
+static const void *find_extension_tag(const char *buf,
+ unsigned long len,
+ uint32_t tag_id)
+{
+ const struct arm_zimage_header *h = (const struct arm_zimage_header *)buf;
+ const struct arm_zimage_tag *tag;
+ uint32_t offset, size;
+ uint32_t max = len - sizeof(struct tag_header);
+
+ if (len < sizeof(*h) ||
+ h->magic != ARM_ZIMAGE_MAGIC1 ||
+ h->magic2 != ARM_ZIMAGE_MAGIC2)
+ return NULL;
+
+ for (offset = h->extension_tag_offset;
+ (tag = (void *)(buf + offset)) != NULL &&
+ offset < max &&
+ (size = le32_to_cpu(byte_size(tag))) != 0 &&
+ offset + size < len;
+ offset += size) {
+ pr_debug(" offset 0x%08x tag 0x%08x size %u\n",
+ offset, le32_to_cpu(tag->hdr.tag), size);
+ if (tag->hdr.tag == tag_id)
+ return tag;
+ }
+
+ return NULL;
+}
+
+static int zimage_probe(const char *kernel_buf, unsigned long kernel_len)
+{
+ const struct arm_zimage_header *h =
+ (struct arm_zimage_header *)(kernel_buf);
+
+ if (!h || (kernel_len < sizeof(*h)))
+ return -EINVAL;
+
+ if ((h->magic != ARM_ZIMAGE_MAGIC1) ||
+ (h->magic2 != ARM_ZIMAGE_MAGIC2))
+ return -EINVAL;
+
+ return 0;
+}
+
+
+#if defined(DEBUG)
+#define debug_offsets() ({ \
+ pr_debug("Image offsets:\n"); \
+ pr_debug(" kernel 0x%08lx 0x%08lx\n", kernel_offset, kernel_len); \
+ pr_debug(" zimage 0x%08lx 0x%08lx\n", zimage_offset, zimage_len); \
+ pr_debug(" initrd 0x%08lx 0x%08lx\n", initrd_offset, initrd_len); \
+})
+#else
+#define debug_offsets()
+#endif
+
+static void *zimage_load(struct kimage *image,
+ char *zimage, unsigned long zimage_len,
+ char *initrd, unsigned long initrd_len,
+ char *cmdline, unsigned long cmdline_len)
+{
+ struct arm_zimage_header *h;
+ struct kexec_buf kbuf;
+ struct kexec_segment *zimage_segment;
+ const struct arm_zimage_tag *tag;
+ int ret = -EINVAL;
+
+ unsigned long zimage_mem = 0x20000; /* malloc 64kB + stack 4 kB + some bss */
+ unsigned long kernel_len = zimage_len * 5; /* 5:1 compression */
+ unsigned long kernel_offset = memblock_start_of_DRAM() +
+ ALIGN(TEXT_OFFSET, PAGE_SIZE);
+ unsigned long zimage_offset = kernel_offset +
+ ALIGN(kernel_len, PAGE_SIZE);
+ unsigned long initrd_offset = zimage_offset +
+ ALIGN(zimage_len + zimage_mem, PAGE_SIZE);
+
+ if (image->type == KEXEC_TYPE_CRASH) {
+ kernel_offset += crashk_res.start;
+ zimage_offset += crashk_res.start;
+ initrd_offset += crashk_res.start;
+ }
+ debug_offsets();
+
+ h = (struct arm_zimage_header *)zimage;
+
+ tag = find_extension_tag(zimage, zimage_len, ZIMAGE_TAG_KRNL_SIZE);
+ if (tag) {
+ uint32_t *p = (void *)zimage +
+ le32_to_cpu(tag->u.krnl_size.size_ptr);
+ uint32_t edata_size = le32_to_cpu(get_unaligned(p));
+ uint32_t bss_size = le32_to_cpu(tag->u.krnl_size.bss_size);
+
+ kernel_len = edata_size + bss_size;
+
+ pr_debug("Decompressed kernel sizes:\n");
+ pr_debug(" text+data 0x%08lx bss 0x%08lx total 0x%08lx\n",
+ (unsigned long)edata_size,
+ (unsigned long)bss_size,
+ (unsigned long)kernel_len);
+
+ zimage_offset = kernel_offset + ALIGN(edata_size, PAGE_SIZE);
+ initrd_offset = zimage_offset +
+ max(ALIGN(zimage_len + 0x20000, PAGE_SIZE),
+ ALIGN((unsigned long)bss_size, PAGE_SIZE));
+ debug_offsets();
+ }
+
+ tag = find_extension_tag(zimage, zimage_len,
+ ZIMAGE_TAG_ZIMAGE_MEM);
+ if (tag) {
+ uint32_t zimage_mem = le32_to_cpu(tag->u.zimage_mem);
+
+ pr_debug("Decompressor requires %d bytes of memory\n", zimage_mem);
+
+ initrd_offset = max(ALIGN(zimage_offset + zimage_len + zimage_mem, PAGE_SIZE),
+ ALIGN(kernel_offset + kernel_len, PAGE_SIZE));
+ debug_offsets();
+ }
+
+ /*
+ * zImage MUST be loaded into the first 128 MiB of physical
+ * memory for proper memory detection. Should the uncompressed
+ * kernel be larger than 128 MiB, zImage relocation becomes
+ * unavoidable and it is best to rely on the relocation code.
+ */
+ if (((zimage_offset - kernel_offset) + PAGE_SIZE + 0x8000) >= SZ_128M) {
+ pr_debug("The kernel is too big (%ld MiB) to avoid "
+ "zImage relocation. Loading zimage at 0x%08lx\n",
+ ((zimage_offset - kernel_offset) >> 20),
+ kernel_offset);
+ zimage_offset = kernel_offset;
+ }
+
+ kbuf.image = image;
+ kbuf.top_down = false;
+
+ kbuf.buf_min = zimage_offset;
+ kbuf.buf_max = ULONG_MAX;
+ kbuf.buffer = zimage;
+ kbuf.bufsz = zimage_len;
+ kbuf.buf_align = PAGE_SIZE;
+
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+ kbuf.memsz = zimage_len;
+
+ ret = kexec_add_buffer(&kbuf);
+ if (ret)
+ return ERR_PTR(ret);
+
+ pr_debug("Loaded zImage at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+ kbuf.mem, kbuf.bufsz, kbuf.memsz);
+
+ initrd_offset += kbuf.mem - zimage_offset;
+ debug_offsets();
+
+ zimage_segment = &image->segment[image->nr_segments - 1];
+ image->start = zimage_segment->mem;
+
+ ret = load_other_segments(image,
+ zimage_segment->mem, zimage_segment->memsz,
+ initrd, initrd_len, initrd_offset,
+ cmdline);
+ return ERR_PTR(ret);
+}
+
+const struct kexec_file_ops kexec_zimage_ops = {
+ .probe = zimage_probe,
+ .load = zimage_load,
+};
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index c10a2dfd53d1..2e4780efabb4 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -93,10 +93,13 @@ int machine_kexec_prepare(struct kimage *image)
current_segment->memsz))
return -EINVAL;
- err = get_user(header, (__be32*)current_segment->buf);
- if (err)
- return err;
-
+ if (image->file_mode) {
+ header = *(__be32 *)current_segment->buf;
+ } else {
+ err = get_user(header, (__be32 *)current_segment->buf);
+ if (err)
+ return err;
+ }
if (header == cpu_to_be32(OF_DT_HEADER))
image->arch.kernel_r2 = current_segment->mem;
}
diff --git a/arch/arm/kernel/machine_kexec_file.c b/arch/arm/kernel/machine_kexec_file.c
new file mode 100644
index 000000000000..a632d351602c
--- /dev/null
+++ b/arch/arm/kernel/machine_kexec_file.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * kexec_file for arm
+ *
+ * Copyright (C) 2018 Linaro Limited
+ * Copyright (C) 2020 Samsung Electronics
+ * Authors:
+ * AKASHI Takahiro <takahiro.akashi@linaro.org>
+ * Łukasz Stelmach <l.stelmach@samsung.com>
+ *
+ */
+
+#define pr_fmt(fmt) "kexec_file: " fmt
+
+#include <linux/kexec.h>
+#include <linux/libfdt.h>
+#include <linux/of_fdt.h>
+#include <linux/random.h>
+
+/* relevant device tree properties */
+#define FDT_PROP_INITRD_START "linux,initrd-start"
+#define FDT_PROP_INITRD_END "linux,initrd-end"
+#define FDT_PROP_BOOTARGS "bootargs"
+#define FDT_PROP_RNG_SEED "rng-seed"
+
+static int setup_dtb(struct kimage *image,
+ unsigned long initrd_load_addr, unsigned long initrd_len,
+ char *cmdline, void *dtb)
+{
+ int off, ret;
+
+ ret = fdt_path_offset(dtb, "/chosen");
+ if (ret < 0)
+ goto out;
+
+ off = ret;
+
+ /* add bootargs */
+ if (cmdline) {
+ ret = fdt_setprop_string(dtb, off, FDT_PROP_BOOTARGS, cmdline);
+ if (ret)
+ goto out;
+ } else {
+ ret = fdt_delprop(dtb, off, FDT_PROP_BOOTARGS);
+ if (ret && (ret != -FDT_ERR_NOTFOUND))
+ goto out;
+ }
+
+ /* add initrd-* */
+ if (initrd_load_addr) {
+ ret = fdt_setprop_u64(dtb, off, FDT_PROP_INITRD_START,
+ initrd_load_addr);
+ if (ret)
+ goto out;
+
+ ret = fdt_setprop_u64(dtb, off, FDT_PROP_INITRD_END,
+ initrd_load_addr + initrd_len);
+ if (ret)
+ goto out;
+ } else {
+ ret = fdt_delprop(dtb, off, FDT_PROP_INITRD_START);
+ if (ret && (ret != -FDT_ERR_NOTFOUND))
+ goto out;
+
+ ret = fdt_delprop(dtb, off, FDT_PROP_INITRD_END);
+ if (ret && (ret != -FDT_ERR_NOTFOUND))
+ goto out;
+ }
+
+ /* add rng-seed */
+ if (rng_is_initialized()) {
+ char seed[128];
+ get_random_bytes(seed, sizeof(seed));
+
+ ret = fdt_setprop(dtb, off, FDT_PROP_RNG_SEED,
+ seed, sizeof(seed));
+ if (ret)
+ goto out;
+ } else {
+ pr_notice("RNG is not initialised: omitting \"%s\" property\n",
+ FDT_PROP_RNG_SEED);
+ ret = 0;
+ }
+
+out:
+ if (ret)
+ return (ret == -FDT_ERR_NOSPACE) ? -ENOMEM : -EINVAL;
+
+ return 0;
+}
+/*
+ * More space needed so that we can add initrd, bootargs and kaslr-seed.
+ */
+#define DTB_EXTRA_SPACE 0x1000
+
+static int create_dtb(struct kimage *image,
+ unsigned long initrd_load_addr, unsigned long initrd_len,
+ char *cmdline, void **dtb)
+{
+ void *buf;
+ size_t buf_size;
+ size_t cmdline_len;
+ int ret;
+
+ cmdline_len = cmdline ? strlen(cmdline) : 0;
+ buf_size = fdt_totalsize(initial_boot_params)
+ + cmdline_len + DTB_EXTRA_SPACE;
+
+ for (;;) {
+ buf = vmalloc(buf_size);
+ if (!buf)
+ return -ENOMEM;
+
+ /* duplicate a device tree blob */
+ ret = fdt_open_into(initial_boot_params, buf, buf_size);
+ if (ret)
+ return -EINVAL;
+
+ ret = setup_dtb(image, initrd_load_addr, initrd_len,
+ cmdline, buf);
+ if (ret) {
+ vfree(buf);
+ if (ret == -ENOMEM) {
+ /* unlikely, but just in case */
+ buf_size += DTB_EXTRA_SPACE;
+ continue;
+ } else {
+ return ret;
+ }
+ }
+
+ /* trim it */
+ fdt_pack(buf);
+ *dtb = buf;
+
+ return 0;
+ }
+}
+
+int load_other_segments(struct kimage *image,
+ unsigned long zimage_load_addr,
+ unsigned long zimage_len,
+ char *initrd,
+ unsigned long initrd_len,
+ unsigned long initrd_offset,
+ char *cmdline)
+{
+ struct kexec_buf kbuf;
+ void *dtb = NULL;
+ unsigned long initrd_load_addr = 0;
+ unsigned long dtb_len;
+ int ret = 0;
+
+ kbuf.image = image;
+ /* not allocate anything below the kernel */
+ kbuf.buf_min = initrd_offset;
+ if (initrd) {
+ kbuf.buffer = initrd;
+ kbuf.bufsz = initrd_len;
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+ kbuf.memsz = initrd_len;
+ kbuf.buf_align = PAGE_SIZE;
+ kbuf.buf_max = ULONG_MAX;
+ kbuf.top_down = false;
+
+ ret = kexec_add_buffer(&kbuf);
+ if (ret)
+ goto out_err;
+
+ pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+ kbuf.mem, kbuf.bufsz, kbuf.memsz);
+
+ initrd_load_addr = kbuf.mem;
+ kbuf.buf_min = initrd_load_addr + kbuf.memsz;
+ }
+
+ /* load dtb */
+ ret = create_dtb(image, initrd_load_addr, initrd_len, cmdline, &dtb);
+ if (ret) {
+ pr_err("Preparing for new dtb failed\n");
+ goto out_err;
+ }
+
+ dtb_len = fdt_totalsize(dtb);
+ kbuf.buffer = dtb;
+ kbuf.bufsz = dtb_len;
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+ kbuf.memsz = dtb_len;
+ kbuf.buf_align = PAGE_SIZE;
+ kbuf.buf_max = ULONG_MAX;
+ kbuf.top_down = false;
+
+ ret = kexec_add_buffer(&kbuf);
+ if (ret)
+ goto out_err;
+
+ pr_debug("Loaded dtb at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+ kbuf.mem, kbuf.bufsz, kbuf.memsz);
+ return 0;
+out_err:
+ vfree(dtb);
+ return ret;
+}
+
+const struct kexec_file_ops * const kexec_file_loaders[] = {
+#ifdef CONFIG_KEXEC_FILE_UIMAGE
+ &kexec_uimage_ops,
+#endif
+ &kexec_zimage_ops,
+ NULL
+};
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v9 9/9] mtd: rawnand: Move the user input parsing bits to the ECC framework
From: Boris Brezillon @ 2020-06-02 16:18 UTC (permalink / raw)
To: Miquel Raynal
Cc: Vignesh Raghavendra, Tudor Ambarus, Julien Su, Richard Weinberger,
linux-mtd, Thomas Petazzoni, Mason Yang, linux-arm-kernel
In-Reply-To: <20200602143124.29553-10-miquel.raynal@bootlin.com>
On Tue, 2 Jun 2020 16:31:24 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> Many helpers are generic to all NAND chips, they should not be
> restricted to be only used by raw NAND controller drivers. They might
> later be used by generic ECC engines and SPI-NAND devices as well so
> move them into a more generic place.
>
> To avoid moving all the raw NAND core "history" into the generic NAND
> layer, we already moved certain bits into legacy helpers in the raw
> NAND core to ensure backward compatibility.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
> drivers/mtd/nand/ecc.c | 138 +++++++++++++++++
> drivers/mtd/nand/raw/atmel/nand-controller.c | 3 +-
> drivers/mtd/nand/raw/denali.c | 3 +
> drivers/mtd/nand/raw/nand_base.c | 150 ++-----------------
> drivers/mtd/nand/raw/sunxi_nand.c | 3 +-
> drivers/mtd/nand/raw/tegra_nand.c | 5 +-
> include/linux/mtd/nand.h | 7 +
> include/linux/mtd/rawnand.h | 1 -
> 8 files changed, 166 insertions(+), 144 deletions(-)
>
> diff --git a/drivers/mtd/nand/ecc.c b/drivers/mtd/nand/ecc.c
> index ad08a047dfc5..1ac7aaa6c6c2 100644
> --- a/drivers/mtd/nand/ecc.c
> +++ b/drivers/mtd/nand/ecc.c
> @@ -328,6 +328,144 @@ const struct mtd_ooblayout_ops *nand_get_large_page_hamming_ooblayout(void)
> }
> EXPORT_SYMBOL_GPL(nand_get_large_page_hamming_ooblayout);
>
> +static enum nand_ecc_engine_type
> +of_get_nand_ecc_engine_type(struct device_node *np)
> +{
> + return NAND_ECC_ENGINE_TYPE_INVALID;
> +}
> +
> +static const char * const nand_ecc_placement[] = {
> + [NAND_ECC_PLACEMENT_OOB] = "oob",
> + [NAND_ECC_PLACEMENT_INTERLEAVED] = "interleaved",
> +};
> +
> +enum nand_ecc_placement of_get_nand_ecc_placement(struct device_node *np)
> +{
> + enum nand_ecc_placement placement;
> + const char *pm;
> + int err;
> +
> + err = of_property_read_string(np, "nand-ecc-placement", &pm);
> + if (!err) {
> + for (placement = NAND_ECC_PLACEMENT_OOB;
> + placement < ARRAY_SIZE(nand_ecc_placement); placement++) {
> + if (!strcasecmp(pm, nand_ecc_placement[placement]))
> + return placement;
> + }
> + }
> +
> + return NAND_ECC_PLACEMENT_UNKNOWN;
> +}
> +
> +static const char * const nand_ecc_algos[] = {
> + [NAND_ECC_ALGO_HAMMING] = "hamming",
> + [NAND_ECC_ALGO_BCH] = "bch",
> + [NAND_ECC_ALGO_RS] = "rs",
Can we use spaces instead of tabs, as done for nand_ecc_placement?
> +};
> +
> +static enum nand_ecc_algo of_get_nand_ecc_algo(struct device_node *np)
> +{
> + enum nand_ecc_algo ecc_algo;
> + const char *pm;
> + int err;
> +
> + err = of_property_read_string(np, "nand-ecc-algo", &pm);
> + if (!err) {
> + for (ecc_algo = NAND_ECC_ALGO_HAMMING;
> + ecc_algo < ARRAY_SIZE(nand_ecc_algos);
> + ecc_algo++) {
> + if (!strcasecmp(pm, nand_ecc_algos[ecc_algo]))
> + return ecc_algo;
> + }
> + }
> +
> + return NAND_ECC_ALGO_UNKNOWN;
> +}
> +
> +static int of_get_nand_ecc_step_size(struct device_node *np)
> +{
> + int ret;
> + u32 val;
> +
> + ret = of_property_read_u32(np, "nand-ecc-step-size", &val);
> + return ret ? ret : val;
> +}
> +
> +static int of_get_nand_ecc_strength(struct device_node *np)
> +{
> + int ret;
> + u32 val;
> +
> + ret = of_property_read_u32(np, "nand-ecc-strength", &val);
> + return ret ? ret : val;
> +}
> +
> +static inline bool of_get_nand_ecc_maximize(struct device_node *np)
> +{
> + return of_property_read_bool(np, "nand-ecc-maximize");
> +}
> +
> +void nand_ecc_read_user_conf(struct nand_device *nand)
> +{
> + struct device_node *dn = nanddev_get_of_node(nand);
> + int strength, size;
> +
> + nand->ecc.user_conf.engine_type = of_get_nand_ecc_engine_type(dn);
> + nand->ecc.user_conf.algo = of_get_nand_ecc_algo(dn);
> + nand->ecc.user_conf.placement = of_get_nand_ecc_placement(dn);
> +
> + strength = of_get_nand_ecc_strength(dn);
> + if (strength >= 0)
> + nand->ecc.user_conf.strength = strength;
> +
> + size = of_get_nand_ecc_step_size(dn);
> + if (size >= 0)
> + nand->ecc.user_conf.step_size = size;
> +
> + if (of_get_nand_ecc_maximize(dn))
> + nand->ecc.user_conf.flags |= NAND_ECC_MAXIMIZE;
> +}
> +EXPORT_SYMBOL(nand_ecc_read_user_conf);
> +
> +/**
> + * nand_ecc_correction_is_enough - Check if the chip configuration meets the
> + * datasheet requirements.
> + *
> + * @nand: Device to check
> + *
> + * If our configuration corrects A bits per B bytes and the minimum
> + * required correction level is X bits per Y bytes, then we must ensure
> + * both of the following are true:
> + *
> + * (1) A / B >= X / Y
> + * (2) A >= X
> + *
> + * Requirement (1) ensures we can correct for the required bitflip density.
> + * Requirement (2) ensures we can correct even when all bitflips are clumped
> + * in the same sector.
> + */
> +bool nand_ecc_correction_is_enough(struct nand_device *nand)
nand_ecc_is_strong_enough() ?
> +{
> + const struct nand_ecc_props *reqs = nanddev_get_ecc_requirements(nand);
> + const struct nand_ecc_props *conf = nanddev_get_ecc_conf(nand);
> + struct mtd_info *mtd = nanddev_to_mtd(nand);
> + int corr, ds_corr;
> +
> + if (conf->step_size == 0 || reqs->step_size == 0)
> + /* Not enough information */
> + return true;
> +
> + /*
> + * We get the number of corrected bits per page to compare
> + * the correction density.
> + */
> + corr = (mtd->writesize * conf->strength) / conf->step_size;
> + ds_corr = (mtd->writesize * reqs->strength) / reqs->step_size;
> +
> + return corr >= ds_corr && conf->strength >= reqs->strength;
> +}
> +EXPORT_SYMBOL(nand_ecc_correction_is_enough);
> +
> MODULE_LICENSE("GPL");
> MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
> MODULE_DESCRIPTION("Generic ECC engine");
> diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
> index 08df7f23b859..39d8fe15b8ab 100644
> --- a/drivers/mtd/nand/raw/atmel/nand-controller.c
> +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
> @@ -1046,6 +1046,7 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip)
> const struct nand_ecc_props *requirements =
> nanddev_get_ecc_requirements(&chip->base);
> struct mtd_info *mtd = nand_to_mtd(chip);
> + struct nand_device *nanddev = mtd_to_nanddev(mtd);
> struct atmel_nand *nand = to_atmel_nand(chip);
> struct atmel_nand_controller *nc;
> struct atmel_pmecc_user_req req;
> @@ -1070,7 +1071,7 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip)
> chip->ecc.size = val;
> }
>
> - if (chip->ecc.options & NAND_ECC_MAXIMIZE)
> + if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE)
> req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH;
I'd prefer to have that done in 2 steps:
1/ move/duplicate definitions found in rawnand.h
2/ patch rawnand code to finally use the nanddev->ecc.user_conf object
for the ECC config.
> else if (chip->ecc.strength)
> req.ecc.strength = chip->ecc.strength;
> diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
> index a6a6464974ec..51bc014ebc0a 100644
> --- a/drivers/mtd/nand/raw/denali.c
> +++ b/drivers/mtd/nand/raw/denali.c
> @@ -1181,6 +1181,7 @@ int denali_chip_init(struct denali_controller *denali,
> {
> struct nand_chip *chip = &dchip->chip;
> struct mtd_info *mtd = nand_to_mtd(chip);
> + struct nand_device *nanddev = mtd_to_nanddev(mtd);
> struct denali_chip *dchip2;
> int i, j, ret;
>
> @@ -1248,6 +1249,8 @@ int denali_chip_init(struct denali_controller *denali,
>
> mtd_set_ooblayout(mtd, &denali_ooblayout_ops);
>
> + nanddev->ecc.user_conf.flags |= NAND_ECC_MAXIMIZE;
> +
Is that correct? I don't find the
chip->ecc.options |= NAND_ECC_MAXIMIZE;
removal that this line is replacing.
> ret = nand_scan(chip, dchip->nsels);
> if (ret)
> return ret;
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index afc3506468ba..036e88cb52a1 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -4854,17 +4854,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
> return ret;
> }
>
> -static const char * const nand_ecc_placement[] = {
> - [NAND_ECC_PLACEMENT_OOB] = "oob",
> - [NAND_ECC_PLACEMENT_INTERLEAVED] = "interleaved",
> -};
> -
> -static enum nand_ecc_engine_type
> -of_get_nand_ecc_engine_type(struct device_node *np)
> -{
> - return NAND_ECC_ENGINE_TYPE_INVALID;
> -}
> -
> static enum nand_ecc_engine_type
> of_get_rawnand_ecc_engine_type_legacy(struct device_node *np)
> {
> @@ -4916,24 +4905,6 @@ of_get_rawnand_ecc_engine_type_legacy(struct device_node *np)
> return NAND_ECC_ENGINE_TYPE_INVALID;
> }
>
> -enum nand_ecc_placement of_get_nand_ecc_placement(struct device_node *np)
> -{
> - enum nand_ecc_placement placement;
> - const char *pm;
> - int err;
> -
> - err = of_property_read_string(np, "nand-ecc-placement", &pm);
> - if (!err) {
> - for (placement = NAND_ECC_PLACEMENT_OOB;
> - placement < ARRAY_SIZE(nand_ecc_placement); placement++) {
> - if (!strcasecmp(pm, nand_ecc_placement[placement]))
> - return placement;
> - }
> - }
> -
> - return NAND_ECC_PLACEMENT_UNKNOWN;
> -}
> -
> enum nand_ecc_placement
> of_get_rawnand_ecc_placement_legacy(struct device_node *np)
> {
> @@ -4949,31 +4920,6 @@ of_get_rawnand_ecc_placement_legacy(struct device_node *np)
> return NAND_ECC_PLACEMENT_UNKNOWN;
> }
>
> -static const char * const nand_ecc_algos[] = {
> - [NAND_ECC_ALGO_HAMMING] = "hamming",
> - [NAND_ECC_ALGO_BCH] = "bch",
> - [NAND_ECC_ALGO_RS] = "rs",
> -};
> -
> -static enum nand_ecc_algo of_get_nand_ecc_algo(struct device_node *np)
> -{
> - enum nand_ecc_algo ecc_algo;
> - const char *pm;
> - int err;
> -
> - err = of_property_read_string(np, "nand-ecc-algo", &pm);
> - if (!err) {
> - for (ecc_algo = NAND_ECC_ALGO_HAMMING;
> - ecc_algo < ARRAY_SIZE(nand_ecc_algos);
> - ecc_algo++) {
> - if (!strcasecmp(pm, nand_ecc_algos[ecc_algo]))
> - return ecc_algo;
> - }
> - }
> -
> - return NAND_ECC_ALGO_UNKNOWN;
> -}
> -
> static enum nand_ecc_algo of_get_rawnand_ecc_algo_legacy(struct device_node *np)
> {
> const char *pm;
> @@ -4990,48 +4936,10 @@ static enum nand_ecc_algo of_get_rawnand_ecc_algo_legacy(struct device_node *np)
> return NAND_ECC_ALGO_UNKNOWN;
> }
>
> -static int of_get_nand_ecc_step_size(struct device_node *np)
> -{
> - int ret;
> - u32 val;
> -
> - ret = of_property_read_u32(np, "nand-ecc-step-size", &val);
> - return ret ? ret : val;
> -}
> -
> -static int of_get_nand_ecc_strength(struct device_node *np)
> -{
> - int ret;
> - u32 val;
> -
> - ret = of_property_read_u32(np, "nand-ecc-strength", &val);
> - return ret ? ret : val;
> -}
> -
> -static void nand_ecc_read_user_conf(struct nand_chip *chip)
> -{
> - struct device_node *dn = nand_get_flash_node(chip);
> - struct nand_device *nand = &chip->base;
> - int strength, size;
> -
> - nand->ecc.user_conf.engine_type = of_get_nand_ecc_engine_type(dn);
> - nand->ecc.user_conf.algo = of_get_nand_ecc_algo(dn);
> - nand->ecc.user_conf.placement = of_get_nand_ecc_placement(dn);
> -
> - strength = of_get_nand_ecc_strength(dn);
> - if (strength >= 0)
> - nand->ecc.user_conf.strength = strength;
> -
> - size = of_get_nand_ecc_step_size(dn);
> - if (size >= 0)
> - nand->ecc.user_conf.step_size = size;
> -}
> -
> static void rawnand_ecc_read_legacy_user_conf(struct nand_chip *chip)
> {
> struct device_node *dn = nand_get_flash_node(chip);
> - struct nand_device *nand = &chip->base;
> - struct nand_ecc_props *user_conf = &nand->ecc.user_conf;
> + struct nand_ecc_props *user_conf = &chip->base.ecc.user_conf;
>
> if (user_conf->engine_type != NAND_ECC_ENGINE_TYPE_INVALID)
> user_conf->engine_type = of_get_rawnand_ecc_engine_type_legacy(dn);
> @@ -5081,10 +4989,7 @@ static int rawnand_dt_init(struct nand_chip *chip)
> if (of_get_nand_on_flash_bbt(dn))
> chip->bbt_options |= NAND_BBT_USE_FLASH;
>
> - if (of_property_read_bool(dn, "nand-ecc-maximize"))
> - chip->ecc.options |= NAND_ECC_MAXIMIZE;
> -
> - nand_ecc_read_user_conf(chip);
> + nand_ecc_read_user_conf(nand);
> rawnand_ecc_read_legacy_user_conf(chip);
>
> /*
> @@ -5214,6 +5119,7 @@ static void nand_scan_ident_cleanup(struct nand_chip *chip)
> static int nand_set_ecc_soft_ops(struct nand_chip *chip)
> {
> struct mtd_info *mtd = nand_to_mtd(chip);
> + struct nand_device *nanddev = mtd_to_nanddev(mtd);
> struct nand_ecc_ctrl *ecc = &chip->ecc;
>
> if (WARN_ON(ecc->engine_type != NAND_ECC_ENGINE_TYPE_SOFT))
> @@ -5289,7 +5195,7 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
> * used.
> */
> if (mtd->ooblayout == nand_get_large_page_ooblayout() &&
> - ecc->options & NAND_ECC_MAXIMIZE) {
> + nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE) {
> int steps, bytes;
>
> /* Always prefer 1k blocks over 512bytes ones */
> @@ -5529,11 +5435,12 @@ nand_maximize_ecc(struct nand_chip *chip,
> * @caps: ECC engine caps info structure
> * @oobavail: OOB size that the ECC engine can use
> *
> - * Choose the ECC configuration according to following logic
> + * Choose the ECC configuration according to following logic.
> *
> * 1. If both ECC step size and ECC strength are already set (usually by DT)
> * then check if it is supported by this controller.
> - * 2. If NAND_ECC_MAXIMIZE is set, then select maximum ECC strength.
> + * 2. If the user provided the nand-ecc-maximize property, then select maximum
> + * ECC strength.
> * 3. Otherwise, try to match the ECC step size and ECC strength closest
> * to the chip's requirement. If available OOB size can't fit the chip
> * requirement then fallback to the maximum ECC step size and ECC strength.
> @@ -5544,6 +5451,7 @@ int nand_ecc_choose_conf(struct nand_chip *chip,
> const struct nand_ecc_caps *caps, int oobavail)
> {
> struct mtd_info *mtd = nand_to_mtd(chip);
> + struct nand_device *nanddev = mtd_to_nanddev(mtd);
>
> if (WARN_ON(oobavail < 0 || oobavail > mtd->oobsize))
> return -EINVAL;
> @@ -5551,7 +5459,7 @@ int nand_ecc_choose_conf(struct nand_chip *chip,
> if (chip->ecc.size && chip->ecc.strength)
> return nand_check_ecc_caps(chip, caps, oobavail);
>
> - if (chip->ecc.options & NAND_ECC_MAXIMIZE)
> + if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE)
> return nand_maximize_ecc(chip, caps, oobavail);
>
> if (!nand_match_ecc_req(chip, caps, oobavail))
> @@ -5561,43 +5469,6 @@ int nand_ecc_choose_conf(struct nand_chip *chip,
> }
> EXPORT_SYMBOL_GPL(nand_ecc_choose_conf);
>
> -/*
> - * Check if the chip configuration meet the datasheet requirements.
> -
> - * If our configuration corrects A bits per B bytes and the minimum
> - * required correction level is X bits per Y bytes, then we must ensure
> - * both of the following are true:
> - *
> - * (1) A / B >= X / Y
> - * (2) A >= X
> - *
> - * Requirement (1) ensures we can correct for the required bitflip density.
> - * Requirement (2) ensures we can correct even when all bitflips are clumped
> - * in the same sector.
> - */
> -static bool nand_ecc_strength_good(struct nand_chip *chip)
> -{
> - struct mtd_info *mtd = nand_to_mtd(chip);
> - struct nand_ecc_ctrl *ecc = &chip->ecc;
> - const struct nand_ecc_props *requirements =
> - nanddev_get_ecc_requirements(&chip->base);
> - int corr, ds_corr;
> -
> - if (ecc->size == 0 || requirements->step_size == 0)
> - /* Not enough information */
> - return true;
> -
> - /*
> - * We get the number of corrected bits per page to compare
> - * the correction density.
> - */
> - corr = (mtd->writesize * ecc->strength) / ecc->size;
> - ds_corr = (mtd->writesize * requirements->strength) /
> - requirements->step_size;
> -
> - return corr >= ds_corr && ecc->strength >= requirements->strength;
> -}
> -
> static int rawnand_erase(struct nand_device *nand, const struct nand_pos *pos)
> {
> struct nand_chip *chip = container_of(nand, struct nand_chip,
> @@ -5653,6 +5524,7 @@ static const struct nand_ops rawnand_ops = {
> static int nand_scan_tail(struct nand_chip *chip)
> {
> struct mtd_info *mtd = nand_to_mtd(chip);
> + struct nand_device *nanddev = mtd_to_nanddev(mtd);
> struct nand_ecc_ctrl *ecc = &chip->ecc;
> int ret, i;
>
> @@ -5880,7 +5752,7 @@ static int nand_scan_tail(struct nand_chip *chip)
> mtd->oobavail = ret;
>
> /* ECC sanity check: warn if it's too weak */
> - if (!nand_ecc_strength_good(chip))
> + if (!nand_ecc_correction_is_enough(nanddev))
Can we do this rename separately?
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v9 9/9] mtd: rawnand: Move the user input parsing bits to the ECC framework
From: Boris Brezillon @ 2020-06-02 16:21 UTC (permalink / raw)
To: Miquel Raynal
Cc: Vignesh Raghavendra, Tudor Ambarus, Julien Su, Richard Weinberger,
linux-mtd, Thomas Petazzoni, Mason Yang, linux-arm-kernel
In-Reply-To: <20200602143124.29553-10-miquel.raynal@bootlin.com>
On Tue, 2 Jun 2020 16:31:24 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> +void nand_ecc_read_user_conf(struct nand_device *nand)
This function is not introduced in this patch, but I'm commenting here.
Looks like it only operates on an OF node, so how about naming it
of_get_nand_ecc_config().
> +{
> + struct device_node *dn = nanddev_get_of_node(nand);
> + int strength, size;
> +
> + nand->ecc.user_conf.engine_type = of_get_nand_ecc_engine_type(dn);
> + nand->ecc.user_conf.algo = of_get_nand_ecc_algo(dn);
> + nand->ecc.user_conf.placement = of_get_nand_ecc_placement(dn);
> +
> + strength = of_get_nand_ecc_strength(dn);
> + if (strength >= 0)
> + nand->ecc.user_conf.strength = strength;
> +
> + size = of_get_nand_ecc_step_size(dn);
> + if (size >= 0)
> + nand->ecc.user_conf.step_size = size;
> +
> + if (of_get_nand_ecc_maximize(dn))
> + nand->ecc.user_conf.flags |= NAND_ECC_MAXIMIZE;
> +}
> +EXPORT_SYMBOL(nand_ecc_read_user_conf);
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v9 9/9] mtd: rawnand: Move the user input parsing bits to the ECC framework
From: Boris Brezillon @ 2020-06-02 16:23 UTC (permalink / raw)
To: Miquel Raynal
Cc: Vignesh Raghavendra, Tudor Ambarus, Julien Su, Richard Weinberger,
linux-mtd, Thomas Petazzoni, Mason Yang, linux-arm-kernel
In-Reply-To: <20200602143124.29553-10-miquel.raynal@bootlin.com>
On Tue, 2 Jun 2020 16:31:24 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> Many helpers are generic to all NAND chips, they should not be
> restricted to be only used by raw NAND controller drivers. They might
> later be used by generic ECC engines and SPI-NAND devices as well so
> move them into a more generic place.
>
> To avoid moving all the raw NAND core "history" into the generic NAND
> layer, we already moved certain bits into legacy helpers in the raw
> NAND core to ensure backward compatibility.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
> drivers/mtd/nand/ecc.c | 138 +++++++++++++++++
> drivers/mtd/nand/raw/atmel/nand-controller.c | 3 +-
> drivers/mtd/nand/raw/denali.c | 3 +
> drivers/mtd/nand/raw/nand_base.c | 150 ++-----------------
> drivers/mtd/nand/raw/sunxi_nand.c | 3 +-
> drivers/mtd/nand/raw/tegra_nand.c | 5 +-
> include/linux/mtd/nand.h | 7 +
> include/linux/mtd/rawnand.h | 1 -
> 8 files changed, 166 insertions(+), 144 deletions(-)
>
> diff --git a/drivers/mtd/nand/ecc.c b/drivers/mtd/nand/ecc.c
> index ad08a047dfc5..1ac7aaa6c6c2 100644
> --- a/drivers/mtd/nand/ecc.c
> +++ b/drivers/mtd/nand/ecc.c
> @@ -328,6 +328,144 @@ const struct mtd_ooblayout_ops *nand_get_large_page_hamming_ooblayout(void)
> }
> EXPORT_SYMBOL_GPL(nand_get_large_page_hamming_ooblayout);
>
> +static enum nand_ecc_engine_type
> +of_get_nand_ecc_engine_type(struct device_node *np)
> +{
> + return NAND_ECC_ENGINE_TYPE_INVALID;
> +}
> +
> +static const char * const nand_ecc_placement[] = {
> + [NAND_ECC_PLACEMENT_OOB] = "oob",
> + [NAND_ECC_PLACEMENT_INTERLEAVED] = "interleaved",
> +};
> +
> +enum nand_ecc_placement of_get_nand_ecc_placement(struct device_node *np)
> +{
> + enum nand_ecc_placement placement;
> + const char *pm;
> + int err;
> +
> + err = of_property_read_string(np, "nand-ecc-placement", &pm);
> + if (!err) {
> + for (placement = NAND_ECC_PLACEMENT_OOB;
> + placement < ARRAY_SIZE(nand_ecc_placement); placement++) {
> + if (!strcasecmp(pm, nand_ecc_placement[placement]))
> + return placement;
> + }
> + }
> +
> + return NAND_ECC_PLACEMENT_UNKNOWN;
> +}
> +
> +static const char * const nand_ecc_algos[] = {
> + [NAND_ECC_ALGO_HAMMING] = "hamming",
> + [NAND_ECC_ALGO_BCH] = "bch",
> + [NAND_ECC_ALGO_RS] = "rs",
> +};
> +
> +static enum nand_ecc_algo of_get_nand_ecc_algo(struct device_node *np)
> +{
> + enum nand_ecc_algo ecc_algo;
> + const char *pm;
> + int err;
> +
> + err = of_property_read_string(np, "nand-ecc-algo", &pm);
> + if (!err) {
> + for (ecc_algo = NAND_ECC_ALGO_HAMMING;
> + ecc_algo < ARRAY_SIZE(nand_ecc_algos);
> + ecc_algo++) {
> + if (!strcasecmp(pm, nand_ecc_algos[ecc_algo]))
> + return ecc_algo;
> + }
> + }
> +
> + return NAND_ECC_ALGO_UNKNOWN;
> +}
> +
> +static int of_get_nand_ecc_step_size(struct device_node *np)
> +{
> + int ret;
> + u32 val;
> +
> + ret = of_property_read_u32(np, "nand-ecc-step-size", &val);
> + return ret ? ret : val;
> +}
> +
> +static int of_get_nand_ecc_strength(struct device_node *np)
> +{
> + int ret;
> + u32 val;
> +
> + ret = of_property_read_u32(np, "nand-ecc-strength", &val);
> + return ret ? ret : val;
> +}
> +
> +static inline bool of_get_nand_ecc_maximize(struct device_node *np)
The inline is useless here, and I'm even wondering if we couldn't
inline the code of_property_read_bool() call directly.
> +{
> + return of_property_read_bool(np, "nand-ecc-maximize");
> +}
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v9 0/9] Preparation to the generic ECC engine abstraction
From: Boris Brezillon @ 2020-06-02 16:33 UTC (permalink / raw)
To: Miquel Raynal
Cc: Vignesh Raghavendra, Tudor Ambarus, Julien Su, Richard Weinberger,
linux-mtd, Thomas Petazzoni, Mason Yang, linux-arm-kernel
In-Reply-To: <20200602143124.29553-1-miquel.raynal@bootlin.com>
On Tue, 2 Jun 2020 16:31:15 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> This is a respin of the end of my previous series, just the patches which needed to be fixed.
>
> Changes in v9:
> * This time sending the additional patchs, not just the old ones with
> corrections. v8 should be ignored, sorry for the noise.
>
> Changes in v8:
> * Split "Convert generic NAND bits to ECC framework" into several peaces:
> > added two helpers
> > converted SPI-NAND then raw-NAND.
> * Fixed a comment.
> * Used the _ooblayout suffix instead of _layout.
>
>
> Miquel Raynal (9):
> mtd: nand: Create a helper to extract the ECC configuration
> mtd: spinand: Use nanddev_get_ecc_conf() when relevant
> mtd: nand: Create a helper to extract the ECC requirements
> mtd: rawnand: Use nanddev_get_ecc_requirements() when relevant
> mtd: nand: Convert generic NAND bits to use the ECC framework
> mtd: rawnand: Hide the generic OOB layout objects behind helpers
> mtd: rawnand: Write a compatibility layer
> mtd: rawnand: Move generic OOB layouts to the ECC framework
> mtd: rawnand: Move the user input parsing bits to the ECC framework
Sorry, but I keep thinking you should re-order things so we don't have
code blocks introduced and then moved around in the same patchset.
What's the point of introducing new props/helpers in rawnand if the
ultimate goal is to move them to nand.h, especially since none of the
existing rawnand drivers (or the rawnand core) need those new DT props
right now. You should really consider doing that in 3 distinct steps:
1/ Introduce ECC related fields/defs/... at the generic NAND level
2/ Patch rawnand to use those fields/new defs and deprecate the old ones
3/ Move rawnand defs/code that can be made generic and be useful to
!rawnand users
>
> drivers/mtd/nand/ecc.c | 314 ++++++++++++++
> drivers/mtd/nand/raw/Kconfig | 1 +
> drivers/mtd/nand/raw/arasan-nand-controller.c | 2 +-
> drivers/mtd/nand/raw/atmel/nand-controller.c | 15 +-
> drivers/mtd/nand/raw/brcmnand/brcmnand.c | 8 +-
> drivers/mtd/nand/raw/davinci_nand.c | 3 +-
> drivers/mtd/nand/raw/denali.c | 3 +
> drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 13 +-
> .../mtd/nand/raw/ingenic/ingenic_nand_drv.c | 6 +-
> drivers/mtd/nand/raw/marvell_nand.c | 8 +-
> drivers/mtd/nand/raw/mtk_nand.c | 6 +-
> drivers/mtd/nand/raw/nand_base.c | 395 ++++--------------
> drivers/mtd/nand/raw/nand_esmt.c | 14 +-
> drivers/mtd/nand/raw/nand_hynix.c | 43 +-
> drivers/mtd/nand/raw/nand_jedec.c | 7 +-
> drivers/mtd/nand/raw/nand_micron.c | 17 +-
> drivers/mtd/nand/raw/nand_onfi.c | 14 +-
> drivers/mtd/nand/raw/nand_samsung.c | 21 +-
> drivers/mtd/nand/raw/nand_toshiba.c | 15 +-
> drivers/mtd/nand/raw/sunxi_nand.c | 9 +-
> drivers/mtd/nand/raw/tegra_nand.c | 15 +-
> drivers/mtd/nand/raw/vf610_nfc.c | 2 +-
> drivers/mtd/nand/spi/core.c | 10 +-
> drivers/mtd/nand/spi/macronix.c | 7 +-
> drivers/mtd/nand/spi/toshiba.c | 6 +-
> include/linux/mtd/nand.h | 40 +-
> include/linux/mtd/rawnand.h | 17 +-
> 27 files changed, 587 insertions(+), 424 deletions(-)
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCHv2 0/7] Support inhibiting input devices
From: Andrzej Pietrasiewicz @ 2020-06-02 16:56 UTC (permalink / raw)
To: Dmitry Torokhov, Hans de Goede
Cc: Nick Dyer, linux-iio, Benjamin Tissoires, platform-driver-x86,
ibm-acpi-devel, Laxman Dewangan, Peter Meerwald-Stadler, kernel,
Fabio Estevam, linux-samsung-soc, Krzysztof Kozlowski,
Jonathan Hunter, linux-acpi, Kukjin Kim, NXP Linux Team,
linux-input, Len Brown, Peter Hutterer, Michael Hennerich,
Sascha Hauer, Sylvain Lemieux, Henrique de Moraes Holschuh,
Vladimir Zapolskiy, Lars-Peter Clausen, linux-tegra,
linux-arm-kernel, Barry Song, Ferruh Yigit, patches,
Rafael J . Wysocki, Thierry Reding, Sangwon Jee,
Pengutronix Kernel Team, Hartmut Knaack, Shawn Guo,
Jonathan Cameron
In-Reply-To: <20200527063430.GJ89269@dtor-ws>
Hi Dmitry,
W dniu 27.05.2020 o 08:34, Dmitry Torokhov pisze:
> On Tue, May 19, 2020 at 11:36:34AM +0200, Hans de Goede wrote:
>> Hi,
>>
>> On 5/19/20 11:02 AM, Andrzej Pietrasiewicz wrote:
>>> Hi Hans, Hi Dmitry,
>>>
>>> W dniu 18.05.2020 o 16:23, Hans de Goede pisze:
>>>> Hi,
>>>
>>> <snip>
>>>
>>>>>>>>
>>>>>>>> So I wonder what this series actually adds for functionality for
>>>>>>>> userspace which can not already be achieved this way?
>>>>>>>>
>>>>>>>> I also noticed that you keep the device open (do not call the
>>>>>>>> input_device's close callback) when inhibited and just throw away
>>>>>>>
>>>>>>> I'm not sure if I understand you correctly, it is called:
>>>>>>>
>>>>>>> +static inline void input_stop(struct input_dev *dev)
>>>>>>> +{
>>>>>>> + if (dev->poller)
>>>>>>> + input_dev_poller_stop(dev->poller);
>>>>>>> + if (dev->close)
>>>>>>> + dev->close(dev);
>>>>>>> ^^^^^^^^^^^^^^^^
>>>>>>> +static int input_inhibit(struct input_dev *dev)
>>>>>>> +{
>>>>>>> + int ret = 0;
>>>>>>> +
>>>>>>> + mutex_lock(&dev->mutex);
>>>>>>> +
>>>>>>> + if (dev->inhibited)
>>>>>>> + goto out;
>>>>>>> +
>>>>>>> + if (dev->users) {
>>>>>>> + if (dev->inhibit) {
>>>>>>> + ret = dev->inhibit(dev);
>>>>>>> + if (ret)
>>>>>>> + goto out;
>>>>>>> + }
>>>>>>> + input_stop(dev);
>>>>>>> ^^^^^^^^^^^^^^^^
>>>>>>>
>>>>>>> It will not be called when dev->users is zero, but if it is zero,
>>>>>>> then nobody has opened the device yet so there is nothing to close.
>>>>>>
>>>>>> Ah, I missed that.
>>>>>>
>>>>>> So if the device implements the inhibit call back then on
>>>>>> inhibit it will get both the inhibit and close callback called?
>>>>>>
>>>>>
>>>>> That's right. And conversely, upon uninhibit open() and uninhibit()
>>>>> callbacks will be invoked. Please note that just as with open()/close(),
>>>>> providing inhibit()/uninhibit() is optional.
>>>>
>>>> Ack.
>>>>
>>>>>> And what happens if the last user goes away and the device
>>>>>> is not inhibited?
>>>>>
>>>>> close() is called as usually.
>>>>
>>>> But not inhibit, hmm, see below.
>>>>
>>>>>> I'm trying to understand here what the difference between the 2
>>>>>> is / what the goal of having a separate inhibit callback ?
>>>>>>
>>>>>
>>>>> Drivers have very different ideas about what it means to suspend/resume
>>>>> and open/close. The optional inhibit/uninhibit callbacks are meant for
>>>>> the drivers to know that it is this particular action going on.
>>>>
>>>> So the inhibit() callback triggers the "suspend" behavior ?
>>>> But shouldn't drivers which are capable of suspending the device
>>>> always do so on close() ?
>>>>
>>>> Since your current proposal also calls close() on inhibit() I
>>>> really see little difference between an inhibit() and the last
>>>> user of the device closing it and IMHO unless there is a good
>>>> reason to actually differentiate the 2 it would be better
>>>> to only stick with the existing close() and in cases where
>>>> that does not put the device in a low-power mode yet, fix
>>>> the existing close() callback to do the low-power mode
>>>> setting instead of adding a new callback.
>>>>
>>>>> For inhibit() there's one more argument: close() does not return a value,
>>>>> so its meaning is "do some last cleanup" and as such it is not allowed
>>>>> to fail - whatever its effect is, we must deem it successful. inhibit()
>>>>> does return a value and so it is allowed to fail.
>>>>
>>>> Well, we could make close() return an error and at least in the inhibit()
>>>> case propagate that to userspace. I wonder if userspace is going to
>>>> do anything useful with that error though...
>
> It really can't do anything. Have you ever seen userspace handling
> errors from close()? And what can be done? A program is terminating, but
> the kernel says "no, you closing input device failed, you have to
> continue running indefinitely..."
>
>>>>
>>>> In my experience errors during cleanup/shutdown are best logged
>>>> (using dev_err) and otherwise ignored, so that we try to clean up
>>>> as much possible. Unless the very first step of the shutdown process
>>>> fails the device is going to be in some twilight zone state anyways
>>>> at this point we might as well try to cleanup as much as possible.
>>>
>>> What you say makes sense to me.
>>> @Dmitry?
>
> I will note here, that inhibit is closer to suspend() than to close(),
> and we do report errors for suspend(). Therefore we could conceivably
> try to handle errors if driver really wants to be fancy. But I think
> majority of cases will be quite happy with using close() and simply
> logging errors, as Hans said.
>
> That said, I think the way we should handle inhibit/uninhibit, is that
> if we have the callback defined, then we call it, and only call open and
> close if uninhibit or inhibit are _not_ defined.
>
If I understand you correctly you suggest to call either inhibit,
if provided or close, if inhibit is not provided, but not both,
that is, if both are provided then on the inhibit path only
inhibit is called. And, consequently, you suggest to call either
uninhibit or open, but not both. The rest of my mail makes this
assumption, so kindly confirm if I understand you correctly.
In my opinion this idea will not work.
The first question is should we be able to inhibit a device
which is not opened? In my opinion we should, in order to be
able to inhibit a device in anticipation without needing to
open it first.
Then what does opening (with input_open_device()) an inhibited
device mean? Should it succeed or should it fail? If it is not
the first opening then effectively it boils down to increasing
device's and handle's counters, so we can allow it to succeed.
If, however, the device is being opened for the first time,
the ->open() method wants to be called, but that somehow
contradicts the device's inhibited state. So a logical thing
to do is to either fail input_open_device() or postpone ->open()
invocation to the moment of uninhibiting - and the latter is
what the patches in this series currently do.
Failing input_open_device() because of the inhibited state is
not the right thing to do. Let me explain. Suppose that a device
is already inhibited and then a new matching handler appears
in the system. Most handlers (apm-power.c, evbug.c, input-leds.c,
mac_hid.c, sysrq.c, vt/keyboard.c and rfkill/input.c) don't create
any character devices (only evdev.c, joydev.c and mousedev.c do),
so for them it makes no sense to delay calling input_open_device()
and it is called in handler's ->connect(). If input_open_device()
now fails, we have lost the only chance for this ->connect() to
succeed.
Summarizing, IMO the uninhibit path should be calling both
->open() and ->uninhibit() (if provided), and conversely, the inhibit
path should be calling both ->inhibit() and ->close() (if provided).
What's your opinion?
Regards,
Andrzej
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v4 4/5] coresight: etm: perf: Add default sink selection to etm perf
From: Mathieu Poirier @ 2020-06-02 16:59 UTC (permalink / raw)
To: Suzuki K Poulose; +Cc: coresight, acme, linux-arm-kernel, mike.leach
In-Reply-To: <73ce6741-0361-7443-6714-56e8d64d49e1@arm.com>
On Tue, Jun 02, 2020 at 02:29:30PM +0100, Suzuki K Poulose wrote:
> On 06/02/2020 02:12 PM, Mike Leach wrote:
> > Hi Suzuki,
> >
> > On Tue, 2 Jun 2020 at 12:40, Suzuki K Poulose <suzuki.poulose@arm.com> wrote:
> > >
> > > On 05/26/2020 11:46 AM, Mike Leach wrote:
> > > > Add default sink selection to the perf trace handling in the etm driver.
> > > > Uses the select default sink infrastructure to select a sink for the perf
> > > > session, if no other sink is specified.
> > > >
> > > > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > >
> > > This patch looks fine to me as such. But please see below for some
> > > discussion on the future support for other configurations.
> > >
> > >
> > > > ---
> > > > .../hwtracing/coresight/coresight-etm-perf.c | 17 ++++++++++++++---
> > > > 1 file changed, 14 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
> > > > index 84f1dcb69827..1a3169e69bb1 100644
> > > > --- a/drivers/hwtracing/coresight/coresight-etm-perf.c
> > > > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
> > > > @@ -226,9 +226,6 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
> > > > sink = coresight_get_enabled_sink(true);
> > > > }
> > > >
> > > > - if (!sink)
> > > > - goto err;
> > > > -
> > > > mask = &event_data->mask;
> > > >
> > > > /*
> > > > @@ -253,6 +250,16 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
> > > > continue;
> > > > }
> > > >
> > > > + /*
> > > > + * No sink provided - look for a default sink for one of the
> > > > + * devices. At present we only support topology where all CPUs
> > > > + * use the same sink [N:1], so only need to find one sink. The
> > > > + * coresight_build_path later will remove any CPU that does not
> > > > + * attach to the sink, or if we have not found a sink.
> > > > + */
> > > > + if (!sink)
> > > > + sink = coresight_find_default_sink(csdev);
> > > > +
> > >
> > > While we are here, should we remove the "find enabled sink" if the csink
> > > is not specified via config. ? That step is problematic, as the user may
> > > not remember which sinks were enabled. Also, we can't hit that with
> > > perf tool as it prevents any invocation without sink (until this change).
Old version of perf tools will take sinks selected on the perf command line and
use the sysfs to communicate that to the kernel. Granted there may not be that
many (if any), removing coresight_get_enabled_sink() will break those
implementation.
The real question is if keeping the functionatlity around so troublesome that it
overweighs the drawbacks of removing it.
> > >
> > > So may be this is a good time to get rid of that ?
> > >
> >
> > You are correct - the 'sink = coresight_get_enabled_sink(true);' was
> > dead code until this patch.
> > However - if someone has set up their system using sysfs to enable
> > sinks, then should we not respect that rather than assume they made a
> > mistake?
>
> If someone really wants to use a specific sink, then they could always
> specify it via the config attribute and it will be honoured. We need not
> carry along this non-intuitive hinting.
>
> >
> > Thinking about N:M topologies mentioned below - one method of handling
> > this is to enable relevant sinks and then let perf trace on any cores
> > that might use them.
> >
> > > Also, we may need to do special handling for cases where there multiple
> > > sinks (ETRS) and the cpus in the event mask has different preferred
> > > sink. We can defer it for now as we don't claim to support such
> > > configurations yet.
> >
> > Yes - the newer topologies will need some changes - beyond what we are
> > handling here.
> > However - especially for 1:1 - the best way may be to always use the
> > default sink - as specifying multiple sinks on the perf command line
> > may be problematical.
> >
> > > When we do, we could either :
> > >
> > > 1) Make sure the event is bound to a single CPU, in which case
> > > the sink remains the same for the event.
> > >
> > > OR
> > >
> > > 2) All the different "preferred" sinks (ETRs selected by the ETM) have
> > > the same capabilitiy. i.e, we can move around the "sink" specific
> > > buffers and use them where we end up using.
> >
> > If here by "capabilities" we are talking about buffer vs system memory
> > type sinks then I agree. We may need in future to limit the search
>
> Not necessarily. e.g, if we ever get two different types of system
> memory sinks, (e.g, a global ETR and a dedicate "new" sink for a
> cluster), we can't keep switching between the two sinks depending on how
> they use the buffers. (i.e, direct buffer vs double copy)
>
> Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v3 00/10] Add MMC and DMA support for Actions S700
From: Amit Singh Tomar @ 2020-06-02 17:33 UTC (permalink / raw)
To: andre.przywara, afaerber, manivannan.sadhasivam, vkoul, sboyd,
robh+dt
Cc: dan.j.williams, linux-actions, linux-kernel, linux-arm-kernel,
cristian.ciocaltea
This Series(v3) addressed the review comments provide by Rob, and
there are changes in patch 5/10 for it.
Also, one of the important change for this series(v3) is about the way we
we handle address range conflict between pinctrl and sps node.
In the last Series(v2), patch 4/10 was sent as *do not merge* but while
discussing about some proper solution for it, we have come up with
idea of limiting pinctrl address range(to 0x100) to avoid this conflict.
This is safe to do as current pinctrl driver uses address range only
up to 0x100 (even less than that?), and this would let sps to work properly.
Since sps block is now enabled , we have to provide power-domain bit
for dma to work properly and patch 6/10 has that change now.
Looking forward have some comments for this series.
---------------------------------------------------------------------------
Series(v2) addressed the review comments provided by Andre, and
there are changes in patch 1/10, 2/10, 5/10 and 9/10.
* Accessor function (to get the frame lenght) has moved from
patch 2/9 to patch 1/9 with inline removed.
* Removed the unnecessary line break.
* Added comments about the way DMA descriptor differs between S700
and S900.
* Added a macro to define fcnt value.
* Updated dma DT bindings.
* Used SoC secific compatible string for MMC.
Apart from it, a new patch 8/10 is added in this series to
update mmc DT bindings.
Series is rebased on 5.7.0-rc6.
-----------------------------------------------------------------------------
Series(v1) have following changes from the previous series.
New patch(5/8) has been introduced that converts dma dt-binding
for Actions OWL SoC from text format to yaml file.
For patch(2/8) new accessor function is added to get the frame
lenght which is common to both S900 and S700. Apart from it
SoC check is removed from irq routine as it is not needed.
Patch(4/8) which is an hack to prove our DMA and MMC works
for S700 is now sent as *do not merge* patch.
DMA is tested using dmatest with follwoing result:
root@ubuntu:~# echo dma0chan1 > /sys/module/dmatest/parameters/channel
root@ubuntu:~# echo 2000 > /sys/module/dmatest/parameters/timeout
root@ubuntu:~# echo 1 > /sys/module/dmatest/parameters/iterations
root@ubuntu:~# echo 1 > /sys/module/dmatest/parameters/run
root@ubuntu:~# dmesg | tail
[ 303.362586] dmatest: Added 1 threads using dma0chan1
[ 317.258658] dmatest: Started 1 threads using dma0chan1
[ 317.259397] dmatest: dma0chan1-copy0: summary 1 tests, 0 failures 16129.03 iops 32258 KB/s (0)
-------------------------------------------------------------------------------
The intention of RFC series is to enable uSD and DMA support for
Cubieboard7 based on Actions S700 SoC, and on the way we found that
it requires changes in dmaengine present on S700 as its different
from what is present on S900.
Patch(1/8) does provide a new way to describe DMA descriptor, idea is
to remove the bit-fields as its less maintainable. It is only build
tested and it would be great if this can be tested on S900 based
hardware.
Patch(2/8) adds S700 DMA engine support, there is new compatible
string added for it, which means a changed bindings needed to submitted
for this. I would plan to send it later the converted "owl-dma.yaml".
Patch(4/8) disables the sps node as its memory range is conflicting
pinctrl node and results in pinctrl proble failure.
Rest of patches in the series adds DMA/MMC nodes for S700
alone with binding constants and enables the uSD for Cubieboard7.
This whole series is tested, by building/compiling Kernel on
Cubieboard7-lite which was *almost* successful (OOM kicked in,
while Linking due to less RAM present on hardware).
Following is the mmc speed :
ubuntu@ubuntu:~$ sudo hdparm -tT /dev/mmcblk0
/dev/mmcblk0:
Timing cached reads: 1310 MB in 2.00 seconds = 655.15 MB/sec
Timing buffered disk reads: 62 MB in 3.05 seconds = 20.30 MB/sec
Amit Singh Tomar (10):
dmaengine: Actions: get rid of bit fields from dma descriptor
dmaengine: Actions: Add support for S700 DMA engine
clk: actions: Add MMC clock-register reset bits
arm64: dts: actions: limit address range for pinctrl node
dt-bindings: dmaengine: convert Actions Semi Owl SoCs bindings to yaml
arm64: dts: actions: Add DMA Controller for S700
dt-bindings: reset: s700: Add binding constants for mmc
dt-bindings: mmc: owl: add compatible string actions,s700-mmc
arm64: dts: actions: Add MMC controller support for S700
arm64: dts: actions: Add uSD support for Cubieboard7
Documentation/devicetree/bindings/dma/owl-dma.txt | 47 --------
Documentation/devicetree/bindings/dma/owl-dma.yaml | 79 +++++++++++++
Documentation/devicetree/bindings/mmc/owl-mmc.yaml | 6 +-
arch/arm64/boot/dts/actions/s700-cubieboard7.dts | 41 +++++++
arch/arm64/boot/dts/actions/s700.dtsi | 51 ++++++++-
drivers/clk/actions/owl-s700.c | 3 +
drivers/dma/owl-dma.c | 126 ++++++++++++---------
include/dt-bindings/reset/actions,s700-reset.h | 3 +
8 files changed, 256 insertions(+), 100 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/dma/owl-dma.txt
create mode 100644 Documentation/devicetree/bindings/dma/owl-dma.yaml
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v3 01/10] dmaengine: Actions: get rid of bit fields from dma descriptor
From: Amit Singh Tomar @ 2020-06-02 17:33 UTC (permalink / raw)
To: andre.przywara, vkoul, afaerber, manivannan.sadhasivam
Cc: linux-actions, linux-kernel, cristian.ciocaltea, dmaengine,
dan.j.williams, linux-arm-kernel
In-Reply-To: <1591119192-18538-1-git-send-email-amittomer25@gmail.com>
At the moment, Driver uses bit fields to describe registers of the DMA
descriptor structure that makes it less portable and maintainable, and
Andre suugested(and even sketched important bits for it) to make use of
array to describe this DMA descriptors instead. It gives the flexibility
while extending support for other platform such as Actions S700.
This commit removes the "owl_dma_lli_hw" (that includes bit-fields) and
uses array to describe DMA descriptor.
Suggested-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Amit Singh Tomar <amittomer25@gmail.com>
---
Changes since v2:
* No change.
Changes since v1:
* Defined macro for frame count value.
* Introduced llc_hw_flen() from patch 2/9.
* Removed the unnecessary line break.
Changes since rfc:
* No change.
---
drivers/dma/owl-dma.c | 84 ++++++++++++++++++++++++---------------------------
1 file changed, 40 insertions(+), 44 deletions(-)
diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
index c683051257fd..dd85c205454e 100644
--- a/drivers/dma/owl-dma.c
+++ b/drivers/dma/owl-dma.c
@@ -120,30 +120,21 @@
#define BIT_FIELD(val, width, shift, newshift) \
((((val) >> (shift)) & ((BIT(width)) - 1)) << (newshift))
-/**
- * struct owl_dma_lli_hw - Hardware link list for dma transfer
- * @next_lli: physical address of the next link list
- * @saddr: source physical address
- * @daddr: destination physical address
- * @flen: frame length
- * @fcnt: frame count
- * @src_stride: source stride
- * @dst_stride: destination stride
- * @ctrla: dma_mode and linklist ctrl config
- * @ctrlb: interrupt config
- * @const_num: data for constant fill
- */
-struct owl_dma_lli_hw {
- u32 next_lli;
- u32 saddr;
- u32 daddr;
- u32 flen:20;
- u32 fcnt:12;
- u32 src_stride;
- u32 dst_stride;
- u32 ctrla;
- u32 ctrlb;
- u32 const_num;
+/* Frame count value is fixed as 1 */
+#define FCNT_VAL 0x1
+
+/* Describe DMA descriptor, hardware link list for dma transfer */
+enum owl_dmadesc_offsets {
+ OWL_DMADESC_NEXT_LLI = 0,
+ OWL_DMADESC_SADDR,
+ OWL_DMADESC_DADDR,
+ OWL_DMADESC_FLEN,
+ OWL_DMADESC_SRC_STRIDE,
+ OWL_DMADESC_DST_STRIDE,
+ OWL_DMADESC_CTRLA,
+ OWL_DMADESC_CTRLB,
+ OWL_DMADESC_CONST_NUM,
+ OWL_DMADESC_SIZE
};
/**
@@ -153,7 +144,7 @@ struct owl_dma_lli_hw {
* @node: node for txd's lli_list
*/
struct owl_dma_lli {
- struct owl_dma_lli_hw hw;
+ u32 hw[OWL_DMADESC_SIZE];
dma_addr_t phys;
struct list_head node;
};
@@ -320,6 +311,11 @@ static inline u32 llc_hw_ctrlb(u32 int_ctl)
return ctl;
}
+static u32 llc_hw_flen(struct owl_dma_lli *lli)
+{
+ return lli->hw[OWL_DMADESC_FLEN] & GENMASK(19, 0);
+}
+
static void owl_dma_free_lli(struct owl_dma *od,
struct owl_dma_lli *lli)
{
@@ -351,8 +347,9 @@ static struct owl_dma_lli *owl_dma_add_lli(struct owl_dma_txd *txd,
list_add_tail(&next->node, &txd->lli_list);
if (prev) {
- prev->hw.next_lli = next->phys;
- prev->hw.ctrla |= llc_hw_ctrla(OWL_DMA_MODE_LME, 0);
+ prev->hw[OWL_DMADESC_NEXT_LLI] = next->phys;
+ prev->hw[OWL_DMADESC_CTRLA] |=
+ llc_hw_ctrla(OWL_DMA_MODE_LME, 0);
}
return next;
@@ -365,8 +362,7 @@ static inline int owl_dma_cfg_lli(struct owl_dma_vchan *vchan,
struct dma_slave_config *sconfig,
bool is_cyclic)
{
- struct owl_dma_lli_hw *hw = &lli->hw;
- u32 mode;
+ u32 mode, ctrlb;
mode = OWL_DMA_MODE_PW(0);
@@ -407,22 +403,22 @@ static inline int owl_dma_cfg_lli(struct owl_dma_vchan *vchan,
return -EINVAL;
}
- hw->next_lli = 0; /* One link list by default */
- hw->saddr = src;
- hw->daddr = dst;
-
- hw->fcnt = 1; /* Frame count fixed as 1 */
- hw->flen = len; /* Max frame length is 1MB */
- hw->src_stride = 0;
- hw->dst_stride = 0;
- hw->ctrla = llc_hw_ctrla(mode,
- OWL_DMA_LLC_SAV_LOAD_NEXT |
- OWL_DMA_LLC_DAV_LOAD_NEXT);
+ lli->hw[OWL_DMADESC_CTRLA] = llc_hw_ctrla(mode,
+ OWL_DMA_LLC_SAV_LOAD_NEXT |
+ OWL_DMA_LLC_DAV_LOAD_NEXT);
if (is_cyclic)
- hw->ctrlb = llc_hw_ctrlb(OWL_DMA_INTCTL_BLOCK);
+ ctrlb = llc_hw_ctrlb(OWL_DMA_INTCTL_BLOCK);
else
- hw->ctrlb = llc_hw_ctrlb(OWL_DMA_INTCTL_SUPER_BLOCK);
+ ctrlb = llc_hw_ctrlb(OWL_DMA_INTCTL_SUPER_BLOCK);
+
+ lli->hw[OWL_DMADESC_NEXT_LLI] = 0;
+ lli->hw[OWL_DMADESC_SADDR] = src;
+ lli->hw[OWL_DMADESC_DADDR] = dst;
+ lli->hw[OWL_DMADESC_SRC_STRIDE] = 0;
+ lli->hw[OWL_DMADESC_DST_STRIDE] = 0;
+ lli->hw[OWL_DMADESC_FLEN] = len | FCNT_VAL << 20;
+ lli->hw[OWL_DMADESC_CTRLB] = ctrlb;
return 0;
}
@@ -754,7 +750,7 @@ static u32 owl_dma_getbytes_chan(struct owl_dma_vchan *vchan)
/* Start from the next active node */
if (lli->phys == next_lli_phy) {
list_for_each_entry(lli, &txd->lli_list, node)
- bytes += lli->hw.flen;
+ bytes += llc_hw_flen(lli);
break;
}
}
@@ -785,7 +781,7 @@ static enum dma_status owl_dma_tx_status(struct dma_chan *chan,
if (vd) {
txd = to_owl_txd(&vd->tx);
list_for_each_entry(lli, &txd->lli_list, node)
- bytes += lli->hw.flen;
+ bytes += llc_hw_flen(lli);
} else {
bytes = owl_dma_getbytes_chan(vchan);
}
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 02/10] dmaengine: Actions: Add support for S700 DMA engine
From: Amit Singh Tomar @ 2020-06-02 17:33 UTC (permalink / raw)
To: andre.przywara, vkoul, afaerber, manivannan.sadhasivam
Cc: linux-actions, linux-kernel, cristian.ciocaltea, dmaengine,
dan.j.williams, linux-arm-kernel
In-Reply-To: <1591119192-18538-1-git-send-email-amittomer25@gmail.com>
DMA controller present on S700 SoC is compatible with the one on S900
(as most of registers are same), but it has different DMA descriptor
structure where registers "fcnt" and "ctrlb" uses different encoding.
For instance, on S900 "fcnt" starts at offset 0x0c and uses upper 12
bits whereas on S700, it starts at offset 0x1c and uses lower 12 bits.
This commit adds support for DMA controller present on S700.
Signed-off-by: Amit Singh Tomar <amittomer25@gmail.com>
---
Changes since v2:
* No changes.
Changes since v1:
* Moved llc_hw_flen() to patch 1/9.
* provided comments about dma descriptor difference.
between S700 and S900.
Changes since RFC:
* Added accessor function to get the frame lenght.
* Removed the SoC specific check in IRQ routine.
---
drivers/dma/owl-dma.c | 46 +++++++++++++++++++++++++++++++++++++---------
1 file changed, 37 insertions(+), 9 deletions(-)
diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
index dd85c205454e..17d2fc2d568b 100644
--- a/drivers/dma/owl-dma.c
+++ b/drivers/dma/owl-dma.c
@@ -137,6 +137,11 @@ enum owl_dmadesc_offsets {
OWL_DMADESC_SIZE
};
+enum owl_dma_id {
+ S900_DMA,
+ S700_DMA,
+};
+
/**
* struct owl_dma_lli - Link list for dma transfer
* @hw: hardware link list
@@ -203,6 +208,7 @@ struct owl_dma_vchan {
* @pchans: array of data for the physical channels
* @nr_vchans: the number of physical channels
* @vchans: array of data for the physical channels
+ * @devid: device id based on OWL SoC
*/
struct owl_dma {
struct dma_device dma;
@@ -217,6 +223,7 @@ struct owl_dma {
unsigned int nr_vchans;
struct owl_dma_vchan *vchans;
+ enum owl_dma_id devid;
};
static void pchan_update(struct owl_dma_pchan *pchan, u32 reg,
@@ -306,6 +313,11 @@ static inline u32 llc_hw_ctrlb(u32 int_ctl)
{
u32 ctl;
+ /*
+ * Irrespective of the SoC, ctrlb value starts filling from
+ * bit 18.
+ */
+
ctl = BIT_FIELD(int_ctl, 7, 0, 18);
return ctl;
@@ -362,6 +374,7 @@ static inline int owl_dma_cfg_lli(struct owl_dma_vchan *vchan,
struct dma_slave_config *sconfig,
bool is_cyclic)
{
+ struct owl_dma *od = to_owl_dma(vchan->vc.chan.device);
u32 mode, ctrlb;
mode = OWL_DMA_MODE_PW(0);
@@ -417,8 +430,18 @@ static inline int owl_dma_cfg_lli(struct owl_dma_vchan *vchan,
lli->hw[OWL_DMADESC_DADDR] = dst;
lli->hw[OWL_DMADESC_SRC_STRIDE] = 0;
lli->hw[OWL_DMADESC_DST_STRIDE] = 0;
- lli->hw[OWL_DMADESC_FLEN] = len | FCNT_VAL << 20;
- lli->hw[OWL_DMADESC_CTRLB] = ctrlb;
+
+ /*
+ * S700 put flen and fcnt at offset 0x0c and 0x1c respectively,
+ * whereas S900 put flen and fcnt at offset 0x0c.
+ */
+ if (od->devid == S700_DMA) {
+ lli->hw[OWL_DMADESC_FLEN] = len;
+ lli->hw[OWL_DMADESC_CTRLB] = FCNT_VAL | ctrlb;
+ } else {
+ lli->hw[OWL_DMADESC_FLEN] = len | FCNT_VAL << 20;
+ lli->hw[OWL_DMADESC_CTRLB] = ctrlb;
+ }
return 0;
}
@@ -580,7 +603,7 @@ static irqreturn_t owl_dma_interrupt(int irq, void *dev_id)
global_irq_pending = dma_readl(od, OWL_DMA_IRQ_PD0);
- if (chan_irq_pending && !(global_irq_pending & BIT(i))) {
+ if (chan_irq_pending && !(global_irq_pending & BIT(i))) {
dev_dbg(od->dma.dev,
"global and channel IRQ pending match err\n");
@@ -1038,11 +1061,20 @@ static struct dma_chan *owl_dma_of_xlate(struct of_phandle_args *dma_spec,
return chan;
}
+static const struct of_device_id owl_dma_match[] = {
+ { .compatible = "actions,s900-dma", .data = (void *)S900_DMA,},
+ { .compatible = "actions,s700-dma", .data = (void *)S700_DMA,},
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, owl_dma_match);
+
static int owl_dma_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct owl_dma *od;
int ret, i, nr_channels, nr_requests;
+ const struct of_device_id *of_id =
+ of_match_device(owl_dma_match, &pdev->dev);
od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
if (!od)
@@ -1067,6 +1099,8 @@ static int owl_dma_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "dma-channels %d, dma-requests %d\n",
nr_channels, nr_requests);
+ od->devid = (enum owl_dma_id)of_id->data;
+
od->nr_pchans = nr_channels;
od->nr_vchans = nr_requests;
@@ -1199,12 +1233,6 @@ static int owl_dma_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id owl_dma_match[] = {
- { .compatible = "actions,s900-dma", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, owl_dma_match);
-
static struct platform_driver owl_dma_driver = {
.probe = owl_dma_probe,
.remove = owl_dma_remove,
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 03/10] clk: actions: Add MMC clock-register reset bits
From: Amit Singh Tomar @ 2020-06-02 17:33 UTC (permalink / raw)
To: andre.przywara, afaerber, manivannan.sadhasivam, sboyd
Cc: linux-actions, linux-kernel, linux-arm-kernel, cristian.ciocaltea
In-Reply-To: <1591119192-18538-1-git-send-email-amittomer25@gmail.com>
This commit adds reset bits needed for MMC clock registers present
on Actions S700 SoC.
Signed-off-by: Amit Singh Tomar <amittomer25@gmail.com>
---
Changes from v2:
* No change.
Changes from v1:
* No change.
Changes from RFC:
* No change.
---
drivers/clk/actions/owl-s700.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/clk/actions/owl-s700.c b/drivers/clk/actions/owl-s700.c
index a2f34d13fb54..cd60eca7727d 100644
--- a/drivers/clk/actions/owl-s700.c
+++ b/drivers/clk/actions/owl-s700.c
@@ -577,6 +577,9 @@ static const struct owl_reset_map s700_resets[] = {
[RESET_DSI] = { CMU_DEVRST0, BIT(2) },
[RESET_CSI] = { CMU_DEVRST0, BIT(13) },
[RESET_SI] = { CMU_DEVRST0, BIT(14) },
+ [RESET_SD0] = { CMU_DEVRST0, BIT(22) },
+ [RESET_SD1] = { CMU_DEVRST0, BIT(23) },
+ [RESET_SD2] = { CMU_DEVRST0, BIT(24) },
[RESET_I2C0] = { CMU_DEVRST1, BIT(0) },
[RESET_I2C1] = { CMU_DEVRST1, BIT(1) },
[RESET_I2C2] = { CMU_DEVRST1, BIT(2) },
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 04/10] arm64: dts: actions: limit address range for pinctrl node
From: Amit Singh Tomar @ 2020-06-02 17:33 UTC (permalink / raw)
To: andre.przywara, afaerber, manivannan.sadhasivam, robh+dt
Cc: devicetree, linux-actions, linux-kernel, linux-arm-kernel,
cristian.ciocaltea
In-Reply-To: <1591119192-18538-1-git-send-email-amittomer25@gmail.com>
After commit 7cdf8446ed1d ("arm64: dts: actions: Add pinctrl node for
Actions Semi S700") following error has been observed while booting
Linux on Cubieboard7-lite(based on S700 SoC).
[ 0.257415] pinctrl-s700 e01b0000.pinctrl: can't request region for
resource [mem 0xe01b0000-0xe01b0fff]
[ 0.266902] pinctrl-s700: probe of e01b0000.pinctrl failed with error -16
This is due to the fact that memory range for "sps" power domain controller
clashes with pinctrl.
One way to fix it, is to limit pinctrl address range which is safe
to do as current pinctrl driver uses address range only up to 0x100.
This commit limits the pinctrl address range to 0x100 so that it doesn't
conflict with sps range.
Fixes: 7cdf8446ed1d ("arm64: dts: actions: Add pinctrl node for Actions
Semi S700")
Suggested-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Amit Singh Tomar <amittomer25@gmail.com>
---
Changes since v2:
* this is no more don't merge and fixed
the broken S700 boot by limiting pinctrl
address range.
* Modified the subject to reflect the changes.
Changes since v1:
* No change.
Changes since RFC:
* kept as do not merge.
---
arch/arm64/boot/dts/actions/s700.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/actions/s700.dtsi b/arch/arm64/boot/dts/actions/s700.dtsi
index 2006ad5424fa..f8eb72bb4125 100644
--- a/arch/arm64/boot/dts/actions/s700.dtsi
+++ b/arch/arm64/boot/dts/actions/s700.dtsi
@@ -231,7 +231,7 @@
pinctrl: pinctrl@e01b0000 {
compatible = "actions,s700-pinctrl";
- reg = <0x0 0xe01b0000 0x0 0x1000>;
+ reg = <0x0 0xe01b0000 0x0 0x100>;
clocks = <&cmu CLK_GPIO>;
gpio-controller;
gpio-ranges = <&pinctrl 0 0 136>;
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 05/10] dt-bindings: dmaengine: convert Actions Semi Owl SoCs bindings to yaml
From: Amit Singh Tomar @ 2020-06-02 17:33 UTC (permalink / raw)
To: andre.przywara, afaerber, vkoul, manivannan.sadhasivam, robh+dt
Cc: devicetree, linux-actions, linux-kernel, cristian.ciocaltea,
dan.j.williams, linux-arm-kernel
In-Reply-To: <1591119192-18538-1-git-send-email-amittomer25@gmail.com>
Converts the device tree bindings for the Actions Semi Owl SoCs DMA
Controller over to YAML schemas.
It also adds new compatible string "actions,s700-dma".
Signed-off-by: Amit Singh Tomar <amittomer25@gmail.com>
---
Changes since v2:
* Addressed Rob's comments:
- removed unnecessary description.
- added unevaluatedProperties
- added relevant information about
dma-channels and dma-request
* Added power-domain property.
Change since v1:
* Updated the description field to reflect
only the necessary information.
* replaced the maxItems field with description for each
controller attribute(except interrupts).
* Replaced the clock macro with number to keep the example
as independent as possible.
New patch, was not there in RFC.
---
Documentation/devicetree/bindings/dma/owl-dma.txt | 47 -------------
Documentation/devicetree/bindings/dma/owl-dma.yaml | 79 ++++++++++++++++++++++
2 files changed, 79 insertions(+), 47 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/dma/owl-dma.txt
create mode 100644 Documentation/devicetree/bindings/dma/owl-dma.yaml
diff --git a/Documentation/devicetree/bindings/dma/owl-dma.txt b/Documentation/devicetree/bindings/dma/owl-dma.txt
deleted file mode 100644
index 03e9bb12b75f..000000000000
--- a/Documentation/devicetree/bindings/dma/owl-dma.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-* Actions Semi Owl SoCs DMA controller
-
-This binding follows the generic DMA bindings defined in dma.txt.
-
-Required properties:
-- compatible: Should be "actions,s900-dma".
-- reg: Should contain DMA registers location and length.
-- interrupts: Should contain 4 interrupts shared by all channel.
-- #dma-cells: Must be <1>. Used to represent the number of integer
- cells in the dmas property of client device.
-- dma-channels: Physical channels supported.
-- dma-requests: Number of DMA request signals supported by the controller.
- Refer to Documentation/devicetree/bindings/dma/dma.txt
-- clocks: Phandle and Specifier of the clock feeding the DMA controller.
-
-Example:
-
-Controller:
- dma: dma-controller@e0260000 {
- compatible = "actions,s900-dma";
- reg = <0x0 0xe0260000 0x0 0x1000>;
- interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
- #dma-cells = <1>;
- dma-channels = <12>;
- dma-requests = <46>;
- clocks = <&clock CLK_DMAC>;
- };
-
-Client:
-
-DMA clients connected to the Actions Semi Owl SoCs DMA controller must
-use the format described in the dma.txt file, using a two-cell specifier
-for each channel.
-
-The two cells in order are:
-1. A phandle pointing to the DMA controller.
-2. The channel id.
-
-uart5: serial@e012a000 {
- ...
- dma-names = "tx", "rx";
- dmas = <&dma 26>, <&dma 27>;
- ...
-};
diff --git a/Documentation/devicetree/bindings/dma/owl-dma.yaml b/Documentation/devicetree/bindings/dma/owl-dma.yaml
new file mode 100644
index 000000000000..5577cd910781
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/owl-dma.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/owl-dma.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Actions Semi Owl SoCs DMA controller
+
+description: |
+ The OWL DMA is a general-purpose direct memory access controller capable of
+ supporting 10 and 12 independent DMA channels for S700 and S900 SoCs
+ respectively.
+
+maintainers:
+ - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+allOf:
+ - $ref: "dma-controller.yaml#"
+
+properties:
+ compatible:
+ enum:
+ - actions,s900-dma
+ - actions,s700-dma
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ description:
+ controller supports 4 interrupts, which are freely assignable to the
+ DMA channels.
+ maxItems: 4
+
+ "#dma-cells":
+ const: 1
+
+ dma-channels:
+ maximum: 12
+
+ dma-requests:
+ maximum: 46
+
+ clocks:
+ maxItems: 1
+ description:
+ Phandle and Specifier of the clock feeding the DMA controller.
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - "#dma-cells"
+ - dma-channels
+ - dma-requests
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ dma: dma-controller@e0260000 {
+ compatible = "actions,s900-dma";
+ reg = <0x0 0xe0260000 0x0 0x1000>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ dma-channels = <12>;
+ dma-requests = <46>;
+ clocks = <&clock 22>;
+ };
+
+...
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 06/10] arm64: dts: actions: Add DMA Controller for S700
From: Amit Singh Tomar @ 2020-06-02 17:33 UTC (permalink / raw)
To: andre.przywara, afaerber, vkoul, manivannan.sadhasivam, robh+dt
Cc: devicetree, linux-actions, linux-kernel, cristian.ciocaltea,
dan.j.williams, linux-arm-kernel
In-Reply-To: <1591119192-18538-1-git-send-email-amittomer25@gmail.com>
This commit adds DAM controller present on Actions S700, it differs from
S900 in terms of number of dma channels and requests.
Signed-off-by: Amit Singh Tomar <amittomer25@gmail.com>
---
Changes since v2:
* added power-domain property as sps
is enabled now and DMA needs it.
Changes since v1:
* No Change.
Changes since RFC:
* No Change.
---
arch/arm64/boot/dts/actions/s700.dtsi | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/arch/arm64/boot/dts/actions/s700.dtsi b/arch/arm64/boot/dts/actions/s700.dtsi
index f8eb72bb4125..605594dd7a0e 100644
--- a/arch/arm64/boot/dts/actions/s700.dtsi
+++ b/arch/arm64/boot/dts/actions/s700.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/clock/actions,s700-cmu.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/actions,s700-reset.h>
+#include <dt-bindings/power/owl-s700-powergate.h>
/ {
compatible = "actions,s700";
@@ -244,5 +245,19 @@
<GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
};
+
+ dma: dma-controller@e0230000 {
+ compatible = "actions,s700-dma";
+ reg = <0x0 0xe0230000 0x0 0x1000>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ dma-channels = <10>;
+ dma-requests = <44>;
+ clocks = <&cmu CLK_DMAC>;
+ power-domains = <&sps S700_PD_DMA>;
+ };
};
};
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 07/10] dt-bindings: reset: s700: Add binding constants for mmc
From: Amit Singh Tomar @ 2020-06-02 17:33 UTC (permalink / raw)
To: andre.przywara, afaerber, manivannan.sadhasivam, robh+dt
Cc: devicetree, linux-actions, linux-kernel, linux-arm-kernel,
cristian.ciocaltea
In-Reply-To: <1591119192-18538-1-git-send-email-amittomer25@gmail.com>
This commit adds device tree binding reset constants for mmc controller
present on Actions S700 Soc.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Amit Singh Tomar <amittomer25@gmail.com>
---
Changes since v2:
* No change.
Changes since v1:
* No change.
Changes since RFC:
* added Rob's acked-by tag
---
include/dt-bindings/reset/actions,s700-reset.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/dt-bindings/reset/actions,s700-reset.h b/include/dt-bindings/reset/actions,s700-reset.h
index 5e3b16b8ef53..a3118de6d7aa 100644
--- a/include/dt-bindings/reset/actions,s700-reset.h
+++ b/include/dt-bindings/reset/actions,s700-reset.h
@@ -30,5 +30,8 @@
#define RESET_UART4 20
#define RESET_UART5 21
#define RESET_UART6 22
+#define RESET_SD0 23
+#define RESET_SD1 24
+#define RESET_SD2 25
#endif /* __DT_BINDINGS_ACTIONS_S700_RESET_H */
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 08/10] dt-bindings: mmc: owl: add compatible string actions, s700-mmc
From: Amit Singh Tomar @ 2020-06-02 17:33 UTC (permalink / raw)
To: andre.przywara, afaerber, manivannan.sadhasivam, robh+dt
Cc: devicetree, linux-actions, linux-kernel, linux-arm-kernel,
cristian.ciocaltea
In-Reply-To: <1591119192-18538-1-git-send-email-amittomer25@gmail.com>
The commit adds a new SoC specific compatible string "actions,s700-mmc"
in combination with more generic string "actions,owl-mmc".
Placement order of these strings should abide by the principle of
"from most specific to most general".
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Amit Singh Tomar <amittomer25@gmail.com>
---
Changes since v2:
* Added Rob's Reviewed-by tag
* Newly added patch in v2.
---
Documentation/devicetree/bindings/mmc/owl-mmc.yaml | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/mmc/owl-mmc.yaml b/Documentation/devicetree/bindings/mmc/owl-mmc.yaml
index 12b40213426d..9604ef695585 100644
--- a/Documentation/devicetree/bindings/mmc/owl-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/owl-mmc.yaml
@@ -14,7 +14,11 @@ maintainers:
properties:
compatible:
- const: actions,owl-mmc
+ oneOf:
+ - const: actions,owl-mmc
+ - items:
+ - const: actions,s700-mmc
+ - const: actions,owl-mmc
reg:
maxItems: 1
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 09/10] arm64: dts: actions: Add MMC controller support for S700
From: Amit Singh Tomar @ 2020-06-02 17:33 UTC (permalink / raw)
To: andre.przywara, afaerber, manivannan.sadhasivam, robh+dt
Cc: devicetree, linux-actions, linux-kernel, linux-arm-kernel,
cristian.ciocaltea
In-Reply-To: <1591119192-18538-1-git-send-email-amittomer25@gmail.com>
This commits adds support for MMC controllers present on Actions S700 SoC,
there are 3 MMC controllers in this SoC which can be used for accessing
SD/EMMC/SDIO cards.
Signed-off-by: Amit Singh Tomar <amittomer25@gmail.com>
---
Changes since v2:
* No change.
Changes since v1:
* Added SoC specific compatibe string.
Changes since RFC:
* No change
---
arch/arm64/boot/dts/actions/s700.dtsi | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/arm64/boot/dts/actions/s700.dtsi b/arch/arm64/boot/dts/actions/s700.dtsi
index 605594dd7a0e..b1a34f95d44c 100644
--- a/arch/arm64/boot/dts/actions/s700.dtsi
+++ b/arch/arm64/boot/dts/actions/s700.dtsi
@@ -259,5 +259,38 @@
clocks = <&cmu CLK_DMAC>;
power-domains = <&sps S700_PD_DMA>;
};
+
+ mmc0: mmc@e0210000 {
+ compatible = "actions,s700-mmc", "actions,owl-mmc";
+ reg = <0x0 0xe0210000 0x0 0x4000>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cmu CLK_SD0>;
+ resets = <&cmu RESET_SD0>;
+ dmas = <&dma 2>;
+ dma-names = "mmc";
+ status = "disabled";
+ };
+
+ mmc1: mmc@e0214000 {
+ compatible = "actions,s700-mmc", "actions,owl-mmc";
+ reg = <0x0 0xe0214000 0x0 0x4000>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cmu CLK_SD1>;
+ resets = <&cmu RESET_SD1>;
+ dmas = <&dma 3>;
+ dma-names = "mmc";
+ status = "disabled";
+ };
+
+ mmc2: mmc@e0218000 {
+ compatible = "actions,s700-mmc", "actions,owl-mmc";
+ reg = <0x0 0xe0218000 0x0 0x4000>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cmu CLK_SD2>;
+ resets = <&cmu RESET_SD2>;
+ dmas = <&dma 4>;
+ dma-names = "mmc";
+ status = "disabled";
+ };
};
};
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 10/10] arm64: dts: actions: Add uSD support for Cubieboard7
From: Amit Singh Tomar @ 2020-06-02 17:33 UTC (permalink / raw)
To: andre.przywara, afaerber, manivannan.sadhasivam, robh+dt
Cc: devicetree, linux-actions, linux-kernel, linux-arm-kernel,
cristian.ciocaltea
In-Reply-To: <1591119192-18538-1-git-send-email-amittomer25@gmail.com>
This commit adds uSD support for Cubieboard7 board based on Actions Semi
S700 SoC. SD0 is connected to uSD slot. Since there is no PMIC support
added yet, fixed regulator has been used as a regulator node.
Signed-off-by: Amit Singh Tomar <amittomer25@gmail.com>
---
Changes since v2:
* No change.
Changes since v1:
* No change.
Changes since RFC:
* No change.
---
arch/arm64/boot/dts/actions/s700-cubieboard7.dts | 41 ++++++++++++++++++++++++
arch/arm64/boot/dts/actions/s700.dtsi | 1 +
2 files changed, 42 insertions(+)
diff --git a/arch/arm64/boot/dts/actions/s700-cubieboard7.dts b/arch/arm64/boot/dts/actions/s700-cubieboard7.dts
index 63e375cd9eb4..ec117eb12f3a 100644
--- a/arch/arm64/boot/dts/actions/s700-cubieboard7.dts
+++ b/arch/arm64/boot/dts/actions/s700-cubieboard7.dts
@@ -13,6 +13,7 @@
aliases {
serial3 = &uart3;
+ mmc0 = &mmc0;
};
chosen {
@@ -28,6 +29,23 @@
device_type = "memory";
reg = <0x1 0xe0000000 0x0 0x0>;
};
+
+ /* Fixed regulator used in the absence of PMIC */
+ vcc_3v1: vcc-3v1 {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-3.1V";
+ regulator-min-microvolt = <3100000>;
+ regulator-max-microvolt = <3100000>;
+ };
+
+ /* Fixed regulator used in the absence of PMIC */
+ sd_vcc: sd-vcc {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-3.1V";
+ regulator-min-microvolt = <3100000>;
+ regulator-max-microvolt = <3100000>;
+ regulator-always-on;
+ };
};
&i2c0 {
@@ -81,6 +99,14 @@
bias-pull-up;
};
};
+
+ mmc0_default: mmc0_default {
+ pinmux {
+ groups = "sd0_d0_mfp", "sd0_d1_mfp", "sd0_d2_d3_mfp",
+ "sd0_cmd_mfp", "sd0_clk_mfp";
+ function = "sd0";
+ };
+ };
};
&timer {
@@ -90,3 +116,18 @@
&uart3 {
status = "okay";
};
+
+/* uSD */
+&mmc0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_default>;
+ cd-gpios = <&pinctrl 120 GPIO_ACTIVE_LOW>;
+ no-sdio;
+ no-mmc;
+ no-1-8-v;
+ bus-width = <4>;
+ vmmc-supply = <&sd_vcc>;
+ vqmmc-supply = <&sd_vcc>;
+};
+
diff --git a/arch/arm64/boot/dts/actions/s700.dtsi b/arch/arm64/boot/dts/actions/s700.dtsi
index b1a34f95d44c..2bb29bc683ef 100644
--- a/arch/arm64/boot/dts/actions/s700.dtsi
+++ b/arch/arm64/boot/dts/actions/s700.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/actions,s700-cmu.h>
+#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/actions,s700-reset.h>
#include <dt-bindings/power/owl-s700-powergate.h>
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v3 015/105] drm/vc4: hvs: Boost the core clock during modeset
From: Eric Anholt @ 2020-06-02 17:52 UTC (permalink / raw)
To: Maxime Ripard
Cc: Tim Gover, Dave Stevenson, linux-kernel, DRI Development,
bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
linux-arm-kernel, linux-rpi-kernel
In-Reply-To: <20200602125227.fe3mt5jnqd6u4pft@gilmour>
On Tue, Jun 2, 2020 at 5:52 AM Maxime Ripard <maxime@cerno.tech> wrote:
>
> Hi Eric,
>
> On Wed, May 27, 2020 at 09:33:44AM -0700, Eric Anholt wrote:
> > On Wed, May 27, 2020 at 8:49 AM Maxime Ripard <maxime@cerno.tech> wrote:
> > >
> > > In order to prevent timeouts and stalls in the pipeline, the core clock
> > > needs to be maxed at 500MHz during a modeset on the BCM2711.
> >
> > Like, the whole system's core clock?
>
> Yep, unfortunately...
>
> > How is it reasonable for some device driver to crank the system's core
> > clock up and back down to some fixed-in-the-driver frequency? Sounds
> > like you need some sort of opp thing here.
>
> That frequency is the minimum rate of that clock. However, since other
> devices have similar requirements (unicam in particular) with different
> minimum requirements, we will switch to setting a minimum rate instead
> of enforcing a particular rate, so that patch would be essentially
> s/clk_set_rate/clk_set_min_rate/.
clk_set_min_rate makes a lot more sense to me. r-b with that obvious
change. Thanks!
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCHv2 0/7] Support inhibiting input devices
From: Dmitry Torokhov @ 2020-06-02 17:52 UTC (permalink / raw)
To: Andrzej Pietrasiewicz
Cc: Nick Dyer, linux-iio, Benjamin Tissoires, platform-driver-x86,
ibm-acpi-devel, Laxman Dewangan, Peter Meerwald-Stadler, kernel,
Fabio Estevam, linux-samsung-soc, Krzysztof Kozlowski,
Jonathan Hunter, linux-acpi, Kukjin Kim, NXP Linux Team,
linux-input, Len Brown, Peter Hutterer, Michael Hennerich,
Sascha Hauer, Sylvain Lemieux, Henrique de Moraes Holschuh,
Vladimir Zapolskiy, Hans de Goede, Lars-Peter Clausen,
linux-tegra, linux-arm-kernel, Barry Song, Ferruh Yigit, patches,
Rafael J . Wysocki, Thierry Reding, Sangwon Jee,
Pengutronix Kernel Team, Hartmut Knaack, Shawn Guo,
Jonathan Cameron
In-Reply-To: <88f939cd-1518-d516-59f2-8f627a6a70d2@collabora.com>
Hi Andrzej,
On Tue, Jun 02, 2020 at 06:56:40PM +0200, Andrzej Pietrasiewicz wrote:
> Hi Dmitry,
>
> W dniu 27.05.2020 o 08:34, Dmitry Torokhov pisze:
> > That said, I think the way we should handle inhibit/uninhibit, is that
> > if we have the callback defined, then we call it, and only call open and
> > close if uninhibit or inhibit are _not_ defined.
> >
>
> If I understand you correctly you suggest to call either inhibit,
> if provided or close, if inhibit is not provided, but not both,
> that is, if both are provided then on the inhibit path only
> inhibit is called. And, consequently, you suggest to call either
> uninhibit or open, but not both. The rest of my mail makes this
> assumption, so kindly confirm if I understand you correctly.
Yes, that is correct. If a driver wants really fine-grained control, it
will provide inhibit (or both inhibit and close), otherwise it will rely
on close in place of inhibit.
>
> In my opinion this idea will not work.
>
> The first question is should we be able to inhibit a device
> which is not opened? In my opinion we should, in order to be
> able to inhibit a device in anticipation without needing to
> open it first.
I agree.
>
> Then what does opening (with input_open_device()) an inhibited
> device mean? Should it succeed or should it fail?
It should succeed.
> If it is not
> the first opening then effectively it boils down to increasing
> device's and handle's counters, so we can allow it to succeed.
> If, however, the device is being opened for the first time,
> the ->open() method wants to be called, but that somehow
> contradicts the device's inhibited state. So a logical thing
> to do is to either fail input_open_device() or postpone ->open()
> invocation to the moment of uninhibiting - and the latter is
> what the patches in this series currently do.
>
> Failing input_open_device() because of the inhibited state is
> not the right thing to do. Let me explain. Suppose that a device
> is already inhibited and then a new matching handler appears
> in the system. Most handlers (apm-power.c, evbug.c, input-leds.c,
> mac_hid.c, sysrq.c, vt/keyboard.c and rfkill/input.c) don't create
> any character devices (only evdev.c, joydev.c and mousedev.c do),
> so for them it makes no sense to delay calling input_open_device()
> and it is called in handler's ->connect(). If input_open_device()
> now fails, we have lost the only chance for this ->connect() to
> succeed.
>
> Summarizing, IMO the uninhibit path should be calling both
> ->open() and ->uninhibit() (if provided), and conversely, the inhibit
> path should be calling both ->inhibit() and ->close() (if provided).
So what you are trying to say is that you see inhibit as something that
is done in addition to what happens in close. But what exactly do you
want to do in inhibit, in addition to what close is doing?
In my view, if we want to have a dedicated inhibit callback, then it
will do everything that close does, they both are aware of each other
and can sort out the state transitions between them. For drivers that do
not have dedicated inhibit/uninhibit, we can use open and close
handlers, and have input core sort out when each should be called. That
means that we should not call dev->open() in input_open_device() when
device is inhibited (and same for dev->close() in input_close_device).
And when uninhibiting, we should not call dev->open() when there are no
users for the device, and no dev->close() when inhibiting with no users.
Do you see any problems with this approach?
Thanks.
--
Dmitry
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 1/6] arm64/vdso: use the fault callback to map vvar pages
From: Andrei Vagin @ 2020-06-02 18:02 UTC (permalink / raw)
To: linux-arm-kernel, Catalin Marinas, Will Deacon
Cc: Mark Rutland, Dmitry Safonov, linux-kernel, Andrei Vagin,
Thomas Gleixner, Vincenzo Frascino
In-Reply-To: <20200602180259.76361-1-avagin@gmail.com>
This is required to support time namespaces where a time namespace data
page is different for each namespace.
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
---
arch/arm64/kernel/vdso.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 033a48f30dbb..031ee1a8d4a8 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -114,28 +114,32 @@ static int __vdso_init(enum arch_vdso_type arch_index)
PAGE_SHIFT;
/* Allocate the vDSO pagelist, plus a page for the data. */
- vdso_pagelist = kcalloc(vdso_lookup[arch_index].vdso_pages + 1,
+ vdso_pagelist = kcalloc(vdso_lookup[arch_index].vdso_pages,
sizeof(struct page *),
GFP_KERNEL);
if (vdso_pagelist == NULL)
return -ENOMEM;
- /* Grab the vDSO data page. */
- vdso_pagelist[0] = phys_to_page(__pa_symbol(vdso_data));
-
-
/* Grab the vDSO code pages. */
pfn = sym_to_pfn(vdso_lookup[arch_index].vdso_code_start);
for (i = 0; i < vdso_lookup[arch_index].vdso_pages; i++)
- vdso_pagelist[i + 1] = pfn_to_page(pfn + i);
+ vdso_pagelist[i] = pfn_to_page(pfn + i);
- vdso_lookup[arch_index].dm->pages = &vdso_pagelist[0];
- vdso_lookup[arch_index].cm->pages = &vdso_pagelist[1];
+ vdso_lookup[arch_index].cm->pages = vdso_pagelist;
return 0;
}
+static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
+ struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ if (vmf->pgoff == 0)
+ return vmf_insert_pfn(vma, vmf->address,
+ sym_to_pfn(vdso_data));
+ return VM_FAULT_SIGBUS;
+}
+
static int __setup_additional_pages(enum arch_vdso_type arch_index,
struct mm_struct *mm,
struct linux_binprm *bprm,
@@ -155,7 +159,7 @@ static int __setup_additional_pages(enum arch_vdso_type arch_index,
}
ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
- VM_READ|VM_MAYREAD,
+ VM_READ|VM_MAYREAD|VM_PFNMAP,
vdso_lookup[arch_index].dm);
if (IS_ERR(ret))
goto up_fail;
@@ -215,6 +219,7 @@ static struct vm_special_mapping aarch32_vdso_spec[C_PAGES] = {
#ifdef CONFIG_COMPAT_VDSO
{
.name = "[vvar]",
+ .fault = vvar_fault,
},
{
.name = "[vdso]",
@@ -385,6 +390,7 @@ static int vdso_mremap(const struct vm_special_mapping *sm,
static struct vm_special_mapping vdso_spec[A_PAGES] __ro_after_init = {
{
.name = "[vvar]",
+ .fault = vvar_fault,
},
{
.name = "[vdso]",
--
2.24.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
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