* [PATCH 2/2] powerpc/83xx: map IMMR with a BAT.
From: Christophe Leroy @ 2019-08-23 12:50 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman, oss,
galak
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <b51b96090138aba1920d2cf7c0e0e348667f9a69.1566564560.git.christophe.leroy@c-s.fr>
On mpc83xx with a QE, IMMR is 2Mbytes.
On mpc83xx without a QE, IMMR is 1Mbytes.
Each driver will map a part of it to access the registers it needs.
Some driver will map the same part of IMMR as other drivers.
In order to reduce TLB misses, map the full IMMR with a BAT.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/platforms/83xx/misc.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c
index f46d7bf3b140..1e395b01c535 100644
--- a/arch/powerpc/platforms/83xx/misc.c
+++ b/arch/powerpc/platforms/83xx/misc.c
@@ -18,6 +18,8 @@
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
+#include <mm/mmu_decl.h>
+
#include "mpc83xx.h"
static __be32 __iomem *restart_reg_base;
@@ -145,6 +147,14 @@ void __init mpc83xx_setup_arch(void)
if (ppc_md.progress)
ppc_md.progress("mpc83xx_setup_arch()", 0);
+ if (!__map_without_bats) {
+ int immrsize = IS_ENABLED(CONFIG_QUICC_ENGINE) ? SZ_2M : SZ_1M;
+
+ ioremap_bot = ALIGN_DOWN(ioremap_bot - immrsize, immrsize);
+ setbat(-1, ioremap_bot, get_immrbase(), immrsize, PAGE_KERNEL_NCG);
+ update_bats();
+ }
+
mpc83xx_setup_pci();
}
--
2.13.3
^ permalink raw reply related
* Re: [PATCH v2] powerpc/powernv: Add ultravisor message log interface
From: Michael Ellerman @ 2019-08-23 12:48 UTC (permalink / raw)
To: Claudio Carvalho, linuxppc-dev
Cc: Madhavan Srinivasan, Michael Anderson, Ram Pai, Claudio Carvalho,
kvm-ppc, Ryan Grimm, Oliver O'Halloran
In-Reply-To: <20190823060654.28842-1-cclaudio@linux.ibm.com>
Hi Claudio,
Claudio Carvalho <cclaudio@linux.ibm.com> writes:
> Ultravisor (UV) provides an in-memory console which follows the OPAL
> in-memory console structure.
>
> This patch extends the OPAL msglog code to also initialize the UV memory
> console and provide a sysfs interface (uv_msglog) for userspace to view
> the UV message log.
>
> CC: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
> CC: Oliver O'Halloran <oohall@gmail.com>
> Signed-off-by: Claudio Carvalho <cclaudio@linux.ibm.com>
> ---
> This patch depends on the "kvmppc: Paravirtualize KVM to support
> ultravisor" patchset submitted by Claudio Carvalho.
> ---
> arch/powerpc/platforms/powernv/opal-msglog.c | 99 ++++++++++++++------
> 1 file changed, 72 insertions(+), 27 deletions(-)
I think the code changes look mostly OK here.
But I'm not sure about the end result in sysfs.
If I'm reading it right this will create:
/sys/firmware/opal/uv_msglog
Which I think is a little weird, because the UV is not OPAL.
So I guess I wonder if the file should be created elsewhere to avoid any
confusion and keep things nicely separated.
Possibly /sys/firmware/ultravisor/msglog ?
cheers
^ permalink raw reply
* [PATCH] powerpc/64: Fix stacktrace on BE when function_graph is enabled
From: Michael Ellerman @ 2019-08-23 12:29 UTC (permalink / raw)
To: linuxppc-dev
Currently if we oops or warn while function_graph is active the stack
trace looks like:
.trace_graph_return+0xac/0x100
.ftrace_return_to_handler+0x98/0x140
.return_to_handler+0x20/0x40
.return_to_handler+0x0/0x40
.return_to_handler+0x0/0x40
.return_to_handler+0x0/0x40
.return_to_handler+0x0/0x40
.return_to_handler+0x0/0x40
.return_to_handler+0x0/0x40
.cpu_startup_entry+0x34/0x40
.start_secondary+0x680/0x6f0
start_secondary_prolog+0x10/0x14
Notice the multiple entries that just show .return_to_handler.
There is logic in show_stack() to detect this case and print the
traced function, but we inadvertently broke it in commit
7d56c65a6ff9 ("powerpc/ftrace: Remove mod_return_to_handler") (2014),
because that commit accidentally removed the dereference of rth which
gets the text address from the function descriptor. Hence this is only
broken on big endian (or technically ELFv1).
Fix it by using the proper accessor, which is ppc_function_entry().
Result is we get a stack trace such as:
.trace_graph_return+0x134/0x160
.ftrace_return_to_handler+0x94/0x140
.return_to_handler+0x20/0x40
.return_to_handler+0x0/0x40 (.shared_cede_loop+0x48/0x130)
.return_to_handler+0x0/0x40 (.cpuidle_enter_state+0xa0/0x690)
.return_to_handler+0x0/0x40 (.cpuidle_enter+0x44/0x70)
.return_to_handler+0x0/0x40 (.call_cpuidle+0x68/0xc0)
.return_to_handler+0x0/0x40 (.do_idle+0x37c/0x400)
.return_to_handler+0x0/0x40 (.cpu_startup_entry+0x30/0x50)
.rest_init+0x224/0x348
Fixes: 7d56c65a6ff9 ("powerpc/ftrace: Remove mod_return_to_handler")
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/kernel/process.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 8fc4de0d22b4..1601d7cfe45e 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -2048,7 +2048,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
struct ftrace_ret_stack *ret_stack;
extern void return_to_handler(void);
- unsigned long rth = (unsigned long)return_to_handler;
+ unsigned long rth = ppc_function_entry(return_to_handler);
int curr_frame = 0;
#endif
--
2.21.0
^ permalink raw reply related
* Re: [PATCH v7 0/7] KVMPPC driver to manage secure guest pages
From: Michael Ellerman @ 2019-08-23 11:57 UTC (permalink / raw)
To: Paul Mackerras, Bharata B Rao
Cc: linuxram, cclaudio, kvm-ppc, linux-mm, jglisse, aneesh.kumar,
paulus, sukadev, linuxppc-dev, hch
In-Reply-To: <20190823041747.ctquda5uwvy2eiqz@oak.ozlabs.ibm.com>
Paul Mackerras <paulus@ozlabs.org> writes:
> On Thu, Aug 22, 2019 at 03:56:13PM +0530, Bharata B Rao wrote:
>> A pseries guest can be run as a secure guest on Ultravisor-enabled
>> POWER platforms. On such platforms, this driver will be used to manage
>> the movement of guest pages between the normal memory managed by
>> hypervisor(HV) and secure memory managed by Ultravisor(UV).
>>
>> Private ZONE_DEVICE memory equal to the amount of secure memory
>> available in the platform for running secure guests is created.
>> Whenever a page belonging to the guest becomes secure, a page from
>> this private device memory is used to represent and track that secure
>> page on the HV side. The movement of pages between normal and secure
>> memory is done via migrate_vma_pages(). The reverse movement is driven
>> via pagemap_ops.migrate_to_ram().
>>
>> The page-in or page-out requests from UV will come to HV as hcalls and
>> HV will call back into UV via uvcalls to satisfy these page requests.
>>
>> These patches are against hmm.git
>> (https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git/log/?h=hmm)
>>
>> plus
>>
>> Claudio Carvalho's base ultravisor enablement patchset v6
>> (https://lore.kernel.org/linuxppc-dev/20190822034838.27876-1-cclaudio@linux.ibm.com/T/#t)
>
> How are you thinking these patches will go upstream? Are you going to
> send them via the hmm tree?
>
> I assume you need Claudio's patchset as a prerequisite for your series
> to compile, which means the hmm maintainers would need to pull in a
> topic branch from Michael Ellerman's powerpc tree, or something like
> that.
I think more workable would be for me to make a topic branch based on
the hmm tree (or some commit from the hmm tree), which I then apply the
patches on top of, and merge any required powerpc changes into that. I
can then ask Linus to merge that branch late in the merge window once
the hmm changes have gone in.
The bigger problem at the moment is the lack of reviews or acks on the
bulk of the series.
cheers
^ permalink raw reply
* [PATCH] powerpc/8xx: Fix permanently mapped IMMR region.
From: Christophe Leroy @ 2019-08-23 9:56 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
When not using large TLBs, the IMMR region is still
mapped as a whole block in the FIXMAP area.
Do not remove pages mapped in the FIXMAP region when
initialising paging.
Properly report that the IMMR region is block-mapped even
when not using large TLBs.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/mm/mem.c | 8 --------
arch/powerpc/mm/nohash/8xx.c | 13 +++++++------
2 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 69f99128a8d6..8e221d8744ba 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -216,14 +216,6 @@ void __init paging_init(void)
unsigned long long total_ram = memblock_phys_mem_size();
phys_addr_t top_of_ram = memblock_end_of_DRAM();
-#ifdef CONFIG_PPC32
- unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1);
- unsigned long end = __fix_to_virt(FIX_HOLE);
-
- for (; v < end; v += PAGE_SIZE)
- map_kernel_page(v, 0, __pgprot(0)); /* XXX gross */
-#endif
-
#ifdef CONFIG_HIGHMEM
map_kernel_page(PKMAP_BASE, 0, __pgprot(0)); /* XXX gross */
pkmap_page_table = virt_to_kpte(PKMAP_BASE);
diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c
index 4a06cb342da2..e6918235fe04 100644
--- a/arch/powerpc/mm/nohash/8xx.c
+++ b/arch/powerpc/mm/nohash/8xx.c
@@ -21,33 +21,34 @@ extern int __map_without_ltlbs;
static unsigned long block_mapped_ram;
/*
- * Return PA for this VA if it is in an area mapped with LTLBs.
+ * Return PA for this VA if it is in an area mapped with LTLBs or fixmap.
* Otherwise, returns 0
*/
phys_addr_t v_block_mapped(unsigned long va)
{
unsigned long p = PHYS_IMMR_BASE;
- if (__map_without_ltlbs)
- return 0;
if (va >= VIRT_IMMR_BASE && va < VIRT_IMMR_BASE + IMMR_SIZE)
return p + va - VIRT_IMMR_BASE;
+ if (__map_without_ltlbs)
+ return 0;
if (va >= PAGE_OFFSET && va < PAGE_OFFSET + block_mapped_ram)
return __pa(va);
return 0;
}
/*
- * Return VA for a given PA mapped with LTLBs or 0 if not mapped
+ * Return VA for a given PA mapped with LTLBs or fixmap
+ * Return 0 if not mapped
*/
unsigned long p_block_mapped(phys_addr_t pa)
{
unsigned long p = PHYS_IMMR_BASE;
- if (__map_without_ltlbs)
- return 0;
if (pa >= p && pa < p + IMMR_SIZE)
return VIRT_IMMR_BASE + pa - p;
+ if (__map_without_ltlbs)
+ return 0;
if (pa < block_mapped_ram)
return (unsigned long)__va(pa);
return 0;
--
2.13.3
^ permalink raw reply related
* [PATCH] powerpc/32: Don't populate page tables for block mapped pages except on the 8xx.
From: Christophe Leroy @ 2019-08-23 9:56 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
Commit d2f15e0979ee ("powerpc/32: always populate page tables for
Abatron BDI.") wrongly sets page tables for any PPC32 for using BDI,
and does't update them after init (remove RX on init section, set
text and rodata read-only)
Only the 8xx requires page tables to be populated for using the BDI.
They also need to be populated in order to see the mappings in
/sys/kernel/debug/kernel_page_tables
On BOOK3S_32, pages that are not mapped by page tables are mapped
by BATs. The BDI knows BATs and they can be viewed in
/sys/kernel/debug/powerpc/block_address_translation
Only set pagetables for RAM and IMMR on the 8xx and properly update
them at the end of init.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/mm/nohash/8xx.c | 52 +++++++++++++++++++++++++++++++++++++++++---
arch/powerpc/mm/pgtable_32.c | 5 +----
2 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c
index e6918235fe04..2c98078d2ede 100644
--- a/arch/powerpc/mm/nohash/8xx.c
+++ b/arch/powerpc/mm/nohash/8xx.c
@@ -104,6 +104,19 @@ static void mmu_patch_addis(s32 *site, long simm)
patch_instruction_site(site, instr);
}
+void __init mmu_mapin_ram_chunk(unsigned long offset, unsigned long top, pgprot_t prot)
+{
+ unsigned long s = offset;
+ unsigned long v = PAGE_OFFSET + s;
+ phys_addr_t p = memstart_addr + s;
+
+ for (; s < top; s += PAGE_SIZE) {
+ map_kernel_page(v, p, prot);
+ v += PAGE_SIZE;
+ p += PAGE_SIZE;
+ }
+}
+
unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
unsigned long mapped;
@@ -116,10 +129,20 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
if (!IS_ENABLED(CONFIG_PIN_TLB_TEXT))
mmu_patch_cmp_limit(&patch__itlbmiss_linmem_top, 0);
} else {
+ unsigned long einittext8 = ALIGN(__pa(_einittext), SZ_8M);
+
mapped = top & ~(LARGE_PAGE_SIZE_8M - 1);
if (!IS_ENABLED(CONFIG_PIN_TLB_TEXT))
- mmu_patch_cmp_limit(&patch__itlbmiss_linmem_top,
- _ALIGN(__pa(_einittext), 8 << 20));
+ mmu_patch_cmp_limit(&patch__itlbmiss_linmem_top, einittext8);
+
+ /*
+ * Populate page tables to:
+ * - have them appear in /sys/kernel/debug/kernel_page_tables
+ * - allow the BDI to find the pages when they are not PINNED
+ */
+ mmu_mapin_ram_chunk(0, einittext8, PAGE_KERNEL_X);
+ mmu_mapin_ram_chunk(einittext8, mapped, PAGE_KERNEL);
+ mmu_mapin_immr();
}
mmu_patch_cmp_limit(&patch__dtlbmiss_linmem_top, mapped);
@@ -145,18 +168,41 @@ void mmu_mark_initmem_nx(void)
if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX) && CONFIG_ETEXT_SHIFT < 23)
mmu_patch_addis(&patch__itlbmiss_linmem_top8,
-((long)_etext & ~(LARGE_PAGE_SIZE_8M - 1)));
- if (!IS_ENABLED(CONFIG_PIN_TLB_TEXT))
+ if (!IS_ENABLED(CONFIG_PIN_TLB_TEXT)) {
+ unsigned long einittext8 = ALIGN(__pa(_einittext), SZ_8M);
+ unsigned long etext8 = ALIGN(__pa(_etext), SZ_8M);
+ unsigned long etext = __pa(_etext);
+
mmu_patch_cmp_limit(&patch__itlbmiss_linmem_top, __pa(_etext));
+
+ /* Update page tables for PTDUMP and BDI */
+ mmu_mapin_ram_chunk(0, einittext8, __pgprot(0));
+ if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) {
+ mmu_mapin_ram_chunk(0, etext, PAGE_KERNEL_TEXT);
+ mmu_mapin_ram_chunk(etext, einittext8, PAGE_KERNEL);
+ } else {
+ mmu_mapin_ram_chunk(0, etext8, PAGE_KERNEL_TEXT);
+ mmu_mapin_ram_chunk(etext8, einittext8, PAGE_KERNEL);
+ }
+ }
}
#ifdef CONFIG_STRICT_KERNEL_RWX
void mmu_mark_rodata_ro(void)
{
+ unsigned long sinittext = __pa(_sinittext);
+ unsigned long etext = __pa(_etext);
+
if (CONFIG_DATA_SHIFT < 23)
mmu_patch_addis(&patch__dtlbmiss_romem_top8,
-__pa(((unsigned long)_sinittext) &
~(LARGE_PAGE_SIZE_8M - 1)));
mmu_patch_addis(&patch__dtlbmiss_romem_top, -__pa(_sinittext));
+
+ /* Update page tables for PTDUMP and BDI */
+ mmu_mapin_ram_chunk(0, sinittext, __pgprot(0));
+ mmu_mapin_ram_chunk(0, etext, PAGE_KERNEL_ROX);
+ mmu_mapin_ram_chunk(etext, sinittext, PAGE_KERNEL_RO);
}
#endif
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 97f401a06fcc..c5fc33a202aa 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -270,10 +270,7 @@ void __init mapin_ram(void)
if (base >= top)
continue;
base = mmu_mapin_ram(base, top);
- if (IS_ENABLED(CONFIG_BDI_SWITCH))
- __mapin_ram_chunk(reg->base, top);
- else
- __mapin_ram_chunk(base, top);
+ __mapin_ram_chunk(base, top);
}
}
--
2.13.3
^ permalink raw reply related
* [PATCH v4 2/3] arm64: dts: ls1028a: Add PCIe controller DT nodes
From: Xiaowei Bao @ 2019-08-23 8:26 UTC (permalink / raw)
To: robh+dt, mark.rutland, shawnguo, leoyang.li, minghuan.Lian,
mingkai.hu, roy.zang, lorenzo.pieralisi, linux-pci, devicetree,
linux-kernel, linux-arm-kernel, linuxppc-dev, zhiqiang.hou
Cc: bhelgaas, Hou Zhiqiang, Xiaowei Bao
In-Reply-To: <20190823082643.10903-1-xiaowei.bao@nxp.com>
LS1028a implements 2 PCIe 3.0 controllers.
Signed-off-by: Xiaowei Bao <xiaowei.bao@nxp.com>
Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
---
v2:
- Fix up the legacy INTx allocate failed issue.
v3:
- No change.
v4:
- Remove the num-lanes proparty.
depends on: https://patchwork.kernel.org/project/linux-pci/list/?series=162215
arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 50 ++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
index 72b9a75..a25f9d9 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
@@ -625,6 +625,56 @@
};
};
+ pcie@3400000 {
+ compatible = "fsl,ls1028a-pcie";
+ reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */
+ 0x80 0x00000000 0x0 0x00002000>; /* configuration space */
+ reg-names = "regs", "config";
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
+ interrupt-names = "pme", "aer";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ dma-coherent;
+ bus-range = <0x0 0xff>;
+ ranges = <0x81000000 0x0 0x00000000 0x80 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ msi-parent = <&its>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 2 &gic 0 0 GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 3 &gic 0 0 GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 4 &gic 0 0 GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ pcie@3500000 {
+ compatible = "fsl,ls1028a-pcie";
+ reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */
+ 0x88 0x00000000 0x0 0x00002000>; /* configuration space */
+ reg-names = "regs", "config";
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "pme", "aer";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ dma-coherent;
+ bus-range = <0x0 0xff>;
+ ranges = <0x81000000 0x0 0x00000000 0x88 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ msi-parent = <&its>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 2 &gic 0 0 GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 3 &gic 0 0 GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 4 &gic 0 0 GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
pcie@1f0000000 { /* Integrated Endpoint Root Complex */
compatible = "pci-host-ecam-generic";
reg = <0x01 0xf0000000 0x0 0x100000>;
--
2.9.5
^ permalink raw reply related
* [PATCH v4 3/3] PCI: layerscape: Add LS1028a support
From: Xiaowei Bao @ 2019-08-23 8:26 UTC (permalink / raw)
To: robh+dt, mark.rutland, shawnguo, leoyang.li, minghuan.Lian,
mingkai.hu, roy.zang, lorenzo.pieralisi, linux-pci, devicetree,
linux-kernel, linux-arm-kernel, linuxppc-dev, zhiqiang.hou
Cc: bhelgaas, Hou Zhiqiang, Xiaowei Bao
In-Reply-To: <20190823082643.10903-1-xiaowei.bao@nxp.com>
Add support for the LS1028a PCIe controller.
Signed-off-by: Xiaowei Bao <xiaowei.bao@nxp.com>
Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
---
v2:
- No change.
v3:
- Reuse the ls2088 driver data structurt.
v4:
- No change.
drivers/pci/controller/dwc/pci-layerscape.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/pci/controller/dwc/pci-layerscape.c b/drivers/pci/controller/dwc/pci-layerscape.c
index 3a5fa26..f24f79a 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -263,6 +263,7 @@ static const struct ls_pcie_drvdata ls2088_drvdata = {
static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls1012a-pcie", .data = &ls1046_drvdata },
{ .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
+ { .compatible = "fsl,ls1028a-pcie", .data = &ls2088_drvdata },
{ .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
{ .compatible = "fsl,ls1046a-pcie", .data = &ls1046_drvdata },
{ .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
--
2.9.5
^ permalink raw reply related
* [PATCH v4 1/3] dt-bindings: pci: layerscape-pci: add compatible strings "fsl, ls1028a-pcie"
From: Xiaowei Bao @ 2019-08-23 8:26 UTC (permalink / raw)
To: robh+dt, mark.rutland, shawnguo, leoyang.li, minghuan.Lian,
mingkai.hu, roy.zang, lorenzo.pieralisi, linux-pci, devicetree,
linux-kernel, linux-arm-kernel, linuxppc-dev, zhiqiang.hou
Cc: bhelgaas, Hou Zhiqiang, Xiaowei Bao
Add the PCIe compatible string for LS1028A
Signed-off-by: Xiaowei Bao <xiaowei.bao@nxp.com>
Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v2:
- No change.
v3:
- No change.
v4:
- No change.
Documentation/devicetree/bindings/pci/layerscape-pci.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index e20ceaa..99a386e 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -21,6 +21,7 @@ Required properties:
"fsl,ls1046a-pcie"
"fsl,ls1043a-pcie"
"fsl,ls1012a-pcie"
+ "fsl,ls1028a-pcie"
EP mode:
"fsl,ls1046a-pcie-ep", "fsl,ls-pcie-ep"
- reg: base addresses and lengths of the PCIe controller register blocks.
--
2.9.5
^ permalink raw reply related
* Re: [PATCH 2/3] powerpc/numa: Early request for home node associativity
From: Satheesh Rajendran @ 2019-08-23 7:16 UTC (permalink / raw)
To: Srikar Dronamraju; +Cc: Nathan Lynch, linuxppc-dev, Nicholas Piggin
In-Reply-To: <20190822144235.19398-3-srikar@linux.vnet.ibm.com>
On Thu, Aug 22, 2019 at 08:12:34PM +0530, Srikar Dronamraju wrote:
> Currently the kernel detects if its running on a shared lpar platform
> and requests home node associativity before the scheduler sched_domains
> are setup. However between the time NUMA setup is initialized and the
> request for home node associativity, workqueue initializes its per node
> cpumask. The per node workqueue possible cpumask may turn invalid
> after home node associativity resulting in weird situations like
> workqueue possible cpumask being a subset of workqueue online cpumask.
Tested this series on Power KVM guest and expected that it fixes
https://github.com/linuxppc/issues/issues/167 but am able to see the below warning
still while doing vcpu hotplug with numa nodes, Advise if am missing anything or
this is not the intended series to fix above issue.
Env:
HW: Power8
Host/Guest Kernel: 5.3.0-rc5-00172-g13e3f1076e29 (linux master + this series)
Qemu: 4.0.90 (v4.1.0-rc3)
Guest Config:
..
<vcpu placement='static' current='2'>4</vcpu>
...
<kernel>/home/kvmci/linux/vmlinux</kernel>
<cmdline>root=/dev/sda2 rw console=tty0 console=ttyS0,115200 init=/sbin/init initcall_debug numa=debug crashkernel=1024M selinux=0</cmdline>
...
<topology sockets='1' cores='2' threads='2'/>
<numa>
<cell id='0' cpus='0-1' memory='2097152' unit='KiB'/>
<cell id='1' cpus='2-3' memory='2097152' unit='KiB'/>
</numa>
Event:
vcpu hotplug
[root@atest-guest ~]# [ 41.447170] random: crng init done
[ 41.448153] random: 7 urandom warning(s) missed due to ratelimiting
[ 51.727256] VPHN hcall succeeded. Reset polling...
[ 51.826301] adding cpu 2 to node 1
[ 51.856238] WARNING: workqueue cpumask: online intersect > possible intersect
[ 51.916297] VPHN hcall succeeded. Reset polling...
[ 52.036272] adding cpu 3 to node 1
Regards,
-Satheesh.
>
> This can be fixed by requesting home node associativity earlier just
> before NUMA setup. However at the NUMA setup time, kernel may not be in
> a position to detect if its running on a shared lpar platform. So
> request for home node associativity and if the request fails, fallback
> on the device tree property.
>
> However home node associativity requires cpu's hwid which is set in
> smp_setup_pacas. Hence call smp_setup_pacas before numa_setup_cpus.
>
> Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Nicholas Piggin <npiggin@gmail.com>
> Cc: Nathan Lynch <nathanl@linux.ibm.com>
> Cc: linuxppc-dev@lists.ozlabs.org
> Reported-by: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com>
> Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
> ---
> arch/powerpc/kernel/setup-common.c | 5 +++--
> arch/powerpc/mm/numa.c | 28 +++++++++++++++++++++++++++-
> 2 files changed, 30 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
> index 1f8db66..9135dba 100644
> --- a/arch/powerpc/kernel/setup-common.c
> +++ b/arch/powerpc/kernel/setup-common.c
> @@ -888,6 +888,9 @@ void __init setup_arch(char **cmdline_p)
> /* Check the SMT related command line arguments (ppc64). */
> check_smt_enabled();
>
> +#ifdef CONFIG_SMP
> + smp_setup_pacas();
> +#endif
> /* Parse memory topology */
> mem_topology_setup();
>
> @@ -899,8 +902,6 @@ void __init setup_arch(char **cmdline_p)
> * so smp_release_cpus() does nothing for them.
> */
> #ifdef CONFIG_SMP
> - smp_setup_pacas();
> -
> /* On BookE, setup per-core TLB data structures. */
> setup_tlb_core_data();
>
> diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
> index 88b5157..7965d3b 100644
> --- a/arch/powerpc/mm/numa.c
> +++ b/arch/powerpc/mm/numa.c
> @@ -461,6 +461,21 @@ static int of_drconf_to_nid_single(struct drmem_lmb *lmb)
> return nid;
> }
>
> +static int vphn_get_nid(unsigned long cpu)
> +{
> + __be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
> + long rc;
> +
> + /* Use associativity from first thread for all siblings */
> + rc = hcall_vphn(get_hard_smp_processor_id(cpu),
> + VPHN_FLAG_VCPU, associativity);
> +
> + if (rc == H_SUCCESS)
> + return associativity_to_nid(associativity);
> +
> + return NUMA_NO_NODE;
> +}
> +
> /*
> * Figure out to which domain a cpu belongs and stick it there.
> * Return the id of the domain used.
> @@ -490,7 +505,18 @@ static int numa_setup_cpu(unsigned long lcpu)
> goto out;
> }
>
> - nid = of_node_to_nid_single(cpu);
> + /*
> + * On a shared lpar, the device tree might not have the correct node
> + * associativity. At this time lppaca, or its __old_status field
> + * may not be updated. Hence request an explicit associativity
> + * irrespective of whether the lpar is shared or dedicated. Use the
> + * device tree property as a fallback.
> + */
> + if (firmware_has_feature(FW_FEATURE_VPHN))
> + nid = vphn_get_nid(lcpu);
> +
> + if (nid == NUMA_NO_NODE)
> + nid = of_node_to_nid_single(cpu);
>
> out_present:
> if (nid < 0 || !node_possible(nid))
> --
> 1.8.3.1
>
^ permalink raw reply
* [RFC 3/3] cpuidle/powernv : Add flags to identify stop state type
From: Abhishek Goel @ 2019-08-23 7:09 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, devicetree, paulus
Cc: ego, mikey, daniel.lezcano, rjw, npiggin, Abhishek Goel
In-Reply-To: <20190823070940.43220-1-huntbag@linux.vnet.ibm.com>
Removed threshold latency which was being used to decide if a state
is cpuidle type or not. This decision can be taken using flags, as this
information has been encapsulated in the state->flags and being read
from idle device-tree.
Signed-off-by: Abhishek Goel <huntbag@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/opal-api.h | 7 +++++++
drivers/cpuidle/cpuidle-powernv.c | 16 +++++++++-------
2 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 383242eb0dea..b9068fee21d8 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -233,6 +233,13 @@
#define OPAL_PM_STOP_INST_FAST 0x00100000
#define OPAL_PM_STOP_INST_DEEP 0x00200000
+/*
+ * Flags for stop states to distinguish between cpuidle and
+ * cpuoffline type of states.
+ */
+#define OPAL_PM_STOP_CPUIDLE 0x01000000
+#define OPAL_PM_STOP_CPUHOTPLUG 0x02000000
+
/*
* OPAL_CONFIG_CPU_IDLE_STATE parameters
*/
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index 1b6c84d4ac77..1a33a548b769 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -270,8 +270,13 @@ static int powernv_add_idle_states(void)
goto out;
}
- /* TODO: Count only states which are eligible for cpuidle */
- dt_idle_states = nr_pnv_idle_states;
+ /* Count only cpuidle states*/
+ for (i = 0; i < nr_pnv_idle_states; i++) {
+ if (pnv_idle_states[i].flags & OPAL_PM_STOP_CPUIDLE)
+ dt_idle_states++;
+ }
+ pr_info("idle states in dt = %d , states with idle flag = %d",
+ nr_pnv_idle_states, dt_idle_states);
/*
* Since snooze is used as first idle state, max idle states allowed is
@@ -300,11 +305,8 @@ static int powernv_add_idle_states(void)
continue;
}
- /*
- * If an idle state has exit latency beyond
- * POWERNV_THRESHOLD_LATENCY_NS then don't use it in cpu-idle.
- */
- if (state->latency_ns > POWERNV_THRESHOLD_LATENCY_NS) {
+ /* Check whether a state is of cpuidle type */
+ if ((state->flags & OPAL_PM_STOP_CPUIDLE) != state->flags) {
pr_info("State %d is not idletype\n", i);
continue;
}
--
2.17.1
^ permalink raw reply related
* [RFC 2/3] cpuidle/powernv: Add support for versioned stop states
From: Abhishek Goel @ 2019-08-23 7:09 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, devicetree, paulus
Cc: ego, mikey, daniel.lezcano, rjw, npiggin, Abhishek Goel
In-Reply-To: <20190823070940.43220-1-huntbag@linux.vnet.ibm.com>
New device tree format adds a compatible flag which has version
corresponding to every state, so that only kernel which has the capability
to handle the version of stop state will enable it. Drawback of the array
based dt node is that versioning of idle states is not possible.
Older kernel will still see stop0 and stop0_lite in older format and we
will deprecate it after some time.
Consider a case that stop4 has a bug. We take the following steps to
mitigate the problem.
1) Change compatible string for stop4 in OPAL to "stop4,v2" from
"stop4,v1", i.e. basicallly bump up the previous version and ship the
new firmware.
2) The kernel will ignore stop4 as it won't be able to recognize this
new version. Kernel will also ignore all the deeper states because its
possible that a cpu have requested for a deeper state but was never able
to enter into it. But we will still have shallower states that are there
before stop 4. This, thus prevents from completely disabling stop states.
Linux kernel can now look at the version string and decide if it has the
ability to handle that idle state. Henceforth, if kernel does not know
about a version, it will skip that state and all the deeper state.
Once when the workaround are implemented into the kernel, we can bump up
the known version in kernel for that state, so that support can be
enabled once again in kernel.
New Device-tree :
Final output
power-mgt {
...
ibm,enabled-stop-levels = <0xec000000>;
ibm,cpu-idle-state-psscr-mask = <0x0 0x3003ff 0x0 0x3003ff>;
ibm,cpu-idle-state-latencies-ns = <0x3e8 0x7d0>;
ibm,cpu-idle-state-psscr = <0x0 0x330 0x0 0x300330>;
ibm,cpu-idle-state-flags = <0x100000 0x101000>;
ibm,cpu-idle-state-residency-ns = <0x2710 0x4e20>;
ibm,idle-states {
stop4 {
flags = <0x207000>;
compatible = "stop4,v1",
psscr-mask = <0x0 0x3003ff>;
latency-ns = <0x186a0>;
residency-ns = <0x989680>;
psscr = <0x0 0x300374>;
...
};
...
stop11 {
...
compatible = "stop11,v1",
...
};
};
Since state pointer is being passed to stop loop, I have separated idle
fast path for lite, shallow and deep states. This improves the
readability of the code and also future maintainability of the code.
Stop handle corresponding to each state can be called directly since
state pointer is being passed now.
Signed-off-by: Abhishek Goel <huntbag@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/cpuidle.h | 8 +-
arch/powerpc/platforms/powernv/idle.c | 331 +++++++++++++++++++++++---
2 files changed, 299 insertions(+), 40 deletions(-)
diff --git a/arch/powerpc/include/asm/cpuidle.h b/arch/powerpc/include/asm/cpuidle.h
index 9844b3ded187..5eb9a98fcb86 100644
--- a/arch/powerpc/include/asm/cpuidle.h
+++ b/arch/powerpc/include/asm/cpuidle.h
@@ -70,15 +70,19 @@
#ifndef __ASSEMBLY__
-#define PNV_IDLE_NAME_LEN 16
+#define PNV_VERSION_LEN 25
+#define PNV_IDLE_NAME_LEN 16
struct pnv_idle_states_t {
char name[PNV_IDLE_NAME_LEN];
+ char compat_version[PNV_VERSION_LEN];
u32 latency_ns;
u32 residency_ns;
u64 psscr_val;
u64 psscr_mask;
- u32 flags;
+ u64 flags;
bool valid;
+ unsigned long (*stop_handle)(struct pnv_idle_states_t *state,
+ bool mmu_on);
};
extern struct pnv_idle_states_t *pnv_idle_states;
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index db810c0a16e1..7398a66e1ddb 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -49,6 +49,12 @@ static bool default_stop_found;
static u64 pnv_first_tb_loss_level = MAX_STOP_STATE + 1;
static u64 pnv_first_spr_loss_level = MAX_STOP_STATE + 1;
+struct stop_version_t {
+ const char compat_version[PNV_VERSION_LEN];
+ unsigned long (*stop_handle)(struct pnv_idle_states_t *state,
+ bool mmu_on);
+};
+
/*
* psscr value and mask of the deepest stop idle state.
* Used when a cpu is offlined.
@@ -599,40 +605,152 @@ struct p9_sprs {
u64 uamor;
};
-static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
+/* Splitting the previous power9_idle_stop into three functions
+ * to separately handle lite, shallow and deep states.
+ */
+
+static unsigned long power9_stop_lite(struct pnv_idle_states_t *state,
+ bool mmu_on)
{
- int cpu = raw_smp_processor_id();
- int first = cpu_first_thread_sibling(cpu);
- unsigned long *state = &paca_ptrs[first]->idle_state;
- unsigned long core_thread_mask = (1UL << threads_per_core) - 1;
unsigned long srr1;
- unsigned long pls;
+ unsigned long psscr;
+
+ psscr = mfspr(SPRN_PSSCR);
+ psscr = (psscr & ~state->psscr_mask) | state->psscr_val;
+
+ /* EC=ESL=0 case */
+ BUG_ON(!mmu_on);
+
+ /*
+ * Wake synchronously. SRESET via xscom may still cause
+ * a 0x100 powersave wakeup with SRR1 reason!
+ */
+ srr1 = isa300_idle_stop_noloss(psscr); /* go idle */
+ if (likely(!srr1))
+ return 0;
+
+ /*
+ * Registers not saved, can't recover!
+ * This would be a hardware bug
+ */
+ BUG_ON((srr1 & SRR1_WAKESTATE) != SRR1_WS_NOLOSS);
+
+ if (mmu_on)
+ mtmsr(MSR_KERNEL);
+
+ return srr1;
+}
+
+static unsigned long power9_stop_shallow(struct pnv_idle_states_t *state,
+ bool mmu_on)
+{
+ unsigned long srr1;
+ unsigned long psscr;
unsigned long mmcr0 = 0;
struct p9_sprs sprs = {}; /* avoid false used-uninitialised */
- bool sprs_saved = false;
- if (!(psscr & (PSSCR_EC|PSSCR_ESL))) {
- /* EC=ESL=0 case */
+ psscr = mfspr(SPRN_PSSCR);
+ psscr = (psscr & ~state->psscr_mask) | state->psscr_val;
- BUG_ON(!mmu_on);
+ /* EC=ESL=1 case */
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+ if (cpu_has_feature(CPU_FTR_P9_TM_XER_SO_BUG)) {
+ local_paca->requested_psscr = psscr;
+ /* order setting requested_psscr vs testing dont_stop */
+ smp_mb();
+ if (atomic_read(&local_paca->dont_stop)) {
+ local_paca->requested_psscr = 0;
+ return 0;
+ }
+ }
+#endif
+ if (!cpu_has_feature(CPU_FTR_POWER9_DD2_1)) {
/*
- * Wake synchronously. SRESET via xscom may still cause
- * a 0x100 powersave wakeup with SRR1 reason!
+ * POWER9 DD2 can incorrectly set PMAO when waking up
+ * after a state-loss idle. Saving and restoring MMCR0
+ * over idle is a workaround.
*/
- srr1 = isa300_idle_stop_noloss(psscr); /* go idle */
- if (likely(!srr1))
- return 0;
+ mmcr0 = mfspr(SPRN_MMCR0);
+ }
+
+ sprs.amr = mfspr(SPRN_AMR);
+ sprs.iamr = mfspr(SPRN_IAMR);
+ sprs.amor = mfspr(SPRN_AMOR);
+ sprs.uamor = mfspr(SPRN_UAMOR);
+
+ srr1 = isa300_idle_stop_mayloss(psscr); /* go idle */
+ if (unlikely(!srr1))
+ return 0;
+
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+ local_paca->requested_psscr = 0;
+#endif
+
+ psscr = mfspr(SPRN_PSSCR);
+
+ WARN_ON_ONCE(!srr1);
+ WARN_ON_ONCE(mfmsr() & (MSR_IR|MSR_DR));
+
+ if ((srr1 & SRR1_WAKESTATE) != SRR1_WS_NOLOSS) {
+ unsigned long mmcra;
/*
- * Registers not saved, can't recover!
- * This would be a hardware bug
+ * We don't need an isync after the mtsprs here because the
+ * upcoming mtmsrd is execution synchronizing.
*/
- BUG_ON((srr1 & SRR1_WAKESTATE) != SRR1_WS_NOLOSS);
+ mtspr(SPRN_AMR, sprs.amr);
+ mtspr(SPRN_IAMR, sprs.iamr);
+ mtspr(SPRN_AMOR, sprs.amor);
+ mtspr(SPRN_UAMOR, sprs.uamor);
- goto out;
+ /*
+ * Workaround for POWER9 DD2.0, if we lost resources, the ERAT
+ * might have been corrupted and needs flushing. We also need
+ * to reload MMCR0 (see mmcr0 comment above).
+ */
+ if (!cpu_has_feature(CPU_FTR_POWER9_DD2_1)) {
+ asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT);
+ mtspr(SPRN_MMCR0, mmcr0);
+ }
+
+ /*
+ * DD2.2 and earlier need to set then clear bit 60 in MMCRA
+ * to ensure the PMU starts running.
+ */
+ mmcra = mfspr(SPRN_MMCRA);
+ mmcra |= PPC_BIT(60);
+ mtspr(SPRN_MMCRA, mmcra);
+ mmcra &= ~PPC_BIT(60);
+ mtspr(SPRN_MMCRA, mmcra);
}
+ if (unlikely((srr1 & SRR1_WAKEMASK_P8) == SRR1_WAKEHMI))
+ hmi_exception_realmode(NULL);
+
+ if (mmu_on)
+ mtmsr(MSR_KERNEL);
+
+ return srr1;
+}
+
+static unsigned long power9_stop_deep(struct pnv_idle_states_t *state,
+ bool mmu_on)
+{
+ int cpu = raw_smp_processor_id();
+ int first = cpu_first_thread_sibling(cpu);
+ unsigned long *first_state = &paca_ptrs[first]->idle_state;
+ unsigned long core_thread_mask = (1UL << threads_per_core) - 1;
+ unsigned long srr1;
+ unsigned long pls;
+ unsigned long psscr;
+ unsigned long mmcr0 = 0;
+ struct p9_sprs sprs = {}; /* avoid false used-uninitialised */
+ bool sprs_saved = false;
+
+ psscr = mfspr(SPRN_PSSCR);
+ psscr = (psscr & ~state->psscr_mask) | state->psscr_val;
+
/* EC=ESL=1 case */
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
if (cpu_has_feature(CPU_FTR_P9_TM_XER_SO_BUG)) {
@@ -654,7 +772,7 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
*/
mmcr0 = mfspr(SPRN_MMCR0);
}
- if ((psscr & PSSCR_RL_MASK) >= pnv_first_spr_loss_level) {
+
sprs.lpcr = mfspr(SPRN_LPCR);
sprs.hfscr = mfspr(SPRN_HFSCR);
sprs.fscr = mfspr(SPRN_FSCR);
@@ -677,14 +795,15 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
sprs_saved = true;
atomic_start_thread_idle();
- }
sprs.amr = mfspr(SPRN_AMR);
sprs.iamr = mfspr(SPRN_IAMR);
sprs.amor = mfspr(SPRN_AMOR);
sprs.uamor = mfspr(SPRN_UAMOR);
- srr1 = isa300_idle_stop_mayloss(psscr); /* go idle */
+ srr1 = isa300_idle_stop_mayloss(psscr); /* go idle */
+ if (unlikely(!srr1))
+ return 0;
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
local_paca->requested_psscr = 0;
@@ -748,7 +867,7 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
atomic_lock_thread_idle();
- if ((*state & core_thread_mask) != 0)
+ if ((*first_state & core_thread_mask) != 0)
goto core_woken;
/* Per-core SPRs */
@@ -804,14 +923,10 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
static unsigned long power9_offline_stop(struct pnv_idle_states_t *state)
{
unsigned long srr1;
- unsigned long psscr;
-
- psscr = mfspr(SPRN_PSSCR);
- psscr = (psscr & ~state->psscr_mask) | state->psscr_val;
#ifndef CONFIG_KVM_BOOK3S_HV_POSSIBLE
__ppc64_runlatch_off();
- srr1 = power9_idle_stop(psscr, true);
+ srr1 = state->stop_handle(state, true);
__ppc64_runlatch_on();
#else
/*
@@ -827,7 +942,7 @@ static unsigned long power9_offline_stop(struct pnv_idle_states_t *state)
local_paca->kvm_hstate.hwthread_state = KVM_HWTHREAD_IN_IDLE;
__ppc64_runlatch_off();
- srr1 = power9_idle_stop(psscr, false);
+ srr1 = state->stop_handle(state, false);
__ppc64_runlatch_on();
local_paca->kvm_hstate.hwthread_state = KVM_HWTHREAD_IN_KERNEL;
@@ -844,17 +959,16 @@ static unsigned long power9_offline_stop(struct pnv_idle_states_t *state)
void power9_idle_type(struct pnv_idle_states_t *state)
{
- unsigned long psscr;
unsigned long srr1;
if (!prep_irq_for_idle_irqsoff())
return;
- psscr = mfspr(SPRN_PSSCR);
- psscr = (psscr & ~state->psscr_mask) | state->psscr_val;
-
__ppc64_runlatch_off();
- srr1 = power9_idle_stop(psscr, true);
+ /* We will directly call the stop handle of the state
+ * as we have the state being passed to the idle loop
+ */
+ srr1 = state->stop_handle(state, true);
__ppc64_runlatch_on();
fini_irq_for_idle_irqsoff();
@@ -989,6 +1103,45 @@ unsigned long pnv_cpu_offline(unsigned int cpu)
}
#endif
+/* Define all the known versions that are compatible for the kernel */
+struct stop_version_t known_versions[] = {
+ {
+ .compat_version = "stop0_lite,v1",
+ .stop_handle = power9_stop_lite
+ },
+ {
+ .compat_version = "stop0,v1",
+ .stop_handle = power9_stop_shallow
+ },
+ {
+ .compat_version = "stop1,v1",
+ .stop_handle = power9_stop_shallow
+ },
+ {
+ .compat_version = "stop2,v1",
+ .stop_handle = power9_stop_shallow
+ },
+ {
+ .compat_version = "stop4,v1",
+ .stop_handle = power9_stop_deep
+ },
+ {
+ .compat_version = "stop5,v1",
+ .stop_handle = power9_stop_deep
+ },
+ {
+ .compat_version = "stop8,v1",
+ .stop_handle = power9_stop_deep
+ },
+ {
+ .compat_version = "stop11,v1",
+ .stop_handle = power9_stop_deep
+ },
+ {
+ .stop_handle = NULL
+ }
+};
+
/*
* Power ISA 3.0 idle initialization.
*
@@ -1202,6 +1355,70 @@ static void __init pnv_probe_idle_states(void)
supported_cpuidle_states |= pnv_idle_states[i].flags;
}
+/* Parsing the new format of idle device tree */
+static int parse_stop_state(struct device_node *dt_node, int idx)
+{
+ const char *temp_str;
+ int rc;
+
+ if (!dt_node) {
+ pr_err("Invalid device_node\n");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_string(dt_node, "name", &temp_str);
+ if (rc) {
+ pr_err("error reading names rc = %d\n", rc);
+ return -EINVAL;
+ }
+ strncpy(pnv_idle_states[idx].name, temp_str, PNV_IDLE_NAME_LEN);
+
+ rc = of_property_read_string(dt_node, "compatible", &temp_str);
+ if (rc) {
+ pr_err("error reading compatible version rc = %d\n", rc);
+ return -EINVAL;
+ }
+ strncpy(pnv_idle_states[idx].compat_version, temp_str,
+ PNV_VERSION_LEN);
+
+ rc = of_property_read_u32(dt_node, "residency-ns",
+ &pnv_idle_states[idx].residency_ns);
+ if (rc) {
+ pr_err("error reading residency rc = %d\n", rc);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32(dt_node, "latency-ns",
+ &pnv_idle_states[idx].latency_ns);
+ if (rc) {
+ pr_err("error reading latency rc = %d\n", rc);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u64(dt_node, "flags",
+ &pnv_idle_states[idx].flags);
+ if (rc) {
+ pr_err("error reading flags rc = %d\n", rc);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u64(dt_node, "psscr-mask",
+ &pnv_idle_states[idx].psscr_mask);
+ if (rc) {
+ pr_err("error reading psscr-mask rc = %d\n", rc);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u64(dt_node, "psscr",
+ &pnv_idle_states[idx].psscr_val);
+ if (rc) {
+ pr_err("error reading psscr rc = %d\n", rc);
+ return -EINVAL;
+ }
+
+ return 0;
+
+}
/*
* This function parses device-tree and populates all the information
* into pnv_idle_states structure. It also sets up nr_pnv_idle_states
@@ -1210,8 +1427,9 @@ static void __init pnv_probe_idle_states(void)
static int pnv_parse_cpuidle_dt(void)
{
- struct device_node *np;
+ struct device_node *np, *np1, *dt_node;
int nr_idle_states, i;
+ int additional_states = 0;
int rc = 0;
u32 *temp_u32;
u64 *temp_u64;
@@ -1225,8 +1443,14 @@ static int pnv_parse_cpuidle_dt(void)
nr_idle_states = of_property_count_u32_elems(np,
"ibm,cpu-idle-state-flags");
- pnv_idle_states = kcalloc(nr_idle_states, sizeof(*pnv_idle_states),
- GFP_KERNEL);
+ np1 = of_find_node_by_path("/ibm,opal/power-mgt/ibm,idle-states");
+ if (np1) {
+ for_each_child_of_node(np1, dt_node)
+ additional_states++;
+ }
+ pr_info("states in new format : %d\n", additional_states);
+ pnv_idle_states = kcalloc(nr_idle_states + additional_states,
+ sizeof(*pnv_idle_states), GFP_KERNEL);
temp_u32 = kcalloc(nr_idle_states, sizeof(u32), GFP_KERNEL);
temp_u64 = kcalloc(nr_idle_states, sizeof(u64), GFP_KERNEL);
temp_string = kcalloc(nr_idle_states, sizeof(char *), GFP_KERNEL);
@@ -1305,8 +1529,39 @@ static int pnv_parse_cpuidle_dt(void)
for (i = 0; i < nr_idle_states; i++)
strlcpy(pnv_idle_states[i].name, temp_string[i],
PNV_IDLE_NAME_LEN);
+
nr_pnv_idle_states = nr_idle_states;
- rc = 0;
+ /* Parsing node-based idle states device-tree format */
+ if (!np1) {
+ pr_info("dt does not contain ibm,idle_states");
+ goto out;
+ }
+ /* Parse each child node with appropriate parser_fn */
+ for_each_child_of_node(np1, dt_node) {
+ bool found_known_version = false;
+
+ for (i = 0; known_versions[i].stop_handle != NULL; i++) {
+ if (of_device_is_compatible(dt_node,
+ known_versions[i].compat_version)) {
+ rc = parse_stop_state(dt_node,
+ nr_pnv_idle_states);
+ if (rc) {
+ pr_err("%s could not parse\n",
+ known_versions[i].compat_version);
+ continue;
+ }
+ found_known_version = true;
+ break;
+ }
+ }
+ if (!found_known_version) {
+ pr_info("Unsupported state, skipping all further state\n");
+ goto out;
+ }
+ pnv_idle_states[nr_pnv_idle_states].stop_handle =
+ known_versions[i].stop_handle;
+ nr_pnv_idle_states++;
+ }
out:
kfree(temp_u32);
kfree(temp_u64);
--
2.17.1
^ permalink raw reply related
* [RFC 1/3] cpuidle/powernv : Pass state pointer instead of values to stop loop
From: Abhishek Goel @ 2019-08-23 7:09 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, devicetree, paulus
Cc: ego, mikey, daniel.lezcano, rjw, npiggin, Abhishek Goel
In-Reply-To: <20190823070940.43220-1-huntbag@linux.vnet.ibm.com>
Instead of passing psscr_val and psscr_mask, we will pass state pointer
to stop loop. This will help to figure out the method to enter/exit idle
state. Removed psscr_mask and psscr_val from driver idle code. Same has
also been done in platform idle code.
Also, added some cleanups and debugging info.
Signed-off-by: Abhishek Goel <huntbag@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/processor.h | 5 +-
arch/powerpc/platforms/powernv/idle.c | 50 ++++++++-----------
drivers/cpuidle/cpuidle-powernv.c | 69 +++++++++++++--------------
3 files changed, 55 insertions(+), 69 deletions(-)
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index a9993e7a443b..855666e8d271 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -39,6 +39,7 @@
#include <linux/thread_info.h>
#include <asm/ptrace.h>
#include <asm/hw_breakpoint.h>
+#include <asm/cpuidle.h>
/* We do _not_ want to define new machine types at all, those must die
* in favor of using the device-tree
@@ -419,9 +420,7 @@ enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
extern int powersave_nap; /* set if nap mode can be used in idle loop */
extern void power7_idle_type(unsigned long type);
-extern void power9_idle_type(unsigned long stop_psscr_val,
- unsigned long stop_psscr_mask);
-
+extern void power9_idle_type(struct pnv_idle_states_t *state);
extern void flush_instruction_cache(void);
extern void hard_reset_now(void);
extern void poweroff_now(void);
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index 09f49eed7fb8..db810c0a16e1 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -40,8 +40,7 @@ int nr_pnv_idle_states;
* The default stop state that will be used by ppc_md.power_save
* function on platforms that support stop instruction.
*/
-static u64 pnv_default_stop_val;
-static u64 pnv_default_stop_mask;
+struct pnv_idle_states_t *pnv_default_state;
static bool default_stop_found;
/*
@@ -54,9 +53,7 @@ static u64 pnv_first_spr_loss_level = MAX_STOP_STATE + 1;
* psscr value and mask of the deepest stop idle state.
* Used when a cpu is offlined.
*/
-static u64 pnv_deepest_stop_psscr_val;
-static u64 pnv_deepest_stop_psscr_mask;
-static u64 pnv_deepest_stop_flag;
+static struct pnv_idle_states_t *pnv_deepest_state;
static bool deepest_stop_found;
static unsigned long power7_offline_type;
@@ -78,7 +75,7 @@ static int pnv_save_sprs_for_deep_states(void)
uint64_t hid5_val = mfspr(SPRN_HID5);
uint64_t hmeer_val = mfspr(SPRN_HMEER);
uint64_t msr_val = MSR_IDLE;
- uint64_t psscr_val = pnv_deepest_stop_psscr_val;
+ uint64_t psscr_val = pnv_deepest_state->psscr_val;
for_each_present_cpu(cpu) {
uint64_t pir = get_hard_smp_processor_id(cpu);
@@ -804,9 +801,13 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
}
#ifdef CONFIG_HOTPLUG_CPU
-static unsigned long power9_offline_stop(unsigned long psscr)
+static unsigned long power9_offline_stop(struct pnv_idle_states_t *state)
{
unsigned long srr1;
+ unsigned long psscr;
+
+ psscr = mfspr(SPRN_PSSCR);
+ psscr = (psscr & ~state->psscr_mask) | state->psscr_val;
#ifndef CONFIG_KVM_BOOK3S_HV_POSSIBLE
__ppc64_runlatch_off();
@@ -841,8 +842,7 @@ static unsigned long power9_offline_stop(unsigned long psscr)
}
#endif
-void power9_idle_type(unsigned long stop_psscr_val,
- unsigned long stop_psscr_mask)
+void power9_idle_type(struct pnv_idle_states_t *state)
{
unsigned long psscr;
unsigned long srr1;
@@ -851,7 +851,7 @@ void power9_idle_type(unsigned long stop_psscr_val,
return;
psscr = mfspr(SPRN_PSSCR);
- psscr = (psscr & ~stop_psscr_mask) | stop_psscr_val;
+ psscr = (psscr & ~state->psscr_mask) | state->psscr_val;
__ppc64_runlatch_off();
srr1 = power9_idle_stop(psscr, true);
@@ -867,7 +867,7 @@ void power9_idle_type(unsigned long stop_psscr_val,
*/
void power9_idle(void)
{
- power9_idle_type(pnv_default_stop_val, pnv_default_stop_mask);
+ power9_idle_type(pnv_default_state);
}
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
@@ -970,12 +970,7 @@ unsigned long pnv_cpu_offline(unsigned int cpu)
__ppc64_runlatch_off();
if (cpu_has_feature(CPU_FTR_ARCH_300) && deepest_stop_found) {
- unsigned long psscr;
-
- psscr = mfspr(SPRN_PSSCR);
- psscr = (psscr & ~pnv_deepest_stop_psscr_mask) |
- pnv_deepest_stop_psscr_val;
- srr1 = power9_offline_stop(psscr);
+ srr1 = power9_offline_stop(pnv_deepest_state);
} else if (cpu_has_feature(CPU_FTR_ARCH_206) && power7_offline_type) {
srr1 = power7_offline();
} else {
@@ -1124,16 +1119,13 @@ static void __init pnv_power9_idle_init(void)
if (max_residency_ns < state->residency_ns) {
max_residency_ns = state->residency_ns;
- pnv_deepest_stop_psscr_val = state->psscr_val;
- pnv_deepest_stop_psscr_mask = state->psscr_mask;
- pnv_deepest_stop_flag = state->flags;
+ pnv_deepest_state = state;
deepest_stop_found = true;
}
if (!default_stop_found &&
(state->flags & OPAL_PM_STOP_INST_FAST)) {
- pnv_default_stop_val = state->psscr_val;
- pnv_default_stop_mask = state->psscr_mask;
+ pnv_default_state = state;
default_stop_found = true;
WARN_ON(state->flags & OPAL_PM_LOSE_FULL_CONTEXT);
}
@@ -1144,15 +1136,16 @@ static void __init pnv_power9_idle_init(void)
} else {
ppc_md.power_save = power9_idle;
pr_info("cpuidle-powernv: Default stop: psscr = 0x%016llx,mask=0x%016llx\n",
- pnv_default_stop_val, pnv_default_stop_mask);
+ pnv_default_state->psscr_val,
+ pnv_default_state->psscr_mask);
}
if (unlikely(!deepest_stop_found)) {
pr_warn("cpuidle-powernv: No suitable stop state for CPU-Hotplug. Offlined CPUs will busy wait");
} else {
pr_info("cpuidle-powernv: Deepest stop: psscr = 0x%016llx,mask=0x%016llx\n",
- pnv_deepest_stop_psscr_val,
- pnv_deepest_stop_psscr_mask);
+ pnv_deepest_state->psscr_val,
+ pnv_deepest_state->psscr_mask);
}
pr_info("cpuidle-powernv: First stop level that may lose SPRs = 0x%llx\n",
@@ -1174,16 +1167,15 @@ static void __init pnv_disable_deep_states(void)
pr_warn("cpuidle-powernv: Idle power-savings, CPU-Hotplug affected\n");
if (cpu_has_feature(CPU_FTR_ARCH_300) &&
- (pnv_deepest_stop_flag & OPAL_PM_LOSE_FULL_CONTEXT)) {
+ (pnv_deepest_state->flags & OPAL_PM_LOSE_FULL_CONTEXT)) {
/*
* Use the default stop state for CPU-Hotplug
* if available.
*/
if (default_stop_found) {
- pnv_deepest_stop_psscr_val = pnv_default_stop_val;
- pnv_deepest_stop_psscr_mask = pnv_default_stop_mask;
+ pnv_deepest_state = pnv_default_state;
pr_warn("cpuidle-powernv: Offlined CPUs will stop with psscr = 0x%016llx\n",
- pnv_deepest_stop_psscr_val);
+ pnv_deepest_state->psscr_val);
} else { /* Fallback to snooze loop for CPU-Hotplug */
deepest_stop_found = false;
pr_warn("cpuidle-powernv: Offlined CPUs will busy wait\n");
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index 84b1ebe212b3..1b6c84d4ac77 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -36,13 +36,7 @@ static struct cpuidle_driver powernv_idle_driver = {
static int max_idle_state __read_mostly;
static struct cpuidle_state *cpuidle_state_table __read_mostly;
-struct stop_psscr_table {
- u64 val;
- u64 mask;
-};
-
-static struct stop_psscr_table stop_psscr_table[CPUIDLE_STATE_MAX] __read_mostly;
-
+static unsigned int stop_driver_index[CPUIDLE_STATE_MAX] __read_mostly;
static u64 default_snooze_timeout __read_mostly;
static bool snooze_timeout_en __read_mostly;
@@ -144,8 +138,9 @@ static int stop_loop(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
- power9_idle_type(stop_psscr_table[index].val,
- stop_psscr_table[index].mask);
+ unsigned int driver_index = stop_driver_index[index];
+
+ power9_idle_type(&pnv_idle_states[driver_index]);
return index;
}
@@ -234,7 +229,7 @@ static inline void add_powernv_state(int index, const char *name,
int),
unsigned int target_residency,
unsigned int exit_latency,
- u64 psscr_val, u64 psscr_mask)
+ unsigned int driver_index)
{
strlcpy(powernv_states[index].name, name, CPUIDLE_NAME_LEN);
strlcpy(powernv_states[index].desc, name, CPUIDLE_NAME_LEN);
@@ -242,9 +237,7 @@ static inline void add_powernv_state(int index, const char *name,
powernv_states[index].target_residency = target_residency;
powernv_states[index].exit_latency = exit_latency;
powernv_states[index].enter = idle_fn;
- /* For power8 and below psscr_* will be 0 */
- stop_psscr_table[index].val = psscr_val;
- stop_psscr_table[index].mask = psscr_mask;
+ stop_driver_index[index] = driver_index;
}
/*
@@ -265,7 +258,7 @@ extern u32 pnv_get_supported_cpuidle_states(void);
static int powernv_add_idle_states(void)
{
int nr_idle_states = 1; /* Snooze */
- int dt_idle_states;
+ int dt_idle_states = 0;
u32 has_stop_states = 0;
int i;
u32 supported_flags = pnv_get_supported_cpuidle_states();
@@ -284,36 +277,38 @@ static int powernv_add_idle_states(void)
* Since snooze is used as first idle state, max idle states allowed is
* CPUIDLE_STATE_MAX -1
*/
- if (nr_pnv_idle_states > CPUIDLE_STATE_MAX - 1) {
+ if (dt_idle_states > CPUIDLE_STATE_MAX - 1) {
pr_warn("cpuidle-powernv: discovered idle states more than allowed");
dt_idle_states = CPUIDLE_STATE_MAX - 1;
}
- /*
- * If the idle states use stop instruction, probe for psscr values
- * and psscr mask which are necessary to specify required stop level.
- */
- has_stop_states = (pnv_idle_states[0].flags &
- (OPAL_PM_STOP_INST_FAST | OPAL_PM_STOP_INST_DEEP));
-
for (i = 0; i < dt_idle_states; i++) {
unsigned int exit_latency, target_residency;
bool stops_timebase = false;
struct pnv_idle_states_t *state = &pnv_idle_states[i];
+ has_stop_states = (pnv_idle_states[i].flags &
+ (OPAL_PM_STOP_INST_FAST |
+ OPAL_PM_STOP_INST_DEEP));
+
/*
* Skip the platform idle state whose flag isn't in
* the supported_cpuidle_states flag mask.
*/
- if ((state->flags & supported_flags) != state->flags)
+ if ((state->flags & supported_flags) != state->flags) {
+ pr_warn("State %d does not have supported flag\n", i);
continue;
+ }
+
/*
* If an idle state has exit latency beyond
- * POWERNV_THRESHOLD_LATENCY_NS then don't use it
- * in cpu-idle.
+ * POWERNV_THRESHOLD_LATENCY_NS then don't use it in cpu-idle.
*/
- if (state->latency_ns > POWERNV_THRESHOLD_LATENCY_NS)
+ if (state->latency_ns > POWERNV_THRESHOLD_LATENCY_NS) {
+ pr_info("State %d is not idletype\n", i);
continue;
+ }
+
/*
* Firmware passes residency and latency values in ns.
* cpuidle expects it in us.
@@ -321,8 +316,10 @@ static int powernv_add_idle_states(void)
exit_latency = DIV_ROUND_UP(state->latency_ns, 1000);
target_residency = DIV_ROUND_UP(state->residency_ns, 1000);
- if (has_stop_states && !(state->valid))
- continue;
+ if (has_stop_states && !(state->valid)) {
+ pr_warn("State %d is invalid\n", i);
+ continue;
+ }
if (state->flags & OPAL_PM_TIMEBASE_STOP)
stops_timebase = true;
@@ -331,13 +328,11 @@ static int powernv_add_idle_states(void)
/* Add NAP state */
add_powernv_state(nr_idle_states, "Nap",
CPUIDLE_FLAG_NONE, nap_loop,
- target_residency, exit_latency, 0, 0);
+ target_residency, exit_latency, 0);
} else if (has_stop_states && !stops_timebase) {
add_powernv_state(nr_idle_states, state->name,
CPUIDLE_FLAG_NONE, stop_loop,
- target_residency, exit_latency,
- state->psscr_val,
- state->psscr_mask);
+ target_residency, exit_latency, i);
}
/*
@@ -351,17 +346,17 @@ static int powernv_add_idle_states(void)
add_powernv_state(nr_idle_states, "FastSleep",
CPUIDLE_FLAG_TIMER_STOP,
fastsleep_loop,
- target_residency, exit_latency, 0, 0);
+ target_residency, exit_latency, 0);
} else if (has_stop_states && stops_timebase) {
add_powernv_state(nr_idle_states, state->name,
CPUIDLE_FLAG_TIMER_STOP, stop_loop,
- target_residency, exit_latency,
- state->psscr_val,
- state->psscr_mask);
+ target_residency, exit_latency, i);
}
#endif
- else
+ else {
+ pr_warn("cpuidle-powernv : could not add state\n");
continue;
+ }
nr_idle_states++;
}
out:
--
2.17.1
^ permalink raw reply related
* [RFC 0/3] New idle device-tree format and support for versioned stop state
From: Abhishek Goel @ 2019-08-23 7:09 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, devicetree, paulus
Cc: ego, mikey, daniel.lezcano, rjw, npiggin, Abhishek Goel
Background
------------------
Previously if a older kernel runs on a newer firmware, it may enable
all available states irrespective of its capability of handling it.
Consider a case that some stop state has a bug, we end up disabling all
the stop states. This patch introduces selective control to solve this
problem.
Previous version of these patches can be found at:
https://lkml.org/lkml/2018/10/11/544
These patch however also had patches for support of opal save-restore
which now I am decoupling and will take them seperately.
I have posted the corresponding skiboot patches for this kernel patchset
here : https://patchwork.ozlabs.org/cover/1144587/
What's new?
--------------------
Add stop states under ibm,idle-states in addition to the current array
based device tree properties.
New device tree format adds a compatible flag which has version
corresponding to every state, so that only kernel which has the capability
to handle the version of stop state will enable it. Drawback of the array
based dt node is that versioning of idle states is not possible.
Older kernel will still see stop0 and stop0_lite in older format and we
will deprecate it after some time.
Consider a case that stop4 has a bug. We take the following steps to
mitigate the problem.
1) Change compatible string for stop4 in OPAL to "stop4,v2" from
"stop4,v1", i.e. basicallly bump up the previous version and ship the
new firmware.
2) The kernel will ignore stop4 as it won't be able to recognize this
new version. Kernel will also ignore all the deeper states because its
possible that a cpu have requested for a deeper state but was never able
to enter into it. But we will still have shallower states that are there
before stop 4. This, thus prevents from completely disabling stop states.
Linux kernel can now look at the version string and decide if it has the
ability to handle that idle state. Henceforth, if kernel does not know
about a version, it will skip that state and all the deeper state.
Once when the workaround are implemented into the kernel, we can bump up
the known version in kernel for that state, so that support can be
enabled once again in kernel.
New Device-tree :
Final output
power-mgt {
...
ibm,enabled-stop-levels = <0xec000000>;
ibm,cpu-idle-state-psscr-mask = <0x0 0x3003ff 0x0 0x3003ff>;
ibm,cpu-idle-state-latencies-ns = <0x3e8 0x7d0>;
ibm,cpu-idle-state-psscr = <0x0 0x330 0x0 0x300330>;
ibm,cpu-idle-state-flags = <0x100000 0x101000>;
ibm,cpu-idle-state-residency-ns = <0x2710 0x4e20>;
ibm,idle-states {
stop4 {
flags = <0x207000>;
compatible = "stop4,v1",
psscr-mask = <0x0 0x3003ff>;
latency-ns = <0x186a0>;
residency-ns = <0x989680>;
psscr = <0x0 0x300374>;
...
};
...
stop11 {
...
compatible = "stop11,v1",
...
};
};
Abhishek Goel (3):
cpuidle/powernv : Pass state pointer instead of values to stop loop
cpuidle/powernv: Add support for versioned stop states
cpuidle/powernv : Add flags to identify stop state type
arch/powerpc/include/asm/cpuidle.h | 8 +-
arch/powerpc/include/asm/opal-api.h | 7 +
arch/powerpc/include/asm/processor.h | 5 +-
arch/powerpc/platforms/powernv/idle.c | 371 +++++++++++++++++++++-----
drivers/cpuidle/cpuidle-powernv.c | 81 +++---
5 files changed, 363 insertions(+), 109 deletions(-)
--
2.17.1
^ permalink raw reply
* Re: [PATCH v6 3/7] powerpc/powernv: Introduce FW_FEATURE_ULTRAVISOR
From: Michael Ellerman @ 2019-08-23 7:07 UTC (permalink / raw)
To: Claudio Carvalho, linuxppc-dev
Cc: Madhavan Srinivasan, Michael Anderson, Ram Pai, Claudio Carvalho,
kvm-ppc, Bharata B Rao, Ryan Grimm, Sukadev Bhattiprolu,
Guerney Hunt, Thiago Bauermann
In-Reply-To: <20190822034838.27876-4-cclaudio@linux.ibm.com>
Claudio Carvalho <cclaudio@linux.ibm.com> writes:
> In PEF enabled systems, some of the resources which were previously
> hypervisor privileged are now ultravisor privileged and controlled by
> the ultravisor firmware.
>
> This adds FW_FEATURE_ULTRAVISOR to indicate if PEF is enabled.
>
> The host kernel can use FW_FEATURE_ULTRAVISOR, for instance, to skip
> accessing resources (e.g. PTCR and LDBAR) in case PEF is enabled.
>
> Signed-off-by: Claudio Carvalho <cclaudio@linux.ibm.com>
> [ andmike: Device node name to "ibm,ultravisor" ]
^ I dropped this comment as it refers to a previous version of the patch
and is not accurate anymore.
cheers
> Signed-off-by: Michael Anderson <andmike@linux.ibm.com>
> ---
> arch/powerpc/include/asm/firmware.h | 5 +++--
> arch/powerpc/include/asm/ultravisor.h | 14 ++++++++++++
> arch/powerpc/kernel/prom.c | 4 ++++
> arch/powerpc/platforms/powernv/Makefile | 1 +
> arch/powerpc/platforms/powernv/ultravisor.c | 24 +++++++++++++++++++++
> 5 files changed, 46 insertions(+), 2 deletions(-)
> create mode 100644 arch/powerpc/include/asm/ultravisor.h
> create mode 100644 arch/powerpc/platforms/powernv/ultravisor.c
>
> diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h
> index faeca8b76c8c..b3e214a97f3a 100644
> --- a/arch/powerpc/include/asm/firmware.h
> +++ b/arch/powerpc/include/asm/firmware.h
> @@ -50,6 +50,7 @@
> #define FW_FEATURE_DRC_INFO ASM_CONST(0x0000000800000000)
> #define FW_FEATURE_BLOCK_REMOVE ASM_CONST(0x0000001000000000)
> #define FW_FEATURE_PAPR_SCM ASM_CONST(0x0000002000000000)
> +#define FW_FEATURE_ULTRAVISOR ASM_CONST(0x0000004000000000)
>
> #ifndef __ASSEMBLY__
>
> @@ -68,9 +69,9 @@ enum {
> FW_FEATURE_TYPE1_AFFINITY | FW_FEATURE_PRRN |
> FW_FEATURE_HPT_RESIZE | FW_FEATURE_DRMEM_V2 |
> FW_FEATURE_DRC_INFO | FW_FEATURE_BLOCK_REMOVE |
> - FW_FEATURE_PAPR_SCM,
> + FW_FEATURE_PAPR_SCM | FW_FEATURE_ULTRAVISOR,
> FW_FEATURE_PSERIES_ALWAYS = 0,
> - FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL,
> + FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_ULTRAVISOR,
> FW_FEATURE_POWERNV_ALWAYS = 0,
> FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
> FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
> diff --git a/arch/powerpc/include/asm/ultravisor.h b/arch/powerpc/include/asm/ultravisor.h
> new file mode 100644
> index 000000000000..dc6e1ea198f2
> --- /dev/null
> +++ b/arch/powerpc/include/asm/ultravisor.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Ultravisor definitions
> + *
> + * Copyright 2019, IBM Corporation.
> + *
> + */
> +#ifndef _ASM_POWERPC_ULTRAVISOR_H
> +#define _ASM_POWERPC_ULTRAVISOR_H
> +
> +int early_init_dt_scan_ultravisor(unsigned long node, const char *uname,
> + int depth, void *data);
> +
> +#endif /* _ASM_POWERPC_ULTRAVISOR_H */
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index 7159e791a70d..5828f1c81dc9 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -55,6 +55,7 @@
> #include <asm/firmware.h>
> #include <asm/dt_cpu_ftrs.h>
> #include <asm/drmem.h>
> +#include <asm/ultravisor.h>
>
> #include <mm/mmu_decl.h>
>
> @@ -702,6 +703,9 @@ void __init early_init_devtree(void *params)
> #ifdef CONFIG_PPC_POWERNV
> /* Some machines might need OPAL info for debugging, grab it now. */
> of_scan_flat_dt(early_init_dt_scan_opal, NULL);
> +
> + /* Scan tree for ultravisor feature */
> + of_scan_flat_dt(early_init_dt_scan_ultravisor, NULL);
> #endif
>
> #ifdef CONFIG_FA_DUMP
> diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
> index 69a3aefa905b..49186f0985a4 100644
> --- a/arch/powerpc/platforms/powernv/Makefile
> +++ b/arch/powerpc/platforms/powernv/Makefile
> @@ -4,6 +4,7 @@ obj-y += idle.o opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
> obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
> obj-y += opal-msglog.o opal-hmi.o opal-power.o opal-irqchip.o
> obj-y += opal-kmsg.o opal-powercap.o opal-psr.o opal-sensor-groups.o
> +obj-y += ultravisor.o
>
> obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o
> obj-$(CONFIG_PCI) += pci.o pci-ioda.o npu-dma.o pci-ioda-tce.o
> diff --git a/arch/powerpc/platforms/powernv/ultravisor.c b/arch/powerpc/platforms/powernv/ultravisor.c
> new file mode 100644
> index 000000000000..02ac57b4bded
> --- /dev/null
> +++ b/arch/powerpc/platforms/powernv/ultravisor.c
> @@ -0,0 +1,24 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Ultravisor high level interfaces
> + *
> + * Copyright 2019, IBM Corporation.
> + *
> + */
> +#include <linux/init.h>
> +#include <linux/printk.h>
> +#include <linux/of_fdt.h>
> +
> +#include <asm/ultravisor.h>
> +#include <asm/firmware.h>
> +
> +int __init early_init_dt_scan_ultravisor(unsigned long node, const char *uname,
> + int depth, void *data)
> +{
> + if (!of_flat_dt_is_compatible(node, "ibm,ultravisor"))
> + return 0;
> +
> + powerpc_firmware_features |= FW_FEATURE_ULTRAVISOR;
> + pr_debug("Ultravisor detected!\n");
> + return 1;
> +}
> --
> 2.20.1
^ permalink raw reply
* Re: [PATCH v7 0/7] KVMPPC driver to manage secure guest pages
From: Bharata B Rao @ 2019-08-23 6:57 UTC (permalink / raw)
To: Paul Mackerras
Cc: linuxram, cclaudio, kvm-ppc, linux-mm, jglisse, aneesh.kumar,
paulus, sukadev, linuxppc-dev, hch
In-Reply-To: <20190823041747.ctquda5uwvy2eiqz@oak.ozlabs.ibm.com>
On Fri, Aug 23, 2019 at 02:17:47PM +1000, Paul Mackerras wrote:
> On Thu, Aug 22, 2019 at 03:56:13PM +0530, Bharata B Rao wrote:
> > Hi,
> >
> > A pseries guest can be run as a secure guest on Ultravisor-enabled
> > POWER platforms. On such platforms, this driver will be used to manage
> > the movement of guest pages between the normal memory managed by
> > hypervisor(HV) and secure memory managed by Ultravisor(UV).
> >
> > Private ZONE_DEVICE memory equal to the amount of secure memory
> > available in the platform for running secure guests is created.
> > Whenever a page belonging to the guest becomes secure, a page from
> > this private device memory is used to represent and track that secure
> > page on the HV side. The movement of pages between normal and secure
> > memory is done via migrate_vma_pages(). The reverse movement is driven
> > via pagemap_ops.migrate_to_ram().
> >
> > The page-in or page-out requests from UV will come to HV as hcalls and
> > HV will call back into UV via uvcalls to satisfy these page requests.
> >
> > These patches are against hmm.git
> > (https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git/log/?h=hmm)
> >
> > plus
> >
> > Claudio Carvalho's base ultravisor enablement patchset v6
> > (https://lore.kernel.org/linuxppc-dev/20190822034838.27876-1-cclaudio@linux.ibm.com/T/#t)
>
> How are you thinking these patches will go upstream? Are you going to
> send them via the hmm tree?
>
> I assume you need Claudio's patchset as a prerequisite for your series
> to compile, which means the hmm maintainers would need to pull in a
> topic branch from Michael Ellerman's powerpc tree, or something like
> that.
I was hoping that changes required from hmm.git would hit upstream soon,
will reflect in mpe's powerpc tree at which time these patches can go
via powerpc tree along with or after Claudio's patchset.
Though this depends on migrate_vma and memremap changes that
happen to be in hmm.git, this is majorly a kvmppc change. Hence I thought
it would be appropriate for this to go via your or mpe's tree together
with required dependencies.
Regards,
Bharata.
^ permalink raw reply
* [PATCH v2] powerpc/powernv: Add ultravisor message log interface
From: Claudio Carvalho @ 2019-08-23 6:06 UTC (permalink / raw)
To: linuxppc-dev
Cc: Madhavan Srinivasan, Michael Anderson, Ram Pai, Claudio Carvalho,
kvm-ppc, Ryan Grimm, Oliver O'Halloran
Ultravisor (UV) provides an in-memory console which follows the OPAL
in-memory console structure.
This patch extends the OPAL msglog code to also initialize the UV memory
console and provide a sysfs interface (uv_msglog) for userspace to view
the UV message log.
CC: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
CC: Oliver O'Halloran <oohall@gmail.com>
Signed-off-by: Claudio Carvalho <cclaudio@linux.ibm.com>
---
This patch depends on the "kvmppc: Paravirtualize KVM to support
ultravisor" patchset submitted by Claudio Carvalho.
---
arch/powerpc/platforms/powernv/opal-msglog.c | 99 ++++++++++++++------
1 file changed, 72 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/opal-msglog.c b/arch/powerpc/platforms/powernv/opal-msglog.c
index dc51d03c6370..da73908fdabe 100644
--- a/arch/powerpc/platforms/powernv/opal-msglog.c
+++ b/arch/powerpc/platforms/powernv/opal-msglog.c
@@ -11,6 +11,7 @@
#include <linux/of.h>
#include <linux/types.h>
#include <asm/barrier.h>
+#include <asm/firmware.h>
/* OPAL in-memory console. Defined in OPAL source at core/console.c */
struct memcons {
@@ -28,24 +29,26 @@ struct memcons {
};
static struct memcons *opal_memcons = NULL;
+static struct memcons *opal_uv_memcons;
-ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
+static ssize_t msglog_copy(struct memcons *memcons, const char *bin_attr_name,
+ char *to, loff_t pos, size_t count)
{
const char *conbuf;
ssize_t ret;
size_t first_read = 0;
uint32_t out_pos, avail;
- if (!opal_memcons)
+ if (!memcons)
return -ENODEV;
- out_pos = be32_to_cpu(READ_ONCE(opal_memcons->out_pos));
+ out_pos = be32_to_cpu(READ_ONCE(memcons->out_pos));
/* Now we've read out_pos, put a barrier in before reading the new
* data it points to in conbuf. */
smp_rmb();
- conbuf = phys_to_virt(be64_to_cpu(opal_memcons->obuf_phys));
+ conbuf = phys_to_virt(be64_to_cpu(memcons->obuf_phys));
/* When the buffer has wrapped, read from the out_pos marker to the end
* of the buffer, and then read the remaining data as in the un-wrapped
@@ -53,7 +56,7 @@ ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
if (out_pos & MEMCONS_OUT_POS_WRAP) {
out_pos &= MEMCONS_OUT_POS_MASK;
- avail = be32_to_cpu(opal_memcons->obuf_size) - out_pos;
+ avail = be32_to_cpu(memcons->obuf_size) - out_pos;
ret = memory_read_from_buffer(to, count, &pos,
conbuf + out_pos, avail);
@@ -71,8 +74,8 @@ ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
}
/* Sanity check. The firmware should not do this to us. */
- if (out_pos > be32_to_cpu(opal_memcons->obuf_size)) {
- pr_err("OPAL: memory console corruption. Aborting read.\n");
+ if (out_pos > be32_to_cpu(memcons->obuf_size)) {
+ pr_err("OPAL: %s corruption. Aborting read.\n", bin_attr_name);
return -EINVAL;
}
@@ -86,53 +89,95 @@ ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
return ret;
}
+#define BIN_ATTR_NAME_OPAL "msglog"
+#define BIN_ATTR_NAME_UV "uv_msglog"
+
+ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
+{
+ return msglog_copy(opal_memcons, BIN_ATTR_NAME_OPAL, to, pos,
+ count);
+}
+
static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
struct bin_attribute *bin_attr, char *to,
loff_t pos, size_t count)
{
- return opal_msglog_copy(to, pos, count);
+ return msglog_copy(opal_memcons, BIN_ATTR_NAME_OPAL, to, pos,
+ count);
+}
+
+static ssize_t opal_uv_msglog_read(struct file *file, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *to,
+ loff_t pos, size_t count)
+{
+ return msglog_copy(opal_uv_memcons, BIN_ATTR_NAME_UV, to, pos,
+ count);
}
static struct bin_attribute opal_msglog_attr = {
- .attr = {.name = "msglog", .mode = 0400},
+ .attr = {.name = BIN_ATTR_NAME_OPAL, .mode = 0400},
.read = opal_msglog_read
};
-void __init opal_msglog_init(void)
+static struct bin_attribute opal_uv_msglog_attr = {
+ .attr = {.name = BIN_ATTR_NAME_UV, .mode = 0400},
+ .read = opal_uv_msglog_read
+};
+
+static void __init msglog_init(struct memcons **memcons,
+ struct bin_attribute *bin_attr,
+ const char *dt_prop_name)
{
- u64 mcaddr;
- struct memcons *mc;
+ u64 memcons_addr;
- if (of_property_read_u64(opal_node, "ibm,opal-memcons", &mcaddr)) {
- pr_warn("OPAL: Property ibm,opal-memcons not found, no message log\n");
+ if (of_property_read_u64(opal_node, dt_prop_name, &memcons_addr)) {
+ pr_warn("OPAL: Property '%s' not found, no message log\n",
+ dt_prop_name);
return;
}
- mc = phys_to_virt(mcaddr);
- if (!mc) {
- pr_warn("OPAL: memory console address is invalid\n");
+ *memcons = phys_to_virt(memcons_addr);
+ if (!(*memcons)) {
+ pr_warn("OPAL: '%s' address is invalid\n", dt_prop_name);
return;
}
- if (be64_to_cpu(mc->magic) != MEMCONS_MAGIC) {
- pr_warn("OPAL: memory console version is invalid\n");
+ if (be64_to_cpu((*memcons)->magic) != MEMCONS_MAGIC) {
+ pr_warn("OPAL: '%s' version is invalid\n", dt_prop_name);
+ *memcons = NULL;
return;
}
/* Report maximum size */
- opal_msglog_attr.size = be32_to_cpu(mc->ibuf_size) +
- be32_to_cpu(mc->obuf_size);
+ bin_attr->size = be32_to_cpu((*memcons)->ibuf_size) +
+ be32_to_cpu((*memcons)->obuf_size);
+}
- opal_memcons = mc;
+void __init opal_msglog_init(void)
+{
+ msglog_init(&opal_memcons, &opal_msglog_attr, "ibm,opal-memcons");
+ if (firmware_has_feature(FW_FEATURE_ULTRAVISOR))
+ msglog_init(&opal_uv_memcons, &opal_uv_msglog_attr,
+ "ibm,opal-uv-memcons");
}
-void __init opal_msglog_sysfs_init(void)
+static void __init msglog_sysfs_create(struct memcons *memcons,
+ struct bin_attribute *bin_attr)
{
- if (!opal_memcons) {
- pr_warn("OPAL: message log initialisation failed, not creating sysfs entry\n");
+ if (!memcons) {
+ pr_warn("OPAL: %s initialization failed, not creating sysfs entry\n",
+ bin_attr->attr.name);
return;
}
- if (sysfs_create_bin_file(opal_kobj, &opal_msglog_attr) != 0)
- pr_warn("OPAL: sysfs file creation failed\n");
+ if (sysfs_create_bin_file(opal_kobj, bin_attr) != 0)
+ pr_warn("OPAL: sysfs %s creation failed\n",
+ bin_attr->attr.name);
+}
+
+void __init opal_msglog_sysfs_init(void)
+{
+ msglog_sysfs_create(opal_memcons, &opal_msglog_attr);
+ if (firmware_has_feature(FW_FEATURE_ULTRAVISOR))
+ msglog_sysfs_create(opal_uv_memcons, &opal_uv_msglog_attr);
}
--
2.20.1
^ permalink raw reply related
* Re: [PATCH v7 0/7] KVMPPC driver to manage secure guest pages
From: Paul Mackerras @ 2019-08-23 4:17 UTC (permalink / raw)
To: Bharata B Rao
Cc: linuxram, cclaudio, kvm-ppc, linux-mm, jglisse, aneesh.kumar,
paulus, sukadev, linuxppc-dev, hch
In-Reply-To: <20190822102620.21897-1-bharata@linux.ibm.com>
On Thu, Aug 22, 2019 at 03:56:13PM +0530, Bharata B Rao wrote:
> Hi,
>
> A pseries guest can be run as a secure guest on Ultravisor-enabled
> POWER platforms. On such platforms, this driver will be used to manage
> the movement of guest pages between the normal memory managed by
> hypervisor(HV) and secure memory managed by Ultravisor(UV).
>
> Private ZONE_DEVICE memory equal to the amount of secure memory
> available in the platform for running secure guests is created.
> Whenever a page belonging to the guest becomes secure, a page from
> this private device memory is used to represent and track that secure
> page on the HV side. The movement of pages between normal and secure
> memory is done via migrate_vma_pages(). The reverse movement is driven
> via pagemap_ops.migrate_to_ram().
>
> The page-in or page-out requests from UV will come to HV as hcalls and
> HV will call back into UV via uvcalls to satisfy these page requests.
>
> These patches are against hmm.git
> (https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git/log/?h=hmm)
>
> plus
>
> Claudio Carvalho's base ultravisor enablement patchset v6
> (https://lore.kernel.org/linuxppc-dev/20190822034838.27876-1-cclaudio@linux.ibm.com/T/#t)
How are you thinking these patches will go upstream? Are you going to
send them via the hmm tree?
I assume you need Claudio's patchset as a prerequisite for your series
to compile, which means the hmm maintainers would need to pull in a
topic branch from Michael Ellerman's powerpc tree, or something like
that.
Paul.
^ permalink raw reply
* Re: [PATCH kernel] vfio/spapr_tce: Fix incorrect tce_iommu_group memory free
From: Paul Mackerras @ 2019-08-23 5:32 UTC (permalink / raw)
To: Alexey Kardashevskiy
Cc: kvm, Jose Ricardo Ziviani, kvm-ppc, Alex Williamson, linuxppc-dev,
David Gibson
In-Reply-To: <20190819015117.94878-1-aik@ozlabs.ru>
On Mon, Aug 19, 2019 at 11:51:17AM +1000, Alexey Kardashevskiy wrote:
> The @tcegrp variable is used in 1) a loop over attached groups
> 2) it stores a pointer to a newly allocated tce_iommu_group if 1) found
> nothing. However the error handler does not distinguish how we got there
> and incorrectly releases memory for a found+incompatible group.
>
> This fixes it by adding another error handling case.
>
> Fixes: 0bd971676e68 ("powerpc/powernv/npu: Add compound IOMMU groups")
> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Good catch. This is potentially nasty since it is a double free.
Alex, are you going to take this, or would you prefer it goes via
Michael Ellerman's tree?
Reviewed-by: Paul Mackerras <paulus@ozlabs.org>
^ permalink raw reply
* RE: [PATCH v2 06/10] PCI: layerscape: Modify the way of getting capability with different PEX
From: Xiaowei Bao @ 2019-08-23 4:13 UTC (permalink / raw)
To: Kishon Vijay Abraham I, bhelgaas@google.com, robh+dt@kernel.org,
mark.rutland@arm.com, shawnguo@kernel.org, Leo Li,
lorenzo.pieralisi@arm.co, arnd@arndb.de,
gregkh@linuxfoundation.org, M.h. Lian, Mingkai Hu, Roy Zang,
jingoohan1@gmail.com, gustavo.pimentel@synopsys.com,
linux-pci@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linuxppc-dev@lists.ozlabs.org, andrew.murray@arm.com
In-Reply-To: <11e9b2c3-f4d0-2f82-bb14-45c38a1419e4@ti.com>
> -----Original Message-----
> From: Kishon Vijay Abraham I <kishon@ti.com>
> Sent: 2019年8月23日 11:40
> To: Xiaowei Bao <xiaowei.bao@nxp.com>; bhelgaas@google.com;
> robh+dt@kernel.org; mark.rutland@arm.com; shawnguo@kernel.org; Leo Li
> <leoyang.li@nxp.com>; lorenzo.pieralisi@arm.co
> <lorenzo.pieralisi@arm.com>; arnd@arndb.de; gregkh@linuxfoundation.org;
> M.h. Lian <minghuan.lian@nxp.com>; Mingkai Hu <mingkai.hu@nxp.com>;
> Roy Zang <roy.zang@nxp.com>; jingoohan1@gmail.com;
> gustavo.pimentel@synopsys.com; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; linux-kernel@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linuxppc-dev@lists.ozlabs.org;
> andrew.murray@arm.com
> Subject: Re: [PATCH v2 06/10] PCI: layerscape: Modify the way of getting
> capability with different PEX
>
> Hi,
>
> (Fixed Lorenzo's email address. All the patches in the series have wrong email
> id)
>
> On 23/08/19 8:09 AM, Xiaowei Bao wrote:
> >
> >
> >> -----Original Message-----
> >> From: Kishon Vijay Abraham I <kishon@ti.com>
> >> Sent: 2019年8月22日 19:44
> >> To: Xiaowei Bao <xiaowei.bao@nxp.com>; bhelgaas@google.com;
> >> robh+dt@kernel.org; mark.rutland@arm.com; shawnguo@kernel.org; Leo
> Li
> >> <leoyang.li@nxp.com>; lorenzo.pieralisi@arm.co; arnd@arndb.de;
> >> gregkh@linuxfoundation.org; M.h. Lian <minghuan.lian@nxp.com>;
> >> Mingkai Hu <mingkai.hu@nxp.com>; Roy Zang <roy.zang@nxp.com>;
> >> jingoohan1@gmail.com; gustavo.pimentel@synopsys.com;
> >> linux-pci@vger.kernel.org; devicetree@vger.kernel.org;
> >> linux-kernel@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> >> linuxppc-dev@lists.ozlabs.org; andrew.murray@arm.com
> >> Subject: Re: [PATCH v2 06/10] PCI: layerscape: Modify the way of
> >> getting capability with different PEX
> >>
> >> Hi,
> >>
> >> On 22/08/19 4:52 PM, Xiaowei Bao wrote:
> >>> The different PCIe controller in one board may be have different
> >>> capability of MSI or MSIX, so change the way of getting the MSI
> >>> capability, make it more flexible.
> >>
> >> please use different pci_epc_features table for different boards.
> > Thanks, I think that it will be more flexible to dynamically get MSI
> > or MSIX capability, Thus, we will not need to define the pci_epc_feature for
> different boards.
>
> Is the restriction because you cannot have different compatible for different
> boards?
Sorry, I am not very clear what your mean, I think even if I use the same compatible
with different boards, each boards will enter the probe function, in there I will get
the MSI or MSIX PCIe capability of the current controller in this board. Why do I need
to define the pci_epc_feature for different boards?
>
> Thanks
> Kishon
>
> >>
> >> Thanks
> >> Kishon
> >>>
> >>> Signed-off-by: Xiaowei Bao <xiaowei.bao@nxp.com>
> >>> ---
> >>> v2:
> >>> - Remove the repeated assignment code.
> >>>
> >>> drivers/pci/controller/dwc/pci-layerscape-ep.c | 26
> >>> +++++++++++++++++++-------
> >>> 1 file changed, 19 insertions(+), 7 deletions(-)
> >>>
> >>> diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> >>> b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> >>> index 4e92a95..8461f62 100644
> >>> --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> >>> +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> >>> @@ -22,6 +22,7 @@
> >>>
> >>> struct ls_pcie_ep {
> >>> struct dw_pcie *pci;
> >>> + struct pci_epc_features *ls_epc;
> >>> };
> >>>
> >>> #define to_ls_pcie_ep(x) dev_get_drvdata((x)->dev)
> >>> @@ -40,25 +41,26 @@ static const struct of_device_id
> >> ls_pcie_ep_of_match[] = {
> >>> { },
> >>> };
> >>>
> >>> -static const struct pci_epc_features ls_pcie_epc_features = {
> >>> - .linkup_notifier = false,
> >>> - .msi_capable = true,
> >>> - .msix_capable = false,
> >>> -};
> >>> -
> >>> static const struct pci_epc_features*
> >>> ls_pcie_ep_get_features(struct dw_pcie_ep *ep) {
> >>> - return &ls_pcie_epc_features;
> >>> + struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> >>> + struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
> >>> +
> >>> + return pcie->ls_epc;
> >>> }
> >>>
> >>> static void ls_pcie_ep_init(struct dw_pcie_ep *ep) {
> >>> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> >>> + struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
> >>> enum pci_barno bar;
> >>>
> >>> for (bar = BAR_0; bar <= BAR_5; bar++)
> >>> dw_pcie_ep_reset_bar(pci, bar);
> >>> +
> >>> + pcie->ls_epc->msi_capable = ep->msi_cap ? true : false;
> >>> + pcie->ls_epc->msix_capable = ep->msix_cap ? true : false;
> >>> }
> >>>
> >>> static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> >>> @@
> >>> -118,6 +120,7 @@ static int __init ls_pcie_ep_probe(struct
> >>> platform_device
> >> *pdev)
> >>> struct device *dev = &pdev->dev;
> >>> struct dw_pcie *pci;
> >>> struct ls_pcie_ep *pcie;
> >>> + struct pci_epc_features *ls_epc;
> >>> struct resource *dbi_base;
> >>> int ret;
> >>>
> >>> @@ -129,6 +132,10 @@ static int __init ls_pcie_ep_probe(struct
> >> platform_device *pdev)
> >>> if (!pci)
> >>> return -ENOMEM;
> >>>
> >>> + ls_epc = devm_kzalloc(dev, sizeof(*ls_epc), GFP_KERNEL);
> >>> + if (!ls_epc)
> >>> + return -ENOMEM;
> >>> +
> >>> dbi_base = platform_get_resource_byname(pdev,
> IORESOURCE_MEM,
> >> "regs");
> >>> pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);
> >>> if (IS_ERR(pci->dbi_base))
> >>> @@ -139,6 +146,11 @@ static int __init ls_pcie_ep_probe(struct
> >> platform_device *pdev)
> >>> pci->ops = &ls_pcie_ep_ops;
> >>> pcie->pci = pci;
> >>>
> >>> + ls_epc->linkup_notifier = false,
> >>> + ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4),
> >>> +
> >>> + pcie->ls_epc = ls_epc;
> >>> +
> >>> platform_set_drvdata(pdev, pcie);
> >>>
> >>> ret = ls_add_pcie_ep(pcie, pdev);
> >>>
^ permalink raw reply
* Re: [PATCH v3 1/2] powerpc/powernv: Enhance opal message read interface
From: Vasant Hegde @ 2019-08-23 4:10 UTC (permalink / raw)
To: Oliver O'Halloran, linuxppc-dev; +Cc: Mahesh Salgaonkar, Jeremy Kerr
In-Reply-To: <448acb2b-8ca1-329a-3070-285c692bbafa@linux.vnet.ibm.com>
On 8/22/19 9:06 PM, Vasant Hegde wrote:
> On 8/22/19 11:21 AM, Oliver O'Halloran wrote:
>> On Wed, 2019-08-21 at 13:43 +0530, Vasant Hegde wrote:
>>> Use "opal-msg-size" device tree property to allocate memory for "opal_msg".
>>>
>>> Cc: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>>> Cc: Jeremy Kerr <jk@ozlabs.org>
>>> Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
>>> ---
>>> Changes in v3:
>>> - Call BUG_ON, if we fail to allocate memory during init.
>>>
>>> -Vasant
>>>
>>> arch/powerpc/platforms/powernv/opal.c | 29 ++++++++++++++++++---------
>>> 1 file changed, 19 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/arch/powerpc/platforms/powernv/opal.c
>>> b/arch/powerpc/platforms/powernv/opal.c
>>> index aba443be7daa..4f1f68f568bf 100644
>>> --- a/arch/powerpc/platforms/powernv/opal.c
>>> +++ b/arch/powerpc/platforms/powernv/opal.c
>>> @@ -58,6 +58,8 @@ static DEFINE_SPINLOCK(opal_write_lock);
>>> static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX];
>>> static uint32_t opal_heartbeat;
>>> static struct task_struct *kopald_tsk;
>>> +static struct opal_msg *opal_msg;
>>> +static uint64_t opal_msg_size;
>>> void opal_configure_cores(void)
>>> {
>>> @@ -271,14 +273,9 @@ static void opal_message_do_notify(uint32_t msg_type,
>>> void *msg)
>>> static void opal_handle_message(void)
>>> {
>>> s64 ret;
>>> - /*
>>> - * TODO: pre-allocate a message buffer depending on opal-msg-size
>>> - * value in /proc/device-tree.
>>> - */
>>> - static struct opal_msg msg;
>>> u32 type;
>>> - ret = opal_get_msg(__pa(&msg), sizeof(msg));
>>> + ret = opal_get_msg(__pa(opal_msg), opal_msg_size);
>>> /* No opal message pending. */
>>> if (ret == OPAL_RESOURCE)
>>> return;
>>> @@ -290,14 +287,14 @@ static void opal_handle_message(void)
>>> return;
>>> }
>>> - type = be32_to_cpu(msg.msg_type);
>>> + type = be32_to_cpu(opal_msg->msg_type);
>>> /* Sanity check */
>>> if (type >= OPAL_MSG_TYPE_MAX) {
>>> pr_warn_once("%s: Unknown message type: %u\n", __func__, type);
>>> return;
>>> }
>>> - opal_message_do_notify(type, (void *)&msg);
>>> + opal_message_do_notify(type, (void *)opal_msg);
>>> }
>>> static irqreturn_t opal_message_notify(int irq, void *data)
>>> @@ -306,9 +303,21 @@ static irqreturn_t opal_message_notify(int irq, void *data)
>>> return IRQ_HANDLED;
>>> }
>>> -static int __init opal_message_init(void)
>>> +static int __init opal_message_init(struct device_node *opal_node)
>>> {
>>> int ret, i, irq;
>>
>>> + const __be32 *val;
>>> +
>>> + val = of_get_property(opal_node, "opal-msg-size", NULL);
>>> + if (val)
>>> + opal_msg_size = be32_to_cpup(val);
>>
>> Use of_property_read_u32()
>
> Yes. Will fix it.
>
>>
>>> +
>>> + /* If opal-msg-size property is not available then use default size */
>>> + if (!opal_msg_size)
>>> + opal_msg_size = sizeof(struct opal_msg);
>>> +
>>> + opal_msg = kmalloc(opal_msg_size, GFP_KERNEL);
>>
>>> + BUG_ON(opal_msg == NULL);
>>
>> Seems questionable. Why not fall back to using a staticly allocated
>> struct opal_msg? Or re-try the allocation with the size limited to
>> sizeof(struct opal_msg)?
>
> If we are not able to allocate memory during init then we have bigger problem.
> No point in continuing. Hence added BUG_ON().
> May be I can retry allocation with fixed size before calling BUG_ON().
> How about something like below :
>
> + /* If opal-msg-size property is not available then use default size */
> + if (!opal_msg_size)
> + opal_msg_size = sizeof(struct opal_msg);
> +
> + opal_msg = kmalloc(opal_msg_size, GFP_KERNEL);
> + if (!opal_msg) {
Just to be clear I will adjust `opal_msg_size` size here.
-Vasant
> + opal_msg = kmalloc(sizeof(struct opal_msg), GFP_KERNEL);
> + BUG_ON(opal_msg == NULL);
> + }
>
>
> -Vasant
>
^ permalink raw reply
* Re: [PATCH v6 7/7] powerpc/kvm: Use UV_RETURN ucall to return to ultravisor
From: Paul Mackerras @ 2019-08-23 3:59 UTC (permalink / raw)
To: Claudio Carvalho
Cc: Madhavan Srinivasan, Michael Anderson, Ram Pai, kvm-ppc,
Bharata B Rao, linuxppc-dev, Ryan Grimm, Sukadev Bhattiprolu,
Guerney Hunt, Thiago Bauermann
In-Reply-To: <20190822034838.27876-8-cclaudio@linux.ibm.com>
On Thu, Aug 22, 2019 at 12:48:38AM -0300, Claudio Carvalho wrote:
> From: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
>
> When an SVM makes an hypercall or incurs some other exception, the
> Ultravisor usually forwards (a.k.a. reflects) the exceptions to the
> Hypervisor. After processing the exception, Hypervisor uses the
> UV_RETURN ultracall to return control back to the SVM.
>
> The expected register state on entry to this ultracall is:
>
> * Non-volatile registers are restored to their original values.
> * If returning from an hypercall, register R0 contains the return value
> (unlike other ultracalls) and, registers R4 through R12 contain any
> output values of the hypercall.
> * R3 contains the ultracall number, i.e UV_RETURN.
> * If returning with a synthesized interrupt, R2 contains the
> synthesized interrupt number.
This isn't accurate: R2 contains the value that should end up in SRR1
when we are back in the secure guest. HSRR0 and HSRR1 contain the
instruction pointer and MSR that the guest should run with. They may
be different from the instruction pointer and MSR that the guest vCPU
last had, if the hypervisor has synthesized an interrupt for the
guest. The ultravisor needs to detect this case and respond
appropriately.
> Thanks to input from Paul Mackerras, Ram Pai and Mike Anderson.
>
> Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
> Signed-off-by: Claudio Carvalho <cclaudio@linux.ibm.com>
Apart from that comment on the patch description -
Acked-by: Paul Mackerras <paulus@ozlabs.org>
^ permalink raw reply
* Re: [PATCH v2 06/10] PCI: layerscape: Modify the way of getting capability with different PEX
From: Kishon Vijay Abraham I @ 2019-08-23 3:39 UTC (permalink / raw)
To: Xiaowei Bao, bhelgaas@google.com, robh+dt@kernel.org,
mark.rutland@arm.com, shawnguo@kernel.org, Leo Li,
lorenzo.pieralisi@arm.co, arnd@arndb.de,
gregkh@linuxfoundation.org, M.h. Lian, Mingkai Hu, Roy Zang,
jingoohan1@gmail.com, gustavo.pimentel@synopsys.com,
linux-pci@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linuxppc-dev@lists.ozlabs.org, andrew.murray@arm.com
In-Reply-To: <AM5PR04MB3299DE7B57F31EA405E4FCBCF5A40@AM5PR04MB3299.eurprd04.prod.outlook.com>
Hi,
(Fixed Lorenzo's email address. All the patches in the series have wrong email id)
On 23/08/19 8:09 AM, Xiaowei Bao wrote:
>
>
>> -----Original Message-----
>> From: Kishon Vijay Abraham I <kishon@ti.com>
>> Sent: 2019年8月22日 19:44
>> To: Xiaowei Bao <xiaowei.bao@nxp.com>; bhelgaas@google.com;
>> robh+dt@kernel.org; mark.rutland@arm.com; shawnguo@kernel.org; Leo Li
>> <leoyang.li@nxp.com>; lorenzo.pieralisi@arm.co; arnd@arndb.de;
>> gregkh@linuxfoundation.org; M.h. Lian <minghuan.lian@nxp.com>; Mingkai
>> Hu <mingkai.hu@nxp.com>; Roy Zang <roy.zang@nxp.com>;
>> jingoohan1@gmail.com; gustavo.pimentel@synopsys.com;
>> linux-pci@vger.kernel.org; devicetree@vger.kernel.org;
>> linux-kernel@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>> linuxppc-dev@lists.ozlabs.org; andrew.murray@arm.com
>> Subject: Re: [PATCH v2 06/10] PCI: layerscape: Modify the way of getting
>> capability with different PEX
>>
>> Hi,
>>
>> On 22/08/19 4:52 PM, Xiaowei Bao wrote:
>>> The different PCIe controller in one board may be have different
>>> capability of MSI or MSIX, so change the way of getting the MSI
>>> capability, make it more flexible.
>>
>> please use different pci_epc_features table for different boards.
> Thanks, I think that it will be more flexible to dynamically get MSI or MSIX capability,
> Thus, we will not need to define the pci_epc_feature for different boards.
Is the restriction because you cannot have different compatible for different
boards?
Thanks
Kishon
>>
>> Thanks
>> Kishon
>>>
>>> Signed-off-by: Xiaowei Bao <xiaowei.bao@nxp.com>
>>> ---
>>> v2:
>>> - Remove the repeated assignment code.
>>>
>>> drivers/pci/controller/dwc/pci-layerscape-ep.c | 26
>>> +++++++++++++++++++-------
>>> 1 file changed, 19 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c
>>> b/drivers/pci/controller/dwc/pci-layerscape-ep.c
>>> index 4e92a95..8461f62 100644
>>> --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
>>> +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
>>> @@ -22,6 +22,7 @@
>>>
>>> struct ls_pcie_ep {
>>> struct dw_pcie *pci;
>>> + struct pci_epc_features *ls_epc;
>>> };
>>>
>>> #define to_ls_pcie_ep(x) dev_get_drvdata((x)->dev)
>>> @@ -40,25 +41,26 @@ static const struct of_device_id
>> ls_pcie_ep_of_match[] = {
>>> { },
>>> };
>>>
>>> -static const struct pci_epc_features ls_pcie_epc_features = {
>>> - .linkup_notifier = false,
>>> - .msi_capable = true,
>>> - .msix_capable = false,
>>> -};
>>> -
>>> static const struct pci_epc_features* ls_pcie_ep_get_features(struct
>>> dw_pcie_ep *ep) {
>>> - return &ls_pcie_epc_features;
>>> + struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
>>> + struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
>>> +
>>> + return pcie->ls_epc;
>>> }
>>>
>>> static void ls_pcie_ep_init(struct dw_pcie_ep *ep) {
>>> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
>>> + struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
>>> enum pci_barno bar;
>>>
>>> for (bar = BAR_0; bar <= BAR_5; bar++)
>>> dw_pcie_ep_reset_bar(pci, bar);
>>> +
>>> + pcie->ls_epc->msi_capable = ep->msi_cap ? true : false;
>>> + pcie->ls_epc->msix_capable = ep->msix_cap ? true : false;
>>> }
>>>
>>> static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, @@
>>> -118,6 +120,7 @@ static int __init ls_pcie_ep_probe(struct platform_device
>> *pdev)
>>> struct device *dev = &pdev->dev;
>>> struct dw_pcie *pci;
>>> struct ls_pcie_ep *pcie;
>>> + struct pci_epc_features *ls_epc;
>>> struct resource *dbi_base;
>>> int ret;
>>>
>>> @@ -129,6 +132,10 @@ static int __init ls_pcie_ep_probe(struct
>> platform_device *pdev)
>>> if (!pci)
>>> return -ENOMEM;
>>>
>>> + ls_epc = devm_kzalloc(dev, sizeof(*ls_epc), GFP_KERNEL);
>>> + if (!ls_epc)
>>> + return -ENOMEM;
>>> +
>>> dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>> "regs");
>>> pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);
>>> if (IS_ERR(pci->dbi_base))
>>> @@ -139,6 +146,11 @@ static int __init ls_pcie_ep_probe(struct
>> platform_device *pdev)
>>> pci->ops = &ls_pcie_ep_ops;
>>> pcie->pci = pci;
>>>
>>> + ls_epc->linkup_notifier = false,
>>> + ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4),
>>> +
>>> + pcie->ls_epc = ls_epc;
>>> +
>>> platform_set_drvdata(pdev, pcie);
>>>
>>> ret = ls_add_pcie_ep(pcie, pdev);
>>>
^ permalink raw reply
* RE: [PATCH v2 06/10] PCI: layerscape: Modify the way of getting capability with different PEX
From: Xiaowei Bao @ 2019-08-23 2:39 UTC (permalink / raw)
To: Kishon Vijay Abraham I, bhelgaas@google.com, robh+dt@kernel.org,
mark.rutland@arm.com, shawnguo@kernel.org, Leo Li,
lorenzo.pieralisi@arm.co, arnd@arndb.de,
gregkh@linuxfoundation.org, M.h. Lian, Mingkai Hu, Roy Zang,
jingoohan1@gmail.com, gustavo.pimentel@synopsys.com,
linux-pci@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linuxppc-dev@lists.ozlabs.org, andrew.murray@arm.com
In-Reply-To: <0c02ac52-e4b1-8071-bf9e-d10b28fc9029@ti.com>
> -----Original Message-----
> From: Kishon Vijay Abraham I <kishon@ti.com>
> Sent: 2019年8月22日 19:44
> To: Xiaowei Bao <xiaowei.bao@nxp.com>; bhelgaas@google.com;
> robh+dt@kernel.org; mark.rutland@arm.com; shawnguo@kernel.org; Leo Li
> <leoyang.li@nxp.com>; lorenzo.pieralisi@arm.co; arnd@arndb.de;
> gregkh@linuxfoundation.org; M.h. Lian <minghuan.lian@nxp.com>; Mingkai
> Hu <mingkai.hu@nxp.com>; Roy Zang <roy.zang@nxp.com>;
> jingoohan1@gmail.com; gustavo.pimentel@synopsys.com;
> linux-pci@vger.kernel.org; devicetree@vger.kernel.org;
> linux-kernel@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> linuxppc-dev@lists.ozlabs.org; andrew.murray@arm.com
> Subject: Re: [PATCH v2 06/10] PCI: layerscape: Modify the way of getting
> capability with different PEX
>
> Hi,
>
> On 22/08/19 4:52 PM, Xiaowei Bao wrote:
> > The different PCIe controller in one board may be have different
> > capability of MSI or MSIX, so change the way of getting the MSI
> > capability, make it more flexible.
>
> please use different pci_epc_features table for different boards.
Thanks, I think that it will be more flexible to dynamically get MSI or MSIX capability,
Thus, we will not need to define the pci_epc_feature for different boards.
>
> Thanks
> Kishon
> >
> > Signed-off-by: Xiaowei Bao <xiaowei.bao@nxp.com>
> > ---
> > v2:
> > - Remove the repeated assignment code.
> >
> > drivers/pci/controller/dwc/pci-layerscape-ep.c | 26
> > +++++++++++++++++++-------
> > 1 file changed, 19 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > index 4e92a95..8461f62 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > @@ -22,6 +22,7 @@
> >
> > struct ls_pcie_ep {
> > struct dw_pcie *pci;
> > + struct pci_epc_features *ls_epc;
> > };
> >
> > #define to_ls_pcie_ep(x) dev_get_drvdata((x)->dev)
> > @@ -40,25 +41,26 @@ static const struct of_device_id
> ls_pcie_ep_of_match[] = {
> > { },
> > };
> >
> > -static const struct pci_epc_features ls_pcie_epc_features = {
> > - .linkup_notifier = false,
> > - .msi_capable = true,
> > - .msix_capable = false,
> > -};
> > -
> > static const struct pci_epc_features* ls_pcie_ep_get_features(struct
> > dw_pcie_ep *ep) {
> > - return &ls_pcie_epc_features;
> > + struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > + struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
> > +
> > + return pcie->ls_epc;
> > }
> >
> > static void ls_pcie_ep_init(struct dw_pcie_ep *ep) {
> > struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > + struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
> > enum pci_barno bar;
> >
> > for (bar = BAR_0; bar <= BAR_5; bar++)
> > dw_pcie_ep_reset_bar(pci, bar);
> > +
> > + pcie->ls_epc->msi_capable = ep->msi_cap ? true : false;
> > + pcie->ls_epc->msix_capable = ep->msix_cap ? true : false;
> > }
> >
> > static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, @@
> > -118,6 +120,7 @@ static int __init ls_pcie_ep_probe(struct platform_device
> *pdev)
> > struct device *dev = &pdev->dev;
> > struct dw_pcie *pci;
> > struct ls_pcie_ep *pcie;
> > + struct pci_epc_features *ls_epc;
> > struct resource *dbi_base;
> > int ret;
> >
> > @@ -129,6 +132,10 @@ static int __init ls_pcie_ep_probe(struct
> platform_device *pdev)
> > if (!pci)
> > return -ENOMEM;
> >
> > + ls_epc = devm_kzalloc(dev, sizeof(*ls_epc), GFP_KERNEL);
> > + if (!ls_epc)
> > + return -ENOMEM;
> > +
> > dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> "regs");
> > pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);
> > if (IS_ERR(pci->dbi_base))
> > @@ -139,6 +146,11 @@ static int __init ls_pcie_ep_probe(struct
> platform_device *pdev)
> > pci->ops = &ls_pcie_ep_ops;
> > pcie->pci = pci;
> >
> > + ls_epc->linkup_notifier = false,
> > + ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4),
> > +
> > + pcie->ls_epc = ls_epc;
> > +
> > platform_set_drvdata(pdev, pcie);
> >
> > ret = ls_add_pcie_ep(pcie, pdev);
> >
^ permalink raw reply
* Re: [PATCH 2/3] powerpc/numa: Early request for home node associativity
From: Nathan Lynch @ 2019-08-22 18:33 UTC (permalink / raw)
To: Srikar Dronamraju; +Cc: linuxppc-dev, Nicholas Piggin
In-Reply-To: <20190822174005.GA31809@linux.vnet.ibm.com>
Srikar Dronamraju <srikar@linux.vnet.ibm.com> writes:
> * Nathan Lynch <nathanl@linux.ibm.com> [2019-08-22 12:17:48]:
>> > However home node associativity requires cpu's hwid which is set in
>> > smp_setup_pacas. Hence call smp_setup_pacas before numa_setup_cpus.
>>
>> But this seems like it would negatively affect pacas' NUMA placements?
>>
>> Would it be less risky to figure out a way to do "early" VPHN hcalls
>> before mem_topology_setup, getting the hwids from the cpu_to_phys_id
>> array perhaps?
>>
>
> Do you mean for calls from mem_topology_setup(), stuff we use cpu_to_phys_id
> but for the calls from ppc_numa_cpu_prepare() we use the
> get_hard_smp_processor_id()?
Yes, something like that, I think. Although numa_setup_cpu() is used in
both contexts.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox