From 1e89da5ef9c28c673e86048c89ef9495618d987d Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Fri, 3 Apr 2020 17:38:35 +0200 Subject: scsi: cxlflash: Access interrupt trigger page from xive directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit xive is already mapping the trigger page in kernel space and it can be accessed through standard APIs, so let's reuse it and simplify the code. Signed-off-by: Frederic Barrat Reviewed-by: Cédric Le Goater Acked-by: Matthew R. Ochs Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200403153838.29224-2-fbarrat@linux.ibm.com --- drivers/scsi/cxlflash/ocxl_hw.c | 18 ++++++++---------- drivers/scsi/cxlflash/ocxl_hw.h | 1 - 2 files changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c index 7018cd802569..d6eec434a607 100644 --- a/drivers/scsi/cxlflash/ocxl_hw.c +++ b/drivers/scsi/cxlflash/ocxl_hw.c @@ -15,7 +15,8 @@ #include #include #include - +#include +#include #include #include @@ -180,7 +181,7 @@ static int afu_map_irq(u64 flags, struct ocxlflash_context *ctx, int num, struct ocxl_hw_afu *afu = ctx->hw_afu; struct device *dev = afu->dev; struct ocxlflash_irqs *irq; - void __iomem *vtrig; + struct xive_irq_data *xd; u32 virq; int rc = 0; @@ -204,15 +205,15 @@ static int afu_map_irq(u64 flags, struct ocxlflash_context *ctx, int num, goto err1; } - vtrig = ioremap(irq->ptrig, PAGE_SIZE); - if (unlikely(!vtrig)) { - dev_err(dev, "%s: Trigger page mapping failed\n", __func__); - rc = -ENOMEM; + xd = irq_get_handler_data(virq); + if (unlikely(!xd)) { + dev_err(dev, "%s: Can't get interrupt data\n", __func__); + rc = -ENXIO; goto err2; } irq->virq = virq; - irq->vtrig = vtrig; + irq->vtrig = xd->trig_mmio; out: return rc; err2: @@ -259,8 +260,6 @@ static void afu_unmap_irq(u64 flags, struct ocxlflash_context *ctx, int num, } irq = &ctx->irqs[num]; - if (irq->vtrig) - iounmap(irq->vtrig); if (irq_find_mapping(NULL, irq->hwirq)) { free_irq(irq->virq, cookie); @@ -648,7 +647,6 @@ static int alloc_afu_irqs(struct ocxlflash_context *ctx, int num) } irqs[i].hwirq = hwirq; - irqs[i].ptrig = addr; } ctx->irqs = irqs; diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h index fc6ad4f985de..f2fe88816bea 100644 --- a/drivers/scsi/cxlflash/ocxl_hw.h +++ b/drivers/scsi/cxlflash/ocxl_hw.h @@ -13,7 +13,6 @@ struct ocxlflash_irqs { int hwirq; u32 virq; - u64 ptrig; void __iomem *vtrig; }; -- cgit v1.2.3 From ad857d47df6a1adc9798558701dd5426643b859f Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Fri, 3 Apr 2020 17:38:36 +0200 Subject: ocxl: Access interrupt trigger page from xive directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can access the trigger page through standard APIs so let's use it and avoid saving it when allocating the interrupt. It will also allow to simplify allocation in a later patch. Signed-off-by: Frederic Barrat Reviewed-by: Cédric Le Goater Reviewed-by: Greg Kurz Acked-by: Andrew Donnellan Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200403153838.29224-3-fbarrat@linux.ibm.com --- drivers/misc/ocxl/afu_irq.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/ocxl/afu_irq.c b/drivers/misc/ocxl/afu_irq.c index 70f8f1c3929d..b30ec0ef7be7 100644 --- a/drivers/misc/ocxl/afu_irq.c +++ b/drivers/misc/ocxl/afu_irq.c @@ -2,6 +2,7 @@ // Copyright 2017 IBM Corp. #include #include +#include #include "ocxl_internal.h" #include "trace.h" @@ -196,13 +197,16 @@ void ocxl_afu_irq_free_all(struct ocxl_context *ctx) u64 ocxl_afu_irq_get_addr(struct ocxl_context *ctx, int irq_id) { + struct xive_irq_data *xd; struct afu_irq *irq; u64 addr = 0; mutex_lock(&ctx->irq_lock); irq = idr_find(&ctx->irq_idr, irq_id); - if (irq) - addr = irq->trigger_page; + if (irq) { + xd = irq_get_handler_data(irq->virq); + addr = xd ? xd->trig_page : 0; + } mutex_unlock(&ctx->irq_lock); return addr; } -- cgit v1.2.3 From dde6f18a8779dcd88d9fd5d6336032fee7e07fcd Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Fri, 3 Apr 2020 17:38:37 +0200 Subject: ocxl: Don't return trigger page when allocating an interrupt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Existing users of ocxl_link_irq_alloc() have been converted to obtain the trigger page of an interrupt through xive directly, we therefore have no need to return the trigger page when allocating an interrupt. It also allows ocxl to use the xive native interface to allocate interrupts, instead of its custom service. Signed-off-by: Frederic Barrat Reviewed-by: Cédric Le Goater Reviewed-by: Greg Kurz Acked-by: Andrew Donnellan Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200403153838.29224-4-fbarrat@linux.ibm.com --- drivers/misc/ocxl/Kconfig | 2 +- drivers/misc/ocxl/afu_irq.c | 4 +--- drivers/misc/ocxl/link.c | 15 +++++++-------- drivers/scsi/cxlflash/ocxl_hw.c | 3 +-- include/misc/ocxl.h | 10 ++-------- 5 files changed, 12 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/ocxl/Kconfig b/drivers/misc/ocxl/Kconfig index 6551007a066c..0d815b2a40b3 100644 --- a/drivers/misc/ocxl/Kconfig +++ b/drivers/misc/ocxl/Kconfig @@ -9,7 +9,7 @@ config OCXL_BASE config OCXL tristate "OpenCAPI coherent accelerator support" - depends on PPC_POWERNV && PCI && EEH + depends on PPC_POWERNV && PCI && EEH && PPC_XIVE_NATIVE select OCXL_BASE select HOTPLUG_PCI_POWERNV default m diff --git a/drivers/misc/ocxl/afu_irq.c b/drivers/misc/ocxl/afu_irq.c index b30ec0ef7be7..ecdcfae025b7 100644 --- a/drivers/misc/ocxl/afu_irq.c +++ b/drivers/misc/ocxl/afu_irq.c @@ -11,7 +11,6 @@ struct afu_irq { int hw_irq; unsigned int virq; char *name; - u64 trigger_page; irqreturn_t (*handler)(void *private); void (*free_private)(void *private); void *private; @@ -125,8 +124,7 @@ int ocxl_afu_irq_alloc(struct ocxl_context *ctx, int *irq_id) goto err_unlock; } - rc = ocxl_link_irq_alloc(ctx->afu->fn->link, &irq->hw_irq, - &irq->trigger_page); + rc = ocxl_link_irq_alloc(ctx->afu->fn->link, &irq->hw_irq); if (rc) goto err_idr; diff --git a/drivers/misc/ocxl/link.c b/drivers/misc/ocxl/link.c index 58d111afd9f6..fd73d3bc0eb6 100644 --- a/drivers/misc/ocxl/link.c +++ b/drivers/misc/ocxl/link.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "ocxl_internal.h" #include "trace.h" @@ -682,23 +683,21 @@ unlock: } EXPORT_SYMBOL_GPL(ocxl_link_remove_pe); -int ocxl_link_irq_alloc(void *link_handle, int *hw_irq, u64 *trigger_addr) +int ocxl_link_irq_alloc(void *link_handle, int *hw_irq) { struct ocxl_link *link = (struct ocxl_link *) link_handle; - int rc, irq; - u64 addr; + int irq; if (atomic_dec_if_positive(&link->irq_available) < 0) return -ENOSPC; - rc = pnv_ocxl_alloc_xive_irq(&irq, &addr); - if (rc) { + irq = xive_native_alloc_irq(); + if (!irq) { atomic_inc(&link->irq_available); - return rc; + return -ENXIO; } *hw_irq = irq; - *trigger_addr = addr; return 0; } EXPORT_SYMBOL_GPL(ocxl_link_irq_alloc); @@ -707,7 +706,7 @@ void ocxl_link_free_irq(void *link_handle, int hw_irq) { struct ocxl_link *link = (struct ocxl_link *) link_handle; - pnv_ocxl_free_xive_irq(hw_irq); + xive_native_free_irq(hw_irq); atomic_inc(&link->irq_available); } EXPORT_SYMBOL_GPL(ocxl_link_free_irq); diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c index d6eec434a607..e4e0d767b98e 100644 --- a/drivers/scsi/cxlflash/ocxl_hw.c +++ b/drivers/scsi/cxlflash/ocxl_hw.c @@ -614,7 +614,6 @@ static int alloc_afu_irqs(struct ocxlflash_context *ctx, int num) struct ocxl_hw_afu *afu = ctx->hw_afu; struct device *dev = afu->dev; struct ocxlflash_irqs *irqs; - u64 addr; int rc = 0; int hwirq; int i; @@ -639,7 +638,7 @@ static int alloc_afu_irqs(struct ocxlflash_context *ctx, int num) } for (i = 0; i < num; i++) { - rc = ocxl_link_irq_alloc(afu->link_token, &hwirq, &addr); + rc = ocxl_link_irq_alloc(afu->link_token, &hwirq); if (unlikely(rc)) { dev_err(dev, "%s: ocxl_link_irq_alloc failed rc=%d\n", __func__, rc); diff --git a/include/misc/ocxl.h b/include/misc/ocxl.h index 357ef1aadbc0..e013736e275d 100644 --- a/include/misc/ocxl.h +++ b/include/misc/ocxl.h @@ -460,14 +460,8 @@ int ocxl_link_remove_pe(void *link_handle, int pasid); * Allocate an AFU interrupt associated to the link. * * 'hw_irq' is the hardware interrupt number - * 'obj_handle' is the 64-bit object handle to be passed to the AFU to - * trigger the interrupt. - * On P9, 'obj_handle' is an address, which, if written, triggers the - * interrupt. It is an MMIO address which needs to be remapped (one - * page). - */ -int ocxl_link_irq_alloc(void *link_handle, int *hw_irq, - u64 *obj_handle); + */ +int ocxl_link_irq_alloc(void *link_handle, int *hw_irq); /* * Free a previously allocated AFU interrupt -- cgit v1.2.3 From 40ac790d99c6dd16b367d5c2339e446a5f1b0593 Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Tue, 7 Apr 2020 13:56:01 +0200 Subject: cxl: Rework error message for incompatible slots Improve the error message shown if a capi adapter is plugged on a capi-incompatible slot directly under the PHB (no intermediate switch). Fixes: 5632874311db ("cxl: Add support for POWER9 DD2") Cc: stable@vger.kernel.org # 4.14+ Signed-off-by: Frederic Barrat Reviewed-by: Andrew Donnellan Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200407115601.25453-1-fbarrat@linux.ibm.com --- drivers/misc/cxl/pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 25a9dd9c0c1b..2ba899f5659f 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -393,8 +393,8 @@ int cxl_calc_capp_routing(struct pci_dev *dev, u64 *chipid, *capp_unit_id = get_capp_unit_id(np, *phb_index); of_node_put(np); if (!*capp_unit_id) { - pr_err("cxl: invalid capp unit id (phb_index: %d)\n", - *phb_index); + pr_err("cxl: No capp unit found for PHB[%lld,%d]. Make sure the adapter is on a capi-compatible slot\n", + *chipid, *phb_index); return -ENODEV; } -- cgit v1.2.3 From 7db0a07273e8f581d0b3e8a102d3d9dd99f43528 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 6 Aug 2020 11:29:01 +0100 Subject: macintosh: windfarm: remove detatch debug containing spelling mistakes There are spelling mistakes in two debug messages. As recommended by Wolfram Sang, these can be removed as there is plenty of debug in the driver core. Signed-off-by: Colin Ian King Reviewed-by: Wolfram Sang Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200806102901.44988-1-colin.king@canonical.com --- drivers/macintosh/windfarm_lm75_sensor.c | 2 -- drivers/macintosh/windfarm_lm87_sensor.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index 1e5fa09845e7..29f48c2028b6 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c @@ -152,8 +152,6 @@ static int wf_lm75_remove(struct i2c_client *client) { struct wf_lm75_sensor *lm = i2c_get_clientdata(client); - DBG("wf_lm75: i2c detatch called for %s\n", lm->sens.name); - /* Mark client detached */ lm->i2c = NULL; diff --git a/drivers/macintosh/windfarm_lm87_sensor.c b/drivers/macintosh/windfarm_lm87_sensor.c index d011899c0a8a..9fab0b47cd3d 100644 --- a/drivers/macintosh/windfarm_lm87_sensor.c +++ b/drivers/macintosh/windfarm_lm87_sensor.c @@ -149,8 +149,6 @@ static int wf_lm87_remove(struct i2c_client *client) { struct wf_lm87_sensor *lm = i2c_get_clientdata(client); - DBG("wf_lm87: i2c detatch called for %s\n", lm->sens.name); - /* Mark client detached */ lm->i2c = NULL; -- cgit v1.2.3 From ffd2961bb41f797eb00b58e019b707555197275e Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Wed, 19 Aug 2020 19:47:00 +1000 Subject: powerpc/powernv/idle: add a basic stop 0-3 driver for POWER10 This driver does not restore stop > 3 state, so it limits itself to states which do not lose full state or TB. The POWER10 SPRs are sufficiently different from P9 that it seems easier to split out the P10 code. The POWER10 deep sleep code (e.g., the BHRB restore) has been taken out, but it can be re-added when stop > 3 support is added. Signed-off-by: Nicholas Piggin Tested-by: Pratik Rajesh Sampat Tested-by: Vaidyanathan Srinivasan Reviewed-by: Pratik Rajesh Sampat Reviewed-by: Gautham R. Shenoy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200819094700.493399-1-npiggin@gmail.com --- arch/powerpc/include/asm/machdep.h | 2 - arch/powerpc/include/asm/processor.h | 2 +- arch/powerpc/include/asm/reg.h | 1 + arch/powerpc/platforms/powernv/idle.c | 302 +++++++++++++++++++++++----------- drivers/cpuidle/cpuidle-powernv.c | 2 +- 5 files changed, 212 insertions(+), 97 deletions(-) (limited to 'drivers') diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index a90b892f0bfe..5082cd496190 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -222,8 +222,6 @@ struct machdep_calls { extern void e500_idle(void); extern void power4_idle(void); -extern void power7_idle(void); -extern void power9_idle(void); extern void ppc6xx_idle(void); extern void book3e_idle(void); diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 36a71cd41f37..22ffe85a91b8 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -432,7 +432,7 @@ enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF}; extern int powersave_nap; /* set if nap mode can be used in idle loop */ extern void power7_idle_type(unsigned long type); -extern void power9_idle_type(unsigned long stop_psscr_val, +extern void arch300_idle_type(unsigned long stop_psscr_val, unsigned long stop_psscr_mask); extern int fix_alignment(struct pt_regs *); diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 5647006ed373..d25c357a873c 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1353,6 +1353,7 @@ #define PVR_POWER8NVL 0x004C #define PVR_POWER8 0x004D #define PVR_POWER9 0x004E +#define PVR_POWER10 0x0080 #define PVR_BE 0x0070 #define PVR_PA6T 0x0090 diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c index 345ab062b21a..1ed7c5286487 100644 --- a/arch/powerpc/platforms/powernv/idle.c +++ b/arch/powerpc/platforms/powernv/idle.c @@ -565,7 +565,7 @@ void power7_idle_type(unsigned long type) irq_set_pending_from_srr1(srr1); } -void power7_idle(void) +static void power7_idle(void) { if (!powersave_nap) return; @@ -659,20 +659,6 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on) mmcr0 = mfspr(SPRN_MMCR0); } - if (cpu_has_feature(CPU_FTR_ARCH_31)) { - /* - * POWER10 uses MMCRA (BHRBRD) as BHRB disable bit. - * If the user hasn't asked for the BHRB to be - * written, the value of MMCRA[BHRBRD] is 1. - * On wakeup from stop, MMCRA[BHRBD] will be 0, - * since it is previleged resource and will be lost. - * Thus, if we do not save and restore the MMCRA[BHRBD], - * hardware will be needlessly writing to the BHRB - * in problem mode. - */ - mmcra = mfspr(SPRN_MMCRA); - } - if ((psscr & PSSCR_RL_MASK) >= deep_spr_loss_state) { sprs.lpcr = mfspr(SPRN_LPCR); sprs.hfscr = mfspr(SPRN_HFSCR); @@ -735,10 +721,6 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on) mtspr(SPRN_MMCR0, mmcr0); } - /* Reload MMCRA to restore BHRB disable bit for POWER10 */ - if (cpu_has_feature(CPU_FTR_ARCH_31)) - mtspr(SPRN_MMCRA, mmcra); - /* * DD2.2 and earlier need to set then clear bit 60 in MMCRA * to ensure the PMU starts running. @@ -823,73 +805,6 @@ out: return srr1; } -#ifdef CONFIG_HOTPLUG_CPU -static unsigned long power9_offline_stop(unsigned long psscr) -{ - unsigned long srr1; - -#ifndef CONFIG_KVM_BOOK3S_HV_POSSIBLE - __ppc64_runlatch_off(); - srr1 = power9_idle_stop(psscr, true); - __ppc64_runlatch_on(); -#else - /* - * Tell KVM we're entering idle. - * This does not have to be done in real mode because the P9 MMU - * is independent per-thread. Some steppings share radix/hash mode - * between threads, but in that case KVM has a barrier sync in real - * mode before and after switching between radix and hash. - * - * kvm_start_guest must still be called in real mode though, hence - * the false argument. - */ - local_paca->kvm_hstate.hwthread_state = KVM_HWTHREAD_IN_IDLE; - - __ppc64_runlatch_off(); - srr1 = power9_idle_stop(psscr, false); - __ppc64_runlatch_on(); - - local_paca->kvm_hstate.hwthread_state = KVM_HWTHREAD_IN_KERNEL; - /* Order setting hwthread_state vs. testing hwthread_req */ - smp_mb(); - if (local_paca->kvm_hstate.hwthread_req) - srr1 = idle_kvm_start_guest(srr1); - mtmsr(MSR_KERNEL); -#endif - - return srr1; -} -#endif - -void power9_idle_type(unsigned long stop_psscr_val, - unsigned long stop_psscr_mask) -{ - unsigned long psscr; - unsigned long srr1; - - if (!prep_irq_for_idle_irqsoff()) - return; - - psscr = mfspr(SPRN_PSSCR); - psscr = (psscr & ~stop_psscr_mask) | stop_psscr_val; - - __ppc64_runlatch_off(); - srr1 = power9_idle_stop(psscr, true); - __ppc64_runlatch_on(); - - fini_irq_for_idle_irqsoff(); - - irq_set_pending_from_srr1(srr1); -} - -/* - * Used for ppc_md.power_save which needs a function with no parameters - */ -void power9_idle(void) -{ - power9_idle_type(pnv_default_stop_val, pnv_default_stop_mask); -} - #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE /* * This is used in working around bugs in thread reconfiguration @@ -962,6 +877,198 @@ void pnv_power9_force_smt4_release(void) EXPORT_SYMBOL_GPL(pnv_power9_force_smt4_release); #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ +struct p10_sprs { + /* + * SPRs that get lost in shallow states: + * + * P10 loses CR, LR, CTR, FPSCR, VSCR, XER, TAR, SPRG2, and HSPRG1 + * isa300 idle routines restore CR, LR. + * CTR is volatile + * idle thread doesn't use FP or VEC + * kernel doesn't use TAR + * HSPRG1 is only live in HV interrupt entry + * SPRG2 is only live in KVM guests, KVM handles it. + */ +}; + +static unsigned long power10_idle_stop(unsigned long psscr, bool mmu_on) +{ + int cpu = raw_smp_processor_id(); + int first = cpu_first_thread_sibling(cpu); + unsigned long *state = &paca_ptrs[first]->idle_state; + unsigned long core_thread_mask = (1UL << threads_per_core) - 1; + unsigned long srr1; + unsigned long pls; +// struct p10_sprs sprs = {}; /* avoid false used-uninitialised */ + bool sprs_saved = false; + + if (!(psscr & (PSSCR_EC|PSSCR_ESL))) { + /* EC=ESL=0 case */ + + BUG_ON(!mmu_on); + + /* + * Wake synchronously. SRESET via xscom may still cause + * a 0x100 powersave wakeup with SRR1 reason! + */ + srr1 = isa300_idle_stop_noloss(psscr); /* go idle */ + if (likely(!srr1)) + return 0; + + /* + * Registers not saved, can't recover! + * This would be a hardware bug + */ + BUG_ON((srr1 & SRR1_WAKESTATE) != SRR1_WS_NOLOSS); + + goto out; + } + + /* EC=ESL=1 case */ + if ((psscr & PSSCR_RL_MASK) >= deep_spr_loss_state) { + /* XXX: save SPRs for deep state loss here. */ + + sprs_saved = true; + + atomic_start_thread_idle(); + } + + srr1 = isa300_idle_stop_mayloss(psscr); /* go idle */ + + psscr = mfspr(SPRN_PSSCR); + + WARN_ON_ONCE(!srr1); + WARN_ON_ONCE(mfmsr() & (MSR_IR|MSR_DR)); + + if (unlikely((srr1 & SRR1_WAKEMASK_P8) == SRR1_WAKEHMI)) + hmi_exception_realmode(NULL); + + /* + * On POWER10, SRR1 bits do not match exactly as expected. + * SRR1_WS_GPRLOSS (10b) can also result in SPR loss, so + * just always test PSSCR for SPR/TB state loss. + */ + pls = (psscr & PSSCR_PLS) >> PSSCR_PLS_SHIFT; + if (likely(pls < deep_spr_loss_state)) { + if (sprs_saved) + atomic_stop_thread_idle(); + goto out; + } + + /* HV state loss */ + BUG_ON(!sprs_saved); + + atomic_lock_thread_idle(); + + if ((*state & core_thread_mask) != 0) + goto core_woken; + + /* XXX: restore per-core SPRs here */ + + if (pls >= pnv_first_tb_loss_level) { + /* TB loss */ + if (opal_resync_timebase() != OPAL_SUCCESS) + BUG(); + } + + /* + * isync after restoring shared SPRs and before unlocking. Unlock + * only contains hwsync which does not necessarily do the right + * thing for SPRs. + */ + isync(); + +core_woken: + atomic_unlock_and_stop_thread_idle(); + + /* XXX: restore per-thread SPRs here */ + + if (!radix_enabled()) + __slb_restore_bolted_realmode(); + +out: + if (mmu_on) + mtmsr(MSR_KERNEL); + + return srr1; +} + +#ifdef CONFIG_HOTPLUG_CPU +static unsigned long arch300_offline_stop(unsigned long psscr) +{ + unsigned long srr1; + +#ifndef CONFIG_KVM_BOOK3S_HV_POSSIBLE + __ppc64_runlatch_off(); + if (cpu_has_feature(CPU_FTR_ARCH_31)) + srr1 = power10_idle_stop(psscr, true); + else + srr1 = power9_idle_stop(psscr, true); + __ppc64_runlatch_on(); +#else + /* + * Tell KVM we're entering idle. + * This does not have to be done in real mode because the P9 MMU + * is independent per-thread. Some steppings share radix/hash mode + * between threads, but in that case KVM has a barrier sync in real + * mode before and after switching between radix and hash. + * + * kvm_start_guest must still be called in real mode though, hence + * the false argument. + */ + local_paca->kvm_hstate.hwthread_state = KVM_HWTHREAD_IN_IDLE; + + __ppc64_runlatch_off(); + if (cpu_has_feature(CPU_FTR_ARCH_31)) + srr1 = power10_idle_stop(psscr, false); + else + srr1 = power9_idle_stop(psscr, false); + __ppc64_runlatch_on(); + + local_paca->kvm_hstate.hwthread_state = KVM_HWTHREAD_IN_KERNEL; + /* Order setting hwthread_state vs. testing hwthread_req */ + smp_mb(); + if (local_paca->kvm_hstate.hwthread_req) + srr1 = idle_kvm_start_guest(srr1); + mtmsr(MSR_KERNEL); +#endif + + return srr1; +} +#endif + +void arch300_idle_type(unsigned long stop_psscr_val, + unsigned long stop_psscr_mask) +{ + unsigned long psscr; + unsigned long srr1; + + if (!prep_irq_for_idle_irqsoff()) + return; + + psscr = mfspr(SPRN_PSSCR); + psscr = (psscr & ~stop_psscr_mask) | stop_psscr_val; + + __ppc64_runlatch_off(); + if (cpu_has_feature(CPU_FTR_ARCH_31)) + srr1 = power10_idle_stop(psscr, true); + else + srr1 = power9_idle_stop(psscr, true); + __ppc64_runlatch_on(); + + fini_irq_for_idle_irqsoff(); + + irq_set_pending_from_srr1(srr1); +} + +/* + * Used for ppc_md.power_save which needs a function with no parameters + */ +static void arch300_idle(void) +{ + arch300_idle_type(pnv_default_stop_val, pnv_default_stop_mask); +} + #ifdef CONFIG_HOTPLUG_CPU void pnv_program_cpu_hotplug_lpcr(unsigned int cpu, u64 lpcr_val) @@ -995,7 +1102,7 @@ unsigned long pnv_cpu_offline(unsigned int cpu) psscr = mfspr(SPRN_PSSCR); psscr = (psscr & ~pnv_deepest_stop_psscr_mask) | pnv_deepest_stop_psscr_val; - srr1 = power9_offline_stop(psscr); + srr1 = arch300_offline_stop(psscr); } else if (cpu_has_feature(CPU_FTR_ARCH_206) && power7_offline_type) { srr1 = power7_offline(); } else { @@ -1093,11 +1200,15 @@ int validate_psscr_val_mask(u64 *psscr_val, u64 *psscr_mask, u32 flags) * @dt_idle_states: Number of idle state entries * Returns 0 on success */ -static void __init pnv_power9_idle_init(void) +static void __init pnv_arch300_idle_init(void) { u64 max_residency_ns = 0; int i; + /* stop is not really architected, we only have p9,p10 drivers */ + if (!pvr_version_is(PVR_POWER10) && !pvr_version_is(PVR_POWER9)) + return; + /* * pnv_deepest_stop_{val,mask} should be set to values corresponding to * the deepest stop state. @@ -1112,6 +1223,11 @@ static void __init pnv_power9_idle_init(void) struct pnv_idle_states_t *state = &pnv_idle_states[i]; u64 psscr_rl = state->psscr_val & PSSCR_RL_MASK; + /* No deep loss driver implemented for POWER10 yet */ + if (pvr_version_is(PVR_POWER10) && + state->flags & (OPAL_PM_TIMEBASE_STOP|OPAL_PM_LOSE_FULL_CONTEXT)) + continue; + if ((state->flags & OPAL_PM_TIMEBASE_STOP) && (pnv_first_tb_loss_level > psscr_rl)) pnv_first_tb_loss_level = psscr_rl; @@ -1162,7 +1278,7 @@ static void __init pnv_power9_idle_init(void) if (unlikely(!default_stop_found)) { pr_warn("cpuidle-powernv: No suitable default stop state found. Disabling platform idle.\n"); } else { - ppc_md.power_save = power9_idle; + ppc_md.power_save = arch300_idle; pr_info("cpuidle-powernv: Default stop: psscr = 0x%016llx,mask=0x%016llx\n", pnv_default_stop_val, pnv_default_stop_mask); } @@ -1224,7 +1340,7 @@ static void __init pnv_probe_idle_states(void) } if (cpu_has_feature(CPU_FTR_ARCH_300)) - pnv_power9_idle_init(); + pnv_arch300_idle_init(); for (i = 0; i < nr_pnv_idle_states; i++) supported_cpuidle_states |= pnv_idle_states[i].flags; @@ -1295,7 +1411,7 @@ static int pnv_parse_cpuidle_dt(void) for (i = 0; i < nr_idle_states; i++) pnv_idle_states[i].residency_ns = temp_u32[i]; - /* For power9 */ + /* For power9 and later */ if (cpu_has_feature(CPU_FTR_ARCH_300)) { /* Read pm_crtl_val */ if (of_property_read_u64_array(np, "ibm,cpu-idle-state-psscr", @@ -1358,8 +1474,8 @@ static int __init pnv_init_idle_states(void) if (!cpu_has_feature(CPU_FTR_ARCH_300)) { /* P7/P8 nap */ p->thread_idle_state = PNV_THREAD_RUNNING; - } else { - /* P9 stop */ + } else if (pvr_version_is(PVR_POWER9)) { + /* P9 stop workarounds */ #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE p->requested_psscr = 0; atomic_set(&p->dont_stop, 0); diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c index addaa6e6718b..c32c600b3cf8 100644 --- a/drivers/cpuidle/cpuidle-powernv.c +++ b/drivers/cpuidle/cpuidle-powernv.c @@ -141,7 +141,7 @@ static int stop_loop(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - power9_idle_type(stop_psscr_table[index].val, + arch300_idle_type(stop_psscr_table[index].val, stop_psscr_table[index].mask); return index; } -- cgit v1.2.3 From 8f7e57e8e29c4fc788811dd4db96126272b8df91 Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Mon, 14 Sep 2020 14:14:11 +0800 Subject: macintosh: windfarm: use for_each_child_of_node() macro Use for_each_child_of_node() macro instead of open coding it. Signed-off-by: Qinglang Miao Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200914061411.3356-1-miaoqinglang@huawei.com --- drivers/macintosh/windfarm_smu_sat.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index cb75dc035616..e46e1153a0b4 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c @@ -216,8 +216,7 @@ static int wf_sat_probe(struct i2c_client *client, vsens[0] = vsens[1] = -1; isens[0] = isens[1] = -1; - child = NULL; - while ((child = of_get_next_child(dev, child)) != NULL) { + for_each_child_of_node(dev, child) { reg = of_get_property(child, "reg", NULL); loc = of_get_property(child, "location", NULL); if (reg == NULL || loc == NULL) -- cgit v1.2.3 From 3db8715ec9dc1d32ecafc67af9fb96508c98efe5 Mon Sep 17 00:00:00 2001 From: Wang Wensheng Date: Mon, 14 Sep 2020 12:26:15 +0000 Subject: drivers/macintosh/smu.c: Fix undeclared symbol warning Make kernel with `C=2`: drivers/macintosh/smu.c:1018:30: warning: symbol '__smu_get_sdb_partition' was not declared. Should it be static? Reported-by: Hulk Robot Signed-off-by: Wang Wensheng Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200914122615.65669-1-wangwensheng4@huawei.com --- drivers/macintosh/smu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 23f1f41c8602..ca2a0bc5c33e 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -1015,7 +1015,7 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id) /* Note: Only allowed to return error code in pointers (using ERR_PTR) * when interruptible is 1 */ -const struct smu_sdbp_header *__smu_get_sdb_partition(int id, +static const struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, int interruptible) { char pname[32]; -- cgit v1.2.3 From 9c826d31a73815464bd3df81e56d39b3d908ac73 Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Wed, 16 Sep 2020 14:21:22 +0800 Subject: drivers/macintosh/smu.c: use for_each_child_of_node() macro Use for_each_child_of_node() macro instead of open coding it. Signed-off-by: Qinglang Miao Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200916062122.190586-1-miaoqinglang@huawei.com --- drivers/macintosh/smu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index ca2a0bc5c33e..51b6f2aa5291 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -638,7 +638,7 @@ static void smu_expose_childs(struct work_struct *unused) { struct device_node *np; - for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) + for_each_child_of_node(smu->of_node, np) if (of_device_is_compatible(np, "smu-sensors")) of_platform_device_create(np, "smu-sensors", &smu->of_dev->dev); -- cgit v1.2.3 From acff5e6c37fa4bf8d002c917a762c4f7615f6eaf Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Wed, 16 Sep 2020 14:21:25 +0800 Subject: macintosh: smu_sensors: use for_each_child_of_node() macro Use for_each_child_of_node() macro instead of open coding it. Signed-off-by: Qinglang Miao Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200916062125.190729-1-miaoqinglang@huawei.com --- drivers/macintosh/windfarm_smu_sensors.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c index 3e6059eaa138..c8706cfb83fd 100644 --- a/drivers/macintosh/windfarm_smu_sensors.c +++ b/drivers/macintosh/windfarm_smu_sensors.c @@ -421,8 +421,7 @@ static int __init smu_sensors_init(void) return -ENODEV; /* Look for sensors subdir */ - for (sensors = NULL; - (sensors = of_get_next_child(smu, sensors)) != NULL;) + for_each_child_of_node(smu, sensors) if (of_node_name_eq(sensors, "sensors")) break; -- cgit v1.2.3 From 1d42e07e9c249b7a032fba82b673ee8a8d6bd7b7 Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Wed, 16 Sep 2020 14:21:38 +0800 Subject: serial: pmac_zilog: use for_each_child_of_node() macro Use for_each_child_of_node() macro instead of open coding it. Signed-off-by: Qinglang Miao Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200916062138.191188-1-miaoqinglang@huawei.com --- drivers/tty/serial/pmac_zilog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index 96e7aa479961..063484b22523 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -1644,7 +1644,7 @@ static int __init pmz_probe(void) * TODO: Add routines with proper locking to do that... */ node_a = node_b = NULL; - for (np = NULL; (np = of_get_next_child(node_p, np)) != NULL;) { + for_each_child_of_node(node_p, np) { if (of_node_name_prefix(np, "ch-a")) node_a = of_node_get(np); else if (of_node_name_prefix(np, "ch-b")) -- cgit v1.2.3 From a2d0230b91f7e23ceb5d8fb6a9799f30517ec33a Mon Sep 17 00:00:00 2001 From: Srikar Dronamraju Date: Tue, 22 Sep 2020 13:32:54 +0530 Subject: cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_reboot_notifier The patch avoids allocating cpufreq_policy on stack hence fixing frame size overflow in 'powernv_cpufreq_reboot_notifier': drivers/cpufreq/powernv-cpufreq.c: In function powernv_cpufreq_reboot_notifier: drivers/cpufreq/powernv-cpufreq.c:906:1: error: the frame size of 2064 bytes is larger than 2048 bytes Fixes: cf30af76 ("cpufreq: powernv: Set the cpus to nominal frequency during reboot/kexec") Signed-off-by: Srikar Dronamraju Reviewed-by: Daniel Axtens Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200922080254.41497-1-srikar@linux.vnet.ibm.com --- drivers/cpufreq/powernv-cpufreq.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index a9af15e994cc..e439b43c19eb 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -885,12 +885,15 @@ static int powernv_cpufreq_reboot_notifier(struct notifier_block *nb, unsigned long action, void *unused) { int cpu; - struct cpufreq_policy cpu_policy; + struct cpufreq_policy *cpu_policy; rebooting = true; for_each_online_cpu(cpu) { - cpufreq_get_policy(&cpu_policy, cpu); - powernv_cpufreq_target_index(&cpu_policy, get_nominal_index()); + cpu_policy = cpufreq_cpu_get(cpu); + if (!cpu_policy) + continue; + powernv_cpufreq_target_index(cpu_policy, get_nominal_index()); + cpufreq_cpu_put(cpu_policy); } return NOTIFY_DONE; -- cgit v1.2.3