Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* aarch64 ACPI boot regressed by commit 7ba5f605f3a0 ("arm64/numa: remove the limitation that cpu0 must bind to node0")
From: Lorenzo Pieralisi @ 2016-10-14 15:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <b8b58d52-691c-11f0-2d26-a51e03430771@redhat.com>

On Fri, Oct 14, 2016 at 05:27:58PM +0200, Laszlo Ersek wrote:
> On 10/14/16 17:01, Laszlo Ersek wrote:
> 
> > Maybe the code I
> > tried to analyze in this email was never *meant* to associate CPU#0 with
> > any NUMA node at all (not even node 0); instead, other code -- for
> > example code removed by 7ba5f605f3a0 -- was meant to perform that
> > association.
> 
> Staring a bit more at the code, this looks very likely; in acpi_map_gic_cpu_interface() we have
> 
> > 	/* Check if GICC structure of boot CPU is available in the MADT */
> > 	if (cpu_logical_map(0) == hwid) {
> > 		if (bootcpu_valid) {
> > 			pr_err("duplicate boot CPU MPIDR: 0x%llx in MADT\n",
> > 			       hwid);
> > 			return;
> > 		}
> > 		bootcpu_valid = true;
> > 		return;
> > 	}
> 
> which means that this callback function (for parsing the GICC
> structures in the MADT) expects to find the boot processor as well.
> 
> Upon finding the boot processor, we set bootcpu_valid to true, and
> that's it -- no association with any NUMA node, and no incrementing of
> "cpu_count".

Yes, because that's to check the MADT contains the boot cpu hwid.

Does this help (compile tested only) ?

-- >8 -- 
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index d3f151c..8507703 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -544,6 +544,7 @@ static int __init smp_cpu_setup(int cpu)
 			return;
 		}
 		bootcpu_valid = true;
+		early_map_cpu_to_node(0, acpi_numa_get_nid(0, hwid));
 		return;
 	}
 

^ permalink raw reply related

* aarch64 ACPI boot regressed by commit 7ba5f605f3a0 ("arm64/numa: remove the limitation that cpu0 must bind to node0")
From: Laszlo Ersek @ 2016-10-14 15:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161014134411.cgba46xpznceucta@hawk.localdomain>

On 10/14/16 15:44, Andrew Jones wrote:
> On Fri, Oct 14, 2016 at 03:18:00PM +0200, Laszlo Ersek wrote:
>> On 10/14/16 10:05, Andrew Jones wrote:
>>> On Fri, Oct 14, 2016 at 12:50:29AM +0200, Laszlo Ersek wrote:
>>>> (4) Analysis (well, a lame attempt at that, because I have zero
>>>> familiarity with this code). Let me quote the patch:
>>>>
>>>>> commit 7ba5f605f3a0d9495aad539eeb8346d726dfc183
>>>>> Author: Zhen Lei <thunder.leizhen@huawei.com>
>>>>> Date:   Thu Sep 1 14:55:04 2016 +0800
>>>>>
>>>>>     arm64/numa: remove the limitation that cpu0 must bind to node0
>>>>>
>>>>>     1. Remove the old binding code.
>>>>>     2. Read the nid of cpu0 from dts.
>>>>>     3. Fallback the nid of cpu0 to 0 when numa=off is set in bootargs.
>>>>>
>>>>>     Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
>>>>>     Signed-off-by: Will Deacon <will.deacon@arm.com>
>>>>>
>>>>> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
>>>>> index c3c08368a685..8b048e6ec34a 100644
>>>>> --- a/arch/arm64/kernel/smp.c
>>>>> +++ b/arch/arm64/kernel/smp.c
>>>>> @@ -624,6 +624,7 @@ static void __init of_parse_and_init_cpus(void)
>>>>>  			}
>>>>>
>>>>>  			bootcpu_valid = true;
>>>>> +			early_map_cpu_to_node(0, of_node_to_nid(dn));
>>>>>
>>>>>  			/*
>>>>>  			 * cpu_logical_map has already been
>>>>> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
>>>>> index 0a15f010b64a..778a985c8a70 100644
>>>>> --- a/arch/arm64/mm/numa.c
>>>>> +++ b/arch/arm64/mm/numa.c
>>>>> @@ -116,16 +116,24 @@ static void __init setup_node_to_cpumask_map(void)
>>>>>   */
>>>>>  void numa_store_cpu_info(unsigned int cpu)
>>>>>  {
>>>>> -	map_cpu_to_node(cpu, numa_off ? 0 : cpu_to_node_map[cpu]);
>>>>> +	map_cpu_to_node(cpu, cpu_to_node_map[cpu]);
>>>>>  }
>>>>>
>>>>>  void __init early_map_cpu_to_node(unsigned int cpu, int nid)
>>>>>  {
>>>>>  	/* fallback to node 0 */
>>>>> -	if (nid < 0 || nid >= MAX_NUMNODES)
>>>>> +	if (nid < 0 || nid >= MAX_NUMNODES || numa_off)
>>>>>  		nid = 0;
>>>
>>> The ACPI equivalent code must be missing (at least) the above, because,
>>> even with DT, mach-virt won't have cpu to node mappings unless numa
>>> is configured on the command line. Can you try adding something like
>>>
>>>     -m 512 -smp 4 \
>>>     -numa node,mem=256M,cpus=0-1,nodeid=0 \
>>>     -numa node,mem=256M,cpus=2-3,nodeid=1
>>>
>>> to your QEMU command line?
>>
>> I added the following to my domain XML, under <cpu>:
>>
>>     <numa>
>>       <cell id='0' cpus='0-1' memory='2097152' unit='KiB'/>
>>       <cell id='1' cpus='2-3' memory='2097152' unit='KiB'/>
>>     </numa>
>>
>> (See <http://libvirt.org/formatdomain.html#elementsCPU>.)
>>
>> With that, each NUMA node gets half of the VCPUs and half of the guest RAM.
>>
>> (This is in a different guest now, one that has a bleeding edge Fedora kernel -- I didn't want to rebuild the upstream kernel yet again, just for this test. So, "4.9.0-0.rc0.git7.1.fc26.aarch64" is based on upstream v4.8-14109-g1573d2c, and it reproduces the problem too.)
>>
>>> Then when you boot with ACPI you'll get a
>>> SRAT.
>>
>> Yes, that's confirmed by the guest kernel log (see below).
>>
>>> If that works, then we're just missing the "no SRAT, nid = 0"
>>> code (that should have been added with this patch)
>>
>> It still crashes with the SRAT, with the following log:
> 
> Rats.
> 
>> Note the warning message (from wq_numa_init()):
>>
>>   workqueue: NUMA node mapping not available for cpu0, disabling NUMA support
>>
>> Something looks genuinely broken with the cpu <-> numa-node associations in the ACPI case -- it even seems to fail when the SRAT does exist.
>>
>> So, perhaps, commit 7ba5f605f3a0 may not have introduced the bug, only exposed one in the ACPI code?...
> 
> The kernel's ACPI NUMA support used to work. It was the test case for
> QEMU's SRAT generation code.
> 
> Two more experiments I wouldn't mind having you try, if you have time;
>  1) confirm that this NUMA configured guest and this latest kernel works
>     with DT. This is just for sanity, but I guess it will.

Yes, it boots fine. It's at v4.8-14604-g29fbff8.

>  2) If (1) succeeds, then try the last-known-good kernel with ACPI again,
>     but this time with the NUMA configured guest.

v4.8, which was my known-good starting point in the acpi=force bisection -- at that time without using a NUMA configuration --, also boots fine under this two-node NUMA configuration, using acpi=force:

> EFI stub: Booting Linux Kernel...
> EFI stub: Using DTB from configuration table
> EFI stub: Exiting boot services and installing virtual address map...
> [    0.000000] Booting Linux on physical CPU 0x0
> [    0.000000] Linux version 4.8.0 (root at aarch64-vgpu-1) (gcc version 6.2.1 20160916 (Red Hat 6.2.1-2) (GCC) ) #2 SMP Thu Oct 13 17:17:59 CEST 2016
> [    0.000000] Boot CPU: AArch64 Processor [500f0000]
> [    0.000000] earlycon: pl11 at MMIO 0x0000000009000000 (options '')
> [    0.000000] bootconsole [pl11] enabled
> [    0.000000] debug: ignoring loglevel setting.
> [    0.000000] efi: Getting EFI parameters from FDT:
> [    0.000000] efi: EFI v2.60 by EDK II
> [    0.000000] efi:  SMBIOS 3.0=0x13bdb0000  ACPI 2.0=0x1386d0000  MEMATTR=0x13a665018
> [    0.000000] cma: Reserved 512 MiB at 0x00000000c0000000
> [    0.000000] ACPI: Early table checksum verification disabled
> [    0.000000] ACPI: RSDP 0x00000001386D0000 000024 (v02 BOCHS )
> [    0.000000] ACPI: XSDT 0x00000001386C0000 000054 (v01 BOCHS  BXPCFACP 00000001      01000013)
> [    0.000000] ACPI: FACP 0x0000000138410000 00010C (v05 BOCHS  BXPCFACP 00000001 BXPC 00000001)
> [    0.000000] ACPI: DSDT 0x0000000138420000 001159 (v02 BOCHS  BXPCDSDT 00000001 BXPC 00000001)
> [    0.000000] ACPI: APIC 0x0000000138400000 0002BC (v03 BOCHS  BXPCAPIC 00000001 BXPC 00000001)
> [    0.000000] ACPI: GTDT 0x00000001383F0000 000060 (v02 BOCHS  BXPCGTDT 00000001 BXPC 00000001)
> [    0.000000] ACPI: MCFG 0x00000001383E0000 00003C (v01 BOCHS  BXPCMCFG 00000001 BXPC 00000001)
> [    0.000000] ACPI: SPCR 0x00000001383D0000 000050 (v02 BOCHS  BXPCSPCR 00000001 BXPC 00000001)
> [    0.000000] ACPI: SRAT 0x00000001383C0000 000110 (v03 BOCHS  BXPCSRAT 00000001 BXPC 00000001)
> [    0.000000] ACPI: NUMA: SRAT: PXM 0 -> MPIDR 0x0 -> Node 0
> [    0.000000] ACPI: NUMA: SRAT: PXM 0 -> MPIDR 0x1 -> Node 0
> [    0.000000] ACPI: NUMA: SRAT: PXM 0 -> MPIDR 0x2 -> Node 0
> [    0.000000] ACPI: NUMA: SRAT: PXM 0 -> MPIDR 0x3 -> Node 0
> [    0.000000] ACPI: NUMA: SRAT: PXM 1 -> MPIDR 0x4 -> Node 1
> [    0.000000] ACPI: NUMA: SRAT: PXM 1 -> MPIDR 0x5 -> Node 1
> [    0.000000] ACPI: NUMA: SRAT: PXM 1 -> MPIDR 0x6 -> Node 1
> [    0.000000] ACPI: NUMA: SRAT: PXM 1 -> MPIDR 0x7 -> Node 1
> [    0.000000] NUMA: Adding memblock [0x40000000 - 0x13fffffff] on node 0
> [    0.000000] ACPI: SRAT: Node 0 PXM 0 [mem 0x40000000-0x13fffffff]
> [    0.000000] NUMA: Adding memblock [0x140000000 - 0x23fffffff] on node 1
> [    0.000000] ACPI: SRAT: Node 1 PXM 1 [mem 0x140000000-0x23fffffff]
> [    0.000000] NUMA: Initmem setup node 0 [mem 0x40000000-0x13fffffff]
> [    0.000000] NUMA: NODE_DATA [mem 0x13fff2580-0x13fffffff]
> [    0.000000] NUMA: Initmem setup node 1 [mem 0x140000000-0x23fffffff]
> [    0.000000] NUMA: NODE_DATA [mem 0x23fff2580-0x23fffffff]
> [    0.000000] Zone ranges:
> [    0.000000]   DMA      [mem 0x0000000040000000-0x00000000ffffffff]
> [    0.000000]   Normal   [mem 0x0000000100000000-0x000000023fffffff]
> [    0.000000] Movable zone start for each node
> [    0.000000] Early memory node ranges
> [    0.000000]   node   0: [mem 0x0000000040000000-0x00000000fffeffff]
> [    0.000000]   node   0: [mem 0x00000000ffff0000-0x00000000ffffffff]
> [    0.000000]   node   0: [mem 0x0000000100000000-0x00000001383bffff]
> [    0.000000]   node   0: [mem 0x00000001383c0000-0x000000013874ffff]
> [    0.000000]   node   0: [mem 0x0000000138750000-0x000000013bc1ffff]
> [    0.000000]   node   0: [mem 0x000000013bc20000-0x000000013bffffff]
> [    0.000000]   node   0: [mem 0x000000013c000000-0x000000013fffffff]
> [    0.000000]   node   1: [mem 0x0000000140000000-0x000000023fffffff]
> [    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x000000013fffffff]
> [    0.000000] On node 0 totalpages: 65536
> [    0.000000]   DMA zone: 48 pages used for memmap
> [    0.000000]   DMA zone: 0 pages reserved
> [    0.000000]   DMA zone: 49152 pages, LIFO batch:1
> [    0.000000]   Normal zone: 16 pages used for memmap
> [    0.000000]   Normal zone: 16384 pages, LIFO batch:1
> [    0.000000] Initmem setup node 1 [mem 0x0000000140000000-0x000000023fffffff]
> [    0.000000] On node 1 totalpages: 65536
> [    0.000000]   Normal zone: 64 pages used for memmap
> [    0.000000]   Normal zone: 65536 pages, LIFO batch:1
> [    0.000000] psci: probing for conduit method from ACPI.
> [    0.000000] psci: PSCIv0.2 detected in firmware.
> [    0.000000] psci: Using standard PSCI v0.2 function IDs
> [    0.000000] psci: Trusted OS migration not required
> [    0.000000] percpu: Embedded 3 pages/cpu @fffffe01ffdc0000 s117320 r8192 d71096 u196608
> [    0.000000] pcpu-alloc: s117320 r8192 d71096 u196608 alloc=3*65536
> [    0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 [0] 4 [0] 5 [0] 6 [0] 7
> [    0.000000] Detected PIPT I-cache on CPU0
> [    0.000000] Built 2 zonelists in Node order, mobility grouping on.  Total pages: 130944
> [    0.000000] Policy zone: Normal
> [    0.000000] Kernel command line: BOOT_IMAGE=/vmlinuz-4.8.0 root=/dev/mapper/fedora-root ro rd.lvm.lv=fedora/root rd.lvm.lv=fedora/swap console=ttyAMA0 earlyprintk=pl011,0x9000000 earlycon ignore_loglevel acpi=force
> [    0.000000] PID hash table entries: 4096 (order: -1, 32768 bytes)
> [    0.000000] software IO TLB [mem 0xfbfe0000-0xfffe0000] (64MB) mapped at [fffffe00bbfe0000-fffffe00bffdffff]
> [    0.000000] Memory: 7717184K/8388608K available (8956K kernel code, 1565K rwdata, 3712K rodata, 1536K init, 15876K bss, 147136K reserved, 524288K cma-reserved)
> [    0.000000] Virtual kernel memory layout:
> [    0.000000]     modules : 0xfffffc0000000000 - 0xfffffc0008000000   (   128 MB)
> [    0.000000]     vmalloc : 0xfffffc0008000000 - 0xfffffdff5fff0000   (  2045 GB)
> [    0.000000]       .text : 0xfffffc0008080000 - 0xfffffc0008940000   (  8960 KB)
> [    0.000000]     .rodata : 0xfffffc0008940000 - 0xfffffc0008cf0000   (  3776 KB)
> [    0.000000]       .init : 0xfffffc0008cf0000 - 0xfffffc0008e70000   (  1536 KB)
> [    0.000000]       .data : 0xfffffc0008e70000 - 0xfffffc0008ff7400   (  1565 KB)
> [    0.000000]        .bss : 0xfffffc0008ff7400 - 0xfffffc0009f78628   ( 15877 KB)
> [    0.000000]     fixed   : 0xfffffdff7e7d0000 - 0xfffffdff7ec00000   (  4288 KB)
> [    0.000000]     PCI I/O : 0xfffffdff7ee00000 - 0xfffffdff7fe00000   (    16 MB)
> [    0.000000]     vmemmap : 0xfffffdff80000000 - 0xfffffe0000000000   (     2 GB maximum)
> [    0.000000]               0xfffffdff80000000 - 0xfffffdff80800000   (     8 MB actual)
> [    0.000000]     memory  : 0xfffffe0000000000 - 0xfffffe0200000000   (  8192 MB)
> [    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8, Nodes=2
> [    0.000000] Running RCU self tests
> [    0.000000] Hierarchical RCU implementation.
> [    0.000000] 	RCU lockdep checking is enabled.
> [    0.000000] 	Build-time adjustment of leaf fanout to 64.
> [    0.000000] 	RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=8.
> [    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=8
> [    0.000000] kmemleak: Kernel memory leak detector disabled
> [    0.000000] NR_IRQS:64 nr_irqs:64 0
> [    0.000000] GICv2m: ACPI overriding V2M MSI_TYPER (base:80, num:64)
> [    0.000000] GICv2m: range[mem 0x08020000-0x08020fff], SPI[80:143]
> [    0.000000] GIC: PPI11 is secure or misconfigured
> [    0.000000] arm_arch_timer: WARNING: Invalid trigger for IRQ3, assuming level low
> [    0.000000] arm_arch_timer: WARNING: Please fix your firmware
> [    0.000000] arm_arch_timer: Architected cp15 timer(s) running at 50.00MHz (virt).
> [    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0xb8812736b, max_idle_ns: 440795202655 ns
> [    0.000002] sched_clock: 56 bits at 50MHz, resolution 20ns, wraps every 4398046511100ns
> [    0.002263] Console: colour dummy device 80x25
> [    0.003385] Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar
> [    0.005291] ... MAX_LOCKDEP_SUBCLASSES:  8
> [    0.006233] ... MAX_LOCK_DEPTH:          48
> [    0.007335] ... MAX_LOCKDEP_KEYS:        8191
> [    0.008339] ... CLASSHASH_SIZE:          4096
> [    0.009334] ... MAX_LOCKDEP_ENTRIES:     32768
> [    0.010497] ... MAX_LOCKDEP_CHAINS:      65536
> [    0.011517] ... CHAINHASH_SIZE:          32768
> [    0.012541]  memory used by lock dependency info: 8159 kB
> [    0.013810]  per task-struct memory footprint: 1920 bytes
> [    0.015809] mempolicy: Enabling automatic NUMA balancing. Configure with numa_balancing= or the kernel.numa_balancing sysctl
> [    0.018762] Calibrating delay loop (skipped), value calculated using timer frequency.. 100.00 BogoMIPS (lpj=50000)
> [    0.021262] pid_max: default: 32768 minimum: 301
> [    0.022804] ACPI: Core revision 20160422
> [    0.027895] ACPI: 1 ACPI AML tables successfully acquired and loaded
> [    0.029485]
> [    0.030614] Security Framework initialized
> [    0.031599] Yama: becoming mindful.
> [    0.032422] SELinux:  Initializing.
> [    0.033949] SELinux:  Starting in permissive mode
> [    0.035498] Dentry cache hash table entries: 1048576 (order: 7, 8388608 bytes)
> [    0.039287] Inode-cache hash table entries: 524288 (order: 6, 4194304 bytes)
> [    0.042406] Mount-cache hash table entries: 16384 (order: 1, 131072 bytes)
> [    0.044138] Mountpoint-cache hash table entries: 16384 (order: 1, 131072 bytes)
> [    0.047820] ftrace: allocating 28926 entries in 8 pages
> [    0.082086] ASID allocator initialised with 65536 entries
> [    0.086231] Remapping and enabling EFI services.
> [    0.087582]   EFI remap 0x0000000004000000 => 0000000020000000
> [    0.089058]   EFI remap 0x0000000009010000 => 0000000024000000
> [    0.090486]   EFI remap 0x0000000138430000 => 0000000024010000
> [    0.091877]   EFI remap 0x0000000138490000 => 0000000024070000
> [    0.093269]   EFI remap 0x00000001384e0000 => 00000000240c0000
> [    0.094687]   EFI remap 0x0000000138530000 => 0000000024110000
> [    0.096076]   EFI remap 0x0000000138580000 => 0000000024160000
> [    0.097471]   EFI remap 0x00000001385d0000 => 00000000241b0000
> [    0.098855]   EFI remap 0x0000000138620000 => 0000000024200000
> [    0.100243]   EFI remap 0x0000000138670000 => 0000000024250000
> [    0.101638]   EFI remap 0x00000001386e0000 => 00000000242a0000
> [    0.103022]   EFI remap 0x000000013bc20000 => 0000000024310000
> [    0.104420]   EFI remap 0x000000013bdb0000 => 00000000244a0000
> [    0.120433] Detected PIPT I-cache on CPU1
> [    0.120539] CPU1: Booted secondary processor [500f0000]
> [    0.134831] Detected PIPT I-cache on CPU2
> [    0.134918] CPU2: Booted secondary processor [500f0000]
> [    0.149136] Detected PIPT I-cache on CPU3
> [    0.149226] CPU3: Booted secondary processor [500f0000]
> [    0.163487] Detected PIPT I-cache on CPU4
> [    0.163576] CPU4: Booted secondary processor [500f0000]
> [    0.177837] Detected PIPT I-cache on CPU5
> [    0.177926] CPU5: Booted secondary processor [500f0000]
> [    0.192172] Detected PIPT I-cache on CPU6
> [    0.192260] CPU6: Booted secondary processor [500f0000]
> [    0.206722] Detected PIPT I-cache on CPU7
> [    0.206811] CPU7: Booted secondary processor [500f0000]
> [    0.207003] Brought up 8 CPUs
> [    0.223904] SMP: Total of 8 processors activated.
> [    0.225110] CPU features: detected feature: 32-bit EL0 Support
> [    0.226534] CPU: All CPU(s) started at EL1
> [    0.319814] devtmpfs: initialized
> [    0.321977] SMBIOS 3.0.0 present.
> [    0.323394] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275000 ns
> [    0.331773] atomic64_test: passed
> [    0.332749] pinctrl core: initialized pinctrl subsystem
> [    0.335763] NET: Registered protocol family 16
> [    0.342141] cpuidle: using governor menu
> [    0.343192] PCCT header not found.
> [    0.344082] vdso: 2 pages (1 code @ fffffc0008960000, 1 data @ fffffc0008e90000)
> [    0.346114] hw-breakpoint: found 4 breakpoint and 4 watchpoint registers.
> [    0.349683] DMA: preallocated 256 KiB pool for atomic allocations
> [    0.351473] ACPI: bus type PCI registered
> [    0.352483] acpiphp: ACPI Hot Plug PCI Controller Driver version: 0.5
> [    0.354595] Serial: AMBA PL011 UART driver
> [    0.373196] HugeTLB registered 2 MB page size, pre-allocated 0 pages
> [    0.374902] HugeTLB registered 512 MB page size, pre-allocated 0 pages
> [    0.380062] ACPI: Added _OSI(Module Device)
> [    0.381157] ACPI: Added _OSI(Processor Device)
> [    0.382200] ACPI: Added _OSI(3.0 _SCP Extensions)
> [    0.383303] ACPI: Added _OSI(Processor Aggregator Device)
> [    0.392501] ACPI: Interpreter enabled
> [    0.393484] ACPI: Using GIC for interrupt routing
> [    0.394751] ACPI: MCFG table detected, 1 entries
> [    0.414519] ARMH0011:00: ttyAMA0 at MMIO 0x9000000 (irq = 5, base_baud = 0) is a SBSA
> [    0.416591] console [ttyAMA0] enabled
> [    0.416591] console [ttyAMA0] enabled
> [    0.418231] bootconsole [pl11] disabled
> [    0.418231] bootconsole [pl11] disabled
> [    0.428624] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-0f])
> [    0.429962] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI]
> [    0.432827] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME AER PCIeCapability]
> [    0.434477] acpi PNP0A08:00: ECAM at [mem 0x3f000000-0x3fffffff] for [bus 00-0f]
> [    0.436078] Remapped I/O 0x000000003eff0000 to [io  0x0000-0xffff window]
> [    0.438129] PCI host bridge to bus 0000:00
> [    0.438987] pci_bus 0000:00: root bus resource [mem 0x10000000-0x3efeffff window]
> [    0.440462] pci_bus 0000:00: root bus resource [io  0x0000-0xffff window]
> [    0.441750] pci_bus 0000:00: root bus resource [mem 0x8000000000-0xffffffffff window]
> [    0.443252] pci_bus 0000:00: root bus resource [bus 00-0f]
> [    0.444377] pci 0000:00:00.0: [1b36:0008] type 00 class 0x060000
> [    0.446402] pci 0000:00:01.0: [8086:3420] type 01 class 0x060400
> [    0.489217] pci 0000:00:01.1: [8086:3420] type 01 class 0x060400
> [    0.528741] pci 0000:00:01.2: [8086:3420] type 01 class 0x060400
> [    0.567928] pci 0000:00:01.3: [8086:3420] type 01 class 0x060400
> [    0.613634] pci 0000:01:00.0: [1033:0194] type 00 class 0x0c0330
> [    0.614948] pci 0000:01:00.0: reg 0x10: [mem 0x10300000-0x10303fff 64bit]
> [    0.631100] pci 0000:02:00.0: [1af4:1048] type 00 class 0x010000
> [    0.679413] pci 0000:02:00.0: reg 0x14: [mem 0x10200000-0x10200fff]
> [    0.752358] pci 0000:02:00.0: reg 0x20: [mem 0x8000000000-0x80007fffff 64bit pref]
> [    0.793032] pci 0000:03:00.0: [1af4:1041] type 00 class 0x020000
> [    0.841238] pci 0000:03:00.0: reg 0x14: [mem 0x10100000-0x10100fff]
> [    0.914350] pci 0000:03:00.0: reg 0x20: [mem 0x8000800000-0x8000ffffff 64bit pref]
> [    0.939819] pci 0000:03:00.0: reg 0x30: [mem 0xfffc0000-0xffffffff pref]
> [    0.956386] pci 0000:04:00.0: [1af4:1050] type 00 class 0x038000
> [    1.004617] pci 0000:04:00.0: reg 0x14: [mem 0x10000000-0x10000fff]
> [    1.077643] pci 0000:04:00.0: reg 0x20: [mem 0x8001000000-0x80017fffff 64bit pref]
> [    1.213423] pci 0000:00:01.1: BAR 15: assigned [mem 0x8000000000-0x80007fffff 64bit pref]
> [    1.215037] pci 0000:00:01.2: BAR 15: assigned [mem 0x8000800000-0x8000ffffff 64bit pref]
> [    1.216626] pci 0000:00:01.3: BAR 15: assigned [mem 0x8001000000-0x80017fffff 64bit pref]
> [    1.219273] pci 0000:00:01.0: BAR 14: assigned [mem 0x10000000-0x101fffff]
> [    1.220663] pci 0000:00:01.0: BAR 15: assigned [mem 0x8001800000-0x80019fffff 64bit pref]
> [    1.222265] pci 0000:00:01.1: BAR 14: assigned [mem 0x10200000-0x103fffff]
> [    1.223605] pci 0000:00:01.2: BAR 14: assigned [mem 0x10400000-0x105fffff]
> [    1.224945] pci 0000:00:01.3: BAR 14: assigned [mem 0x10600000-0x107fffff]
> [    1.226270] pci 0000:00:01.0: BAR 13: assigned [io  0x1000-0x1fff]
> [    1.227475] pci 0000:00:01.1: BAR 13: assigned [io  0x2000-0x2fff]
> [    1.228668] pci 0000:00:01.2: BAR 13: assigned [io  0x3000-0x3fff]
> [    1.229853] pci 0000:00:01.3: BAR 13: assigned [io  0x4000-0x4fff]
> [    1.231064] pci 0000:01:00.0: BAR 0: assigned [mem 0x10000000-0x10003fff 64bit]
> [    1.232564] pci 0000:00:01.0: PCI bridge to [bus 01]
> [    1.233530] pci 0000:00:01.0:   bridge window [io  0x1000-0x1fff]
> [    1.253214] pci 0000:00:01.0:   bridge window [mem 0x10000000-0x101fffff]
> [    1.267540] pci 0000:00:01.0:   bridge window [mem 0x8001800000-0x80019fffff 64bit pref]
> [    1.294996] pci 0000:02:00.0: BAR 4: assigned [mem 0x8000000000-0x80007fffff 64bit pref]
> [    1.321082] pci 0000:02:00.0: BAR 1: assigned [mem 0x10200000-0x10200fff]
> [    1.323053] pci 0000:00:01.1: PCI bridge to [bus 02]
> [    1.324004] pci 0000:00:01.1:   bridge window [io  0x2000-0x2fff]
> [    1.344149] pci 0000:00:01.1:   bridge window [mem 0x10200000-0x103fffff]
> [    1.358181] pci 0000:00:01.1:   bridge window [mem 0x8000000000-0x80007fffff 64bit pref]
> [    1.384572] pci 0000:03:00.0: BAR 4: assigned [mem 0x8000800000-0x8000ffffff 64bit pref]
> [    1.410293] pci 0000:03:00.0: BAR 6: assigned [mem 0x10400000-0x1043ffff pref]
> [    1.412715] pci 0000:03:00.0: BAR 1: assigned [mem 0x10440000-0x10440fff]
> [    1.426032] pci 0000:00:01.2: PCI bridge to [bus 03]
> [    1.427117] pci 0000:00:01.2:   bridge window [io  0x3000-0x3fff]
> [    1.446229] pci 0000:00:01.2:   bridge window [mem 0x10400000-0x105fffff]
> [    1.460070] pci 0000:00:01.2:   bridge window [mem 0x8000800000-0x8000ffffff 64bit pref]
> [    1.486803] pci 0000:04:00.0: BAR 4: assigned [mem 0x8001000000-0x80017fffff 64bit pref]
> [    1.512454] pci 0000:04:00.0: BAR 1: assigned [mem 0x10600000-0x10600fff]
> [    1.526310] pci 0000:00:01.3: PCI bridge to [bus 04]
> [    1.527283] pci 0000:00:01.3:   bridge window [io  0x4000-0x4fff]
> [    1.546456] pci 0000:00:01.3:   bridge window [mem 0x10600000-0x107fffff]
> [    1.560368] pci 0000:00:01.3:   bridge window [mem 0x8001000000-0x80017fffff 64bit pref]
> [    1.587389] ACPI: PCI Interrupt Link [GSI0] (IRQs *35)
> [    1.588527] ACPI: PCI Interrupt Link [GSI1] (IRQs *36)
> [    1.589607] ACPI: PCI Interrupt Link [GSI2] (IRQs *37)
> [    1.590670] ACPI: PCI Interrupt Link [GSI3] (IRQs *38)
> [    1.594331] vgaarb: loaded
> [    1.595642] SCSI subsystem initialized
> [    1.596943] libata version 3.00 loaded.
> [    1.597907] ACPI: bus type USB registered
> [    1.598884] usbcore: registered new interface driver usbfs
> [    1.600034] usbcore: registered new interface driver hub
> [    1.601350] usbcore: registered new device driver usb
> [    1.604990] NetLabel: Initializing
> [    1.605716] NetLabel:  domain hash size = 128
> [    1.606524] NetLabel:  protocols = UNLABELED CIPSOv4
> [    1.607669] NetLabel:  unlabeled traffic allowed by default
> [    1.611142] DMA-API: preallocated 4096 debug entries
> [    1.612105] DMA-API: debugging enabled by kernel config
> [    1.705795] clocksource: Switched to clocksource arch_sys_counter
> [    1.787821] VFS: Disk quotas dquot_6.6.0
> [    1.789040] VFS: Dquot-cache hash table entries: 8192 (order 0, 65536 bytes)
> [    1.791938] pnp: PnP ACPI init
> [    1.793312] pnp: PnP ACPI: found 0 devices
> [    1.810253] NET: Registered protocol family 2
> [    1.813094] TCP established hash table entries: 65536 (order: 3, 524288 bytes)
> [    1.814846] TCP bind hash table entries: 65536 (order: 6, 4194304 bytes)
> [    1.822396] TCP: Hash tables configured (established 65536 bind 65536)
> [    1.823873] UDP hash table entries: 4096 (order: 3, 655360 bytes)
> [    1.825936] UDP-Lite hash table entries: 4096 (order: 3, 655360 bytes)
> [    1.828672] NET: Registered protocol family 1
> [    1.829673] pci 0000:01:00.0: enabling device (0000 -> 0002)
> [    1.837906] PCI: CLS 0 bytes, default 128
> [    1.839209] Unpacking initramfs...
> [    2.755342] Freeing initrd memory: 30400K (fffffe00f53c0000 - fffffe00f7170000)
> [    2.757373] kvm [1]: HYP mode not available
> [    2.758651] alg: No test for __ecb-aes-neon (__driver-ecb-aes-neon)
> [    2.760171] cryptomgr_test (75) used greatest stack depth: 13824 bytes left
> [    2.767725] modprobe (81) used greatest stack depth: 12944 bytes left
> [    2.772040] alg: No test for __ecb-aes-neon (cryptd(__driver-ecb-aes-neon))
> [    2.774374] cryptomgr_test (79) used greatest stack depth: 12368 bytes left
> [    2.777350] futex hash table entries: 2048 (order: 2, 262144 bytes)
> [    2.779027] audit: initializing netlink subsys (disabled)
> [    2.780231] audit: type=2000 audit(2.600:1): initialized
> [    2.782020] Initialise system trusted keyrings
> [    2.784150] workingset: timestamp_bits=37 max_order=17 bucket_order=0
> [    2.802041] zbud: loaded
> [    2.808395] Key type big_key registered
> [    2.809229] SELinux:  Registering netfilter hooks
> [    2.897252] alg: drbg: Test 0 failed for drbg_pr_ctr_aes128
> [    2.898554] cryptomgr_test (104) used greatest stack depth: 12016 bytes left
> [    2.908631] alg: drbg: Test 0 failed for drbg_nopr_ctr_aes128
> [    2.910204] alg: drbg: Test 0 failed for drbg_nopr_ctr_aes192
> [    2.911772] alg: drbg: Test 0 failed for drbg_nopr_ctr_aes256
> [    2.915338] NET: Registered protocol family 38
> [    2.916380] Key type asymmetric registered
> [    2.917318] Asymmetric key parser 'x509' registered
> [    2.918805] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 250)
> [    2.920707] io scheduler noop registered
> [    2.921443] io scheduler deadline registered
> [    2.923122] io scheduler cfq registered (default)
> [    2.924139] start plist test
> [    2.927415] end plist test
> [    2.931670] pl061_gpio ARMH0061:00: PL061 GPIO chip @0x0000000009030000 registered
> [    2.934507] ACPI: PCI Interrupt Link [GSI1] enabled at IRQ 36
> [    2.973148] aer 0000:00:01.0:pcie002: service driver aer loaded
> [    2.974725] aer 0000:00:01.1:pcie002: service driver aer loaded
> [    2.976977] aer 0000:00:01.2:pcie002: service driver aer loaded
> [    2.978502] aer 0000:00:01.3:pcie002: service driver aer loaded
> [    2.979878] pcieport 0000:00:01.0: Signaling PME through PCIe PME interrupt
> [    2.981335] pci 0000:01:00.0: Signaling PME through PCIe PME interrupt
> [    2.982761] pcie_pme 0000:00:01.0:pcie001: service driver pcie_pme loaded
> [    2.984298] pcieport 0000:00:01.1: Signaling PME through PCIe PME interrupt
> [    2.985781] pci 0000:02:00.0: Signaling PME through PCIe PME interrupt
> [    2.987087] pcie_pme 0000:00:01.1:pcie001: service driver pcie_pme loaded
> [    2.988619] pcieport 0000:00:01.2: Signaling PME through PCIe PME interrupt
> [    2.990050] pci 0000:03:00.0: Signaling PME through PCIe PME interrupt
> [    2.991448] pcie_pme 0000:00:01.2:pcie001: service driver pcie_pme loaded
> [    2.993019] pcieport 0000:00:01.3: Signaling PME through PCIe PME interrupt
> [    2.994518] pci 0000:04:00.0: Signaling PME through PCIe PME interrupt
> [    2.995867] pcie_pme 0000:00:01.3:pcie001: service driver pcie_pme loaded
> [    2.997328] pci_hotplug: PCI Hot Plug PCI Core version: 0.5
> [    2.998614] pciehp 0000:00:01.0:pcie004: Slot #0 AttnBtn+ PwrCtrl+ MRL- AttnInd+ PwrInd+ HotPlug+ Surprise+ Interlock+ NoCompl- LLActRep-
> [    3.001848] pciehp 0000:00:01.0:pcie004: service driver pciehp loaded
> [    3.003202] pciehp 0000:00:01.1:pcie004: Slot #0 AttnBtn+ PwrCtrl+ MRL- AttnInd+ PwrInd+ HotPlug+ Surprise+ Interlock+ NoCompl- LLActRep-
> [    3.006097] pciehp 0000:00:01.1:pcie004: service driver pciehp loaded
> [    3.007533] pciehp 0000:00:01.2:pcie004: Slot #0 AttnBtn+ PwrCtrl+ MRL- AttnInd+ PwrInd+ HotPlug+ Surprise+ Interlock+ NoCompl- LLActRep-
> [    3.010330] pciehp 0000:00:01.2:pcie004: service driver pciehp loaded
> [    3.011748] pciehp 0000:00:01.3:pcie004: Slot #0 AttnBtn+ PwrCtrl+ MRL- AttnInd+ PwrInd+ HotPlug+ Surprise+ Interlock+ NoCompl- LLActRep-
> [    3.014587] pciehp 0000:00:01.3:pcie004: service driver pciehp loaded
> [    3.015864] pciehp: PCI Express Hot Plug Controller Driver version: 0.4
> [    3.017707] efifb: invalid framebuffer address
> [    3.020376] Serial: 8250/16550 driver, 32 ports, IRQ sharing enabled
> [    3.033876] msm_serial: driver initialized
> [    3.035876] Failed to find cpu0 device node
> [    3.036713] Unable to detect cache hierarchy from DT for CPU 0
> [    3.038968] libphy: Fixed MDIO Bus: probed
> [    3.040219] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
> [    3.041636] ehci-pci: EHCI PCI platform driver
> [    3.042554] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
> [    3.043761] ohci-pci: OHCI PCI platform driver
> [    3.044666] uhci_hcd: USB Universal Host Controller Interface driver
> [    3.054963] xhci_hcd 0000:01:00.0: xHCI Host Controller
> [    3.056725] xhci_hcd 0000:01:00.0: new USB bus registered, assigned bus number 1
> [    3.060495] xhci_hcd 0000:01:00.0: hcc params 0x00087001 hci version 0x100 quirks 0x00000014
> [    3.064236] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
> [    3.065654] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> [    3.067032] usb usb1: Product: xHCI Host Controller
> [    3.067982] usb usb1: Manufacturer: Linux 4.8.0 xhci-hcd
> [    3.069014] usb usb1: SerialNumber: 0000:01:00.0
> [    3.071283] hub 1-0:1.0: USB hub found
> [    3.072298] hub 1-0:1.0: 4 ports detected
> [    3.074921] xhci_hcd 0000:01:00.0: xHCI Host Controller
> [    3.076485] xhci_hcd 0000:01:00.0: new USB bus registered, assigned bus number 2
> [    3.078304] usb usb2: We don't know the algorithms for LPM for this host, disabling LPM.
> [    3.080160] usb usb2: New USB device found, idVendor=1d6b, idProduct=0003
> [    3.081526] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> [    3.082893] usb usb2: Product: xHCI Host Controller
> [    3.083821] usb usb2: Manufacturer: Linux 4.8.0 xhci-hcd
> [    3.084825] usb usb2: SerialNumber: 0000:01:00.0
> [    3.086840] hub 2-0:1.0: USB hub found
> [    3.087745] hub 2-0:1.0: 4 ports detected
> [    3.090180] usbcore: registered new interface driver usbserial
> [    3.091473] usbcore: registered new interface driver usbserial_generic
> [    3.093048] usbserial: USB Serial support registered for generic
> [    3.094847] mousedev: PS/2 mouse device common for all mice
> [    3.097427] rtc-efi rtc-efi: rtc core: registered rtc-efi as rtc0
> [    3.099602] device-mapper: uevent: version 1.0.3
> [    3.101336] device-mapper: ioctl: 4.35.0-ioctl (2016-06-23) initialised: dm-devel at redhat.com
> [    3.104534] EFI Variables Facility v0.08 2004-May-17
> [    3.107690] hidraw: raw HID events driver (C) Jiri Kosina
> [    3.109001] usbcore: registered new interface driver usbhid
> [    3.110141] usbhid: USB HID core driver
> [    3.111920] drop_monitor: Initializing network drop monitor service
> [    3.113583] ip_tables: (C) 2000-2006 Netfilter Core Team
> [    3.114948] Initializing XFRM netlink socket
> [    3.117302] NET: Registered protocol family 10
> [    3.120493] mip6: Mobile IPv6
> [    3.121237] NET: Registered protocol family 17
> [    3.123363] registered taskstats version 1
> [    3.124289] Loading compiled-in X.509 certificates
> [    3.132881] alg: No test for pkcs1pad(rsa,sha256) (pkcs1pad(rsa-generic,sha256))
> [    3.136159] Loaded X.509 cert 'Build time autogenerated kernel key: 646bee5e17f26888c6e6ef5950998cb2000dfbae'
> [    3.138723] zswap: loaded using pool lzo/zbud
> [    3.166483] rtc-efi rtc-efi: setting system clock to 2016-10-14 15:41:17 UTC (1476459677)
> [    3.168727] PM: Hibernation image not present or could not be loaded.
> [    3.170839] Freeing unused kernel memory: 1536K (fffffe0000cf0000 - fffffe0000e70000)
> [    3.190833] random: systemd: uninitialized urandom read (16 bytes read)
> [    3.194327] random: systemd: uninitialized urandom read (16 bytes read)
> [    3.213481] systemd[1]: systemd 229 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
> [    3.217655] systemd[1]: Detected virtualization kvm.
> [    3.218614] systemd[1]: Detected architecture arm64.
> [    3.219547] systemd[1]: Running in initial RAM disk.
>
> Welcome to Fedora 24 (Server Edition) dracut-044-20.fc24 (Initramfs)!

> If (2) fails then we may need to expand the bisection :-(

Thankfully, it didn't fail.

Thanks
Laszlo

^ permalink raw reply

* aarch64 ACPI boot regressed by commit 7ba5f605f3a0 ("arm64/numa: remove the limitation that cpu0 must bind to node0")
From: Laszlo Ersek @ 2016-10-14 16:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161014154231.GA4411@red-moon>

On 10/14/16 17:42, Lorenzo Pieralisi wrote:
> On Fri, Oct 14, 2016 at 05:27:58PM +0200, Laszlo Ersek wrote:
>> On 10/14/16 17:01, Laszlo Ersek wrote:
>>
>>> Maybe the code I
>>> tried to analyze in this email was never *meant* to associate CPU#0 with
>>> any NUMA node at all (not even node 0); instead, other code -- for
>>> example code removed by 7ba5f605f3a0 -- was meant to perform that
>>> association.
>>
>> Staring a bit more at the code, this looks very likely; in acpi_map_gic_cpu_interface() we have
>>
>>> 	/* Check if GICC structure of boot CPU is available in the MADT */
>>> 	if (cpu_logical_map(0) == hwid) {
>>> 		if (bootcpu_valid) {
>>> 			pr_err("duplicate boot CPU MPIDR: 0x%llx in MADT\n",
>>> 			       hwid);
>>> 			return;
>>> 		}
>>> 		bootcpu_valid = true;
>>> 		return;
>>> 	}
>>
>> which means that this callback function (for parsing the GICC
>> structures in the MADT) expects to find the boot processor as well.
>>
>> Upon finding the boot processor, we set bootcpu_valid to true, and
>> that's it -- no association with any NUMA node, and no incrementing of
>> "cpu_count".
> 
> Yes, because that's to check the MADT contains the boot cpu hwid.
> 
> Does this help (compile tested only) ?
> 
> -- >8 -- 
> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index d3f151c..8507703 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -544,6 +544,7 @@ static int __init smp_cpu_setup(int cpu)
>  			return;
>  		}
>  		bootcpu_valid = true;
> +		early_map_cpu_to_node(0, acpi_numa_get_nid(0, hwid));
>  		return;
>  	}
>  
> 

Your patch applies to the tree at v4.8-14604-g29fbff8698fc, but the function the hunk modifies is not smp_cpu_setup(), it is acpi_map_gic_cpu_interface():

> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index d3f151cfd4a1..8507703dabe4 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -544,6 +544,7 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
>  			return;
>  		}
>  		bootcpu_valid = true;
> +		early_map_cpu_to_node(0, acpi_numa_get_nid(0, hwid));
>  		return;
>  	}
> 

Anyway, your patch works with both the two-node NUMA configuration Drew suggested for testing, and with the single-node config that I originally used for the bisection. Therefore:

Tested-by: Laszlo Ersek <lersek@redhat.com>
Reported-by: Laszlo Ersek <lersek@redhat.com>

Thank you very much for the quick bugfix! And, I think your patch (when you send it for real) should carry

Fixes: 7ba5f605f3a0d9495aad539eeb8346d726dfc183

too, because it supplies the cpu#0<->node#xxx association that 7ba5f605f3a0 removed not just for DT, but also for ACPI.

Cheers!
Laszlo

^ 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-14 16:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <912acc88-fbaf-2576-8048-1fcc67439600@codeaurora.org>

On 13/10/16 20:37, Baicar, Tyler wrote:
> Hello Suzuki,
>
> On 10/13/2016 2:50 AM, Suzuki K Poulose wrote:
>> On 12/10/16 23:10, Baicar, Tyler wrote:

>>>> 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.
>>
> Okay, understood. I'll make sure to add those who have commented in the cc/to list to avoid the e-mail filters.

Thanks !

>> Is it always the same endianness as that of the CPU ?
> It is a fair assumption that the firmware populating this record will use a CPU of the same endianness. There is no mechanism in the spec to indicate otherwise.

Yep, you are right. The EFI expects the EL2/EL1 to be of the same endianness

Cheers
Suzuki

^ permalink raw reply

* [PATCH V3 02/10] ras: acpi/apei: cper: generic error data entry v3 per ACPI 6.1
From: Mark Rutland @ 2016-10-14 16:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <38c7c9ac-e8ad-6fb5-3ee9-3ba85e4b8299@arm.com>

On Fri, Oct 14, 2016 at 05:28:58PM +0100, Suzuki K Poulose wrote:
> On 13/10/16 20:37, Baicar, Tyler wrote:
> >On 10/13/2016 2:50 AM, Suzuki K Poulose wrote:
> >>Is it always the same endianness as that of the CPU ?
> >
> >It is a fair assumption that the firmware populating this record will
> >use a CPU of the same endianness. There is no mechanism in the spec
> >to indicate otherwise.
> 
> Yep, you are right. The EFI expects the EL2/EL1 to be of the same endianness

To be clear, it is specifically required in the ACPI spec that elements
are in little-endian. Per the ACPI 6.1 spec, page 109:

	All numeric values in ACPI-defined tables, blocks, and
	structures are always encoded in little endian
	format.

Given that CPER, HEST, etc are defined within the ACPI specification,
they are covered by this requirement.

Elements outside of the ACPI spec are not necessarily covered by this
requirement, but their specifications should state their endianness.

Thanks,
Mark.

^ permalink raw reply

* aarch64 ACPI boot regressed by commit 7ba5f605f3a0 ("arm64/numa: remove the limitation that cpu0 must bind to node0")
From: Lorenzo Pieralisi @ 2016-10-14 16:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <c8b9f6fc-3a4b-f74a-c930-f500bcc00a1d@redhat.com>

On Fri, Oct 14, 2016 at 06:22:55PM +0200, Laszlo Ersek wrote:
> On 10/14/16 17:42, Lorenzo Pieralisi wrote:
> > On Fri, Oct 14, 2016 at 05:27:58PM +0200, Laszlo Ersek wrote:
> >> On 10/14/16 17:01, Laszlo Ersek wrote:
> >>
> >>> Maybe the code I
> >>> tried to analyze in this email was never *meant* to associate CPU#0 with
> >>> any NUMA node at all (not even node 0); instead, other code -- for
> >>> example code removed by 7ba5f605f3a0 -- was meant to perform that
> >>> association.
> >>
> >> Staring a bit more at the code, this looks very likely; in acpi_map_gic_cpu_interface() we have
> >>
> >>> 	/* Check if GICC structure of boot CPU is available in the MADT */
> >>> 	if (cpu_logical_map(0) == hwid) {
> >>> 		if (bootcpu_valid) {
> >>> 			pr_err("duplicate boot CPU MPIDR: 0x%llx in MADT\n",
> >>> 			       hwid);
> >>> 			return;
> >>> 		}
> >>> 		bootcpu_valid = true;
> >>> 		return;
> >>> 	}
> >>
> >> which means that this callback function (for parsing the GICC
> >> structures in the MADT) expects to find the boot processor as well.
> >>
> >> Upon finding the boot processor, we set bootcpu_valid to true, and
> >> that's it -- no association with any NUMA node, and no incrementing of
> >> "cpu_count".
> > 
> > Yes, because that's to check the MADT contains the boot cpu hwid.
> > 
> > Does this help (compile tested only) ?
> > 
> > -- >8 -- 
> > diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> > index d3f151c..8507703 100644
> > --- a/arch/arm64/kernel/smp.c
> > +++ b/arch/arm64/kernel/smp.c
> > @@ -544,6 +544,7 @@ static int __init smp_cpu_setup(int cpu)
> >  			return;
> >  		}
> >  		bootcpu_valid = true;
> > +		early_map_cpu_to_node(0, acpi_numa_get_nid(0, hwid));
> >  		return;
> >  	}
> >  
> > 
> 
> Your patch applies to the tree at v4.8-14604-g29fbff8698fc, but the function the hunk modifies is not smp_cpu_setup(), it is acpi_map_gic_cpu_interface():
> 
> > diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> > index d3f151cfd4a1..8507703dabe4 100644
> > --- a/arch/arm64/kernel/smp.c
> > +++ b/arch/arm64/kernel/smp.c
> > @@ -544,6 +544,7 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
> >  			return;
> >  		}
> >  		bootcpu_valid = true;
> > +		early_map_cpu_to_node(0, acpi_numa_get_nid(0, hwid));
> >  		return;
> >  	}
> > 
> 
> Anyway, your patch works with both the two-node NUMA configuration
> Drew suggested for testing, and with the single-node config that I
> originally used for the bisection. Therefore:
> 
> Tested-by: Laszlo Ersek <lersek@redhat.com>
> Reported-by: Laszlo Ersek <lersek@redhat.com>
> 
> Thank you very much for the quick bugfix! And, I think your patch
> (when you send it for real) should carry
> 
> Fixes: 7ba5f605f3a0d9495aad539eeb8346d726dfc183
> 
> too, because it supplies the cpu#0<->node#xxx association that
> 7ba5f605f3a0 removed not just for DT, but also for ACPI.

Sure, will do, I will send it out on Monday.

Cheers,
Lorenzo

^ permalink raw reply

* [PATCH v3 0/8] PM / Domains: DT support for domain idle states & atomic PM domains
From: Lina Iyer @ 2016-10-14 17:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

Changes since v2 [3] -
- Addressed review comments from v2.
	- domain-idle-states documentation updated
	- fixed compiler issues with imx driver
	- minor code change in pm_domains.c
- The series is available at [4].

Changes since v1 [2] -
- Addressed review comments from v1.
        - Fixes around dynamic allocation of genpd states
        - Used OF method for iterating phandles
        - Updated documentation, examples
        - Rename state variable (provider -> fwnode)
- The series is available at [3].

The changes from [1] are -
- Allocating memory for domain idle states dynamically
- Conform to naming conventions for internal and exported genpd functions
- DT binding example for domain-idle-state
- Use fwnode instead of of_node
- Handle atomic case for removal of PM Domain
- Rebase on top of Rafael's pm/genpd tree

Thanks,
Lina

Lina Iyer (8):
  PM / Domains: Make genpd state allocation dynamic
  PM / Domain: Add residency property to genpd states
  PM / Domains: Allow domain power states to be read from DT
  PM / Domains: Save the fwnode in genpd_power_state
  dt/bindings: Update binding for PM domain idle states
  PM / Domains: Abstract genpd locking
  PM / Domains: Support IRQ safe PM domains
  PM / doc: Update device documentation for devices in IRQ safe PM
    domains

 .../devicetree/bindings/power/power_domain.txt     |  43 +++
 Documentation/power/devices.txt                    |   9 +-
 arch/arm/mach-imx/gpc.c                            |  17 +-
 drivers/base/power/domain.c                        | 358 +++++++++++++++++----
 include/linux/pm_domain.h                          |  28 +-
 5 files changed, 383 insertions(+), 72 deletions(-)

-- 
2.7.4

[1]. https://www.spinics.net/lists/arm-kernel/msg526814.html
[2]. http://www.spinics.net/lists/arm-kernel/msg535106.html
[3]. https://git.linaro.org/people/lina.iyer/linux-next.git/shortlog/refs/heads/genpd-v2
[4]. https://git.linaro.org/people/lina.iyer/linux-next.git/shortlog/refs/heads/genpd-v3

^ permalink raw reply

* [PATCH v3 1/8] PM / Domains: Make genpd state allocation dynamic
From: Lina Iyer @ 2016-10-14 17:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476467276-75094-1-git-send-email-lina.iyer@linaro.org>

Allow PM Domain states to be defined dynamically by the drivers. This
removes the limitation on the maximum number of states possible for a
domain.

Cc: Axel Haslam <ahaslam+renesas@baylibre.com>
Suggested-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 arch/arm/mach-imx/gpc.c     | 17 ++++++++++-------
 drivers/base/power/domain.c | 35 +++++++++++++++++++++++------------
 include/linux/pm_domain.h   |  5 ++---
 3 files changed, 35 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 0df062d..57a410b 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -380,13 +380,6 @@ static struct pu_domain imx6q_pu_domain = {
 		.name = "PU",
 		.power_off = imx6q_pm_pu_power_off,
 		.power_on = imx6q_pm_pu_power_on,
-		.states = {
-			[0] = {
-				.power_off_latency_ns = 25000,
-				.power_on_latency_ns = 2000000,
-			},
-		},
-		.state_count = 1,
 	},
 };
 
@@ -430,6 +423,16 @@ static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
 	if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
 		return 0;
 
+	imx6q_pu_domain.base.states = devm_kzalloc(dev,
+					sizeof(*imx6q_pu_domain.base.states),
+					GFP_KERNEL);
+	if (!imx6q_pu_domain.base.states)
+		return -ENOMEM;
+
+	imx6q_pu_domain.base.states[0].power_off_latency_ns = 25000;
+	imx6q_pu_domain.base.states[0].power_on_latency_ns = 2000000;
+	imx6q_pu_domain.base.state_count = 1;
+
 	pm_genpd_init(&imx6q_pu_domain.base, NULL, false);
 	return of_genpd_add_provider_onecell(dev->of_node,
 					     &imx_gpc_onecell_data);
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index e023066..37ab7f1 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1282,6 +1282,21 @@ out:
 }
 EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
 
+static int genpd_set_default_power_state(struct generic_pm_domain *genpd)
+{
+	struct genpd_power_state *state;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	genpd->states = state;
+	genpd->state_count = 1;
+	genpd->free = state;
+
+	return 0;
+}
+
 /**
  * pm_genpd_init - Initialize a generic I/O PM domain object.
  * @genpd: PM domain object to initialize.
@@ -1293,6 +1308,8 @@ EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
 int pm_genpd_init(struct generic_pm_domain *genpd,
 		  struct dev_power_governor *gov, bool is_off)
 {
+	int ret;
+
 	if (IS_ERR_OR_NULL(genpd))
 		return -EINVAL;
 
@@ -1325,19 +1342,12 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
 		genpd->dev_ops.start = pm_clk_resume;
 	}
 
-	if (genpd->state_idx >= GENPD_MAX_NUM_STATES) {
-		pr_warn("Initial state index out of bounds.\n");
-		genpd->state_idx = GENPD_MAX_NUM_STATES - 1;
-	}
-
-	if (genpd->state_count > GENPD_MAX_NUM_STATES) {
-		pr_warn("Limiting states to  %d\n", GENPD_MAX_NUM_STATES);
-		genpd->state_count = GENPD_MAX_NUM_STATES;
-	}
-
 	/* Use only one "off" state if there were no states declared */
-	if (genpd->state_count == 0)
-		genpd->state_count = 1;
+	if (genpd->state_count == 0) {
+		ret = genpd_set_default_power_state(genpd);
+		if (ret)
+			return ret;
+	}
 
 	mutex_lock(&gpd_list_lock);
 	list_add(&genpd->gpd_list_node, &gpd_list);
@@ -1377,6 +1387,7 @@ static int genpd_remove(struct generic_pm_domain *genpd)
 	list_del(&genpd->gpd_list_node);
 	mutex_unlock(&genpd->lock);
 	cancel_work_sync(&genpd->power_off_work);
+	kfree(genpd->free);
 	pr_debug("%s: removed %s\n", __func__, genpd->name);
 
 	return 0;
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index a09fe5c..de1d8f3 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -19,8 +19,6 @@
 /* Defines used for the flags field in the struct generic_pm_domain */
 #define GENPD_FLAG_PM_CLK	(1U << 0) /* PM domain uses PM clk */
 
-#define GENPD_MAX_NUM_STATES	8 /* Number of possible low power states */
-
 enum gpd_status {
 	GPD_STATE_ACTIVE = 0,	/* PM domain is active */
 	GPD_STATE_POWER_OFF,	/* PM domain is off */
@@ -70,9 +68,10 @@ struct generic_pm_domain {
 	void (*detach_dev)(struct generic_pm_domain *domain,
 			   struct device *dev);
 	unsigned int flags;		/* Bit field of configs for genpd */
-	struct genpd_power_state states[GENPD_MAX_NUM_STATES];
+	struct genpd_power_state *states;
 	unsigned int state_count; /* number of states */
 	unsigned int state_idx; /* state that genpd will go to when off */
+	void *free; /* Free the state that was allocated for default */
 
 };
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 2/8] PM / Domain: Add residency property to genpd states
From: Lina Iyer @ 2016-10-14 17:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476467276-75094-1-git-send-email-lina.iyer@linaro.org>

Residency of a domain's idle state indicates that the minimum idle time
for the domain's idle state to be beneficial for power. Add the
parameter to the state node. Future patches, will use the residency
value in the genpd governor to determine if it is worth while to enter
an idle state.

Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 include/linux/pm_domain.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index de1d8f3..f4492eb 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -38,6 +38,7 @@ struct gpd_dev_ops {
 struct genpd_power_state {
 	s64 power_off_latency_ns;
 	s64 power_on_latency_ns;
+	s64 residency_ns;
 };
 
 struct generic_pm_domain {
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 3/8] PM / Domains: Allow domain power states to be read from DT
From: Lina Iyer @ 2016-10-14 17:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476467276-75094-1-git-send-email-lina.iyer@linaro.org>

This patch allows domains to define idle states in the DT. SoC's can
define domain idle states in DT using the "domain-idle-states" property
of the domain provider. Add API to read the idle states from DT that can
be set in the genpd object.

This patch is based on the original patch by Marc Titinger.

Signed-off-by: Marc Titinger <mtitinger+renesas@baylibre.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
---
 drivers/base/power/domain.c | 94 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_domain.h   |  8 ++++
 2 files changed, 102 insertions(+)

diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 37ab7f1..9af75ba 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1916,6 +1916,100 @@ out:
 	return ret ? -EPROBE_DEFER : 0;
 }
 EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
+
+static const struct of_device_id idle_state_match[] = {
+	{ .compatible = "arm,idle-state", },
+	{ }
+};
+
+static int genpd_parse_state(struct genpd_power_state *genpd_state,
+				    struct device_node *state_node)
+{
+	int err;
+	u32 residency;
+	u32 entry_latency, exit_latency;
+	const struct of_device_id *match_id;
+
+	match_id = of_match_node(idle_state_match, state_node);
+	if (!match_id)
+		return -EINVAL;
+
+	err = of_property_read_u32(state_node, "entry-latency-us",
+						&entry_latency);
+	if (err) {
+		pr_debug(" * %s missing entry-latency-us property\n",
+						state_node->full_name);
+		return -EINVAL;
+	}
+
+	err = of_property_read_u32(state_node, "exit-latency-us",
+						&exit_latency);
+	if (err) {
+		pr_debug(" * %s missing exit-latency-us property\n",
+						state_node->full_name);
+		return -EINVAL;
+	}
+
+	err = of_property_read_u32(state_node, "min-residency-us", &residency);
+	if (!err)
+		genpd_state->residency_ns = 1000 * residency;
+
+	genpd_state->power_on_latency_ns = 1000 * exit_latency;
+	genpd_state->power_off_latency_ns = 1000 * entry_latency;
+
+	return 0;
+}
+
+/**
+ * of_genpd_parse_idle_states: Return array of idle states for the genpd.
+ *
+ * @dn: The genpd device node
+ * @states: The pointer to which the state array will be saved.
+ * @n: The count of elements in the array returned from this function.
+ *
+ * Returns the device states parsed from the OF node. The memory for the states
+ * is allocated by this function and is the responsibility of the caller to
+ * free the memory after use.
+ */
+int of_genpd_parse_idle_states(struct device_node *dn,
+			struct genpd_power_state **states, int *n)
+{
+	struct genpd_power_state *st;
+	struct device_node *np;
+	int i = 0;
+	int err, ret;
+	int count;
+	struct of_phandle_iterator it;
+
+	count = of_count_phandle_with_args(dn, "domain-idle-states", NULL);
+	if (!count)
+		return -EINVAL;
+
+	st = kcalloc(count, sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM;
+
+	/* Loop over the phandles until all the requested entry is found */
+	of_for_each_phandle(&it, err, dn, "domain-idle-states", NULL, 0) {
+		np = it.node;
+		ret = genpd_parse_state(&st[i++], np);
+		if (ret) {
+			pr_err
+			("Parsing idle state node %s failed with err %d\n",
+							np->full_name, ret);
+			of_node_put(np);
+			kfree(st);
+			return ret;
+		}
+	}
+
+	*n = count;
+	*states = st;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states);
+
 #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
 
 
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index f4492eb..b489496 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -205,6 +205,8 @@ extern int of_genpd_add_device(struct of_phandle_args *args,
 extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
 				  struct of_phandle_args *new_subdomain);
 extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
+extern int of_genpd_parse_idle_states(struct device_node *dn,
+			struct genpd_power_state **states, int *n);
 
 int genpd_dev_pm_attach(struct device *dev);
 #else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
@@ -234,6 +236,12 @@ static inline int of_genpd_add_subdomain(struct of_phandle_args *parent,
 	return -ENODEV;
 }
 
+static inline int of_genpd_parse_idle_states(struct device_node *dn,
+			struct genpd_power_state **states, int *n)
+{
+	return -ENODEV;
+}
+
 static inline int genpd_dev_pm_attach(struct device *dev)
 {
 	return -ENODEV;
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 4/8] PM / Domains: Save the fwnode in genpd_power_state
From: Lina Iyer @ 2016-10-14 17:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476467276-75094-1-git-send-email-lina.iyer@linaro.org>

Save the fwnode for the genpd state in the state node. PM Domain clients
may use the fwnode to read in the platform specific domain state
properties and associate them with the state.

Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/base/power/domain.c | 1 +
 include/linux/pm_domain.h   | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 9af75ba..1a6073aa 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1956,6 +1956,7 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state,
 
 	genpd_state->power_on_latency_ns = 1000 * exit_latency;
 	genpd_state->power_off_latency_ns = 1000 * entry_latency;
+	genpd_state->fwnode = &state_node->fwnode;
 
 	return 0;
 }
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index b489496..6a89881 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -39,6 +39,7 @@ struct genpd_power_state {
 	s64 power_off_latency_ns;
 	s64 power_on_latency_ns;
 	s64 residency_ns;
+	struct fwnode_handle *fwnode;
 };
 
 struct generic_pm_domain {
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 5/8] dt/bindings: Update binding for PM domain idle states
From: Lina Iyer @ 2016-10-14 17:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476467276-75094-1-git-send-email-lina.iyer@linaro.org>

Update DT bindings to describe idle states of PM domains.

This patch is based on the original patch by Marc Titinger.

Cc: <devicetree@vger.kernel.org>
Signed-off-by: Marc Titinger <mtitinger+renesas@baylibre.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Acked-by: Rob Herring <robh@kernel.org>
---
 .../devicetree/bindings/power/power_domain.txt     | 43 ++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/Documentation/devicetree/bindings/power/power_domain.txt b/Documentation/devicetree/bindings/power/power_domain.txt
index 025b5e7..e165036 100644
--- a/Documentation/devicetree/bindings/power/power_domain.txt
+++ b/Documentation/devicetree/bindings/power/power_domain.txt
@@ -29,6 +29,15 @@ Optional properties:
    specified by this binding. More details about power domain specifier are
    available in the next section.
 
+- domain-idle-states : A phandle of an idle-state that shall be soaked into a
+                generic domain power state. The idle state definitions are
+                compatible with arm,idle-state specified in [1].
+  The domain-idle-state property reflects the idle state of this PM domain and
+  not the idle states of the devices or sub-domains in the PM domain. Devices
+  and sub-domains have their own idle-states independent of the parent
+  domain's idle states. In the absence of this property, the domain would be
+  considered as capable of being powered-on or powered-off.
+
 Example:
 
 	power: power-controller at 12340000 {
@@ -59,6 +68,38 @@ The nodes above define two power controllers: 'parent' and 'child'.
 Domains created by the 'child' power controller are subdomains of '0' power
 domain provided by the 'parent' power controller.
 
+Example 3:
+	parent: power-controller at 12340000 {
+		compatible = "foo,power-controller";
+		reg = <0x12340000 0x1000>;
+		#power-domain-cells = <0>;
+		domain-idle-states = <&DOMAIN_RET>, <&DOMAIN_PWR_DN>;
+	};
+
+	child: power-controller at 12341000 {
+		compatible = "foo,power-controller";
+		reg = <0x12341000 0x1000>;
+		power-domains = <&parent 0>;
+		#power-domain-cells = <0>;
+		domain-idle-states = <&DOMAIN_PWR_DN>;
+	};
+
+	DOMAIN_RET: state at 0 {
+		compatible = "arm,idle-state";
+		reg = <0x0>;
+		entry-latency-us = <1000>;
+		exit-latency-us = <2000>;
+		min-residency-us = <10000>;
+	};
+
+	DOMAIN_PWR_DN: state at 1 {
+		compatible = "arm,idle-state";
+		reg = <0x1>;
+		entry-latency-us = <5000>;
+		exit-latency-us = <8000>;
+		min-residency-us = <7000>;
+	};
+
 ==PM domain consumers==
 
 Required properties:
@@ -76,3 +117,5 @@ Example:
 The node above defines a typical PM domain consumer device, which is located
 inside a PM domain with index 0 of a power controller represented by a node
 with the label "power".
+
+[1]. Documentation/devicetree/bindings/arm/idle-states.txt
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 6/8] PM / Domains: Abstract genpd locking
From: Lina Iyer @ 2016-10-14 17:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476467276-75094-1-git-send-email-lina.iyer@linaro.org>

Abstract genpd lock/unlock calls, in preparation for domain specific
locks added in the following patches.

Cc: Kevin Hilman <khilman@kernel.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/base/power/domain.c | 121 +++++++++++++++++++++++++++++---------------
 include/linux/pm_domain.h   |   5 +-
 2 files changed, 85 insertions(+), 41 deletions(-)

diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 1a6073aa..4194012 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -39,6 +39,46 @@
 static LIST_HEAD(gpd_list);
 static DEFINE_MUTEX(gpd_list_lock);
 
+struct genpd_lock_ops {
+	void (*lock)(struct generic_pm_domain *genpd);
+	void (*lock_nested)(struct generic_pm_domain *genpd, int depth);
+	int (*lock_interruptible)(struct generic_pm_domain *genpd);
+	void (*unlock)(struct generic_pm_domain *genpd);
+};
+
+static void genpd_lock_mtx(struct generic_pm_domain *genpd)
+{
+	mutex_lock(&genpd->mlock);
+}
+
+static void genpd_lock_nested_mtx(struct generic_pm_domain *genpd,
+					int depth)
+{
+	mutex_lock_nested(&genpd->mlock, depth);
+}
+
+static int genpd_lock_interruptible_mtx(struct generic_pm_domain *genpd)
+{
+	return mutex_lock_interruptible(&genpd->mlock);
+}
+
+static void genpd_unlock_mtx(struct generic_pm_domain *genpd)
+{
+	return mutex_unlock(&genpd->mlock);
+}
+
+static const struct genpd_lock_ops genpd_mtx_ops = {
+	.lock = genpd_lock_mtx,
+	.lock_nested = genpd_lock_nested_mtx,
+	.lock_interruptible = genpd_lock_interruptible_mtx,
+	.unlock = genpd_unlock_mtx,
+};
+
+#define genpd_lock(p)			p->lock_ops->lock(p)
+#define genpd_lock_nested(p, d)		p->lock_ops->lock_nested(p, d)
+#define genpd_lock_interruptible(p)	p->lock_ops->lock_interruptible(p)
+#define genpd_unlock(p)			p->lock_ops->unlock(p)
+
 /*
  * Get the generic PM domain for a particular struct device.
  * This validates the struct device pointer, the PM domain pointer,
@@ -200,9 +240,9 @@ static int genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth)
 
 		genpd_sd_counter_inc(master);
 
-		mutex_lock_nested(&master->lock, depth + 1);
+		genpd_lock_nested(master, depth + 1);
 		ret = genpd_poweron(master, depth + 1);
-		mutex_unlock(&master->lock);
+		genpd_unlock(master);
 
 		if (ret) {
 			genpd_sd_counter_dec(master);
@@ -255,9 +295,9 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
 		spin_unlock_irq(&dev->power.lock);
 
 		if (!IS_ERR(genpd)) {
-			mutex_lock(&genpd->lock);
+			genpd_lock(genpd);
 			genpd->max_off_time_changed = true;
-			mutex_unlock(&genpd->lock);
+			genpd_unlock(genpd);
 		}
 
 		dev = dev->parent;
@@ -354,9 +394,9 @@ static void genpd_power_off_work_fn(struct work_struct *work)
 
 	genpd = container_of(work, struct generic_pm_domain, power_off_work);
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 	genpd_poweroff(genpd, true);
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 }
 
 /**
@@ -472,9 +512,9 @@ static int genpd_runtime_suspend(struct device *dev)
 	if (dev->power.irq_safe)
 		return 0;
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 	genpd_poweroff(genpd, false);
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	return 0;
 }
@@ -509,9 +549,9 @@ static int genpd_runtime_resume(struct device *dev)
 		goto out;
 	}
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 	ret = genpd_poweron(genpd, 0);
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	if (ret)
 		return ret;
@@ -547,9 +587,9 @@ err_stop:
 	genpd_stop_dev(genpd, dev);
 err_poweroff:
 	if (!dev->power.irq_safe) {
-		mutex_lock(&genpd->lock);
+		genpd_lock(genpd);
 		genpd_poweroff(genpd, 0);
-		mutex_unlock(&genpd->lock);
+		genpd_unlock(genpd);
 	}
 
 	return ret;
@@ -732,20 +772,20 @@ static int pm_genpd_prepare(struct device *dev)
 	if (resume_needed(dev, genpd))
 		pm_runtime_resume(dev);
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 
 	if (genpd->prepared_count++ == 0)
 		genpd->suspended_count = 0;
 
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	ret = pm_generic_prepare(dev);
 	if (ret) {
-		mutex_lock(&genpd->lock);
+		genpd_lock(genpd);
 
 		genpd->prepared_count--;
 
-		mutex_unlock(&genpd->lock);
+		genpd_unlock(genpd);
 	}
 
 	return ret;
@@ -936,13 +976,13 @@ static void pm_genpd_complete(struct device *dev)
 
 	pm_generic_complete(dev);
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 
 	genpd->prepared_count--;
 	if (!genpd->prepared_count)
 		genpd_queue_power_off_work(genpd);
 
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 }
 
 /**
@@ -1071,7 +1111,7 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
 	if (IS_ERR(gpd_data))
 		return PTR_ERR(gpd_data);
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 
 	if (genpd->prepared_count > 0) {
 		ret = -EAGAIN;
@@ -1088,7 +1128,7 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
 	list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
 
  out:
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	if (ret)
 		genpd_free_dev_data(dev, gpd_data);
@@ -1130,7 +1170,7 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
 	gpd_data = to_gpd_data(pdd);
 	dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 
 	if (genpd->prepared_count > 0) {
 		ret = -EAGAIN;
@@ -1145,14 +1185,14 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
 
 	list_del_init(&pdd->list_node);
 
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	genpd_free_dev_data(dev, gpd_data);
 
 	return 0;
 
  out:
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 	dev_pm_qos_add_notifier(dev, &gpd_data->nb);
 
 	return ret;
@@ -1187,8 +1227,8 @@ static int genpd_add_subdomain(struct generic_pm_domain *genpd,
 	if (!link)
 		return -ENOMEM;
 
-	mutex_lock(&subdomain->lock);
-	mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
+	genpd_lock(subdomain);
+	genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING);
 
 	if (genpd->status == GPD_STATE_POWER_OFF
 	    &&  subdomain->status != GPD_STATE_POWER_OFF) {
@@ -1211,8 +1251,8 @@ static int genpd_add_subdomain(struct generic_pm_domain *genpd,
 		genpd_sd_counter_inc(genpd);
 
  out:
-	mutex_unlock(&genpd->lock);
-	mutex_unlock(&subdomain->lock);
+	genpd_unlock(genpd);
+	genpd_unlock(subdomain);
 	if (ret)
 		kfree(link);
 	return ret;
@@ -1250,8 +1290,8 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
 		return -EINVAL;
 
-	mutex_lock(&subdomain->lock);
-	mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
+	genpd_lock(subdomain);
+	genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING);
 
 	if (!list_empty(&subdomain->master_links) || subdomain->device_count) {
 		pr_warn("%s: unable to remove subdomain %s\n", genpd->name,
@@ -1275,8 +1315,8 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 	}
 
 out:
-	mutex_unlock(&genpd->lock);
-	mutex_unlock(&subdomain->lock);
+	genpd_unlock(genpd);
+	genpd_unlock(subdomain);
 
 	return ret;
 }
@@ -1316,7 +1356,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
 	INIT_LIST_HEAD(&genpd->master_links);
 	INIT_LIST_HEAD(&genpd->slave_links);
 	INIT_LIST_HEAD(&genpd->dev_list);
-	mutex_init(&genpd->lock);
+	mutex_init(&genpd->mlock);
+	genpd->lock_ops = &genpd_mtx_ops;
 	genpd->gov = gov;
 	INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
 	atomic_set(&genpd->sd_count, 0);
@@ -1364,16 +1405,16 @@ static int genpd_remove(struct generic_pm_domain *genpd)
 	if (IS_ERR_OR_NULL(genpd))
 		return -EINVAL;
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 
 	if (genpd->has_provider) {
-		mutex_unlock(&genpd->lock);
+		genpd_unlock(genpd);
 		pr_err("Provider present, unable to remove %s\n", genpd->name);
 		return -EBUSY;
 	}
 
 	if (!list_empty(&genpd->master_links) || genpd->device_count) {
-		mutex_unlock(&genpd->lock);
+		genpd_unlock(genpd);
 		pr_err("%s: unable to remove %s\n", __func__, genpd->name);
 		return -EBUSY;
 	}
@@ -1385,7 +1426,7 @@ static int genpd_remove(struct generic_pm_domain *genpd)
 	}
 
 	list_del(&genpd->gpd_list_node);
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 	cancel_work_sync(&genpd->power_off_work);
 	kfree(genpd->free);
 	pr_debug("%s: removed %s\n", __func__, genpd->name);
@@ -1909,9 +1950,9 @@ int genpd_dev_pm_attach(struct device *dev)
 	dev->pm_domain->detach = genpd_dev_pm_detach;
 	dev->pm_domain->sync = genpd_dev_pm_sync;
 
-	mutex_lock(&pd->lock);
+	genpd_lock(pd);
 	ret = genpd_poweron(pd, 0);
-	mutex_unlock(&pd->lock);
+	genpd_unlock(pd);
 out:
 	return ret ? -EPROBE_DEFER : 0;
 }
@@ -2064,7 +2105,7 @@ static int pm_genpd_summary_one(struct seq_file *s,
 	char state[16];
 	int ret;
 
-	ret = mutex_lock_interruptible(&genpd->lock);
+	ret = genpd_lock_interruptible(genpd);
 	if (ret)
 		return -ERESTARTSYS;
 
@@ -2101,7 +2142,7 @@ static int pm_genpd_summary_one(struct seq_file *s,
 
 	seq_puts(s, "\n");
 exit:
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	return 0;
 }
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 6a89881..811b968 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -42,13 +42,14 @@ struct genpd_power_state {
 	struct fwnode_handle *fwnode;
 };
 
+struct genpd_lock_ops;
+
 struct generic_pm_domain {
 	struct dev_pm_domain domain;	/* PM domain operations */
 	struct list_head gpd_list_node;	/* Node in the global PM domains list */
 	struct list_head master_links;	/* Links with PM domain as a master */
 	struct list_head slave_links;	/* Links with PM domain as a slave */
 	struct list_head dev_list;	/* List of devices */
-	struct mutex lock;
 	struct dev_power_governor *gov;
 	struct work_struct power_off_work;
 	struct fwnode_handle *provider;	/* Identity of the domain provider */
@@ -74,6 +75,8 @@ struct generic_pm_domain {
 	unsigned int state_count; /* number of states */
 	unsigned int state_idx; /* state that genpd will go to when off */
 	void *free; /* Free the state that was allocated for default */
+	const struct genpd_lock_ops *lock_ops;
+	struct mutex mlock;
 
 };
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 7/8] PM / Domains: Support IRQ safe PM domains
From: Lina Iyer @ 2016-10-14 17:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476467276-75094-1-git-send-email-lina.iyer@linaro.org>

Generic Power Domains currently support turning on/off only in process
context. This prevents the usage of PM domains for domains that could be
powered on/off in a context where IRQs are disabled. Many such domains
exist today and do not get powered off, when the IRQ safe devices in
that domain are powered off, because of this limitation.

However, not all domains can operate in IRQ safe contexts. Genpd
therefore, has to support both cases where the domain may or may not
operate in IRQ safe contexts. Configuring genpd to use an appropriate
lock for that domain, would allow domains that have IRQ safe devices to
runtime suspend and resume, in atomic context.

To achieve domain specific locking, set the domain's ->flag to
GENPD_FLAG_IRQ_SAFE while defining the domain. This indicates that genpd
should use a spinlock instead of a mutex for locking the domain. Locking
is abstracted through genpd_lock() and genpd_unlock() functions that use
the flag to determine the appropriate lock to be used for that domain.

Domains that have lower latency to suspend and resume and can operate
with IRQs disabled may now be able to save power, when the component
devices and sub-domains are idle at runtime.

The restriction this imposes on the domain hierarchy is that non-IRQ
safe domains may not have IRQ-safe subdomains, but IRQ safe domains may
have IRQ safe and non-IRQ safe subdomains and devices.

Cc: Ulf Hansson <ulf.hansson@linaro.org>
Cc: Kevin Hilman <khilman@kernel.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/base/power/domain.c | 111 ++++++++++++++++++++++++++++++++++++++++----
 include/linux/pm_domain.h   |  10 +++-
 2 files changed, 110 insertions(+), 11 deletions(-)

diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 4194012..aac656a 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -74,11 +74,70 @@ static const struct genpd_lock_ops genpd_mtx_ops = {
 	.unlock = genpd_unlock_mtx,
 };
 
+static void genpd_lock_spin(struct generic_pm_domain *genpd)
+	__acquires(&genpd->slock)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&genpd->slock, flags);
+	genpd->lock_flags = flags;
+}
+
+static void genpd_lock_nested_spin(struct generic_pm_domain *genpd,
+					int depth)
+	__acquires(&genpd->slock)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave_nested(&genpd->slock, flags, depth);
+	genpd->lock_flags = flags;
+}
+
+static int genpd_lock_interruptible_spin(struct generic_pm_domain *genpd)
+	__acquires(&genpd->slock)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&genpd->slock, flags);
+	genpd->lock_flags = flags;
+	return 0;
+}
+
+static void genpd_unlock_spin(struct generic_pm_domain *genpd)
+	__releases(&genpd->slock)
+{
+	spin_unlock_irqrestore(&genpd->slock, genpd->lock_flags);
+}
+
+static const struct genpd_lock_ops genpd_spin_ops = {
+	.lock = genpd_lock_spin,
+	.lock_nested = genpd_lock_nested_spin,
+	.lock_interruptible = genpd_lock_interruptible_spin,
+	.unlock = genpd_unlock_spin,
+};
+
 #define genpd_lock(p)			p->lock_ops->lock(p)
 #define genpd_lock_nested(p, d)		p->lock_ops->lock_nested(p, d)
 #define genpd_lock_interruptible(p)	p->lock_ops->lock_interruptible(p)
 #define genpd_unlock(p)			p->lock_ops->unlock(p)
 
+#define genpd_is_irq_safe(genpd)	(genpd->flags & GENPD_FLAG_IRQ_SAFE)
+
+static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev,
+		struct generic_pm_domain *genpd)
+{
+	bool ret;
+
+	ret = pm_runtime_is_irq_safe(dev) && !genpd_is_irq_safe(genpd);
+
+	/* Warn once for each IRQ safe dev in no sleep domain */
+	if (ret)
+		dev_warn_once(dev, "PM domain %s will not be powered off\n",
+				genpd->name);
+
+	return ret;
+}
+
 /*
  * Get the generic PM domain for a particular struct device.
  * This validates the struct device pointer, the PM domain pointer,
@@ -343,7 +402,12 @@ static int genpd_poweroff(struct generic_pm_domain *genpd, bool is_async)
 		if (stat > PM_QOS_FLAGS_NONE)
 			return -EBUSY;
 
-		if (!pm_runtime_suspended(pdd->dev) || pdd->dev->power.irq_safe)
+		/*
+		 * Do not allow PM domain to be powered off, when an IRQ safe
+		 * device is part of a non-IRQ safe domain.
+		 */
+		if (!pm_runtime_suspended(pdd->dev) ||
+			irq_safe_dev_in_no_sleep_domain(pdd->dev, genpd))
 			not_suspended++;
 	}
 
@@ -506,10 +570,10 @@ static int genpd_runtime_suspend(struct device *dev)
 	}
 
 	/*
-	 * If power.irq_safe is set, this routine will be run with interrupts
-	 * off, so it can't use mutexes.
+	 * If power.irq_safe is set, this routine may be run with
+	 * IRQs disabled, so suspend only if the PM domain also is irq_safe.
 	 */
-	if (dev->power.irq_safe)
+	if (irq_safe_dev_in_no_sleep_domain(dev, genpd))
 		return 0;
 
 	genpd_lock(genpd);
@@ -543,8 +607,11 @@ static int genpd_runtime_resume(struct device *dev)
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	/* If power.irq_safe, the PM domain is never powered off. */
-	if (dev->power.irq_safe) {
+	/*
+	 * As we don't power off a non IRQ safe domain, which holds
+	 * an IRQ safe device, we don't need to restore power to it.
+	 */
+	if (irq_safe_dev_in_no_sleep_domain(dev, genpd)) {
 		timed = false;
 		goto out;
 	}
@@ -586,7 +653,8 @@ static int genpd_runtime_resume(struct device *dev)
 err_stop:
 	genpd_stop_dev(genpd, dev);
 err_poweroff:
-	if (!dev->power.irq_safe) {
+	if (!pm_runtime_is_irq_safe(dev) ||
+		(pm_runtime_is_irq_safe(dev) && genpd_is_irq_safe(genpd))) {
 		genpd_lock(genpd);
 		genpd_poweroff(genpd, 0);
 		genpd_unlock(genpd);
@@ -1223,6 +1291,17 @@ static int genpd_add_subdomain(struct generic_pm_domain *genpd,
 	    || genpd == subdomain)
 		return -EINVAL;
 
+	/*
+	 * If the domain can be powered on/off in an IRQ safe
+	 * context, ensure that the subdomain can also be
+	 * powered on/off in that context.
+	 */
+	if (!genpd_is_irq_safe(genpd) && genpd_is_irq_safe(subdomain)) {
+		WARN("Parent %s of subdomain %s must be IRQ safe\n",
+				genpd->name, subdomain->name);
+		return -EINVAL;
+	}
+
 	link = kzalloc(sizeof(*link), GFP_KERNEL);
 	if (!link)
 		return -ENOMEM;
@@ -1337,6 +1416,17 @@ static int genpd_set_default_power_state(struct generic_pm_domain *genpd)
 	return 0;
 }
 
+static void genpd_lock_init(struct generic_pm_domain *genpd)
+{
+	if (genpd->flags & GENPD_FLAG_IRQ_SAFE) {
+		spin_lock_init(&genpd->slock);
+		genpd->lock_ops = &genpd_spin_ops;
+	} else {
+		mutex_init(&genpd->mlock);
+		genpd->lock_ops = &genpd_mtx_ops;
+	}
+}
+
 /**
  * pm_genpd_init - Initialize a generic I/O PM domain object.
  * @genpd: PM domain object to initialize.
@@ -1356,8 +1446,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
 	INIT_LIST_HEAD(&genpd->master_links);
 	INIT_LIST_HEAD(&genpd->slave_links);
 	INIT_LIST_HEAD(&genpd->dev_list);
-	mutex_init(&genpd->mlock);
-	genpd->lock_ops = &genpd_mtx_ops;
+	genpd_lock_init(genpd);
 	genpd->gov = gov;
 	INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
 	atomic_set(&genpd->sd_count, 0);
@@ -2131,7 +2220,9 @@ static int pm_genpd_summary_one(struct seq_file *s,
 	}
 
 	list_for_each_entry(pm_data, &genpd->dev_list, list_node) {
-		kobj_path = kobject_get_path(&pm_data->dev->kobj, GFP_KERNEL);
+		kobj_path = kobject_get_path(&pm_data->dev->kobj,
+				genpd_is_irq_safe(genpd) ?
+				GFP_ATOMIC : GFP_KERNEL);
 		if (kobj_path == NULL)
 			continue;
 
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 811b968..81ece61 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -15,9 +15,11 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/notifier.h>
+#include <linux/spinlock.h>
 
 /* Defines used for the flags field in the struct generic_pm_domain */
 #define GENPD_FLAG_PM_CLK	(1U << 0) /* PM domain uses PM clk */
+#define GENPD_FLAG_IRQ_SAFE	(1U << 1) /* PM domain operates in atomic */
 
 enum gpd_status {
 	GPD_STATE_ACTIVE = 0,	/* PM domain is active */
@@ -76,7 +78,13 @@ struct generic_pm_domain {
 	unsigned int state_idx; /* state that genpd will go to when off */
 	void *free; /* Free the state that was allocated for default */
 	const struct genpd_lock_ops *lock_ops;
-	struct mutex mlock;
+	union {
+		struct mutex mlock;
+		struct {
+			spinlock_t slock;
+			unsigned long lock_flags;
+		};
+	};
 
 };
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 8/8] PM / doc: Update device documentation for devices in IRQ safe PM domains
From: Lina Iyer @ 2016-10-14 17:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476467276-75094-1-git-send-email-lina.iyer@linaro.org>

Update documentation to reflect the changes made to support IRQ safe PM
domains.

Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 Documentation/power/devices.txt | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 8ba6625..0401b53 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -607,7 +607,14 @@ individually.  Instead, a set of devices sharing a power resource can be put
 into a low-power state together at the same time by turning off the shared
 power resource.  Of course, they also need to be put into the full-power state
 together, by turning the shared power resource on.  A set of devices with this
-property is often referred to as a power domain.
+property is often referred to as a power domain. A power domain may also be
+nested inside another power domain.
+
+Devices and PM domains may be defined as IRQ-safe, if they can be powered
+on/off even when the IRQs are disabled. An IRQ-safe device in a domain will
+disallow power management on the domain, unless the domain is also defined as
+IRQ-safe. The restriction this framework imposes on the parent domain of an
+IRQ-safe domain is that it must also be defined as IRQ-safe.
 
 Support for power domains is provided through the pm_domain field of struct
 device.  This field is a pointer to an object of type struct dev_pm_domain,
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 4/5] arm64: mm: support additional contiguous kernel mapping region sizes
From: Ard Biesheuvel @ 2016-10-14 17:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161014102853.GA23339@e104818-lin.cambridge.arm.com>

On 14 October 2016 at 11:28, Catalin Marinas <catalin.marinas@arm.com> wrote:
> On Wed, Oct 12, 2016 at 12:23:44PM +0100, Ard Biesheuvel wrote:
>> Extend the basic support for kernel mappings using contiguous regions
>> by adding support for contiguous PUDs (4k granule only), either as a
>> discrete level or folded into the PGDs. In the same way, handle folded
>> PMDs so that contiguous PMDs (for 16k and 64k granule kernels) will
>> work as expected for 2 levels of translation as well.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  arch/arm64/include/asm/pgtable-hwdef.h |  6 +++
>>  arch/arm64/mm/mmu.c                    | 40 +++++++++++++++++++-
>>  2 files changed, 44 insertions(+), 2 deletions(-)
>
> After looking at this patch, I concluded it's not worth hassle as no
> hardware I'm aware of currently would benefit from it.  We can revisit
> it in the future if we hear otherwise.
>

That is what I expected, which is why this is a separate patch. I will
drop this patch and the next one from the next version of the series.

^ permalink raw reply

* [arm-soc:to-build 18/18] drivers/spi/spi-fsl-espi.c:462:4: warning: 'rx_data' may be used uninitialized in this function
From: kbuild test robot @ 2016-10-14 18:19 UTC (permalink / raw)
  To: linux-arm-kernel

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git to-build
head:   9f700f316330ee9341e1e817468bd272a4535291
commit: 9f700f316330ee9341e1e817468bd272a4535291 [18/18] Revert "Disable "maybe-uninitialized" warning globally"
config: powerpc-kmp204x_defconfig (attached as .config)
compiler: powerpc-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        git checkout 9f700f316330ee9341e1e817468bd272a4535291
        # save the attached .config to linux build tree
        make.cross ARCH=powerpc 

Note: it may well be a FALSE warning. FWIW you are at least aware of it now.
http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings

All warnings (new ones prefixed by >>):

   drivers/spi/spi-fsl-espi.c: In function 'fsl_espi_irq':
>> drivers/spi/spi-fsl-espi.c:462:4: warning: 'rx_data' may be used uninitialized in this function [-Wmaybe-uninitialized]
       mspi->get_rx(rx_data, mspi);
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/spi/spi-fsl-espi.c:421:7: note: 'rx_data' was declared here
      u32 rx_data, tmp;
          ^~~~~~~

vim +/rx_data +462 drivers/spi/spi-fsl-espi.c

e6289d63 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-12-21  446  		} else {
6319a680 drivers/spi/spi-fsl-espi.c Nobuteru Hayashi 2016-03-18  447  			rx_nr_bytes = mspi->len;
e6289d63 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-12-21  448  			tmp = mspi->len;
e6289d63 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-12-21  449  			rx_data = 0;
e6289d63 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-12-21  450  			while (tmp--) {
46afd38b drivers/spi/spi-fsl-espi.c Heiner Kallweit  2016-09-13  451  				rx_data_8 = fsl_espi_read_reg8(mspi,
46afd38b drivers/spi/spi-fsl-espi.c Heiner Kallweit  2016-09-13  452  							       ESPI_SPIRF);
e6289d63 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-12-21  453  				rx_data |= (rx_data_8 << (tmp * 8));
e6289d63 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-12-21  454  			}
e6289d63 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-12-21  455  
e6289d63 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-12-21  456  			rx_data <<= (4 - mspi->len) * 8;
e6289d63 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-12-21  457  		}
e6289d63 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-12-21  458  
6319a680 drivers/spi/spi-fsl-espi.c Nobuteru Hayashi 2016-03-18  459  		mspi->len -= rx_nr_bytes;
8b60d6c2 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-10-12  460  
8b60d6c2 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-10-12  461  		if (mspi->rx)
8b60d6c2 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-10-12 @462  			mspi->get_rx(rx_data, mspi);
8b60d6c2 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-10-12  463  	}
8b60d6c2 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-10-12  464  
81abc2ec drivers/spi/spi-fsl-espi.c Heiner Kallweit  2016-09-13  465  	if (!(events & SPIE_TNF)) {
8b60d6c2 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-10-12  466  		int ret;
8b60d6c2 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-10-12  467  
8b60d6c2 drivers/spi/spi_fsl_espi.c Mingkai Hu       2010-10-12  468  		/* spin until TX is done */
46afd38b drivers/spi/spi-fsl-espi.c Heiner Kallweit  2016-09-13  469  		ret = spin_event_timeout(((events = fsl_espi_read_reg(
81abc2ec drivers/spi/spi-fsl-espi.c Heiner Kallweit  2016-09-13  470  				mspi, ESPI_SPIE)) & SPIE_TNF), 1000, 0);

:::::: The code at line 462 was first introduced by commit
:::::: 8b60d6c25b2a2d3525d5322de856c3ca408e5783 spi/fsl_spi: add eSPI controller support

:::::: TO: Mingkai Hu <Mingkai.hu@freescale.com>
:::::: CC: Grant Likely <grant.likely@secretlab.ca>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 16547 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161015/0ed9d6a0/attachment-0001.gz>

^ permalink raw reply

* [PATCH v3 1/2] devicetree: Add vendor prefix for Rikomagic
From: Heiko Stuebner @ 2016-10-14 18:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <d51c7719a314f723a0a69b932997502a2fe0e3ee.1475957884.git.paweljarosz3691@gmail.com>

Am Samstag, 8. Oktober 2016, 22:22:05 CEST schrieb Pawe? Jarosz:
> Add Rikomagic to vendor-prefixes.txt
> 
> Signed-off-by: Pawe? Jarosz <paweljarosz3691@gmail.com>
> ---
> 
> Changes in v2:
> - none
> 
> Changes in v3:
> - none
> 
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt
> b/Documentation/devicetree/bindings/vendor-prefixes.txt index
> 69caf14..3edfa08 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -224,6 +224,7 @@ realtek Realtek Semiconductor Corp.
>  renesas	Renesas Electronics Corporation
>  richtek	Richtek Technology Corporation
>  ricoh	Ricoh Co. Ltd.
> +rikomagic	Rikomagic
				^ Rikomagic Tech Corp. Ltd

(according to http://www.rikomagic.com/en/index.html)

But I can change that myself. I'll just need to wait a bit more if Rob or Mark 
want to Ack this vendor-prefix addition.


Heiko

^ permalink raw reply

* [PATCH] arm64: kaslr: fix breakage with CONFIG_MODVERSIONS=y
From: Ard Biesheuvel @ 2016-10-14 18:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <57FFE78E.4040002@codeaurora.org>

On 13 October 2016 at 20:59, Timur Tabi <timur@codeaurora.org> wrote:
> Ard Biesheuvel wrote:
>>
>> As it turns out, the KASLR code breaks CONFIG_MODVERSIONS, since the
>> kcrctab has an absolute address field that is relocated at runtime
>> when the kernel offset is randomized.
>>
>> This has been fixed already for PowerPC in the past, so simply wire up
>> the existing code dealing with this issue.
>>
>> Signed-off-by: Ard Biesheuvel<ard.biesheuvel@linaro.org>
>
>
> Tested-by: Timur Tabi <timur@codeaurora.org>
>

Thanks. I will resend this with a fixes: tag and a better description

^ permalink raw reply

* [PATCH] arm64: kaslr: fix breakage with CONFIG_MODVERSIONS=y
From: Will Deacon @ 2016-10-14 18:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu-sdgkoQvbpgHXZmDyxg6NTGJpC+hsqzdbwTkny+TeqfA@mail.gmail.com>

On Fri, Oct 14, 2016 at 07:23:15PM +0100, Ard Biesheuvel wrote:
> On 13 October 2016 at 20:59, Timur Tabi <timur@codeaurora.org> wrote:
> > Ard Biesheuvel wrote:
> >>
> >> As it turns out, the KASLR code breaks CONFIG_MODVERSIONS, since the
> >> kcrctab has an absolute address field that is relocated at runtime
> >> when the kernel offset is randomized.
> >>
> >> This has been fixed already for PowerPC in the past, so simply wire up
> >> the existing code dealing with this issue.
> >>
> >> Signed-off-by: Ard Biesheuvel<ard.biesheuvel@linaro.org>
> >
> >
> > Tested-by: Timur Tabi <timur@codeaurora.org>
> >
> 
> Thanks. I will resend this with a fixes: tag and a better description

Feel free, but I already queued it locally and added the Fixes tag myself.
I'm just waiting for Lorenzo to post a fix to the ACPI NUMA stuff, then
I'll send these two up together next week.
Will

^ permalink raw reply

* [PATCH] clk: samsung: clk-exynos-audss: Fix module autoload
From: Javier Martinez Canillas @ 2016-10-14 18:44 UTC (permalink / raw)
  To: linux-arm-kernel

If the driver is built as a module, autoload won't work because the module
alias information is not filled. So user-space can't match the registered
device with the corresponding module.

Export the module alias information using the MODULE_DEVICE_TABLE() macro.

Before this patch:

$ modinfo drivers/clk/samsung/clk-exynos-audss.ko | grep alias
alias:          platform:exynos-audss-clk

After this patch:

$ modinfo drivers/clk/samsung/clk-exynos-audss.ko | grep alias
alias:          platform:exynos-audss-clk
alias:          of:N*T*Csamsung,exynos5420-audss-clockC*
alias:          of:N*T*Csamsung,exynos5420-audss-clock
alias:          of:N*T*Csamsung,exynos5410-audss-clockC*
alias:          of:N*T*Csamsung,exynos5410-audss-clock
alias:          of:N*T*Csamsung,exynos5250-audss-clockC*
alias:          of:N*T*Csamsung,exynos5250-audss-clock
alias:          of:N*T*Csamsung,exynos4210-audss-clockC*
alias:          of:N*T*Csamsung,exynos4210-audss-clock

Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
---

 drivers/clk/samsung/clk-exynos-audss.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c
index 51d152f735cc..17e68a724945 100644
--- a/drivers/clk/samsung/clk-exynos-audss.c
+++ b/drivers/clk/samsung/clk-exynos-audss.c
@@ -106,6 +106,7 @@ static const struct of_device_id exynos_audss_clk_of_match[] = {
 	},
 	{ },
 };
+MODULE_DEVICE_TABLE(of, exynos_audss_clk_of_match);
 
 static void exynos_audss_clk_teardown(void)
 {
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 1/2] devicetree: Add vendor prefix for Rikomagic
From: Paweł Jarosz @ 2016-10-14 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <7746988.aAT8rmUZDV@phil>

>> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt
>> b/Documentation/devicetree/bindings/vendor-prefixes.txt index
>> 69caf14..3edfa08 100644
>> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
>> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
>> @@ -224,6 +224,7 @@ realtek Realtek Semiconductor Corp.
>>   renesas	Renesas Electronics Corporation
>>   richtek	Richtek Technology Corporation
>>   ricoh	Ricoh Co. Ltd.
>> +rikomagic	Rikomagic
> 				^ Rikomagic Tech Corp. Ltd
>
> (according to http://www.rikomagic.com/en/index.html)
>
> But I can change that myself. I'll just need to wait a bit more if Rob or Mark
> want to Ack this vendor-prefix addition.
>
>
> Heiko

Sorry for that.


Pawe?

^ permalink raw reply

* [PATCH] arm64: kaslr: fix breakage with CONFIG_MODVERSIONS=y
From: Ard Biesheuvel @ 2016-10-14 19:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161014182637.GF6534@arm.com>

On 14 October 2016 at 19:26, Will Deacon <will.deacon@arm.com> wrote:
> On Fri, Oct 14, 2016 at 07:23:15PM +0100, Ard Biesheuvel wrote:
>> On 13 October 2016 at 20:59, Timur Tabi <timur@codeaurora.org> wrote:
>> > Ard Biesheuvel wrote:
>> >>
>> >> As it turns out, the KASLR code breaks CONFIG_MODVERSIONS, since the
>> >> kcrctab has an absolute address field that is relocated at runtime
>> >> when the kernel offset is randomized.
>> >>
>> >> This has been fixed already for PowerPC in the past, so simply wire up
>> >> the existing code dealing with this issue.
>> >>
>> >> Signed-off-by: Ard Biesheuvel<ard.biesheuvel@linaro.org>
>> >
>> >
>> > Tested-by: Timur Tabi <timur@codeaurora.org>
>> >
>>
>> Thanks. I will resend this with a fixes: tag and a better description
>
> Feel free, but I already queued it locally and added the Fixes tag myself.
> I'm just waiting for Lorenzo to post a fix to the ACPI NUMA stuff, then
> I'll send these two up together next week.

It's no big deal. The description is not entirely accurate in the
sense that the kcrctab does not contain an absolute address field, but
it masquerades as an absolute address so that the build system can
populate the kcrctab entries using a linker script include containing
name=value pairs. This does not only result in 4 wasted bytes per CRC,
but on PPC64 and arm64 with CONFIG_RELOCATABLE=y, it also results in
the breakage this patch addresses, and more importantly, results in a
24 byte RELA entry per CRC in the __init section. So I intend to
propose a patch to change this in the generic code, after which this
patch could be reverted.

BTW, I spotted another KASLR issue, with ftrace this time, where it
attempts to poke relative branches into modules targeting the core
kernel, which is likely to fail when
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y. Should we address this at the
Kconfig level? Or should we try to fix ftrace to support long
branches?

^ permalink raw reply

* master build: 2 failures 4 warnings (v4.8-11811-g35ff96d)
From: Arnd Bergmann @ 2016-10-14 20:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161014103344.GB3304@dell>

On Friday, October 14, 2016 11:33:44 AM CEST Lee Jones wrote:
> On Tue, 11 Oct 2016, Mark Brown wrote:
> 
> > On Tue, Oct 11, 2016 at 07:30:35AM +0100, Build bot for Mark Brown wrote:
> > 
> > Linus' tree is currently failing to build arm and arm64 allmodconfigs
> > with:
> > 
> > >     arm64-allmodconfig
> > > ERROR: "irq_set_parent" [drivers/mfd/tps65217.ko] undefined!
> > 
> > >     arm-allmodconfig
> > > ERROR: "irq_set_parent" [drivers/mfd/tps65217.ko] undefined!
> > 
> > due to 6556bdacf646fc (mfd: tps65217: Add support for IRQs) since
> > irq_set_parent() isn't exported.  This has been present in -next
> > for getting on for a month, a patch was proposed adding the relevant
> > export but that isn't present in -next yet.
> > 
> > The function is being used in order to enable lazy IRQ disabling for
> > threaded interrupts:
> > 
> >       https://www.spinics.net/lists/arm-kernel/msg532864.html
> > 
> > What's the plan for getting this fixed in Linus' tree?
> 
> Here's the conversation:
> 
>   https://www.spinics.net/lists/arm-kernel/msg531850.html
> 
> I'm waiting on a firm answer from Arnd and Thomas before applying
> anything.

I don't understand what the hardware does, so I'm not really
able to answer this. Maybe just mark the driver as 'depends on
BROKEN' for now?

	Arnd

^ permalink raw reply

* [PATCH 23/57] [media] exynos4-is: don't break long lines
From: Mauro Carvalho Chehab @ 2016-10-14 20:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1476475770.git.mchehab@s-opensource.com>

Due to the 80-cols checkpatch warnings, several strings
were broken into multiple lines. This is not considered
a good practice anymore, as it makes harder to grep for
strings at the source code. So, join those continuation
lines.

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
---
 drivers/media/platform/exynos4-is/media-dev.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index 1a1154a9dfa4..e3a8709138fa 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -938,8 +938,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
 
 			csis = fmd->csis[pdata->mux_id].sd;
 			if (WARN(csis == NULL,
-				 "MIPI-CSI interface specified "
-				 "but s5p-csis module is not loaded!\n"))
+				 "MIPI-CSI interface specified but s5p-csis module is not loaded!\n"))
 				return -EINVAL;
 
 			pad = sensor->entity.num_pads - 1;
-- 
2.7.4

^ 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