* [PATCH] Arm: mm: ftrace: Only set text back to ro after kernel has been marked ro
From: Matthias Reichl @ 2017-12-05 11:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170823150351.606ba09f@gandalf.local.home>
On Wed, Aug 23, 2017 at 03:03:51PM -0400, Steven Rostedt wrote:
> On Wed, 23 Aug 2017 11:48:13 -0700
> Kees Cook <keescook@chromium.org> wrote:
>
> > > diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
> > > index ad80548..fd75f38 100644
> > > --- a/arch/arm/mm/init.c
> > > +++ b/arch/arm/mm/init.c
> > > @@ -745,19 +745,29 @@ static int __mark_rodata_ro(void *unused)
> > > return 0;
> > > }
> > >
> > > +static int kernel_set_to_readonly;
> >
> > Adding a comment here might be a good idea, something like:
> >
> > /* Has system boot-up reached mark_rodata_ro() yet? */
>
> I don't mind adding a comment, but the above is rather self explanatory
> (one can easily see that it is set in mark_rodata_ro() with a simple
> search).
>
> If a comment is to be added, something a bit more descriptive of the
> functionality of the variable would be appropriate:
>
> /*
> * Ignore modifying kernel text permissions until the kernel core calls
> * make_rodata_ro() at system start up.
> */
>
> I can resend with the comment, or whoever takes this could add it
> themselves.
Gentle ping: this patch doesn't seem to have landed in upstream
trees yet. Is any more work required?
It would be nice to have this fix added. Just tested next-20171205
on RPi B+, it oopses when the function tracer is enabled during boot.
next-20171205 plus this patch boots up fine.
so long,
Hias
>
> -- Steve
>
>
> >
> > Otherwise:
> >
> > Acked-by: Kees Cook <keescook@chromium.org>
> >
> > > +
> > > void mark_rodata_ro(void)
> > > {
> > > + kernel_set_to_readonly = 1;
> > > +
> > > stop_machine(__mark_rodata_ro, NULL, NULL);
> > > }
> > >
> > > void set_kernel_text_rw(void)
> > > {
> > > + if (!kernel_set_to_readonly)
> > > + return;
> > > +
> > > set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), false,
> > > current->active_mm);
> > > }
> > >
> > > void set_kernel_text_ro(void)
> > > {
> > > + if (!kernel_set_to_readonly)
> > > + return;
> > > +
> > > set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true,
> > > current->active_mm);
> > > }
> >
> > Does arm64 suffer from a similar condition? (It looks like no, as text
> > patching is done with a fixmap poke.)
> >
> > -Kees
> >
>
^ permalink raw reply
* [PATCH] soc: qcom: Separate kryo l2 accessors from PMU driver
From: ilialin at codeaurora.org @ 2017-12-05 11:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171205103516.bczf43vvpcin24zl@lakrids.cambridge.arm.com>
Hello Mark,
> -----Original Message-----
> From: Mark Rutland [mailto:mark.rutland at arm.com]
> Sent: Tuesday, December 5, 2017 12:35 PM
> To: Ilia Lin <ilialin@codeaurora.org>
> Cc: linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH] soc: qcom: Separate kryo l2 accessors from PMU driver
>
> Hi,
>
> On Tue, Dec 05, 2017 at 08:33:50AM +0200, Ilia Lin wrote:
> > The driver provides kernel level API for other drivers to access the
> > MSM8996 L2 cache registers.
> > Separating the L2 access code from the PMU driver and making it public
> > to allow other drivers use it.
> > The accesses must be separated with a single spinlock, maintained in
> > this driver.
> >
> > Change-Id: I2865e888491e85d678e298279400c371427e30ea
> > Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
>
> What other driver is going to use this?
>
> Until there is another driver, I don't see much point in factoring this
out.
The other driver currently is the CPU clock driver, which needs configuring
the L2 registers. The clock driver will be submitted through the linux-clk
list and will depend on the kryo-l2-accessors driver then.
Thanks,
Ilia
>
> Thanks,
> Mark.
>
> > ---
> > arch/arm64/Kconfig.platforms | 7 ++++
> > drivers/perf/qcom_l2_pmu.c | 48 +--------------------------
> > drivers/soc/qcom/Makefile | 1 +
> > drivers/soc/qcom/kryo-l2-accessors.c | 64
> > ++++++++++++++++++++++++++++++++++++
> > include/soc/qcom/kryo-l2-accessors.h | 27 +++++++++++++++
> > 5 files changed, 100 insertions(+), 47 deletions(-) create mode
> > 100644 drivers/soc/qcom/kryo-l2-accessors.c
> > create mode 100644 include/soc/qcom/kryo-l2-accessors.h
> >
> > diff --git a/arch/arm64/Kconfig.platforms
> > b/arch/arm64/Kconfig.platforms index 2401373..1cfed45 100644
> > --- a/arch/arm64/Kconfig.platforms
> > +++ b/arch/arm64/Kconfig.platforms
> > @@ -138,6 +138,13 @@ config ARCH_QCOM
> > help
> > This enables support for the ARMv8 based Qualcomm chipsets.
> >
> > +config ARCH_MSM8996
> > + bool "Enable Support for Qualcomm Technologies, Inc. MSM8996"
> > + depends on ARCH_QCOM
> > + help
> > + This enables support for the MSM8996 chipset. If you do not
> > + wish to build a kernel that runs on this chipset, say 'N' here.
> > +
> > config ARCH_REALTEK
> > bool "Realtek Platforms"
> > help
> > diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
> > index 4fdc848..ba5f241 100644
> > --- a/drivers/perf/qcom_l2_pmu.c
> > +++ b/drivers/perf/qcom_l2_pmu.c
> > @@ -30,7 +30,7 @@
> >
> > #include <asm/barrier.h>
> > #include <asm/local64.h>
> > -#include <asm/sysreg.h>
> > +#include <soc/qcom/kryo-l2-accessors.h>
> >
> > #define MAX_L2_CTRS 9
> >
> > @@ -87,9 +87,6 @@
> > #define L2_COUNTER_RELOAD BIT_ULL(31)
> > #define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63)
> >
> > -#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
> > -#define L2CPUSRDR_EL1 sys_reg(3, 3, 15, 0, 7)
> > -
> > #define reg_idx(reg, i) (((i) * IA_L2_REG_OFFSET) + reg##_BASE)
> >
> > /*
> > @@ -107,49 +104,6 @@
> > #define L2_EVENT_STREX 0x421
> > #define L2_EVENT_CLREX 0x422
> >
> > -static DEFINE_RAW_SPINLOCK(l2_access_lock);
> > -
> > -/**
> > - * set_l2_indirect_reg: write value to an L2 register
> > - * @reg: Address of L2 register.
> > - * @value: Value to be written to register.
> > - *
> > - * Use architecturally required barriers for ordering between system
> > register
> > - * accesses
> > - */
> > -static void set_l2_indirect_reg(u64 reg, u64 val) -{
> > - unsigned long flags;
> > -
> > - raw_spin_lock_irqsave(&l2_access_lock, flags);
> > - write_sysreg_s(reg, L2CPUSRSELR_EL1);
> > - isb();
> > - write_sysreg_s(val, L2CPUSRDR_EL1);
> > - isb();
> > - raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> > -}
> > -
> > -/**
> > - * get_l2_indirect_reg: read an L2 register value
> > - * @reg: Address of L2 register.
> > - *
> > - * Use architecturally required barriers for ordering between system
> > register
> > - * accesses
> > - */
> > -static u64 get_l2_indirect_reg(u64 reg) -{
> > - u64 val;
> > - unsigned long flags;
> > -
> > - raw_spin_lock_irqsave(&l2_access_lock, flags);
> > - write_sysreg_s(reg, L2CPUSRSELR_EL1);
> > - isb();
> > - val = read_sysreg_s(L2CPUSRDR_EL1);
> > - raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> > -
> > - return val;
> > -}
> > -
> > struct cluster_pmu;
> >
> > /*
> > diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> > index 40c56f6..2bf8d93 100644
> > --- a/drivers/soc/qcom/Makefile
> > +++ b/drivers/soc/qcom/Makefile
> > @@ -10,3 +10,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) +=
> smem_state.o
> > obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
> > obj-$(CONFIG_QCOM_SMSM) += smsm.o
> > obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
> > +obj-$(CONFIG_ARCH_MSM8996) += kryo-l2-accessors.o
> > diff --git a/drivers/soc/qcom/kryo-l2-accessors.c
> > b/drivers/soc/qcom/kryo-l2-accessors.c
> > new file mode 100644
> > index 0000000..6be57e6
> > --- /dev/null
> > +++ b/drivers/soc/qcom/kryo-l2-accessors.c
> > @@ -0,0 +1,64 @@
> > +/*
> > + * Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights
reserved.
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License version 2 and
> > + * only 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.
> > + */
> > +
> > +#include <linux/spinlock.h>
> > +#include <asm/sysreg.h>
> > +#include <soc/qcom/kryo-l2-accessors.h>
> > +
> > +#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
> > +#define L2CPUSRDR_EL1 sys_reg(3, 3, 15, 0, 7)
> > +
> > +static DEFINE_RAW_SPINLOCK(l2_access_lock);
> > +
> > +/**
> > + * set_l2_indirect_reg: write value to an L2 register
> > + * @reg: Address of L2 register.
> > + * @value: Value to be written to register.
> > + *
> > + * Use architecturally required barriers for ordering between system
> > +register
> > + * accesses, and system registers with respect to device memory */
> > +void set_l2_indirect_reg(u64 reg, u64 val) {
> > + unsigned long flags;
> > + mb();
> > + raw_spin_lock_irqsave(&l2_access_lock, flags);
> > + write_sysreg_s(reg, L2CPUSRSELR_EL1);
> > + isb();
> > + write_sysreg_s(val, L2CPUSRDR_EL1);
> > + isb();
> > + raw_spin_unlock_irqrestore(&l2_access_lock, flags); }
> > +EXPORT_SYMBOL(set_l2_indirect_reg);
> > +
> > +/**
> > + * get_l2_indirect_reg: read an L2 register value
> > + * @reg: Address of L2 register.
> > + *
> > + * Use architecturally required barriers for ordering between system
> > +register
> > + * accesses, and system registers with respect to device memory */
> > +u64 get_l2_indirect_reg(u64 reg)
> > +{
> > + u64 val;
> > + unsigned long flags;
> > +
> > + raw_spin_lock_irqsave(&l2_access_lock, flags);
> > + write_sysreg_s(reg, L2CPUSRSELR_EL1);
> > + isb();
> > + val = read_sysreg_s(L2CPUSRDR_EL1);
> > + raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> > +
> > + return val;
> > +}
> > +EXPORT_SYMBOL(get_l2_indirect_reg);
> > diff --git a/include/soc/qcom/kryo-l2-accessors.h
> > b/include/soc/qcom/kryo-l2-accessors.h
> > new file mode 100644
> > index 0000000..2bebce1
> > --- /dev/null
> > +++ b/include/soc/qcom/kryo-l2-accessors.h
> > @@ -0,0 +1,27 @@
> > +/*
> > + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License version 2 and
> > + * only 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.
> > + */
> > +
> > +#ifndef __ASM_ARCH_MSM_MSM_KRYO_L2_ACCESSORS_H
> > +#define __ASM_ARCH_MSM_MSM_KRYO_L2_ACCESSORS_H
> > +
> > +#ifdef CONFIG_ARCH_QCOM
> > +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> > +u64 get_l2_indirect_reg(u64 reg_addr); #else static inline void
> > +set_l2_indirect_reg(u32 reg_addr, u32 val) {} static inline u32
> > +get_l2_indirect_reg(u32 reg_addr) {
> > + return 0;
> > +}
> > +#endif
> > +#endif
> > --
> > 1.9.1
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] ASoC: atmel-classd: select correct Kconfig symbol
From: Nicolas Ferre @ 2017-12-05 11:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAK8P3a29G4T1DbkjwhEqa6cSVQL77z0jW0znMX47tqd5vM-P9Q@mail.gmail.com>
On 05/12/2017 at 12:13, Arnd Bergmann wrote:
> On Tue, Dec 5, 2017 at 11:57 AM, Alexandre Belloni
> <alexandre.belloni@free-electrons.com> wrote:
>> On 05/12/2017 at 11:09:38 +0100, Arnd Bergmann wrote:
>>> Commit 061981ff8cc8 ("ASoC: atmel: properly select dma driver state")
>>> changed the way that the dependencies are handled, but then the
>>> Class D amplifier support got merged, which used the old method.
>>>
>>> This seems to have triggered a very rare randconfig condition for me
>>> now, leading to a link error:
>>>
>>> sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_set_audio':
>>> atmel_ssc_dai.c:(.text+0x79c): undefined reference to `atmel_pcm_dma_platform_register'
>>> atmel_ssc_dai.c:(.text+0x79c): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `atmel_pcm_dma_platform_register'
>>> sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_put_audio':
>>> atmel_ssc_dai.c:(.text+0xf24): undefined reference to `atmel_pcm_dma_platform_unregister'
>>> atmel_ssc_dai.c:(.text+0xf24): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `atmel_pcm_dma_platform_unregister'
>>>
>>> Changing it to select SND_ATMEL_SOC_SSC_DMA as intended rather than
>>> SND_ATMEL_SOC_DMA directly makes it work again.
>>>
>>> Fixes: e0a25b6d1862 ("ASoC: atmel-classd: add the Audio Class D Amplifier")
>>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>> Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
>
> Unfortunately, my testing just found a new problem with this patch
> applied, I had
> not run enough randconfig tests on top of it:
>
> sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_set_audio':
> atmel_ssc_dai.c:(.text+0x73c): undefined reference to `ssc_request'
> sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_put_audio':
> atmel_ssc_dai.c:(.text+0x7be): undefined reference to `ssc_free'
>
> This is for a configuration with SND_ATMEL_SOC_CLASSD=y
> and CONFIG_ATMEL_SSC=n. Could you tell me whether that is a
> sensible configuration that should work, or whether we need a dependency
> on ATMEL_SSC in SND_ATMEL_SOC_CLASSD? I can't really tell
> from the source code, but you probably know the answer.
Actually, they are two different interfaces which can be enabled at the
same time or not and CLASSD doesn't use the SSC.
So no dependency between them.
It might be an issue with SND_ATMEL_SOC_DMA not selecting the proper code...
Regards,
--
Nicolas Ferre
^ permalink raw reply
* [PATCH] ASoC: atmel-classd: select correct Kconfig symbol
From: Arnd Bergmann @ 2017-12-05 11:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171205105750.GI21780@piout.net>
On Tue, Dec 5, 2017 at 11:57 AM, Alexandre Belloni
<alexandre.belloni@free-electrons.com> wrote:
> On 05/12/2017 at 11:09:38 +0100, Arnd Bergmann wrote:
>> Commit 061981ff8cc8 ("ASoC: atmel: properly select dma driver state")
>> changed the way that the dependencies are handled, but then the
>> Class D amplifier support got merged, which used the old method.
>>
>> This seems to have triggered a very rare randconfig condition for me
>> now, leading to a link error:
>>
>> sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_set_audio':
>> atmel_ssc_dai.c:(.text+0x79c): undefined reference to `atmel_pcm_dma_platform_register'
>> atmel_ssc_dai.c:(.text+0x79c): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `atmel_pcm_dma_platform_register'
>> sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_put_audio':
>> atmel_ssc_dai.c:(.text+0xf24): undefined reference to `atmel_pcm_dma_platform_unregister'
>> atmel_ssc_dai.c:(.text+0xf24): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `atmel_pcm_dma_platform_unregister'
>>
>> Changing it to select SND_ATMEL_SOC_SSC_DMA as intended rather than
>> SND_ATMEL_SOC_DMA directly makes it work again.
>>
>> Fixes: e0a25b6d1862 ("ASoC: atmel-classd: add the Audio Class D Amplifier")
>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Unfortunately, my testing just found a new problem with this patch
applied, I had
not run enough randconfig tests on top of it:
sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_set_audio':
atmel_ssc_dai.c:(.text+0x73c): undefined reference to `ssc_request'
sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_put_audio':
atmel_ssc_dai.c:(.text+0x7be): undefined reference to `ssc_free'
This is for a configuration with SND_ATMEL_SOC_CLASSD=y
and CONFIG_ATMEL_SSC=n. Could you tell me whether that is a
sensible configuration that should work, or whether we need a dependency
on ATMEL_SSC in SND_ATMEL_SOC_CLASSD? I can't really tell
from the source code, but you probably know the answer.
Arnd
^ permalink raw reply
* [RFC PATCH] arm64: deactivate saved ttbr when mm is deactivated
From: Mark Rutland @ 2017-12-05 11:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <72abe8f2-4d82-1375-956c-5e8b7869864c@codeaurora.org>
On Tue, Dec 05, 2017 at 10:30:40AM +0530, Vinayak Menon wrote:
> On 12/4/2017 11:30 PM, Mark Rutland wrote:
> > On Mon, Dec 04, 2017 at 04:55:33PM +0000, Will Deacon wrote:
> >> On Mon, Dec 04, 2017 at 09:53:26PM +0530, Vinayak Menon wrote:
> >>> A case is observed where a wrong physical address is read,
> >>> resulting in a bus error and that happens soon after TTBR0 is
> >>> set to the saved ttbr by uaccess_ttbr0_enable. This is always
> >>> seen to happen in the exit path of the task.
> >>>
> >>> exception
> >>> __arch_copy_from_user
> >>> __copy_from_user
> >>> probe_kernel_read
> >>> get_freepointer_safe
> >>> slab_alloc_node
> >>> slab_alloc
> >>> kmem_cache_alloc
> >>> kmem_cache_zalloc
> >>> fill_pool
> >>> __debug_object_init
> >>> debug_object_init
> >>> rcuhead_fixup_activate
> >>> debug_object_fixup
> >>> debug_object_activate
> >>> debug_rcu_head_queue
> >>> __call_rcu
> >>> ep_remove
> >>> eventpoll_release_file
> >>> __fput
> >>> ____fput
> >>> task_work_run
> >>> do_exit
> >>>
> >>> The mm has been released and the pgd is freed, but probe_kernel_read
> >>> invoked from slub results in call to __arch_copy_from_user. At the
> >>> entry to __arch_copy_from_user, when SW PAN is enabled, this results
> >>> in stale value being set to ttbr0. May be a speculative fetch aftwerwards
> >>> is resulting in invalid physical address access.
> > I think the problem here is that switch_mm() avoids updating the saved ttbr
> > value when the next mm is init_mm.
> For this switch to happen, the schedule() in do_task_dead at the end
> of do_exit() need to be called, right ? The issue is happening soon
> after exit_mm (probably from exit_files).
I'd assumed that we'd switch_mm() away from the task's mm prior to the
final mmput(). Otherwise, I can't see why we don't have issues in the
non SW PAN case (as that would leave the HW TTBR0 stale).
However, I can't see exactly where we do that, so I'll go diggging.
Something doesn't seem quite right.
Do you have a reproducer for the issue?
Thanks,
Mark.
^ permalink raw reply
* [PATCH 4/7 v2] net: ethernet: i825xx: Fix platform_get_irq's error checking
From: Russell King - ARM Linux @ 2017-12-05 10:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <791fdb7d-e0ec-eefb-c703-205c039eddc3@cogentembedded.com>
On Tue, Dec 05, 2017 at 01:12:23PM +0300, Sergei Shtylyov wrote:
> Well, we can have:
>
> return r && r->start ? r->start : -ENXIO;
>
> instead of:
>
> return r ? r->start : -ENXIO;
>
> at the end of platform_get_irq(). But I don't really think it's worth doing
> -- request_irq() doesn't filter out IRQ0 anyway, IIRC...
There's a bunch of platforms in the kernel that still use IRQ0, and
have done prior to Linus' comments on the subject. Such a change
would regress them.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH] ASoC: atmel-classd: select correct Kconfig symbol
From: Alexandre Belloni @ 2017-12-05 10:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171205101000.968887-1-arnd@arndb.de>
On 05/12/2017 at 11:09:38 +0100, Arnd Bergmann wrote:
> Commit 061981ff8cc8 ("ASoC: atmel: properly select dma driver state")
> changed the way that the dependencies are handled, but then the
> Class D amplifier support got merged, which used the old method.
>
> This seems to have triggered a very rare randconfig condition for me
> now, leading to a link error:
>
> sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_set_audio':
> atmel_ssc_dai.c:(.text+0x79c): undefined reference to `atmel_pcm_dma_platform_register'
> atmel_ssc_dai.c:(.text+0x79c): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `atmel_pcm_dma_platform_register'
> sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_put_audio':
> atmel_ssc_dai.c:(.text+0xf24): undefined reference to `atmel_pcm_dma_platform_unregister'
> atmel_ssc_dai.c:(.text+0xf24): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `atmel_pcm_dma_platform_unregister'
>
> Changing it to select SND_ATMEL_SOC_SSC_DMA as intended rather than
> SND_ATMEL_SOC_DMA directly makes it work again.
>
> Fixes: e0a25b6d1862 ("ASoC: atmel-classd: add the Audio Class D Amplifier")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> ---
> sound/soc/atmel/Kconfig | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
> index 4a56f3dfba51..2d998e5c4fb5 100644
> --- a/sound/soc/atmel/Kconfig
> +++ b/sound/soc/atmel/Kconfig
> @@ -64,7 +64,7 @@ config SND_AT91_SOC_SAM9X5_WM8731
> config SND_ATMEL_SOC_CLASSD
> tristate "Atmel ASoC driver for boards using CLASSD"
> depends on ARCH_AT91 || COMPILE_TEST
> - select SND_ATMEL_SOC_DMA
> + select SND_ATMEL_SOC_SSC_DMA
> select REGMAP_MMIO
> help
> Say Y if you want to add support for Atmel ASoC driver for boards using
> --
> 2.9.0
>
--
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH v6 2/2] media: i2c: Add the ov7740 image sensor driver
From: Sakari Ailus @ 2017-12-05 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171204065858.3138-3-wenyou.yang@microchip.com>
Hi Wenyou,
On Mon, Dec 04, 2017 at 02:58:58PM +0800, Wenyou Yang wrote:
> The ov7740 (color) image sensor is a high performance VGA CMOS
> image snesor, which supports for output formats: RAW RGB and YUV
> and image sizes: VGA, and QVGA, CIF and any size smaller.
>
> Signed-off-by: Songjun Wu <songjun.wu@microchip.com>
> Signed-off-by: Wenyou Yang <wenyou.yang@microchip.com>
> ---
>
> Changes in v6:
> - Remove unnecessary #include <linux/init>.
> - Remove unnecessary comments and extra newline.
> - Add const for some structures.
> - Add the check of the return value from regmap_write().
> - Simplify the calling of __v4l2_ctrl_handler_setup().
> - Add the default format initialization function.
> - Integrate the set_power() and enable/disable the clock into
> one function.
>
> Changes in v5:
> - Squash the driver and MAINTAINERS entry patches to one.
> - Precede the driver patch with the bindings patch.
>
> Changes in v4:
> - Assign 'val' a initial value to avoid warning: 'val' may be
> used uninitialized.
> - Rename REG_REG15 to avoid warning: "REG_REG15" redefined.
>
> Changes in v3:
> - Put the MAINTAINERS change to a separate patch.
>
> Changes in v2:
> - Split off the bindings into a separate patch.
> - Add a new entry to the MAINTAINERS file.
>
> MAINTAINERS | 8 +
> drivers/media/i2c/Kconfig | 8 +
> drivers/media/i2c/Makefile | 1 +
> drivers/media/i2c/ov7740.c | 1226 ++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 1243 insertions(+)
> create mode 100644 drivers/media/i2c/ov7740.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7a52a66aa991..1de965009b13 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -10053,6 +10053,14 @@ S: Maintained
> F: drivers/media/i2c/ov7670.c
> F: Documentation/devicetree/bindings/media/i2c/ov7670.txt
>
> +OMNIVISION OV7740 SENSOR DRIVER
> +M: Wenyou Yang <wenyou.yang@microchip.com>
> +L: linux-media at vger.kernel.org
> +T: git git://linuxtv.org/media_tree.git
> +S: Maintained
> +F: drivers/media/i2c/ov7740.c
> +F: Documentation/devicetree/bindings/media/i2c/ov7740.txt
> +
> ONENAND FLASH DRIVER
> M: Kyungmin Park <kyungmin.park@samsung.com>
> L: linux-mtd at lists.infradead.org
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> index cb5d7ff82915..00b1c4c031d4 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -665,6 +665,14 @@ config VIDEO_OV7670
> OV7670 VGA camera. It currently only works with the M88ALP01
> controller.
>
> +config VIDEO_OV7740
> + tristate "OmniVision OV7740 sensor support"
> + depends on I2C && VIDEO_V4L2
> + depends on MEDIA_CAMERA_SUPPORT
> + ---help---
> + This is a Video4Linux2 sensor-level driver for the OmniVision
> + OV7740 VGA camera sensor.
> +
> config VIDEO_OV9650
> tristate "OmniVision OV9650/OV9652 sensor support"
> depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
> diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
> index 548a9efce966..9b19ec7fcaf4 100644
> --- a/drivers/media/i2c/Makefile
> +++ b/drivers/media/i2c/Makefile
> @@ -68,6 +68,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o
> obj-$(CONFIG_VIDEO_OV6650) += ov6650.o
> obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
> obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
> +obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
> obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
> obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
> obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
> diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c
> new file mode 100644
> index 000000000000..42c25277d005
> --- /dev/null
> +++ b/drivers/media/i2c/ov7740.c
> @@ -0,0 +1,1226 @@
> +/*
> + * Copyright (c) 2017 Microchip Corporation.
> + *
> + * 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.
> + *
> + */
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/gpio.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-event.h>
> +#include <media/v4l2-image-sizes.h>
> +#include <media/v4l2-subdev.h>
> +
> +#define REG_OUTSIZE_LSB 0x34
> +
> +/* OV7740 register tables */
> +#define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */
> +#define REG_BGAIN 0x01 /* blue gain */
> +#define REG_RGAIN 0x02 /* red gain */
> +#define REG_GGAIN 0x03 /* green gain */
> +#define REG_REG04 0x04 /* analog setting, dont change*/
> +#define REG_BAVG 0x05 /* b channel average */
> +#define REG_GAVG 0x06 /* g channel average */
> +#define REG_RAVG 0x07 /* r channel average */
> +
> +#define REG_REG0C 0x0C /* filp enable */
> +#define REG0C_IMG_FLIP 0x80
> +#define REG0C_IMG_MIRROR 0x40
> +
> +#define REG_REG0E 0x0E /* blc line */
> +#define REG_HAEC 0x0F /* auto exposure cntrl */
> +#define REG_AEC 0x10 /* auto exposure cntrl */
> +
> +#define REG_CLK 0x11 /* Clock control */
> +#define REG_REG55 0x55 /* Clock PLL DIV/PreDiv */
> +
> +#define REG_REG12 0x12
> +
> +#define REG_REG13 0x13 /* auto/manual AGC, AEC, Write Balance*/
> +#define REG13_AEC_EN 0x01
> +#define REG13_AGC_EN 0x04
> +
> +#define REG_REG14 0x14
> +#define REG_CTRL15 0x15
> +#define REG15_GAIN_MSB 0x03
> +
> +#define REG_REG16 0x16
> +
> +#define REG_MIDH 0x1C /* manufacture id byte */
> +#define REG_MIDL 0x1D /* manufacture id byre */
> +#define REG_PIDH 0x0A /* Product ID MSB */
> +#define REG_PIDL 0x0B /* Product ID LSB */
> +
> +#define REG_84 0x84 /* lots of stuff */
> +#define REG_REG38 0x38 /* sub-addr */
> +
> +#define REG_AHSTART 0x17 /* Horiz start high bits */
> +#define REG_AHSIZE 0x18
> +#define REG_AVSTART 0x19 /* Vert start high bits */
> +#define REG_AVSIZE 0x1A
> +#define REG_PSHFT 0x1b /* Pixel delay after HREF */
> +
> +#define REG_HOUTSIZE 0x31
> +#define REG_VOUTSIZE 0x32
> +#define REG_HVSIZEOFF 0x33
> +#define REG_REG34 0x34 /* DSP output size H/V LSB*/
> +
> +#define REG_ISP_CTRL00 0x80
> +#define ISPCTRL00_AWB_EN 0x10
> +#define ISPCTRL00_AWB_GAIN_EN 0x04
> +
> +#define REG_YGAIN 0xE2 /* ygain for contrast control */
> +
> +#define REG_YBRIGHT 0xE3
> +#define REG_SGNSET 0xE4
> +#define SGNSET_YBRIGHT_MASK 0x08
> +
> +#define REG_USAT 0xDD
> +#define REG_VSAT 0xDE
> +
> +
> +struct ov7740 {
> + struct v4l2_subdev subdev;
> +#if defined(CONFIG_MEDIA_CONTROLLER)
> + struct media_pad pad;
> +#endif
> + struct v4l2_mbus_framefmt format;
> + const struct ov7740_pixfmt *fmt; /* Current format */
> + const struct ov7740_framesize *frmsize;
> + struct regmap *regmap;
> + struct clk *xvclk;
> + struct v4l2_ctrl_handler ctrl_handler;
> + struct {
> + /* gain cluster */
> + struct v4l2_ctrl *auto_gain;
> + struct v4l2_ctrl *gain;
> + };
> + struct {
> + struct v4l2_ctrl *auto_wb;
> + struct v4l2_ctrl *blue_balance;
> + struct v4l2_ctrl *red_balance;
> + };
> + struct {
> + struct v4l2_ctrl *hflip;
> + struct v4l2_ctrl *vflip;
> + };
> + struct {
> + /* exposure cluster */
> + struct v4l2_ctrl *auto_exposure;
> + struct v4l2_ctrl *exposure;
> + };
> + struct {
> + /* saturation/hue cluster */
> + struct v4l2_ctrl *saturation;
> + struct v4l2_ctrl *hue;
> + };
> + struct v4l2_ctrl *brightness;
> + struct v4l2_ctrl *contrast;
> +
> + struct mutex mutex; /* To serialize asynchronus callbacks */
> + bool streaming; /* Streaming on/off */
> +
> + struct gpio_desc *resetb_gpio;
> + struct gpio_desc *pwdn_gpio;
> +};
> +
> +struct ov7740_pixfmt {
> + u32 mbus_code;
> + enum v4l2_colorspace colorspace;
> + const struct reg_sequence *regs;
> + u32 reg_num;
> +};
> +
> +struct ov7740_framesize {
> + u16 width;
> + u16 height;
> + const struct reg_sequence *regs;
> + u32 reg_num;
> +};
> +
> +static const struct reg_sequence ov7740_vga[] = {
> + {0x55, 0x40},
> + {0x11, 0x02},
> +
> + {0xd5, 0x10},
> + {0x0c, 0x12},
> + {0x0d, 0x34},
> + {0x17, 0x25},
> + {0x18, 0xa0},
> + {0x19, 0x03},
> + {0x1a, 0xf0},
> + {0x1b, 0x89},
> + {0x22, 0x03},
> + {0x29, 0x18},
> + {0x2b, 0xf8},
> + {0x2c, 0x01},
> + {REG_HOUTSIZE, 0xa0},
> + {REG_VOUTSIZE, 0xf0},
> + {0x33, 0xc4},
> + {REG_OUTSIZE_LSB, 0x0},
> + {0x35, 0x05},
> + {0x04, 0x60},
> + {0x27, 0x80},
> + {0x3d, 0x0f},
> + {0x3e, 0x80},
> + {0x3f, 0x40},
> + {0x40, 0x7f},
> + {0x41, 0x6a},
> + {0x42, 0x29},
> + {0x44, 0x22},
> + {0x45, 0x41},
> + {0x47, 0x02},
> + {0x49, 0x64},
> + {0x4a, 0xa1},
> + {0x4b, 0x40},
> + {0x4c, 0x1a},
> + {0x4d, 0x50},
> + {0x4e, 0x13},
> + {0x64, 0x00},
> + {0x67, 0x88},
> + {0x68, 0x1a},
> +
> + {0x14, 0x28},
> + {0x24, 0x3c},
> + {0x25, 0x30},
> + {0x26, 0x72},
> + {0x50, 0x97},
> + {0x51, 0x1f},
> + {0x52, 0x00},
> + {0x53, 0x00},
> + {0x20, 0x00},
> + {0x21, 0xcf},
> + {0x50, 0x4b},
> + {0x38, 0x14},
> + {0xe9, 0x00},
> + {0x56, 0x55},
> + {0x57, 0xff},
> + {0x58, 0xff},
> + {0x59, 0xff},
> + {0x5f, 0x04},
> + {0xec, 0x00},
> + {0x13, 0xff},
> +
> + {0x81, 0x3f},
> + {0x82, 0x32},
> + {0x38, 0x11},
> + {0x84, 0x70},
> + {0x85, 0x00},
> + {0x86, 0x03},
> + {0x87, 0x01},
> + {0x88, 0x05},
> + {0x89, 0x30},
> + {0x8d, 0x30},
> + {0x8f, 0x85},
> + {0x93, 0x30},
> + {0x95, 0x85},
> + {0x99, 0x30},
> + {0x9b, 0x85},
> +
> + {0x9c, 0x08},
> + {0x9d, 0x12},
> + {0x9e, 0x23},
> + {0x9f, 0x45},
> + {0xa0, 0x55},
> + {0xa1, 0x64},
> + {0xa2, 0x72},
> + {0xa3, 0x7f},
> + {0xa4, 0x8b},
> + {0xa5, 0x95},
> + {0xa6, 0xa7},
> + {0xa7, 0xb5},
> + {0xa8, 0xcb},
> + {0xa9, 0xdd},
> + {0xaa, 0xec},
> + {0xab, 0x1a},
> +
> + {0xce, 0x78},
> + {0xcf, 0x6e},
> + {0xd0, 0x0a},
> + {0xd1, 0x0c},
> + {0xd2, 0x84},
> + {0xd3, 0x90},
> + {0xd4, 0x1e},
> +
> + {0x5a, 0x24},
> + {0x5b, 0x1f},
> + {0x5c, 0x88},
> + {0x5d, 0x60},
> +
> + {0xac, 0x6e},
> + {0xbe, 0xff},
> + {0xbf, 0x00},
> +
> + {0x0f, 0x1d},
> + {0x0f, 0x1f},
> +};
> +
> +static const struct ov7740_framesize ov7740_framesizes[] = {
> + {
> + .width = VGA_WIDTH,
> + .height = VGA_HEIGHT,
> + .regs = ov7740_vga,
> + .reg_num = ARRAY_SIZE(ov7740_vga),
> + },
> +};
> +
> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> +static int ov7740_get_register(struct v4l2_subdev *sd,
> + struct v4l2_dbg_register *reg)
> +{
> + struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> + struct regmap *regmap = ov7740->regmap;
> + unsigned int val = 0;
> + int ret;
> +
> + ret = regmap_read(regmap, reg->reg & 0xff, &val);
> + reg->val = val;
> + reg->size = 1;
> +
> + return 0;
> +}
> +
> +static int ov7740_set_register(struct v4l2_subdev *sd,
> + const struct v4l2_dbg_register *reg)
> +{
> + struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> + struct regmap *regmap = ov7740->regmap;
> +
> + regmap_write(regmap, reg->reg & 0xff, reg->val & 0xff);
> +
> + return 0;
> +}
> +#endif
> +
> +static int ov7740_set_power(struct ov7740 *ov7740, int on)
> +{
> + int ret;
> +
> + if (on) {
> + ret = clk_prepare_enable(ov7740->xvclk);
> + if (ret)
> + return ret;
> +
> + if (ov7740->pwdn_gpio)
> + gpiod_direction_output(ov7740->pwdn_gpio, 0);
> +
> + if (ov7740->resetb_gpio) {
> + gpiod_set_value(ov7740->resetb_gpio, 1);
> + usleep_range(500, 1000);
> + gpiod_set_value(ov7740->resetb_gpio, 0);
> + usleep_range(3000, 5000);
> + }
> + } else {
> + clk_disable_unprepare(ov7740->xvclk);
> +
> + if (ov7740->pwdn_gpio)
> + gpiod_direction_output(ov7740->pwdn_gpio, 0);
> + }
> +
> + return 0;
> +}
> +
> +static struct v4l2_subdev_core_ops ov7740_subdev_core_ops = {
> + .log_status = v4l2_ctrl_subdev_log_status,
> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> + .g_register = ov7740_get_register,
> + .s_register = ov7740_set_register,
> +#endif
> + .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
> + .unsubscribe_event = v4l2_event_subdev_unsubscribe,
> +};
> +
> +static int ov7740_set_white_balance(struct ov7740 *ov7740, int awb)
> +{
> + struct regmap *regmap = ov7740->regmap;
> + unsigned int value;
> + int ret;
> +
> + ret = regmap_read(regmap, REG_ISP_CTRL00, &value);
> + if (!ret) {
> + if (awb)
> + value |= (ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
> + else
> + value &= ~(ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
> + ret = regmap_write(regmap, REG_ISP_CTRL00, value);
> + if (ret)
> + return ret;
> + }
> +
> + if (!awb) {
> + ret = regmap_write(regmap, REG_BGAIN,
> + ov7740->blue_balance->val);
> + if (ret)
> + return ret;
> +
> + ret = regmap_write(regmap, REG_RGAIN, ov7740->red_balance->val);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int ov7740_set_saturation(struct regmap *regmap, int value)
> +{
> + int ret;
> +
> + ret = regmap_write(regmap, REG_USAT, (unsigned char)value);
> + if (ret)
> + return ret;
> +
> + return regmap_write(regmap, REG_VSAT, (unsigned char)value);
> +}
> +
> +static int ov7740_set_gain(struct regmap *regmap, int value)
> +{
> + int ret;
> +
> + ret = regmap_write(regmap, REG_GAIN, value & 0xff);
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(regmap, REG_CTRL15,
> + REG15_GAIN_MSB, (value >> 8) & 0x3);
> + if (!ret)
> + ret = regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
> +
> + return ret;
> +}
> +
> +static int ov7740_set_autogain(struct regmap *regmap, int value)
> +{
> + unsigned int reg;
> + int ret;
> +
> + ret = regmap_read(regmap, REG_REG13, ®);
> + if (ret)
> + return ret;
> + if (value)
> + reg |= REG13_AGC_EN;
> + else
> + reg &= ~REG13_AGC_EN;
> + return regmap_write(regmap, REG_REG13, reg);
> +}
> +
> +static int ov7740_set_brightness(struct regmap *regmap, int value)
> +{
> + /* Turn off AEC/AGC */
> + regmap_update_bits(regmap, REG_REG13, REG13_AEC_EN, 0);
> + regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
> +
> + if (value >= 0) {
> + regmap_write(regmap, REG_YBRIGHT, (unsigned char)value);
> + regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 0);
> + } else{
> + regmap_write(regmap, REG_YBRIGHT, (unsigned char)(-value));
> + regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 1);
> + }
> +
> + return 0;
> +}
> +
> +static int ov7740_set_contrast(struct regmap *regmap, int value)
> +{
> + return regmap_write(regmap, REG_YGAIN, (unsigned char)value);
> +}
> +
> +static int ov7740_get_gain(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl)
> +{
> + struct regmap *regmap = ov7740->regmap;
> + unsigned int value0, value1;
> + int ret;
> +
> + if (!ctrl->val)
> + return 0;
> +
> + ret = regmap_read(regmap, REG_GAIN, &value0);
> + if (ret)
> + return ret;
> + ret = regmap_read(regmap, REG_CTRL15, &value1);
> + if (ret)
> + return ret;
> +
> + ov7740->gain->val = (value1 << 8) | (value0 & 0xff);
> +
> + return 0;
> +}
> +
> +static int ov7740_set_exp(struct regmap *regmap, int value)
> +{
> + int ret;
> +
> + /* Turn off AEC/AGC */
> + ret = regmap_update_bits(regmap, REG_REG13,
> + REG13_AEC_EN | REG13_AGC_EN, 0);
> + if (ret)
> + return ret;
> +
> + ret = regmap_write(regmap, REG_AEC, (unsigned char)value);
> + if (ret)
> + return ret;
> +
> + return regmap_write(regmap, REG_HAEC, (unsigned char)(value >> 8));
> +}
> +
> +static int ov7740_set_autoexp(struct regmap *regmap,
> + enum v4l2_exposure_auto_type value)
> +{
> + unsigned int reg;
> + int ret;
> +
> + ret = regmap_read(regmap, REG_REG13, ®);
> + if (!ret) {
> + if (value == V4L2_EXPOSURE_AUTO)
> + reg |= (REG13_AEC_EN | REG13_AGC_EN);
> + else
> + reg &= ~(REG13_AEC_EN | REG13_AGC_EN);
> + ret = regmap_write(regmap, REG_REG13, reg);
> + }
> +
> + return ret;
> +}
> +
> +
> +static int ov7740_get_volatile_ctrl(struct v4l2_ctrl *ctrl)
> +{
> + struct ov7740 *ov7740 = container_of(ctrl->handler,
> + struct ov7740, ctrl_handler);
> + int ret;
> +
> + switch (ctrl->id) {
> + case V4L2_CID_AUTOGAIN:
> + ret = ov7740_get_gain(ov7740, ctrl);
> + break;
> + default:
> + ret = -EINVAL;
> + break;
> + }
> + return ret;
> +}
> +
> +static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl)
> +{
> + struct ov7740 *ov7740 = container_of(ctrl->handler,
> + struct ov7740, ctrl_handler);
> + struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
> + struct regmap *regmap = ov7740->regmap;
> + int ret;
> + u8 val = 0;
> +
> + if (pm_runtime_get_if_in_use(&client->dev) <= 0)
> + return 0;
> +
> + switch (ctrl->id) {
> + case V4L2_CID_AUTO_WHITE_BALANCE:
> + ret = ov7740_set_white_balance(ov7740, ctrl->val);
> + break;
> + case V4L2_CID_SATURATION:
> + ret = ov7740_set_saturation(regmap, ctrl->val);
> + break;
> + case V4L2_CID_BRIGHTNESS:
> + ret = ov7740_set_brightness(regmap, ctrl->val);
> + break;
> + case V4L2_CID_CONTRAST:
> + ret = ov7740_set_contrast(regmap, ctrl->val);
> + break;
> + case V4L2_CID_VFLIP:
> + ret = regmap_update_bits(regmap, REG_REG0C,
> + REG0C_IMG_FLIP, val);
> + break;
> + case V4L2_CID_HFLIP:
> + val = ctrl->val ? REG0C_IMG_MIRROR : 0x00;
> + ret = regmap_update_bits(regmap, REG_REG0C,
> + REG0C_IMG_MIRROR, val);
> + break;
> + case V4L2_CID_AUTOGAIN:
> + if (!ctrl->val)
> + return ov7740_set_gain(regmap, ov7740->gain->val);
> +
> + ret = ov7740_set_autogain(regmap, ctrl->val);
> + break;
> +
> + case V4L2_CID_EXPOSURE_AUTO:
> + if (ctrl->val == V4L2_EXPOSURE_MANUAL)
> + return ov7740_set_exp(regmap, ov7740->exposure->val);
> +
> + ret = ov7740_set_autoexp(regmap, ctrl->val);
> + break;
> + default:
> + ret = -EINVAL;
> + break;
> + }
> +
> + pm_runtime_put(&client->dev);
> +
> + return ret;
> +}
> +
> +static const struct v4l2_ctrl_ops ov7740_ctrl_ops = {
> + .g_volatile_ctrl = ov7740_get_volatile_ctrl,
> + .s_ctrl = ov7740_set_ctrl,
> +};
> +
> +static int ov7740_start_streaming(struct ov7740 *ov7740)
> +{
> + return __v4l2_ctrl_handler_setup(ov7740->subdev.ctrl_handler);
> +}
> +
> +static int ov7740_set_stream(struct v4l2_subdev *sd, int enable)
> +{
> + struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> + struct i2c_client *client = v4l2_get_subdevdata(sd);
> + int ret = 0;
> +
> + mutex_lock(&ov7740->mutex);
> + if (ov7740->streaming == enable) {
> + mutex_unlock(&ov7740->mutex);
> + return 0;
> + }
> +
> + if (enable) {
> + ret = pm_runtime_get_sync(&client->dev);
> + if (ret < 0) {
> + pm_runtime_put_noidle(&client->dev);
> + goto err_unlock;
> + }
> +
> + ret = ov7740_start_streaming(ov7740);
> + if (ret)
> + goto err_rpm_put;
> + } else {
> + pm_runtime_put(&client->dev);
> + }
> +
> + ov7740->streaming = enable;
> +
> + mutex_unlock(&ov7740->mutex);
> + return ret;
> +
> +err_rpm_put:
> + pm_runtime_put(&client->dev);
> +err_unlock:
> + mutex_unlock(&ov7740->mutex);
> + return ret;
> +}
> +
> +static int ov7740_get_parm(struct v4l2_subdev *sd,
> + struct v4l2_streamparm *parms)
> +{
> + struct v4l2_captureparm *cp = &parms->parm.capture;
> + struct v4l2_fract *tpf = &cp->timeperframe;
> +
> + if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> + return -EINVAL;
> +
> + memset(cp, 0, sizeof(struct v4l2_captureparm));
> + cp->capability = V4L2_CAP_TIMEPERFRAME;
> +
> + tpf->numerator = 1;
> + tpf->denominator = 60;
> +
> + return 0;
> +}
> +
> +static int ov7740_set_parm(struct v4l2_subdev *sd,
> + struct v4l2_streamparm *parms)
> +{
> + struct v4l2_captureparm *cp = &parms->parm.capture;
> + struct v4l2_fract *tpf = &cp->timeperframe;
> +
> + if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> + return -EINVAL;
> + if (cp->extendedmode != 0)
> + return -EINVAL;
> +
> + cp->capability = V4L2_CAP_TIMEPERFRAME;
> +
> + tpf->numerator = 1;
> + tpf->denominator = 60;
> +
> + return 0;
> +}
> +
> +static struct v4l2_subdev_video_ops ov7740_subdev_video_ops = {
> + .s_stream = ov7740_set_stream,
> + .s_parm = ov7740_set_parm,
> + .g_parm = ov7740_get_parm,
> +};
> +
> +static const struct reg_sequence ov7740_format_yuyv[] = {
> + {0x12, 0x00},
> + {0x36, 0x3f},
> + {0x80, 0x7f},
> + {0x83, 0x01},
> +};
> +
> +static const struct reg_sequence ov7740_format_bggr8[] = {
> + {0x36, 0x2f},
> + {0x80, 0x01},
> + {0x83, 0x04},
> +};
> +
> +static const struct ov7740_pixfmt ov7740_formats[] = {
> + {
> + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
> + .colorspace = V4L2_COLORSPACE_SRGB,
> + .regs = ov7740_format_yuyv,
> + .reg_num = ARRAY_SIZE(ov7740_format_yuyv),
> + },
> + {
> + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
> + .colorspace = V4L2_COLORSPACE_SRGB,
> + .regs = ov7740_format_bggr8,
> + .reg_num = ARRAY_SIZE(ov7740_format_bggr8),
> + }
> +};
> +#define N_OV7740_FMTS ARRAY_SIZE(ov7740_formats)
> +
> +static int ov7740_enum_mbus_code(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_mbus_code_enum *code)
> +{
> + if (code->pad || code->index >= N_OV7740_FMTS)
> + return -EINVAL;
> +
> + code->code = ov7740_formats[code->index].mbus_code;
> +
> + return 0;
> +}
> +
> +static int ov7740_enum_frame_interval(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_frame_interval_enum *fie)
> +{
> + if (fie->pad)
> + return -EINVAL;
> +
> + if (fie->index >= 1)
> + return -EINVAL;
> +
> + if ((fie->width != VGA_WIDTH) || (fie->height != VGA_HEIGHT))
> + return -EINVAL;
> +
> + fie->interval.numerator = 1;
> + fie->interval.denominator = 60;
> +
> + return 0;
> +}
> +
> +static int ov7740_enum_frame_size(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_frame_size_enum *fse)
> +{
> + if (fse->pad)
> + return -EINVAL;
> +
> + if (fse->index > 0)
> + return -EINVAL;
> +
> + fse->min_width = fse->max_width = VGA_WIDTH;
> + fse->min_height = fse->max_height = VGA_HEIGHT;
> +
> + return 0;
> +}
> +
> +static int ov7740_try_fmt_internal(struct v4l2_subdev *sd,
> + struct v4l2_mbus_framefmt *fmt,
> + const struct ov7740_pixfmt **ret_fmt,
> + const struct ov7740_framesize **ret_frmsize)
> +{
> + struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> + const struct ov7740_framesize *fsize = &ov7740_framesizes[0];
> + int index, i;
> +
> + for (index = 0; index < N_OV7740_FMTS; index++) {
> + if (ov7740_formats[index].mbus_code == fmt->code)
> + break;
> + }
> + if (index >= N_OV7740_FMTS) {
> + /* default to first format */
> + index = 0;
> + fmt->code = ov7740_formats[0].mbus_code;
> + }
> + if (ret_fmt != NULL)
> + *ret_fmt = ov7740_formats + index;
> +
> + for (i = 0; i < ARRAY_SIZE(ov7740_framesizes); i++) {
> + if ((fsize->width >= fmt->width) &&
> + (fsize->height >= fmt->height)) {
> + fmt->width = fsize->width;
> + fmt->height = fsize->height;
> + break;
> + }
> +
> + fsize++;
> + }
> +
> + if (ret_frmsize != NULL)
> + *ret_frmsize = fsize;
> +
> + fmt->field = V4L2_FIELD_NONE;
> + fmt->colorspace = ov7740_formats[index].colorspace;
> +
> + ov7740->format = *fmt;
> +
> + return 0;
> +}
> +
> +static int ov7740_set_fmt(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_format *format)
> +{
> + struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> + const struct ov7740_pixfmt *ovfmt;
> + const struct ov7740_framesize *fsize;
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> + struct v4l2_mbus_framefmt *mbus_fmt;
> +#endif
> + int ret;
> +
> + mutex_lock(&ov7740->mutex);
> + if (format->pad) {
> + ret = -EINVAL;
> + goto error;
> + }
> +
> + if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
> + ret = ov7740_try_fmt_internal(sd, &format->format, NULL, NULL);
> + if (ret)
> + goto error;
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
> + *mbus_fmt = format->format;
> +
> + mutex_unlock(&ov7740->mutex);
> + return 0;
> +#else
> + ret = -ENOTTY;
> + goto error;
> +#endif
> + }
> +
> + ret = ov7740_try_fmt_internal(sd, &format->format, &ovfmt, &fsize);
> + if (ret)
> + goto error;
> +
> + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
> + regmap_multi_reg_write(ov7740->regmap,
> + ovfmt->regs, ovfmt->reg_num);
> +
> + regmap_multi_reg_write(ov7740->regmap,
> + fsize->regs, fsize->reg_num);
> + }
> +
> + ov7740->fmt = ovfmt;
> +
> + mutex_unlock(&ov7740->mutex);
> + return 0;
> +
> +error:
> + mutex_unlock(&ov7740->mutex);
> + return ret;
> +}
> +
> +static int ov7740_get_fmt(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_format *format)
> +{
> + struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> + struct v4l2_mbus_framefmt *mbus_fmt;
> +#endif
> + int ret = 0;
> +
> + mutex_lock(&ov7740->mutex);
> + if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
> + format->format = *mbus_fmt;
> + ret = 0;
> +#else
> + ret = -ENOTTY;
> +#endif
> + } else {
> + format->format = ov7740->format;
> + }
> + mutex_unlock(&ov7740->mutex);
> +
> + return ret;
> +}
> +
> +static const struct v4l2_subdev_pad_ops ov7740_subdev_pad_ops = {
> + .enum_frame_interval = ov7740_enum_frame_interval,
> + .enum_frame_size = ov7740_enum_frame_size,
> + .enum_mbus_code = ov7740_enum_mbus_code,
> + .get_fmt = ov7740_get_fmt,
> + .set_fmt = ov7740_set_fmt,
> +};
> +
> +static const struct v4l2_subdev_ops ov7740_subdev_ops = {
> + .core = &ov7740_subdev_core_ops,
> + .video = &ov7740_subdev_video_ops,
> + .pad = &ov7740_subdev_pad_ops,
> +};
> +
> +static void ov7740_get_default_format(struct v4l2_subdev *sd,
> + struct v4l2_mbus_framefmt *format)
> +{
> + struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +
> + format->width = ov7740->frmsize->width;
> + format->height = ov7740->frmsize->height;
> + format->colorspace = ov7740->fmt->colorspace;
> + format->code = ov7740->fmt->mbus_code;
> + format->field = V4L2_FIELD_NONE;
> +}
> +
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> + struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> + struct v4l2_mbus_framefmt *format =
> + v4l2_subdev_get_try_format(sd, fh->pad, 0);
> +
> + mutex_lock(&ov7740->mutex);
> + ov7740_get_default_format(sd, format);
> + mutex_unlock(&ov7740->mutex);
> +
> + return 0;
> +}
> +
> +static const struct v4l2_subdev_internal_ops ov7740_subdev_internal_ops = {
> + .open = ov7740_open,
> +};
> +#endif
> +
> +static void ov7740_init_default_format(struct ov7740 *ov7740)
> +{
> + ov7740->frmsize = &ov7740_framesizes[0];
> + ov7740->fmt = &ov7740_formats[0];
> +
> + regmap_multi_reg_write(ov7740->regmap,
> + ov7740->fmt->regs, ov7740->fmt->reg_num);
> +
> + regmap_multi_reg_write(ov7740->regmap,
> + ov7740->frmsize->regs, ov7740->frmsize->reg_num);
> +}
> +
> +static int ov7740_probe_dt(struct i2c_client *client,
> + struct ov7740 *ov7740)
> +{
> + ov7740->resetb_gpio = devm_gpiod_get_optional(&client->dev, "reset",
> + GPIOD_OUT_HIGH);
> + if (IS_ERR(ov7740->resetb_gpio)) {
> + dev_info(&client->dev, "can't get %s GPIO\n", "reset");
> + return PTR_ERR(ov7740->resetb_gpio);
> + }
> +
> + ov7740->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
> + GPIOD_OUT_LOW);
> + if (IS_ERR(ov7740->pwdn_gpio)) {
> + dev_info(&client->dev, "can't get %s GPIO\n", "powerdown");
> + return PTR_ERR(ov7740->pwdn_gpio);
> + }
> +
> + return 0;
> +}
> +
> +static int ov7740_detect(struct ov7740 *ov7740)
> +{
> + struct regmap *regmap = ov7740->regmap;
> + unsigned int midh, midl, pidh, pidl;
> + int ret;
> +
> + ret = regmap_read(regmap, REG_MIDH, &midh);
> + if (ret)
> + return ret;
> + if (midh != 0x7f)
> + return -ENODEV;
> +
> + ret = regmap_read(regmap, REG_MIDL, &midl);
> + if (ret)
> + return ret;
> + if (midl != 0xa2)
> + return -ENODEV;
> +
> + ret = regmap_read(regmap, REG_PIDH, &pidh);
> + if (ret)
> + return ret;
> + if (pidh != 0x77)
> + return -ENODEV;
> +
> + ret = regmap_read(regmap, REG_PIDL, &pidl);
> + if (ret)
> + return ret;
> + if ((pidl != 0x40) && (pidl != 0x41) && (pidl != 0x42))
> + return -ENODEV;
> +
> + return 0;
> +}
> +
> +static int ov7740_init_controls(struct ov7740 *ov7740)
> +{
> + struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
> + struct v4l2_ctrl_handler *ctrl_hdlr = &ov7740->ctrl_handler;
> + int ret;
> +
> + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 2);
> + if (ret < 0)
> + return ret;
> +
> + ctrl_hdlr->lock = &ov7740->mutex;
> + ov7740->auto_wb = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> + V4L2_CID_AUTO_WHITE_BALANCE,
> + 0, 1, 1, 1);
> + ov7740->blue_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> + V4L2_CID_BLUE_BALANCE,
> + 0, 0xff, 1, 0x80);
> + ov7740->red_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> + V4L2_CID_RED_BALANCE,
> + 0, 0xff, 1, 0x80);
> +
> + ov7740->brightness = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> + V4L2_CID_BRIGHTNESS,
> + -255, 255, 1, 0);
> + ov7740->contrast = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> + V4L2_CID_CONTRAST,
> + 0, 127, 1, 0x20);
> + ov7740->saturation = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> + V4L2_CID_SATURATION, 0, 256, 1, 0x80);
> + ov7740->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> + V4L2_CID_HFLIP, 0, 1, 1, 0);
> + ov7740->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> + V4L2_CID_VFLIP, 0, 1, 1, 0);
> + ov7740->gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> + V4L2_CID_GAIN, 0, 1023, 1, 500);
> + ov7740->auto_gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> + V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
> + ov7740->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> + V4L2_CID_EXPOSURE, 0, 65535, 1, 500);
> + ov7740->auto_exposure = v4l2_ctrl_new_std_menu(ctrl_hdlr,
> + &ov7740_ctrl_ops,
> + V4L2_CID_EXPOSURE_AUTO,
> + V4L2_EXPOSURE_MANUAL, 0,
> + V4L2_EXPOSURE_AUTO);
> +
> + ov7740->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
> + ov7740->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
> +
> + v4l2_ctrl_auto_cluster(3, &ov7740->auto_wb, 0, false);
> + v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true);
> + v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure,
> + V4L2_EXPOSURE_MANUAL, false);
> + v4l2_ctrl_cluster(2, &ov7740->hflip);
> +
> + ret = v4l2_ctrl_handler_setup(ctrl_hdlr);
> + if (ret) {
> + dev_err(&client->dev, "%s control init failed (%d)\n",
> + __func__, ret);
> + goto error;
> + }
> +
> + ov7740->subdev.ctrl_handler = ctrl_hdlr;
> + return 0;
> +
> +error:
> + v4l2_ctrl_handler_free(ctrl_hdlr);
> + mutex_destroy(&ov7740->mutex);
> + return ret;
> +}
> +
> +static void ov7740_free_controls(struct ov7740 *ov7740)
> +{
> + v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
> + mutex_destroy(&ov7740->mutex);
> +}
> +
> +#define OV7740_MAX_REGISTER 0xff
> +static const struct regmap_config ov7740_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = OV7740_MAX_REGISTER,
> +};
> +
> +static int ov7740_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct ov7740 *ov7740;
> + struct v4l2_subdev *sd;
> + int ret;
> +
> + if (!i2c_check_functionality(client->adapter,
> + I2C_FUNC_SMBUS_BYTE_DATA)) {
> + dev_err(&client->dev,
> + "OV7740: I2C-Adapter doesn't support SMBUS\n");
> + return -EIO;
> + }
> +
> + ov7740 = devm_kzalloc(&client->dev, sizeof(*ov7740), GFP_KERNEL);
> + if (!ov7740)
> + return -ENOMEM;
> +
> + ov7740->xvclk = devm_clk_get(&client->dev, "xvclk");
> + if (IS_ERR(ov7740->xvclk)) {
> + ret = PTR_ERR(ov7740->xvclk);
> + dev_err(&client->dev,
> + "OV7740: fail to get xvclk: %d\n", ret);
> + return ret;
> + }
> +
> + ret = ov7740_probe_dt(client, ov7740);
> + if (ret)
> + return ret;
> +
> + ov7740->regmap = devm_regmap_init_i2c(client, &ov7740_regmap_config);
> + if (IS_ERR(ov7740->regmap)) {
> + ret = PTR_ERR(ov7740->regmap);
> + dev_err(&client->dev, "Failed to allocate register map: %d\n",
> + ret);
> + return ret;
> + }
> +
> + sd = &ov7740->subdev;
> + client->flags |= I2C_CLIENT_SCCB;
> + v4l2_i2c_subdev_init(sd, client, &ov7740_subdev_ops);
> +
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> + sd->internal_ops = &ov7740_subdev_internal_ops;
> + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> +#endif
> +
> +#if defined(CONFIG_MEDIA_CONTROLLER)
> + ov7740->pad.flags = MEDIA_PAD_FL_SOURCE;
> + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
> + ret = media_entity_pads_init(&sd->entity, 1, &ov7740->pad);
> + if (ret)
> + return ret;
> +#endif
> +
> + ret = ov7740_set_power(ov7740, 1);
> + if (ret)
> + return ret;
> +
> + ret = ov7740_detect(ov7740);
> + if (ret)
> + goto error_detect;
> +
> + mutex_init(&ov7740->mutex);
> +
> + ret = ov7740_init_controls(ov7740);
> + if (ret)
> + goto error_init_controls;
> +
> + v4l_info(client, "chip found @ 0x%02x (%s)\n",
> + client->addr << 1, client->adapter->name);
> +
> + ov7740_init_default_format(ov7740);
This doesn't yet address the issue. The sensor will be powered off just a
few lines below, so the device state will be lost. You need to ensure the
registers get programmed after the sensor is powered on and before
streaming is started.
> +
> + ov7740_get_default_format(sd, &ov7740->format);
> +
> + ret = v4l2_async_register_subdev(sd);
> + if (ret)
> + goto error_async_register;
> +
> + pm_runtime_set_active(&client->dev);
> + pm_runtime_enable(&client->dev);
> + pm_runtime_idle(&client->dev);
> +
> + return 0;
> +
> +error_async_register:
> + v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
> +error_init_controls:
> + ov7740_free_controls(ov7740);
> +error_detect:
> + ov7740_set_power(ov7740, 0);
> + media_entity_cleanup(&ov7740->subdev.entity);
> +
> + return ret;
> +}
> +
> +static int ov7740_remove(struct i2c_client *client)
> +{
> + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> + struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +
> + mutex_destroy(&ov7740->mutex);
> + v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
> +#if defined(CONFIG_MEDIA_CONTROLLER)
> + media_entity_cleanup(&ov7740->subdev.entity);
> +#endif
> + v4l2_async_unregister_subdev(sd);
> + ov7740_free_controls(ov7740);
> +
> + pm_runtime_get_sync(&client->dev);
> + pm_runtime_disable(&client->dev);
> + pm_runtime_set_suspended(&client->dev);
> + pm_runtime_put_noidle(&client->dev);
> +
> + ov7740_set_power(ov7740, 0);
> + return 0;
> +}
> +
> +static int __maybe_unused ov7740_runtime_suspend(struct device *dev)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> + struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +
> + ov7740_set_power(ov7740, 0);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused ov7740_runtime_resume(struct device *dev)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> + struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +
> + return ov7740_set_power(ov7740, 1);
> +}
> +
> +static const struct i2c_device_id ov7740_id[] = {
> + { "ov7740", 0 },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(i2c, ov7740_id);
> +
> +static const struct dev_pm_ops ov7740_pm_ops = {
> + SET_RUNTIME_PM_OPS(ov7740_runtime_suspend, ov7740_runtime_resume, NULL)
> +};
> +
> +static const struct of_device_id ov7740_of_match[] = {
> + {.compatible = "ovti,ov7740", },
> + { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, ov7740_of_match);
> +
> +static struct i2c_driver ov7740_i2c_driver = {
> + .driver = {
> + .name = "ov7740",
> + .pm = &ov7740_pm_ops,
> + .of_match_table = of_match_ptr(ov7740_of_match),
> + },
> + .probe = ov7740_probe,
> + .remove = ov7740_remove,
> + .id_table = ov7740_id,
> +};
> +module_i2c_driver(ov7740_i2c_driver);
> +
> +MODULE_DESCRIPTION("The V4L2 driver for Omnivision 7740 sensor");
> +MODULE_AUTHOR("Songjun Wu <songjun.wu@atmel.com>");
> +MODULE_LICENSE("GPL v2");
> --
> 2.15.0
>
--
Sakari Ailus
e-mail: sakari.ailus at iki.fi
^ permalink raw reply
* [RFC PATCH 1/6] drm: Add Content Protection property
From: Daniel Vetter @ 2017-12-05 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171205102840.GB12982@amd>
On Tue, Dec 05, 2017 at 11:28:40AM +0100, Pavel Machek wrote:
> On Wed 2017-11-29 22:08:56, Sean Paul wrote:
> > This patch adds a new optional connector property to allow userspace to enable
> > protection over the content it is displaying. This will typically be implemented
> > by the driver using HDCP.
> >
> > The property is a tri-state with the following values:
> > - OFF: Self explanatory, no content protection
> > - DESIRED: Userspace requests that the driver enable protection
> > - ENABLED: Once the driver has authenticated the link, it sets this value
> >
> > The driver is responsible for downgrading ENABLED to DESIRED if the link becomes
> > unprotected. The driver should also maintain the desiredness of protection
> > across hotplug/dpms/suspend.
>
> Why would user of the machine want this to be something else than
> 'OFF'?
>
> If kernel implements this, will it mean hardware vendors will have to
> prevent user from updating kernel on machines they own?
>
> If this is merged, does it open kernel developers to DMCA threats if
> they try to change it?
Because this just implements one part of the content protection scheme.
This only gives you an option to enable HDCP (aka encryption, it's really
nothing else) on the cable. Just because it has Content Protection in the
name does _not_ mean it is (stand-alone) an effective nor complete content
protection scheme. It's simply encrypting data, that's all.
If you want to actually lock down a machine to implement content
protection, then you need secure boot without unlockable boot-loader and a
pile more bits in userspace. If you do all that, only then do you have
full content protection. And yes, then you don't really own the machine
fully, and I think users who are concerned with being able to update their
kernels and be able to exercise their software freedoms already know to
avoid such locked down systems.
So yeah it would be better to call this the "HDMI/DP cable encryption
support", but well, it's not what it's called really.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
^ permalink raw reply
* [PATCH] mtd: nand: squash struct nand_buffers into struct nand_chip
From: Masahiro Yamada @ 2017-12-05 10:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171205112815.0b59ab2d@bbrezillon>
2017-12-05 19:28 GMT+09:00 Boris Brezillon <boris.brezillon@free-electrons.com>:
> On Tue, 5 Dec 2017 19:02:26 +0900
> Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
>
>> Hi Boris,
>>
>> 2017-12-04 18:10 GMT+09:00 Boris Brezillon
>> <boris.brezillon@free-electrons.com>:
>>
>> >> }
>> >>
>> >> if (!(chip->options & NAND_OWN_BUFFERS)) {
>> >> - nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
>> >> - if (!nbuf)
>> >> + chip->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
>> >> + if (!chip->ecccalc)
>> >> return -ENOMEM;
>> >>
>> >> - nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
>> >> - if (!nbuf->ecccalc) {
>> >> + chip->ecccode = kmalloc(mtd->oobsize, GFP_KERNEL);
>> >> + if (!chip->ecccode) {
>> >> ret = -ENOMEM;
>> >> goto err_free_nbuf;
>> >> }
>> >
>> > Hm, again not directly related to this patch, but I wonder if we
>> > couldn't allocate those buffers only when they are really needed.
>> > For example, most NAND controllers do the ECC calculation/correct
>> > in HW and simply don't need those buffers.
>>
>>
>> The only idea I came up with is to add a new flag,
>> but I am not sure if you are happy with it
>> because we are removing NAND_OWN_BUFFERS.
>
> All drivers using ->calc/code_buf are providing a ->correct() and/or
> ->calculate() method, so I thought we could make the allocation
> dependent on the presence of one of these hooks [1].
>
> The only exception is the denali driver, but I think we can patch it
> to not use the ->code_buf buffer [2].
Cool!
> [1]http://code.bulix.org/2ks7yp-236649
> [2]http://code.bulix.org/sxqx7o-236650
>
Thanks!
I can issue Acked-by for [2].
--
Best Regards
Masahiro Yamada
^ permalink raw reply
* [PATCH v2 00/27] Improve DE2 support
From: Maxime Ripard @ 2017-12-05 10:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171201060550.10392-1-jernej.skrabec@siol.net>
Hi,
On Fri, Dec 01, 2017 at 07:05:23AM +0100, Jernej Skrabec wrote:
> Current DE2 driver is very basic and uses a lot of magic constants since
> there is no documentation and knowledge about it was limited at the time.
>
> With studying BSP source code, deeper knowledge was gained which allows
> to improve mainline driver considerably.
>
> At the beginning of this series, some code refactoring is done as well
> as adding some checks (patches 1-15).
>
> Further patches add multi-plane support with HW scaling and all possible
> RGB formats (patches 16-21).
>
> At last, support for YUV formats is added (patches 22-26).
>
> At the end, I included patch which puts lowest plane before second lowest.
> This should help testing VI planes when mixer has configuration 1 VI plane
> and 1 or more UI planes (most SoCs except V3s).
>
> This code was developed on H3, but it should work on every SoC if correct
> configuration structure is provided.
>
> H3 code can be found here:
> https://github.com/jernejsk/linux-1/commits/de2_impr_for_next
Thanks a lot for that huge rework.
I've applied the patches 1 to 26, and will push them to drm-misc once
the compilations are done.
In the future, if you happen to do such a huge rework again (which
hopefully won't be needed :)), please use the -M option of
format-patch. It will reduce a lot the verbosity of files renaming and
will help the review.
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171205/45d8e03c/attachment.sig>
^ permalink raw reply
* [PATCH] soc: qcom: Separate kryo l2 accessors from PMU driver
From: Mark Rutland @ 2017-12-05 10:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512455630-25119-1-git-send-email-ilialin@codeaurora.org>
Hi,
On Tue, Dec 05, 2017 at 08:33:50AM +0200, Ilia Lin wrote:
> The driver provides kernel level API for other drivers
> to access the MSM8996 L2 cache registers.
> Separating the L2 access code from the PMU driver and
> making it public to allow other drivers use it.
> The accesses must be separated with a single spinlock,
> maintained in this driver.
>
> Change-Id: I2865e888491e85d678e298279400c371427e30ea
> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
What other driver is going to use this?
Until there is another driver, I don't see much point in factoring this
out.
Thanks,
Mark.
> ---
> arch/arm64/Kconfig.platforms | 7 ++++
> drivers/perf/qcom_l2_pmu.c | 48 +--------------------------
> drivers/soc/qcom/Makefile | 1 +
> drivers/soc/qcom/kryo-l2-accessors.c | 64 ++++++++++++++++++++++++++++++++++++
> include/soc/qcom/kryo-l2-accessors.h | 27 +++++++++++++++
> 5 files changed, 100 insertions(+), 47 deletions(-)
> create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c
> create mode 100644 include/soc/qcom/kryo-l2-accessors.h
>
> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
> index 2401373..1cfed45 100644
> --- a/arch/arm64/Kconfig.platforms
> +++ b/arch/arm64/Kconfig.platforms
> @@ -138,6 +138,13 @@ config ARCH_QCOM
> help
> This enables support for the ARMv8 based Qualcomm chipsets.
>
> +config ARCH_MSM8996
> + bool "Enable Support for Qualcomm Technologies, Inc. MSM8996"
> + depends on ARCH_QCOM
> + help
> + This enables support for the MSM8996 chipset. If you do not
> + wish to build a kernel that runs on this chipset, say 'N' here.
> +
> config ARCH_REALTEK
> bool "Realtek Platforms"
> help
> diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
> index 4fdc848..ba5f241 100644
> --- a/drivers/perf/qcom_l2_pmu.c
> +++ b/drivers/perf/qcom_l2_pmu.c
> @@ -30,7 +30,7 @@
>
> #include <asm/barrier.h>
> #include <asm/local64.h>
> -#include <asm/sysreg.h>
> +#include <soc/qcom/kryo-l2-accessors.h>
>
> #define MAX_L2_CTRS 9
>
> @@ -87,9 +87,6 @@
> #define L2_COUNTER_RELOAD BIT_ULL(31)
> #define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63)
>
> -#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
> -#define L2CPUSRDR_EL1 sys_reg(3, 3, 15, 0, 7)
> -
> #define reg_idx(reg, i) (((i) * IA_L2_REG_OFFSET) + reg##_BASE)
>
> /*
> @@ -107,49 +104,6 @@
> #define L2_EVENT_STREX 0x421
> #define L2_EVENT_CLREX 0x422
>
> -static DEFINE_RAW_SPINLOCK(l2_access_lock);
> -
> -/**
> - * set_l2_indirect_reg: write value to an L2 register
> - * @reg: Address of L2 register.
> - * @value: Value to be written to register.
> - *
> - * Use architecturally required barriers for ordering between system register
> - * accesses
> - */
> -static void set_l2_indirect_reg(u64 reg, u64 val)
> -{
> - unsigned long flags;
> -
> - raw_spin_lock_irqsave(&l2_access_lock, flags);
> - write_sysreg_s(reg, L2CPUSRSELR_EL1);
> - isb();
> - write_sysreg_s(val, L2CPUSRDR_EL1);
> - isb();
> - raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> -}
> -
> -/**
> - * get_l2_indirect_reg: read an L2 register value
> - * @reg: Address of L2 register.
> - *
> - * Use architecturally required barriers for ordering between system register
> - * accesses
> - */
> -static u64 get_l2_indirect_reg(u64 reg)
> -{
> - u64 val;
> - unsigned long flags;
> -
> - raw_spin_lock_irqsave(&l2_access_lock, flags);
> - write_sysreg_s(reg, L2CPUSRSELR_EL1);
> - isb();
> - val = read_sysreg_s(L2CPUSRDR_EL1);
> - raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> -
> - return val;
> -}
> -
> struct cluster_pmu;
>
> /*
> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index 40c56f6..2bf8d93 100644
> --- a/drivers/soc/qcom/Makefile
> +++ b/drivers/soc/qcom/Makefile
> @@ -10,3 +10,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
> obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
> obj-$(CONFIG_QCOM_SMSM) += smsm.o
> obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
> +obj-$(CONFIG_ARCH_MSM8996) += kryo-l2-accessors.o
> diff --git a/drivers/soc/qcom/kryo-l2-accessors.c b/drivers/soc/qcom/kryo-l2-accessors.c
> new file mode 100644
> index 0000000..6be57e6
> --- /dev/null
> +++ b/drivers/soc/qcom/kryo-l2-accessors.c
> @@ -0,0 +1,64 @@
> +/*
> + * Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only 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.
> + */
> +
> +#include <linux/spinlock.h>
> +#include <asm/sysreg.h>
> +#include <soc/qcom/kryo-l2-accessors.h>
> +
> +#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
> +#define L2CPUSRDR_EL1 sys_reg(3, 3, 15, 0, 7)
> +
> +static DEFINE_RAW_SPINLOCK(l2_access_lock);
> +
> +/**
> + * set_l2_indirect_reg: write value to an L2 register
> + * @reg: Address of L2 register.
> + * @value: Value to be written to register.
> + *
> + * Use architecturally required barriers for ordering between system register
> + * accesses, and system registers with respect to device memory
> + */
> +void set_l2_indirect_reg(u64 reg, u64 val)
> +{
> + unsigned long flags;
> + mb();
> + raw_spin_lock_irqsave(&l2_access_lock, flags);
> + write_sysreg_s(reg, L2CPUSRSELR_EL1);
> + isb();
> + write_sysreg_s(val, L2CPUSRDR_EL1);
> + isb();
> + raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> +}
> +EXPORT_SYMBOL(set_l2_indirect_reg);
> +
> +/**
> + * get_l2_indirect_reg: read an L2 register value
> + * @reg: Address of L2 register.
> + *
> + * Use architecturally required barriers for ordering between system register
> + * accesses, and system registers with respect to device memory
> + */
> +u64 get_l2_indirect_reg(u64 reg)
> +{
> + u64 val;
> + unsigned long flags;
> +
> + raw_spin_lock_irqsave(&l2_access_lock, flags);
> + write_sysreg_s(reg, L2CPUSRSELR_EL1);
> + isb();
> + val = read_sysreg_s(L2CPUSRDR_EL1);
> + raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> +
> + return val;
> +}
> +EXPORT_SYMBOL(get_l2_indirect_reg);
> diff --git a/include/soc/qcom/kryo-l2-accessors.h b/include/soc/qcom/kryo-l2-accessors.h
> new file mode 100644
> index 0000000..2bebce1
> --- /dev/null
> +++ b/include/soc/qcom/kryo-l2-accessors.h
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only 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.
> + */
> +
> +#ifndef __ASM_ARCH_MSM_MSM_KRYO_L2_ACCESSORS_H
> +#define __ASM_ARCH_MSM_MSM_KRYO_L2_ACCESSORS_H
> +
> +#ifdef CONFIG_ARCH_QCOM
> +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> +u64 get_l2_indirect_reg(u64 reg_addr);
> +#else
> +static inline void set_l2_indirect_reg(u32 reg_addr, u32 val) {}
> +static inline u32 get_l2_indirect_reg(u32 reg_addr)
> +{
> + return 0;
> +}
> +#endif
> +#endif
> --
> 1.9.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [RFC PATCH 1/6] drm: Add Content Protection property
From: Pavel Machek @ 2017-12-05 10:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171130030907.26848-2-seanpaul@chromium.org>
On Wed 2017-11-29 22:08:56, Sean Paul wrote:
> This patch adds a new optional connector property to allow userspace to enable
> protection over the content it is displaying. This will typically be implemented
> by the driver using HDCP.
>
> The property is a tri-state with the following values:
> - OFF: Self explanatory, no content protection
> - DESIRED: Userspace requests that the driver enable protection
> - ENABLED: Once the driver has authenticated the link, it sets this value
>
> The driver is responsible for downgrading ENABLED to DESIRED if the link becomes
> unprotected. The driver should also maintain the desiredness of protection
> across hotplug/dpms/suspend.
Why would user of the machine want this to be something else than
'OFF'?
If kernel implements this, will it mean hardware vendors will have to
prevent user from updating kernel on machines they own?
If this is merged, does it open kernel developers to DMCA threats if
they try to change it?
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171205/db10c986/attachment.sig>
^ permalink raw reply
* [PATCH] mtd: nand: squash struct nand_buffers into struct nand_chip
From: Boris Brezillon @ 2017-12-05 10:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAK7LNATtk9=i3HkPrW=F1YtnM1vvEM3NtMZcPNi_0C5s_X1X1A@mail.gmail.com>
On Tue, 5 Dec 2017 19:02:26 +0900
Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
> Hi Boris,
>
> 2017-12-04 18:10 GMT+09:00 Boris Brezillon
> <boris.brezillon@free-electrons.com>:
>
> >> }
> >>
> >> if (!(chip->options & NAND_OWN_BUFFERS)) {
> >> - nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
> >> - if (!nbuf)
> >> + chip->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
> >> + if (!chip->ecccalc)
> >> return -ENOMEM;
> >>
> >> - nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
> >> - if (!nbuf->ecccalc) {
> >> + chip->ecccode = kmalloc(mtd->oobsize, GFP_KERNEL);
> >> + if (!chip->ecccode) {
> >> ret = -ENOMEM;
> >> goto err_free_nbuf;
> >> }
> >
> > Hm, again not directly related to this patch, but I wonder if we
> > couldn't allocate those buffers only when they are really needed.
> > For example, most NAND controllers do the ECC calculation/correct
> > in HW and simply don't need those buffers.
>
>
> The only idea I came up with is to add a new flag,
> but I am not sure if you are happy with it
> because we are removing NAND_OWN_BUFFERS.
All drivers using ->calc/code_buf are providing a ->correct() and/or
->calculate() method, so I thought we could make the allocation
dependent on the presence of one of these hooks [1].
The only exception is the denali driver, but I think we can patch it
to not use the ->code_buf buffer [2].
[1]http://code.bulix.org/2ks7yp-236649
[2]http://code.bulix.org/sxqx7o-236650
^ permalink raw reply
* [PATCH v8 0/6] stm32 clocksource driver rework
From: Alexandre Torgue @ 2017-12-05 10:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1f3d581f-e001-5011-829e-bf79e2f639a7@linaro.org>
On 12/05/2017 11:15 AM, Daniel Lezcano wrote:
> On 05/12/2017 11:12, Alexandre Torgue wrote:
> [ ... ]
>
>>> Benjamin Gaignard (6):
>>> ?? clocksource: timer_of: rename timer_of_exit to timer_of_cleanup
>>> ?? clocksource: stm32: convert driver to timer_of
>>> ?? clocksource: stm32: increase min delta value
>>> ?? clocksource: stm32: only use 32 bits timers
>>> ?? clocksource: stm32: add clocksource support
>>> ?? arm: dts: stm32: remove useless clocksource nodes
>>>
>>> ? arch/arm/boot/dts/stm32f429.dtsi? |? 32 -----
>>> ? arch/arm/boot/dts/stm32f746.dtsi? |? 32 -----
>>> ? drivers/clocksource/Kconfig?????? |?? 1 +
>>> ? drivers/clocksource/timer-of.c??? |?? 9 +-
>>> ? drivers/clocksource/timer-of.h??? |?? 2 +-
>>> ? drivers/clocksource/timer-stm32.c | 242
>>> ++++++++++++++++++++------------------
>>> ? 6 files changed, 138 insertions(+), 180 deletions(-)
>>>
>>
>> What is the status of this patch-set ? Is there a chance to have it for
>> v4.16 ?
>
> I will take care of reviewing them this week. It is in my todo list.
>
>
Thanks Daniel
^ permalink raw reply
* [PATCH v8 0/6] stm32 clocksource driver rework
From: Daniel Lezcano @ 2017-12-05 10:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <dcff2fd0-58ca-51bb-ea2d-dfd1c5ca0cc3@st.com>
On 05/12/2017 11:12, Alexandre Torgue wrote:
[ ... ]
>> Benjamin Gaignard (6):
>> ?? clocksource: timer_of: rename timer_of_exit to timer_of_cleanup
>> ?? clocksource: stm32: convert driver to timer_of
>> ?? clocksource: stm32: increase min delta value
>> ?? clocksource: stm32: only use 32 bits timers
>> ?? clocksource: stm32: add clocksource support
>> ?? arm: dts: stm32: remove useless clocksource nodes
>>
>> ? arch/arm/boot/dts/stm32f429.dtsi? |? 32 -----
>> ? arch/arm/boot/dts/stm32f746.dtsi? |? 32 -----
>> ? drivers/clocksource/Kconfig?????? |?? 1 +
>> ? drivers/clocksource/timer-of.c??? |?? 9 +-
>> ? drivers/clocksource/timer-of.h??? |?? 2 +-
>> ? drivers/clocksource/timer-stm32.c | 242
>> ++++++++++++++++++++------------------
>> ? 6 files changed, 138 insertions(+), 180 deletions(-)
>>
>
> What is the status of this patch-set ? Is there a chance to have it for
> v4.16 ?
I will take care of reviewing them this week. It is in my todo list.
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH 4/7 v2] net: ethernet: i825xx: Fix platform_get_irq's error checking
From: Sergei Shtylyov @ 2017-12-05 10:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171204.132556.1601454745789376393.davem@davemloft.net>
On 12/4/2017 9:25 PM, David Miller wrote:
>> @@ -120,9 +120,10 @@ static int sni_82596_probe(struct platform_device *dev)
>> netdevice->dev_addr[5] = readb(eth_addr + 0x06);
>> iounmap(eth_addr);
>>
>> - if (!netdevice->irq) {
>> + if (netdevice->irq <= 0) {
>> printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
>> __FILE__, netdevice->base_addr);
>> + retval = netdevice->irq ? netdevice->irq : -ENODEV;
>> goto probe_failed;
>> }
>
> Ok, thinking about this some more...
>
> It is impossible to use platform_get_irq() without every single call
> site having this funny:
>
> ret = val ? val : -ENODEV;
>
> sequence.
>
> This is unnecessary duplication and it is also error prone, so I
> really think this logic belongs in platform_get_irq() itself. It can
> convert '0' to -ENODEV and that way we need no special logic in the
> callers at all.
Well, we can have:
return r && r->start ? r->start : -ENXIO;
instead of:
return r ? r->start : -ENXIO;
at the end of platform_get_irq(). But I don't really think it's worth doing --
request_irq() doesn't filter out IRQ0 anyway, IIRC...
MBR, Sergei
^ permalink raw reply
* [PATCH v8 0/6] stm32 clocksource driver rework
From: Alexandre Torgue @ 2017-12-05 10:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1510649563-22975-1-git-send-email-benjamin.gaignard@linaro.org>
Hi
On 11/14/2017 09:52 AM, Benjamin Gaignard wrote:
> version 8:
> - rebased on timers/core
> - change timer_of_exit() name to timer_of_cleanup()
> - update stm32 clocksource driver to use this function
>
> version 7:
> - reword "clocksource: stm32: only use 32 bits timers" commit message
> to give more details about why 16 bits are problematics.
>
> version 6:
> - add dedicated patch min delta change
> - rework commit messages, I hope it will be better now
> - change new function name from timer_of_deinit to timer_of_exit
> - make stm32_clock_event_set_next_event() safer like done in other
> drivers
>
> version 6:
> - add timer_of_deinit function in core
> - rework failure cases in probe function
>
> version 5:
> - rebase on top of timer/core branch
> - rework commit message of the first patch
>
> version 4:
> - split patch in 3 parts
> - convert code to timer_of
> - only use 32 bits timers
> - add clocksource support
>
> version 3:
> - fix comments done by Daniel
> - use timer_of helper functions
>
> version 2:
> - fix uninitialized variable
>
> Benjamin Gaignard (6):
> clocksource: timer_of: rename timer_of_exit to timer_of_cleanup
> clocksource: stm32: convert driver to timer_of
> clocksource: stm32: increase min delta value
> clocksource: stm32: only use 32 bits timers
> clocksource: stm32: add clocksource support
> arm: dts: stm32: remove useless clocksource nodes
>
> arch/arm/boot/dts/stm32f429.dtsi | 32 -----
> arch/arm/boot/dts/stm32f746.dtsi | 32 -----
> drivers/clocksource/Kconfig | 1 +
> drivers/clocksource/timer-of.c | 9 +-
> drivers/clocksource/timer-of.h | 2 +-
> drivers/clocksource/timer-stm32.c | 242 ++++++++++++++++++++------------------
> 6 files changed, 138 insertions(+), 180 deletions(-)
>
What is the status of this patch-set ? Is there a chance to have it for
v4.16 ?
Thanks
Alex
^ permalink raw reply
* [PATCH] ASoC: atmel-classd: select correct Kconfig symbol
From: Arnd Bergmann @ 2017-12-05 10:09 UTC (permalink / raw)
To: linux-arm-kernel
Commit 061981ff8cc8 ("ASoC: atmel: properly select dma driver state")
changed the way that the dependencies are handled, but then the
Class D amplifier support got merged, which used the old method.
This seems to have triggered a very rare randconfig condition for me
now, leading to a link error:
sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_set_audio':
atmel_ssc_dai.c:(.text+0x79c): undefined reference to `atmel_pcm_dma_platform_register'
atmel_ssc_dai.c:(.text+0x79c): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `atmel_pcm_dma_platform_register'
sound/soc/atmel/atmel_ssc_dai.o: In function `atmel_ssc_put_audio':
atmel_ssc_dai.c:(.text+0xf24): undefined reference to `atmel_pcm_dma_platform_unregister'
atmel_ssc_dai.c:(.text+0xf24): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `atmel_pcm_dma_platform_unregister'
Changing it to select SND_ATMEL_SOC_SSC_DMA as intended rather than
SND_ATMEL_SOC_DMA directly makes it work again.
Fixes: e0a25b6d1862 ("ASoC: atmel-classd: add the Audio Class D Amplifier")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
sound/soc/atmel/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 4a56f3dfba51..2d998e5c4fb5 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -64,7 +64,7 @@ config SND_AT91_SOC_SAM9X5_WM8731
config SND_ATMEL_SOC_CLASSD
tristate "Atmel ASoC driver for boards using CLASSD"
depends on ARCH_AT91 || COMPILE_TEST
- select SND_ATMEL_SOC_DMA
+ select SND_ATMEL_SOC_SSC_DMA
select REGMAP_MMIO
help
Say Y if you want to add support for Atmel ASoC driver for boards using
--
2.9.0
^ permalink raw reply related
* [PATCH] arm64: dts: allwinner: a64: bananapi-m64: Add LED device node
From: Maxime Ripard @ 2017-12-05 10:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171201162733.23156-1-wens@csie.org>
Hi,
On Sat, Dec 02, 2017 at 12:27:33AM +0800, Chen-Yu Tsai wrote:
> The Bananapi-M64 has 3 LEDS in red, green, and blue. These are toggled
> via GPIO lines, which drive transistors that control current across the
> LEDS. The red LED is by default on, via an additional pull-up on the
> control line. We consider this means that it is a power indicator.
> So we set the "default-on" property for it.
>
> The pingroups the GPIO lines belong to require external regulators be
> enabled to be able to drive the GPIO high. These regulators also have
> other purposes. However the pin controller does not have bindings for
> regulators. Here we just set them to always-on.
I guess we should take the opportunity to do just that.
We have been deferring this for quite some time now, this is a perfect
occasion to do it once and for all :)
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171205/67860803/attachment.sig>
^ permalink raw reply
* [PATCH v2] ARM: dts: sun8i: h3: Add dts file for Libre Computer Board ALL-H3-CC H3 ver.
From: Maxime Ripard @ 2017-12-05 10:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171205060615.14349-1-wens@csie.org>
On Tue, Dec 05, 2017 at 02:06:15PM +0800, Chen-Yu Tsai wrote:
> The Libre Computer Board ALL-H3-CC from Libre Technology is a Raspberry
> Pi B+ form factor single board computer based on the Allwinner H3 SoC.
> The board has 1GB DDR3 SDRAM, provided by 4 2Gb chips. The mounting holes
> and connectors are in the exact same position as on the Raspberry Pi B+.
>
> Raspberry Pi B+ like peripherals supported on this board include:
>
> - Power input through micro-USB connector (without USB OTG)
> - Native 100 Mbps ethernet using the internal PHY, as opposed to
> USB-based on the RPi
> - 4x USB 2.0 host ports, directly connected to the SoC, as opposed to
> being connected through a USB 2.0 hub on the RPi
> - TV and audio output on a 3.5mm TRRS jack
> - HDMI output
> - Micro-SD card slot
> - Standard RPi B+ GPIO header, with the standard peripherals routed to
> the same pins.
>
> * 5V, 3.3V power, and ground
> * I2C0 on the H3 is routed to I2C1 pins on the RPi header
> * I2C1 on the H3 is routed to I2C0 pins on the RPi header
> * UART1 on the H3 is routed to UART0 pins on the RPi header
> * SPI0 on the H3 is routed to SPI0 pins on the RPi header,
> with GPIO pin PA17 replacing the missing Chip Select 1
> * I2S1 on the H3 is routed to PCM pins on the RPi header
>
> - Additional peripherals from the H3 are available on different pins.
> These include I2S0, JTAG, PWM1, SPDIF, SPI1, and UART3
>
> In addition, there are a number of new features:
>
> - Console UART header
> - Consumer IR receiver
> - Camera interface (not compatible with RPi)
> - Onboard microphone
> - eMMC expansion module port
> - Heatsink mounting holes
> - Power button
>
> The power button requires corresponding software for the embedded
> coprocessor to properly function.
>
> This patch adds a dts file for this board that enables all "onboard"
> peripherals currently supported. This means no display or camera
> support.
>
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Applied, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171205/01552a93/attachment.sig>
^ permalink raw reply
* [PATCH] mtd: nand: squash struct nand_buffers into struct nand_chip
From: Masahiro Yamada @ 2017-12-05 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171204101043.602ff213@bbrezillon>
Hi Boris,
2017-12-04 18:10 GMT+09:00 Boris Brezillon <boris.brezillon@free-electrons.com>:
>> }
>>
>> if (!(chip->options & NAND_OWN_BUFFERS)) {
>> - nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
>> - if (!nbuf)
>> + chip->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
>> + if (!chip->ecccalc)
>> return -ENOMEM;
>>
>> - nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
>> - if (!nbuf->ecccalc) {
>> + chip->ecccode = kmalloc(mtd->oobsize, GFP_KERNEL);
>> + if (!chip->ecccode) {
>> ret = -ENOMEM;
>> goto err_free_nbuf;
>> }
>
> Hm, again not directly related to this patch, but I wonder if we
> couldn't allocate those buffers only when they are really needed. For
> example, most NAND controllers do the ECC calculation/correct in HW and
> simply don't need those buffers.
The only idea I came up with is to add a new flag,
but I am not sure if you are happy with it
because we are removing NAND_OWN_BUFFERS.
--
Best Regards
Masahiro Yamada
^ permalink raw reply
* [PATCH 0/7 v2] net: Fix platform_get_irq's error checking
From: Arvind Yadav @ 2017-12-05 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <dc7589c8-33d8-44ba-c6e1-b7a67649709c@cogentembedded.com>
Hi Sergei,
On Tuesday 05 December 2017 03:27 PM, Sergei Shtylyov wrote:
> On 12/5/2017 12:54 PM, Sergei Shtylyov wrote:
>
>>> The platform_get_irq() function returns negative number if an error
>>> occurs, Zero if No irq is found and positive number if irq gets
>>> successful.
>>
>> No, returning 0 is not a failure indication anymore! It used to
>> be but not any longer...
>
> And I fixed this function exactly to avoid overly complex error
> checks (which you're trying to propose here).
>
Thanks for your comment. yes you are right. Now It'll not return 0. It
will return irq and error as negative.
I will not add a check for 0.
>>> platform_get_irq() error checking for only zero is not correct.
>>
>> [...]
>
> MBR, Sergei
Thank you,
~arvind
^ permalink raw reply
* [RFC v3 PATCH 2/2] arm64/efi: Introduce Security Version to ARM64
From: Gary Lin @ 2017-12-05 10:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171205100148.5757-1-glin@suse.com>
This commit introduces Security Version for ARM64. As in x86, it
utilizes the resource section defined in the PE/COFF format(*) to locate
the struct of Security Version.
Similar to the debug table, the resource table is stored in .init.rodata
section while the struct of Security Version is in the 4K padding area of
the EFI header.
(*) PE Format: The .rsrc Section
https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms680547(v=vs.85).aspx#the_.rsrc_section
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Joey Lee <jlee@suse.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
| 57 ++++++++++++++++++++++++++++++++++++++++++
drivers/firmware/efi/Kconfig | 6 ++---
2 files changed, 60 insertions(+), 3 deletions(-)
--git a/arch/arm64/kernel/efi-header.S b/arch/arm64/kernel/efi-header.S
index 613fc3000677..f4404db6ca5c 100644
--- a/arch/arm64/kernel/efi-header.S
+++ b/arch/arm64/kernel/efi-header.S
@@ -61,7 +61,12 @@ extra_header_fields:
.quad 0 // ExportTable
.quad 0 // ImportTable
+#ifdef CONFIG_SECURITY_VERSION_SUPPORT
+ .long rsrc_table - _head // ResourceTable
+ .long rsrc_table_size
+#else
.quad 0 // ResourceTable
+#endif
.quad 0 // ExceptionTable
.quad 0 // CertificationTable
.quad 0 // BaseRelocationTable
@@ -103,6 +108,58 @@ section_table:
.set section_count, (. - section_table) / 40
+#ifdef CONFIG_SECURITY_VERSION_SUPPORT
+ /*
+ * Resource Table
+ */
+ __INITRODATA
+
+ .align 2
+rsrc_table:
+ // Resource Directory
+ .long 0 // Characteristics
+ .long 0 // TimeDateStamp
+ .short 0 // MajorVersion
+ .short 0 // MinorVersion
+ .short 1 // NumberOfNamedEntries
+ .short 0 // NumberOfIdEntries
+
+ // Resource Directory Entry
+ .long name_offset | 0x80000000 // NameOffset:31
+ // NameIsString:1
+ .long rsrc_data_entry - rsrc_table // OffsetToData
+
+ .set name_offset, . - rsrc_table
+ // Resource Directory String
+ .short 7 // Length
+ .short 0x4C00 // 'L'
+ .short 0x6900 // 'i'
+ .short 0x6E00 // 'n'
+ .short 0x7500 // 'u'
+ .short 0x7800 // 'x'
+ .short 0x5300 // 'S'
+ .short 0x5600 // 'V'
+
+ // Resource Data Entry
+rsrc_data_entry:
+ .long svdata_begin - _head // OffsetToData
+ .long svdata_end - svdata_begin // Size
+ .long 0 // CodePage
+ .long 0 // Reserved
+
+ .set rsrc_table_size, . - rsrc_table
+ .previous
+
+ // Security Version
+svdata_begin:
+ .short sv_signer - svdata_begin
+ .short CONFIG_SECURITY_VERSION
+ .long CONFIG_DISTRO_VERSION
+sv_signer:
+ .string CONFIG_SIGNER_NAME
+svdata_end:
+#endif
+
#ifdef CONFIG_DEBUG_EFI
/*
* The debug table is referenced via its Relative Virtual Address (RVA),
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 1dd82f1dd094..3cad8d63897e 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -179,14 +179,14 @@ menuconfig SECURITY_VERSION_SUPPORT
config SIGNER_NAME
string "Signer Name" if SECURITY_VERSION_SUPPORT
- depends on EFI && X86
+ depends on EFI && (X86 || ARM64)
default ""
help
This option specifies who signs or releases this kernel.
config DISTRO_VERSION
int "Distribution Version" if SECURITY_VERSION_SUPPORT
- depends on EFI && X86
+ depends on EFI && (X86 || ARM64)
default 0
range 0 4294967295
help
@@ -195,7 +195,7 @@ config DISTRO_VERSION
config SECURITY_VERSION
int "Security Version" if SECURITY_VERSION_SUPPORT
- depends on EFI && X86
+ depends on EFI && (X86 || ARM64)
default 0
range 0 65535
help
--
2.15.0
^ permalink raw reply related
* [RFC v3 PATCH 1/2] x86/efi: Introduce Security Version to x86
From: Gary Lin @ 2017-12-05 10:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171205100148.5757-1-glin@suse.com>
Security Version is a mechanism based on UEFI Secure Boot to keep the
user from loading an insecure kernel accidentally. It's a monotonically
increasing number representing how "secure" the kernel is. The distro
kernel maintainer has to specify the distro name (signer) and the distro
version to distinguish the distro kernel among other kernel images. When
a critical vulnerability is fixed, the maintainer bumps Security Version,
and the bootloader (e.g. shim) records the Security Version in a UEFI
BootService variable. If the user tries to load a kernel with a lower
Security Version, the bootloader shows a warning prompt, and the user
decides whether to boot the kernel or not.
For the better portability, Security Version utilizes the resource
section(*) of PE/COFF to locate the struct of Security Version. The
resource section is a read-only section to index data in a binary-sorted
tree structure. The Windows images stores the resource data in a three
levels struture. For simplicity, we only use one level for Security
Version. A directory called "LinuxSV" is created and it contains the
offset to the struct of Security Version. The bootloader just follows
the resource table to fetch the details.
The struct of Security Version can be presented as the following:
struct sv_hdr {
__u16 header_length;
__u16 security_version;
__u32 distro_version;
} __attribute__((packed));
char *signer;
It consists of a fixed size structure and a null-terminated string.
"header_length" is the size of "struct sv_hdr". It's also used as a
kind of the "header version" in case a new member is introduced later.
(*) PE Format: The .rsrc Section
https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms680547(v=vs.85).aspx#the_.rsrc_section
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Joey Lee <jlee@suse.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
| 55 ++++++++++++++++++++++++++++++++++++++++++++
drivers/firmware/efi/Kconfig | 40 ++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+)
--git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 850b8762e889..dc1b80b29478 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -188,7 +188,12 @@ extra_header_fields:
.quad 0 # ExportTable
.quad 0 # ImportTable
+#ifdef CONFIG_SECURITY_VERSION_SUPPORT
+ .long rsrc_table # ResourceTable
+ .long rsrc_table_size
+#else
.quad 0 # ResourceTable
+#endif
.quad 0 # ExceptionTable
.quad 0 # CertificationTable
.quad 0 # BaseRelocationTable
@@ -634,3 +639,53 @@ die:
setup_corrupt:
.byte 7
.string "No setup signature found...\n"
+
+#ifdef CONFIG_SECURITY_VERSION_SUPPORT
+# Resource Table
+ .section ".rodata", "a", @progbits
+ .align 2
+rsrc_table:
+ # Resource Directory
+ .long 0 # Characteristics
+ .long 0 # TimeDateStamp
+ .short 0 # MajorVersion
+ .short 0 # MinorVersion
+ .short 1 # NumberOfNamedEntries
+ .short 0 # NumberOfIdEntries
+
+ # Resource Directory Entry
+ .long name_offset | 0x80000000 # NameOffset:31
+ # NameIsString:1
+ .long rsrc_data_entry - rsrc_table # OffsetToData
+
+ .set name_offset, . - rsrc_table
+ # Resource Directory String
+ .short 7 # Length
+ .short 0x4C00 # 'L'
+ .short 0x6900 # 'i'
+ .short 0x6E00 # 'n'
+ .short 0x7500 # 'u'
+ .short 0x7800 # 'x'
+ .short 0x5300 # 'S'
+ .short 0x5600 # 'V'
+
+ .set svdata_entry_offset, . - rsrc_table
+ # Resource Data Entry
+rsrc_data_entry:
+ .long svdata_begin # OffsetToData
+ .long svdata_end - svdata_begin # Size
+ .long 0 # CodePage
+ .long 0 # Reserved
+
+ .set rsrc_table_size, . - rsrc_table
+
+ # Security Version
+svdata_begin:
+ .short sv_signer - svdata_begin
+ .short CONFIG_SECURITY_VERSION
+ .long CONFIG_DISTRO_VERSION
+sv_signer:
+ .string CONFIG_SIGNER_NAME
+svdata_end:
+
+#endif /* CONFIG_SECURITY_VERSION_SUPPORT */
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 2b4c39fdfa91..1dd82f1dd094 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -161,6 +161,46 @@ config RESET_ATTACK_MITIGATION
still contains secrets in RAM, booting another OS and extracting the
secrets.
+menuconfig SECURITY_VERSION_SUPPORT
+ bool "Security Version Support" if EFI_STUB
+ help
+ The security version is the number defined by the distribution
+ to indicate the critical security fixes. The bootloader could
+ maintain a list of the security versions of the current kernels.
+ After fixing a severe vulnerability in the kernel, the distribution
+ bumps the security version to notify the bootloader to update
+ the list. If the user tries to load a kernel with a smaller security
+ version, the bootloadr could show a warning to the user to avoid
+ a vulnerable kernel from being loaded accidentally.
+
+ This is mainly designed for the distribution kernel maintainer.
+ Say N if you don't know what it is.
+
+
+config SIGNER_NAME
+ string "Signer Name" if SECURITY_VERSION_SUPPORT
+ depends on EFI && X86
+ default ""
+ help
+ This option specifies who signs or releases this kernel.
+
+config DISTRO_VERSION
+ int "Distribution Version" if SECURITY_VERSION_SUPPORT
+ depends on EFI && X86
+ default 0
+ range 0 4294967295
+ help
+ This option specifies the distribution version which this
+ kernel belongs to.
+
+config SECURITY_VERSION
+ int "Security Version" if SECURITY_VERSION_SUPPORT
+ depends on EFI && X86
+ default 0
+ range 0 65535
+ help
+ This option specifies the security version of this kernel.
+
endmenu
config UEFI_CPER
--
2.15.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox