* [RFC PATCH 01/29] arm64: signal: Refactor sigcontext parsing in rt_sigreturn
From: Dave Martin @ 2016-11-25 19:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480102762-23647-1-git-send-email-Dave.Martin@arm.com>
Currently, rt_sigreturn does very limited checking on the
sigcontext coming from userspace.
Future additions of extra dynamic sigcontext data will increase the
potential for surprises. Also, it is not clear whether the
sigcontext extension records are supposed to occur in a particular
order.
This patch factors out the sigcontext parsing into a separate
function, and adds extra checks to validate the well-formedness of
the sigcontext structure.
To help with this, an abstraction for the signal frame layout is
also added, using offsets to track the location of different
records in the frame. Although trivial, this provides a base to
extend upon in order to track more complex layouts.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
arch/arm64/kernel/signal.c | 121 +++++++++++++++++++++++++++++++++++++--------
1 file changed, 101 insertions(+), 20 deletions(-)
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 404dd67..4f8dbe0 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -19,9 +19,11 @@
#include <linux/compat.h>
#include <linux/errno.h>
+#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/personality.h>
#include <linux/freezer.h>
+#include <linux/stddef.h>
#include <linux/uaccess.h>
#include <linux/tracehook.h>
#include <linux/ratelimit.h>
@@ -45,6 +47,10 @@ struct rt_sigframe {
u64 lr;
};
+struct rt_sigframe_user_layout {
+ struct rt_sigframe __user *sigframe;
+};
+
static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
{
struct fpsimd_state *fpsimd = ¤t->thread.fpsimd_state;
@@ -92,12 +98,86 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
return err ? -EFAULT : 0;
}
+struct user_ctxs {
+ struct fpsimd_context __user *fpsimd;
+};
+
+static int parse_user_sigframe(struct user_ctxs *user,
+ struct rt_sigframe __user *sf)
+{
+ struct sigcontext __user *sc = &sf->uc.uc_mcontext;
+ struct _aarch64_ctx __user *head =
+ (struct _aarch64_ctx __user *)&sc->__reserved;
+ size_t offset = 0;
+
+ user->fpsimd = NULL;
+
+ while (1) {
+ int err;
+ u32 magic, size;
+
+ head = (struct _aarch64_ctx __user *)&sc->__reserved[offset];
+ if (!IS_ALIGNED((unsigned long)head, 16))
+ goto invalid;
+
+ err = 0;
+ __get_user_error(magic, &head->magic, err);
+ __get_user_error(size, &head->size, err);
+ if (err)
+ return err;
+
+ switch (magic) {
+ case 0:
+ if (size)
+ goto invalid;
+
+ goto done;
+
+ case FPSIMD_MAGIC:
+ if (user->fpsimd)
+ goto invalid;
+
+ if (offset > sizeof(sc->__reserved) -
+ sizeof(*user->fpsimd) ||
+ size < sizeof(*user->fpsimd))
+ goto invalid;
+
+ user->fpsimd = (struct fpsimd_context __user *)head;
+ break;
+
+ case ESR_MAGIC:
+ /* ignore */
+ break;
+
+ default:
+ goto invalid;
+ }
+
+ if (size < sizeof(*head))
+ goto invalid;
+
+ if (size > sizeof(sc->__reserved) - (sizeof(*head) + offset))
+ goto invalid;
+
+ offset += size;
+ }
+
+done:
+ if (!user->fpsimd)
+ goto invalid;
+
+ return 0;
+
+invalid:
+ return -EINVAL;
+}
+
static int restore_sigframe(struct pt_regs *regs,
struct rt_sigframe __user *sf)
{
sigset_t set;
int i, err;
- void *aux = sf->uc.uc_mcontext.__reserved;
+ struct user_ctxs user;
err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
if (err == 0)
@@ -116,12 +196,11 @@ static int restore_sigframe(struct pt_regs *regs,
regs->syscallno = ~0UL;
err |= !valid_user_regs(®s->user_regs, current);
+ if (err == 0)
+ err = parse_user_sigframe(&user, sf);
- if (err == 0) {
- struct fpsimd_context *fpsimd_ctx =
- container_of(aux, struct fpsimd_context, head);
- err |= restore_fpsimd_context(fpsimd_ctx);
- }
+ if (err == 0)
+ err = restore_fpsimd_context(user.fpsimd);
return err;
}
@@ -162,10 +241,11 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
return 0;
}
-static int setup_sigframe(struct rt_sigframe __user *sf,
+static int setup_sigframe(struct rt_sigframe_user_layout *user,
struct pt_regs *regs, sigset_t *set)
{
int i, err = 0;
+ struct rt_sigframe __user *sf = user->sigframe;
void *aux = sf->uc.uc_mcontext.__reserved;
struct _aarch64_ctx *end;
@@ -209,33 +289,32 @@ static int setup_sigframe(struct rt_sigframe __user *sf,
return err;
}
-static struct rt_sigframe __user *get_sigframe(struct ksignal *ksig,
- struct pt_regs *regs)
+static int get_sigframe(struct rt_sigframe_user_layout *user,
+ struct ksignal *ksig, struct pt_regs *regs)
{
unsigned long sp, sp_top;
- struct rt_sigframe __user *frame;
sp = sp_top = sigsp(regs->sp, ksig);
sp = (sp - sizeof(struct rt_sigframe)) & ~15;
- frame = (struct rt_sigframe __user *)sp;
+ user->sigframe = (struct rt_sigframe __user *)sp;
/*
* Check that we can actually write to the signal frame.
*/
- if (!access_ok(VERIFY_WRITE, frame, sp_top - sp))
- frame = NULL;
+ if (!access_ok(VERIFY_WRITE, user->sigframe, sp_top - sp))
+ return -EFAULT;
- return frame;
+ return 0;
}
static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
- void __user *frame, int usig)
+ struct rt_sigframe_user_layout *user, int usig)
{
__sigrestore_t sigtramp;
regs->regs[0] = usig;
- regs->sp = (unsigned long)frame;
+ regs->sp = (unsigned long)user->sigframe;
regs->regs[29] = regs->sp + offsetof(struct rt_sigframe, fp);
regs->pc = (unsigned long)ka->sa.sa_handler;
@@ -250,20 +329,22 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
+ struct rt_sigframe_user_layout user;
struct rt_sigframe __user *frame;
int err = 0;
- frame = get_sigframe(ksig, regs);
- if (!frame)
+ if (get_sigframe(&user, ksig, regs))
return 1;
+ frame = user.sigframe;
+
__put_user_error(0, &frame->uc.uc_flags, err);
__put_user_error(NULL, &frame->uc.uc_link, err);
err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
- err |= setup_sigframe(frame, regs, set);
+ err |= setup_sigframe(&user, regs, set);
if (err == 0) {
- setup_return(regs, &ksig->ka, frame, usig);
+ setup_return(regs, &ksig->ka, &user, usig);
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
regs->regs[1] = (unsigned long)&frame->info;
--
2.1.4
^ permalink raw reply related
* [RFC PATCH 00/29] arm64: Scalable Vector Extension core support
From: Dave Martin @ 2016-11-25 19:38 UTC (permalink / raw)
To: linux-arm-kernel
The Scalable Vector Extension (SVE) [1] is an extension to AArch64 which
adds extra SIMD functionality and supports much larger vectors.
This series implements core Linux support for SVE.
Recipents not copied on the whole series can find the rest of the
patches in the linux-arm-kernel archives [2].
The first 5 patches "arm64: signal: ..." factor out the allocation and
placement of state information in the signal frame. The first three
are prerequisites for the SVE support patches.
Patches 04-05 implement expansion of the signal frame, and may remain
controversial due to ABI break issues:
* Discussion is needed on how userspace should detect/negotiate signal
frame size in order for this expansion mechanism to be workable.
The remaining patches implement initial SVE support for Linux, with the
following limitations:
* No KVM/virtualisation support for guests.
* No independent SVE vector length configuration per thread. This is
planned, but will follow as a separate add-on series.
* As a temporary workaround for the signal frame size issue, vector
length is software-limited to 512 bits (see patch 29), with a
build-time kernel configuration option to relax this.
Discussion is needed on how to smooth address the signal ABI issues
so that this workaround can be removed.
* A fair number of development BUG_ON()s are still present, which
will be demoted or removed for merge.
* There is a context-switch race condition lurking somewhere which
fires in certain situations with my development KVM hacks (not part
of this posting) -- the underlying bug might or might not be in this
series.
Review and comments welcome.
Cheers
---Dave
[1] https://community.arm.com/groups/processors/blog/2016/08/22/technology-update-the-scalable-vector-extension-sve-for-the-armv8-a-architecture
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-November/thread.html
Alan Hayward (1):
arm64/sve: ptrace support
Dave Martin (28):
arm64: signal: Refactor sigcontext parsing in rt_sigreturn
arm64: signal: factor frame layout and population into separate passes
arm64: signal: factor out signal frame record allocation
arm64: signal: Allocate extra sigcontext space as needed
arm64: signal: Parse extra_context during sigreturn
arm64: efi: Add missing Kconfig dependency on KERNEL_MODE_NEON
arm64/sve: Allow kernel-mode NEON to be disabled in Kconfig
arm64/sve: Low-level save/restore code
arm64/sve: Boot-time feature detection and reporting
arm64/sve: Boot-time feature enablement
arm64/sve: Expand task_struct for Scalable Vector Extension state
arm64/sve: Save/restore SVE state on context switch paths
arm64/sve: Basic support for KERNEL_MODE_NEON
Revert "arm64/sve: Allow kernel-mode NEON to be disabled in Kconfig"
arm64/sve: Restore working FPSIMD save/restore around signals
arm64/sve: signal: Add SVE state record to sigcontext
arm64/sve: signal: Dump Scalable Vector Extension registers to user
stack
arm64/sve: signal: Restore FPSIMD/SVE state in rt_sigreturn
arm64/sve: Avoid corruption when replacing the SVE state
arm64/sve: traps: Add descriptive string for SVE exceptions
arm64/sve: Enable SVE on demand for userspace
arm64/sve: Implement FPSIMD-only context for tasks not using SVE
arm64/sve: Move ZEN handling to the common task_fpsimd_load() path
arm64/sve: Discard SVE state on system call
arm64/sve: Avoid preempt_disable() during sigreturn
arm64/sve: Avoid stale user register state after SVE access exception
arm64: KVM: Treat SVE use by guests as undefined instruction execution
arm64/sve: Limit vector length to 512 bits by default
arch/arm64/Kconfig | 48 +++
arch/arm64/include/asm/esr.h | 3 +-
arch/arm64/include/asm/fpsimd.h | 37 +++
arch/arm64/include/asm/fpsimdmacros.h | 145 +++++++++
arch/arm64/include/asm/kvm_arm.h | 1 +
arch/arm64/include/asm/sysreg.h | 11 +
arch/arm64/include/asm/thread_info.h | 2 +
arch/arm64/include/uapi/asm/hwcap.h | 1 +
arch/arm64/include/uapi/asm/ptrace.h | 125 ++++++++
arch/arm64/include/uapi/asm/sigcontext.h | 117 ++++++++
arch/arm64/kernel/cpufeature.c | 3 +
arch/arm64/kernel/cpuinfo.c | 1 +
arch/arm64/kernel/entry-fpsimd.S | 17 ++
arch/arm64/kernel/entry.S | 18 +-
arch/arm64/kernel/fpsimd.c | 301 ++++++++++++++++++-
arch/arm64/kernel/head.S | 16 +-
arch/arm64/kernel/process.c | 2 +-
arch/arm64/kernel/ptrace.c | 254 +++++++++++++++-
arch/arm64/kernel/setup.c | 3 +
arch/arm64/kernel/signal.c | 497 +++++++++++++++++++++++++++++--
arch/arm64/kernel/signal32.c | 2 +-
arch/arm64/kernel/traps.c | 1 +
arch/arm64/kvm/handle_exit.c | 9 +
arch/arm64/mm/proc.S | 27 +-
include/uapi/linux/elf.h | 1 +
25 files changed, 1583 insertions(+), 59 deletions(-)
--
2.1.4
^ permalink raw reply
* [PATCH 0/2] kexec-tools: arm64: Add dcache enabling facility
From: James Morse @ 2016-11-25 18:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <8415f028-f42e-2980-9b60-e85aae046d02@infradead.org>
Hi guys,
On 22/11/16 18:56, Geoff Levand wrote:
> On 11/21/2016 08:32 PM, Pratyush Anand wrote:
>> It takes more that 2 minutes to verify SHA in purgatory when vmlinuz image
>> is around 13MB and initramfs is around 30MB. It takes more than 20 second
>> even when we have -O2 optimization enabled. However, if dcache is enabled
>> during purgatory execution then, it takes just a second in SHA verification.
>
> As I had mentioned in another thread, I think -O2 optimization is
> sufficient considering the complexity of the code needed to enable
> the dcache. Integrity checking is only needed for crash dump
> support. If the crash reboot takes an extra 20 seconds does it
> matter?
>
> For the re-boot of a stable system where the new kernel is loaded
> then immediately kexec'ed into integrity checking is not needed.
I agree.
If purgatory detects corruption in the new-kernel or initramfs all it can do is
spin in a loop. If we are very lucky in could print a debug message to the
serial console. If the planets line up, someone might see this message.
If we validate the checksum in the kernel kexec core code we can possibly fail
the syscall and return to a running system. We can use EFI runtime services to
try and reboot, or print a message to somewhere that might get seen such as
syslog or netconsole.
I agree kdump is different but I don't think 'we crashed' is performance critical.
Thanks,
James
^ permalink raw reply
* [PATCH 1/2] arm64: Add enable/disable d-cache support for purgatory
From: James Morse @ 2016-11-25 18:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <7a4866b928c0905ec1074dce1bfc7984c968a58a.1479788404.git.panand@redhat.com>
Hi Pratyush,
(CC: Mark, mismatched memory attributes in paragraph 3?)
On 22/11/16 04:32, Pratyush Anand wrote:
> This patch adds support to enable/disable d-cache, which can be used for
> faster purgatory sha256 verification.
(I'm not clear why we want the sha256, but that is being discussed elsewhere on
the thread)
> We are supporting only 4K and 64K page sizes. This code will not work if a
> hardware is not supporting at least one of these page sizes. Therefore,
> D-cache is disabled by default and enabled only when "enable-dcache" is
> passed to the kexec().
I don't think the maybe-4K/maybe-64K/maybe-neither logic is needed. It would be
a lot simpler to only support one page size, which should be 4K as that is what
UEFI requires. (If there are CPUs that only support one size, I bet its 4K!)
I would go as far as to generate the page tables at 'kexec -l' time, and only if
'/sys/firmware/efi' exists to indicate we booted via UEFI. (and therefore must
support 4K pages). This would keep the purgatory code as simple as possible.
I don't think the performance difference between 4K and 64K page sizes will be
measurable, is purgatory really performance sensitive code?
> Since this is an identity mapped system, so VA_BITS will be same as max PA
> bits supported. If VA_BITS <= 42 for 64K and <= 39 for 4K then only one
> level of page table will be there with block descriptor entries.
> Otherwise, For 4K mapping, TTBR points to level 0 lookups, which will have
> only table entries pointing to a level 1 lookup. Level 1 will have only
> block entries which will map 1GB block. For 64K mapping, TTBR points to
> level 1 lookups, which will have only table entries pointing to a level 2
> lookup. Level 2 will have only block entries which will map 512MB block. If
This is more complexity to pick a VA size. Why not always use the maximum 48bit
VA? The cost is negligible compared to having simpler (easier to review!)
purgatory code.
By always using 1GB blocks you may be creating aliases with mismatched attributes:
* If kdump only reserves 128MB, your 1GB mapping will alias whatever else was
in the same 1GB of address space. This could be a reserved region with some
other memory attributes.
* With kdump, we may have failed to park the other CPUs if they are executing
with interrupts masked and haven't yet handled the smp_send_stop() IPI.
* One of these other CPUs could be reading/writing in this area as it doesn't
belong to the kdump reserved area, just happens to be in the same 1GB.
I need to dig through the ARM-ARM to find out what happens next, but I'm pretty
sure this is well into the "don't do that" territory.
It would be much better to force the memory areas to be a multiple of 2MB and
2MB aligned, which will allow you to use 2M section mappings for memory, (but
not the uart). This way we only map regions we had reserved and know are memory.
> UART base address and RAM addresses are not at least 1GB and 512MB apart
> for 4K and 64K respectively, then mapping result could be unpredictable. In
> that case we need to support one more level of granularity, but until
> someone needs that keep it like this only.
>
> We can not allocate dynamic memory in purgatory. Therefore we keep page
> table allocation size fixed as (3 * MAX_PAGE_SIZE). (page_table) points to
> first level (having only table entries) and (page_table + MAX_PAGE_SIZE)
> points to table at next level (having block entries). If index for RAM
> area and UART area in first table is not same, then we will need another
> next level table which will be located at (page_table + 2 * MAX_PAGE_SIZE).
> diff --git a/purgatory/arch/arm64/cache-asm.S b/purgatory/arch/arm64/cache-asm.S
> new file mode 100644
> index 000000000000..bef97ef48888
> --- /dev/null
> +++ b/purgatory/arch/arm64/cache-asm.S
> @@ -0,0 +1,186 @@
> +/*
> + * Some of the routines have been copied from Linux Kernel, therefore
> + * copying the license as well.
> + *
> + * Copyright (C) 2001 Deep Blue Solutions Ltd.
> + * Copyright (C) 2012 ARM Ltd.
> + * Copyright (C) 2015 Pratyush Anand <panand@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "cache.h"
> +
> +/*
> + * dcache_line_size - get the minimum D-cache line size from the CTR register.
> + */
> + .macro dcache_line_size, reg, tmp
> + mrs \tmp, ctr_el0 // read CTR
> + ubfm \tmp, \tmp, #16, #19 // cache line size encoding
> + mov \reg, #4 // bytes per word
> + lsl \reg, \reg, \tmp // actual cache line size
> + .endm
> +
> +/*
> + * inval_cache_range(start, end)
> + * - x0 - start - start address of region
> + * - x1 - end - end address of region
> + */
> +.globl inval_cache_range
> +inval_cache_range:
> + dcache_line_size x2, x3
> + sub x3, x2, #1
> + tst x1, x3 // end cache line aligned?
> + bic x1, x1, x3
> + b.eq 1f
> + dc civac, x1 // clean & invalidate D / U line
> +1: tst x0, x3 // start cache line aligned?
> + bic x0, x0, x3
> + b.eq 2f
> + dc civac, x0 // clean & invalidate D / U line
> + b 3f
> +2: dc ivac, x0 // invalidate D / U line
> +3: add x0, x0, x2
> + cmp x0, x1
> + b.lo 2b
> + dsb sy
> + ret
> +/*
> + * flush_dcache_range(start, end)
> + * - x0 - start - start address of region
> + * - x1 - end - end address of region
> + *
> + */
> +.globl flush_dcache_range
> +flush_dcache_range:
> + dcache_line_size x2, x3
> + sub x3, x2, #1
> + bic x0, x0, x3
> +1: dc civac, x0 // clean & invalidate D line / unified line
> + add x0, x0, x2
> + cmp x0, x1
> + b.lo 1b
> + dsb sy
> + ret
> +
> +/*
> + * invalidate_tlbs_el1()
> + */
> +.globl invalidate_tlbs_el1
> +invalidate_tlbs_el1:
> + dsb nshst
> + tlbi vmalle1
> + dsb nsh
> + isb
> + ret
> +
> +/*
> + * invalidate_tlbs_el2()
> + */
> +.globl invalidate_tlbs_el2
> +invalidate_tlbs_el2:
> + dsb nshst
> + tlbi alle2
> + dsb nsh
> + isb
> + ret
> +
> +/*
> + * get_mm_feature_reg0_val - Get information about supported MM
> + * features
> + */
> +.globl get_mm_feature_reg0_val
> +get_mm_feature_reg0_val:
> + mrs x0, ID_AA64MMFR0_EL1
> + ret
> +
> +/*
> + * get_current_el - Get information about current exception level
> + */
> +.globl get_current_el
> +get_current_el:
> + mrs x0, CurrentEL
> + lsr x0, x0, #2
> + ret
> +
> +/*
> + * invalidate_icache - Invalidate I-cache
> + */
> +.globl invalidate_icache
> +invalidate_icache:
> + ic iallu
> + dsb nsh
> + isb
> + ret
> +
> +/*
> + * set_mair_tcr_ttbr_sctlr_el1(page_table, tcr_flags) - sets MAIR, TCR , TTBR and SCTLR registers
> + * x0 - page_table - Page Table Base
> + * x1 - tcr_flags - TCR Flags to be set
> + */
> +.globl set_mair_tcr_ttbr_sctlr_el1
> +set_mair_tcr_ttbr_sctlr_el1:
> + ldr x2, =MEMORY_ATTRIBUTES
> + msr mair_el1, x2
> + msr tcr_el1, x1
> + msr ttbr0_el1, x0
> + isb
> + mrs x0, sctlr_el1
> + ldr x3, =SCTLR_ELx_FLAGS
> + orr x0, x0, x3
> + msr sctlr_el1, x0
> + isb
> + ret
> +
> +/*
> + * set_mair_tcr_ttbr_sctlr_el2(page_table, tcr_flags) - sets MAIR, TCR , TTBR and SCTLR registers
> + * x0 - page_table - Page Table Base
> + * x1 - tcr_flags - TCR Flags to be set
> + */
> +.globl set_mair_tcr_ttbr_sctlr_el2
> +set_mair_tcr_ttbr_sctlr_el2:
> + ldr x2, =MEMORY_ATTRIBUTES
> + msr mair_el2, x2
> + msr tcr_el2, x1
> + msr ttbr0_el2, x0
> + isb
> + mrs x0, sctlr_el2
> + ldr x3, =SCTLR_ELx_FLAGS
> + orr x0, x0, x3
> + msr sctlr_el2, x0
> + isb
> + ret
> +
> +/*
> + * reset_sctlr_el1 - disables cache and mmu
> + */
> +.globl reset_sctlr_el1
> +reset_sctlr_el1:
> + mrs x0, sctlr_el1
> + bic x0, x0, #SCTLR_ELx_C
> + bic x0, x0, #SCTLR_ELx_M
> + msr sctlr_el1, x0
> + isb
> + ret
> +
> +/*
> + * reset_sctlr_el2 - disables cache and mmu
> + */
> +.globl reset_sctlr_el2
> +reset_sctlr_el2:
> + mrs x0, sctlr_el2
> + bic x0, x0, #SCTLR_ELx_C
> + bic x0, x0, #SCTLR_ELx_M
> + msr sctlr_el2, x0
> + isb
> + ret
> diff --git a/purgatory/arch/arm64/cache.c b/purgatory/arch/arm64/cache.c
> new file mode 100644
> index 000000000000..3c7e058ccf11
> --- /dev/null
> +++ b/purgatory/arch/arm64/cache.c
> @@ -0,0 +1,330 @@
> +/*
> + * Copyright (C) 2015 Pratyush Anand <panand@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +/* We are supporting only 4K and 64K page sizes. This code will not work if
> + * a hardware is not supporting at least one of these page sizes.
> + * Therefore, D-cache is disabled by default and enabled only when
> + * "enable-dcache" is passed to the kexec().
> + * Since this is an identity mapped system, so VA_BITS will be same as max
> + * PA bits supported. If VA_BITS <= 42 for 64K and <= 39 for 4K then only
> + * one level of page table will be there with block descriptor entries.
> + * Otherwise, For 4K mapping, TTBR points to level 0 lookups, which will
> + * have only table entries pointing to a level 1 lookup. Level 1 will have
> + * only block entries which will map 1GB block.For 64K mapping, TTBR points
> + * to level 1 lookups, which will have only table entries pointing to a
> + * level 2 lookup. Level 2 will have only block entries which will map
> + * 512MB block. If UART base address and RAM addresses are not at least 1GB
> + * and 512MB apart for 4K and 64K respectively, then mapping result could
> + * be unpredictable. In that case we need to support one more level of
> + * granularity, but until someone needs that keep it like this only.
> + * We can not allocate dynamic memory in purgatory. Therefore we keep page
> + * table allocation size fixed as (3 * MAX_PAGE_SIZE). (page_table) points
> + * to first level (having only table entries) and (page_table +
> + * MAX_PAGE_SIZE) points to table at next level (having block entries). If
> + * index for RAM area and UART area in first table is not same, then we
> + * will need another next level table which will be located at (page_table
> + * + 2 * MAX_PAGE_SIZE).
> + */
> +
> +#include <stdint.h>
> +#include <string.h>
> +#include <purgatory.h>
> +#include "cache.h"
> +
> +static uint64_t page_shift;
> +static uint64_t pgtable_level;
> +static uint64_t va_bits;
> +
> +static uint64_t page_table[PAGE_TABLE_SIZE / sizeof(uint64_t)] __attribute__ ((aligned (MAX_PAGE_SIZE))) = { };
> +static uint64_t page_table_used;
> +
> +#define PAGE_SIZE (1 << page_shift)
> +/*
> + * is_4k_page_supported - return true if 4k page is supported else
> + * false
> + */
> +static int is_4k_page_supported(void)
> +{
> + return ((get_mm_feature_reg0_val() & ID_AA64MMFR0_TGRAN4_MASK) ==
> + ID_AA64MMFR0_TGRAN4_SUPPORTED);
> +}
> +
> +/*
> + * is_64k_page_supported - return true if 64k page is supported else
> + * false
> + */
> +static int is_64k_page_supported(void)
> +{
> + return ((get_mm_feature_reg0_val() & ID_AA64MMFR0_TGRAN64_MASK) ==
> + ID_AA64MMFR0_TGRAN64_SUPPORTED);
> +}
> +
> +/*
> + * get_ips_bits - return supported IPS bits
> + */
> +static uint64_t get_ips_bits(void)
> +{
> + return ((get_mm_feature_reg0_val() & ID_AA64MMFR0_PARANGE_MASK) >>
> + ID_AA64MMFR0_PARANGE_SHIFT);
> +}
> +
> +/*
> + * get_va_bits - return supported VA bits (For identity mapping VA = PA)
> + */
> +static uint64_t get_va_bits(void)
> +{
> + uint64_t ips = get_ips_bits();
> +
> + switch(ips) {
> + case ID_AA64MMFR0_PARANGE_48:
> + return 48;
> + case ID_AA64MMFR0_PARANGE_44:
> + return 44;
> + case ID_AA64MMFR0_PARANGE_42:
> + return 42;
> + case ID_AA64MMFR0_PARANGE_40:
> + return 40;
> + case ID_AA64MMFR0_PARANGE_36:
> + return 36;
> + default:
> + return 32;
> + }
> +}
> +
> +/*
> + * get_section_shift - get block shift for supported page size
> + */
> +static uint64_t get_section_shift(void)
> +{
> + if (page_shift == 16)
> + return 29;
> + else if(page_shift == 12)
> + return 30;
> + else
> + return 0;
> +}
> +
> +/*
> + * get_section_mask - get section mask for supported page size
> + */
> +static uint64_t get_section_mask(void)
> +{
> + if (page_shift == 16)
> + return 0x1FFF;
> + else if(page_shift == 12)
> + return 0x1FF;
> + else
> + return 0;
> +}
> +
> +/*
> + * get_pgdir_shift - get pgdir shift for supported page size
> + */
> +static uint64_t get_pgdir_shift(void)
> +{
> + if (page_shift == 16)
> + return 42;
> + else if(page_shift == 12)
> + return 39;
> + else
> + return 0;
> +}
> +
> +/*
> + * init_page_table - Initializes page table locations
> + */
> +
> +static void init_page_table(void)
> +{
> + /*
> + * Invalidate the page tables to avoid potential dirty cache lines
> + * being evicted.
> + */
How do these lines get dirty? arm64_relocate_new_kernel() invalidated these
pages to PoC before it copied the data. If they were speculatively fetched (I
don't know the rules of when/how that happens) they may be wrong, but will be
clean and not written back. If we change them in purgatory, you invalidate again
from enable_mmu_dcache(). I don't think this is needed.
> + inval_cache_range((uint64_t)page_table,
> + (uint64_t)page_table + PAGE_TABLE_SIZE);
> + memset(page_table, 0, PAGE_TABLE_SIZE);
> +}
> +/*
> + * create_identity_mapping(start, end, flags)
> + * start - start address
> + * end - end address
> + * flags - MMU Flags for Normal or Device type memory
> + */
> +static void create_identity_mapping(uint64_t start, uint64_t end,
> + uint64_t flags)
> +{
> + uint32_t sec_shift, pgdir_shift, sec_mask;
> + uint64_t desc, s1, e1, s2, e2;
> + uint64_t *table2;
> +
> + s1 = start;
> + e1 = end - 1;
> +
> + sec_shift = get_section_shift();
> + if (pgtable_level == 1) {
> + s1 >>= sec_shift;
> + e1 >>= sec_shift;
> + do {
> + desc = s1 << sec_shift;
> + desc |= flags;
> + page_table[s1] = desc;
> + s1++;
> + } while (s1 <= e1);
> + } else {
> + pgdir_shift = get_pgdir_shift();
> + sec_mask = get_section_mask();
> + s1 >>= pgdir_shift;
> + e1 >>= pgdir_shift;
> + do {
> + /*
> + * If there is no table entry then write a new
> + * entry else, use old entry
> + */
> + if (!page_table[s1]) {
> + table2 = &page_table[(++page_table_used *
> + MAX_PAGE_SIZE) /
> + sizeof(uint64_t)];
> + desc = (uint64_t)table2 | PMD_TYPE_TABLE;
> + page_table[s1] = desc;
> + } else {
> + table2 = (uint64_t *)(page_table[s1] &
> + ~PMD_TYPE_MASK);
> + }
> + s1++;
> + s2 = start >> sec_shift;
> + s2 &= sec_mask;
> + e2 = (end - 1) >> sec_shift;
> + e2 &= sec_mask;
> + do {
> + desc = s2 << sec_shift;
> + desc |= flags;
> + table2[s2] = desc;
> + s2++;
> + } while (s2 <= e2);
> + } while (s1 <= e1);
> + }
> +}
(I will need to come back to this ... it looks pretty complicated. If you mimic
Linux's p?d/pte macros it will be more familiar and easier to read.)
> +
> +/*
> + * enable_mmu_dcache: Enable mmu and D-cache in sctlr_el1
> + */
> +static void enable_mmu_dcache(void)
> +{
> + uint64_t tcr_flags = TCR_FLAGS | TCR_T0SZ(va_bits);
> +
> + switch(page_shift) {
> + case 16:
> + tcr_flags |= TCR_TG0_64K;
> + break;
> + case 12:
> + tcr_flags |= TCR_TG0_4K;
> + break;
> + default:
> + printf("page shift not supported\n");
> + return;
> + }
> + /*
> + * Since the page tables have been populated with non-cacheable
> + * accesses (MMU disabled), invalidate the page tables to remove
> + * any speculatively loaded cache lines.
> + */
> + inval_cache_range((uint64_t)page_table,
> + (uint64_t)page_table + PAGE_TABLE_SIZE);
> +
> + switch(get_current_el()) {
> + case 2:
> + invalidate_tlbs_el2();
> + tcr_flags |= (get_ips_bits() << TCR_PS_EL2_SHIFT);
> + set_mair_tcr_ttbr_sctlr_el2((uint64_t)page_table, tcr_flags);
> + break;
> + case 1:
> + invalidate_tlbs_el1();
> + tcr_flags |= (get_ips_bits() << TCR_IPS_EL1_SHIFT);
> + set_mair_tcr_ttbr_sctlr_el1((uint64_t)page_table, tcr_flags);
> + break;
> + default:
> + return;
> + }
> + invalidate_icache();
What is this protecting against? We have executed instructions between here and
setting the I+M bits in set_mair_tcr_ttbr_sctlr_el1(). (so it may be too late)
arm64_relocate_new_kernel() already did 'ic iallu' before it branched into the
purgatory code. No executable code has been changed or moved since then, so I
don't think this is necessary.
> +}
> +
> +/*
> + * enable_dcache: Enable D-cache and set appropriate attributes
> + * ram_start - Start address of RAM
> + * ram_end - End address of RAM
> + * uart_base - Base address of uart
> + */
> +int enable_dcache(uint64_t ram_start, uint64_t ram_end, uint64_t uart_base)
> +{
> + va_bits = get_va_bits();
> +
> + page_table_used = 0;
> + if (is_64k_page_supported()) {
> + page_shift = 16;
> + if (va_bits <= 42)
> + pgtable_level = 1;
> + else
> + pgtable_level = 2;
> + } else if (is_4k_page_supported()) {
> + page_shift = 12;
> + if (va_bits <= 39)
> + pgtable_level = 1;
> + else
> + pgtable_level = 2;
> + } else {
> + printf("Valid Page Granule not supported by hardware\n");
> + return -1;
> + }
> + init_page_table();
> + create_identity_mapping(ram_start, ram_end, MM_MMUFLAGS_NORMAL);
> + printf("Normal identity mapping created from %lx to %lx\n",
> + ram_start, ram_end);
> + if (uart_base) {
> + create_identity_mapping((uint64_t)uart_base,
> + (uint64_t)uart_base + PAGE_SIZE,
> + MM_MMUFLAGS_DEVICE);
> + printf("Device identity mapping created from %lx to %lx\n",
> + (uint64_t)uart_base,
> + (uint64_t)uart_base + PAGE_SIZE);
> + }
> + enable_mmu_dcache();
> + printf("Cache Enabled\n");
> +
> + return 0;
> +}
> +
> +/*
> + * disable_dcache: Disable D-cache and flush RAM locations
> + * ram_start - Start address of RAM
> + * ram_end - End address of RAM
> + */
> +void disable_dcache(uint64_t ram_start, uint64_t ram_end)
> +{
> + switch(get_current_el()) {
> + case 2:
> + reset_sctlr_el2();
> + break;
> + case 1:
> + reset_sctlr_el1();
You have C code running between disabling the MMU and cleaning the cache. The
compiler is allowed to move data on and off the stack in here, but after
disabling the MMU it will see whatever was on the stack before we turned the MMU
on. Any data written at the beginning of this function is left in the caches.
I'm afraid this sort of stuff needs to be done in assembly!
> + break;
> + default:
> + return;
> + }
> + invalidate_icache();
> + flush_dcache_range(ram_start, ram_end);
> + printf("Cache Disabled\n");
> +}
> diff --git a/purgatory/arch/arm64/cache.h b/purgatory/arch/arm64/cache.h
> new file mode 100644
> index 000000000000..c988020566e3
> --- /dev/null
> +++ b/purgatory/arch/arm64/cache.h
> @@ -0,0 +1,79 @@
> +#ifndef __CACHE_H__
> +#define __CACHE_H__
> +
> +#define MT_DEVICE_NGNRNE 0
> +#define MT_DEVICE_NGNRE 1
> +#define MT_DEVICE_GRE 2
> +#define MT_NORMAL_NC 3
> +#define MT_NORMAL 4
You only use two of these. I guess this is so the MAIR value matches the kernel?
> +
> +#ifndef __ASSEMBLER__
> +
> +#define MAX_PAGE_SIZE 0x10000
> +#define PAGE_TABLE_SIZE (3 * MAX_PAGE_SIZE)
> +#define ID_AA64MMFR0_TGRAN64_SHIFT 24
> +#define ID_AA64MMFR0_TGRAN4_SHIFT 28
> +#define ID_AA64MMFR0_TGRAN64_MASK (0xFUL << ID_AA64MMFR0_TGRAN64_SHIFT)
> +#define ID_AA64MMFR0_TGRAN4_MASK (0xFUL << ID_AA64MMFR0_TGRAN4_SHIFT)
> +#define ID_AA64MMFR0_TGRAN64_SUPPORTED 0x0
> +#define ID_AA64MMFR0_TGRAN4_SUPPORTED 0x0
> +#define ID_AA64MMFR0_PARANGE_SHIFT 0
> +#define ID_AA64MMFR0_PARANGE_MASK (0xFUL << ID_AA64MMFR0_PARANGE_SHIFT)
> +#define ID_AA64MMFR0_PARANGE_48 0x5
> +#define ID_AA64MMFR0_PARANGE_44 0x4
> +#define ID_AA64MMFR0_PARANGE_42 0x3
> +#define ID_AA64MMFR0_PARANGE_40 0x2
> +#define ID_AA64MMFR0_PARANGE_36 0x1
> +#define ID_AA64MMFR0_PARANGE_32 0x0
> +
> +#define TCR_TG0_64K (1UL << 14)
> +#define TCR_TG0_4K (0UL << 14)
> +#define TCR_SHARED_NONE (0UL << 12)
> +#define TCR_ORGN_WBWA (1UL << 10)
> +#define TCR_IRGN_WBWA (1UL << 8)
> +#define TCR_IPS_EL1_SHIFT 32
> +#define TCR_PS_EL2_SHIFT 16
> +#define TCR_T0SZ(x) ((unsigned long)(64 - (x)) << 0)
> +#define TCR_FLAGS (TCR_SHARED_NONE | TCR_ORGN_WBWA | TCR_IRGN_WBWA)
> +
> +#define PMD_TYPE_SECT (1UL << 0)
> +#define PMD_TYPE_TABLE (3UL << 0)
> +#define PMD_TYPE_MASK 0x3
> +#define PMD_SECT_AF (1UL << 10)
> +#define PMD_ATTRINDX(t) ((unsigned long)(t) << 2)
> +#define PMD_FLAGS_NORMAL (PMD_TYPE_SECT | PMD_SECT_AF)
> +#define PMD_SECT_PXN (1UL << 53)
> +#define PMD_SECT_UXN (1UL << 54)
> +#define PMD_FLAGS_DEVICE (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_PXN | PMD_SECT_UXN)
> +#define MM_MMUFLAGS_NORMAL PMD_ATTRINDX(MT_NORMAL) | PMD_FLAGS_NORMAL
> +#define MM_MMUFLAGS_DEVICE PMD_ATTRINDX(MT_DEVICE_NGNRE) | PMD_FLAGS_DEVICE
> +
> +void disable_dcache(uint64_t ram_start, uint64_t ram_end);
> +int enable_dcache(uint64_t ram_start, uint64_t ram_end, uint64_t uart_base);
> +uint64_t get_mm_feature_reg0_val(void);
> +void inval_cache_range(uint64_t start, uint64_t end);
> +void flush_dcache_range(uint64_t start, uint64_t end);
> +uint64_t get_current_el(void);
> +void set_mair_tcr_ttbr_sctlr_el1(uint64_t page_table, uint64_t tcr_flags);
> +void set_mair_tcr_ttbr_sctlr_el2(uint64_t page_table, uint64_t tcr_flags);
> +void invalidate_tlbs_el1(void);
> +void invalidate_tlbs_el2(void);
> +void invalidate_icache(void);
> +void reset_sctlr_el1(void);
> +void reset_sctlr_el2(void);
> +#else
> +#define MEMORY_ATTRIBUTES ((0x00 << (MT_DEVICE_NGNRNE*8)) | \
> + (0x04 << (MT_DEVICE_NGNRE*8)) | \
> + (0x0C << (MT_DEVICE_GRE*8)) | \
> + (0x44 << (MT_NORMAL_NC*8)) | \
> + (0xFF << (MT_NORMAL*8)))
Again, you only use two of these.
> +/* Common SCTLR_ELx flags. */
> +#define SCTLR_ELx_I (1 << 12)
> +#define SCTLR_ELx_C (1 << 2)
> +#define SCTLR_ELx_M (1 << 0)
> +
> +#define SCTLR_ELx_FLAGS (SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_I)
> +
> +#endif
> +#endif
>
Thanks!
James
^ permalink raw reply
* [PATCH V5 03/10] efi: parse ARMv8 processor error
From: James Morse @ 2016-11-25 18:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479767763-27532-4-git-send-email-tbaicar@codeaurora.org>
Hi Tyler,
On 21/11/16 22:35, Tyler Baicar wrote:
> Add support for ARMv8 Common Platform Error Record (CPER).
> UEFI 2.6 specification adds support for ARMv8 specific
> processor error information to be reported as part of the
> CPER records. This provides more detail on for processor error logs.
I think I'm missing a big part of the puzzle here, I will come back to this next
week. I can't quite line up some of the masks and shifts with the table
descriptions in the UEFI spec[0].
> diff --git a/include/linux/cper.h b/include/linux/cper.h
> index 13ea41c..2a9d553 100644
> --- a/include/linux/cper.h
> +++ b/include/linux/cper.h
> @@ -180,6 +185,10 @@ enum {
> #define CPER_SEC_PROC_IPF \
> UUID_LE(0xE429FAF1, 0x3CB7, 0x11D4, 0x0B, 0xCA, 0x07, 0x00, \
> 0x80, 0xC7, 0x3C, 0x88, 0x81)
> +/* Processor Specific: ARMv8 */
> +#define CPER_SEC_PROC_ARMV8 \
> + UUID_LE(0xE19E3D16, 0xBC11, 0x11E4, 0x9C, 0xAA, 0xC2, 0x05, \
> + 0x1D, 0x5D, 0x46, 0xB0)
Nit: UEFI v2.6 N.2.2 (table 249) describes this as 'ARM' not 'ARMV8' (which is
an architectural version).
> /* Platform Memory */
> #define CPER_SEC_PLATFORM_MEM \
> UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
> @@ -255,6 +264,34 @@ enum {
>
> #define CPER_PCIE_SLOT_SHIFT 3
>
> +#define CPER_ARMV8_ERR_INFO_NUM_MASK 0x00000000000000FF
> +#define CPER_ARMV8_CTX_INFO_NUM_MASK 0x0000000000FFFF00
Table 260 describes both ERR_INFO_NUM and CONTEXT_INFO_NUM for as both being
2bytes long, as does your struct cper_sec_proc_armv8 below. Are these for
something else? Do these correspond with one of the four bitfield formats
described in Table 262->265?
I can't see where they are used, and they look like they are reaching across
multiple fields in a struct.
> +#define CPER_ARMV8_CTX_INFO_NUM_SHIFT 8
> +
> +#define CPER_ARMV8_VALID_MPIDR 0x00000001
> +#define CPER_ARMV8_VALID_AFFINITY_LEVEL 0x00000002
> +#define CPER_ARMV8_VALID_RUNNING_STATE 0x00000004
> +#define CPER_ARMV8_VALID_VENDOR_INFO 0x00000008
> +
> +#define CPER_ARMV8_INFO_VALID_MULTI_ERR 0x0001
> +#define CPER_ARMV8_INFO_VALID_FLAGS 0x0002
> +#define CPER_ARMV8_INFO_VALID_ERR_INFO 0x0004
> +#define CPER_ARMV8_INFO_VALID_VIRT_ADDR 0x0008
> +#define CPER_ARMV8_INFO_VALID_PHYSICAL_ADDR 0x0010
> +
> +#define CPER_ARMV8_INFO_FLAGS_FIRST 0x0001
> +#define CPER_ARMV8_INFO_FLAGS_LAST 0x0002
> +#define CPER_ARMV8_INFO_FLAGS_PROPAGATED 0x0004
> +
> +#define CPER_AARCH64_CTX_LEN 368
> +#define CPER_AARCH32_CTX_LEN 256
Are these the worst case sizes for combinations of the structures in N2.4.4.2?
(Tables 266 to 273)
If so is there any chance they could be sizeof(<some union of structs>), even if
the structs are things like:
> /* ARMv8 AArch64 GPRs (Type 4) - defined in UEFI Spec N2.4.4.2 */
> struct cper_armv8_aarch64_gprs {
> u64 regs[32];
> }
This way its easier to check the number is correct, and if a new type is added
this won't get forgotten.
> +#define CPER_ARMV8_CTX_TYPE_MASK 0x000000000000000F
> +#define CPER_ARMV8_CTX_EL_MASK 0x0000000000000070
> +#define CPER_ARMV8_CTX_NS_MASK 0x0000000000000080
> +#define CPER_ARMV8_CTX_EL_SHIFT 4
> +#define CPER_ARMV8_CTX_NS_SHIFT 7
> +
Again, I can't work out what these correspond to. I can't see a secure bit or EL
field in any of those UEFI tables.
Is this one of the 'ARM Vendor Specific Micro-Architecture Error Structure's? If
so we should have some infrastructure for picking the correct (or unknown)
decode function based on a range of MIDRs.
> #define acpi_hest_generic_data_error_length(gdata) \
> (((struct acpi_hest_generic_data *)(gdata))->error_data_length)
> #define acpi_hest_generic_data_size(gdata) \
> @@ -352,6 +389,41 @@ struct cper_ia_proc_ctx {
> __u64 mm_reg_addr;
> };
>
> +/* ARMv8 Processor Error Section */
> +struct cper_sec_proc_armv8 {
> + __u32 validation_bits;
> + __u16 err_info_num; /* Number of Processor Error Info */
> + __u16 context_info_num; /* Number of Processor Context Info Records*/
> + __u32 section_length;
> + __u8 affinity_level;
> + __u8 reserved[3]; /* must be zero */
> + __u64 mpidr;
> + __u64 midr;
> + __u32 running_state; /* Bit 0 set - Processor running. PSCI = 0 */
> + __u32 psci_state;
> +};
> +
> +/* ARMv8 Processor Error Information Structure */
> +struct cper_armv8_err_info {
> + __u8 version;
> + __u8 length;
> + __u16 validation_bits;
> + __u8 type;
> + __u16 multiple_error;
> + __u8 flags;
> + __u64 error_info;
> + __u64 virt_fault_addr;
> + __u64 physical_fault_addr;
> +};
> +/* ARMv8 AARCH64 Processor Context Information Structure */
> +struct cper_armv8_aarch64_ctx {
> + __u8 type_el_ns;
> + __u8 reserved[7]; /* must be zero */
> + __u8 gpr[288];
> + __u8 spr[68];
> +};
Is this:
"Table 265. ARM Processor Error Context Information Header Structure"?
Sorry if I've missed something blindingly obvious!
Thanks,
James
[0] http://www.uefi.org/sites/default/files/resources/UEFI%20Spec%202_6.pdf
^ permalink raw reply
* [PATCH V5 02/10] ras: acpi/apei: cper: generic error data entry v3 per ACPI 6.1
From: James Morse @ 2016-11-25 18:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479767763-27532-3-git-send-email-tbaicar@codeaurora.org>
Hi Tyler,
On 21/11/16 22:35, Tyler Baicar wrote:
> Currently when a RAS error is reported it is not timestamped.
> The ACPI 6.1 spec adds the timestamp field to the generic error
> data entry v3 structure. The timestamp of when the firmware
> generated the error is now being reported.
> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
> index b79abc5..9063d68 100644
> --- a/drivers/acpi/apei/ghes.c
> +++ b/drivers/acpi/apei/ghes.c
> @@ -420,7 +420,8 @@ static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int
> int flags = -1;
> int sec_sev = ghes_severity(gdata->error_severity);
> struct cper_sec_mem_err *mem_err;
> - mem_err = (struct cper_sec_mem_err *)(gdata + 1);
> +
> + mem_err = acpi_hest_generic_data_payload(gdata);
>
> if (!(mem_err->validation_bits & CPER_MEM_VALID_PA))
> return;
> @@ -450,14 +451,18 @@ static void ghes_do_proc(struct ghes *ghes,
> {
> int sev, sec_sev;
> struct acpi_hest_generic_data *gdata;
> + uuid_le sec_type;
ghes.c doesn't include <linux/uuid.h>, but I see it already uses uuid_le_cmp().
Worth fixing as part of this patch?
>
> sev = ghes_severity(estatus->error_severity);
> apei_estatus_for_each_section(estatus, gdata) {
> sec_sev = ghes_severity(gdata->error_severity);
> - if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
> + sec_type = *(uuid_le *)gdata->section_type;
> +
You don't use sec_type again here, why change this?
(should it be in a later patch?)
> + if (!uuid_le_cmp(sec_type,
> CPER_SEC_PLATFORM_MEM)) {
> struct cper_sec_mem_err *mem_err;
> - mem_err = (struct cper_sec_mem_err *)(gdata+1);
> +
> + mem_err = acpi_hest_generic_data_payload(gdata);
> ghes_edac_report_mem_error(ghes, sev, mem_err);
>
> arch_apei_report_mem_error(sev, mem_err);
> @@ -467,7 +472,8 @@ static void ghes_do_proc(struct ghes *ghes,
> else if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
> CPER_SEC_PCIE)) {
> struct cper_sec_pcie *pcie_err;
> - pcie_err = (struct cper_sec_pcie *)(gdata+1);
> +
> + pcie_err = acpi_hest_generic_data_payload(gdata);
> if (sev == GHES_SEV_RECOVERABLE &&
> sec_sev == GHES_SEV_RECOVERABLE &&
> pcie_err->validation_bits & CPER_PCIE_VALID_DEVICE_ID &&
> diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
> index d425374..7e2439e 100644
> --- a/drivers/firmware/efi/cper.c
> +++ b/drivers/firmware/efi/cper.c
> @@ -32,6 +32,9 @@
> #include <linux/acpi.h>
> #include <linux/pci.h>
> #include <linux/aer.h>
> +#include <linux/printk.h>
> +#include <linux/bcd.h>
> +#include <acpi/ghes.h>
>
> #define INDENT_SP " "
>
> @@ -386,13 +389,37 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
> pfx, pcie->bridge.secondary_status, pcie->bridge.control);
> }
>
> +static void cper_estatus_print_section_v300(const char *pfx,
> + const struct acpi_hest_generic_data_v300 *gdata)
> +{
> + __u8 hour, min, sec, day, mon, year, century, *timestamp;
> +
> + if (gdata->validation_bits & ACPI_HEST_GEN_VALID_TIMESTAMP) {
> + timestamp = (__u8 *)&(gdata->time_stamp);
> + sec = bcd2bin(timestamp[0]);
> + min = bcd2bin(timestamp[1]);
> + hour = bcd2bin(timestamp[2]);
> + day = bcd2bin(timestamp[4]);
> + mon = bcd2bin(timestamp[5]);
> + year = bcd2bin(timestamp[6]);
> + century = bcd2bin(timestamp[7]);
> + printk("%stime: %7s %02d%02d-%02d-%02d %02d:%02d:%02d\n", pfx,
> + 0x01 & *(timestamp + 3) ? "precise" : "", century,
> + year, mon, day, hour, min, sec);
> + }
> +}
> +
> static void cper_estatus_print_section(
> - const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no)
> + const char *pfx, struct acpi_hest_generic_data *gdata, int sec_no)
> {
> uuid_le *sec_type = (uuid_le *)gdata->section_type;
> __u16 severity;
> char newpfx[64];
>
> + if (acpi_hest_generic_data_version(gdata) >= 3)
> + cper_estatus_print_section_v300(pfx,
> + (const struct acpi_hest_generic_data_v300 *)gdata);
> +
> severity = gdata->error_severity;
> printk("%s""Error %d, type: %s\n", pfx, sec_no,
> cper_severity_str(severity));
> @@ -403,14 +430,18 @@ static void cper_estatus_print_section(
>
> snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
> if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_GENERIC)) {
> - struct cper_sec_proc_generic *proc_err = (void *)(gdata + 1);
> + struct cper_sec_proc_generic *proc_err;
> +
> + proc_err = acpi_hest_generic_data_payload(gdata);
> printk("%s""section_type: general processor error\n", newpfx);
> if (gdata->error_data_length >= sizeof(*proc_err))
> cper_print_proc_generic(newpfx, proc_err);
> else
> goto err_section_too_small;
> } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) {
> - struct cper_sec_mem_err *mem_err = (void *)(gdata + 1);
> + struct cper_sec_mem_err *mem_err;
> +
> + mem_err = acpi_hest_generic_data_payload(gdata);
> printk("%s""section_type: memory error\n", newpfx);
> if (gdata->error_data_length >=
> sizeof(struct cper_sec_mem_err_old))
> @@ -419,7 +450,9 @@ static void cper_estatus_print_section(
> else
> goto err_section_too_small;
> } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) {
> - struct cper_sec_pcie *pcie = (void *)(gdata + 1);
> + struct cper_sec_pcie *pcie;
> +
> + pcie = acpi_hest_generic_data_payload(gdata);
> printk("%s""section_type: PCIe error\n", newpfx);
> if (gdata->error_data_length >= sizeof(*pcie))
> cper_print_pcie(newpfx, pcie, gdata);
> @@ -438,7 +471,7 @@ void cper_estatus_print(const char *pfx,
> const struct acpi_hest_generic_status *estatus)
> {
> struct acpi_hest_generic_data *gdata;
> - unsigned int data_len, gedata_len;
> + unsigned int data_len;
> int sec_no = 0;
> char newpfx[64];
> __u16 severity;
> @@ -451,12 +484,12 @@ void cper_estatus_print(const char *pfx,
> printk("%s""event severity: %s\n", pfx, cper_severity_str(severity));
> data_len = estatus->data_length;
> gdata = (struct acpi_hest_generic_data *)(estatus + 1);
> +
> snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
> - while (data_len >= sizeof(*gdata)) {
> - gedata_len = gdata->error_data_length;
> +
> + while (data_len >= acpi_hest_generic_data_size(gdata)) {
> cper_estatus_print_section(newpfx, gdata, sec_no);
> - data_len -= gedata_len + sizeof(*gdata);
> - gdata = (void *)(gdata + 1) + gedata_len;
> + gdata = acpi_hest_generic_data_next(gdata);
> sec_no++;
> }
> }
> @@ -486,12 +519,13 @@ int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
> return rc;
> data_len = estatus->data_length;
> gdata = (struct acpi_hest_generic_data *)(estatus + 1);
> - while (data_len >= sizeof(*gdata)) {
> - gedata_len = gdata->error_data_length;
> - if (gedata_len > data_len - sizeof(*gdata))
> +
> + while (data_len >= acpi_hest_generic_data_size(gdata)) {
> + gedata_len = acpi_hest_generic_data_error_length(gdata);
> + if (gedata_len > data_len - acpi_hest_generic_data_size(gdata))
> return -EINVAL;
> - data_len -= gedata_len + sizeof(*gdata);
> - gdata = (void *)(gdata + 1) + gedata_len;
> + data_len -= gedata_len + acpi_hest_generic_data_size(gdata);
> + gdata = acpi_hest_generic_data_next(gdata);
> }
> if (data_len)
> return -EINVAL;
> diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
> index 68f088a..56b9679 100644
> --- a/include/acpi/ghes.h
> +++ b/include/acpi/ghes.h
> @@ -73,3 +73,13 @@ static inline void ghes_edac_unregister(struct ghes *ghes)
> {
> }
> #endif
> +
> +#define acpi_hest_generic_data_version(gdata) \
> + (gdata->revision >> 8)
> +
> +static inline void *acpi_hest_generic_data_payload(struct acpi_hest_generic_data *gdata)
> +{
> + return acpi_hest_generic_data_version(gdata) >= 3 ?
> + (void *)(((struct acpi_hest_generic_data_v300 *)(gdata)) + 1) :
> + gdata + 1;
> +}
> diff --git a/include/linux/cper.h b/include/linux/cper.h
> index dcacb1a..13ea41c 100644
> --- a/include/linux/cper.h
> +++ b/include/linux/cper.h
> @@ -255,6 +255,18 @@ enum {
>
> #define CPER_PCIE_SLOT_SHIFT 3
>
> +#define acpi_hest_generic_data_error_length(gdata) \
> + (((struct acpi_hest_generic_data *)(gdata))->error_data_length)
> +#define acpi_hest_generic_data_size(gdata) \
> + ((acpi_hest_generic_data_version(gdata) >= 3) ? \
> + sizeof(struct acpi_hest_generic_data_v300) : \
> + sizeof(struct acpi_hest_generic_data))
> +#define acpi_hest_generic_data_record_size(gdata) \
> + (acpi_hest_generic_data_size(gdata) + \
> + acpi_hest_generic_data_error_length(gdata))
> +#define acpi_hest_generic_data_next(gdata) \
> + ((void *)(gdata) + acpi_hest_generic_data_record_size(gdata))
> +
How come these aren't in ghes.h?
Reviewed-by: James Morse <james.morse@arm.com>
Thanks,
James
^ permalink raw reply
* [PATCH V5 01/10] acpi: apei: read ack upon ghes record consumption
From: James Morse @ 2016-11-25 18:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479767763-27532-2-git-send-email-tbaicar@codeaurora.org>
Hi Tyler,
On 21/11/16 22:35, Tyler Baicar wrote:
> A RAS (Reliability, Availability, Serviceability) controller
> may be a separate processor running in parallel with OS
> execution, and may generate error records for consumption by
> the OS. If the RAS controller produces multiple error records,
> then they may be overwritten before the OS has consumed them.
>
> The Generic Hardware Error Source (GHES) v2 structure
> introduces the capability for the OS to acknowledge the
> consumption of the error record generated by the RAS
> controller. A RAS controller supporting GHESv2 shall wait for
> the acknowledgment before writing a new error record, thus
> eliminating the race condition.
This patch also adds support for parsing GHESv2 sub-tables.
Before they would be rejected as an unknown hardware error source.
> Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Nit: the patch author's Sign-off should come first, you either need a 'From:
Jonathan (Zhixiong) Zhang ...' on this patch, or re-order these Signed-off-by's.
> Signed-off-by: Richard Ruigrok <rruigrok@codeaurora.org>
> Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
> Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
> ---
> drivers/acpi/apei/ghes.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---
> drivers/acpi/apei/hest.c | 7 +++++--
> include/acpi/ghes.h | 5 ++++-
> 3 files changed, 55 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
> index 60746ef..b79abc5 100644
> --- a/drivers/acpi/apei/ghes.c
> +++ b/drivers/acpi/apei/ghes.c
> @@ -45,6 +45,7 @@
> #include <linux/aer.h>
> #include <linux/nmi.h>
>
> +#include <acpi/actbl1.h>
> #include <acpi/ghes.h>
> #include <acpi/apei.h>
> #include <asm/tlbflush.h>
> @@ -79,6 +80,10 @@
> ((struct acpi_hest_generic_status *) \
> ((struct ghes_estatus_node *)(estatus_node) + 1))
>
> +#define HEST_TYPE_GENERIC_V2(ghes) \
> + ((struct acpi_hest_header *)ghes->generic)->type == \
> + ACPI_HEST_TYPE_GENERIC_ERROR_V2
> +
IS_ HEST_TYPE_GENERIC_V2() ? (for the sake of readability)
> /*
> * This driver isn't really modular, however for the time being,
> * continuing to use module_param is the easiest way to remain
> @@ -248,10 +253,18 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
> ghes = kzalloc(sizeof(*ghes), GFP_KERNEL);
> if (!ghes)
> return ERR_PTR(-ENOMEM);
> +
> ghes->generic = generic;
> + if (HEST_TYPE_GENERIC_V2(ghes)) {
> + rc = apei_map_generic_address(
> + &ghes->generic_v2->read_ack_register);
> + if (rc)
> + goto err_free;
> + }
> +
> rc = apei_map_generic_address(&generic->error_status_address);
> if (rc)
> - goto err_free;
> + goto err_unmap_read_ack_addr;
> error_block_length = generic->error_block_length;
> if (error_block_length > GHES_ESTATUS_MAX_SIZE) {
> pr_warning(FW_WARN GHES_PFX
> @@ -263,13 +276,17 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
> ghes->estatus = kmalloc(error_block_length, GFP_KERNEL);
> if (!ghes->estatus) {
> rc = -ENOMEM;
> - goto err_unmap;
> + goto err_unmap_status_addr;
> }
>
> return ghes;
>
> -err_unmap:
> +err_unmap_status_addr:
> apei_unmap_generic_address(&generic->error_status_address);
> +err_unmap_read_ack_addr:
> + if (HEST_TYPE_GENERIC_V2(ghes))
> + apei_unmap_generic_address(
> + &ghes->generic_v2->read_ack_register);
> err_free:
> kfree(ghes);
> return ERR_PTR(rc);
> @@ -279,6 +296,9 @@ static void ghes_fini(struct ghes *ghes)
> {
> kfree(ghes->estatus);
> apei_unmap_generic_address(&ghes->generic->error_status_address);
> + if (HEST_TYPE_GENERIC_V2(ghes))
> + apei_unmap_generic_address(
> + &ghes->generic_v2->read_ack_register);
> }
>
> static inline int ghes_severity(int severity)
> @@ -648,6 +668,23 @@ static void ghes_estatus_cache_add(
> rcu_read_unlock();
> }
>
> +static int ghes_ack_error(struct acpi_hest_generic_v2 *generic_v2)
> +{
> + int rc;
> + u64 val = 0;
> +
> + rc = apei_read(&val, &generic_v2->read_ack_register);
> + if (rc)
> + return rc;
> + val &= generic_v2->read_ack_preserve <<
> + generic_v2->read_ack_register.bit_offset;
> + val |= generic_v2->read_ack_write <<
> + generic_v2->read_ack_register.bit_offset;
Is this bit_offset shifting needed in case the read_ack_register is in the
'system io' (or embedded controller) address space and shares a register with
some other stuff?
The read_ack_{preserve,write} values are u64, so if bit_offset is non-zero the
high order bits get lost, but both ends of this are in the firmware's control.
(I assumed this thing would always be in memory and these fields would never be
used - but I guess that isn't true!)
> + rc = apei_write(val, &generic_v2->read_ack_register);
> +
> + return rc;
> +}
> +
> static int ghes_proc(struct ghes *ghes)
> {
> int rc;
> @@ -660,6 +697,12 @@ static int ghes_proc(struct ghes *ghes)
> ghes_estatus_cache_add(ghes->generic, ghes->estatus);
> }
> ghes_do_proc(ghes, ghes->estatus);
> +
> + if (HEST_TYPE_GENERIC_V2(ghes)) {
> + rc = ghes_ack_error(ghes->generic_v2);
> + if (rc)
> + return rc;
> + }
> out:
> ghes_clear_estatus(ghes);
> return 0;
> diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
> index 792a0d9..ef725a9 100644
> --- a/drivers/acpi/apei/hest.c
> +++ b/drivers/acpi/apei/hest.c
> @@ -52,6 +52,7 @@ static const int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
> [ACPI_HEST_TYPE_AER_ENDPOINT] = sizeof(struct acpi_hest_aer),
> [ACPI_HEST_TYPE_AER_BRIDGE] = sizeof(struct acpi_hest_aer_bridge),
> [ACPI_HEST_TYPE_GENERIC_ERROR] = sizeof(struct acpi_hest_generic),
> + [ACPI_HEST_TYPE_GENERIC_ERROR_V2] = sizeof(struct acpi_hest_generic_v2),
> };
>
> static int hest_esrc_len(struct acpi_hest_header *hest_hdr)
> @@ -146,7 +147,8 @@ static int __init hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void
> {
> int *count = data;
>
> - if (hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR)
> + if (hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR ||
> + hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR_V2)
> (*count)++;
> return 0;
> }
> @@ -157,7 +159,8 @@ static int __init hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
> struct ghes_arr *ghes_arr = data;
> int rc, i;
>
> - if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR)
> + if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR &&
> + hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR_V2)
> return 0;
>
> if (!((struct acpi_hest_generic *)hest_hdr)->enabled)
> diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
> index 720446c..68f088a 100644
> --- a/include/acpi/ghes.h
> +++ b/include/acpi/ghes.h
> @@ -13,7 +13,10 @@
> #define GHES_EXITING 0x0002
>
> struct ghes {
> - struct acpi_hest_generic *generic;
> + union {
> + struct acpi_hest_generic *generic;
> + struct acpi_hest_generic_v2 *generic_v2;
> + };
> struct acpi_hest_generic_status *estatus;
> u64 buffer_paddr;
> unsigned long flags;
>
Looks good to me, for what its worth:
Reviewed-by: James Morse <james.morse@arm.com>
Thanks,
James
^ permalink raw reply
* [net-next PATCH v1 0/2] stmmac: dwmac-meson8b: configurable RGMII TX delay
From: Florian Fainelli @ 2016-11-25 17:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6a6af561-4e83-ca6e-d989-f421e18bce1e@laposte.net>
On 11/25/2016 03:13 AM, Sebastian Frias wrote:
> On 24/11/16 19:55, Florian Fainelli wrote:
>> Le 24/11/2016 ? 09:05, Martin Blumenstingl a ?crit :
>>> On Thu, Nov 24, 2016 at 4:56 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:
>>>> On Thu, 2016-11-24 at 15:34 +0100, Martin Blumenstingl wrote:
>>>>> Currently the dwmac-meson8b stmmac glue driver uses a hardcoded 1/4
>>>>> cycle TX clock delay. This seems to work fine for many boards (for
>>>>> example Odroid-C2 or Amlogic's reference boards) but there are some
>>>>> others where TX traffic is simply broken.
>>>>> There are probably multiple reasons why it's working on some boards
>>>>> while it's broken on others:
>>>>> - some of Amlogic's reference boards are using a Micrel PHY
>>>>> - hardware circuit design
>>>>> - maybe more...
>>>>>
>>>>> This raises a question though:
>>>>> Which device is supposed to enable the TX delay when both MAC and PHY
>>>>> support it? And should we implement it for each PHY / MAC separately
>>>>> or should we think about a more generic solution (currently it's not
>>>>> possible to disable the TX delay generated by the RTL8211F PHY via
>>>>> devicetree when using phy-mode "rgmii")?
>>>>
>>>> Actually you can skip the part which activate the Tx-delay on the phy
>>>> by setting "phy-mode = "rgmii-id" instead of "rgmii"
>>>>
>>>> phy->interface will no longer be PHY_INTERFACE_MODE_RGMII
>>>> but PHY_INTERFACE_MODE_RGMII_ID.
>>> unfortunately this is not true for RTL8211F (I did my previous tests
>>> with the same expectation in mind)!
>>> the code seems to suggest that TX-delay is disabled whenever mode !=
>>> PHY_INTERFACE_MODE_RGMII.
>>> BUT: on my device RTL8211F_TX_DELAY is set even before
>>> "phy_write(phydev, 0x11, reg);"!
>
> If you look at the Atheros 803x PHY and its driver
> 'drivers/net/phy/at803x.c':
> - by default (as HW reset preset) the PHY has RX delay enabled, TX
> delay disabled
> - the driver only enables RX, or TX, or both, according to "rgmii-rxid",
> "rgmii-txid", or "rgmii-id" respectively, but does not alter HW reset
> presets. In other words:
> a "rgmii-rxid" results in RX enabled (expected)
> b "rgmii-txid" results in RX *and* TX enabled (unexpected?)
> c "rgmii-id" results in RX *and* TX enabled (expected)
> d "rgmii" results in RX enabled (unexpected?)
>
> This is a bit surprising and I think that some boards and PHY<->MAC
> combinations are working a little bit by chance, unless I'm missing
> something.
>
>>
>> (Adding Sebastian (and Mans, and Andrew) since he raised the same
>> question a while ago. I think I now understand a bit better what
>> Sebastian was after a couple of weeks ago)
>>
>
> Thanks for CCing us, it is indeed a very similar issue.
>
>>>
>>> Based on what I found it seems that rgmii-id, rgmii-txid and
>>> rgmii-rxid are supposed to be handled by the PHY.
>>
>> Correct, the meaning of PHY_INTERFACE_MODE should be from the
>> perspective of the PHY device:
>>
>> - PHY_INTERFACE_MODE_RGMII_TXID means that the PHY is responsible for
>> adding a delay when the MAC transmits (TX MAC -> PHY (delay) -> wire)
>> - PHY_INTERFACE_MODE_RGMII_RXID means that the PHY is responsible for
>> adding a delay when the MAC receives (RX MAC <- (delay) PHY) <- wire)
>>
>
> Thanks for the explanation.
> Actually I had thought that the delay was to account for board routing
> (wires) between the MAC and the PHY.
> From your explanation it appears that the delay is to account for board
> routing (wires) between the PHY and the RJ45 socket.
The placement of the (delay) was not meant to be exact, but it was
wrongly place anyway, so it should be between the MAC and PHY, always.
This is why you see people either fixing the need for a delay by
appropriately programming the PHY, or the MAC, or by just inserting a
fixed delay on the PCB between the PHY and the MAC and programming no
delays (or using the default values and hoping this works).
>
>>> That would mean that we have two problems here:
>>> 1) drivers/net/phy/realtek.c:rtl8211f_config_init should check for
>>> PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_TXID and
>>> enable the TX-delay in that case - otherwise explicitly disable it
>>
>> Agreed.
>>
>>> 2) dwmac-meson8b.c should only use the configured TX-delay for
>>> PHY_INTERFACE_MODE_RGMII
>>> @Florian: could you please share your thoughts on this (who handles
>>> the TX delay in which case)?
>>
>> This also seems reasonable to do, provided that the PHY is also properly
>> configured not to add delays in both directions, and therefore assumes
>> that the MAC does it.
>>
>> We have a fairly large problem with how RGMII delays are done in PHYLIB
>> and Ethernet MAC drivers (or just in general), where we can't really
>> intersect properly what a PHY is supporting (in terms of internal
>> delays), and what the MAC supports either. One possible approach could
>> be to update PHY drivers a list of PHY_INTERFACE_MODE_* that they
>> support (ideally, even with normalized nanosecond delay values),
>
> Just to make sure I understood this, the DT would say something like:
>
> phy-connection-type = "rgmii-txid";
> txid-delay-ns = <3>;
>
> For a 3ns TX delay, would that be good?
That's one possibility, although, see below, some PHYs support
sub-nanosecond values, but in general, that seems like a good
representation. If the "txid-delay-ns" property is omitted, a standard
2ns delay is assumed.
>
>> and
>> then intersect that with the requested phy_interface_t during
>> phy_{attach,connect} time, and feed this back to the MAC with a special
>> error code/callback, so we could gracefully try to choose another
>> PHY_INTERFACE_MODE_* value that the MAC supports....
>>
>> A larger problem is that a number of drivers have been deployed, and
>> Device Trees, possibly with the meaning of "phy-mode" and
>> "phy-connection-type" being from the MAC perspective, and not the PHY
>> perspective *sigh*, good luck auditing those.
>>
>> So from there, here is possibly what we could do
>>
>> - submit a series of patches that update the PHYLIB documentation (there
>> are other things missing here) and make it clear from which entity (PHY
>> or MAC) does the delay apply to, document the "intersection" problem here
>
> I think documenting is necessary, thanks in advance!
>
> However, I'm wondering if there's a way to make this work in all cases.
> Indeed, if we consider for example that TX delay is required, we have 4
> cases:
>
> PHY | MAC | Who applies?
> TXID supported | TXID supported | PHY
> TXID supported | TXID not supported | PHY
> TXID not supported | TXID supported | MAC
> TXID not supported | TXID not supported | cannot be done
>
> That is basically what my patch:
>
> https://marc.info/?l=linux-netdev&m=147869658031783&w=2
>
> attempted to achieve. That would allow more combinations of MAC<->PHY to
> work, right?
Yes, indeed.
>
> Nevertheless, I think we also need to keep in mind that most of this
> discussion assumes the case where both, MAC and PHY have equal capabilities.
> Could it happen that the PHY supports only 2ns delay, and the MAC only
> 1ns delay?
I doubt this exists at the MAC level what we should have is either a 2ns
delay, in either RX or TX path, or nothing, because that's the value
that results in shifting the data lines and the RX/TX lines by 90
degrees at 125Mhz (1/125^6 = 8 ns, one quarter shift is 90 degrees =
2ns). The PHY may have a similar set of pre-programmed, fixed 2ns
delays, but it is not uncommon to see 0.X ns resolution available:
drivers/net/phy/mscc.c
drivers/net/phy/dp83867.c w/ arch/arm/boot/dts/dra72-evm-revc.dts
In these cases, if you end-up using a non 2ns delay, you are fixing a
PCB problem more than an interoperability problem between your MAC and PHY.
> Could it happen that the delay is bigger than what is supported by
> either the PHY or MAC alone? maybe if combined it could work, for example
> a 3ns delay required and the PHY supporting 2ns and the MAC 1ns, combined
> it could work?
I suppose such a thing would work yes, but it would be difficult to
report correctly to the core PHYLIB how this can work considering the
vast array of options available to introduce delays in that case:
MAC-level, PHY-level, pinctrl/pad level and possibly at the PCB itself.
Once we can't rely on the fixed 2ns delay to work, we are going to have
people do various experiments until they can either measure what the
right delay value is for the specific PCB, or they just found the value
that happens to work. I don't think we can do much at that point from a
core PHYLIB perspective other than tell the network driver that the PHY
supports delay in either RX, TX or both directions, and have the MAC
decide what to apply that makes sense here, considering that this is
already kind of an exceptional situation to be in.
--
Florian
^ permalink raw reply
* [PATCH] arm64: mm: Fix memmap to be initialized for the entire section
From: Ard Biesheuvel @ 2016-11-25 17:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu9h2YWJd8-+FhSYSftUsddj1f-HTA2D-6nC=8Wk6U1iAg@mail.gmail.com>
On 25 November 2016 at 12:28, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 25 November 2016 at 11:29, Robert Richter <robert.richter@cavium.com> wrote:
>> On 24.11.16 19:42:47, Ard Biesheuvel wrote:
>>> On 24 November 2016 at 19:26, Robert Richter <robert.richter@cavium.com> wrote:
>>
>>> > I revisited the code and it is working well already since:
>>> >
>>> > e7cd190385d1 arm64: mark reserved memblock regions explicitly in iomem
>>> >
>>> > Now, try_ram_remap() is only called if the region to be mapped is
>>> > entirely in IORESOURCE_SYSTEM_RAM. This is only true for normal mem
>>> > ranges and not NOMAP mem. region_intersects() then returns
>>> > REGION_INTERSECTS and calls try_ram_remap(). For the NOMAP memory case
>>> > REGION_DISJOINT would be returned and thus arch_memremap_wb() being
>>> > called directly. Before the e7cd190385d1 change try_ram_remap() was
>>> > called also for nomap regions.
>>> >
>>> > So we can leave memremap() as it is and just apply this patch
>>> > unmodified. What do you think?
>>>
>>> I agree. The pfn_valid() check in try_ram_remap() is still appropriate
>>> simply because the PageHighmem check requires a valid struct page. But
>>> if we don't enter that code path anymore for NOMAP regions, I think
>>> we're ok.
>>>
>>> > Please ack.
>>> >
>>>
>>> I still don't fully understand how it is guaranteed that *all* memory
>>> (i.e., all regions for which memblock_is_memory() returns true) is
>>> covered by a struct page, but marked as reserved. Are we relying on
>>> the fact that NOMAP memory is also memblock_reserve()'d?
>>
>> See free_low_memory_core_early():
>>
>> ----
>> for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end,
>> NULL)
>> count += __free_memory_core(start, end);
>> ----
>>
>> Only mem with the MEMBLOCK_NONE flag is added. And NOMAP pages are
>> also *not* marked reserved. So nothing at all from NOMAP mem is
>> reported to mm, it is not present (see below for a mem config, note
>> flags: 0x4 mem regions).
>>
>
> OK, thanks for clearing that up. But that still does not explain how
> we can be certain that NOMAP regions are guaranteed to be covered by a
> struct page, does it? Because that is ultimately what pfn_valid()
> means, that it is safe to, e.g., look at the page flags.
>
Answering to self: arm64_memory_present() registers all memory as
present, which means that sparse_init() will allocate struct page
backing for all of memory, including NOMAP regions.
We could ask ourselves whether it makes sense to disregard NOMAP
memory here, but that probably buys us very little (but I do wonder
how it affects the occurrence of the bug).
In any case, it looks to me like your patch is safe, i.e., calling
pfn_valid() on NOMAP pages is safe, although I still find it debatable
whether the kernel should be tracking memory it does not own. However,
for performance reasons, it probably makes sense to apply your patch,
and if anyone ever comes up with a use case where this is problematic
(e.g., gigabytes of NOMAP memory), we can look into it then.
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
^ permalink raw reply
* [PATCH 5/7] efi: Get the secure boot status [ver #3]
From: David Howells @ 2016-11-25 16:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu_w-w7a8TA1Y=y2+Ek5vH4BvDUTMOcp68=3bsuT1Njg7w@mail.gmail.com>
Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> yes, I actually pointed that out in my reply (although somewhat tersely)
Ah! Sorry, it went unnoticed amongst all the other lines beginning with '>'.
David
^ permalink raw reply
* [PATCH 5/7] efi: Get the secure boot status [ver #3]
From: Ard Biesheuvel @ 2016-11-25 16:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <7005.1480092635@warthog.procyon.org.uk>
On 25 November 2016 at 16:50, David Howells <dhowells@redhat.com> wrote:
> David Howells <dhowells@redhat.com> wrote:
>
>> + /* UEFI-2.6 requires DeployedMode to be 1. */
>> + if (sys_table_arg->hdr.revision == EFI_2_60_SYSTEM_TABLE_REVISION) {
>
> Actually, I suspect that this should be '>='.
>
yes, I actually pointed that out in my reply (although somewhat tersely)
^ permalink raw reply
* [PATCH 5/7] efi: Get the secure boot status [ver #3]
From: David Howells @ 2016-11-25 16:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <31374.1480078855@warthog.procyon.org.uk>
David Howells <dhowells@redhat.com> wrote:
> + /* UEFI-2.6 requires DeployedMode to be 1. */
> + if (sys_table_arg->hdr.revision == EFI_2_60_SYSTEM_TABLE_REVISION) {
Actually, I suspect that this should be '>='.
David
^ permalink raw reply
* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
From: Gabriele Paoloni @ 2016-11-25 16:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <107039805.6PaPa1fbx1@wuerfel>
Hi Arnd
> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 25 November 2016 12:04
> To: Gabriele Paoloni
> Cc: linux-arm-kernel at lists.infradead.org; mark.rutland at arm.com;
> catalin.marinas at arm.com; linux-pci at vger.kernel.org;
> liviu.dudau at arm.com; Linuxarm; lorenzo.pieralisi at arm.com; xuwei (O);
> Jason Gunthorpe; T homas Petazzoni; linux-serial at vger.kernel.org;
> benh at kernel.crashing.org; devicetree at vger.kernel.org; minyard at acm.org;
> will.deacon at arm.com; John Garry; olof at lixom.net; robh+dt at kernel.org;
> bhelgaas at go og le.com; kantyzc at 163.com; zhichang.yuan 02 at gmail.com;
> linux-kernel at vger.kernel.org; Yuanzhichang; zourongrong at gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
>
> On Friday, November 25, 2016 8:46:11 AM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > >
> > > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > > > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> > > wrote:
> > > > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> > > /*
> > > @@ -549,9 +548,14 @@ static int of_translate_one(struct device_node
> > > *parent, struct of_bus *bus,
> > > * that translation is impossible (that is we are not dealing with
> a
> > > value
> > > * that can be mapped to a cpu physical address). This is not
> really
> > > specified
> > > * that way, but this is traditionally the way IBM at least do
> things
> > > + *
> > > + * Whenever the translation fails, the *host pointer will be set
> to
> > > the
> > > + * device that lacks a tranlation, and the return code is relative
> to
> > > + * that node.
> >
> > This seems to be wrong to me. We are abusing of the error conditions.
> > So effectively if there is a buggy DT for an IO resource we end up
> > assuming that we are using a special IO device with unmapped
> addresses.
> >
> > The patch at the bottom apply on top of this one and I think is a
> more
> > reasonable approach
>
> It was meant as a logical extension to the existing interface,
> translating the address as far as we can, and reporting back
> how far we got.
>
> Maybe we can return 'of_root' by instead of NULL to signify
> that we have converted all the way to the root of the DT?
> That would make it more consistent, but slightly more complicated
> for the common case.
Mmm not sure really...the point is that now the **host parameter is
used both as a flag and also in of_translate_ioport...the problem
that I see is where we set the "host" parameter...I have a proposal
below...
[...]
> pci_bus_alloc_resource(struct
> > > pci_bus *bus,
> > > void *alignf_data);
>
> [Many lines of reply trimmed here, please make sure you don't quote too
> much context when you reply, it's really annoying to read through
> it otherwise]
Sorry! I'll take care of this in the future...
>
> > /*
> > + * of_isa_indirect_io - get the IO address from some isa reg
> property value.
> > + * For some isa/lpc devices, no ranges property in ancestor node.
> > + * The device addresses are described directly in their regs
> property.
> > + * This fixup function will be called to get the IO address of
> isa/lpc
> > + * devices when the normal of_translation failed.
> > + *
> > + * @parent: points to the parent dts node;
> > + * @bus: points to the of_bus which can be used to parse
> address;
> > + * @addr: the address from reg property;
> > + * @na: the address cell counter of @addr;
> > + * @presult: store the address paresed from @addr;
> > + *
> > + * return 1 when successfully get the I/O address;
> > + * 0 will return for some failures.
> > + */
> > +static int of_get_isa_indirect_io(struct device_node *parent,
> > + struct of_bus *bus, __be32 *addr,
> > + int na, u64 *presult)
> > +{
> > + unsigned int flags;
> > + unsigned int rlen;
> > +
> > + /* whether support indirectIO */
> > + if (!indirect_io_enabled())
> > + return 0;
> > +
> > + if (!of_bus_isa_match(parent))
> > + return 0;
> > +
> > + flags = bus->get_flags(addr);
> > + if (!(flags & IORESOURCE_IO))
> > + return 0;
> > +
> > + /* there is ranges property, apply the normal translation
> directly. */
> > + if (of_get_property(parent, "ranges", &rlen))
> > + return 0;
> > +
> > + *presult = of_read_number(addr + 1, na - 1);
> > + /* this fixup is only valid for specific I/O range. */
> > + return addr_is_indirect_io(*presult);
> > +}
>
> Right, this would work. The reason I didn't go down this route is
> that I wanted to keep it generic enough to allow doing the same
> for PCI host bridges with a nonlinear mapping of the I/O space.
>
> There isn't really anything special about ISA here, other than the
> fact that the one driver that needs it happens to be for ISA rather
> than PCI.
Yes I see your point please consider the patch at the bottom...
>
> > +/*
> > * Translate an address from the device-tree into a CPU physical
> address,
> > * this walks up the tree and applies the various bus mappings on
> the
> > * way.
> > @@ -600,14 +643,23 @@ static u64 __of_translate_address(struct
> device_node *dev,
> > result = of_read_number(addr, na);
> > break;
> > }
> > + /*
> > + * For indirectIO device which has no ranges property, get
> > + * the address from reg directly.
> > + */
> > + if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > + pr_debug("isa indirectIO matched(%s)..addr =
> 0x%llx\n",
> > + of_node_full_name(dev), result);
> > + *host = of_node_get(parent);
> > + break;
> > + }
> >
>
> If we do the special case for ISA as you suggest above, I would still
> want
> to keep it in of_translate_ioport(), I think that's a useful change by
> itself in my patch.
This comes without saying...the patch I proposed here already applied on
top of your changes and, in fact, you can see that I set
"*host = of_node_get(parent);" above in my patch to be used by
of_translate_ioport()
>
> Arnde
>
>
>
Below I have reworked my patch (that still applies on top of your one) to
make it not ISA specific.
Notice that of_translate_ioport() still stands and that in addr_is_indirect_io()
we make sure the bus address to be in the bus address range that the special
host operates on...
---
drivers/of/address.c | 56 ++++++++++++++++++++++++++++++++++++++++++++--
include/linux/of_address.h | 17 ++++++++++++++
2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 5decaba..2b34931 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -540,6 +540,48 @@ static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
}
/*
+ * of_get_indirect_io - get the IO address from some reg property value.
+ * For some special host devices, we have no ranges property node and
+ * we directly use the bus addresses of the children regs property.
+ * This fixup function will be called to get the IO address of isa/lpc
+ * devices when the normal of_translation failed.
+ *
+ * @parent: points to the parent dts node;
+ * @bus: points to the of_bus which can be used to parse address;
+ * @addr: the address from reg property;
+ * @na: the address cell counter of @addr;
+ * @presult: store the address parsed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_indirect_io(struct device_node *parent,
+ struct of_bus *bus, __be32 *addr,
+ int na, u64 *presult)
+{
+ unsigned int flags;
+ unsigned int rlen;
+
+ /* whether support indirectIO */
+ if (!indirect_io_enabled())
+ return 0;
+
+ flags = bus->get_flags(addr);
+ if (!(flags & IORESOURCE_IO))
+ return 0;
+
+ /* there is ranges property, apply the normal translation directly. */
+ if (of_get_property(parent, "ranges", &rlen))
+ return 0;
+
+ *presult = of_read_number(addr + 1, na - 1);
+
+ /* check if the bus address falls into the range of
+ * the special host device*/
+ return addr_is_indirect_io(*presult);
+}
+
+/*
* Translate an address from the device-tree into a CPU physical address,
* this walks up the tree and applies the various bus mappings on the
* way.
@@ -601,13 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
break;
}
+ /*
+ * For indirectIO device which has no ranges property, get
+ * the address from reg directly.
+ */
+ if (of_get_indirect_io(dev, bus, addr, na, &result)) {
+ pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+ of_node_full_name(dev), result);
+ *host = of_node_get(parent);
+ break;
+ }
+
/* Get new parent bus and counts */
pbus = of_match_bus(parent);
pbus->count_cells(dev, &pna, &pns);
if (!OF_CHECK_COUNTS(pna, pns)) {
- pr_debug("Bad cell count for %s\n",
+ pr_err("Bad cell count for %s\n",
of_node_full_name(dev));
- *host = of_node_get(parent);
break;
}
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..14848d8 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
#define for_each_of_pci_range(parser, range) \
for (; of_pci_range_parser_one(parser, range);)
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+ return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+ return 0;
+}
+#endif
+
+
/* Translate a DMA address from device space to CPU space */
extern u64 of_translate_dma_address(struct device_node *dev,
const __be32 *in_addr);
--
2.7.4
^ permalink raw reply related
* [PATCH v28 0/9] arm64: add kdump support
From: Catalin Marinas @ 2016-11-25 16:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161124095523.6972-1-takahiro.akashi@linaro.org>
On Thu, Nov 24, 2016 at 06:55:23PM +0900, AKASHI Takahiro wrote:
> AKASHI Takahiro (8):
> arm64: kdump: reserve memory for crash dump kernel
> memblock: add memblock_cap_memory_range()
> arm64: limit memory regions based on DT property, usable-memory-range
> arm64: kdump: implement machine_crash_shutdown()
> arm64: kdump: add kdump support
> arm64: kdump: add VMCOREINFO's for user-space coredump tools
> arm64: kdump: enable kdump in the arm64 defconfig
> arm64: kdump: update a kernel doc
Given that it's nearly -rc7, holiday in the US and more acks needed, we
should defer merging this series to 4.11. In the meantime, since Will is
going to handle the 4.11 merging window, I'm acking the whole series:
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply
* [PATCH v5 2/2] ARM: dts: add support for Turris Omnia
From: Gregory CLEMENT @ 2016-11-25 16:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161125142658.21690-3-uwe@kleine-koenig.org>
Hi Uwe,
On ven., nov. 25 2016, Uwe Kleine-K?nig <uwe@kleine-koenig.org> wrote:
> This machine is an open hardware router by cz.nic driven by a
> Marvell Armada 385.
>
> Signed-off-by: Uwe Kleine-K?nig <uwe@kleine-koenig.org>
Applied on mvebu/dt with few changes:
First I added the SoB from Thomas Hlavacek you initially planed to add
as seen on IRC.
The other change I did are mentioned inline.
Thanks,
Gregory
[...]
> +&spi0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&spi0_pins &spi0cs0_pins>;
> + status = "okay";
> +
> + spi-nor at 0 {
> + compatible = "spansion,s25fl164k", "jedec,spi-nor";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + reg = <0>;
> + spi-max-frequency = <40000000>;
> +
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
it is mandatory since v4.4 to use this pattern for partitions.
> + partition at 0 {
> + reg = <0x0 0x00100000>;
> + label = "U-Boot";
> + };
> +
> + partition at 1 {
@0x100000
We should use the reg value here ^
> + reg = <0x00100000 0x00700000>;
> + label = "Rescue system";
> + };
+ };
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH v5 1/2] devicetree: Add vendor prefix for CZ.NIC
From: Gregory CLEMENT @ 2016-11-25 16:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161125142658.21690-2-uwe@kleine-koenig.org>
Hi Uwe,
On ven., nov. 25 2016, Uwe Kleine-K?nig <uwe@kleine-koenig.org> wrote:
> Signed-off-by: Uwe Kleine-K?nig <uwe@kleine-koenig.org>
Applied on mvebu/dt and I added back the Acked-by from Rob Herring.
Thanks,
Gregory
> ---
> Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index f0a48ea78659..ae9fce9fed03 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -67,6 +67,7 @@ creative Creative Technology Ltd
> crystalfontz Crystalfontz America, Inc.
> cubietech Cubietech, Ltd.
> cypress Cypress Semiconductor Corporation
> +cznic CZ.NIC, z.s.p.o.
> dallas Maxim Integrated Products (formerly Dallas Semiconductor)
> davicom DAVICOM Semiconductor, Inc.
> delta Delta Electronics, Inc.
> --
> 2.10.2
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH v2] bus: imx-weim: Fix the "fsl,weim-cs-gpr" lookup method
From: Fabio Estevam @ 2016-11-25 16:04 UTC (permalink / raw)
To: linux-arm-kernel
From: Fabio Estevam <fabio.estevam@nxp.com>
Commit 1be81ea5860744520 ("ARM: dts: imx6: Add imx-weim parameters to
dtsi's") causes the following probe error when the weim node is not
present on the board dts (such as imx6q-sabresd):
imx-weim 21b8000.weim: Invalid 'ranges' configuration
imx-weim: probe of 21b8000.weim failed with error -22
As the "fsl,weim-cs-gpr" property changed the location from the individual
board dts "&weim" node to the common dtsi node we can no longer reach it
via syscon_regmap_lookup_by_phandle(), so use
syscon_regmap_lookup_by_compatible() instead, which will successfully
find the "fsl,weim-cs-gpr" property.
Fixes: 1be81ea5860744520 ("ARM: dts: imx6: Add imx-weim parameters to dtsi's")
Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
Changes since v1:
- Fix copy and paste error of the error message
- Add Fixes tag
drivers/bus/imx-weim.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index 4bd361d..9824c58 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -76,7 +76,7 @@ static int __init imx_weim_gpr_setup(struct platform_device *pdev)
int cs = 0;
int i = 0;
- gpr = syscon_regmap_lookup_by_phandle(np, "fsl,weim-cs-gpr");
+ gpr = syscon_regmap_lookup_by_compatible("fsl,weim-cs-gpr");
if (IS_ERR(gpr)) {
dev_dbg(&pdev->dev, "failed to find weim-cs-gpr\n");
return 0;
--
2.7.4
^ permalink raw reply related
* [PATCH 3/3] ARM: dts: da850: enable the memctrl and mstpri nodes per board
From: Bartosz Golaszewski @ 2016-11-25 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480089795-29811-1-git-send-email-bgolaszewski@baylibre.com>
Currently the memory controller and master priorities drivers are
enabled in da850.dtsi. For boards for which there are no settings
defined, this makes these drivers emit error messages.
Disable the nodes in da850.dtsi and only enable them for da850-lcdk -
the only board that currently needs them.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
arch/arm/boot/dts/da850-lcdk.dts | 8 ++++++++
arch/arm/boot/dts/da850.dtsi | 2 ++
2 files changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/da850-lcdk.dts b/arch/arm/boot/dts/da850-lcdk.dts
index 6952c68..d0f7680 100644
--- a/arch/arm/boot/dts/da850-lcdk.dts
+++ b/arch/arm/boot/dts/da850-lcdk.dts
@@ -285,3 +285,11 @@
remote-endpoint = <&vga_bridge_in>;
};
};
+
+&prictrl {
+ status = "okay";
+};
+
+&memctrl {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index 9b7c444..2ea0e06 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -213,6 +213,7 @@
prictrl: priority-controller at 14110 {
compatible = "ti,da850-mstpri";
reg = <0x14110 0x0c>;
+ status = "disabled";
};
cfgchip: chip-controller at 1417c {
compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
@@ -486,5 +487,6 @@
memctrl: memory-controller at b0000000 {
compatible = "ti,da850-ddr-controller";
reg = <0xb0000000 0xe8>;
+ status = "disabled";
};
};
--
2.9.3
^ permalink raw reply related
* [PATCH 2/3] ARM: dts: da850: specify the maximum bandwidth for tilcdc
From: Bartosz Golaszewski @ 2016-11-25 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480089795-29811-1-git-send-email-bgolaszewski@baylibre.com>
It has been determined that the maximum resolution supported correctly
by tilcdc rev1 on da850 SoCs is 800x600 at 60. Due to memory throughput
constraints we must filter out higher modes.
Specify the max-bandwidth property for the display node for
da850-based boards.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
arch/arm/boot/dts/da850.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index 8e30d9b..9b7c444 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -452,6 +452,7 @@
compatible = "ti,da850-tilcdc";
reg = <0x213000 0x1000>;
interrupts = <52>;
+ max-bandwidth = <28800000>;
status = "disabled";
ports {
--
2.9.3
^ permalink raw reply related
* [PATCH 1/3] ARM: da850-lcdk: add the dumb-vga-dac node
From: Bartosz Golaszewski @ 2016-11-25 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480089795-29811-1-git-send-email-bgolaszewski@baylibre.com>
Add the dumb-vga-dac node to the board DT together with corresponding
ports and vga connector. This allows to retrieve the edid info from
the display automatically.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
arch/arm/boot/dts/da850-lcdk.dts | 58 ++++++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/da850.dtsi | 17 ++++++++++++
2 files changed, 75 insertions(+)
diff --git a/arch/arm/boot/dts/da850-lcdk.dts b/arch/arm/boot/dts/da850-lcdk.dts
index 8411a91..6952c68 100644
--- a/arch/arm/boot/dts/da850-lcdk.dts
+++ b/arch/arm/boot/dts/da850-lcdk.dts
@@ -50,6 +50,53 @@
system-clock-frequency = <24576000>;
};
};
+
+ vga_bridge {
+ compatible = "dumb-vga-dac";
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pins>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port at 0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ vga_bridge_in: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&display_out_vga>;
+ };
+ };
+
+ port at 1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ vga_bridge_out: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&vga_con_in>;
+ };
+ };
+ };
+ };
+
+ vga {
+ compatible = "vga-connector";
+
+ ddc-i2c-bus = <&i2c0>;
+
+ port {
+ vga_con_in: endpoint {
+ remote-endpoint = <&vga_bridge_out>;
+ };
+ };
+ };
};
&pmx_core {
@@ -227,3 +274,14 @@
};
};
};
+
+&display {
+ status = "okay";
+};
+
+&display_out {
+ display_out_vga: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&vga_bridge_in>;
+ };
+};
diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index ff13e95..8e30d9b 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -453,6 +453,23 @@
reg = <0x213000 0x1000>;
interrupts = <52>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ display_in: port at 0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ display_out: port at 1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+ };
};
};
aemif: aemif at 68000000 {
--
2.9.3
^ permalink raw reply related
* [PATCH 0/3] ARM: dts: da850: tilcdc related DT changes
From: Bartosz Golaszewski @ 2016-11-25 16:03 UTC (permalink / raw)
To: linux-arm-kernel
I previously sent these patches separately, but since they're touching
the same files while coming from different trees, I decided to post
it again in a series to make applying them easier.
Bartosz Golaszewski (3):
ARM: da850-lcdk: add the dumb-vga-dac node
ARM: dts: da850: specify the maximum bandwidth for tilcdc
ARM: dts: da850: enable the memctrl and mstpri nodes per board
arch/arm/boot/dts/da850-lcdk.dts | 66 ++++++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/da850.dtsi | 20 ++++++++++++
2 files changed, 86 insertions(+)
--
2.9.3
^ permalink raw reply
* [RFC PATCH 3/3] dt-bindings: display: add Amlogic Meson DRM Bindings
From: Neil Armstrong @ 2016-11-25 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480089791-12517-1-git-send-email-narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
.../bindings/display/meson/meson-drm.txt | 134 +++++++++++++++++++++
1 file changed, 134 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/meson/meson-drm.txt
diff --git a/Documentation/devicetree/bindings/display/meson/meson-drm.txt b/Documentation/devicetree/bindings/display/meson/meson-drm.txt
new file mode 100644
index 0000000..89c1b5f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/meson/meson-drm.txt
@@ -0,0 +1,134 @@
+Amlogic Meson Display Controller
+================================
+
+The Amlogic Meson Display controller is composed of several components
+that are going to be documented below:
+
+DMC|---------------VPU (Video Processing Unit)----------------|------HHI------|
+ | vd1 _______ _____________ _________________ | |
+D |-------| |----| | | | | HDMI PLL |
+D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK |
+R |-------| |----| Processing | | | | |
+ | osd2 | | | |---| Enci ----------|----|-----VDAC------|
+R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----|
+A | osd1 | | | Blenders | | Encl ----------|----|---------------|
+M |-------|______|----|____________| |________________| | |
+___|__________________________________________________________|_______________|
+
+
+VIU: Video Input Unit
+---------------------
+
+The Video Input Unit is in charge of the pixel scanout from the DDR memory.
+It fetches the frames addresses, stride and parameters from the "Canvas" memory.
+This part is also in charge of the CSC (Colorspace Conversion).
+It can handle 2 OSD Planes and 2 Video Planes.
+
+VPP: Video Processing Unit
+--------------------------
+
+The Video Processing Unit is in charge if the scaling and blending of the
+various planes into a single pixel stream.
+There is a special "pre-blending" used by the video planes with a dedicated
+scaler and a "post-blending" to merge with the OSD Planes.
+The OSD planes also have a dedicated scaler for one of the OSD.
+
+VENC: Video Encoders
+--------------------
+
+The VENC is composed of the multiple pixel encoders :
+ - ENCI : Interlace Video encoder for CVBS and Interlace HDMI
+ - ENCP : Progressive Video Encoder for HDMI
+ - ENCL : LCD LVDS Encoder
+The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock
+tree and provides the scanout clock to the VPP and VIU.
+The ENCI is connected to a single VDAC for Composite Output.
+The ENCI and ENCP are connected to an on-chip HDMI Transceiver.
+
+Device Tree Bindings:
+---------------------
+
+VPU: Video Processing Unit
+--------------------------
+
+Required properties:
+ - compatible: value should be different for each SoC family as :
+ - GXBB (S905) : "amlogic,meson-gxbb-vpu"
+ - GXL (S905X, S905D) : "amlogic,meson-gxl-vpu"
+ - GXM (S912) : "amlogic,meson-gxm-vpu"
+ followed by the common "amlogic,meson-gx-vpu"
+ - reg: base address and size of he following memory-mapped regions :
+ - vpu
+ - hhi
+ - dmc
+ - reg-names: should contain the names of the previous memory regions
+ - interrupts: should contain the VENC Vsync interrupt number
+
+- ports: A ports node with endpoint definitions as defined in
+ Documentation/devicetree/bindings/media/video-interfaces.txt. The
+ second port should be the output endpoints for VENC connectors.
+
+VENC CBVS Output
+----------------------
+
+The VENC can output Composite/CVBS output via a decicated VDAC.
+
+Required properties:
+ - compatible: value must be one of:
+ - compatible: value should be different for each SoC family as :
+ - GXBB (S905) : "amlogic,meson-gxbb-venc-cvbs"
+ - GXL (S905X, S905D) : "amlogic,meson-gxl-venc-cvbs"
+ - GXM (S912) : "amlogic,meson-gxm-venc-cvbs"
+ followed by the common "amlogic,meson-gx-venc-cvbs"
+
+- ports: A ports node with endpoint definitions as defined in
+ Documentation/devicetree/bindings/media/video-interfaces.txt. The
+ first port should be the input endpoints, connected ot the VPU node.
+
+Example:
+
+venc_cvbs: venc-cvbs {
+ compatible = "amlogic,meson-gxbb-venc-cvbs";
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ enc_cvbs_in: port at 0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ venc_cvbs_in_vpu: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&vpu_out_venc_cvbs>;
+ };
+ };
+ };
+};
+
+vpu: vpu at d0100000 {
+ compatible = "amlogic,meson-gxbb-vpu";
+ reg = <0x0 0xd0100000 0x0 0x100000>,
+ <0x0 0xc883c000 0x0 0x1000>,
+ <0x0 0xc8838000 0x0 0x1000>;
+ reg-names = "base", "hhi", "dmc";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vpu_out: port at 1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ vpu_out_venc_cvbs: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&venc_cvbs_in_vpu>;
+ };
+ };
+ };
+};
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 2/3] ARM64: dts: meson-gx: Add Graphic Controller nodes
From: Neil Armstrong @ 2016-11-25 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480089791-12517-1-git-send-email-narmstrong@baylibre.com>
Add Video Processing Unit and CVBS Output nodes, and enable CVBS on selected
boards.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 46 ++++++++++++++++++++++
.../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts | 4 ++
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 4 ++
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 12 ++++++
.../boot/dts/amlogic/meson-gxl-nexbox-a95x.dts | 4 ++
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 8 ++++
.../arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts | 4 ++
arch/arm64/boot/dts/amlogic/meson-gxm.dtsi | 9 +++++
8 files changed, 91 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
index fc033c0..bcc1d1f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -153,6 +153,27 @@
};
};
+ venc_cvbs: venc-cvbs {
+ compatible = "amlogic,meson-gx-venc-cvbs";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ enc_cvbs_in: port at 0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ venc_cvbs_in_vpu: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&vpu_out_venc_cvbs>;
+ };
+ };
+ };
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <2>;
@@ -356,5 +377,30 @@
status = "disabled";
};
};
+
+ vpu: vpu at d0100000 {
+ compatible = "amlogic,meson-gx-vpu";
+ reg = <0x0 0xd0100000 0x0 0x100000>,
+ <0x0 0xc883c000 0x0 0x1000>,
+ <0x0 0xc8838000 0x0 0x1000>;
+ reg-names = "base", "hhi", "dmc";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vpu_out: port at 1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ vpu_out_venc_cvbs: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&venc_cvbs_in_vpu>;
+ };
+ };
+ };
+ };
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
index 9696820..a55d1cf 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
@@ -229,3 +229,7 @@
clocks = <&clkc CLKID_FCLK_DIV4>;
clock-names = "clkin0";
};
+
+&venc_cvbs {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index 5e5e2de..3c09bd1 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -266,3 +266,7 @@
clocks = <&clkc CLKID_FCLK_DIV4>;
clock-names = "clkin0";
};
+
+&venc_cvbs {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index ac5ad3b..99ff37c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -506,3 +506,15 @@
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
};
+
+&venc_cvbs {
+ status = "okay";
+};
+
+&venc_cvbs {
+ compatible = "amlogic,meson-gxbb-venc-cvbs", "amlogic,meson-gx-venc-cvbs";
+};
+
+&vpu {
+ compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts
index e99101a..2a9b46f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts
@@ -203,3 +203,7 @@
clocks = <&clkc CLKID_FCLK_DIV4>;
clock-names = "clkin0";
};
+
+&venc_cvbs {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index 3af54dc..98b8118 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -299,3 +299,11 @@
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
};
+
+&venc_cvbs {
+ compatible = "amlogic,meson-gxl-venc-cvbs", "amlogic,meson-gx-venc-cvbs";
+};
+
+&vpu {
+ compatible = "amlogic,meson-gxl-vpu", "amlogic,meson-gx-vpu";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
index d320727..1ae2451 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
@@ -167,3 +167,7 @@
max-speed = <1000>;
};
};
+
+&venc_cvbs {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
index c1974bb..7bf2d6e 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
@@ -112,3 +112,12 @@
};
};
};
+
+
+&venc_cvbs {
+ compatible = "amlogic,meson-gxm-venc-cvbs", "amlogic,meson-gx-venc-cvbs";
+};
+
+&vpu {
+ compatible = "amlogic,meson-gxm-vpu", "amlogic,meson-gx-vpu";
+};
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 0/3] drm: Add support for the Amlogic Video Processing Unit
From: Neil Armstrong @ 2016-11-25 16:03 UTC (permalink / raw)
To: linux-arm-kernel
The Amlogic Meson SoCs embeds a Video Processing Unit able to output at least
a Composite/CVBS Video with embedded VDAC and an HDMI Link with Embedded HDMI
Transceiver.
Thus, the current driver does not support HDMI yet.
The Video Processig Unit is composed of multiple modules like the Video
Input Unit and the Video Post Processing that can be associated to a
CRTC with Planes management.
The last Unit is the Venc that embeds at least 3 Encoders, ENCI for Interlace
Video used by CVBS or HDMI, ENCP for Progressive Video used by the HDMI
Transceiver and ENCL for LCD Display.
The LCD Display is not planned to be supported on the Meson GX Family.
This driver is a DRM/KMS driver using the following DRM components :
- GEM-CMA
- PRIME-CMA
- Atomic Modesetting
- FBDev-CMA
For the following SoCs :
- GXBB Family (S905)
- GXL Family (S905X, S905D)
- GXM Family (S912)
The current driver only supports the CVBS PAL/NTSC output modes, but the
CRTC/Planes management should support bigger modes.
But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in
a second time.
The Device Tree bindings makes use of the endpoints video interface definitions
to connect to the optional CVBS and in the future the HDMI Connector nodes.
The driver has been tested with Xorg modesetting driver and Weston DRM backend.
Neil Armstrong (3):
drm: Add support for Amlogic Meson Graphic Controller
ARM64: dts: meson-gx: Add Graphic Controller nodes
dt-bindings: display: add Amlogic Meson DRM Bindings
.../bindings/display/meson/meson-drm.txt | 134 ++
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 46 +
.../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts | 4 +
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 4 +
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 12 +
.../boot/dts/amlogic/meson-gxl-nexbox-a95x.dts | 4 +
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 8 +
.../arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts | 4 +
arch/arm64/boot/dts/amlogic/meson-gxm.dtsi | 9 +
drivers/gpu/drm/Kconfig | 2 +
drivers/gpu/drm/Makefile | 1 +
drivers/gpu/drm/meson/Kconfig | 8 +
drivers/gpu/drm/meson/Makefile | 5 +
drivers/gpu/drm/meson/meson_canvas.c | 96 ++
drivers/gpu/drm/meson/meson_canvas.h | 31 +
drivers/gpu/drm/meson/meson_crtc.c | 176 +++
drivers/gpu/drm/meson/meson_crtc.h | 34 +
drivers/gpu/drm/meson/meson_cvbs.c | 293 ++++
drivers/gpu/drm/meson/meson_cvbs.h | 32 +
drivers/gpu/drm/meson/meson_drv.c | 383 ++++++
drivers/gpu/drm/meson/meson_drv.h | 68 +
drivers/gpu/drm/meson/meson_plane.c | 150 +++
drivers/gpu/drm/meson/meson_plane.h | 32 +
drivers/gpu/drm/meson/meson_registers.h | 1395 ++++++++++++++++++++
drivers/gpu/drm/meson/meson_vclk.c | 169 +++
drivers/gpu/drm/meson/meson_vclk.h | 36 +
drivers/gpu/drm/meson/meson_venc.c | 286 ++++
drivers/gpu/drm/meson/meson_venc.h | 77 ++
drivers/gpu/drm/meson/meson_viu.c | 497 +++++++
drivers/gpu/drm/meson/meson_viu.h | 37 +
drivers/gpu/drm/meson/meson_vpp.c | 189 +++
drivers/gpu/drm/meson/meson_vpp.h | 43 +
32 files changed, 4265 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/meson/meson-drm.txt
create mode 100644 drivers/gpu/drm/meson/Kconfig
create mode 100644 drivers/gpu/drm/meson/Makefile
create mode 100644 drivers/gpu/drm/meson/meson_canvas.c
create mode 100644 drivers/gpu/drm/meson/meson_canvas.h
create mode 100644 drivers/gpu/drm/meson/meson_crtc.c
create mode 100644 drivers/gpu/drm/meson/meson_crtc.h
create mode 100644 drivers/gpu/drm/meson/meson_cvbs.c
create mode 100644 drivers/gpu/drm/meson/meson_cvbs.h
create mode 100644 drivers/gpu/drm/meson/meson_drv.c
create mode 100644 drivers/gpu/drm/meson/meson_drv.h
create mode 100644 drivers/gpu/drm/meson/meson_plane.c
create mode 100644 drivers/gpu/drm/meson/meson_plane.h
create mode 100644 drivers/gpu/drm/meson/meson_registers.h
create mode 100644 drivers/gpu/drm/meson/meson_vclk.c
create mode 100644 drivers/gpu/drm/meson/meson_vclk.h
create mode 100644 drivers/gpu/drm/meson/meson_venc.c
create mode 100644 drivers/gpu/drm/meson/meson_venc.h
create mode 100644 drivers/gpu/drm/meson/meson_viu.c
create mode 100644 drivers/gpu/drm/meson/meson_viu.h
create mode 100644 drivers/gpu/drm/meson/meson_vpp.c
create mode 100644 drivers/gpu/drm/meson/meson_vpp.h
--
1.9.1
^ permalink raw reply
* [PATCH 5/7] efi: Get the secure boot status [ver #3]
From: David Howells @ 2016-11-25 15:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu9qkPrq1rXN_7=BbZ=8v14Px+oHBqST0OnarUWVwhtZyg@mail.gmail.com>
Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > + if (val != 1)
> > + return 0;
>
> val == 0 is better imo, since that will prevent unexpected values from
> being interpreted as 'secure boot disabled'
I've made that change.
David
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox