* [PATCH v3 5/6] fs/core/vmcore: Move sev_active() reference to x86 arch code
From: Thiago Jung Bauermann @ 2019-07-18 3:28 UTC (permalink / raw)
To: x86
Cc: linux-s390, Konrad Rzeszutek Wilk, Robin Murphy, Mike Anderson,
Ram Pai, linux-kernel, Alexey Dobriyan, Halil Pasic, iommu,
Ingo Molnar, Borislav Petkov, Thomas Lendacky, H. Peter Anvin,
linux-fsdevel, Thomas Gleixner, linuxppc-dev, Christoph Hellwig,
Thiago Jung Bauermann, Marek Szyprowski
In-Reply-To: <20190718032858.28744-1-bauerman@linux.ibm.com>
Secure Encrypted Virtualization is an x86-specific feature, so it shouldn't
appear in generic kernel code because it forces non-x86 architectures to
define the sev_active() function, which doesn't make a lot of sense.
To solve this problem, add an x86 elfcorehdr_read() function to override
the generic weak implementation. To do that, it's necessary to make
read_from_oldmem() public so that it can be used outside of vmcore.c.
Also, remove the export for sev_active() since it's only used in files that
won't be built as modules.
Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
---
arch/x86/kernel/crash_dump_64.c | 5 +++++
arch/x86/mm/mem_encrypt.c | 1 -
fs/proc/vmcore.c | 8 ++++----
include/linux/crash_dump.h | 14 ++++++++++++++
include/linux/mem_encrypt.h | 1 -
5 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c
index 22369dd5de3b..045e82e8945b 100644
--- a/arch/x86/kernel/crash_dump_64.c
+++ b/arch/x86/kernel/crash_dump_64.c
@@ -70,3 +70,8 @@ ssize_t copy_oldmem_page_encrypted(unsigned long pfn, char *buf, size_t csize,
{
return __copy_oldmem_page(pfn, buf, csize, offset, userbuf, true);
}
+
+ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos)
+{
+ return read_from_oldmem(buf, count, ppos, 0, sev_active());
+}
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 7139f2f43955..b1e823441093 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -349,7 +349,6 @@ bool sev_active(void)
{
return sme_me_mask && sev_enabled;
}
-EXPORT_SYMBOL(sev_active);
/* Override for DMA direct allocation check - ARCH_HAS_FORCE_DMA_UNENCRYPTED */
bool force_dma_unencrypted(struct device *dev)
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 57957c91c6df..ca1f20bedd8c 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -100,9 +100,9 @@ static int pfn_is_ram(unsigned long pfn)
}
/* Reads a page from the oldmem device from given offset. */
-static ssize_t read_from_oldmem(char *buf, size_t count,
- u64 *ppos, int userbuf,
- bool encrypted)
+ssize_t read_from_oldmem(char *buf, size_t count,
+ u64 *ppos, int userbuf,
+ bool encrypted)
{
unsigned long pfn, offset;
size_t nr_bytes;
@@ -166,7 +166,7 @@ void __weak elfcorehdr_free(unsigned long long addr)
*/
ssize_t __weak elfcorehdr_read(char *buf, size_t count, u64 *ppos)
{
- return read_from_oldmem(buf, count, ppos, 0, sev_active());
+ return read_from_oldmem(buf, count, ppos, 0, false);
}
/*
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index f774c5eb9e3c..4664fc1871de 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -115,4 +115,18 @@ static inline int vmcore_add_device_dump(struct vmcoredd_data *data)
return -EOPNOTSUPP;
}
#endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */
+
+#ifdef CONFIG_PROC_VMCORE
+ssize_t read_from_oldmem(char *buf, size_t count,
+ u64 *ppos, int userbuf,
+ bool encrypted);
+#else
+static inline ssize_t read_from_oldmem(char *buf, size_t count,
+ u64 *ppos, int userbuf,
+ bool encrypted)
+{
+ return -EOPNOTSUPP;
+}
+#endif /* CONFIG_PROC_VMCORE */
+
#endif /* LINUX_CRASHDUMP_H */
diff --git a/include/linux/mem_encrypt.h b/include/linux/mem_encrypt.h
index 0c5b0ff9eb29..5c4a18a91f89 100644
--- a/include/linux/mem_encrypt.h
+++ b/include/linux/mem_encrypt.h
@@ -19,7 +19,6 @@
#else /* !CONFIG_ARCH_HAS_MEM_ENCRYPT */
static inline bool mem_encrypt_active(void) { return false; }
-static inline bool sev_active(void) { return false; }
#endif /* CONFIG_ARCH_HAS_MEM_ENCRYPT */
^ permalink raw reply related
* [PATCH v3 4/6] x86, s390/mm: Move sme_active() and sme_me_mask to x86-specific header
From: Thiago Jung Bauermann @ 2019-07-18 3:28 UTC (permalink / raw)
To: x86
Cc: linux-s390, Konrad Rzeszutek Wilk, Robin Murphy, Mike Anderson,
Ram Pai, linux-kernel, Alexey Dobriyan, Halil Pasic, iommu,
Ingo Molnar, Borislav Petkov, Thomas Lendacky, H. Peter Anvin,
linux-fsdevel, Thomas Gleixner, linuxppc-dev, Christoph Hellwig,
Thiago Jung Bauermann, Marek Szyprowski
In-Reply-To: <20190718032858.28744-1-bauerman@linux.ibm.com>
Now that generic code doesn't reference them, move sme_active() and
sme_me_mask to x86's <asm/mem_encrypt.h>.
Also remove the export for sme_active() since it's only used in files that
won't be built as modules. sme_me_mask on the other hand is used in
arch/x86/kvm/svm.c (via __sme_set() and __psp_pa()) which can be built as a
module so its export needs to stay.
Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
---
arch/s390/include/asm/mem_encrypt.h | 4 +---
arch/x86/include/asm/mem_encrypt.h | 10 ++++++++++
arch/x86/mm/mem_encrypt.c | 1 -
include/linux/mem_encrypt.h | 14 +-------------
4 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/arch/s390/include/asm/mem_encrypt.h b/arch/s390/include/asm/mem_encrypt.h
index 3eb018508190..ff813a56bc30 100644
--- a/arch/s390/include/asm/mem_encrypt.h
+++ b/arch/s390/include/asm/mem_encrypt.h
@@ -4,9 +4,7 @@
#ifndef __ASSEMBLY__
-#define sme_me_mask 0ULL
-
-static inline bool sme_active(void) { return false; }
+static inline bool mem_encrypt_active(void) { return false; }
extern bool sev_active(void);
int set_memory_encrypted(unsigned long addr, int numpages);
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 0c196c47d621..848ce43b9040 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -92,6 +92,16 @@ early_set_memory_encrypted(unsigned long vaddr, unsigned long size) { return 0;
extern char __start_bss_decrypted[], __end_bss_decrypted[], __start_bss_decrypted_unused[];
+static inline bool mem_encrypt_active(void)
+{
+ return sme_me_mask;
+}
+
+static inline u64 sme_get_me_mask(void)
+{
+ return sme_me_mask;
+}
+
#endif /* __ASSEMBLY__ */
#endif /* __X86_MEM_ENCRYPT_H__ */
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index c805f0a5c16e..7139f2f43955 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -344,7 +344,6 @@ bool sme_active(void)
{
return sme_me_mask && !sev_enabled;
}
-EXPORT_SYMBOL(sme_active);
bool sev_active(void)
{
diff --git a/include/linux/mem_encrypt.h b/include/linux/mem_encrypt.h
index 470bd53a89df..0c5b0ff9eb29 100644
--- a/include/linux/mem_encrypt.h
+++ b/include/linux/mem_encrypt.h
@@ -18,23 +18,11 @@
#else /* !CONFIG_ARCH_HAS_MEM_ENCRYPT */
-#define sme_me_mask 0ULL
-
-static inline bool sme_active(void) { return false; }
+static inline bool mem_encrypt_active(void) { return false; }
static inline bool sev_active(void) { return false; }
#endif /* CONFIG_ARCH_HAS_MEM_ENCRYPT */
-static inline bool mem_encrypt_active(void)
-{
- return sme_me_mask;
-}
-
-static inline u64 sme_get_me_mask(void)
-{
- return sme_me_mask;
-}
-
#ifdef CONFIG_AMD_MEM_ENCRYPT
/*
* The __sme_set() and __sme_clr() macros are useful for adding or removing
^ permalink raw reply related
* [PATCH v3 6/6] s390/mm: Remove sev_active() function
From: Thiago Jung Bauermann @ 2019-07-18 3:28 UTC (permalink / raw)
To: x86
Cc: linux-s390, Konrad Rzeszutek Wilk, Robin Murphy, Mike Anderson,
Ram Pai, linux-kernel, Alexey Dobriyan, Halil Pasic, iommu,
Ingo Molnar, Borislav Petkov, Thomas Lendacky, H. Peter Anvin,
linux-fsdevel, Thomas Gleixner, linuxppc-dev, Christoph Hellwig,
Thiago Jung Bauermann, Marek Szyprowski
In-Reply-To: <20190718032858.28744-1-bauerman@linux.ibm.com>
All references to sev_active() were moved to arch/x86 so we don't need to
define it for s390 anymore.
Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
---
arch/s390/include/asm/mem_encrypt.h | 1 -
arch/s390/mm/init.c | 8 +-------
2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/arch/s390/include/asm/mem_encrypt.h b/arch/s390/include/asm/mem_encrypt.h
index ff813a56bc30..2542cbf7e2d1 100644
--- a/arch/s390/include/asm/mem_encrypt.h
+++ b/arch/s390/include/asm/mem_encrypt.h
@@ -5,7 +5,6 @@
#ifndef __ASSEMBLY__
static inline bool mem_encrypt_active(void) { return false; }
-extern bool sev_active(void);
int set_memory_encrypted(unsigned long addr, int numpages);
int set_memory_decrypted(unsigned long addr, int numpages);
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 78c319c5ce48..6286eb3e815b 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -155,15 +155,9 @@ int set_memory_decrypted(unsigned long addr, int numpages)
return 0;
}
-/* are we a protected virtualization guest? */
-bool sev_active(void)
-{
- return is_prot_virt_guest();
-}
-
bool force_dma_unencrypted(struct device *dev)
{
- return sev_active();
+ return is_prot_virt_guest();
}
/* protected virtualization */
^ permalink raw reply related
* Re: [PATCH] powerpc/dma: Fix invalid DMA mmap behavior
From: Oliver O'Halloran @ 2019-07-18 3:45 UTC (permalink / raw)
To: Shawn Anastasio
Cc: Alexey Kardashevskiy, Sam Bobroff, linuxppc-dev,
Christoph Hellwig
In-Reply-To: <f9753335-b62c-67b4-84d7-7b67fe1b64ca@anastas.io>
On Thu, Jul 18, 2019 at 1:16 PM Shawn Anastasio <shawn@anastas.io> wrote:
>
> On 7/17/19 9:59 PM, Alexey Kardashevskiy wrote:
> >
> > On 18/07/2019 09:54, Shawn Anastasio wrote:
> >> The refactor of powerpc DMA functions in commit 6666cc17d780
> >> ("powerpc/dma: remove dma_nommu_mmap_coherent") incorrectly
> >> changes the way DMA mappings are handled on powerpc.
> >> Since this change, all mapped pages are marked as cache-inhibited
> >> through the default implementation of arch_dma_mmap_pgprot.
> >> This differs from the previous behavior of only marking pages
> >> in noncoherent mappings as cache-inhibited and has resulted in
> >> sporadic system crashes in certain hardware configurations and
> >> workloads (see Bugzilla).
> >>
> >> This commit restores the previous correct behavior by providing
> >> an implementation of arch_dma_mmap_pgprot that only marks
> >> pages in noncoherent mappings as cache-inhibited. As this behavior
> >> should be universal for all powerpc platforms a new file,
> >> dma-generic.c, was created to store it.
> >>
> >> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204145
> >> Fixes: 6666cc17d780 ("powerpc/dma: remove dma_nommu_mmap_coherent")
> >> Signed-off-by: Shawn Anastasio <shawn@anastas.io>
> >
> > Is this the default one?
> >
> > include/linux/dma-noncoherent.h
> > # define arch_dma_mmap_pgprot(dev, prot, attrs) pgprot_noncached(prot)
>
> Yep, that's the one.
>
> > Out of curiosity - do not we want to fix this one for everyone?
>
> Other than m68k, mips, and arm64, everybody else that doesn't have
> ARCH_NO_COHERENT_DMA_MMAP set uses this default implementation, so
> I assume this behavior is acceptable on those architectures.
It might be acceptable, but there's no reason to use pgport_noncached
if the platform supports cache-coherent DMA.
Christoph (+cc) made the change so maybe he saw something we're missing.
> >> ---
> >> arch/powerpc/Kconfig | 1 +
> >> arch/powerpc/kernel/Makefile | 3 ++-
> >> arch/powerpc/kernel/dma-common.c | 17 +++++++++++++++++
> >> 3 files changed, 20 insertions(+), 1 deletion(-)
> >> create mode 100644 arch/powerpc/kernel/dma-common.c
> >>
> >> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> >> index d8dcd8820369..77f6ebf97113 100644
> >> --- a/arch/powerpc/Kconfig
> >> +++ b/arch/powerpc/Kconfig
> >> @@ -121,6 +121,7 @@ config PPC
> >> select ARCH_32BIT_OFF_T if PPC32
> >> select ARCH_HAS_DEBUG_VIRTUAL
> >> select ARCH_HAS_DEVMEM_IS_ALLOWED
> >> + select ARCH_HAS_DMA_MMAP_PGPROT
> >> select ARCH_HAS_ELF_RANDOMIZE
> >> select ARCH_HAS_FORTIFY_SOURCE
> >> select ARCH_HAS_GCOV_PROFILE_ALL
> >> diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
> >> index 56dfa7a2a6f2..ea0c69236789 100644
> >> --- a/arch/powerpc/kernel/Makefile
> >> +++ b/arch/powerpc/kernel/Makefile
> >> @@ -49,7 +49,8 @@ obj-y := cputable.o ptrace.o
> >> syscalls.o \
> >> signal.o sysfs.o cacheinfo.o time.o \
> >> prom.o traps.o setup-common.o \
> >> udbg.o misc.o io.o misc_$(BITS).o \
> >> - of_platform.o prom_parse.o
> >> + of_platform.o prom_parse.o \
> >> + dma-common.o
> >> obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \
> >> signal_64.o ptrace32.o \
> >> paca.o nvram_64.o firmware.o
> >> diff --git a/arch/powerpc/kernel/dma-common.c
> >> b/arch/powerpc/kernel/dma-common.c
> >> new file mode 100644
> >> index 000000000000..5a15f99f4199
> >> --- /dev/null
> >> +++ b/arch/powerpc/kernel/dma-common.c
> >> @@ -0,0 +1,17 @@
> >> +// SPDX-License-Identifier: GPL-2.0-or-later
> >> +/*
> >> + * Contains common dma routines for all powerpc platforms.
> >> + *
> >> + * Copyright (C) 2019 Shawn Anastasio (shawn@anastas.io)
> >> + */
> >> +
> >> +#include <linux/mm.h>
> >> +#include <linux/dma-noncoherent.h>
> >> +
> >> +pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
> >> + unsigned long attrs)
> >> +{
> >> + if (!dev_is_dma_coherent(dev))
> >> + return pgprot_noncached(prot);
> >> + return prot;
> >> +}
> >>
> >
^ permalink raw reply
* [PATCH kernel v4 0/2] powerpc/xive: Drop deregistered irqs
From: Alexey Kardashevskiy @ 2019-07-18 5:06 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Cédric Le Goater, Greg Kurz
Now 2 patches.
v3 is here: https://patchwork.ozlabs.org/patch/1133106/
This is based on sha1
a2b6f26c264e Christophe Leroy "powerpc/module64: Use symbolic instructions names.".
Please comment. Thanks.
Alexey Kardashevskiy (2):
powerpc: Add handler for orphaned interrupts
powerpc/xive: Drop current cpu priority for orphaned interrupts
arch/powerpc/include/asm/machdep.h | 3 +++
arch/powerpc/kernel/irq.c | 9 ++++++---
arch/powerpc/sysdev/xive/common.c | 18 ++++++++++++++++++
3 files changed, 27 insertions(+), 3 deletions(-)
--
2.17.1
^ permalink raw reply
* [PATCH kernel v4 1/2] powerpc: Add handler for orphaned interrupts
From: Alexey Kardashevskiy @ 2019-07-18 5:06 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Cédric Le Goater, Greg Kurz
In-Reply-To: <20190718050604.74233-1-aik@ozlabs.ru>
The test on generic_handle_irq() catches interrupt events that
were served on a target CPU while the source interrupt was being
shutdown on another CPU. This may lead to a blocked interrupt queue
on a target CPU so if there is another assigned irq on that CPU, that
device stops working.
This adds necessary infrastructure to allow platform to deal with it.
The next patch implements it for XIVE.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
arch/powerpc/include/asm/machdep.h | 3 +++
arch/powerpc/kernel/irq.c | 9 ++++++---
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index c43d6eca9edd..6cc14e28e89a 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -59,6 +59,9 @@ struct machdep_calls {
/* Return an irq, or 0 to indicate there are none pending. */
unsigned int (*get_irq)(void);
+ /* Drops irq if it does not have a valid descriptor */
+ void (*orphan_irq)(unsigned int irq);
+
/* PCI stuff */
/* Called after allocating resources */
void (*pcibios_fixup)(void);
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 5645bc9cbc09..e0689dcb17f0 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -632,10 +632,13 @@ void __do_irq(struct pt_regs *regs)
may_hard_irq_enable();
/* And finally process it */
- if (unlikely(!irq))
+ if (unlikely(!irq)) {
__this_cpu_inc(irq_stat.spurious_irqs);
- else
- generic_handle_irq(irq);
+ } else if (generic_handle_irq(irq)) {
+ if (ppc_md.orphan_irq)
+ ppc_md.orphan_irq(irq);
+ __this_cpu_inc(irq_stat.spurious_irqs);
+ }
trace_irq_exit(regs);
--
2.17.1
^ permalink raw reply related
* [PATCH kernel v4 2/2] powerpc/xive: Drop current cpu priority for orphaned interrupts
From: Alexey Kardashevskiy @ 2019-07-18 5:06 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Cédric Le Goater, Greg Kurz
In-Reply-To: <20190718050604.74233-1-aik@ozlabs.ru>
There is a race between releasing an irq on one cpu and fetching it
from XIVE on another cpu. When such released irq appears in a queue,
we take it from the queue but we do not change the current priority
on that cpu and since there is no handler for the irq, EOI is never
called and the cpu current priority remains elevated
(7 vs. 0xff==unmasked). If another irq is assigned to the same cpu,
then that device stops working until irq is moved to another cpu or
the device is reset.
This implements ppc_md.orphan_irq callback which is called if no irq
descriptor is found and which drops the current priority
to 0xff which effectively unmasks interrupts in a current CPU.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
arch/powerpc/sysdev/xive/common.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c
index 082c7e1c20f0..17e696b2d71b 100644
--- a/arch/powerpc/sysdev/xive/common.c
+++ b/arch/powerpc/sysdev/xive/common.c
@@ -283,6 +283,23 @@ static unsigned int xive_get_irq(void)
return irq;
}
+/*
+ * Handles the case when a target CPU catches an interrupt which is being shut
+ * down on another CPU. generic_handle_irq() returns an error in such case
+ * and then the orphan_irq() handler restores the CPPR to reenable interrupts.
+ *
+ * Without orphan_irq() and valid irq_desc, there is no other way to restore
+ * the CPPR. This executes on a CPU which caught the interrupt.
+ */
+static void xive_orphan_irq(unsigned int irq)
+{
+ struct xive_cpu *xc = __this_cpu_read(xive_cpu);
+
+ xc->cppr = 0xff;
+ out_8(xive_tima + xive_tima_offset + TM_CPPR, 0xff);
+ DBG_VERBOSE("orphan_irq: irq %d, adjusting CPPR to 0xff\n", irq);
+}
+
/*
* After EOI'ing an interrupt, we need to re-check the queue
* to see if another interrupt is pending since multiple
@@ -1419,6 +1436,7 @@ bool __init xive_core_init(const struct xive_ops *ops, void __iomem *area, u32 o
xive_irq_priority = max_prio;
ppc_md.get_irq = xive_get_irq;
+ ppc_md.orphan_irq = xive_orphan_irq;
__xive_enabled = true;
pr_devel("Initializing host..\n");
--
2.17.1
^ permalink raw reply related
* [PATCH kernel v5 1/4] powerpc/powernv/ioda: Fix race in TCE level allocation
From: Alexey Kardashevskiy @ 2019-07-18 5:11 UTC (permalink / raw)
To: linuxppc-dev
Cc: Sam Bobroff, Alistair Popple, stable, Alexey Kardashevskiy,
Oliver O'Halloran, David Gibson
In-Reply-To: <20190718051139.74787-1-aik@ozlabs.ru>
pnv_tce() returns a pointer to a TCE entry and originally a TCE table
would be pre-allocated. For the default case of 2GB window the table
needs only a single level and that is fine. However if more levels are
requested, it is possible to get a race when 2 threads want a pointer
to a TCE entry from the same page of TCEs.
This adds cmpxchg to handle the race. Note that once TCE is non-zero,
it cannot become zero again.
CC: stable@vger.kernel.org # v4.19+
Fixes: a68bd1267b72 ("powerpc/powernv/ioda: Allocate indirect TCE levels on demand")
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
The race occurs about 30 times in the first 3 minutes of copying files
via rsync and that's about it.
This fixes EEH's from
https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=110810
---
Changes:
v2:
* replaced spin_lock with cmpxchg+readonce
---
arch/powerpc/platforms/powernv/pci-ioda-tce.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/pci-ioda-tce.c b/arch/powerpc/platforms/powernv/pci-ioda-tce.c
index e28f03e1eb5e..8d6569590161 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda-tce.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda-tce.c
@@ -48,6 +48,9 @@ static __be64 *pnv_alloc_tce_level(int nid, unsigned int shift)
return addr;
}
+static void pnv_pci_ioda2_table_do_free_pages(__be64 *addr,
+ unsigned long size, unsigned int levels);
+
static __be64 *pnv_tce(struct iommu_table *tbl, bool user, long idx, bool alloc)
{
__be64 *tmp = user ? tbl->it_userspace : (__be64 *) tbl->it_base;
@@ -57,9 +60,9 @@ static __be64 *pnv_tce(struct iommu_table *tbl, bool user, long idx, bool alloc)
while (level) {
int n = (idx & mask) >> (level * shift);
- unsigned long tce;
+ unsigned long oldtce, tce = be64_to_cpu(READ_ONCE(tmp[n]));
- if (tmp[n] == 0) {
+ if (!tce) {
__be64 *tmp2;
if (!alloc)
@@ -70,10 +73,15 @@ static __be64 *pnv_tce(struct iommu_table *tbl, bool user, long idx, bool alloc)
if (!tmp2)
return NULL;
- tmp[n] = cpu_to_be64(__pa(tmp2) |
- TCE_PCI_READ | TCE_PCI_WRITE);
+ tce = __pa(tmp2) | TCE_PCI_READ | TCE_PCI_WRITE;
+ oldtce = be64_to_cpu(cmpxchg(&tmp[n], 0,
+ cpu_to_be64(tce)));
+ if (oldtce) {
+ pnv_pci_ioda2_table_do_free_pages(tmp2,
+ ilog2(tbl->it_level_size) + 3, 1);
+ tce = oldtce;
+ }
}
- tce = be64_to_cpu(tmp[n]);
tmp = __va(tce & ~(TCE_PCI_READ | TCE_PCI_WRITE));
idx &= ~mask;
--
2.17.1
^ permalink raw reply related
* [PATCH kernel v5 0/4] powerpc/ioda2: Yet another attempt to allow DMA masks between 32 and 59
From: Alexey Kardashevskiy @ 2019-07-18 5:11 UTC (permalink / raw)
To: linuxppc-dev
Cc: Sam Bobroff, Alistair Popple, Oliver O'Halloran,
Alexey Kardashevskiy, David Gibson
This is an attempt to allow DMA masks between 32..59 which are not large
enough to use either a PHB3 bypass mode or a sketchy bypass. Depending
on the max order, up to 40 is usually available.
This is an optimization and not a bug fix for DMA API usage.
Changelogs are in the patches.
This is based on sha1
a2b6f26c264e Christophe Leroy "powerpc/module64: Use symbolic instructions names.".
Please comment. Thanks.
Alexey Kardashevskiy (4):
powerpc/powernv/ioda: Fix race in TCE level allocation
powerpc/iommu: Allow bypass-only for DMA
powerpc/powernv/ioda2: Allocate TCE table levels on demand for default
DMA window
powerpc/powernv/ioda2: Create bigger default window with 64k IOMMU
pages
arch/powerpc/include/asm/iommu.h | 7 +-
arch/powerpc/platforms/powernv/pci.h | 2 +-
arch/powerpc/kernel/dma-iommu.c | 11 ++-
arch/powerpc/kernel/iommu.c | 74 +++++++++++++------
arch/powerpc/platforms/cell/iommu.c | 2 +-
arch/powerpc/platforms/pasemi/iommu.c | 2 +-
arch/powerpc/platforms/powernv/pci-ioda-tce.c | 38 ++++++----
arch/powerpc/platforms/powernv/pci-ioda.c | 42 +++++++++--
arch/powerpc/platforms/pseries/iommu.c | 8 +-
arch/powerpc/platforms/pseries/vio.c | 2 +-
arch/powerpc/sysdev/dart_iommu.c | 2 +-
11 files changed, 129 insertions(+), 61 deletions(-)
--
2.17.1
^ permalink raw reply
* [PATCH kernel v5 2/4] powerpc/iommu: Allow bypass-only for DMA
From: Alexey Kardashevskiy @ 2019-07-18 5:11 UTC (permalink / raw)
To: linuxppc-dev
Cc: Sam Bobroff, Alistair Popple, Oliver O'Halloran,
Alexey Kardashevskiy, David Gibson
In-Reply-To: <20190718051139.74787-1-aik@ozlabs.ru>
POWER8 and newer support a bypass mode which maps all host memory to
PCI buses so an IOMMU table is not always required. However if we fail to
create such a table, the DMA setup fails and the kernel does not boot.
This skips the 32bit DMA setup check if the bypass is selected.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
---
This minor thing helped me debugging next 2 patches so it can help
somebody else too.
---
arch/powerpc/kernel/dma-iommu.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index a0879674a9c8..c963d704fa31 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -122,18 +122,17 @@ int dma_iommu_dma_supported(struct device *dev, u64 mask)
{
struct iommu_table *tbl = get_iommu_table_base(dev);
- if (!tbl) {
- dev_info(dev, "Warning: IOMMU dma not supported: mask 0x%08llx"
- ", table unavailable\n", mask);
- return 0;
- }
-
if (dev_is_pci(dev) && dma_iommu_bypass_supported(dev, mask)) {
dev->archdata.iommu_bypass = true;
dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n");
return 1;
}
+ if (!tbl) {
+ dev_err(dev, "Warning: IOMMU dma not supported: mask 0x%08llx, table unavailable\n", mask);
+ return 0;
+ }
+
if (tbl->it_offset > (mask >> tbl->it_page_shift)) {
dev_info(dev, "Warning: IOMMU offset too big for device mask\n");
dev_info(dev, "mask: 0x%08llx, table offset: 0x%08lx\n",
--
2.17.1
^ permalink raw reply related
* [PATCH kernel v5 3/4] powerpc/powernv/ioda2: Allocate TCE table levels on demand for default DMA window
From: Alexey Kardashevskiy @ 2019-07-18 5:11 UTC (permalink / raw)
To: linuxppc-dev
Cc: Sam Bobroff, Alistair Popple, Oliver O'Halloran,
Alexey Kardashevskiy, David Gibson
In-Reply-To: <20190718051139.74787-1-aik@ozlabs.ru>
We allocate only the first level of multilevel TCE tables for KVM
already (alloc_userspace_copy==true), and the rest is allocated on demand.
This is not enabled though for bare metal.
This removes the KVM limitation (implicit, via the alloc_userspace_copy
parameter) and always allocates just the first level. The on-demand
allocation of missing levels is already implemented.
As from now on DMA map might happen with disabled interrupts, this
allocates TCEs with GFP_ATOMIC; otherwise lockdep reports errors 1].
In practice just a single page is allocated there so chances for failure
are quite low.
To save time when creating a new clean table, this skips non-allocated
indirect TCE entries in pnv_tce_free just like we already do in
the VFIO IOMMU TCE driver.
This changes the default level number from 1 to 2 to reduce the amount
of memory required for the default 32bit DMA window at the boot time.
The default window size is up to 2GB which requires 4MB of TCEs which is
unlikely to be used entirely or at all as most devices these days are
64bit capable so by switching to 2 levels by default we save 4032KB of
RAM per a device.
While at this, add __GFP_NOWARN to alloc_pages_node() as the userspace
can trigger this path via VFIO, see the failure and try creating a table
again with different parameters which might succeed.
[1]:
===
BUG: sleeping function called from invalid context at mm/page_alloc.c:4596
in_atomic(): 1, irqs_disabled(): 1, pid: 1038, name: scsi_eh_1
2 locks held by scsi_eh_1/1038:
#0: 000000005efd659a (&host->eh_mutex){+.+.}, at: ata_eh_acquire+0x34/0x80
#1: 0000000006cf56a6 (&(&host->lock)->rlock){....}, at: ata_exec_internal_sg+0xb0/0x5c0
irq event stamp: 500
hardirqs last enabled at (499): [<c000000000cb8a74>] _raw_spin_unlock_irqrestore+0x94/0xd0
hardirqs last disabled at (500): [<c000000000cb85c4>] _raw_spin_lock_irqsave+0x44/0x120
softirqs last enabled at (0): [<c000000000101120>] copy_process.isra.4.part.5+0x640/0x1a80
softirqs last disabled at (0): [<0000000000000000>] 0x0
CPU: 73 PID: 1038 Comm: scsi_eh_1 Not tainted 5.2.0-rc6-le_nv2_aikATfstn1-p1 #634
Call Trace:
[c000003d064cef50] [c000000000c8e6c4] dump_stack+0xe8/0x164 (unreliable)
[c000003d064cefa0] [c00000000014ed78] ___might_sleep+0x2f8/0x310
[c000003d064cf020] [c0000000003ca084] __alloc_pages_nodemask+0x2a4/0x1560
[c000003d064cf220] [c0000000000c2530] pnv_alloc_tce_level.isra.0+0x90/0x130
[c000003d064cf290] [c0000000000c2888] pnv_tce+0x128/0x3b0
[c000003d064cf360] [c0000000000c2c00] pnv_tce_build+0xb0/0xf0
[c000003d064cf3c0] [c0000000000bbd9c] pnv_ioda2_tce_build+0x3c/0xb0
[c000003d064cf400] [c00000000004cfe0] ppc_iommu_map_sg+0x210/0x550
[c000003d064cf510] [c00000000004b7a4] dma_iommu_map_sg+0x74/0xb0
[c000003d064cf530] [c000000000863944] ata_qc_issue+0x134/0x470
[c000003d064cf5b0] [c000000000863ec4] ata_exec_internal_sg+0x244/0x5c0
[c000003d064cf700] [c0000000008642d0] ata_exec_internal+0x90/0xe0
[c000003d064cf780] [c0000000008650ac] ata_dev_read_id+0x2ec/0x640
[c000003d064cf8d0] [c000000000878e28] ata_eh_recover+0x948/0x16d0
[c000003d064cfa10] [c00000000087d760] sata_pmp_error_handler+0x480/0xbf0
[c000003d064cfbc0] [c000000000884624] ahci_error_handler+0x74/0xe0
[c000003d064cfbf0] [c000000000879fa8] ata_scsi_port_error_handler+0x2d8/0x7c0
[c000003d064cfca0] [c00000000087a544] ata_scsi_error+0xb4/0x100
[c000003d064cfd00] [c000000000802450] scsi_error_handler+0x120/0x510
[c000003d064cfdb0] [c000000000140c48] kthread+0x1b8/0x1c0
[c000003d064cfe20] [c00000000000bd8c] ret_from_kernel_thread+0x5c/0x70
ata1: SATA link up 6.0 Gbps (SStatus 133 SControl 300)
irq event stamp: 2305
========================================================
hardirqs last enabled at (2305): [<c00000000000e4c8>] fast_exc_return_irq+0x28/0x34
hardirqs last disabled at (2303): [<c000000000cb9fd0>] __do_softirq+0x4a0/0x654
WARNING: possible irq lock inversion dependency detected
5.2.0-rc6-le_nv2_aikATfstn1-p1 #634 Tainted: G W
softirqs last enabled at (2304): [<c000000000cba054>] __do_softirq+0x524/0x654
softirqs last disabled at (2297): [<c00000000010f278>] irq_exit+0x128/0x180
--------------------------------------------------------
swapper/0/0 just changed the state of lock:
0000000006cf56a6 (&(&host->lock)->rlock){-...}, at: ahci_single_level_irq_intr+0xac/0x120
but this lock took another, HARDIRQ-unsafe lock in the past:
(fs_reclaim){+.+.}
and interrupts could create inverse lock ordering between them.
other info that might help us debug this:
Possible interrupt unsafe locking scenario:
CPU0 CPU1
---- ----
lock(fs_reclaim);
local_irq_disable();
lock(&(&host->lock)->rlock);
lock(fs_reclaim);
<Interrupt>
lock(&(&host->lock)->rlock);
*** DEADLOCK ***
no locks held by swapper/0/0.
the shortest dependencies between 2nd lock and 1st lock:
-> (fs_reclaim){+.+.} ops: 167579 {
HARDIRQ-ON-W at:
lock_acquire+0xf8/0x2a0
fs_reclaim_acquire.part.23+0x44/0x60
kmem_cache_alloc_node_trace+0x80/0x590
alloc_desc+0x64/0x270
__irq_alloc_descs+0x2e4/0x3a0
irq_domain_alloc_descs+0xb0/0x150
irq_create_mapping+0x168/0x2c0
xics_smp_probe+0x2c/0x98
pnv_smp_probe+0x40/0x9c
smp_prepare_cpus+0x524/0x6c4
kernel_init_freeable+0x1b4/0x650
kernel_init+0x2c/0x148
ret_from_kernel_thread+0x5c/0x70
SOFTIRQ-ON-W at:
lock_acquire+0xf8/0x2a0
fs_reclaim_acquire.part.23+0x44/0x60
kmem_cache_alloc_node_trace+0x80/0x590
alloc_desc+0x64/0x270
__irq_alloc_descs+0x2e4/0x3a0
irq_domain_alloc_descs+0xb0/0x150
irq_create_mapping+0x168/0x2c0
xics_smp_probe+0x2c/0x98
pnv_smp_probe+0x40/0x9c
smp_prepare_cpus+0x524/0x6c4
kernel_init_freeable+0x1b4/0x650
kernel_init+0x2c/0x148
ret_from_kernel_thread+0x5c/0x70
INITIAL USE at:
lock_acquire+0xf8/0x2a0
fs_reclaim_acquire.part.23+0x44/0x60
kmem_cache_alloc_node_trace+0x80/0x590
alloc_desc+0x64/0x270
__irq_alloc_descs+0x2e4/0x3a0
irq_domain_alloc_descs+0xb0/0x150
irq_create_mapping+0x168/0x2c0
xics_smp_probe+0x2c/0x98
pnv_smp_probe+0x40/0x9c
smp_prepare_cpus+0x524/0x6c4
kernel_init_freeable+0x1b4/0x650
kernel_init+0x2c/0x148
ret_from_kernel_thread+0x5c/0x70
}
===
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Alistair Popple <alistair@popple.id.au>
---
Changes:
v4:
* added lockdep output to the commit log to justify ATOMIC in alloc_pages_node
v2:
* added __GFP_NOWARN to alloc_pages_node
---
arch/powerpc/platforms/powernv/pci.h | 2 +-
arch/powerpc/platforms/powernv/pci-ioda-tce.c | 20 +++++++++----------
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 469c24463247..f914f0b14e4e 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -219,7 +219,7 @@ extern struct iommu_table_group *pnv_npu_compound_attach(
struct pnv_ioda_pe *pe);
/* pci-ioda-tce.c */
-#define POWERNV_IOMMU_DEFAULT_LEVELS 1
+#define POWERNV_IOMMU_DEFAULT_LEVELS 2
#define POWERNV_IOMMU_MAX_LEVELS 5
extern int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
diff --git a/arch/powerpc/platforms/powernv/pci-ioda-tce.c b/arch/powerpc/platforms/powernv/pci-ioda-tce.c
index 8d6569590161..a0b9c0c23ed2 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda-tce.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda-tce.c
@@ -36,7 +36,8 @@ static __be64 *pnv_alloc_tce_level(int nid, unsigned int shift)
struct page *tce_mem = NULL;
__be64 *addr;
- tce_mem = alloc_pages_node(nid, GFP_KERNEL, shift - PAGE_SHIFT);
+ tce_mem = alloc_pages_node(nid, GFP_ATOMIC | __GFP_NOWARN,
+ shift - PAGE_SHIFT);
if (!tce_mem) {
pr_err("Failed to allocate a TCE memory, level shift=%d\n",
shift);
@@ -169,6 +170,9 @@ void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
if (ptce)
*ptce = cpu_to_be64(0);
+ else
+ /* Skip the rest of the level */
+ i |= tbl->it_level_size - 1;
}
}
@@ -268,7 +272,6 @@ long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
unsigned int table_shift = max_t(unsigned int, entries_shift + 3,
PAGE_SHIFT);
const unsigned long tce_table_size = 1UL << table_shift;
- unsigned int tmplevels = levels;
if (!levels || (levels > POWERNV_IOMMU_MAX_LEVELS))
return -EINVAL;
@@ -276,9 +279,6 @@ long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
if (!is_power_of_2(window_size))
return -EINVAL;
- if (alloc_userspace_copy && (window_size > (1ULL << 32)))
- tmplevels = 1;
-
/* Adjust direct table size from window_size and levels */
entries_shift = (entries_shift + levels - 1) / levels;
level_shift = entries_shift + 3;
@@ -289,7 +289,7 @@ long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
/* Allocate TCE table */
addr = pnv_pci_ioda2_table_do_alloc_pages(nid, level_shift,
- tmplevels, tce_table_size, &offset, &total_allocated);
+ 1, tce_table_size, &offset, &total_allocated);
/* addr==NULL means that the first level allocation failed */
if (!addr)
@@ -300,18 +300,18 @@ long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
* we did not allocate as much as we wanted,
* release partially allocated table.
*/
- if (tmplevels == levels && offset < tce_table_size)
+ if (levels == 1 && offset < tce_table_size)
goto free_tces_exit;
/* Allocate userspace view of the TCE table */
if (alloc_userspace_copy) {
offset = 0;
uas = pnv_pci_ioda2_table_do_alloc_pages(nid, level_shift,
- tmplevels, tce_table_size, &offset,
+ 1, tce_table_size, &offset,
&total_allocated_uas);
if (!uas)
goto free_tces_exit;
- if (tmplevels == levels && (offset < tce_table_size ||
+ if (levels == 1 && (offset < tce_table_size ||
total_allocated_uas != total_allocated))
goto free_uas_exit;
}
@@ -326,7 +326,7 @@ long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
pr_debug("Created TCE table: ws=%08llx ts=%lx @%08llx base=%lx uas=%p levels=%d/%d\n",
window_size, tce_table_size, bus_offset, tbl->it_base,
- tbl->it_userspace, tmplevels, levels);
+ tbl->it_userspace, 1, levels);
return 0;
--
2.17.1
^ permalink raw reply related
* [PATCH kernel v5 4/4] powerpc/powernv/ioda2: Create bigger default window with 64k IOMMU pages
From: Alexey Kardashevskiy @ 2019-07-18 5:11 UTC (permalink / raw)
To: linuxppc-dev
Cc: Sam Bobroff, Alistair Popple, Oliver O'Halloran,
Alexey Kardashevskiy, David Gibson
In-Reply-To: <20190718051139.74787-1-aik@ozlabs.ru>
At the moment we create a small window only for 32bit devices, the window
maps 0..2GB of the PCI space only. For other devices we either use
a sketchy bypass or hardware bypass but the former can only work if
the amount of RAM is no bigger than the device's DMA mask and the latter
requires devices to support at least 59bit DMA.
This extends the default DMA window to the maximum size possible to allow
a wider DMA mask than just 32bit. The default window size is now limited
by the the iommu_table::it_map allocation bitmap which is a contiguous
array, 1 bit per an IOMMU page.
This increases the default IOMMU page size from hard coded 4K to
the system page size to allow wider DMA masks.
This increases the level number to not exceed the max order allocation
limit per TCE level. By the same time, this keeps minimal levels number
as 2 in order to save memory.
As the extended window now overlaps the 32bit MMIO region, this adds
an area reservation to iommu_init_table().
After this change the default window size is 0x80000000000==1<<43 so
devices limited to DMA mask smaller than the amount of system RAM can
still use more than just 2GB of memory for DMA.
This is an optimization and not a bug fix for DMA API usage.
With the on-demand allocation of indirect TCE table levels enabled and
2 levels, the first TCE level size is just
1<<ceil((log2(0x7ffffffffff+1)-16)/2)=16384 TCEs or 2 system pages.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
Changes:
v5:
* ditched iommu_init_table_res and pass start..end to iommu_init_table
directly
* fixed WARN_ON in iommu_table_reserve_pages (was opposite)
v4:
* fixed take/release ownership handlers
* fixed reserved region for tables with it_offset!=0 (this is not going
to be exploited here but still this is a correct behavior)
v3:
* fixed tce levels calculation
v2:
* adjusted level number to the max order
---
arch/powerpc/include/asm/iommu.h | 7 ++-
arch/powerpc/kernel/iommu.c | 74 ++++++++++++++++-------
arch/powerpc/platforms/cell/iommu.c | 2 +-
arch/powerpc/platforms/pasemi/iommu.c | 2 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 42 ++++++++++---
arch/powerpc/platforms/pseries/iommu.c | 8 +--
arch/powerpc/platforms/pseries/vio.c | 2 +-
arch/powerpc/sysdev/dart_iommu.c | 2 +-
8 files changed, 100 insertions(+), 39 deletions(-)
diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
index 18d342b815e4..d7bf1f104c15 100644
--- a/arch/powerpc/include/asm/iommu.h
+++ b/arch/powerpc/include/asm/iommu.h
@@ -111,6 +111,8 @@ struct iommu_table {
struct iommu_table_ops *it_ops;
struct kref it_kref;
int it_nid;
+ unsigned long it_reserved_start; /* Start of not-DMA-able (MMIO) area */
+ unsigned long it_reserved_end;
};
#define IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry) \
@@ -149,8 +151,9 @@ extern int iommu_tce_table_put(struct iommu_table *tbl);
/* Initializes an iommu_table based in values set in the passed-in
* structure
*/
-extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
- int nid);
+extern struct iommu_table *iommu_init_table(struct iommu_table *tbl,
+ int nid, unsigned long res_start, unsigned long res_end);
+
#define IOMMU_TABLE_GROUP_MAX_TABLES 2
struct iommu_table_group;
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 0a67ce9f827e..e7a2b160d4c6 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -633,11 +633,54 @@ static void iommu_table_clear(struct iommu_table *tbl)
#endif
}
+static void iommu_table_reserve_pages(struct iommu_table *tbl,
+ unsigned long res_start, unsigned long res_end)
+{
+ int i;
+
+ WARN_ON_ONCE(res_end < res_start);
+ /*
+ * Reserve page 0 so it will not be used for any mappings.
+ * This avoids buggy drivers that consider page 0 to be invalid
+ * to crash the machine or even lose data.
+ */
+ if (tbl->it_offset == 0)
+ set_bit(0, tbl->it_map);
+
+ tbl->it_reserved_start = res_start;
+ tbl->it_reserved_end = res_end;
+
+ /* Check if res_start..res_end isn't empty and overlaps the table */
+ if (res_start && res_end &&
+ (tbl->it_offset + tbl->it_size < res_start ||
+ res_end < tbl->it_offset))
+ return;
+
+ for (i = tbl->it_reserved_start; i < tbl->it_reserved_end; ++i)
+ set_bit(i - tbl->it_offset, tbl->it_map);
+}
+
+static void iommu_table_release_pages(struct iommu_table *tbl)
+{
+ int i;
+
+ /*
+ * In case we have reserved the first bit, we should not emit
+ * the warning below.
+ */
+ if (tbl->it_offset == 0)
+ clear_bit(0, tbl->it_map);
+
+ for (i = tbl->it_reserved_start; i < tbl->it_reserved_end; ++i)
+ clear_bit(i - tbl->it_offset, tbl->it_map);
+}
+
/*
* Build a iommu_table structure. This contains a bit map which
* is used to manage allocation of the tce space.
*/
-struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
+struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid,
+ unsigned long res_start, unsigned long res_end)
{
unsigned long sz;
static int welcomed = 0;
@@ -656,13 +699,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
tbl->it_map = page_address(page);
memset(tbl->it_map, 0, sz);
- /*
- * Reserve page 0 so it will not be used for any mappings.
- * This avoids buggy drivers that consider page 0 to be invalid
- * to crash the machine or even lose data.
- */
- if (tbl->it_offset == 0)
- set_bit(0, tbl->it_map);
+ iommu_table_reserve_pages(tbl, res_start, res_end);
/* We only split the IOMMU table if we have 1GB or more of space */
if ((tbl->it_size << tbl->it_page_shift) >= (1UL * 1024 * 1024 * 1024))
@@ -714,12 +751,7 @@ static void iommu_table_free(struct kref *kref)
return;
}
- /*
- * In case we have reserved the first bit, we should not emit
- * the warning below.
- */
- if (tbl->it_offset == 0)
- clear_bit(0, tbl->it_map);
+ iommu_table_release_pages(tbl);
/* verify that table contains no entries */
if (!bitmap_empty(tbl->it_map, tbl->it_size))
@@ -1024,15 +1056,14 @@ int iommu_take_ownership(struct iommu_table *tbl)
for (i = 0; i < tbl->nr_pools; i++)
spin_lock(&tbl->pools[i].lock);
- if (tbl->it_offset == 0)
- clear_bit(0, tbl->it_map);
+ iommu_table_release_pages(tbl);
if (!bitmap_empty(tbl->it_map, tbl->it_size)) {
pr_err("iommu_tce: it_map is not empty");
ret = -EBUSY;
- /* Restore bit#0 set by iommu_init_table() */
- if (tbl->it_offset == 0)
- set_bit(0, tbl->it_map);
+ /* Undo iommu_table_release_pages, i.e. restore bit#0, etc */
+ iommu_table_reserve_pages(tbl, tbl->it_reserved_start,
+ tbl->it_reserved_end);
} else {
memset(tbl->it_map, 0xff, sz);
}
@@ -1055,9 +1086,8 @@ void iommu_release_ownership(struct iommu_table *tbl)
memset(tbl->it_map, 0, sz);
- /* Restore bit#0 set by iommu_init_table() */
- if (tbl->it_offset == 0)
- set_bit(0, tbl->it_map);
+ iommu_table_reserve_pages(tbl, tbl->it_reserved_start,
+ tbl->it_reserved_end);
for (i = 0; i < tbl->nr_pools; i++)
spin_unlock(&tbl->pools[i].lock);
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 16dfee29aa41..ca9ffc1c8685 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -486,7 +486,7 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
window->table.it_size = size >> window->table.it_page_shift;
window->table.it_ops = &cell_iommu_ops;
- iommu_init_table(&window->table, iommu->nid);
+ iommu_init_table(&window->table, iommu->nid, 0, 0);
pr_debug("\tioid %d\n", window->ioid);
pr_debug("\tblocksize %ld\n", window->table.it_blocksize);
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
index 77fee09104f8..b500a6e47e6b 100644
--- a/arch/powerpc/platforms/pasemi/iommu.c
+++ b/arch/powerpc/platforms/pasemi/iommu.c
@@ -146,7 +146,7 @@ static void iommu_table_iobmap_setup(void)
*/
iommu_table_iobmap.it_blocksize = 4;
iommu_table_iobmap.it_ops = &iommu_table_iobmap_ops;
- iommu_init_table(&iommu_table_iobmap, 0);
+ iommu_init_table(&iommu_table_iobmap, 0, 0, 0);
pr_debug(" <- %s\n", __func__);
}
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index d8080558d020..ec48ea25a674 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -2303,7 +2303,7 @@ static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb,
tbl->it_ops = &pnv_ioda1_iommu_ops;
pe->table_group.tce32_start = tbl->it_offset << tbl->it_page_shift;
pe->table_group.tce32_size = tbl->it_size << tbl->it_page_shift;
- iommu_init_table(tbl, phb->hose->node);
+ iommu_init_table(tbl, phb->hose->node, 0, 0);
if (pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL))
pnv_ioda_setup_bus_dma(pe, pe->pbus);
@@ -2420,6 +2420,7 @@ static long pnv_pci_ioda2_setup_default_config(struct pnv_ioda_pe *pe)
{
struct iommu_table *tbl = NULL;
long rc;
+ unsigned long res_start, res_end;
/*
* crashkernel= specifies the kdump kernel's maximum memory at
@@ -2433,19 +2434,46 @@ static long pnv_pci_ioda2_setup_default_config(struct pnv_ioda_pe *pe)
* DMA window can be larger than available memory, which will
* cause errors later.
*/
- const u64 window_size = min((u64)pe->table_group.tce32_size, max_memory);
+ const u64 maxblock = 1UL << (PAGE_SHIFT + MAX_ORDER - 1);
- rc = pnv_pci_ioda2_create_table(&pe->table_group, 0,
- IOMMU_PAGE_SHIFT_4K,
- window_size,
- POWERNV_IOMMU_DEFAULT_LEVELS, false, &tbl);
+ /*
+ * We create the default window as big as we can. The constraint is
+ * the max order of allocation possible. The TCE table is likely to
+ * end up being multilevel and with on-demand allocation in place,
+ * the initial use is not going to be huge as the default window aims
+ * to support crippled devices (i.e. not fully 64bit DMAble) only.
+ */
+ /* iommu_table::it_map uses 1 bit per IOMMU page, hence 8 */
+ const u64 window_size = min((maxblock * 8) << PAGE_SHIFT, max_memory);
+ /* Each TCE level cannot exceed maxblock so go multilevel if needed */
+ unsigned long tces_order = ilog2(window_size >> PAGE_SHIFT);
+ unsigned long tcelevel_order = ilog2(maxblock >> 3);
+ unsigned int levels = tces_order / tcelevel_order;
+
+ if (tces_order % tcelevel_order)
+ levels += 1;
+ /*
+ * We try to stick to default levels (which is >1 at the moment) in
+ * order to save memory by relying on on-demain TCE level allocation.
+ */
+ levels = max_t(unsigned int, levels, POWERNV_IOMMU_DEFAULT_LEVELS);
+
+ rc = pnv_pci_ioda2_create_table(&pe->table_group, 0, PAGE_SHIFT,
+ window_size, levels, false, &tbl);
if (rc) {
pe_err(pe, "Failed to create 32-bit TCE table, err %ld",
rc);
return rc;
}
- iommu_init_table(tbl, pe->phb->hose->node);
+ /* We use top part of 32bit space for MMIO so exclude it from DMA */
+ res_start = 0;
+ res_end = 0;
+ if (window_size > pe->phb->ioda.m32_pci_base) {
+ res_start = pe->phb->ioda.m32_pci_base >> tbl->it_page_shift;
+ res_end = min(window_size, SZ_4G) >> tbl->it_page_shift;
+ }
+ iommu_init_table(tbl, pe->phb->hose->node, res_start, res_end);
rc = pnv_pci_ioda2_set_window(&pe->table_group, 0, tbl);
if (rc) {
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 889dc2e44b89..42fb03253334 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -609,7 +609,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
iommu_table_setparms(pci->phb, dn, tbl);
tbl->it_ops = &iommu_table_pseries_ops;
- iommu_init_table(tbl, pci->phb->node);
+ iommu_init_table(tbl, pci->phb->node, 0, 0);
/* Divide the rest (1.75GB) among the children */
pci->phb->dma_window_size = 0x80000000ul;
@@ -690,7 +690,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
iommu_table_setparms_lpar(ppci->phb, pdn, tbl,
ppci->table_group, dma_window);
tbl->it_ops = &iommu_table_lpar_multi_ops;
- iommu_init_table(tbl, ppci->phb->node);
+ iommu_init_table(tbl, ppci->phb->node, 0, 0);
iommu_register_group(ppci->table_group,
pci_domain_nr(bus), 0);
pr_debug(" created table: %p\n", ppci->table_group);
@@ -719,7 +719,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
tbl = PCI_DN(dn)->table_group->tables[0];
iommu_table_setparms(phb, dn, tbl);
tbl->it_ops = &iommu_table_pseries_ops;
- iommu_init_table(tbl, phb->node);
+ iommu_init_table(tbl, phb->node, 0, 0);
set_iommu_table_base(&dev->dev, tbl);
return;
}
@@ -1169,7 +1169,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
iommu_table_setparms_lpar(pci->phb, pdn, tbl,
pci->table_group, dma_window);
tbl->it_ops = &iommu_table_lpar_multi_ops;
- iommu_init_table(tbl, pci->phb->node);
+ iommu_init_table(tbl, pci->phb->node, 0, 0);
iommu_register_group(pci->table_group,
pci_domain_nr(pci->phb->bus), 0);
pr_debug(" created table: %p\n", pci->table_group);
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
index 6601b9d404dc..115934f83935 100644
--- a/arch/powerpc/platforms/pseries/vio.c
+++ b/arch/powerpc/platforms/pseries/vio.c
@@ -1191,7 +1191,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
else
tbl->it_ops = &iommu_table_pseries_ops;
- return iommu_init_table(tbl, -1);
+ return iommu_init_table(tbl, -1, 0, 0);
}
/**
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 21a1fae0714e..6b4a34b36d98 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -344,7 +344,7 @@ static void iommu_table_dart_setup(void)
iommu_table_dart.it_index = 0;
iommu_table_dart.it_blocksize = 1;
iommu_table_dart.it_ops = &iommu_dart_ops;
- iommu_init_table(&iommu_table_dart, -1);
+ iommu_init_table(&iommu_table_dart, -1, 0, 0);
/* Reserve the last page of the DART to avoid possible prefetch
* past the DART mapped area
--
2.17.1
^ permalink raw reply related
* Re: [EXTERNAL] Re: [PATCH v2 3/6] powerpc/eeh: Improve debug messages around device addition
From: Sam Bobroff @ 2019-07-18 5:24 UTC (permalink / raw)
To: Oliver O'Halloran; +Cc: Alexey Kardashevskiy, linuxppc-dev, Tyrel Datwyler
In-Reply-To: <8cadf8fd4540c2e3ca2426fc195226aa93bdbe65.camel@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 6095 bytes --]
On Tue, Jul 16, 2019 at 05:00:44PM +1000, Oliver O'Halloran wrote:
> On Tue, 2019-07-16 at 16:48 +1000, Sam Bobroff wrote:
> > On Thu, Jun 20, 2019 at 01:45:24PM +1000, Oliver O'Halloran wrote:
> > > On Thu, Jun 20, 2019 at 12:40 PM Alexey Kardashevskiy <aik@ozlabs.ru> wrote:
> > > > On 19/06/2019 14:27, Sam Bobroff wrote:
> > > > > On Tue, Jun 11, 2019 at 03:47:58PM +1000, Alexey Kardashevskiy wrote:
> > > > > > On 07/05/2019 14:30, Sam Bobroff wrote:
> > > > > > > Also remove useless comment.
> > > > > > >
> > > > > > > Signed-off-by: Sam Bobroff <sbobroff@linux.ibm.com>
> > > > > > > Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> > > > > > > ---
> > > > *snip*
> > > > > I can see that edev will be non-NULL here, but that pr_debug() pattern
> > > > > (using the PDN information to form the PCI address) is quite common
> > > > > across the EEH code, so I think rather than changing a couple of
> > > > > specific cases, I should do a separate cleanup patch and introduce
> > > > > something like pdn_debug(pdn, "...."). What do you think?
> > > >
> > > > I'd switch them all to already existing dev_dbg/pci_debug rather than
> > > > adding pdn_debug as imho it should not have been used in the first place
> > > > really...
> > > >
> > > > > (I don't know exactly when edev->pdev can be NULL.)
> > > >
> > > > ... and if you switch to dev_dbg/pci_debug, I think quite soon you'll
> > > > know if it can or cannot be NULL :)
> > >
> > > As far as I can tell edev->pdev is NULL in two cases:
> > >
> > > 1. Before eeh_device_add_late() has been called on the pdev. The late
> > > part of the add maps the pdev to an edev and sets the pdev's edev
> > > pointer and vis a vis.
> > > 2. While recoverying EEH unaware devices. Unaware devices are
> > > destroyed and rescanned and the edev->pdev pointer is cleared by
> > > pcibios_device_release()
> > >
> > > In most of these cases it should be safe to use the pci_*() functions
> > > rather than making a new one up for printing pdns. In the cases where
> > > we might not have a PCI dev i'd make a new set of prints that take an
> > > EEH dev rather than a pci_dn since i'd like pci_dn to die sooner
> > > rather than later.
> > >
> > > Oliver
> >
> > I'll change the calls in {pnv,pseries}_pcibios_bus_add_device() and
> > eeh_add_device_late() to use dev_dbg() and post a new version.
> >
> > For {pnv,pseries}_eeh_probe() I'm not sure what we can do; there's no
> > pci_dev available yet and while it would be nice to use the eeh_dev
> > rather than the pdn, it doesn't seem to have the bus/device/fn
> > information we need. Am I missing something there? (The code in the
> > probe functions seems to get it from the pci_dn.)
>
> We do have a pci_dev in the powernv case since pnv_eeh_probe() isn't
> called until the late probe happens (which is after the pci_dev has
> been created). I've got some patches to rework the probe path to make
> this a bit clearer, but they need a bit more work.
>
> >
> > If there isn't an easy way around this, would it therefore be reasonable
> > to just leave them open-coded as they are?
>
> I've had this patch floating around a while that should do the trick.
> The PCI_BUSNO macro is probably unnecessary since I'm sure there is
> something that does it in generic code, but I couldn't find it.
Looks good, I'll try including it and create a dev_dbg style function
or macro that takes an edev.
I don't think I can use it in the pcibios bus add device handlers (where
there is no edev, or where it may be attached to the wrong device) but
I'll use it for all the other cases.
If it works out well I can follow up and update more of the EEH logging
to use it :-)
> From 61ff8c23c4d13ff640fb2d069dcedacdf2ee22dd Mon Sep 17 00:00:00 2001
> From: Oliver O'Halloran <oohall@gmail.com>
> Date: Thu, 18 Apr 2019 18:25:13 +1000
> Subject: [PATCH] powerpc/eeh: Add bdfn field to eeh_dev
>
> Preperation for removing pci_dn from the powernv EEH code. The only thing we
> really use pci_dn for is to get the bdfn of the device for config space
> accesses, so adding that information to eeh_dev reduces the need to carry
> around the pci_dn.
>
> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
> ---
> arch/powerpc/include/asm/eeh.h | 2 ++
> arch/powerpc/include/asm/ppc-pci.h | 2 ++
> arch/powerpc/kernel/eeh_dev.c | 2 ++
> 3 files changed, 6 insertions(+)
>
> diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
> index 7fd476d..a208e02 100644
> --- a/arch/powerpc/include/asm/eeh.h
> +++ b/arch/powerpc/include/asm/eeh.h
> @@ -131,6 +131,8 @@ static inline bool eeh_pe_passed(struct eeh_pe *pe)
> struct eeh_dev {
> int mode; /* EEH mode */
> int class_code; /* Class code of the device */
> + int bdfn; /* bdfn of device (for cfg ops) */
> + struct pci_controller *controller;
> int pe_config_addr; /* PE config address */
> u32 config_space[16]; /* Saved PCI config space */
> int pcix_cap; /* Saved PCIx capability */
> diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h
> index cec2d64..72860de 100644
> --- a/arch/powerpc/include/asm/ppc-pci.h
> +++ b/arch/powerpc/include/asm/ppc-pci.h
> @@ -74,6 +74,8 @@ static inline const char *eeh_driver_name(struct pci_dev *pdev)
>
> #endif /* CONFIG_EEH */
>
> +#define PCI_BUSNO(bdfn) ((bdfn >> 8) & 0xff)
> +
> #else /* CONFIG_PCI */
> static inline void init_pci_config_tokens(void) { }
> #endif /* !CONFIG_PCI */
> diff --git a/arch/powerpc/kernel/eeh_dev.c b/arch/powerpc/kernel/eeh_dev.c
> index c4317c4..7370185 100644
> --- a/arch/powerpc/kernel/eeh_dev.c
> +++ b/arch/powerpc/kernel/eeh_dev.c
> @@ -47,6 +47,8 @@ struct eeh_dev *eeh_dev_init(struct pci_dn *pdn)
> /* Associate EEH device with OF node */
> pdn->edev = edev;
> edev->pdn = pdn;
> + edev->bdfn = (pdn->busno << 8) | pdn->devfn;
> + edev->controller = pdn->phb;
>
> return edev;
> }
> --
> 2.9.5
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH v2] powerpc/nvdimm: Pick the nearby online node if the device node is not online
From: Aneesh Kumar K.V @ 2019-07-18 7:49 UTC (permalink / raw)
To: Oliver O'Halloran, Dan Williams, mpe
Cc: linuxppc-dev, Paul Mackerras, Nicholas Piggin
In-Reply-To: <CAOSf1CGvu9GNCNTD8zvvu3XHe9qzjTd7K+wxC98c6cUo5xFa6Q@mail.gmail.com>
"Oliver O'Halloran" <oohall@gmail.com> writes:
> On Tue, Jul 16, 2019 at 7:08 PM Aneesh Kumar K.V
> <aneesh.kumar@linux.ibm.com> wrote:
>>
>> This is similar to what ACPI does. Nvdimm layer doesn't bring the SCM device
>> numa node online. Hence we need to make sure we always use an online node
>> as ndr_desc.numa_node. Otherwise this result in kernel crashes. The target
>> node is used by dax/kmem and that will bring up the numa node online correctly.
>>
>> Without this patch, we do hit kernel crash as below because we try to access
>> uninitialized NODE_DATA in different code paths.
>
> Right, so we're getting a crash due to libnvdimm (via devm_kmalloc)
> trying to to node local allocations to an offline node. Using a
> different node fixes that problem, but what else does changing
> ndr_desc.numa_node do?
>
>> cpu 0x0: Vector: 300 (Data Access) at [c0000000fac53170]
>> pc: c0000000004bbc50: ___slab_alloc+0x120/0xca0
>> lr: c0000000004bc834: __slab_alloc+0x64/0xc0
>> sp: c0000000fac53400
>> msr: 8000000002009033
>> dar: 73e8
>> dsisr: 80000
>> current = 0xc0000000fabb6d80
>> paca = 0xc000000003870000 irqmask: 0x03 irq_happened: 0x01
>> pid = 7, comm = kworker/u16:0
>> Linux version 5.2.0-06234-g76bd729b2644 (kvaneesh@ltc-boston123) (gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #135 SMP Thu Jul 11 05:36:30 CDT 2019
>> enter ? for help
>> [link register ] c0000000004bc834 __slab_alloc+0x64/0xc0
>> [c0000000fac53400] c0000000fac53480 (unreliable)
>> [c0000000fac53500] c0000000004bc818 __slab_alloc+0x48/0xc0
>> [c0000000fac53560] c0000000004c30a0 __kmalloc_node_track_caller+0x3c0/0x6b0
>> [c0000000fac535d0] c000000000cfafe4 devm_kmalloc+0x74/0xc0
>> [c0000000fac53600] c000000000d69434 nd_region_activate+0x144/0x560
>> [c0000000fac536d0] c000000000d6b19c nd_region_probe+0x17c/0x370
>> [c0000000fac537b0] c000000000d6349c nvdimm_bus_probe+0x10c/0x230
>> [c0000000fac53840] c000000000cf3cc4 really_probe+0x254/0x4e0
>> [c0000000fac538d0] c000000000cf429c driver_probe_device+0x16c/0x1e0
>> [c0000000fac53950] c000000000cf0b44 bus_for_each_drv+0x94/0x130
>> [c0000000fac539b0] c000000000cf392c __device_attach+0xdc/0x200
>> [c0000000fac53a50] c000000000cf231c bus_probe_device+0x4c/0xf0
>> [c0000000fac53a90] c000000000ced268 device_add+0x528/0x810
>> [c0000000fac53b60] c000000000d62a58 nd_async_device_register+0x28/0xa0
>> [c0000000fac53bd0] c0000000001ccb8c async_run_entry_fn+0xcc/0x1f0
>> [c0000000fac53c50] c0000000001bcd9c process_one_work+0x46c/0x860
>> [c0000000fac53d20] c0000000001bd4f4 worker_thread+0x364/0x5f0
>> [c0000000fac53db0] c0000000001c7260 kthread+0x1b0/0x1c0
>> [c0000000fac53e20] c00000000000b954 ret_from_kernel_thread+0x5c/0x68
>>
>> With the patch we get
>>
>> # numactl -H
>> available: 2 nodes (0-1)
>> node 0 cpus:
>> node 0 size: 0 MB
>> node 0 free: 0 MB
>> node 1 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
>> node 1 size: 130865 MB
>> node 1 free: 129130 MB
>> node distances:
>> node 0 1
>> 0: 10 20
>> 1: 20 10
>> # cat /sys/bus/nd/devices/region0/numa_node
>> 0
>> # dmesg | grep papr_scm
>> [ 91.332305] papr_scm ibm,persistent-memory:ibm,pmemory@44104001: Region registered with target node 2 and online node 0
>>
>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
>> ---
>> changes from V1:
>> * handle NUMA_NO_NODE
>>
>> arch/powerpc/platforms/pseries/papr_scm.c | 30 +++++++++++++++++++++--
>> 1 file changed, 28 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
>> index c8ec670ee924..b813bc92f35f 100644
>> --- a/arch/powerpc/platforms/pseries/papr_scm.c
>> +++ b/arch/powerpc/platforms/pseries/papr_scm.c
>> @@ -255,12 +255,32 @@ static const struct attribute_group *papr_scm_dimm_groups[] = {
>> NULL,
>> };
>>
>> +static inline int papr_scm_node(int node)
>> +{
>> + int min_dist = INT_MAX, dist;
>> + int nid, min_node;
>> +
>> + if ((node == NUMA_NO_NODE) || node_online(node))
>> + return node;
>> +
>> + min_node = first_online_node;
>> + for_each_online_node(nid) {
>> + dist = node_distance(node, nid);
>> + if (dist < min_dist) {
>> + min_dist = dist;
>> + min_node = nid;
>> + }
>> + }
>> + return min_node;
>> +}
>> +
>> static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
>> {
>> struct device *dev = &p->pdev->dev;
>> struct nd_mapping_desc mapping;
>> struct nd_region_desc ndr_desc;
>> unsigned long dimm_flags;
>> + int target_nid, online_nid;
>>
>> p->bus_desc.ndctl = papr_scm_ndctl;
>> p->bus_desc.module = THIS_MODULE;
>> @@ -299,8 +319,11 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
>>
>> memset(&ndr_desc, 0, sizeof(ndr_desc));
>> ndr_desc.attr_groups = region_attr_groups;
>> - ndr_desc.numa_node = dev_to_node(&p->pdev->dev);
>> - ndr_desc.target_node = ndr_desc.numa_node;
>> + target_nid = dev_to_node(&p->pdev->dev);
>> + online_nid = papr_scm_node(target_nid);
>> + set_dev_node(&p->pdev->dev, online_nid);
>> + ndr_desc.numa_node = online_nid;
>> + ndr_desc.target_node = target_nid;
>
> Annoying question: Say I have two SCM regions with slightly different
> numa affinities and I online one, then the other. If the first is
> setup to be used as kmem could we have the target_node of the first
> being used as the online_node of the second? If so, what happens if I
> unbind kmem from the first region?
kmem, for now, doesn't allow to unregister the mem region. So this won't
happen. But when we start supporting hot unplugging memory added via
kmem, I would expect we continue to keep the SCM region 1 attached to
the node that had kmem before.
>
> I'm mostly wondering if we need to set online_node to the nearest node
> with actual memory on it.
>
>> ndr_desc.res = &p->res;
>> ndr_desc.of_node = p->dn;
>> ndr_desc.provider_data = p;
>> @@ -318,6 +341,9 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
>> ndr_desc.res, p->dn);
>> goto err;
>> }
>> + if (target_nid != online_nid)
>> + dev_info(dev, "Region registered with target node %d and online node %d",
>> + target_nid, online_nid);
>>
>> return 0;
>>
There was a related question that Michael asked w.r.t how do we
define closest NUMA node if we have two NUMA nodes (say `x` and `y`)
with the same distance from the nvdimm region NUMA node. For now, we
pick the first one. But then that also means we lose the information
that nvdimm region access latency is going to be same from both nodes
`x` and `y`.
I guess if application want to find those detail, they will have to use
/sys/devices/system/node/nodeX/accessY/ introduced as part of
08d9dbe72b1f8 ("node: Link memory nodes to their compute nodes")
-aneesh
^ permalink raw reply
* Re: [PATCH v2 03/13] powerpc/prom_init: Add the ESM call to prom_init
From: Alexey Kardashevskiy @ 2019-07-18 8:11 UTC (permalink / raw)
To: Thiago Jung Bauermann, linuxppc-dev
Cc: Anshuman Khandual, Mike Anderson, Ram Pai, linux-kernel,
Claudio Carvalho, Paul Mackerras, Christoph Hellwig
In-Reply-To: <20190713060023.8479-4-bauerman@linux.ibm.com>
On 13/07/2019 16:00, Thiago Jung Bauermann wrote:
> From: Ram Pai <linuxram@us.ibm.com>
>
> Make the Enter-Secure-Mode (ESM) ultravisor call to switch the VM to secure
> mode. Add "svm=" command line option to turn on switching to secure mode.
>
> Signed-off-by: Ram Pai <linuxram@us.ibm.com>
> [ andmike: Generate an RTAS os-term hcall when the ESM ucall fails. ]
> Signed-off-by: Michael Anderson <andmike@linux.ibm.com>
> [ bauerman: Cleaned up the code a bit. ]
> Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
> ---
> .../admin-guide/kernel-parameters.txt | 5 +
> arch/powerpc/include/asm/ultravisor-api.h | 1 +
> arch/powerpc/kernel/prom_init.c | 99 +++++++++++++++++++
> 3 files changed, 105 insertions(+)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 7b15abf7db21..c611891b5992 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -4585,6 +4585,11 @@
> /sys/power/pm_test). Only available when CONFIG_PM_DEBUG
> is set. Default value is 5.
>
> + svm= [PPC]
> + Format: { on | off | y | n | 1 | 0 }
> + This parameter controls use of the Protected
> + Execution Facility on pSeries.
> +
> swapaccount=[0|1]
> [KNL] Enable accounting of swap in memory resource
> controller if no parameter or 1 is given or disable
> diff --git a/arch/powerpc/include/asm/ultravisor-api.h b/arch/powerpc/include/asm/ultravisor-api.h
> index c8180427fa01..fe9a0d8d7673 100644
> --- a/arch/powerpc/include/asm/ultravisor-api.h
> +++ b/arch/powerpc/include/asm/ultravisor-api.h
> @@ -19,6 +19,7 @@
>
> /* opcodes */
> #define UV_WRITE_PATE 0xF104
> +#define UV_ESM 0xF110
> #define UV_RETURN 0xF11C
> #define UV_REGISTER_MEM_SLOT 0xF120
> #define UV_UNREGISTER_MEM_SLOT 0xF124
> diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
> index a3fb90bb5a39..6389a992451b 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -44,6 +44,7 @@
> #include <asm/sections.h>
> #include <asm/machdep.h>
> #include <asm/asm-prototypes.h>
> +#include <asm/ultravisor-api.h>
>
> #include <linux/linux_logo.h>
>
> @@ -175,6 +176,10 @@ static bool __prombss prom_radix_disable;
> static bool __prombss prom_xive_disable;
> #endif
>
> +#ifdef CONFIG_PPC_SVM
> +static bool __prombss prom_svm_enable;
> +#endif
> +
> struct platform_support {
> bool hash_mmu;
> bool radix_mmu;
> @@ -816,6 +821,17 @@ static void __init early_cmdline_parse(void)
> prom_debug("XIVE disabled from cmdline\n");
> }
> #endif /* CONFIG_PPC_PSERIES */
> +
> +#ifdef CONFIG_PPC_SVM
> + opt = prom_strstr(prom_cmd_line, "svm=");
> + if (opt) {
> + bool val;
> +
> + opt += sizeof("svm=") - 1;
> + if (!prom_strtobool(opt, &val))
> + prom_svm_enable = val;
> + }
> +#endif /* CONFIG_PPC_SVM */
> }
>
> #ifdef CONFIG_PPC_PSERIES
> @@ -1716,6 +1732,43 @@ static void __init prom_close_stdin(void)
> }
> }
>
> +#ifdef CONFIG_PPC_SVM
> +static int prom_rtas_hcall(uint64_t args)
> +{
> + register uint64_t arg1 asm("r3") = H_RTAS;
> + register uint64_t arg2 asm("r4") = args;
> +
> + asm volatile("sc 1\n" : "=r" (arg1) :
> + "r" (arg1),
> + "r" (arg2) :);
> + return arg1;
> +}
> +
> +static struct rtas_args __prombss os_term_args;
> +
> +static void __init prom_rtas_os_term(char *str)
> +{
> + phandle rtas_node;
> + __be32 val;
> + u32 token;
> +
> + prom_debug("%s: start...\n", __func__);
> + rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
> + prom_debug("rtas_node: %x\n", rtas_node);
> + if (!PHANDLE_VALID(rtas_node))
> + return;
> +
> + val = 0;
> + prom_getprop(rtas_node, "ibm,os-term", &val, sizeof(val));
> + token = be32_to_cpu(val);
> + prom_debug("ibm,os-term: %x\n", token);
> + if (token == 0)
> + prom_panic("Could not get token for ibm,os-term\n");
> + os_term_args.token = cpu_to_be32(token);
> + prom_rtas_hcall((uint64_t)&os_term_args);
> +}
> +#endif /* CONFIG_PPC_SVM */
> +
> /*
> * Allocate room for and instantiate RTAS
> */
> @@ -3172,6 +3225,49 @@ static void unreloc_toc(void)
> #endif
> #endif
>
> +#ifdef CONFIG_PPC_SVM
> +/*
> + * Perform the Enter Secure Mode ultracall.
> + */
> +static int enter_secure_mode(unsigned long kbase, unsigned long fdt)
> +{
> + register uint64_t func asm("r3") = UV_ESM;
> + register uint64_t arg1 asm("r4") = (uint64_t)kbase;
> + register uint64_t arg2 asm("r5") = (uint64_t)fdt;
What does UV do with kbase and fdt precisely? Few words in the commit
log will do.
> +
> + asm volatile("sc 2\n"
> + : "=r"(func)
> + : "0"(func), "r"(arg1), "r"(arg2)
> + :);
> +
> + return (int)func;
And why "func"? Is it "function"? Weird name. Thanks,
> +}
> +
> +/*
> + * Call the Ultravisor to transfer us to secure memory if we have an ESM blob.
> + */
> +static void setup_secure_guest(unsigned long kbase, unsigned long fdt)
> +{
> + int ret;
> +
> + if (!prom_svm_enable)
> + return;
> +
> + /* Switch to secure mode. */
> + prom_printf("Switching to secure mode.\n");
> +
> + ret = enter_secure_mode(kbase, fdt);
> + if (ret != U_SUCCESS) {
> + prom_printf("Returned %d from switching to secure mode.\n", ret);
> + prom_rtas_os_term("Switch to secure mode failed.\n");
> + }
> +}
> +#else
> +static void setup_secure_guest(unsigned long kbase, unsigned long fdt)
> +{
> +}
> +#endif /* CONFIG_PPC_SVM */
> +
> /*
> * We enter here early on, when the Open Firmware prom is still
> * handling exceptions and the MMU hash table for us.
> @@ -3370,6 +3466,9 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
> unreloc_toc();
> #endif
>
> + /* Move to secure memory if we're supposed to be secure guests. */
> + setup_secure_guest(kbase, hdr);
> +
> __start(hdr, kbase, 0, 0, 0, 0, 0);
>
> return 0;
>
--
Alexey
^ permalink raw reply
* Re: [PATCH v2 04/13] powerpc/pseries/svm: Add helpers for UV_SHARE_PAGE and UV_UNSHARE_PAGE
From: Alexey Kardashevskiy @ 2019-07-18 8:13 UTC (permalink / raw)
To: Thiago Jung Bauermann, linuxppc-dev
Cc: Anshuman Khandual, Mike Anderson, Ram Pai, linux-kernel,
Claudio Carvalho, Paul Mackerras, Christoph Hellwig
In-Reply-To: <20190713060023.8479-5-bauerman@linux.ibm.com>
On 13/07/2019 16:00, Thiago Jung Bauermann wrote:
> From: Ram Pai <linuxram@us.ibm.com>
>
> These functions are used when the guest wants to grant the hypervisor
> access to certain pages.
>
> Signed-off-by: Ram Pai <linuxram@us.ibm.com>
> Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
> ---
> arch/powerpc/include/asm/ultravisor-api.h | 2 ++
> arch/powerpc/include/asm/ultravisor.h | 15 +++++++++++++++
> 2 files changed, 17 insertions(+)
>
> diff --git a/arch/powerpc/include/asm/ultravisor-api.h b/arch/powerpc/include/asm/ultravisor-api.h
> index fe9a0d8d7673..c7513bbadf57 100644
> --- a/arch/powerpc/include/asm/ultravisor-api.h
> +++ b/arch/powerpc/include/asm/ultravisor-api.h
> @@ -25,6 +25,8 @@
> #define UV_UNREGISTER_MEM_SLOT 0xF124
> #define UV_PAGE_IN 0xF128
> #define UV_PAGE_OUT 0xF12C
> +#define UV_SHARE_PAGE 0xF130
> +#define UV_UNSHARE_PAGE 0xF134
> #define UV_PAGE_INVAL 0xF138
> #define UV_SVM_TERMINATE 0xF13C
>
> diff --git a/arch/powerpc/include/asm/ultravisor.h b/arch/powerpc/include/asm/ultravisor.h
> index f5dc5af739b8..f7418b663a0e 100644
> --- a/arch/powerpc/include/asm/ultravisor.h
> +++ b/arch/powerpc/include/asm/ultravisor.h
> @@ -91,6 +91,21 @@ static inline int uv_svm_terminate(u64 lpid)
>
> return ucall(UV_SVM_TERMINATE, retbuf, lpid);
> }
> +
> +static inline int uv_share_page(u64 pfn, u64 npages)
> +{
> + unsigned long retbuf[UCALL_BUFSIZE];
> +
> + return ucall(UV_SHARE_PAGE, retbuf, pfn, npages);
What is in that retbuf? Can you pass NULL instead?
> +}
> +
> +static inline int uv_unshare_page(u64 pfn, u64 npages)
> +{
> + unsigned long retbuf[UCALL_BUFSIZE];
> +
> + return ucall(UV_UNSHARE_PAGE, retbuf, pfn, npages);
> +}
> +
> #endif /* !__ASSEMBLY__ */
>
> #endif /* _ASM_POWERPC_ULTRAVISOR_H */
>
--
Alexey
^ permalink raw reply
* Re: [PATCH v3 2/6] swiotlb: Remove call to sme_active()
From: Christoph Hellwig @ 2019-07-18 8:42 UTC (permalink / raw)
To: Thiago Jung Bauermann
Cc: linux-s390, Mike Anderson, Konrad Rzeszutek Wilk, Robin Murphy,
x86, Ram Pai, linux-kernel, Alexey Dobriyan, Halil Pasic, iommu,
Ingo Molnar, Borislav Petkov, Thomas Lendacky, H. Peter Anvin,
linux-fsdevel, Thomas Gleixner, linuxppc-dev, Christoph Hellwig,
Marek Szyprowski
In-Reply-To: <20190718032858.28744-3-bauerman@linux.ibm.com>
On Thu, Jul 18, 2019 at 12:28:54AM -0300, Thiago Jung Bauermann wrote:
> sme_active() is an x86-specific function so it's better not to call it from
> generic code.
>
> There's no need to mention which memory encryption feature is active, so
> just use a more generic message. Besides, other architectures will have
> different names for similar technology.
>
> Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH v3 3/6] dma-mapping: Remove dma_check_mask()
From: Christoph Hellwig @ 2019-07-18 8:42 UTC (permalink / raw)
To: Thiago Jung Bauermann
Cc: linux-s390, Mike Anderson, Konrad Rzeszutek Wilk, Robin Murphy,
x86, Ram Pai, linux-kernel, Alexey Dobriyan, Halil Pasic, iommu,
Ingo Molnar, Borislav Petkov, Thomas Lendacky, H. Peter Anvin,
linux-fsdevel, Thomas Gleixner, linuxppc-dev, Christoph Hellwig,
Marek Szyprowski
In-Reply-To: <20190718032858.28744-4-bauerman@linux.ibm.com>
On Thu, Jul 18, 2019 at 12:28:55AM -0300, Thiago Jung Bauermann wrote:
> sme_active() is an x86-specific function so it's better not to call it from
> generic code. Christoph Hellwig mentioned that "There is no reason why we
> should have a special debug printk just for one specific reason why there
> is a requirement for a large DMA mask.", so just remove dma_check_mask().
>
> Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH v3 4/6] x86,s390/mm: Move sme_active() and sme_me_mask to x86-specific header
From: Christoph Hellwig @ 2019-07-18 8:42 UTC (permalink / raw)
To: Thiago Jung Bauermann
Cc: linux-s390, Mike Anderson, Konrad Rzeszutek Wilk, Robin Murphy,
x86, Ram Pai, linux-kernel, Alexey Dobriyan, Halil Pasic, iommu,
Ingo Molnar, Borislav Petkov, Thomas Lendacky, H. Peter Anvin,
linux-fsdevel, Thomas Gleixner, linuxppc-dev, Christoph Hellwig,
Marek Szyprowski
In-Reply-To: <20190718032858.28744-5-bauerman@linux.ibm.com>
On Thu, Jul 18, 2019 at 12:28:56AM -0300, Thiago Jung Bauermann wrote:
> Now that generic code doesn't reference them, move sme_active() and
> sme_me_mask to x86's <asm/mem_encrypt.h>.
>
> Also remove the export for sme_active() since it's only used in files that
> won't be built as modules. sme_me_mask on the other hand is used in
> arch/x86/kvm/svm.c (via __sme_set() and __psp_pa()) which can be built as a
> module so its export needs to stay.
>
> Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH v3 5/6] fs/core/vmcore: Move sev_active() reference to x86 arch code
From: Christoph Hellwig @ 2019-07-18 8:44 UTC (permalink / raw)
To: Thiago Jung Bauermann
Cc: linux-s390, Mike Anderson, Konrad Rzeszutek Wilk, Robin Murphy,
x86, Ram Pai, linux-kernel, Alexey Dobriyan, Halil Pasic, iommu,
Ingo Molnar, Borislav Petkov, Thomas Lendacky, H. Peter Anvin,
linux-fsdevel, Thomas Gleixner, linuxppc-dev, Christoph Hellwig,
Marek Szyprowski
In-Reply-To: <20190718032858.28744-6-bauerman@linux.ibm.com>
On Thu, Jul 18, 2019 at 12:28:57AM -0300, Thiago Jung Bauermann wrote:
> Secure Encrypted Virtualization is an x86-specific feature, so it shouldn't
> appear in generic kernel code because it forces non-x86 architectures to
> define the sev_active() function, which doesn't make a lot of sense.
>
> To solve this problem, add an x86 elfcorehdr_read() function to override
> the generic weak implementation. To do that, it's necessary to make
> read_from_oldmem() public so that it can be used outside of vmcore.c.
>
> Also, remove the export for sev_active() since it's only used in files that
> won't be built as modules.
I have to say I find the __weak overrides of the vmcore files very
confusing and which we'd have a better scheme there. But as this fits
into that scheme and allows to remove the AMD SME vs SEV knowledge from
the core I'm fine with it.
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH v3 6/6] s390/mm: Remove sev_active() function
From: Christoph Hellwig @ 2019-07-18 8:44 UTC (permalink / raw)
To: Thiago Jung Bauermann
Cc: linux-s390, Mike Anderson, Konrad Rzeszutek Wilk, Robin Murphy,
x86, Ram Pai, linux-kernel, Alexey Dobriyan, Halil Pasic, iommu,
Ingo Molnar, Borislav Petkov, Thomas Lendacky, H. Peter Anvin,
linux-fsdevel, Thomas Gleixner, linuxppc-dev, Christoph Hellwig,
Marek Szyprowski
In-Reply-To: <20190718032858.28744-7-bauerman@linux.ibm.com>
> -/* are we a protected virtualization guest? */
> -bool sev_active(void)
> -{
> - return is_prot_virt_guest();
> -}
> -
> bool force_dma_unencrypted(struct device *dev)
> {
> - return sev_active();
> + return is_prot_virt_guest();
> }
Do we want to keep the comment for force_dma_unencrypted?
Otherwise looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH V3] cpufreq: Make cpufreq_generic_init() return void
From: Rafael J. Wysocki @ 2019-07-18 8:47 UTC (permalink / raw)
To: Viresh Kumar
Cc: Jiaxun Yang, linux-mips, Thierry Reding, Paul Mackerras,
Fabio Estevam, linux-samsung-soc, Vincent Guittot, Kevin Hilman,
Krzysztof Kozlowski, Jonathan Hunter, Kukjin Kim,
bcm-kernel-feedback-list, NXP Linux Team, Keguang Zhang, linux-pm,
Sascha Hauer, Markus Mayer, linux-tegra, linux-omap,
linux-arm-kernel, linuxppc-dev, linux-kernel,
Pengutronix Kernel Team, Shawn Guo
In-Reply-To: <770b46d99e2fa88bc8cdfd95388374284c8b3cf8.1563249700.git.viresh.kumar@linaro.org>
On Tuesday, July 16, 2019 6:06:08 AM CEST Viresh Kumar wrote:
> It always returns 0 (success) and its return type should really be void.
> Over that, many drivers have added error handling code based on its
> return value, which is not required at all.
>
> change its return type to void and update all the callers.
>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
> V2->V3:
> - Update bmips cpufreq driver to avoid "warning: 'ret' may be used
> uninitialized".
> - Build bot reported this issue almost after 4 days of posting this
> patch, I was expecting this a lot earlier :)
>
> drivers/cpufreq/bmips-cpufreq.c | 17 ++++++-----------
> drivers/cpufreq/cpufreq.c | 4 +---
> drivers/cpufreq/davinci-cpufreq.c | 3 ++-
> drivers/cpufreq/imx6q-cpufreq.c | 6 ++----
> drivers/cpufreq/kirkwood-cpufreq.c | 3 ++-
> drivers/cpufreq/loongson1-cpufreq.c | 8 +++-----
> drivers/cpufreq/loongson2_cpufreq.c | 3 ++-
> drivers/cpufreq/maple-cpufreq.c | 3 ++-
> drivers/cpufreq/omap-cpufreq.c | 15 +++++----------
> drivers/cpufreq/pasemi-cpufreq.c | 3 ++-
> drivers/cpufreq/pmac32-cpufreq.c | 3 ++-
> drivers/cpufreq/pmac64-cpufreq.c | 3 ++-
> drivers/cpufreq/s3c2416-cpufreq.c | 9 ++-------
> drivers/cpufreq/s3c64xx-cpufreq.c | 15 +++------------
> drivers/cpufreq/s5pv210-cpufreq.c | 3 ++-
> drivers/cpufreq/sa1100-cpufreq.c | 3 ++-
> drivers/cpufreq/sa1110-cpufreq.c | 3 ++-
> drivers/cpufreq/spear-cpufreq.c | 3 ++-
> drivers/cpufreq/tegra20-cpufreq.c | 8 +-------
> include/linux/cpufreq.h | 2 +-
> 20 files changed, 46 insertions(+), 71 deletions(-)
>
> diff --git a/drivers/cpufreq/bmips-cpufreq.c b/drivers/cpufreq/bmips-cpufreq.c
> index 56a4ebbf00e0..f7c23fa468f0 100644
> --- a/drivers/cpufreq/bmips-cpufreq.c
> +++ b/drivers/cpufreq/bmips-cpufreq.c
> @@ -131,23 +131,18 @@ static int bmips_cpufreq_exit(struct cpufreq_policy *policy)
> static int bmips_cpufreq_init(struct cpufreq_policy *policy)
> {
> struct cpufreq_frequency_table *freq_table;
> - int ret;
>
> freq_table = bmips_cpufreq_get_freq_table(policy);
> if (IS_ERR(freq_table)) {
> - ret = PTR_ERR(freq_table);
> - pr_err("%s: couldn't determine frequency table (%d).\n",
> - BMIPS_CPUFREQ_NAME, ret);
> - return ret;
> + pr_err("%s: couldn't determine frequency table (%ld).\n",
> + BMIPS_CPUFREQ_NAME, PTR_ERR(freq_table));
> + return PTR_ERR(freq_table);
> }
>
> - ret = cpufreq_generic_init(policy, freq_table, TRANSITION_LATENCY);
> - if (ret)
> - bmips_cpufreq_exit(policy);
> - else
> - pr_info("%s: registered\n", BMIPS_CPUFREQ_NAME);
> + cpufreq_generic_init(policy, freq_table, TRANSITION_LATENCY);
> + pr_info("%s: registered\n", BMIPS_CPUFREQ_NAME);
>
> - return ret;
> + return 0;
> }
>
> static struct cpufreq_driver bmips_cpufreq_driver = {
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 4d6043ee7834..8dda62367816 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -159,7 +159,7 @@ EXPORT_SYMBOL_GPL(arch_set_freq_scale);
> * - set policies transition latency
> * - policy->cpus with all possible CPUs
> */
> -int cpufreq_generic_init(struct cpufreq_policy *policy,
> +void cpufreq_generic_init(struct cpufreq_policy *policy,
> struct cpufreq_frequency_table *table,
> unsigned int transition_latency)
> {
> @@ -171,8 +171,6 @@ int cpufreq_generic_init(struct cpufreq_policy *policy,
> * share the clock and voltage and clock.
> */
> cpumask_setall(policy->cpus);
> -
> - return 0;
> }
> EXPORT_SYMBOL_GPL(cpufreq_generic_init);
>
> diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c
> index 3de48ae60c29..297d23cad8b5 100644
> --- a/drivers/cpufreq/davinci-cpufreq.c
> +++ b/drivers/cpufreq/davinci-cpufreq.c
> @@ -90,7 +90,8 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
> * Setting the latency to 2000 us to accommodate addition of drivers
> * to pre/post change notification list.
> */
> - return cpufreq_generic_init(policy, freq_table, 2000 * 1000);
> + cpufreq_generic_init(policy, freq_table, 2000 * 1000);
> + return 0;
> }
>
> static struct cpufreq_driver davinci_driver = {
> diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
> index 47ccfa6b17b7..648a09a1778a 100644
> --- a/drivers/cpufreq/imx6q-cpufreq.c
> +++ b/drivers/cpufreq/imx6q-cpufreq.c
> @@ -190,14 +190,12 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
>
> static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
> {
> - int ret;
> -
> policy->clk = clks[ARM].clk;
> - ret = cpufreq_generic_init(policy, freq_table, transition_latency);
> + cpufreq_generic_init(policy, freq_table, transition_latency);
> policy->suspend_freq = max_freq;
> dev_pm_opp_of_register_em(policy->cpus);
>
> - return ret;
> + return 0;
> }
>
> static struct cpufreq_driver imx6q_cpufreq_driver = {
> diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
> index 7ab564c1f7ae..cb74bdc5baaa 100644
> --- a/drivers/cpufreq/kirkwood-cpufreq.c
> +++ b/drivers/cpufreq/kirkwood-cpufreq.c
> @@ -85,7 +85,8 @@ static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
> /* Module init and exit code */
> static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy)
> {
> - return cpufreq_generic_init(policy, kirkwood_freq_table, 5000);
> + cpufreq_generic_init(policy, kirkwood_freq_table, 5000);
> + return 0;
> }
>
> static struct cpufreq_driver kirkwood_cpufreq_driver = {
> diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c
> index 21c9ce8526c0..0ea88778882a 100644
> --- a/drivers/cpufreq/loongson1-cpufreq.c
> +++ b/drivers/cpufreq/loongson1-cpufreq.c
> @@ -81,7 +81,7 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy)
> struct device *cpu_dev = get_cpu_device(policy->cpu);
> struct cpufreq_frequency_table *freq_tbl;
> unsigned int pll_freq, freq;
> - int steps, i, ret;
> + int steps, i;
>
> pll_freq = clk_get_rate(cpufreq->pll_clk) / 1000;
>
> @@ -103,11 +103,9 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy)
> freq_tbl[i].frequency = CPUFREQ_TABLE_END;
>
> policy->clk = cpufreq->clk;
> - ret = cpufreq_generic_init(policy, freq_tbl, 0);
> - if (ret)
> - kfree(freq_tbl);
> + cpufreq_generic_init(policy, freq_tbl, 0);
>
> - return ret;
> + return 0;
> }
>
> static int ls1x_cpufreq_exit(struct cpufreq_policy *policy)
> diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
> index da344696beed..890813e0bb76 100644
> --- a/drivers/cpufreq/loongson2_cpufreq.c
> +++ b/drivers/cpufreq/loongson2_cpufreq.c
> @@ -95,7 +95,8 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
> }
>
> policy->clk = cpuclk;
> - return cpufreq_generic_init(policy, &loongson2_clockmod_table[0], 0);
> + cpufreq_generic_init(policy, &loongson2_clockmod_table[0], 0);
> + return 0;
> }
>
> static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
> diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c
> index f5220b3d4ec5..28d346062166 100644
> --- a/drivers/cpufreq/maple-cpufreq.c
> +++ b/drivers/cpufreq/maple-cpufreq.c
> @@ -140,7 +140,8 @@ static unsigned int maple_cpufreq_get_speed(unsigned int cpu)
>
> static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy)
> {
> - return cpufreq_generic_init(policy, maple_cpu_freqs, 12000);
> + cpufreq_generic_init(policy, maple_cpu_freqs, 12000);
> + return 0;
> }
>
> static struct cpufreq_driver maple_cpufreq_driver = {
> diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
> index 29643f06a3c3..8d14b42a8c6f 100644
> --- a/drivers/cpufreq/omap-cpufreq.c
> +++ b/drivers/cpufreq/omap-cpufreq.c
> @@ -122,23 +122,18 @@ static int omap_cpu_init(struct cpufreq_policy *policy)
> dev_err(mpu_dev,
> "%s: cpu%d: failed creating freq table[%d]\n",
> __func__, policy->cpu, result);
> - goto fail;
> + clk_put(policy->clk);
> + return result;
> }
> }
>
> atomic_inc_return(&freq_table_users);
>
> /* FIXME: what's the actual transition time? */
> - result = cpufreq_generic_init(policy, freq_table, 300 * 1000);
> - if (!result) {
> - dev_pm_opp_of_register_em(policy->cpus);
> - return 0;
> - }
> + cpufreq_generic_init(policy, freq_table, 300 * 1000);
> + dev_pm_opp_of_register_em(policy->cpus);
>
> - freq_table_free();
> -fail:
> - clk_put(policy->clk);
> - return result;
> + return 0;
> }
>
> static int omap_cpu_exit(struct cpufreq_policy *policy)
> diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c
> index 6b1e4abe3248..93f39a1d4c3d 100644
> --- a/drivers/cpufreq/pasemi-cpufreq.c
> +++ b/drivers/cpufreq/pasemi-cpufreq.c
> @@ -196,7 +196,8 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
> policy->cur = pas_freqs[cur_astate].frequency;
> ppc_proc_freq = policy->cur * 1000ul;
>
> - return cpufreq_generic_init(policy, pas_freqs, get_gizmo_latency());
> + cpufreq_generic_init(policy, pas_freqs, get_gizmo_latency());
> + return 0;
>
> out_unmap_sdcpwr:
> iounmap(sdcpwr_mapbase);
> diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c
> index 650104d729f3..73621bc11976 100644
> --- a/drivers/cpufreq/pmac32-cpufreq.c
> +++ b/drivers/cpufreq/pmac32-cpufreq.c
> @@ -372,7 +372,8 @@ static int pmac_cpufreq_target( struct cpufreq_policy *policy,
>
> static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
> {
> - return cpufreq_generic_init(policy, pmac_cpu_freqs, transition_latency);
> + cpufreq_generic_init(policy, pmac_cpu_freqs, transition_latency);
> + return 0;
> }
>
> static u32 read_gpio(struct device_node *np)
> diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c
> index 1af3492a000d..d7542a106e6b 100644
> --- a/drivers/cpufreq/pmac64-cpufreq.c
> +++ b/drivers/cpufreq/pmac64-cpufreq.c
> @@ -321,7 +321,8 @@ static unsigned int g5_cpufreq_get_speed(unsigned int cpu)
>
> static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
> {
> - return cpufreq_generic_init(policy, g5_cpu_freqs, transition_latency);
> + cpufreq_generic_init(policy, g5_cpu_freqs, transition_latency);
> + return 0;
> }
>
> static struct cpufreq_driver g5_cpufreq_driver = {
> diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c
> index f7ff1ed7fef1..106910351c41 100644
> --- a/drivers/cpufreq/s3c2416-cpufreq.c
> +++ b/drivers/cpufreq/s3c2416-cpufreq.c
> @@ -447,21 +447,16 @@ static int s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy)
> /* Datasheet says PLL stabalisation time must be at least 300us,
> * so but add some fudge. (reference in LOCKCON0 register description)
> */
> - ret = cpufreq_generic_init(policy, s3c_freq->freq_table,
> + cpufreq_generic_init(policy, s3c_freq->freq_table,
> (500 * 1000) + s3c_freq->regulator_latency);
> - if (ret)
> - goto err_freq_table;
> -
> register_reboot_notifier(&s3c2416_cpufreq_reboot_notifier);
>
> return 0;
>
> -err_freq_table:
> #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
> - regulator_put(s3c_freq->vddarm);
> err_vddarm:
> -#endif
> clk_put(s3c_freq->armclk);
> +#endif
> err_armclk:
> clk_put(s3c_freq->hclk);
> err_hclk:
> diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c
> index 37df2d892eb0..af0c00dabb22 100644
> --- a/drivers/cpufreq/s3c64xx-cpufreq.c
> +++ b/drivers/cpufreq/s3c64xx-cpufreq.c
> @@ -144,7 +144,6 @@ static void s3c64xx_cpufreq_config_regulator(void)
>
> static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
> {
> - int ret;
> struct cpufreq_frequency_table *freq;
>
> if (policy->cpu != 0)
> @@ -165,8 +164,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
> #ifdef CONFIG_REGULATOR
> vddarm = regulator_get(NULL, "vddarm");
> if (IS_ERR(vddarm)) {
> - ret = PTR_ERR(vddarm);
> - pr_err("Failed to obtain VDDARM: %d\n", ret);
> + pr_err("Failed to obtain VDDARM: %ld\n", PTR_ERR(vddarm));
> pr_err("Only frequency scaling available\n");
> vddarm = NULL;
> } else {
> @@ -196,16 +194,9 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
> * the PLLs, which we don't currently) is ~300us worst case,
> * but add some fudge.
> */
> - ret = cpufreq_generic_init(policy, s3c64xx_freq_table,
> + cpufreq_generic_init(policy, s3c64xx_freq_table,
> (500 * 1000) + regulator_latency);
> - if (ret != 0) {
> - pr_err("Failed to configure frequency table: %d\n",
> - ret);
> - regulator_put(vddarm);
> - clk_put(policy->clk);
> - }
> -
> - return ret;
> + return 0;
> }
>
> static struct cpufreq_driver s3c64xx_cpufreq_driver = {
> diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
> index e5cb17d4be7b..5d10030f2560 100644
> --- a/drivers/cpufreq/s5pv210-cpufreq.c
> +++ b/drivers/cpufreq/s5pv210-cpufreq.c
> @@ -541,7 +541,8 @@ static int s5pv210_cpu_init(struct cpufreq_policy *policy)
> s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
>
> policy->suspend_freq = SLEEP_FREQ;
> - return cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
> + cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
> + return 0;
>
> out_dmc1:
> clk_put(dmc0_clk);
> diff --git a/drivers/cpufreq/sa1100-cpufreq.c b/drivers/cpufreq/sa1100-cpufreq.c
> index ab5cab93e638..5c075ef6adc0 100644
> --- a/drivers/cpufreq/sa1100-cpufreq.c
> +++ b/drivers/cpufreq/sa1100-cpufreq.c
> @@ -181,7 +181,8 @@ static int sa1100_target(struct cpufreq_policy *policy, unsigned int ppcr)
>
> static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
> {
> - return cpufreq_generic_init(policy, sa11x0_freq_table, 0);
> + cpufreq_generic_init(policy, sa11x0_freq_table, 0);
> + return 0;
> }
>
> static struct cpufreq_driver sa1100_driver __refdata = {
> diff --git a/drivers/cpufreq/sa1110-cpufreq.c b/drivers/cpufreq/sa1110-cpufreq.c
> index dab54e051c0e..d9d04d935b3a 100644
> --- a/drivers/cpufreq/sa1110-cpufreq.c
> +++ b/drivers/cpufreq/sa1110-cpufreq.c
> @@ -303,7 +303,8 @@ static int sa1110_target(struct cpufreq_policy *policy, unsigned int ppcr)
>
> static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
> {
> - return cpufreq_generic_init(policy, sa11x0_freq_table, 0);
> + cpufreq_generic_init(policy, sa11x0_freq_table, 0);
> + return 0;
> }
>
> /* sa1110_driver needs __refdata because it must remain after init registers
> diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c
> index 4074e2615522..73bd8dc47074 100644
> --- a/drivers/cpufreq/spear-cpufreq.c
> +++ b/drivers/cpufreq/spear-cpufreq.c
> @@ -153,8 +153,9 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
> static int spear_cpufreq_init(struct cpufreq_policy *policy)
> {
> policy->clk = spear_cpufreq.clk;
> - return cpufreq_generic_init(policy, spear_cpufreq.freq_tbl,
> + cpufreq_generic_init(policy, spear_cpufreq.freq_tbl,
> spear_cpufreq.transition_latency);
> + return 0;
> }
>
> static struct cpufreq_driver spear_cpufreq_driver = {
> diff --git a/drivers/cpufreq/tegra20-cpufreq.c b/drivers/cpufreq/tegra20-cpufreq.c
> index 3c32cc7b0671..f84ecd22f488 100644
> --- a/drivers/cpufreq/tegra20-cpufreq.c
> +++ b/drivers/cpufreq/tegra20-cpufreq.c
> @@ -118,17 +118,11 @@ static int tegra_target(struct cpufreq_policy *policy, unsigned int index)
> static int tegra_cpu_init(struct cpufreq_policy *policy)
> {
> struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
> - int ret;
>
> clk_prepare_enable(cpufreq->cpu_clk);
>
> /* FIXME: what's the actual transition time? */
> - ret = cpufreq_generic_init(policy, freq_table, 300 * 1000);
> - if (ret) {
> - clk_disable_unprepare(cpufreq->cpu_clk);
> - return ret;
> - }
> -
> + cpufreq_generic_init(policy, freq_table, 300 * 1000);
> policy->clk = cpufreq->cpu_clk;
> policy->suspend_freq = freq_table[0].frequency;
> return 0;
> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index d757a56a74dc..536a049d7ecc 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -992,7 +992,7 @@ extern struct freq_attr *cpufreq_generic_attr[];
> int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy);
>
> unsigned int cpufreq_generic_get(unsigned int cpu);
> -int cpufreq_generic_init(struct cpufreq_policy *policy,
> +void cpufreq_generic_init(struct cpufreq_policy *policy,
> struct cpufreq_frequency_table *table,
> unsigned int transition_latency);
> #endif /* _LINUX_CPUFREQ_H */
>
Applied, thanks!
^ permalink raw reply
* Re: [PATCH] powerpc/dma: Fix invalid DMA mmap behavior
From: Christoph Hellwig @ 2019-07-18 8:49 UTC (permalink / raw)
To: Oliver O'Halloran
Cc: Alexey Kardashevskiy, linuxppc-dev, Shawn Anastasio,
Christoph Hellwig, Sam Bobroff
In-Reply-To: <CAOSf1CGA_fDH7aAqRkc4maJUByaX7adGcjyt3cj4KFsMJNnocA@mail.gmail.com>
On Thu, Jul 18, 2019 at 01:45:16PM +1000, Oliver O'Halloran wrote:
> > Other than m68k, mips, and arm64, everybody else that doesn't have
> > ARCH_NO_COHERENT_DMA_MMAP set uses this default implementation, so
> > I assume this behavior is acceptable on those architectures.
>
> It might be acceptable, but there's no reason to use pgport_noncached
> if the platform supports cache-coherent DMA.
>
> Christoph (+cc) made the change so maybe he saw something we're missing.
I always found the forcing of noncached access even for coherent
devices a little odd, but this was inherited from the previous
implementation, which surprised me a bit as the different attributes
are usually problematic even on x86. Let me dig into the history a
bit more, but I suspect the righ fix is to default to cached mappings
for coherent devices.
^ permalink raw reply
* Re: [PATCH] powerpc/dma: Fix invalid DMA mmap behavior
From: Christoph Hellwig @ 2019-07-18 9:52 UTC (permalink / raw)
To: Oliver O'Halloran
Cc: Shawn Anastasio, Alexey Kardashevskiy, Sam Bobroff, iommu,
linuxppc-dev, Christoph Hellwig, Marek Szyprowski
In-Reply-To: <20190718084934.GF24562@lst.de>
On Thu, Jul 18, 2019 at 10:49:34AM +0200, Christoph Hellwig wrote:
> On Thu, Jul 18, 2019 at 01:45:16PM +1000, Oliver O'Halloran wrote:
> > > Other than m68k, mips, and arm64, everybody else that doesn't have
> > > ARCH_NO_COHERENT_DMA_MMAP set uses this default implementation, so
> > > I assume this behavior is acceptable on those architectures.
> >
> > It might be acceptable, but there's no reason to use pgport_noncached
> > if the platform supports cache-coherent DMA.
> >
> > Christoph (+cc) made the change so maybe he saw something we're missing.
>
> I always found the forcing of noncached access even for coherent
> devices a little odd, but this was inherited from the previous
> implementation, which surprised me a bit as the different attributes
> are usually problematic even on x86. Let me dig into the history a
> bit more, but I suspect the righ fix is to default to cached mappings
> for coherent devices.
Ok, some history:
The generic dma mmap implementation, which we are effectively still
using today was added by:
commit 64ccc9c033c6089b2d426dad3c56477ab066c999
Author: Marek Szyprowski <m.szyprowski@samsung.com>
Date: Thu Jun 14 13:03:04 2012 +0200
common: dma-mapping: add support for generic dma_mmap_* calls
and unconditionally uses pgprot_noncached in dma_common_mmap, which is
then used as the fallback by dma_mmap_attrs if no ->mmap method is
present. At that point we already had the powerpc implementation
that only uses pgprot_noncached for non-coherent mappings, and
the arm one, which uses pgprot_writecombine if DMA_ATTR_WRITE_COMBINE
is set and otherwise pgprot_dmacoherent, which seems to be uncached.
Arm did support coherent platforms at that time, but they might have
been an afterthought and not handled properly.
So it migt have been that we were all wrong for that time and might
have to fix it up.
^ permalink raw reply
* [PATCH v7] cpufreq/pasemi: fix an use-after-free inpas_cpufreq_cpu_init()
From: Christian Zigotzky @ 2019-07-18 12:46 UTC (permalink / raw)
To: wen.yang99; +Cc: linuxppc-dev
In-Reply-To: <201907090939164296374@zte.com.cn>
On 09.07.2019 at 03:39am, wen.yang99@zte.com.cn wrote:
>> Hello Wen,
>>
>> Thanks for your patch!
>>
>> Did you test your patch with a P.A. Semi board?
>>
> Hello Christian, thank you.
> We don't have a P.A. Semi board yet, so we didn't test it.
> If you have such a board, could you please kindly help to test it?
>
> --
> Thanks and regards,
> Wen
Hello Wen,
I successfully tested your pasemi cpufreq modifications with my P.A.
Semi board [1] today.
First I patched the latest Git kernel with Viresh Kumar's patch [2].
After that I was able to patch the latest Git kernel with your v7 patch [3].
Then the kernel compiled without any errors.
Afterwards I successfully tested the new Git kernel with some cpufreq
governors on openSUSE Tumbleweed 20190521 PowerPC64 [4] and on ubuntu
MATE 16.04.6 LTS PowerPC32.
Thanks a lot for your work!
Tested-by: Christian Zigotzky <chzigotzky@xenosoft.de>
Cheers,
Christian
[1] https://en.wikipedia.org/wiki/AmigaOne_X1000
[2]
https://lore.kernel.org/lkml/ee8cf5fb4b4a01fdf9199037ff6d835b935cfd13.1562902877.git.viresh.kumar@linaro.org/#Z30drivers:cpufreq:pasemi-cpufreq.c
[3] https://lists.ozlabs.org/pipermail/linuxppc-dev/2019-July/193735.html
[4] Screenshots:
https://i.pinimg.com/originals/37/66/93/37669306cbc909a9d79270a849d18aa6.png
and
https://i.pinimg.com/originals/fe/f8/bf/fef8bfc90d95b5ae9cf31e175e8ba2da.png
^ 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