Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/2] clocksource: arm_arch_timer: Don't assume clock runs in suspend
From: Daniel Lezcano @ 2016-10-13 12:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475604730-140264-1-git-send-email-briannorris@chromium.org>

On 04/10/2016 20:12, Brian Norris wrote:
> The ARM ARM specifies that the system counter "must be implemented in an
> always-on power domain," and so we try to use the counter as a source of
> timekeeping across suspend/resume. Unfortunately, some SoCs (e.g.,
> Rockchip's RK3399) do not keep the counter ticking properly when
> switched from their high-power clock to the lower-power clock used in
> system suspend. Support this quirk by adding a new device tree property.
> 
> Signed-off-by: Brian Norris <briannorris@chromium.org>
> ---

Both patches applied for 4.10.

Thanks !

  -- Daniel

-- 
 <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 RESEND] ARM: dts: keystone-k2*: Increase SPI Flash partition size for U-Boot
From: Vignesh R @ 2016-10-13 12:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161012115703.GE1041@n2100.armlinux.org.uk>



On Wednesday 12 October 2016 05:27 PM, Russell King - ARM Linux wrote:
> On Wed, Oct 12, 2016 at 04:30:28PM +0530, Vignesh R wrote:
[...]
>>>
>>> - What is this "misc" partition?
>>>
>>
>> This partition seems to exists from the very beginning.  I believe, this
>> is just a spare area of flash that can be used as per end-user
>> requirement. Either to store a small filesystem or kernel. Copying
>> Murali who added above partition if he has any input here.
>>
>>> - Why is it safe to move the "misc" partition in this way?
>>>
>>> - Do users need to do anything with data stored in the "misc" partition
>>>   when changing kernels?
>>>
>>
>> MTD layer will take care of most abstractions (like start address etc).
>> Will add a note in commit message informing about the reduction in size
>> of the partition.
>>
>>> If the "misc" partition is simply unused space on the flash device, why
>>> list it in DT?
>>>
>>
>> If the unused space is not listed in the DT, then there is no /dev/mtdX
>> node created for the unused section. User will then have to manually
>> edit DT, in order to get the node and mount it. Instead, lets make it
>> available by default.
> 
> So, taken all together, your argument is:
> 
> - We want a user partition
> - It's okay to destroy the data in the user's partition by moving it
>   around randomly between kernel versions.
> 
> The two do not naturally go together at all.  You're messing with user
> expectations in ways you should not be.  This really is not an acceptable
> approach.
> 

Ok, I understand that if the user just updates to new kernel(w/o
updating bootloader) then this patch will end up setting "misc"
partition at wrong offset. At this point, I don't see how to provide a
way to upgrade boot loader at the same time support old and new layouts
simultaneously.
Could you please suggest an alternative approach that would enable users
to update U-Boot partition?
If not, then I guess, will have to drop this patch. Note that, this
means there won't be a straight forward way of updating SPI U-Boot
partition from kernel for K2 devices.

-- 
Regards
Vignesh

^ permalink raw reply

* [PATCH 2/2] power/reset: at91-poweroff: timely shitdown LPDDR memories
From: Alexandre Belloni @ 2016-10-13 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACh+v5NCxPb_U8HOeczHicCD-Wp8BqBzvc1LtCzmEXZ74Cgshw@mail.gmail.com>

On 12/10/2016 at 14:48:27 +0200, Jean-Jacques Hiblot wrote :
> > +static void at91_lpddr_poweroff(void)
> > +{
> > +       asm volatile(
> > +               /* Align to cache lines */
> > +               ".balign 32\n\t"
> > +
> > +               "       ldr     r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
> At first sight, it looks useless. I assume it's used to preload the
> TLB before the LPDDR is turned off.
> A comment to explain why this line is useful would prevent its removal.

Yes, this is the case. I can add a comment.

Anyway, I would prefer the whole thing to run from SRAM, as a PIE
instead of relying on the cache.

> > +       ddr_type = readl(mpddrc_base + AT91_DDRSDRC_MDR) & AT91_DDRSDRC_MD;
> > +       if ((ddr_type == AT91_DDRSDRC_MD_LPDDR2) ||
> > +           (ddr_type == AT91_DDRSDRC_MD_LPDDR3))
> Souldn't there be something like "pm_power_off = at91_lpddr_poweroff;" here ?
> 

Indeed


-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [RFC] arm64: Enforce observed order for spinlock and data
From: Will Deacon @ 2016-10-13 11:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <781b6bb229ed566e1b948bfcea18bb61@codeaurora.org>

Brent,

On Wed, Oct 12, 2016 at 04:01:06PM -0400, bdegraaf at codeaurora.org wrote:
> I am still working through some additional analyses for mixed accesses,
> but I thought I'd send along some sample commit text for the fix as it
> currently stands.  Please feel free to comment if you see something that
> needs clarification.

Everything from this point down needs clarification.

> All arm64 lockref accesses that occur without taking the spinlock must
> behave like true atomics, ensuring successive operations are all done
> sequentially.

What is a "true atomic"? What do you mean by "successive"? What do you
mean by "done sequentially"?

The guarantee provided by lockref is that, if you hold the spinlock, then
you don't need to use atomics to inspect the reference count, as it is
guaranteed to be stable. You can't just go around replacing spin_lock
calls with lockref_get -- that's not what this is about.

> Currently
> the lockref accesses, when decompiled, look like the following sequence:
> 
>                     <Lockref "unlocked" Access [A]>
> 
>                     // Lockref "unlocked" (B)
>                 1:  ldxr   x0, [B]         // Exclusive load
>                      <change lock_count B>
>                     stxr   w1, x0, [B]
>                     cbnz   w1, 1b
> 
>                      <Lockref "unlocked" Access [C]>
> 
> Even though access to the lock_count is protected by exclusives, this is not
> enough
> to guarantee order: The lock_count must change atomically, in order, so the
> only
> permitted ordering would be:
>                               A -> B -> C

Says who? Please point me at a piece of code that relies on this. I'm
willing to believe that are bugs in this area, but waving your hands around
and saying certain properties "must" hold is not helpful unless you can
say *why* they must hold and *where* that is required.

> Unfortunately, this is not the case by the letter of the architecture and,
> in fact,
> the accesses to A and C are not protected by any sort of barrier, and hence
> are
> permitted to reorder freely, resulting in orderings such as
> 
>                            Bl -> A -> C -> Bs

Again, why is this a problem? It's exactly the same as if you did:

	spin_lock(lock);
	inc_ref_cnt();
	spin_unlock(lock);

Accesses outside of the critical section can still be reordered. Big deal.

> In this specific scenario, since "change lock_count" could be an
> increment, a decrement or even a set to a specific value, there could be
> trouble. 

What trouble?

> With more agents accessing the lockref without taking the lock, even
> scenarios where the cmpxchg passes falsely can be encountered, as there is
> no guarantee that the the "old" value will not match exactly a newer value
> due to out-of-order access by a combination of agents that increment and
> decrement the lock_count by the same amount.

This is the A-B-A problem, but I don't see why it affects us here. We're
dealing with a single reference count.

> Since multiple agents are accessing this without locking the spinlock,
> this access must have the same protections in place as atomics do in the
> arch's atomic.h.

Why? I don't think that it does. Have a look at how lockref is used by
the dcache code: it's really about keeping a reference to a dentry,
which may be in the process of being unhashed and removed. The
interaction with concurrent updaters to the dentry itself is handled
using a seqlock, which does have the necessary barriers. Yes, the code
is extremely complicated, but given that you're reporting issues based
on code inspection, then you'll need to understand what you're changing.

> Fortunately, the fix is not complicated: merely removing the errant
> _relaxed option on the cmpxchg64 is enough to introduce exactly the same
> code sequence justified in commit 8e86f0b409a44193f1587e87b69c5dcf8f65be67
> to fix arm64 atomics.

I introduced cmpxchg64_relaxed precisely for the lockref case. I still
don't see a compelling reason to strengthen it. If you think there's a bug,
please spend the effort to describe how it manifests and what can actually
go wrong in the existing codebase. Your previous patches fixing so-called
bugs found by inspection have both turned out to be bogus, so I'm sorry,
but I'm not exactly leaping on your contributions to this.

Will

^ permalink raw reply

* [PATCH V3 08/10] ras: acpi / apei: generate trace event for unrecognized CPER section
From: Punit Agrawal @ 2016-10-13 10:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475875882-2604-9-git-send-email-tbaicar@codeaurora.org>

Hi Tyler,

One last comment...

Tyler Baicar <tbaicar@codeaurora.org> writes:

> UEFI spec allows for non-standard section in Common Platform Error
> Record. This is defined in section N.2.3 of UEFI version 2.5.
>
> Currently if the CPER section's type (UUID) does not match with
> any section type that the kernel knows how to parse, trace event
> is not generated for such section. And thus user is not able to know
> happening of such hardware error, including error record of
> non-standard section.
>
> This commit generates a trace event which contains raw error data
> for unrecognized CPER section.
>
> Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
> Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
> ---
>  drivers/acpi/apei/ghes.c | 18 +++++++++++++++++-
>  drivers/ras/ras.c        |  1 +
>  include/ras/ras_event.h  | 45 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 63 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
> index 36894c8..cb4c7f4 100644
> --- a/drivers/acpi/apei/ghes.c
> +++ b/drivers/acpi/apei/ghes.c
> @@ -49,6 +49,7 @@
>  #include <acpi/ghes.h>
>  #include <acpi/apei.h>
>  #include <asm/tlbflush.h>
> +#include <ras/ras_event.h>
>  
>  #ifdef CONFIG_HAVE_ACPI_APEI_SEA
>  #include <asm/system_misc.h>
> @@ -468,12 +469,21 @@ static void ghes_do_proc(struct ghes *ghes,
>  	int sev, sec_sev;
>  	struct acpi_hest_generic_data *gdata;
>  	uuid_le sec_type;
> +	uuid_le *fru_id;
> +	char *fru_text = "";
>  
>  	sev = ghes_severity(estatus->error_severity);
>  	apei_estatus_for_each_section(estatus, gdata) {
>  		sec_sev = ghes_severity(gdata->error_severity);
>  		sec_type = *(uuid_le *)gdata->section_type;
>  
> +		if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
> +			fru_id = (uuid_le *)gdata->fru_id;
> +		else
> +			fru_id = &NULL_UUID_LE;

fru_id can be initialised at declaration and drop the else here. The
same is already being done for fru_text.

Thanks,
Punit

> +		if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
> +			fru_text = gdata->fru_text;
> +
>  		if (!uuid_le_cmp(sec_type,
>  				 CPER_SEC_PLATFORM_MEM)) {
>  			struct cper_sec_mem_err *mem_err;

[...]

^ permalink raw reply

* [PATCH] perf: xgene: Remove bogus IS_ERR() check
From: Mark Rutland @ 2016-10-13 10:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476290367-8092-1-git-send-email-ttnguyen@apm.com>

On Wed, Oct 12, 2016 at 09:39:27AM -0700, Tai Nguyen wrote:
> This patch fixes the warning issue with static checker.
> The bug is reported in [1]
> 
> [1] https://www.spinics.net/lists/arm-kernel/msg535957.html
> 
> Signed-off-by: Tai Nguyen <ttnguyen@apm.com>

Please put the problem description in the commit message:

  In acpi_get_pmu_hw_inf we pass the address of a local variable to IS_ERR(),
  which doesn't make sense, as the pointer must be a real, valid pointer. This
  doesn't cause a functional problem, as IS_ERR() will evaluate as false, but
  the check is bogus and causes static checkers to complain.

  Remove the bogus check.

Please also add a Reported-by for Dan.

The patch itself is fine, so with the above, you can add:

Acked-by: Mark Rutland <mark.rutland@arm.com>

Please Cc Will Deacon when sending that, I expect that he will pick it up
(though perhaps not until rc1 given this is not a critical issue).

Thanks,
Mark.

> ---
>  drivers/perf/xgene_pmu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/perf/xgene_pmu.c b/drivers/perf/xgene_pmu.c
> index c2ac764..a8ac4bc 100644
> --- a/drivers/perf/xgene_pmu.c
> +++ b/drivers/perf/xgene_pmu.c
> @@ -1011,7 +1011,7 @@ xgene_pmu_dev_ctx *acpi_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
>  	rc = acpi_dev_get_resources(adev, &resource_list,
>  				    acpi_pmu_dev_add_resource, &res);
>  	acpi_dev_free_resource_list(&resource_list);
> -	if (rc < 0 || IS_ERR(&res)) {
> +	if (rc < 0) {
>  		dev_err(dev, "PMU type %d: No resource address found\n", type);
>  		goto err;
>  	}
> -- 
> 1.9.1
> 

^ permalink raw reply

* [PATCH 3/4] arm64: Allow hw watchpoint of length 3,5,6 and 7
From: Pratyush Anand @ 2016-10-13 10:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAH=s-PNFESLA6TTem-49g0CKsjpKOsj1XYfPUXz6YbEfMWXqXg@mail.gmail.com>



On Wednesday 12 October 2016 04:46 PM, Yao Qi wrote:
> On Wed, Oct 12, 2016 at 6:58 AM, Pratyush Anand <panand@redhat.com> wrote:
>> Since, arm64 can support all offset within a double word limit. Therefore,
>> now support other lengths within that range as well.
>
> How does ptracer (like GDB) detect kernel has already supported all byte
> address select values?  I suppose ptrace(NT_ARM_HW_WATCH, ) with
> len is 3 or 5 fail on current kernel but is of success after your patches
> applied.
>

Thanks for testing these patches.

I do not know if we can know that other than the failure of 
ptrace(PTRACE_SETREGSET, .., NT_ARM_HW_WATCH, ..). I do not see any such 
option in `man ptrace`.


> GDB is aware of the byte address select limitation in kernel, so it always
> sets 1,2,4,8 in len in ctrl.  GDB needs to know whether the limitation is still
> there or not.
>

Not sure if other than "kernel version" anything will help here.

~Pratyush

^ permalink raw reply

* [PATCH v2 1/2] clocksource: arm_arch_timer: Don't assume clock runs in suspend
From: Marc Zyngier @ 2016-10-13 10:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475604730-140264-1-git-send-email-briannorris@chromium.org>

On Tue,  4 Oct 2016 11:12:09 -0700
Brian Norris <briannorris@chromium.org> wrote:

> The ARM ARM specifies that the system counter "must be implemented in an
> always-on power domain," and so we try to use the counter as a source of
> timekeeping across suspend/resume. Unfortunately, some SoCs (e.g.,
> Rockchip's RK3399) do not keep the counter ticking properly when
> switched from their high-power clock to the lower-power clock used in
> system suspend. Support this quirk by adding a new device tree property.
> 
> Signed-off-by: Brian Norris <briannorris@chromium.org>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply

* [PATCH 2/3] arm64: hw_breakpoint: Handle inexact watchpoint addresses
From: Pratyush Anand @ 2016-10-13  9:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJt8pk-HJYFUCxRuY5EV6KnM+kNP6mVBrFgPwiGfEkMKqGyjXw@mail.gmail.com>

Hi Pavel,

Thanks a lot for your testing.

On Wed, Oct 12, 2016 at 7:20 PM, Pavel Labath <labath@google.com> wrote:
> Hello Pratyush,
>
> I am sorry about the delay. I have finally had a chance to try out
> your changes today. Response inline.
>
> On 8 October 2016 at 06:10, Pratyush Anand <panand@redhat.com> wrote:
>> On Fri, Oct 7, 2016 at 10:54 PM, Pavel Labath <labath@google.com> wrote:
>>> The thing is, I have observed different behavior here depending on the
>>> exact hardware used. I don't have the exact parameters with me now,
>>> but I can look it up next week.
>>>
>>> The thing is that the spec is imprecise about what exact address the
>>> hardware can report for the watchpoint hit. I presume that is
>>> deliberate to give some leeway to implementers. The spec says the
>>> address can be anywhere in the range from the lowest memory address
>>> accessed by the instruction to the highest address watched by the
>>> watchpoint,
>>
>> I think, my patches should  be able to take care of the above condition.
> Unfortunately, the patch does not solve the problem for my hardware,
> because of the leeway you give in watchpoint_handler is not big
> enough. It does work however, if I change the line
>> if (addr + 7 < val + lens || addr > val + lene)
> to
>> if (addr + 15 < val + lens || addr > val + lene)

Yes, I missed that floating point register will be of size 16.

> I do not think we can assume that address reported by the hardware
> will be at most 7 bytes off from the address we put the watchpoint at.
> There is nothing in the spec that guarantees that, and it does not
> seem to be enough for some hardware. In fact, I am not sure we can
> assume 15 is enough either, but maybe it can do for now, until we can

Right. It might even be bigger, in case of cache maintenance instructions.

> find hardware that does not work with that (I haven't yet tried what
> happens it the watchpoint is triggered by cache management
> instructions, which can access much larger blocks of memory).

Not, sure, may be it can lie in cache line size range.

>
> For reference, the hardware in question is:
>> Processor : AArch64 Processor rev 0 (aarch64)
>> processor : 0
>> min_vddcx : 400000
>> min_vddmx : 490000
>> BogoMIPS : 38.00
>> Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
>> CPU implementer : 0x51
>> CPU architecture: 8
>> CPU variant : 0x2
>> CPU part : 0x201
>> CPU revision : 0
>> CPU param : 300 468 468 621 939 299 445 445 621 1077
>> Hardware : Qualcomm Technologies, Inc MSM8996pro
>
> And this is how it behaves:
> The output of the test app triggering the watchpoint (I have set a
> single-byte watchpoint at 555556705f)
>>
>> Writing to: 555556705f, size: 1
>> Writing to: 555556705e, size: 2
>> Writing to: 555556705c, size: 4
>> Writing to: 5555567058, size: 8
>> Writing to: 5555567050, size: 16
>> Writing to: 5555567040, size: 32
>
> The addresses received by the kernel:
> [  251.812166] c1   3780 hw-breakpoint: watchpoint_handler: addr:
> 555556705f, val+lens: 555556705f, val+lene: 555556705f
> [  251.820341] c1   3781 hw-breakpoint: watchpoint_handler: addr:
> 555556705e, val+lens: 555556705f, val+lene: 555556705f
> [  251.825572] c0   3782 hw-breakpoint: watchpoint_handler: addr:
> 555556705c, val+lens: 555556705f, val+lene: 555556705f
> [  251.831085] c0   3783 hw-breakpoint: watchpoint_handler: addr:
> 5555567058, val+lens: 555556705f, val+lene: 555556705f
> [  251.835804] c0   3784 hw-breakpoint: watchpoint_handler: addr:
> 5555567050, val+lens: 555556705f, val+lene: 555556705f
> [  251.841350] c0   3785 hw-breakpoint: watchpoint_handler: addr:
> 5555567050, val+lens: 555556705f, val+lene: 555556705f
>
> Note that for the case of 16 and 32-byte access it returns the address
> 5555567050 -- this is why the "+15" is sufficient for me.
>
>
> The other thing I am not so sure about in your patch is that it has
> potential to mis-attribute the watchpoint hit if we have two
> watchpoints close together. For example, if I have first watchpoint on
> 0x1008-0x100f and a second one on 0x1000-0x1007, *and* the application
> writes one byte to 0x1004, then your code will still attribute the hit
> to the first watchpoint, even though it was not really triggered. This

Hummm..yes, thanks for pointing it out.
There could be only two solutions for it:
(1) We read instruction at the location regs->pc and analyse it and
find the size of read/write.
or(2) What you have suggested in your patch.

I think, its easier to go with your implementation. So, I have taken
your patch and updated my perf/upstream_arm64_devel branch. May be you
can give it a test for your test cases.

> is the reason I implemented my fix as a two-stage process, first
> looking for exact hits, and then falling back to the nearest one. That
> said, I don't know enough about the codebase to say if this is a real
> problem.
>
> On the plus side, I like the fact that we can watch arbitrary memory
> regions now, and the feature is working perfectly. :)
>

Thanks :-)

>
> My proposal would be to combine the two patches - take the byte mask
> handling code from yours, and the hit-attribution code from my patch.
> What do you think?

I am ok with merging them together as well as sending them as
different patch in my v2 series.

~Pratyush

^ permalink raw reply

* [PATCH 0/2] arm64 kexec-tools fixups
From: Simon Horman @ 2016-10-13  9:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <ebe32436-6069-06c5-702f-d435d0dacd48@suse.com>

On Tue, Oct 11, 2016 at 12:20:41PM +0200, Matthias Brugger wrote:
> 
> 
> On 10/10/2016 11:22 PM, Geoff Levand wrote:
> >Hi Simon,
> >
> >Fixes for 'make tarball'.  Please apply.
> >
> >-Geoff
> >
> >The following changes since commit 6e8804f9ca67bee65aedd5e1cdf504737ab5c7ed:
> >
> >  multiboot: Use the "reserved" type for non-ram zones (2016-10-07 11:54:44 +0900)
> >
> >are available in the git repository at:
> >
> >  git://git.kernel.org/pub/scm/linux/kernel/git/geoff/kexec-tools.git for-merge-arm64-dist
> >
> >for you to fetch changes up to 3552a3e85a910688d932535549b35354a54927ad:
> >
> >  arm64: Add missing kexec dist files (2016-10-10 14:15:21 -0700)
> >
> >----------------------------------------------------------------
> >Geoff Levand (2):
> >      arm64: Cleanup kexec Makefile
> >      arm64: Add missing kexec dist files
> >
> > kexec/arch/arm64/Makefile | 15 +++++++++------
> > 1 file changed, 9 insertions(+), 6 deletions(-)
> >
> 
> Reviewed-by: Matthias Brugger <mbrugger@suse.com>

Thanks, applied.

^ permalink raw reply

* [PATCH v7 2/8] power: add power sequence library
From: Peter Chen @ 2016-10-13  8:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <10186696.bBGEe05eC7@phil>

On Thu, Oct 13, 2016 at 09:04:42AM +0200, Heiko Stuebner wrote:
> > > > +static int __init pwrseq_generic_register(void)
> > > > +{
> > > > +	struct pwrseq_generic *pwrseq_gen;
> > > > +	int i;
> > > > +
> > > > +	for (i = 0; i < CONFIG_PWRSEQ_GENERIC_INSTANCE_NUMBER; i++) {
> > > > +		pwrseq_gen = kzalloc(sizeof(*pwrseq_gen), GFP_KERNEL);
> > > > +		if (!pwrseq_gen)
> > > > +			return -ENOMEM;
> > > > +
> > > > +		pwrseq_gen->pwrseq.pwrseq_of_match_table = generic_id_table;
> > > > +		pwrseq_gen->pwrseq.get = pwrseq_generic_get;
> > > > +		pwrseq_gen->pwrseq.on = pwrseq_generic_on;
> > > > +		pwrseq_gen->pwrseq.off = pwrseq_generic_off;
> > > > +		pwrseq_gen->pwrseq.put = pwrseq_generic_put;
> > > > +		pwrseq_gen->pwrseq.free = pwrseq_generic_free;
> > > > +
> > > > +		pwrseq_register(&pwrseq_gen->pwrseq);
> > > > +	}
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +postcore_initcall(pwrseq_generic_register)
> > > 
> > > I see that you need to have it preallocated for the compatible matching,
> > > but wouldn't it also work to either just register the type and allocate
> > > dynamically or otherwise just allocate a new spare everytime
> > > pwrseq_generic_get() picks up the previous spare?
> > 
> > Before compatible matching, the host driver doesn't know which pwrseq type
> > for its child node, then doesn't know which pwrseq instance needs to be
> > allocated. From dts, we don't know which pwrseq type for the node.
> 
> yes, that is why I was suggesting allocating one (or two) here in 
> pwrseq_generic_register() and every time pwrseq_generic_get() grabs the last 
> free sequence instance, you allocate a new free spare one in that function.

Good idea.

-- 

Best Regards,
Peter Chen

^ permalink raw reply

* [PATCH] ARM: dts: rockchip: Reserve unusable memory region on rk3066
From: Paweł Jarosz @ 2016-10-13  8:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <e3746f9a-084e-163e-a412-1a1fc66926d5@rock-chips.com>

Hi


W dniu 13.10.2016 o 09:12, Huang, Tao pisze:
> Hi, Pawe?:
> On 2016?10?10? 17:11, Pawe? Jarosz wrote:
>> W dniu 10.10.2016 o 09:18, Huang, Tao pisze:
>>> Our IC guy need us tell them which master can not access such area, DMA
>>> or EMMC Controller or GPU, etc? Could you tell me how to reproduce such
>>> issue?
>>> And we can confirm CPU core can access this memory through /dev/mem and
>>> the test board is 1GB too. Personally, I don't think RK3066 has such
>>> limit because when we verify this chip, we don't found such limit at all.
>>>
>>> Thanks,
>>> Huang, Tao
>> I'm getting this on Ubuntu 16.04 with mainline kernel.
>> My board always freezes when i type: "memtester 800M"
>>
> We try run memtest 800M with Linux kernel 4.8, which killed by OOM.
> But if we run:
> # memtester -p 0x9F000000 16K 1
> memtester version 4.3.0 (32-bit)
> Copyright (C) 2001-2012 Charles Cazabon.
> Licensed under the GNU General Public License version 2 (only).
>
> pagesize is 4096
> pagesizemask is 0xfffff000
> want 0MB (16384 bytes)
> Loop 1/1:
>     Stuck Address       : ok
>     Random Value        : ok
>     Compare XOR         : ok
>     Compare SUB         : ok
>     Compare MUL         : ok
>     Compare DIV         : ok
>     Compare OR          : ok
>     Compare AND         : ok
>     Sequential Increment: ok
>     Solid Bits          : ok
>     Block Sequential    : ok
>     Checkerboard        : ok
>     Bit Spread          : ok
>     Bit Flip            : ok
>     Walking Ones        : ok
>     Walking Zeroes      : ok
>     8-bit Writes        : ok
>     16-bit Writes       : ok
>
> So these memory should be fine to CPU core. Maybe your system just
> freeze because out of memory.
>

weird ... memtester -p 0x9F000000 16K 1 gave me the same result.

Could you try one last command:

	memtester 400M

Values > 200M causing freeze.

If this won't do it, than maybe there is something wrong with my board.

Thanks for your time.

^ permalink raw reply

* [PATCH V3 02/10] ras: acpi/apei: cper: generic error data entry v3 per ACPI 6.1
From: Suzuki K Poulose @ 2016-10-13  8:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <c17a0c03-5037-d88d-f096-4cc72dbfcb99@codeaurora.org>

On 12/10/16 23:10, Baicar, Tyler wrote:
> Hello Suzuki,
>
> Thank you for the feedback! Responses below.
>
>
> On 10/11/2016 11:28 AM, Suzuki K Poulose wrote:
>> On 07/10/16 22:31, Tyler Baicar wrote:
>>> Currently when a RAS error is reported it is not timestamped.
>>> The ACPI 6.1 spec adds the timestamp field to the generic error
>>> data entry v3 structure. The timestamp of when the firmware
>>> generated the error is now being reported.
>>>
>>> Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
>>> Signed-off-by: Richard Ruigrok <rruigrok@codeaurora.org>
>>> Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
>>> Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
>>
>> Please could you keep the people who reviewed/commented on your series in the past,
>> whenever you post a new version ?
> Do you mean to just send the new version to their e-mail directly in addition to the lists? If so, I will do that next time.

If you send a new version of a series to the list, it is a good idea to keep
the people who commented (significantly) on your previous version in Cc, especially
when you have addressed their feedback. That will help them to keep track of the
series. People can always see the new version in the list, but then it is so easy
to miss something in the 100s of emails you get each day. I am sure people have
special filters for the emails based on if they are in Cc/To etc.

>
> I know you provided good feedback on the previous patchset, but I did not have anyone specifically respond to add "reviewed-by:...". I don't think I should add reviewed-by for someone unless they specifically add it in a response :)

No, I haven't yet "Reviewed-by" your patches. I had some comments on it, which means
I expected it to be addressed as you committed in your response.

>>> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
>>> index 3021f0e..c8488f1 100644
>>> --- a/drivers/acpi/apei/ghes.c
>>> +++ b/drivers/acpi/apei/ghes.c
>>> @@ -80,6 +80,10 @@

> I think that should work to avoid duplication. I will move them to a header file in the next patchset.
>>> +
>>> +static void cper_estatus_print_section_v300(const char *pfx,
>>> +    const struct acpi_hest_generic_data_v300 *gdata)
>>> +{
>>> +    __u8 hour, min, sec, day, mon, year, century, *timestamp;
>>> +
>>> +    if (gdata->validation_bits & ACPI_HEST_GEN_VALID_TIMESTAMP) {
>>> +        timestamp = (__u8 *)&(gdata->time_stamp);
>>> +        memcpy(&sec, timestamp, 1);
>>> +        memcpy(&min, timestamp + 1, 1);
>>> +        memcpy(&hour, timestamp + 2, 1);
>>> +        memcpy(&day, timestamp + 4, 1);
>>> +        memcpy(&mon, timestamp + 5, 1);
>>> +        memcpy(&year, timestamp + 6, 1);
>>> +        memcpy(&century, timestamp + 7, 1);
>>> +        printk("%stime: ", pfx);
>>> +        printk("%7s", 0x01 & *(timestamp + 3) ? "precise" : "");
>>
>> What format is the (timestamp + 3) stored in ? Does it need conversion ?
> The third byte of the timestamp is currently only used to determine if the time is precise or not. Bit 0 is used to specify that and the other bits in this byte are marked as reserved. This is shown in table 247 of the UEFI spec 2.6:
>
> Byte 3:
>   Bit 0 ? Timestamp is precise if this bit is set and correlates to the time of the error event.
>   Bit 7:1 ? Reserved

Is it always the same endianness as that of the CPU ?

Cheers
Suzuki

^ permalink raw reply

* [PATCH 2/3] irqchip: mtk-cirq: Add mediatek mtk-cirq implement
From: Marc Zyngier @ 2016-10-13  8:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476335194-26604-3-git-send-email-youlin.pei@mediatek.com>

On Thu, 13 Oct 2016 13:06:33 +0800
Youlin Pei <youlin.pei@mediatek.com> wrote:

> This commit add the mtk-cirq implement for mt2701.

Can you please expand this a bit?

> 
> Signed-off-by: Youlin Pei <youlin.pei@mediatek.com>
> ---
>  drivers/irqchip/Makefile       |    2 +-
>  drivers/irqchip/irq-mtk-cirq.c |  257 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 258 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/irqchip/irq-mtk-cirq.c
> 
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 4c203b6..eee95c6 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -59,7 +59,7 @@ obj-$(CONFIG_BCM7120_L2_IRQ)		+= irq-bcm7120-l2.o
>  obj-$(CONFIG_BRCMSTB_L2_IRQ)		+= irq-brcmstb-l2.o
>  obj-$(CONFIG_KEYSTONE_IRQ)		+= irq-keystone.o
>  obj-$(CONFIG_MIPS_GIC)			+= irq-mips-gic.o
> -obj-$(CONFIG_ARCH_MEDIATEK)		+= irq-mtk-sysirq.o
> +obj-$(CONFIG_ARCH_MEDIATEK)		+= irq-mtk-sysirq.o irq-mtk-cirq.o
>  obj-$(CONFIG_ARCH_DIGICOLOR)		+= irq-digicolor.o
>  obj-$(CONFIG_RENESAS_H8300H_INTC)	+= irq-renesas-h8300h.o
>  obj-$(CONFIG_RENESAS_H8S_INTC)		+= irq-renesas-h8s.o
> diff --git a/drivers/irqchip/irq-mtk-cirq.c b/drivers/irqchip/irq-mtk-cirq.c
> new file mode 100644
> index 0000000..544767d
> --- /dev/null
> +++ b/drivers/irqchip/irq-mtk-cirq.c
> @@ -0,0 +1,257 @@
> +/*
> + * Copyright (c) 2016 MediaTek Inc.
> + * Author: Youlin.Pei <youlin.pei@mediatek.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/irq.h>
> +#include <linux/irqchip.h>
> +#include <linux/irqdomain.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_address.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/syscore_ops.h>
> +
> +#define CIRQ_MASK_SET	0xC0
> +#define CIRQ_MASK_CLR	0x100
> +#define CIRQ_SENS_SET	0x180
> +#define CIRQ_SENS_CLR	0x1C0
> +#define CIRQ_POL_SET	0x240
> +#define CIRQ_POL_CLR	0x280
> +#define CIRQ_CONTROL	0x300
> +
> +#define CIRQ_EN		0x1
> +#define CIRQ_EDGE	0x2
> +#define CIRQ_FLUSH	0x4
> +
> +#define CIRQ_IRQ_NUM    0x200
> +
> +struct mtk_cirq_chip_data {
> +	void __iomem *base;
> +	unsigned int ext_irq_start;
> +};
> +
> +struct mtk_cirq_chip_data *cirq_data;

Any reason why this is not static?

> +
> +static void mtk_cirq_write_mask(struct irq_data *data, unsigned int offset)
> +{
> +	struct mtk_cirq_chip_data *chip_data = data->chip_data;
> +	unsigned int cirq_num = data->hwirq - chip_data->ext_irq_start;

I wonder why you have to compute this offset. Ideally, data->hwirq
should be the bit position (starting at zero). The fact that you have
an offset between the pin number in this driver and the IRQ number in
the GIC or sysirq should be resolved at alloc time.

> +	u32 mask = 1 << (cirq_num % 32);
> +
> +	writel(mask, chip_data->base + offset + (cirq_num / 32) * 4);
> +}
> +
> +static void mtk_cirq_mask(struct irq_data *data)
> +{
> +	mtk_cirq_write_mask(data, CIRQ_MASK_SET);
> +	irq_chip_mask_parent(data);
> +}
> +
> +static void mtk_cirq_unmask(struct irq_data *data)
> +{
> +	mtk_cirq_write_mask(data, CIRQ_MASK_CLR);
> +	irq_chip_unmask_parent(data);
> +}
> +
> +static int mtk_cirq_set_type(struct irq_data *data, unsigned int type)
> +{
> +	int ret;
> +
> +	switch (type & IRQ_TYPE_SENSE_MASK) {
> +	case IRQ_TYPE_EDGE_FALLING:
> +		mtk_cirq_write_mask(data, CIRQ_POL_CLR);
> +		mtk_cirq_write_mask(data, CIRQ_SENS_CLR);
> +		break;
> +	case IRQ_TYPE_EDGE_RISING:
> +		mtk_cirq_write_mask(data, CIRQ_POL_SET);
> +		mtk_cirq_write_mask(data, CIRQ_SENS_CLR);
> +		break;
> +	case IRQ_TYPE_LEVEL_LOW:
> +		mtk_cirq_write_mask(data, CIRQ_POL_CLR);
> +		mtk_cirq_write_mask(data, CIRQ_SENS_SET);
> +		break;
> +	case IRQ_TYPE_LEVEL_HIGH:
> +		mtk_cirq_write_mask(data, CIRQ_POL_SET);
> +		mtk_cirq_write_mask(data, CIRQ_SENS_SET);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	data = data->parent_data;
> +	ret = data->chip->irq_set_type(data, type);
> +	return ret;
> +}
> +
> +static struct irq_chip mtk_cirq_chip = {
> +	.name			= "MT_CIRQ",
> +	.irq_mask		= mtk_cirq_mask,
> +	.irq_unmask		= mtk_cirq_unmask,
> +	.irq_eoi		= irq_chip_eoi_parent,
> +	.irq_set_type		= mtk_cirq_set_type,
> +	.irq_retrigger		= irq_chip_retrigger_hierarchy,
> +#ifdef CONFIG_SMP
> +	.irq_set_affinity	= irq_chip_set_affinity_parent,
> +#endif
> +};

I'm surprised that you don't implement irq_set_wake. Do you wake-up on
*any* interrupt?

> +
> +static int mtk_cirq_domain_translate(struct irq_domain *d,
> +				     struct irq_fwspec *fwspec,
> +				     unsigned long *hwirq,
> +				     unsigned int *type)
> +{
> +	if (is_of_node(fwspec->fwnode)) {
> +		if (fwspec->param_count != 3)
> +			return -EINVAL;
> +
> +		/* No PPI should point to this domain */
> +		if (fwspec->param[0] != 0)
> +			return -EINVAL;
> +
> +		/* cirq support irq number check */
> +		if (fwspec->param[1] < ;)
> +			return -EINVAL;
> +
> +		*hwirq = fwspec->param[1];

So if you turn this into:

		*hwirq = fwspec->param[1] - cirq_data->ext_irq_start;

and drop the above offset computing in your write function, you'd have
something that'd make a bit more sense.

> +		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
> +		return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int mtk_cirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
> +				 unsigned int nr_irqs, void *arg)
> +{
> +	int i;
> +	irq_hw_number_t hwirq;
> +	struct irq_fwspec *fwspec = arg;
> +	struct irq_fwspec parent_fwspec = *fwspec;
> +
> +	if (fwspec->param_count != 3)
> +		return -EINVAL;
> +
> +	/* cirq doesn't support PPI */
> +	if (fwspec->param[0])
> +		return -EINVAL;
> +
> +	if (fwspec->param[1] < cirq_data->ext_irq_start)
> +		return -EINVAL;
> +
> +	hwirq = fwspec->param[1];
> +	for (i = 0; i < nr_irqs; i++)
> +		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
> +					      &mtk_cirq_chip,
> +					      domain->host_data);
> +
> +	parent_fwspec.fwnode = domain->parent->fwnode;
> +	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
> +					    &parent_fwspec);
> +}
> +
> +static const struct irq_domain_ops cirq_domain_ops = {
> +	.translate	= mtk_cirq_domain_translate,
> +	.alloc		= mtk_cirq_domain_alloc,
> +	.free		= irq_domain_free_irqs_common,
> +};
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int mtk_cirq_suspend(void)
> +{
> +	u32 value;
> +
> +	/* set edge_only mode, record edge-triggerd interrupts */
> +	/* enable cirq */
> +	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> +	value |= (CIRQ_EDGE | CIRQ_EN);
> +	writel(value, cirq_data->base + CIRQ_CONTROL);
> +	return 0;
> +}
> +
> +static void mtk_cirq_resume(void)
> +{
> +	u32 value;
> +
> +	/* flush recored interrupts, will send signals to parent controller */
> +	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> +	writel(value | CIRQ_FLUSH, cirq_data->base + CIRQ_CONTROL);
> +
> +	/* disable cirq */
> +	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> +	value &= ~(CIRQ_EDGE | CIRQ_EN);
> +	writel(value, cirq_data->base + CIRQ_CONTROL);
> +}
> +
> +static struct syscore_ops mtk_cirq_syscore_ops = {
> +	.suspend	= mtk_cirq_suspend,
> +	.resume		= mtk_cirq_resume,
> +};
> +
> +static void mtk_cirq_syscore_init(void)
> +{
> +	register_syscore_ops(&mtk_cirq_syscore_ops);
> +}
> +#else
> +static inline void mtk_cirq_syscore_init(void) {}
> +#endif
> +
> +static int __init mtk_cirq_of_init(struct device_node *node,
> +				   struct device_node *parent)
> +{
> +	struct irq_domain *domain, *domain_parent;
> +	int ret;
> +
> +	domain_parent = irq_find_host(parent);
> +	if (!domain_parent) {
> +		pr_err("mtk_cirq: interrupt-parent not found\n");
> +		return -EINVAL;
> +	}
> +
> +	cirq_data = kzalloc(sizeof(*cirq_data), GFP_KERNEL);
> +	if (!cirq_data)
> +		return -ENOMEM;
> +
> +	cirq_data->base = of_iomap(node, 0);
> +	if (!cirq_data->base) {
> +		pr_err("mtk_cirq: unable to map cirq register\n");
> +		ret = -ENXIO;
> +		goto out_free;
> +	}
> +
> +	if (of_property_read_u32(node, "mediatek,ext-irq-start",
> +				 &cirq_data->ext_irq_start)) {
> +		ret = -EINVAL;
> +		goto out_free;
> +	}
> +
> +	domain = irq_domain_add_hierarchy(domain_parent, 0, CIRQ_IRQ_NUM, node,
> +					  &cirq_domain_ops, cirq_data);
> +	if (!domain) {
> +		ret = -ENOMEM;
> +		goto out_unmap;
> +	}
> +
> +	mtk_cirq_syscore_init();
> +
> +	return 0;
> +
> +out_unmap:
> +	iounmap(cirq_data->base);
> +out_free:
> +	kfree(cirq_data);
> +	return ret;
> +}
> +
> +IRQCHIP_DECLARE(mtk_cirq, "mediatek,mt2701-cirq", mtk_cirq_of_init);

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply

* [PATCH 00/10] mm: adjust get_user_pages* functions to explicitly pass FOLL_* flags
From: Christian König @ 2016-10-13  7:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161013002020.3062-1-lstoakes@gmail.com>

Am 13.10.2016 um 02:20 schrieb Lorenzo Stoakes:
> This patch series adjusts functions in the get_user_pages* family such that
> desired FOLL_* flags are passed as an argument rather than implied by flags.
>
> The purpose of this change is to make the use of FOLL_FORCE explicit so it is
> easier to grep for and clearer to callers that this flag is being used. The use
> of FOLL_FORCE is an issue as it overrides missing VM_READ/VM_WRITE flags for the
> VMA whose pages we are reading from/writing to, which can result in surprising
> behaviour.
>
> The patch series came out of the discussion around commit 38e0885, which
> addressed a BUG_ON() being triggered when a page was faulted in with PROT_NONE
> set but having been overridden by FOLL_FORCE. do_numa_page() was run on the
> assumption the page _must_ be one marked for NUMA node migration as an actual
> PROT_NONE page would have been dealt with prior to this code path, however
> FOLL_FORCE introduced a situation where this assumption did not hold.
>
> See https://marc.info/?l=linux-mm&m=147585445805166 for the patch proposal.
>
> Lorenzo Stoakes (10):
>    mm: remove write/force parameters from __get_user_pages_locked()
>    mm: remove write/force parameters from __get_user_pages_unlocked()
>    mm: replace get_user_pages_unlocked() write/force parameters with gup_flags
>    mm: replace get_user_pages_locked() write/force parameters with gup_flags
>    mm: replace get_vaddr_frames() write/force parameters with gup_flags
>    mm: replace get_user_pages() write/force parameters with gup_flags
>    mm: replace get_user_pages_remote() write/force parameters with gup_flags
>    mm: replace __access_remote_vm() write parameter with gup_flags
>    mm: replace access_remote_vm() write parameter with gup_flags
>    mm: replace access_process_vm() write parameter with gup_flags

Patch number 6 in this series (which touches drivers I co-maintain) is 
Acked-by: Christian K?nig <christian.koenig@amd.com>.

In general looks like a very nice cleanup to me, but I'm not enlightened 
enough to full judge.

Regards,
Christian.

>
>   arch/alpha/kernel/ptrace.c                         |  9 ++--
>   arch/blackfin/kernel/ptrace.c                      |  5 ++-
>   arch/cris/arch-v32/drivers/cryptocop.c             |  4 +-
>   arch/cris/arch-v32/kernel/ptrace.c                 |  4 +-
>   arch/ia64/kernel/err_inject.c                      |  2 +-
>   arch/ia64/kernel/ptrace.c                          | 14 +++---
>   arch/m32r/kernel/ptrace.c                          | 15 ++++---
>   arch/mips/kernel/ptrace32.c                        |  5 ++-
>   arch/mips/mm/gup.c                                 |  2 +-
>   arch/powerpc/kernel/ptrace32.c                     |  5 ++-
>   arch/s390/mm/gup.c                                 |  3 +-
>   arch/score/kernel/ptrace.c                         | 10 +++--
>   arch/sh/mm/gup.c                                   |  3 +-
>   arch/sparc/kernel/ptrace_64.c                      | 24 +++++++----
>   arch/sparc/mm/gup.c                                |  3 +-
>   arch/x86/kernel/step.c                             |  3 +-
>   arch/x86/mm/gup.c                                  |  2 +-
>   arch/x86/mm/mpx.c                                  |  5 +--
>   arch/x86/um/ptrace_32.c                            |  3 +-
>   arch/x86/um/ptrace_64.c                            |  3 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c            |  7 ++-
>   drivers/gpu/drm/etnaviv/etnaviv_gem.c              |  7 ++-
>   drivers/gpu/drm/exynos/exynos_drm_g2d.c            |  3 +-
>   drivers/gpu/drm/i915/i915_gem_userptr.c            |  6 ++-
>   drivers/gpu/drm/radeon/radeon_ttm.c                |  3 +-
>   drivers/gpu/drm/via/via_dmablit.c                  |  4 +-
>   drivers/infiniband/core/umem.c                     |  6 ++-
>   drivers/infiniband/core/umem_odp.c                 |  7 ++-
>   drivers/infiniband/hw/mthca/mthca_memfree.c        |  2 +-
>   drivers/infiniband/hw/qib/qib_user_pages.c         |  3 +-
>   drivers/infiniband/hw/usnic/usnic_uiom.c           |  5 ++-
>   drivers/media/pci/ivtv/ivtv-udma.c                 |  4 +-
>   drivers/media/pci/ivtv/ivtv-yuv.c                  |  5 ++-
>   drivers/media/platform/omap/omap_vout.c            |  2 +-
>   drivers/media/v4l2-core/videobuf-dma-sg.c          |  7 ++-
>   drivers/media/v4l2-core/videobuf2-memops.c         |  6 ++-
>   drivers/misc/mic/scif/scif_rma.c                   |  3 +-
>   drivers/misc/sgi-gru/grufault.c                    |  2 +-
>   drivers/platform/goldfish/goldfish_pipe.c          |  3 +-
>   drivers/rapidio/devices/rio_mport_cdev.c           |  3 +-
>   drivers/scsi/st.c                                  |  5 +--
>   .../interface/vchiq_arm/vchiq_2835_arm.c           |  3 +-
>   .../vc04_services/interface/vchiq_arm/vchiq_arm.c  |  3 +-
>   drivers/video/fbdev/pvr2fb.c                       |  4 +-
>   drivers/virt/fsl_hypervisor.c                      |  4 +-
>   fs/exec.c                                          |  9 +++-
>   fs/proc/base.c                                     | 19 +++++---
>   include/linux/mm.h                                 | 18 ++++----
>   kernel/events/uprobes.c                            |  6 ++-
>   kernel/ptrace.c                                    | 16 ++++---
>   mm/frame_vector.c                                  |  9 ++--
>   mm/gup.c                                           | 50 ++++++++++------------
>   mm/memory.c                                        | 16 ++++---
>   mm/mempolicy.c                                     |  2 +-
>   mm/nommu.c                                         | 38 +++++++---------
>   mm/process_vm_access.c                             |  7 ++-
>   mm/util.c                                          |  8 ++--
>   net/ceph/pagevec.c                                 |  2 +-
>   security/tomoyo/domain.c                           |  2 +-
>   virt/kvm/async_pf.c                                |  3 +-
>   virt/kvm/kvm_main.c                                | 11 +++--
>   61 files changed, 260 insertions(+), 187 deletions(-)
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* [PATCH] ARM: dts: da850: Add basic DTS for the L138/C6748 Dev Kit
From: Karl Beldan @ 2016-10-13  7:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160804234349.GA4391@gobelin>

On Thu, Aug 04, 2016 at 11:43:49PM +0000, Karl Beldan wrote:
> On Thu, Aug 04, 2016 at 04:13:10PM -0500, Rob Herring wrote:
> > +Peter H
> > 
> > On Thu, Aug 4, 2016 at 4:03 PM, Karl Beldan <kbeldan@baylibre.com> wrote:
> > > On Thu, Aug 04, 2016 at 01:29:02PM -0500, Rob Herring wrote:
> > >> On Thu, Aug 04, 2016 at 02:43:32PM +0000, Karl Beldan wrote:
> > >> > The LCDK is the successor to the late Hawkboard and has the same machine
> > >> > number.
> > >> > Among the differences are the flash (16bits vs 8bits) and some pins
> > >> > (MMC, LEDs, buttons, some external connectors), however the main
> > >> > components remain the same (eth. PHY, Audio Codec, Video decoder and
> > >> > DAC) except for the main PMIC, different and hard-wired on the LCDK (the
> > >> > LDOs and DCDCs are always ON).
> > >> > A DT-only boot with this addition gives functional uart, reboot via
> > >> > watchdog, rtc, ethernet and MMC (I added the CD gpio for the MMC
> > >> > although davinci_mmc doesn't call yet the mmc core OF facilities).
> > 
> > [...]
> > 
> > >> > +   aliases {
> > >> > +           serial2 = &serial2;
> > >> > +   };
> > >> > +
> > >> > +   chosen {
> > >> > +           bootargs = "console=ttyS2,115200n8 earlycon";
> > >>
> > >> You don't need console with stdout-path set. And really, earlycon should
> > >> not be the default.
> > >>
> > > Ok for earlycon.
> > >
> > > For the console, I thought likewise .. until I _struggled_ to understand
> > > why the console was disappearing under my feet.
> > > It seemed even stranger when I started looking at the codepath because
> > > drivers/of/base.c would properly add_preferred_console as expected after
> > > the corresponding UART was added. But the reality was there, without it
> > > the console was not like stdout-path.
> > > Among the commits that could instill doubt as to whether stdout-path
> > > rules is f64255b5072d:
> > > "The assumption that at least 1 preferred console will be registered
> > > when the stdout-path property is set is invalid, which can result in
> > > _no_ consoles.", though it didn't answer my question.
> > > I started looking whether tty0 was not getting in the way and in the end
> > > I came up with setting console.
> > > But you seem affirmative.
> > 
> > There have been some issues in this area, but I thought they were in
> > conjunction with earlycon and solved now. This is a fairly common
> > review request for dts files, so I'm surprised if it doesn't work
> > right. Maybe having tty0 or not has some influence. Or people just
> > accept review comments without testing or caring...
> > 
> I can assure you I tested without early{con,printk} ;).
> 
> Now I have just rechecked the codepaths and something caught my
> attention in kernel/printk/printk.c:__add_preferred_console(): if
> console_cmdline is empty selected_console gets unconditionally set to
> zero ! Knowing this I confirmed by replacing with idx (works), and also
> by using ttyS0 (i.e. alias serial0 = &uart2) (works), this would not
> affect DTs using serial0. It's late here so I'll stop there.
>  

The stdout-path bug was fixed last week by Paul Burton in 05fd007e4629 
("console: don't prefer first registered if DT specifies stdout-path").
 
Karl

^ permalink raw reply

* [PATCH] ARM: dts: rockchip: Reserve unusable memory region on rk3066
From: Huang, Tao @ 2016-10-13  7:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <149df5ee-3478-6d15-bb76-47becac146e9@gmail.com>

Hi, Pawe?:
On 2016?10?10? 17:11, Pawe? Jarosz wrote:
> W dniu 10.10.2016 o 09:18, Huang, Tao pisze:
>> Our IC guy need us tell them which master can not access such area, DMA
>> or EMMC Controller or GPU, etc? Could you tell me how to reproduce such
>> issue?
>> And we can confirm CPU core can access this memory through /dev/mem and
>> the test board is 1GB too. Personally, I don't think RK3066 has such
>> limit because when we verify this chip, we don't found such limit at all.
>>
>> Thanks,
>> Huang, Tao
> I'm getting this on Ubuntu 16.04 with mainline kernel.
> My board always freezes when i type: "memtester 800M"
>
We try run memtest 800M with Linux kernel 4.8, which killed by OOM.
But if we run:
# memtester -p 0x9F000000 16K 1
memtester version 4.3.0 (32-bit)
Copyright (C) 2001-2012 Charles Cazabon.
Licensed under the GNU General Public License version 2 (only).

pagesize is 4096
pagesizemask is 0xfffff000
want 0MB (16384 bytes)
Loop 1/1:
   Stuck Address       : ok
   Random Value        : ok
   Compare XOR         : ok
   Compare SUB         : ok
   Compare MUL         : ok
   Compare DIV         : ok
   Compare OR          : ok
   Compare AND         : ok
   Sequential Increment: ok
   Solid Bits          : ok
   Block Sequential    : ok
   Checkerboard        : ok
   Bit Spread          : ok
   Bit Flip            : ok
   Walking Ones        : ok
   Walking Zeroes      : ok
   8-bit Writes        : ok
   16-bit Writes       : ok

So these memory should be fine to CPU core. Maybe your system just
freeze because out of memory.

^ permalink raw reply

* [PATCH 4/4] staging/vchi: Remove dependency on CONFIG_BROKEN.
From: Greg Kroah-Hartman @ 2016-10-13  7:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003185209.27733-5-eric@anholt.net>

On Mon, Oct 03, 2016 at 11:52:09AM -0700, Eric Anholt wrote:
> The driver builds now.
> 
> Signed-off-by: Eric Anholt <eric@anholt.net>
> ---
>  drivers/staging/vc04_services/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/staging/vc04_services/Kconfig b/drivers/staging/vc04_services/Kconfig
> index 9676fb29075a..db8e1beb89f9 100644
> --- a/drivers/staging/vc04_services/Kconfig
> +++ b/drivers/staging/vc04_services/Kconfig
> @@ -1,6 +1,6 @@
>  config BCM2708_VCHIQ
>  	tristate "Videocore VCHIQ"
> -	depends on RASPBERRYPI_FIRMWARE && BROKEN
> +	depends on RASPBERRYPI_FIRMWARE
>  	default y
>  	help
>  		Kernel to VideoCore communication interface for the

I've dropped this patch from my branch as there are build errors on
arm64 systems still, and we don't want regressions like that.

I've forwarded you the error messages, and I'll be glad to add this
patch back once these issues are fixed.

thanks,

greg k-h

^ permalink raw reply

* [PATCH v7 2/8] power: add power sequence library
From: Heiko Stuebner @ 2016-10-13  7:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161013012216.GA8114@b29397-desktop>

Am Donnerstag, 13. Oktober 2016, 09:22:16 CEST schrieb Peter Chen:
> On Wed, Oct 12, 2016 at 12:30:29PM +0200, Heiko Stuebner wrote:
> > Hi,
> > 
> > Am Dienstag, 20. September 2016, 11:36:41 CEST schrieb Peter Chen:
> > > We have an well-known problem that the device needs to do some power
> > > sequence before it can be recognized by related host, the typical
> > > example like hard-wired mmc devices and usb devices.
> > > 
> > > This power sequence is hard to be described at device tree and handled
> > > by
> > > related host driver, so we have created a common power sequence
> > > library to cover this requirement. The core code has supplied
> > > some common helpers for host driver, and individual power sequence
> > > libraries handle kinds of power sequence for devices.
> > > 
> > > pwrseq_generic is intended for general purpose of power sequence, which
> > > handles gpios and clocks currently, and can cover regulator and pinctrl
> > > in future. The host driver just needs to call of_pwrseq_on/of_pwrseq_off
> > > if only one power sequence is needed, else call of_pwrseq_on_list
> > > /of_pwrseq_off_list instead (eg, USB hub driver).
> > > 
> > > Signed-off-by: Peter Chen <peter.chen@nxp.com>
> > > Tested-by Joshua Clayton <stillcompiling@gmail.com>
> > > Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
> > > Tested-by: Matthias Kaehlcke <mka@chromium.org>
> > 
> > first of all, glad to see this move forward. I've only some qualms with
> > the
> > static number of allocated power sequences below.
> 
> Thanks for commenting it, the preallocate way is not a good way, but I
> can't find suitable way. See below comments.
> 
> > > +static int __init pwrseq_generic_register(void)
> > > +{
> > > +	struct pwrseq_generic *pwrseq_gen;
> > > +	int i;
> > > +
> > > +	for (i = 0; i < CONFIG_PWRSEQ_GENERIC_INSTANCE_NUMBER; i++) {
> > > +		pwrseq_gen = kzalloc(sizeof(*pwrseq_gen), GFP_KERNEL);
> > > +		if (!pwrseq_gen)
> > > +			return -ENOMEM;
> > > +
> > > +		pwrseq_gen->pwrseq.pwrseq_of_match_table = generic_id_table;
> > > +		pwrseq_gen->pwrseq.get = pwrseq_generic_get;
> > > +		pwrseq_gen->pwrseq.on = pwrseq_generic_on;
> > > +		pwrseq_gen->pwrseq.off = pwrseq_generic_off;
> > > +		pwrseq_gen->pwrseq.put = pwrseq_generic_put;
> > > +		pwrseq_gen->pwrseq.free = pwrseq_generic_free;
> > > +
> > > +		pwrseq_register(&pwrseq_gen->pwrseq);
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +postcore_initcall(pwrseq_generic_register)
> > 
> > I see that you need to have it preallocated for the compatible matching,
> > but wouldn't it also work to either just register the type and allocate
> > dynamically or otherwise just allocate a new spare everytime
> > pwrseq_generic_get() picks up the previous spare?
> 
> Before compatible matching, the host driver doesn't know which pwrseq type
> for its child node, then doesn't know which pwrseq instance needs to be
> allocated. From dts, we don't know which pwrseq type for the node.

yes, that is why I was suggesting allocating one (or two) here in 
pwrseq_generic_register() and every time pwrseq_generic_get() grabs the last 
free sequence instance, you allocate a new free spare one in that function.

^ permalink raw reply

* [PATCH v2] sdhci-esdhc-imx: Correct two register accesses
From: Ulf Hansson @ 2016-10-13  7:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476124792-18441-1-git-send-email-aaron.brice@datasoft.com>

On 10 October 2016 at 20:39, Aaron Brice <aaron.brice@datasoft.com> wrote:
>
>  - The DMA error interrupt bit is in a different position as
>    compared to the sdhci standard.  This is accounted for in
>    many cases, but not handled in the case of clearing the
>    INT_STATUS register by writing a 1 to that location.
>  - The HOST_CONTROL register is very different as compared to
>    the sdhci standard.  This is accounted for in the write
>    case, but not when read back out (which it is in the sdhci
>    code).
>
> Signed-off-by: Dave Russell <david.russell@datasoft.com>
> Signed-off-by: Aaron Brice <aaron.brice@datasoft.com>
> Acked-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---

Thanks, applied for fixes!

Kind regards
Uffe

>
> v1 -> v2:
> - rename long_val to val
>
>  drivers/mmc/host/sdhci-esdhc-imx.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 1f54fd8..7123ef9 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -346,7 +346,8 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
>         struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
>         u32 data;
>
> -       if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) {
> +       if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE ||
> +                       reg == SDHCI_INT_STATUS)) {
>                 if ((val & SDHCI_INT_CARD_INT) && !esdhc_is_usdhc(imx_data)) {
>                         /*
>                          * Clear and then set D3CD bit to avoid missing the
> @@ -555,6 +556,25 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>         esdhc_clrset_le(host, 0xffff, val, reg);
>  }
>
> +static u8 esdhc_readb_le(struct sdhci_host *host, int reg)
> +{
> +       u8 ret;
> +       u32 val;
> +
> +       switch (reg) {
> +       case SDHCI_HOST_CONTROL:
> +               val = readl(host->ioaddr + reg);
> +
> +               ret = val & SDHCI_CTRL_LED;
> +               ret |= (val >> 5) & SDHCI_CTRL_DMA_MASK;
> +               ret |= (val & ESDHC_CTRL_4BITBUS);
> +               ret |= (val & ESDHC_CTRL_8BITBUS) << 3;
> +               return ret;
> +       }
> +
> +       return readb(host->ioaddr + reg);
> +}
> +
>  static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
>  {
>         struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> @@ -947,6 +967,7 @@ static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
>  static struct sdhci_ops sdhci_esdhc_ops = {
>         .read_l = esdhc_readl_le,
>         .read_w = esdhc_readw_le,
> +       .read_b = esdhc_readb_le,
>         .write_l = esdhc_writel_le,
>         .write_w = esdhc_writew_le,
>         .write_b = esdhc_writeb_le,
> --
> 2.7.4
>

^ permalink raw reply

* [PATCH 02/10] mm: remove write/force parameters from __get_user_pages_unlocked()
From: Paolo Bonzini @ 2016-10-13  6:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161013002020.3062-3-lstoakes@gmail.com>



On 13/10/2016 02:20, Lorenzo Stoakes wrote:
> This patch removes the write and force parameters from
> __get_user_pages_unlocked() to make the use of FOLL_FORCE explicit in callers as
> use of this flag can result in surprising behaviour (and hence bugs) within the
> mm subsystem.
> 
> Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
> ---
>  include/linux/mm.h     |  3 +--
>  mm/gup.c               | 17 +++++++++--------
>  mm/nommu.c             | 12 +++++++++---
>  mm/process_vm_access.c |  7 +++++--
>  virt/kvm/async_pf.c    |  3 ++-
>  virt/kvm/kvm_main.c    | 11 ++++++++---
>  6 files changed, 34 insertions(+), 19 deletions(-)
> 
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index e9caec6..2db98b6 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1285,8 +1285,7 @@ long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
>  		    int write, int force, struct page **pages, int *locked);
>  long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
>  			       unsigned long start, unsigned long nr_pages,
> -			       int write, int force, struct page **pages,
> -			       unsigned int gup_flags);
> +			       struct page **pages, unsigned int gup_flags);
>  long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
>  		    int write, int force, struct page **pages);
>  int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> diff --git a/mm/gup.c b/mm/gup.c
> index ba83942..3d620dd 100644
> --- a/mm/gup.c
> +++ b/mm/gup.c
> @@ -865,17 +865,11 @@ EXPORT_SYMBOL(get_user_pages_locked);
>   */
>  __always_inline long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
>  					       unsigned long start, unsigned long nr_pages,
> -					       int write, int force, struct page **pages,
> -					       unsigned int gup_flags)
> +					       struct page **pages, unsigned int gup_flags)
>  {
>  	long ret;
>  	int locked = 1;
>  
> -	if (write)
> -		gup_flags |= FOLL_WRITE;
> -	if (force)
> -		gup_flags |= FOLL_FORCE;
> -
>  	down_read(&mm->mmap_sem);
>  	ret = __get_user_pages_locked(tsk, mm, start, nr_pages, pages, NULL,
>  				      &locked, false, gup_flags);
> @@ -905,8 +899,15 @@ EXPORT_SYMBOL(__get_user_pages_unlocked);
>  long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
>  			     int write, int force, struct page **pages)
>  {
> +	unsigned int flags = FOLL_TOUCH;
> +
> +	if (write)
> +		flags |= FOLL_WRITE;
> +	if (force)
> +		flags |= FOLL_FORCE;
> +
>  	return __get_user_pages_unlocked(current, current->mm, start, nr_pages,
> -					 write, force, pages, FOLL_TOUCH);
> +					 pages, flags);
>  }
>  EXPORT_SYMBOL(get_user_pages_unlocked);
>  
> diff --git a/mm/nommu.c b/mm/nommu.c
> index 95daf81..925dcc1 100644
> --- a/mm/nommu.c
> +++ b/mm/nommu.c
> @@ -185,8 +185,7 @@ EXPORT_SYMBOL(get_user_pages_locked);
>  
>  long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
>  			       unsigned long start, unsigned long nr_pages,
> -			       int write, int force, struct page **pages,
> -			       unsigned int gup_flags)
> +			       struct page **pages, unsigned int gup_flags)
>  {
>  	long ret;
>  	down_read(&mm->mmap_sem);
> @@ -200,8 +199,15 @@ EXPORT_SYMBOL(__get_user_pages_unlocked);
>  long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
>  			     int write, int force, struct page **pages)
>  {
> +	unsigned int flags = 0;
> +
> +	if (write)
> +		flags |= FOLL_WRITE;
> +	if (force)
> +		flags |= FOLL_FORCE;
> +
>  	return __get_user_pages_unlocked(current, current->mm, start, nr_pages,
> -					 write, force, pages, 0);
> +					 pages, flags);
>  }
>  EXPORT_SYMBOL(get_user_pages_unlocked);
>  
> diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c
> index 07514d4..be8dc8d 100644
> --- a/mm/process_vm_access.c
> +++ b/mm/process_vm_access.c
> @@ -88,12 +88,16 @@ static int process_vm_rw_single_vec(unsigned long addr,
>  	ssize_t rc = 0;
>  	unsigned long max_pages_per_loop = PVM_MAX_KMALLOC_PAGES
>  		/ sizeof(struct pages *);
> +	unsigned int flags = FOLL_REMOTE;
>  
>  	/* Work out address and page range required */
>  	if (len == 0)
>  		return 0;
>  	nr_pages = (addr + len - 1) / PAGE_SIZE - addr / PAGE_SIZE + 1;
>  
> +	if (vm_write)
> +		flags |= FOLL_WRITE;
> +
>  	while (!rc && nr_pages && iov_iter_count(iter)) {
>  		int pages = min(nr_pages, max_pages_per_loop);
>  		size_t bytes;
> @@ -104,8 +108,7 @@ static int process_vm_rw_single_vec(unsigned long addr,
>  		 * current/current->mm
>  		 */
>  		pages = __get_user_pages_unlocked(task, mm, pa, pages,
> -						  vm_write, 0, process_pages,
> -						  FOLL_REMOTE);
> +						  process_pages, flags);
>  		if (pages <= 0)
>  			return -EFAULT;
>  
> diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c
> index db96688..8035cc1 100644
> --- a/virt/kvm/async_pf.c
> +++ b/virt/kvm/async_pf.c
> @@ -84,7 +84,8 @@ static void async_pf_execute(struct work_struct *work)
>  	 * mm and might be done in another context, so we must
>  	 * use FOLL_REMOTE.
>  	 */
> -	__get_user_pages_unlocked(NULL, mm, addr, 1, 1, 0, NULL, FOLL_REMOTE);
> +	__get_user_pages_unlocked(NULL, mm, addr, 1, NULL,
> +			FOLL_WRITE | FOLL_REMOTE);
>  
>  	kvm_async_page_present_sync(vcpu, apf);
>  
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 81dfc73..28510e7 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -1416,10 +1416,15 @@ static int hva_to_pfn_slow(unsigned long addr, bool *async, bool write_fault,
>  		down_read(&current->mm->mmap_sem);
>  		npages = get_user_page_nowait(addr, write_fault, page);
>  		up_read(&current->mm->mmap_sem);
> -	} else
> +	} else {
> +		unsigned int flags = FOLL_TOUCH | FOLL_HWPOISON;
> +
> +		if (write_fault)
> +			flags |= FOLL_WRITE;
> +
>  		npages = __get_user_pages_unlocked(current, current->mm, addr, 1,
> -						   write_fault, 0, page,
> -						   FOLL_TOUCH|FOLL_HWPOISON);
> +						   page, flags);
> +	}
>  	if (npages != 1)
>  		return npages;
>  
> 

Acked-by: Paolo Bonzini <pbonzini@redhat.com>

^ permalink raw reply

* Low network throughput on i.MX28
From: Lothar Waßmann @ 2016-10-13  6:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476313753.2065.11.camel@embedded.rocks>

Hi,

On Thu, 13 Oct 2016 01:09:13 +0200 J?rg Krause wrote:
> Hi,
> 
> I am using a custom i.MX28 board similar to the i.MX28-EVK. For Wi-Fi
> the board assembles a BCM43362 from Broadcom and for Ethernet a
> LAN8720A from Microchip. The board is running mainline Linux 4.7.
> 
> While both, wireless and wired network interfaces work, the TCP
> throughput measured with iperf is low.
> 
> The bandwith for Ethernet is between 20-30 MBits/sec and for WLAN is
> about 4-5 MBits/sec.
> 
> There exists an Application Note "i.MX28 Ethernet Performance on
> Linux" [1] which shows a bandwith of > 60 MBits/sec. A user an the NXP
> forum [2] told he achieved 20 MBits/sec with some Qualcom chip.
> 
> Note, that these values are most probably measured with the legacy
> Linux Kernel 2.6.35 from NXP.
> 
> Does anybody has done throughput tests on i.MX28 with mainline Kernel?
> If so, what are the results? What might be the bottleneck?
>

This is the iperf output on a TX28 with current mainline kernel
(4.8.0-rc5):
------------------------------------------------------------
Client connecting to 192.168.100.1, TCP port 5001
TCP window size: 43.8 KByte (default)
------------------------------------------------------------
[  3] local 192.168.100.56 port 60325 connected with 192.168.100.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec  57.5 MBytes  48.2 Mbits/sec

You might check your kernel DEBUG configs (especially
CONFIG_DEBUG_PAGEALLOC).


Lothar Wa?mann

^ permalink raw reply

* [PATCH 6/10] mmc: sdhci-xenon: Add Marvell Xenon SDHC core functionality
From: Ziji Hu @ 2016-10-13  5:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <7939a923-eb97-ca44-ac4c-f0a3cd4f45bc@intel.com>

Hi Adrian,

On 2016/10/12 21:07, Adrian Hunter wrote:
> On 12/10/16 14:58, Ziji Hu wrote:
>> Hi Adrian,
>>
>> 	Thank you very much for your review.
>> 	I will firstly fix the typo.
>>
>> On 2016/10/11 20:37, Adrian Hunter wrote:
<snip>
>>>> +
>>>> +static int xenon_start_signal_voltage_switch(struct mmc_host *mmc,
>>>> +					     struct mmc_ios *ios)
>>>> +{
>>>> +	struct sdhci_host *host = mmc_priv(mmc);
>>>> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>>> +	struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>>> +
>>>> +	/*
>>>> +	 * Before SD/SDIO set signal voltage, SD bus clock should be
>>>> +	 * disabled. However, sdhci_set_clock will also disable the Internal
>>>> +	 * clock in mmc_set_signal_voltage().
>>>> +	 * If Internal clock is disabled, the 3.3V/1.8V bit can not be updated.
>>>> +	 * Thus here manually enable internal clock.
>>>> +	 *
>>>> +	 * After switch completes, it is unnecessary to disable internal clock,
>>>> +	 * since keeping internal clock active obeys SD spec.
>>>> +	 */
>>>> +	enable_xenon_internal_clk(host);
>>>> +
>>>> +	if (priv->card_candidate) {
>>>
>>> mmc_power_up() calls __mmc_set_signal_voltage() calls
>>> host->ops->start_signal_voltage_switch so priv->card_candidate could be an
>>> invalid reference to an old card.
>>>
>>> So that's not going to work if the card changes - not only for removable
>>> cards but even for eMMC if init fails and retries.
>>>
>> 	As you point out, this piece of code have defects, even though it actually works on Marvell multiple platforms, unless eMMC card is removable.
>>
>> 	I can add a property to explicitly indicate eMMC type in DTS.
>> 	Then card_candidate access can be removed here.
>> 	Does it sounds more reasonable to you?
> 
> Sure
> 
>>
>>>> +		if (mmc_card_mmc(priv->card_candidate))
>>>> +			return xenon_emmc_signal_voltage_switch(mmc, ios);
>>>
>>> So if all you need to know is whether it is a eMMC, why can't DT tell you?
>>>
>> 	I can add an eMMC type property in DTS, to remove the card_candidate access here.
>>
>>>> +	}
>>>> +
>>>> +	return sdhci_start_signal_voltage_switch(mmc, ios);
>>>> +}
>>>> +
>>>> +/*
>>>> + * After determining which slot is used for SDIO,
>>>> + * some additional task is required.
>>>> + */
>>>> +static void xenon_init_card(struct mmc_host *mmc, struct mmc_card *card)
>>>> +{
>>>> +	struct sdhci_host *host = mmc_priv(mmc);
>>>> +	u32 reg;
>>>> +	u8 slot_idx;
>>>> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>>> +	struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>>> +
>>>> +	/* Link the card for delay adjustment */
>>>> +	priv->card_candidate = card;
>>>
>>> You really need a better way to get the card.  I suggest you take up the
>>> issue with Ulf.  One possibility is to have mmc core set host->card = card
>>> much earlier.
>>>
>> 	Could you please tell me if any issue related to card_candidate still exists, after the card_candidate is removed from xenon_start_signal_voltage_switch() in above?
>> 	It seems that when init_card is called, the structure card has already been updated and stable in MMC/SD/SDIO initialization sequence.
>> 	May I keep it here?
> 
> It works by accident rather than by design.  We can do better.
> 
	Could you please tell me some details which are satisfied about card_candidate?

	I must admit that card_candidate in xenon_start_signal_voltage_switch() is imperfect.
	But card_candidate in init_card() and later in set_ios() work by design, rather than by accident. We did a lot of tests on several platforms.
	
	The structure mmc_card passed in here is a stable one. Thus in my very own opinion, it is safe and stable to use mmc_card here.
	card_candidate is used only in card initialization. It is not active in later transfers after initialization is done.
	It will always updated with mmc_card in next card initialization.

>>
>>>> +	/* Set tuning functionality of this slot */
>>>> +	xenon_slot_tuning_setup(host);
>>>> +
>>>> +	slot_idx = priv->slot_idx;
>>>> +	if (!mmc_card_sdio(card)) {
>>>> +		/* Re-enable the Auto-CMD12 cap flag. */
>>>> +		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
>>>> +		host->flags |= SDHCI_AUTO_CMD12;
>>>> +
>>>> +		/* Clear SDIO Card Inserted indication */
>>>> +		reg = sdhci_readl(host, SDHC_SYS_CFG_INFO);
>>>> +		reg &= ~(1 << (slot_idx + SLOT_TYPE_SDIO_SHIFT));
>>>> +		sdhci_writel(host, reg, SDHC_SYS_CFG_INFO);
>>>> +
>>>> +		if (mmc_card_mmc(card)) {
>>>> +			mmc->caps |= MMC_CAP_NONREMOVABLE;
>>>> +			if (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V))
>>>> +				mmc->caps |= MMC_CAP_1_8V_DDR;
>>>> +			/*
>>>> +			 * Force to clear BUS_TEST to
>>>> +			 * skip bus_test_pre and bus_test_post
>>>> +			 */
>>>> +			mmc->caps &= ~MMC_CAP_BUS_WIDTH_TEST;
>>>> +			mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ |
>>>> +				      MMC_CAP2_PACKED_CMD;
>>>> +			if (mmc->caps & MMC_CAP_8_BIT_DATA)
>>>> +				mmc->caps2 |= MMC_CAP2_HS400_1_8V;
>>>> +		}
>>>> +	} else {
>>>> +		/*
>>>> +		 * Delete the Auto-CMD12 cap flag.
>>>> +		 * Otherwise, when sending multi-block CMD53,
>>>> +		 * Driver will set Transfer Mode Register to enable Auto CMD12.
>>>> +		 * However, SDIO device cannot recognize CMD12.
>>>> +		 * Thus SDHC will time-out for waiting for CMD12 response.
>>>> +		 */
>>>> +		host->quirks &= ~SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
>>>> +		host->flags &= ~SDHCI_AUTO_CMD12;
>>>
>>> sdhci_set_transfer_mode() won't enable auto-CMD12 for CMD53 anyway, so is
>>> this needed?
>>>
>> 	In Xenon driver, Auto-CMD12 flag is set to enable full support to Auto-CMD feature, both Auto-CMD12 and Auto-CMD23.
>> 	As a result, when Xenon SDHC slot can both support SD and SDIO, Auto-CMD12 is disabled when SDIO card is inserted, and renabled when SD is inserted.
>>
>> 	I recheck the sdhci code to set Auto-CMD bit in Transfer Mode register, in sdhci_set_transfer_mode():
>> 	if (mmc_op_multi(cmd->opcode) || data->blocks > 1)
>> 	As you can see, as long as it is CMD18/CMD25 OR there are multiple data blocks, Auto-CMD field will be set.
>> 	CMD53 doesn't have CMD23. Thus Auto-CMD12 is selected since Auto-CMD12 flag is set.
>> 	Thus I have to clear Auto-CMD12 to avoid issuing Auto-CMD12 in SDIO transfer.
> 
> 
> The code is:
> 
> 	if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {
> 		mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;
> 		/*
> 		 * If we are sending CMD23, CMD12 never gets sent
> 		 * on successful completion (so no Auto-CMD12).
> 		 */
> 		if (sdhci_auto_cmd12(host, cmd->mrq) &&
> 		    (cmd->opcode != SD_IO_RW_EXTENDED))
> 			mode |= SDHCI_TRNS_AUTO_CMD12;
> 		else if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {
> 			mode |= SDHCI_TRNS_AUTO_CMD23;
> 			sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);
> 		}
> 	}
> 
> You can see the check for SD_IO_RW_EXTENDED which is CMD53.
> 
	Sorry. I didn't notice CMD53 check was added.
	I introduced this Auto-CMD12 hack since kernel 3.8. It seems that this check is not added in kernel 3.8.
	Thanks for the information. I will remove the Auto-CMD12 hack.

>>
>> 	I just meet a similar issue in RPMB.
>> 	When Auto-CMD12 flag is set, eMMC RPMB access will trigger Auto-CMD12, since CMD25 is in use.
>> 	It will cause RPMB access failed.
> 
> Can you explain more about the RPMB issue.  Doesn't it use CMD23, so CMD12
> wouldn't be used - auto or manually.
> 
	RPMB go through the MMC ioctl routine.
	Unlike normal data transfer, MMC ioctl for RPMB explicitly issues CMD23. When CMD25 is issued, there is neither data->sbc nor Auto-CMD23.
	As a result, sdhci driver will automatically enable Auto-CMD12 for RPMB CMD25 if Auto-CMD12 flag is set.

>>
>> 	One possible solution is to drop Auto-CMD12 support and use Auto-CMD23 only, in Xenon driver.
>> 	May I know you opinion, please?
> 
> I don't use auto-CMD12 because I don't know if it provides any benefit and
> sdhci does not seem to have implemented Auto CMD12 Error Recovery, although
> I have never looked at it closely.
>
	Actually, Auto-CMD23 is always used on our Xenon. Auto-CMD12 is not used at all.
	But since this driver is a general one for all Marvell products, Auto-CMD12 is also supported in case that Auto-CMD23 is not available.
 

^ permalink raw reply

* [PATCH 3/3] ARM: dts: mt2701: Add mtk-cirq node for mt2701
From: Youlin Pei @ 2016-10-13  5:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476335194-26604-1-git-send-email-youlin.pei@mediatek.com>

This commit add mtk-cirq node to mt2701 dtsi.

Signed-off-by: Youlin Pei <youlin.pei@mediatek.com>
---
 arch/arm/boot/dts/mt2701.dtsi |   11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 7eab6f4..a314df9 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -21,7 +21,7 @@
 
 / {
 	compatible = "mediatek,mt2701";
-	interrupt-parent = <&sysirq>;
+	interrupt-parent = <&cirq>;
 
 	cpus {
 		#address-cells = <1>;
@@ -158,6 +158,15 @@
 		reg = <0 0x10200100 0 0x1c>;
 	};
 
+	cirq: interrupt-controller at 10204000 {
+		compatible = "mediatek,mt2701-cirq";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&sysirq>;
+		reg = <0 0x10204000 0 0x4000>;
+		mediatek,ext-irq-start = <32>;
+	};
+
 	apmixedsys: syscon at 10209000 {
 		compatible = "mediatek,mt2701-apmixedsys", "syscon";
 		reg = <0 0x10209000 0 0x1000>;
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 2/3] irqchip: mtk-cirq: Add mediatek mtk-cirq implement
From: Youlin Pei @ 2016-10-13  5:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476335194-26604-1-git-send-email-youlin.pei@mediatek.com>

This commit add the mtk-cirq implement for mt2701.

Signed-off-by: Youlin Pei <youlin.pei@mediatek.com>
---
 drivers/irqchip/Makefile       |    2 +-
 drivers/irqchip/irq-mtk-cirq.c |  257 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 258 insertions(+), 1 deletion(-)
 create mode 100644 drivers/irqchip/irq-mtk-cirq.c

diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 4c203b6..eee95c6 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -59,7 +59,7 @@ obj-$(CONFIG_BCM7120_L2_IRQ)		+= irq-bcm7120-l2.o
 obj-$(CONFIG_BRCMSTB_L2_IRQ)		+= irq-brcmstb-l2.o
 obj-$(CONFIG_KEYSTONE_IRQ)		+= irq-keystone.o
 obj-$(CONFIG_MIPS_GIC)			+= irq-mips-gic.o
-obj-$(CONFIG_ARCH_MEDIATEK)		+= irq-mtk-sysirq.o
+obj-$(CONFIG_ARCH_MEDIATEK)		+= irq-mtk-sysirq.o irq-mtk-cirq.o
 obj-$(CONFIG_ARCH_DIGICOLOR)		+= irq-digicolor.o
 obj-$(CONFIG_RENESAS_H8300H_INTC)	+= irq-renesas-h8300h.o
 obj-$(CONFIG_RENESAS_H8S_INTC)		+= irq-renesas-h8s.o
diff --git a/drivers/irqchip/irq-mtk-cirq.c b/drivers/irqchip/irq-mtk-cirq.c
new file mode 100644
index 0000000..544767d
--- /dev/null
+++ b/drivers/irqchip/irq-mtk-cirq.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Youlin.Pei <youlin.pei@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
+
+#define CIRQ_MASK_SET	0xC0
+#define CIRQ_MASK_CLR	0x100
+#define CIRQ_SENS_SET	0x180
+#define CIRQ_SENS_CLR	0x1C0
+#define CIRQ_POL_SET	0x240
+#define CIRQ_POL_CLR	0x280
+#define CIRQ_CONTROL	0x300
+
+#define CIRQ_EN		0x1
+#define CIRQ_EDGE	0x2
+#define CIRQ_FLUSH	0x4
+
+#define CIRQ_IRQ_NUM    0x200
+
+struct mtk_cirq_chip_data {
+	void __iomem *base;
+	unsigned int ext_irq_start;
+};
+
+struct mtk_cirq_chip_data *cirq_data;
+
+static void mtk_cirq_write_mask(struct irq_data *data, unsigned int offset)
+{
+	struct mtk_cirq_chip_data *chip_data = data->chip_data;
+	unsigned int cirq_num = data->hwirq - chip_data->ext_irq_start;
+	u32 mask = 1 << (cirq_num % 32);
+
+	writel(mask, chip_data->base + offset + (cirq_num / 32) * 4);
+}
+
+static void mtk_cirq_mask(struct irq_data *data)
+{
+	mtk_cirq_write_mask(data, CIRQ_MASK_SET);
+	irq_chip_mask_parent(data);
+}
+
+static void mtk_cirq_unmask(struct irq_data *data)
+{
+	mtk_cirq_write_mask(data, CIRQ_MASK_CLR);
+	irq_chip_unmask_parent(data);
+}
+
+static int mtk_cirq_set_type(struct irq_data *data, unsigned int type)
+{
+	int ret;
+
+	switch (type & IRQ_TYPE_SENSE_MASK) {
+	case IRQ_TYPE_EDGE_FALLING:
+		mtk_cirq_write_mask(data, CIRQ_POL_CLR);
+		mtk_cirq_write_mask(data, CIRQ_SENS_CLR);
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		mtk_cirq_write_mask(data, CIRQ_POL_SET);
+		mtk_cirq_write_mask(data, CIRQ_SENS_CLR);
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		mtk_cirq_write_mask(data, CIRQ_POL_CLR);
+		mtk_cirq_write_mask(data, CIRQ_SENS_SET);
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		mtk_cirq_write_mask(data, CIRQ_POL_SET);
+		mtk_cirq_write_mask(data, CIRQ_SENS_SET);
+		break;
+	default:
+		break;
+	}
+
+	data = data->parent_data;
+	ret = data->chip->irq_set_type(data, type);
+	return ret;
+}
+
+static struct irq_chip mtk_cirq_chip = {
+	.name			= "MT_CIRQ",
+	.irq_mask		= mtk_cirq_mask,
+	.irq_unmask		= mtk_cirq_unmask,
+	.irq_eoi		= irq_chip_eoi_parent,
+	.irq_set_type		= mtk_cirq_set_type,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	= irq_chip_set_affinity_parent,
+#endif
+};
+
+static int mtk_cirq_domain_translate(struct irq_domain *d,
+				     struct irq_fwspec *fwspec,
+				     unsigned long *hwirq,
+				     unsigned int *type)
+{
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;
+
+		/* No PPI should point to this domain */
+		if (fwspec->param[0] != 0)
+			return -EINVAL;
+
+		/* cirq support irq number check */
+		if (fwspec->param[1] < cirq_data->ext_irq_start)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[1];
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int mtk_cirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+				 unsigned int nr_irqs, void *arg)
+{
+	int i;
+	irq_hw_number_t hwirq;
+	struct irq_fwspec *fwspec = arg;
+	struct irq_fwspec parent_fwspec = *fwspec;
+
+	if (fwspec->param_count != 3)
+		return -EINVAL;
+
+	/* cirq doesn't support PPI */
+	if (fwspec->param[0])
+		return -EINVAL;
+
+	if (fwspec->param[1] < cirq_data->ext_irq_start)
+		return -EINVAL;
+
+	hwirq = fwspec->param[1];
+	for (i = 0; i < nr_irqs; i++)
+		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+					      &mtk_cirq_chip,
+					      domain->host_data);
+
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
+}
+
+static const struct irq_domain_ops cirq_domain_ops = {
+	.translate	= mtk_cirq_domain_translate,
+	.alloc		= mtk_cirq_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int mtk_cirq_suspend(void)
+{
+	u32 value;
+
+	/* set edge_only mode, record edge-triggerd interrupts */
+	/* enable cirq */
+	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
+	value |= (CIRQ_EDGE | CIRQ_EN);
+	writel(value, cirq_data->base + CIRQ_CONTROL);
+	return 0;
+}
+
+static void mtk_cirq_resume(void)
+{
+	u32 value;
+
+	/* flush recored interrupts, will send signals to parent controller */
+	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
+	writel(value | CIRQ_FLUSH, cirq_data->base + CIRQ_CONTROL);
+
+	/* disable cirq */
+	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
+	value &= ~(CIRQ_EDGE | CIRQ_EN);
+	writel(value, cirq_data->base + CIRQ_CONTROL);
+}
+
+static struct syscore_ops mtk_cirq_syscore_ops = {
+	.suspend	= mtk_cirq_suspend,
+	.resume		= mtk_cirq_resume,
+};
+
+static void mtk_cirq_syscore_init(void)
+{
+	register_syscore_ops(&mtk_cirq_syscore_ops);
+}
+#else
+static inline void mtk_cirq_syscore_init(void) {}
+#endif
+
+static int __init mtk_cirq_of_init(struct device_node *node,
+				   struct device_node *parent)
+{
+	struct irq_domain *domain, *domain_parent;
+	int ret;
+
+	domain_parent = irq_find_host(parent);
+	if (!domain_parent) {
+		pr_err("mtk_cirq: interrupt-parent not found\n");
+		return -EINVAL;
+	}
+
+	cirq_data = kzalloc(sizeof(*cirq_data), GFP_KERNEL);
+	if (!cirq_data)
+		return -ENOMEM;
+
+	cirq_data->base = of_iomap(node, 0);
+	if (!cirq_data->base) {
+		pr_err("mtk_cirq: unable to map cirq register\n");
+		ret = -ENXIO;
+		goto out_free;
+	}
+
+	if (of_property_read_u32(node, "mediatek,ext-irq-start",
+				 &cirq_data->ext_irq_start)) {
+		ret = -EINVAL;
+		goto out_free;
+	}
+
+	domain = irq_domain_add_hierarchy(domain_parent, 0, CIRQ_IRQ_NUM, node,
+					  &cirq_domain_ops, cirq_data);
+	if (!domain) {
+		ret = -ENOMEM;
+		goto out_unmap;
+	}
+
+	mtk_cirq_syscore_init();
+
+	return 0;
+
+out_unmap:
+	iounmap(cirq_data->base);
+out_free:
+	kfree(cirq_data);
+	return ret;
+}
+
+IRQCHIP_DECLARE(mtk_cirq, "mediatek,mt2701-cirq", mtk_cirq_of_init);
-- 
1.7.9.5

^ permalink raw reply related


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