linux/arch/powerpc/sysdev
Balbir Singh 1ced52ead2 powerpc/xics: Work around limitations of OPAL XICS priority handling
commit a69e2fb703 upstream.

The CPPR (Current Processor Priority Register) of a XICS interrupt
presentation controller contains a value N, such that only interrupts
with a priority "more favoured" than N will be received by the CPU,
where "more favoured" means "less than". So if the CPPR has the value 5
then only interrupts with a priority of 0-4 inclusive will be received.

In theory the CPPR can support a value of 0 to 255 inclusive.
In practice Linux only uses values of 0, 4, 5 and 0xff. Setting the CPPR
to 0 rejects all interrupts, setting it to 0xff allows all interrupts.
The values 4 and 5 are used to differentiate IPIs from external
interrupts. Setting the CPPR to 5 allows IPIs to be received but not
external interrupts.

The CPPR emulation in the OPAL XICS implementation only directly
supports priorities 0 and 0xff. All other priorities are considered
equivalent, and mapped to a single priority value internally. This means
when using icp-opal we can not allow IPIs but not externals.

This breaks Linux's use of priority values when a CPU is hot unplugged.
After migrating IRQs away from the CPU that is being offlined, we set
the priority to 5, meaning we still want the offline CPU to receive
IPIs. But the effect of the OPAL XICS emulation's use of a single
priority value is that all interrupts are rejected by the CPU. With the
CPU offline, and not receiving IPIs, we may not be able to wake it up to
bring it back online.

The first part of the fix is in icp_opal_set_cpu_priority(). CPPR values
of 0 to 4 inclusive will correctly cause all interrupts to be rejected,
so we pass those CPPR values through to OPAL. However if we are called
with a CPPR of 5 or greater, the caller is expecting to be able to allow
IPIs but not external interrupts. We know this doesn't work, so instead
of rejecting all interrupts we choose the opposite which is to allow all
interrupts. This is still not correct behaviour, but we know for the
only existing caller (xics_migrate_irqs_away()), that it is the better
option.

The other part of the fix is in xics_migrate_irqs_away(). Instead of
setting priority (CPPR) to 0, and then back to 5 before migrating IRQs,
we migrate the IRQs before setting the priority back to 5. This should
have no effect on an ICP backend with a working set_priority(), and on
icp-opal it means we will keep all interrupts blocked until after we've
finished doing the IRQ migration. Additionally we wait for 5ms after
doing the migration to make sure there are no IRQs in flight.

Fixes: d74361881f ("powerpc/xics: Add ICP OPAL backend")
Suggested-by: Michael Ellerman <mpe@ellerman.id.au>
Reported-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Tested-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Signed-off-by: Balbir Singh <bsingharora@gmail.com>
[mpe: Rewrote comments and change log, change delay to 5ms]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
History 2017-03-18 19:14:30 +08:00
..
ge powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
xics powerpc/xics: Work around limitations of OPAL XICS priority handling 2017-03-18 19:14:30 +08:00
6xx-suspend.S powerpc: Use CURRENT_THREAD_INFO instead of open coded assembly 2012-07-11 14:18:22 +10:00
axonram.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
cpm1.c soc/fsl/qe: fix Oops on CPM1 (and likely CPM2) 2016-09-25 02:38:52 -05:00
cpm2.c soc/fsl/qe: fix Oops on CPM1 (and likely CPM2) 2016-09-25 02:38:52 -05:00
cpm2_pic.c powerpc/cpm2: Use irq_set_handler_locked() 2015-09-16 15:43:10 +02:00
cpm2_pic.h powerpc/cpm2: Checkpatch cleanup 2010-03-04 10:43:58 -06:00
cpm_common.c soc/fsl/qe: fix Oops on CPM1 (and likely CPM2) 2016-09-25 02:38:52 -05:00
dart.h [POWERPC] Use 4kB iommu pages even on 64kB-page systems 2006-11-01 14:52:48 +11:00
dart_iommu.c dma-mapping: use unsigned long for dma_attrs 2016-08-04 08:50:07 -04:00
dcr-low.S ppc: move exports to definitions 2016-08-07 23:50:09 -04:00
dcr.c powerpc: Use bool function return values of true/false not 1/0 2015-03-31 14:19:47 +11:00
ehv_pic.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
fsl_85xx_cache_ctlr.h powerpc/85xx: Fix sram_offset parameter type 2012-07-26 13:24:32 -05:00
fsl_85xx_cache_sram.c powerpc/85xx: Fix compiler error with THIS_MODULE and related 2012-03-16 14:50:25 -05:00
fsl_85xx_l2ctlr.c powerpc/85xx: Don't report SRAM to L2 cache fallback as error 2016-07-08 19:55:34 -05:00
fsl_gtm.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
fsl_lbc.c powerpc/fsl-lbc: Modify suspend/resume entry sequence 2016-03-09 10:44:17 -06:00
fsl_mpic_err.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
fsl_mpic_timer_wakeup.c powerpc/fsl: add MPIC timer wakeup support 2013-07-01 18:38:42 -05:00
fsl_msi.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
fsl_msi.h powerpc/85xx: workaround for chips with MSI hardware errata 2015-03-23 19:51:18 -05:00
fsl_pci.c powerpc/fsl_pci: Size upper inbound window based on RAM size 2016-09-25 02:38:54 -05:00
fsl_pci.h EDAC, mpc85xx: Make mpc85xx-pci-edac a platform device 2015-12-11 16:56:16 +01:00
fsl_pmc.c powerpc: sysdev: drop owner assignment from platform_drivers 2014-10-20 16:20:13 +02:00
fsl_rcpm.c powerpc/rcpm: Fix build break when SMP=n 2016-03-16 15:22:32 +11:00
fsl_rio.c powerpc: migrate exception table users off module.h and onto extable.h 2016-08-22 11:09:33 +10:00
fsl_rio.h rapidio: add global inbound port write interfaces 2016-03-22 15:36:02 -07:00
fsl_rmu.c rapidio: add global inbound port write interfaces 2016-03-22 15:36:02 -07:00
fsl_soc.c powerpc: Convert fsl_rstcr_restart to a reset handler 2016-09-25 02:38:50 -05:00
fsl_soc.h powerpc: Convert fsl_rstcr_restart to a reset handler 2016-09-25 02:38:50 -05:00
grackle.c powerpc: rename ppc_pci_*_flags to pci_*_flags 2011-07-12 09:28:04 -05:00
i8259.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
indirect_pci.c powerpc/fsl_pci: Fix pci stack build bug with FRAME_WARN 2015-01-29 19:56:15 -06:00
ipic.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
ipic.h irq_domain/powerpc: Use common irq_domain structure instead of irq_host 2012-02-14 14:06:50 -07:00
Kconfig powerpc/rcpm: add RCPM driver 2016-03-04 23:50:27 -06:00
Makefile powerpc/rcpm: add RCPM driver 2016-03-04 23:50:27 -06:00
micropatch.c powerpc/8xx: Remove empty asm/mpc8xx.h 2014-06-25 18:49:40 -05:00
mmio_nvram.c powerpc/sparse: Make a bunch of things static 2016-09-13 17:35:47 +10:00
mpc5xxx_clocks.c powerpc/mpc5xxx: Use of_get_next_parent to simplify code 2015-10-15 20:32:01 +11:00
mpc8xx_pic.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
mpc8xx_pic.h [POWERPC] 8xx: mpc885ads pcmcia support 2007-07-10 00:33:51 -05:00
mpic.c powerpc/mpic: use of_property_read_bool 2016-09-25 02:38:51 -05:00
mpic.h powerpc/pasemi: Only the build the pasemi MSI code for PASEMI=y 2015-05-11 19:55:25 +10:00
mpic_msgr.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
mpic_msi.c irqdomain: Use irq_domain_get_of_node() instead of direct field access 2015-10-13 19:01:23 +02:00
mpic_timer.c powerpc/mpic_timer: fix convert ticks to time subtraction overflow 2014-01-09 17:52:14 -06:00
mpic_u3msi.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
msi_bitmap.c treewide: replace obsolete _refok by __ref 2016-08-02 17:31:41 -04:00
mv64x60.h [POWERPC] Add Marvell mv64x60 udbg putc/getc functions 2007-09-22 14:49:21 +10:00
mv64x60_dev.c powerpc: make of_device_ids const 2014-09-25 23:14:46 +10:00
mv64x60_pci.c POWERPC: drivers: remove __dev* attributes. 2013-01-03 15:57:04 -08:00
mv64x60_pic.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
mv64x60_udbg.c dt/bindings: Remove device_type "serial" from marvell,mv64360-mpsc 2014-01-16 16:31:31 +00:00
of_rtc.c powerpc: add explicit OF includes 2013-10-09 20:04:11 -05:00
pmi.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
ppc4xx_cpm.c powerpc/4xx/cpm: delete unneeded test before of_node_put 2014-11-10 09:59:34 +11:00
ppc4xx_gpio.c powerpc: ppc4xx: drop unused variable 2016-03-31 09:14:22 +02:00
ppc4xx_hsta_msi.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
ppc4xx_msi.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
ppc4xx_ocm.c powerpc/44x: Fix ocm_block allocation 2013-12-10 11:25:04 +11:00
ppc4xx_pci.c powerpc: Remove superfluous bootmem includes 2014-11-10 09:59:26 +11:00
ppc4xx_pci.h powerpc/476fpe: Add 476fpe SoC code 2011-12-09 07:51:02 -05:00
ppc4xx_soc.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
rtc_cmos_setup.c PTR_RET is now PTR_ERR_OR_ZERO(): Replace most. 2013-07-15 11:25:01 +09:30
scom.c powerpc/scom: Improve debugfs interface 2013-11-06 14:13:50 +11:00
simple_gpio.c powerpc: simple-gpio: use gpiochip data pointer 2016-03-30 10:53:23 +02:00
simple_gpio.h powerpc: Implement GPIO driver for simple memory-mapped banks 2008-12-30 11:13:45 -06:00
tsi108_dev.c Disintegrate asm/system.h for PowerPC 2012-03-28 18:30:02 +01:00
tsi108_pci.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
udbg_memcons.c powerpc: Delete non-required instances of include <linux/init.h> 2014-01-15 13:46:44 +11:00
uic.c powerpc: Remove all usages of NO_IRQ 2016-09-20 20:57:12 +10:00
xilinx_intc.c genirq: Remove irq argument from irq flow handlers 2015-09-16 15:47:51 +02:00
xilinx_pci.c powerpc: make of_device_ids const 2014-09-25 23:14:46 +10:00