summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-30 21:01:36 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-30 21:01:36 -0700
commitbad60e6f259a01cf9f29a1ef8d435ab6c60b2de9 (patch)
treec9aaa8166735659761239c117af2b11b022bc6cb /arch/powerpc/platforms
parentdd0f0cf58af70dc9267409f113bea772d57f675c (diff)
parent719dbb2df78fc9a40e28392b07cd715bfc5a665c (diff)
downloadlinux-bad60e6f259a01cf9f29a1ef8d435ab6c60b2de9.tar.gz
linux-bad60e6f259a01cf9f29a1ef8d435ab6c60b2de9.tar.bz2
linux-bad60e6f259a01cf9f29a1ef8d435ab6c60b2de9.zip
Merge tag 'powerpc-4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc updates from Michael Ellerman: "Highlights: - PowerNV PCI hotplug support. - Lots more Power9 support. - eBPF JIT support on ppc64le. - Lots of cxl updates. - Boot code consolidation. Bug fixes: - Fix spin_unlock_wait() from Boqun Feng - Fix stack pointer corruption in __tm_recheckpoint() from Michael Neuling - Fix multiple bugs in memory_hotplug_max() from Bharata B Rao - mm: Ensure "special" zones are empty from Oliver O'Halloran - ftrace: Separate the heuristics for checking call sites from Michael Ellerman - modules: Never restore r2 for a mprofile-kernel style mcount() call from Michael Ellerman - Fix endianness when reading TCEs from Alexey Kardashevskiy - start rtasd before PCI probing from Greg Kurz - PCI: rpaphp: Fix slot registration for multiple slots under a PHB from Tyrel Datwyler - powerpc/mm: Add memory barrier in __hugepte_alloc() from Sukadev Bhattiprolu Cleanups & fixes: - Drop support for MPIC in pseries from Rashmica Gupta - Define and use PPC64_ELF_ABI_v2/v1 from Michael Ellerman - Remove unused symbols in asm-offsets.c from Rashmica Gupta - Fix SRIOV not building without EEH enabled from Russell Currey - Remove kretprobe_trampoline_holder from Thiago Jung Bauermann - Reduce log level of PCI I/O space warning from Benjamin Herrenschmidt - Add array bounds checking to crash_shutdown_handlers from Suraj Jitindar Singh - Avoid -maltivec when using clang integrated assembler from Anton Blanchard - Fix array overrun in ppc_rtas() syscall from Andrew Donnellan - Fix error return value in cmm_mem_going_offline() from Rasmus Villemoes - export cpu_to_core_id() from Mauricio Faria de Oliveira - Remove old symbols from defconfigs from Andrew Donnellan - Update obsolete comments in setup_32.c about entry conditions from Benjamin Herrenschmidt - Add comment explaining the purpose of setup_kdump_trampoline() from Benjamin Herrenschmidt - Merge the RELOCATABLE config entries for ppc32 and ppc64 from Kevin Hao - Remove RELOCATABLE_PPC32 from Kevin Hao - Fix .long's in tlb-radix.c to more meaningful from Balbir Singh Minor cleanups & fixes: - Andrew Donnellan, Anna-Maria Gleixner, Anton Blanchard, Benjamin Herrenschmidt, Bharata B Rao, Christophe Leroy, Colin Ian King, Geliang Tang, Greg Kurz, Madhavan Srinivasan, Michael Ellerman, Michael Ellerman, Stephen Rothwell, Stewart Smith. Freescale updates from Scott: - "Highlights include more 8xx optimizations, device tree updates, and MVME7100 support." PowerNV PCI hotplug from Gavin Shan: - PCI: Add pcibios_setup_bridge() - Override pcibios_setup_bridge() - Remove PCI_RESET_DELAY_US - Move pnv_pci_ioda_setup_opal_tce_kill() around - Increase PE# capacity - Allocate PE# in reverse order - Create PEs in pcibios_setup_bridge() - Setup PE for root bus - Extend PCI bridge resources - Make pnv_ioda_deconfigure_pe() visible - Dynamically release PE - Update bridge windows on PCI plug - Delay populating pdn - Support PCI slot ID - Use PCI slot reset infrastructure - Introduce pnv_pci_get_slot_id() - Functions to get/set PCI slot state - PCI/hotplug: PowerPC PowerNV PCI hotplug driver - Print correct PHB type names Power9 idle support from Shreyas B. Prabhu: - set power_save func after the idle states are initialized - Use PNV_THREAD_WINKLE macro while requesting for winkle - make hypervisor state restore a function - Rename idle_power7.S to idle_book3s.S - Rename reusable idle functions to hardware agnostic names - Make pnv_powersave_common more generic - abstraction for saving SPRs before entering deep idle states - Add platform support for stop instruction - cpuidle/powernv: Use CPUIDLE_STATE_MAX instead of MAX_POWERNV_IDLE_STATES - cpuidle/powernv: cleanup cpuidle-powernv.c - cpuidle/powernv: Add support for POWER ISA v3 idle states - Use deepest stop state when cpu is offlined Power9 PMU from Madhavan Srinivasan: - factor out power8 pmu macros and defines - factor out power8 pmu functions - factor out power8 __init_pmu code - Add power9 event list macros for generic and cache events - Power9 PMU support - Export Power9 generic and cache events to sysfs Power9 preliminary interrupt & PCI support from Benjamin Herrenschmidt: - Add XICS emulation APIs - Move a few exception common handlers to make room - Add support for HV virtualization interrupts - Add mechanism to force a replay of interrupts - Add ICP OPAL backend - Discover IODA3 PHBs - pci: Remove obsolete SW invalidate - opal: Add real mode call wrappers - Rename TCE invalidation calls - Remove SWINV constants and obsolete TCE code - Rework accessing the TCE invalidate register - Fallback to OPAL for TCE invalidations - Use the device-tree to get available range of M64's - Check status of a PHB before using it - pci: Don't try to allocate resources that will be reassigned Other Power9: - Send SIGBUS on unaligned copy and paste from Chris Smart - Large Decrementer support from Oliver O'Halloran - Load Monitor Register Support from Jack Miller Performance improvements from Anton Blanchard: - Avoid load hit store in __giveup_fpu() and __giveup_altivec() - Avoid load hit store in setup_sigcontext() - Remove assembly versions of strcpy, strcat, strlen and strcmp - Align hot loops of some string functions eBPF JIT from Naveen N. Rao: - Fix/enhance 32-bit Load Immediate implementation - Optimize 64-bit Immediate loads - Introduce rotate immediate instructions - A few cleanups - Isolate classic BPF JIT specifics into a separate header - Implement JIT compiler for extended BPF Operator Panel driver from Suraj Jitindar Singh: - devicetree/bindings: Add binding for operator panel on FSP machines - Add inline function to get rc from an ASYNC_COMP opal_msg - Add driver for operator panel on FSP machines Sparse fixes from Daniel Axtens: - make some things static - Introduce asm-prototypes.h - Include headers containing prototypes - Use #ifdef __BIG_ENDIAN__ #else for REG_BYTE - kvm: Clarify __user annotations - Pass endianness to sparse - Make ppc_md.{halt, restart} __noreturn MM fixes & cleanups from Aneesh Kumar K.V: - radix: Update LPCR HR bit as per ISA - use _raw variant of page table accessors - Compile out radix related functions if RADIX_MMU is disabled - Clear top 16 bits of va only on older cpus - Print formation regarding the the MMU mode - hash: Update SDR1 size encoding as documented in ISA 3.0 - radix: Update PID switch sequence - radix: Update machine call back to support new HCALL. - radix: Add LPID based tlb flush helpers - radix: Add a kernel command line to disable radix - Cleanup LPCR defines Boot code consolidation from Benjamin Herrenschmidt: - Move epapr_paravirt_early_init() to early_init_devtree() - cell: Don't use flat device-tree after boot - ge_imp3a: Don't use the flat device-tree after boot - mpc85xx_ds: Don't use the flat device-tree after boot - mpc85xx_rdb: Don't use the flat device-tree after boot - Don't test for machine type in rtas_initialize() - Don't test for machine type in smp_setup_cpu_maps() - dt: Add of_device_compatible_match() - Factor do_feature_fixup calls - Move 64-bit feature fixup earlier - Move 64-bit memory reserves to setup_arch() - Use a cachable DART - Move FW feature probing out of pseries probe() - Put exception configuration in a common place - Remove early allocation of the SMU command buffer - Move MMU backend selection out of platform code - pasemi: Remove IOBMAP allocation from platform probe() - mm/hash: Don't use machine_is() early during boot - Don't test for machine type to detect HEA special case - pmac: Remove spurrious machine type test - Move hash table ops to a separate structure - Ensure that ppc_md is empty before probing for machine type - Move 64-bit probe_machine() to later in the boot process - Move 32-bit probe() machine to later in the boot process - Get rid of ppc_md.init_early() - Move the boot time info banner to a separate function - Move setting of {i,d}cache_bsize to initialize_cache_info() - Move the content of setup_system() to setup_arch() - Move cache info inits to a separate function - Re-order the call to smp_setup_cpu_maps() - Re-order setup_panic() - Make a few boot functions __init - Merge 32-bit and 64-bit setup_arch() Other new features: - tty/hvc: Use IRQF_SHARED for OPAL hvc consoles from Sam Mendoza-Jonas - tty/hvc: Use opal irqchip interface if available from Sam Mendoza-Jonas - powerpc: Add module autoloading based on CPU features from Alastair D'Silva - crypto: vmx - Convert to CPU feature based module autoloading from Alastair D'Silva - Wake up kopald polling thread before waiting for events from Benjamin Herrenschmidt - xmon: Dump ISA 2.06 SPRs from Michael Ellerman - xmon: Dump ISA 2.07 SPRs from Michael Ellerman - Add a parameter to disable 1TB segs from Oliver O'Halloran - powerpc/boot: Add OPAL console to epapr wrappers from Oliver O'Halloran - Assign fixed PHB number based on device-tree properties from Guilherme G. Piccoli - pseries: Add pseries hotplug workqueue from John Allen - pseries: Add support for hotplug interrupt source from John Allen - pseries: Use kernel hotplug queue for PowerVM hotplug events from John Allen - pseries: Move property cloning into its own routine from Nathan Fontenot - pseries: Dynamic add entires to associativity lookup array from Nathan Fontenot - pseries: Auto-online hotplugged memory from Nathan Fontenot - pseries: Remove call to memblock_add() from Nathan Fontenot cxl: - Add set and get private data to context struct from Michael Neuling - make base more explicitly non-modular from Paul Gortmaker - Use for_each_compatible_node() macro from Wei Yongjun - Frederic Barrat - Abstract the differences between the PSL and XSL - Make vPHB device node match adapter's - Philippe Bergheaud - Add mechanism for delivering AFU driver specific events - Ignore CAPI adapters misplaced in switched slots - Refine slice error debug messages - Andrew Donnellan - static-ify variables to fix sparse warnings - PCI/hotplug: pnv_php: export symbols and move struct types needed by cxl - PCI/hotplug: pnv_php: handle OPAL_PCI_SLOT_OFFLINE power state - Add cxl_check_and_switch_mode() API to switch bi-modal cards - remove dead Kconfig options - fix potential NULL dereference in free_adapter() - Ian Munsie - Update process element after allocating interrupts - Add support for CAPP DMA mode - Fix allowing bogus AFU descriptors with 0 maximum processes - Fix allocating a minimum of 2 pages for the SPA - Fix bug where AFU disable operation had no effect - Workaround XSL bug that does not clear the RA bit after a reset - Fix NULL pointer dereference on kernel contexts with no AFU interrupts - powerpc/powernv: Split cxl code out into a separate file - Add cxl_slot_is_supported API - Enable bus mastering for devices using CAPP DMA mode - Move cxl_afu_get / cxl_afu_put to base - Allow a default context to be associated with an external pci_dev - Do not create vPHB if there are no AFU configuration records - powerpc/powernv: Add support for the cxl kernel api on the real phb - Add support for using the kernel API with a real PHB - Add kernel APIs to get & set the max irqs per context - Add preliminary workaround for CX4 interrupt limitation - Add support for interrupts on the Mellanox CX4 - Workaround PE=0 hardware limitation in Mellanox CX4 - powerpc/powernv: Fix pci-cxl.c build when CONFIG_MODULES=n selftests: - Test unaligned copy and paste from Chris Smart - Load Monitor Register Tests from Jack Miller - Cyril Bur - exec() with suspended transaction - Use signed long to read perf_event_paranoid - Fix usage message in context_switch - Fix generation of vector instructions/types in context_switch - Michael Ellerman - Use "Delta" rather than "Error" in normal output - Import Anton's mmap & futex micro benchmarks - Add a test for PROT_SAO" * tag 'powerpc-4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (263 commits) powerpc/mm: Parenthesise IS_ENABLED() in if condition tty/hvc: Use opal irqchip interface if available tty/hvc: Use IRQF_SHARED for OPAL hvc consoles selftests/powerpc: exec() with suspended transaction powerpc: Improve comment explaining why we modify VRSAVE powerpc/mm: Drop unused externs for hpte_init_beat[_v3]() powerpc/mm: Rename hpte_init_lpar() and move the fallback to a header powerpc/mm: Fix build break when PPC_NATIVE=n crypto: vmx - Convert to CPU feature based module autoloading powerpc: Add module autoloading based on CPU features powerpc/powernv/ioda: Fix endianness when reading TCEs powerpc/mm: Add memory barrier in __hugepte_alloc() powerpc/modules: Never restore r2 for a mprofile-kernel style mcount() call powerpc/ftrace: Separate the heuristics for checking call sites powerpc: Merge 32-bit and 64-bit setup_arch() powerpc/64: Make a few boot functions __init powerpc: Re-order setup_panic() powerpc: Re-order the call to smp_setup_cpu_maps() powerpc/32: Move cache info inits to a separate function powerpc/64: Move the content of setup_system() to setup_arch() ...
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/40x/ep405.c4
-rw-r--r--arch/powerpc/platforms/40x/ppc40x_simple.c2
-rw-r--r--arch/powerpc/platforms/40x/virtex.c4
-rw-r--r--arch/powerpc/platforms/40x/walnut.c4
-rw-r--r--arch/powerpc/platforms/44x/canyonlands.c5
-rw-r--r--arch/powerpc/platforms/44x/ebony.c4
-rw-r--r--arch/powerpc/platforms/44x/iss4xx.c4
-rw-r--r--arch/powerpc/platforms/44x/ppc44x_simple.c3
-rw-r--r--arch/powerpc/platforms/44x/ppc476.c10
-rw-r--r--arch/powerpc/platforms/44x/sam440ep.c4
-rw-r--r--arch/powerpc/platforms/44x/virtex.c4
-rw-r--r--arch/powerpc/platforms/44x/warp.c4
-rw-r--r--arch/powerpc/platforms/512x/clock-commonclk.c2
-rw-r--r--arch/powerpc/platforms/512x/mpc5121_ads.c8
-rw-r--r--arch/powerpc/platforms/512x/mpc512x.h2
-rw-r--r--arch/powerpc/platforms/512x/mpc512x_generic.c8
-rw-r--r--arch/powerpc/platforms/512x/mpc512x_shared.c2
-rw-r--r--arch/powerpc/platforms/512x/pdm360ng.c8
-rw-r--r--arch/powerpc/platforms/52xx/efika.c3
-rw-r--r--arch/powerpc/platforms/52xx/lite5200.c2
-rw-r--r--arch/powerpc/platforms/52xx/media5200.c2
-rw-r--r--arch/powerpc/platforms/52xx/mpc5200_simple.c2
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c3
-rw-r--r--arch/powerpc/platforms/82xx/ep8248e.c3
-rw-r--r--arch/powerpc/platforms/82xx/km82xx.c3
-rw-r--r--arch/powerpc/platforms/82xx/mpc8272_ads.c3
-rw-r--r--arch/powerpc/platforms/82xx/pq2.c2
-rw-r--r--arch/powerpc/platforms/82xx/pq2.h2
-rw-r--r--arch/powerpc/platforms/82xx/pq2fads.c3
-rw-r--r--arch/powerpc/platforms/83xx/asp834x.c3
-rw-r--r--arch/powerpc/platforms/83xx/km83xx.c3
-rw-r--r--arch/powerpc/platforms/83xx/misc.c2
-rw-r--r--arch/powerpc/platforms/83xx/mpc830x_rdb.c2
-rw-r--r--arch/powerpc/platforms/83xx/mpc831x_rdb.c2
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_rdb.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_mds.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_mds.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_rdk.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc837x_mds.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc837x_rdb.c2
-rw-r--r--arch/powerpc/platforms/83xx/mpc83xx.h2
-rw-r--r--arch/powerpc/platforms/83xx/sbc834x.c4
-rw-r--r--arch/powerpc/platforms/85xx/bsc913x_qds.c4
-rw-r--r--arch/powerpc/platforms/85xx/bsc913x_rdb.c4
-rw-r--r--arch/powerpc/platforms/85xx/c293pcie.c4
-rw-r--r--arch/powerpc/platforms/85xx/corenet_generic.c5
-rw-r--r--arch/powerpc/platforms/85xx/ge_imp3a.c7
-rw-r--r--arch/powerpc/platforms/85xx/ksi8560.c6
-rw-r--r--arch/powerpc/platforms/85xx/mpc8536_ds.c4
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c4
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.c6
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ds.c16
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c12
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_rdb.c43
-rw-r--r--arch/powerpc/platforms/85xx/mvme2500.c4
-rw-r--r--arch/powerpc/platforms/85xx/p1010rdb.c6
-rw-r--r--arch/powerpc/platforms/85xx/p1022_ds.c4
-rw-r--r--arch/powerpc/platforms/85xx/p1022_rdk.c4
-rw-r--r--arch/powerpc/platforms/85xx/p1023_rdb.c4
-rw-r--r--arch/powerpc/platforms/85xx/ppa8548.c4
-rw-r--r--arch/powerpc/platforms/85xx/qemu_e500.c4
-rw-r--r--arch/powerpc/platforms/85xx/sbc8548.c4
-rw-r--r--arch/powerpc/platforms/85xx/socrates.c4
-rw-r--r--arch/powerpc/platforms/85xx/stx_gp3.c4
-rw-r--r--arch/powerpc/platforms/85xx/tqm85xx.c2
-rw-r--r--arch/powerpc/platforms/85xx/twr_p102x.c4
-rw-r--r--arch/powerpc/platforms/85xx/xes_mpc85xx.c12
-rw-r--r--arch/powerpc/platforms/86xx/Kconfig8
-rw-r--r--arch/powerpc/platforms/86xx/Makefile1
-rw-r--r--arch/powerpc/platforms/86xx/gef_ppc9a.c4
-rw-r--r--arch/powerpc/platforms/86xx/gef_sbc310.c4
-rw-r--r--arch/powerpc/platforms/86xx/gef_sbc610.c4
-rw-r--r--arch/powerpc/platforms/86xx/mpc8610_hpcd.c4
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c6
-rw-r--r--arch/powerpc/platforms/86xx/mvme7100.c121
-rw-r--r--arch/powerpc/platforms/86xx/sbc8641d.c4
-rw-r--r--arch/powerpc/platforms/8xx/adder875.c3
-rw-r--r--arch/powerpc/platforms/8xx/ep88xc.c3
-rw-r--r--arch/powerpc/platforms/8xx/m8xx_setup.c2
-rw-r--r--arch/powerpc/platforms/8xx/mpc86xads_setup.c3
-rw-r--r--arch/powerpc/platforms/8xx/mpc885ads_setup.c3
-rw-r--r--arch/powerpc/platforms/8xx/mpc8xx.h2
-rw-r--r--arch/powerpc/platforms/8xx/tqm8xx_setup.c4
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype1
-rw-r--r--arch/powerpc/platforms/amigaone/setup.c6
-rw-r--r--arch/powerpc/platforms/cell/iommu.c4
-rw-r--r--arch/powerpc/platforms/cell/setup.c7
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c2
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c4
-rw-r--r--arch/powerpc/platforms/cell/spu_manage.c3
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c2
-rw-r--r--arch/powerpc/platforms/chrp/setup.c7
-rw-r--r--arch/powerpc/platforms/embedded6xx/c2k.c10
-rw-r--r--arch/powerpc/platforms/embedded6xx/gamecube.c19
-rw-r--r--arch/powerpc/platforms/embedded6xx/holly.c6
-rw-r--r--arch/powerpc/platforms/embedded6xx/linkstation.c12
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c6
-rw-r--r--arch/powerpc/platforms/embedded6xx/mvme5100.c6
-rw-r--r--arch/powerpc/platforms/embedded6xx/storcenter.c6
-rw-r--r--arch/powerpc/platforms/embedded6xx/wii.c19
-rw-r--r--arch/powerpc/platforms/maple/pci.c34
-rw-r--r--arch/powerpc/platforms/maple/setup.c37
-rw-r--r--arch/powerpc/platforms/pasemi/iommu.c15
-rw-r--r--arch/powerpc/platforms/pasemi/pasemi.h1
-rw-r--r--arch/powerpc/platforms/pasemi/pci.c3
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c18
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c2
-rw-r--r--arch/powerpc/platforms/powermac/pci.c38
-rw-r--r--arch/powerpc/platforms/powermac/setup.c54
-rw-r--r--arch/powerpc/platforms/powermac/smp.c3
-rw-r--r--arch/powerpc/platforms/powernv/Makefile1
-rw-r--r--arch/powerpc/platforms/powernv/eeh-powernv.c49
-rw-r--r--arch/powerpc/platforms/powernv/idle.c188
-rw-r--r--arch/powerpc/platforms/powernv/npu-dma.c8
-rw-r--r--arch/powerpc/platforms/powernv/opal-async.c5
-rw-r--r--arch/powerpc/platforms/powernv/opal-memory-errors.c2
-rw-r--r--arch/powerpc/platforms/powernv/opal-sensor.c2
-rw-r--r--arch/powerpc/platforms/powernv/opal-sysparam.c4
-rw-r--r--arch/powerpc/platforms/powernv/opal-tracepoints.c1
-rw-r--r--arch/powerpc/platforms/powernv/opal-wrappers.S72
-rw-r--r--arch/powerpc/platforms/powernv/opal.c30
-rw-r--r--arch/powerpc/platforms/powernv/pci-cxl.c385
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c905
-rw-r--r--arch/powerpc/platforms/powernv/pci.c132
-rw-r--r--arch/powerpc/platforms/powernv/pci.h43
-rw-r--r--arch/powerpc/platforms/powernv/powernv.h1
-rw-r--r--arch/powerpc/platforms/powernv/setup.c16
-rw-r--r--arch/powerpc/platforms/powernv/smp.c4
-rw-r--r--arch/powerpc/platforms/ps3/htab.c12
-rw-r--r--arch/powerpc/platforms/ps3/repository.c2
-rw-r--r--arch/powerpc/platforms/ps3/setup.c23
-rw-r--r--arch/powerpc/platforms/pseries/cmm.c2
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c56
-rw-r--r--arch/powerpc/platforms/pseries/eeh_pseries.c2
-rw-r--r--arch/powerpc/platforms/pseries/event_sources.c53
-rw-r--r--arch/powerpc/platforms/pseries/firmware.c48
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c13
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c184
-rw-r--r--arch/powerpc/platforms/pseries/io_event_irq.c2
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c53
-rw-r--r--arch/powerpc/platforms/pseries/kexec.c23
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c41
-rw-r--r--arch/powerpc/platforms/pseries/nvram.c2
-rw-r--r--arch/powerpc/platforms/pseries/power.c2
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h21
-rw-r--r--arch/powerpc/platforms/pseries/pseries_energy.c8
-rw-r--r--arch/powerpc/platforms/pseries/ras.c39
-rw-r--r--arch/powerpc/platforms/pseries/setup.c241
-rw-r--r--arch/powerpc/platforms/pseries/smp.c31
153 files changed, 2079 insertions, 1465 deletions
diff --git a/arch/powerpc/platforms/40x/ep405.c b/arch/powerpc/platforms/40x/ep405.c
index ddc12a1926ef..1c8aec6e9bb7 100644
--- a/arch/powerpc/platforms/40x/ep405.c
+++ b/arch/powerpc/platforms/40x/ep405.c
@@ -105,9 +105,7 @@ static void __init ep405_setup_arch(void)
static int __init ep405_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "ep405"))
+ if (!of_machine_is_compatible("ep405"))
return 0;
return 1;
diff --git a/arch/powerpc/platforms/40x/ppc40x_simple.c b/arch/powerpc/platforms/40x/ppc40x_simple.c
index b0c46375dd95..2a050007bbae 100644
--- a/arch/powerpc/platforms/40x/ppc40x_simple.c
+++ b/arch/powerpc/platforms/40x/ppc40x_simple.c
@@ -63,7 +63,7 @@ static const char * const board[] __initconst = {
static int __init ppc40x_probe(void)
{
- if (of_flat_dt_match(of_get_flat_dt_root(), board)) {
+ if (of_device_compatible_match(of_root, board)) {
pci_set_flags(PCI_REASSIGN_ALL_RSRC);
return 1;
}
diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c
index 9aa7ae2f4164..91a08ea758a8 100644
--- a/arch/powerpc/platforms/40x/virtex.c
+++ b/arch/powerpc/platforms/40x/virtex.c
@@ -37,9 +37,7 @@ machine_device_initcall(virtex, virtex_device_probe);
static int __init virtex_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "xlnx,virtex"))
+ if (!of_machine_is_compatible("xlnx,virtex"))
return 0;
return 1;
diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c
index f7ac2d0fcb44..e5797815e2f1 100644
--- a/arch/powerpc/platforms/40x/walnut.c
+++ b/arch/powerpc/platforms/40x/walnut.c
@@ -46,9 +46,7 @@ machine_device_initcall(walnut, walnut_device_probe);
static int __init walnut_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "ibm,walnut"))
+ if (!of_machine_is_compatible("ibm,walnut"))
return 0;
pci_set_flags(PCI_REASSIGN_ALL_RSRC);
diff --git a/arch/powerpc/platforms/44x/canyonlands.c b/arch/powerpc/platforms/44x/canyonlands.c
index 22ca5430c9cb..157f4ce46386 100644
--- a/arch/powerpc/platforms/44x/canyonlands.c
+++ b/arch/powerpc/platforms/44x/canyonlands.c
@@ -53,11 +53,10 @@ machine_device_initcall(canyonlands, ppc460ex_device_probe);
static int __init ppc460ex_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "amcc,canyonlands")) {
+ if (of_machine_is_compatible("amcc,canyonlands")) {
pci_set_flags(PCI_REASSIGN_ALL_RSRC);
return 1;
- }
+ }
return 0;
}
diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c
index ae893226392d..1070225f5f9b 100644
--- a/arch/powerpc/platforms/44x/ebony.c
+++ b/arch/powerpc/platforms/44x/ebony.c
@@ -49,9 +49,7 @@ machine_device_initcall(ebony, ebony_device_probe);
*/
static int __init ebony_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "ibm,ebony"))
+ if (!of_machine_is_compatible("ibm,ebony"))
return 0;
pci_set_flags(PCI_REASSIGN_ALL_RSRC);
diff --git a/arch/powerpc/platforms/44x/iss4xx.c b/arch/powerpc/platforms/44x/iss4xx.c
index c7c6758b3cfe..5f296dd6b1c0 100644
--- a/arch/powerpc/platforms/44x/iss4xx.c
+++ b/arch/powerpc/platforms/44x/iss4xx.c
@@ -149,9 +149,7 @@ static void __init iss4xx_setup_arch(void)
*/
static int __init iss4xx_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "ibm,iss-4xx"))
+ if (!of_machine_is_compatible("ibm,iss-4xx"))
return 0;
return 1;
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c
index 573c3d2689c6..8d6e4da9dfbe 100644
--- a/arch/powerpc/platforms/44x/ppc44x_simple.c
+++ b/arch/powerpc/platforms/44x/ppc44x_simple.c
@@ -67,11 +67,10 @@ static char *board[] __initdata = {
static int __init ppc44x_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
int i = 0;
for (i = 0; i < ARRAY_SIZE(board); i++) {
- if (of_flat_dt_is_compatible(root, board[i])) {
+ if (of_machine_is_compatible(board[i])) {
pci_set_flags(PCI_REASSIGN_ALL_RSRC);
return 1;
}
diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c
index c11ce6516c8f..e55933f9cd55 100644
--- a/arch/powerpc/platforms/44x/ppc476.c
+++ b/arch/powerpc/platforms/44x/ppc476.c
@@ -68,7 +68,7 @@ DECLARE_PCI_FIXUP_HEADER(0x1033, 0x0035, quirk_ppc_currituck_usb_fixup);
#define AVR_PWRCTL_RESET (0x02)
static struct i2c_client *avr_i2c_client;
-static void avr_halt_system(int pwrctl_flags)
+static void __noreturn avr_halt_system(int pwrctl_flags)
{
/* Request the AVR to reset the system */
i2c_smbus_write_byte_data(avr_i2c_client,
@@ -84,7 +84,7 @@ static void avr_power_off_system(void)
avr_halt_system(AVR_PWRCTL_PWROFF);
}
-static void avr_reset_system(char *cmd)
+static void __noreturn avr_reset_system(char *cmd)
{
avr_halt_system(AVR_PWRCTL_RESET);
}
@@ -275,12 +275,10 @@ static void ppc47x_pci_irq_fixup(struct pci_dev *dev)
*/
static int __init ppc47x_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "ibm,akebono"))
+ if (of_machine_is_compatible("ibm,akebono"))
return 1;
- if (of_flat_dt_is_compatible(root, "ibm,currituck")) {
+ if (of_machine_is_compatible("ibm,currituck")) {
ppc_md.pci_irq_fixup = ppc47x_pci_irq_fixup;
return 1;
}
diff --git a/arch/powerpc/platforms/44x/sam440ep.c b/arch/powerpc/platforms/44x/sam440ep.c
index 3ee4a03c1496..688ffeab0699 100644
--- a/arch/powerpc/platforms/44x/sam440ep.c
+++ b/arch/powerpc/platforms/44x/sam440ep.c
@@ -46,9 +46,7 @@ machine_device_initcall(sam440ep, sam440ep_device_probe);
static int __init sam440ep_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "acube,sam440ep"))
+ if (!of_machine_is_compatible("acube,sam440ep"))
return 0;
pci_set_flags(PCI_REASSIGN_ALL_RSRC);
diff --git a/arch/powerpc/platforms/44x/virtex.c b/arch/powerpc/platforms/44x/virtex.c
index ad272c17c640..a7e08026097a 100644
--- a/arch/powerpc/platforms/44x/virtex.c
+++ b/arch/powerpc/platforms/44x/virtex.c
@@ -43,9 +43,7 @@ machine_device_initcall(virtex, virtex_device_probe);
static int __init virtex_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "xlnx,virtex440"))
+ if (!of_machine_is_compatible("xlnx,virtex440"))
return 0;
return 1;
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
index 501333cf42cf..5ecce543103e 100644
--- a/arch/powerpc/platforms/44x/warp.c
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -44,9 +44,7 @@ machine_device_initcall(warp, warp_device_probe);
static int __init warp_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "pika,warp"))
+ if (!of_machine_is_compatible("pika,warp"))
return 0;
/* For __dma_alloc_coherent */
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 6081fbd75330..add5a5374fa0 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -719,7 +719,7 @@ static void mpc512x_clk_setup_clock_tree(struct device_node *np, int busfreq)
* most one of a mux, div, and gate each into one 'struct clk'
* item
* - PSC/MSCAN/SPDIF clock generation OTOH already is very
- * specific and cannot get mapped to componsites (at least not
+ * specific and cannot get mapped to composites (at least not
* a single one, maybe two of them, but then some of these
* intermediate clock signals get referenced elsewhere (e.g.
* in the clock frequency measurement, CFM) and thus need
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c
index 3e90ece10ae9..f65d5033cdb0 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
@@ -57,9 +57,12 @@ static void __init mpc5121_ads_init_IRQ(void)
*/
static int __init mpc5121_ads_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
+ if (!of_machine_is_compatible("fsl,mpc5121ads"))
+ return 0;
- return of_flat_dt_is_compatible(root, "fsl,mpc5121ads");
+ mpc512x_init_early();
+
+ return 1;
}
define_machine(mpc5121_ads) {
@@ -67,7 +70,6 @@ define_machine(mpc5121_ads) {
.probe = mpc5121_ads_probe,
.setup_arch = mpc5121_ads_setup_arch,
.init = mpc512x_init,
- .init_early = mpc512x_init_early,
.init_IRQ = mpc5121_ads_init_IRQ,
.get_irq = ipic_get_irq,
.calibrate_decr = generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h
index cc97f022d028..14ba49fd7938 100644
--- a/arch/powerpc/platforms/512x/mpc512x.h
+++ b/arch/powerpc/platforms/512x/mpc512x.h
@@ -18,6 +18,6 @@ extern void __init mpc512x_setup_arch(void);
extern int __init mpc5121_clk_init(void);
extern const char *mpc512x_select_psc_compat(void);
extern const char *mpc512x_select_reset_compat(void);
-extern void mpc512x_restart(char *cmd);
+extern void __noreturn mpc512x_restart(char *cmd);
#endif /* __MPC512X_H__ */
diff --git a/arch/powerpc/platforms/512x/mpc512x_generic.c b/arch/powerpc/platforms/512x/mpc512x_generic.c
index ce71408781a0..bf884d3075e4 100644
--- a/arch/powerpc/platforms/512x/mpc512x_generic.c
+++ b/arch/powerpc/platforms/512x/mpc512x_generic.c
@@ -38,14 +38,18 @@ static const char * const board[] __initconst = {
*/
static int __init mpc512x_generic_probe(void)
{
- return of_flat_dt_match(of_get_flat_dt_root(), board);
+ if (!of_device_compatible_match(of_root, board))
+ return 0;
+
+ mpc512x_init_early();
+
+ return 1;
}
define_machine(mpc512x_generic) {
.name = "MPC512x generic",
.probe = mpc512x_generic_probe,
.init = mpc512x_init,
- .init_early = mpc512x_init_early,
.setup_arch = mpc512x_setup_arch,
.init_IRQ = mpc512x_init_IRQ,
.get_irq = ipic_get_irq,
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index 452da2391153..6b4f4cb7009a 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -47,7 +47,7 @@ static void __init mpc512x_restart_init(void)
of_node_put(np);
}
-void mpc512x_restart(char *cmd)
+void __noreturn mpc512x_restart(char *cmd)
{
if (reset_module_base) {
/* Enable software reset "RSTE" */
diff --git a/arch/powerpc/platforms/512x/pdm360ng.c b/arch/powerpc/platforms/512x/pdm360ng.c
index 116f2325b20b..dc81f05e0bce 100644
--- a/arch/powerpc/platforms/512x/pdm360ng.c
+++ b/arch/powerpc/platforms/512x/pdm360ng.c
@@ -113,9 +113,12 @@ void __init pdm360ng_init(void)
static int __init pdm360ng_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
+ if (!of_machine_is_compatible("ifm,pdm360ng"))
+ return 0;
- return of_flat_dt_is_compatible(root, "ifm,pdm360ng");
+ mpc512x_init_early();
+
+ return 1;
}
define_machine(pdm360ng) {
@@ -123,7 +126,6 @@ define_machine(pdm360ng) {
.probe = pdm360ng_probe,
.setup_arch = mpc512x_setup_arch,
.init = pdm360ng_init,
- .init_early = mpc512x_init_early,
.init_IRQ = mpc512x_init_IRQ,
.get_irq = ipic_get_irq,
.calibrate_decr = generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index 6af651e69129..39b49822ace1 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -200,8 +200,7 @@ static void __init efika_setup_arch(void)
static int __init efika_probe(void)
{
- const char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
- "model", NULL);
+ const char *model = of_get_property(of_root, "model", NULL);
if (model == NULL)
return 0;
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 7492de3cf6d0..c94c385cc919 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -183,7 +183,7 @@ static const char * const board[] __initconst = {
*/
static int __init lite5200_probe(void)
{
- return of_flat_dt_match(of_get_flat_dt_root(), board);
+ return of_device_compatible_match(of_root, board);
}
define_machine(lite5200) {
diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c
index 8fb95480fd73..a3227040cc86 100644
--- a/arch/powerpc/platforms/52xx/media5200.c
+++ b/arch/powerpc/platforms/52xx/media5200.c
@@ -242,7 +242,7 @@ static const char * const board[] __initconst = {
*/
static int __init media5200_probe(void)
{
- return of_flat_dt_match(of_get_flat_dt_root(), board);
+ return of_device_compatible_match(of_root, board);
}
define_machine(media5200_platform) {
diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
index 792a301a0bf0..a80c6278d515 100644
--- a/arch/powerpc/platforms/52xx/mpc5200_simple.c
+++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
@@ -70,7 +70,7 @@ static const char *board[] __initdata = {
*/
static int __init mpc5200_simple_probe(void)
{
- return of_flat_dt_match(of_get_flat_dt_root(), board);
+ return of_device_compatible_match(of_root, board);
}
define_machine(mpc5200_simple_platform) {
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 26993826a797..565e3a83dc9e 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -243,8 +243,7 @@ EXPORT_SYMBOL(mpc52xx_get_xtal_freq);
/**
* mpc52xx_restart: ppc_md->restart hook for mpc5200 using the watchdog timer
*/
-void
-mpc52xx_restart(char *cmd)
+void __noreturn mpc52xx_restart(char *cmd)
{
local_irq_disable();
diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c
index 6781bda117be..cdab847749e6 100644
--- a/arch/powerpc/platforms/82xx/ep8248e.c
+++ b/arch/powerpc/platforms/82xx/ep8248e.c
@@ -309,8 +309,7 @@ machine_device_initcall(ep8248e, declare_of_platform_devices);
*/
static int __init ep8248e_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "fsl,ep8248e");
+ return of_machine_is_compatible("fsl,ep8248e");
}
define_machine(ep8248e)
diff --git a/arch/powerpc/platforms/82xx/km82xx.c b/arch/powerpc/platforms/82xx/km82xx.c
index 387b446f4161..28860e40b5db 100644
--- a/arch/powerpc/platforms/82xx/km82xx.c
+++ b/arch/powerpc/platforms/82xx/km82xx.c
@@ -198,8 +198,7 @@ machine_device_initcall(km82xx, declare_of_platform_devices);
*/
static int __init km82xx_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "keymile,km82xx");
+ return of_machine_is_compatible("keymile,km82xx");
}
define_machine(km82xx)
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c
index d24deacf07d0..d23c10a96bde 100644
--- a/arch/powerpc/platforms/82xx/mpc8272_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c
@@ -201,8 +201,7 @@ machine_device_initcall(mpc8272_ads, declare_of_platform_devices);
*/
static int __init mpc8272_ads_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "fsl,mpc8272ads");
+ return of_machine_is_compatible("fsl,mpc8272ads");
}
define_machine(mpc8272_ads)
diff --git a/arch/powerpc/platforms/82xx/pq2.c b/arch/powerpc/platforms/82xx/pq2.c
index fc8b2d6a7d8d..c4f7029fc9ae 100644
--- a/arch/powerpc/platforms/82xx/pq2.c
+++ b/arch/powerpc/platforms/82xx/pq2.c
@@ -22,7 +22,7 @@
#define RMR_CSRE 0x00000001
-void pq2_restart(char *cmd)
+void __noreturn pq2_restart(char *cmd)
{
local_irq_disable();
setbits32(&cpm2_immr->im_clkrst.car_rmr, RMR_CSRE);
diff --git a/arch/powerpc/platforms/82xx/pq2.h b/arch/powerpc/platforms/82xx/pq2.h
index a41f84ae2325..3080ce3441c1 100644
--- a/arch/powerpc/platforms/82xx/pq2.h
+++ b/arch/powerpc/platforms/82xx/pq2.h
@@ -1,7 +1,7 @@
#ifndef _PQ2_H
#define _PQ2_H
-void pq2_restart(char *cmd);
+void __noreturn pq2_restart(char *cmd);
#ifdef CONFIG_PCI
int pq2ads_pci_init_irq(void);
diff --git a/arch/powerpc/platforms/82xx/pq2fads.c b/arch/powerpc/platforms/82xx/pq2fads.c
index 3a5164ad10ad..6c654dc74a4b 100644
--- a/arch/powerpc/platforms/82xx/pq2fads.c
+++ b/arch/powerpc/platforms/82xx/pq2fads.c
@@ -164,8 +164,7 @@ static void __init pq2fads_setup_arch(void)
*/
static int __init pq2fads_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "fsl,pq2fads");
+ return of_machine_is_compatible("fsl,pq2fads");
}
static const struct of_device_id of_bus_ids[] __initconst = {
diff --git a/arch/powerpc/platforms/83xx/asp834x.c b/arch/powerpc/platforms/83xx/asp834x.c
index 464ea8e0292d..17e54339f8d9 100644
--- a/arch/powerpc/platforms/83xx/asp834x.c
+++ b/arch/powerpc/platforms/83xx/asp834x.c
@@ -43,8 +43,7 @@ machine_device_initcall(asp834x, mpc83xx_declare_of_platform_devices);
*/
static int __init asp834x_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "analogue-and-micro,asp8347e");
+ return of_machine_is_compatible("analogue-and-micro,asp8347e");
}
define_machine(asp834x) {
diff --git a/arch/powerpc/platforms/83xx/km83xx.c b/arch/powerpc/platforms/83xx/km83xx.c
index 4bc6bbbe9ada..e7fbd6366abb 100644
--- a/arch/powerpc/platforms/83xx/km83xx.c
+++ b/arch/powerpc/platforms/83xx/km83xx.c
@@ -171,11 +171,10 @@ static char *board[] __initdata = {
*/
static int __init mpc83xx_km_probe(void)
{
- unsigned long node = of_get_flat_dt_root();
int i = 0;
while (board[i]) {
- if (of_flat_dt_is_compatible(node, board[i]))
+ if (of_machine_is_compatible(board[i]))
break;
i++;
}
diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c
index 7e923cad56cf..8899aa9d11f5 100644
--- a/arch/powerpc/platforms/83xx/misc.c
+++ b/arch/powerpc/platforms/83xx/misc.c
@@ -35,7 +35,7 @@ static int __init mpc83xx_restart_init(void)
arch_initcall(mpc83xx_restart_init);
-void mpc83xx_restart(char *cmd)
+void __noreturn mpc83xx_restart(char *cmd)
{
#define RST_OFFSET 0x00000900
#define RST_PROT_REG 0x00000018
diff --git a/arch/powerpc/platforms/83xx/mpc830x_rdb.c b/arch/powerpc/platforms/83xx/mpc830x_rdb.c
index 4f2d9fea77b7..040d5d085467 100644
--- a/arch/powerpc/platforms/83xx/mpc830x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc830x_rdb.c
@@ -46,7 +46,7 @@ static const char *board[] __initdata = {
*/
static int __init mpc830x_rdb_probe(void)
{
- return of_flat_dt_match(of_get_flat_dt_root(), board);
+ return of_device_compatible_match(of_root, board);
}
machine_device_initcall(mpc830x_rdb, mpc83xx_declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/83xx/mpc831x_rdb.c b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
index fa25977c52de..40e0d8307b59 100644
--- a/arch/powerpc/platforms/83xx/mpc831x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
@@ -46,7 +46,7 @@ static const char *board[] __initdata = {
*/
static int __init mpc831x_rdb_probe(void)
{
- return of_flat_dt_match(of_get_flat_dt_root(), board);
+ return of_device_compatible_match(of_root, board);
}
machine_device_initcall(mpc831x_rdb, mpc83xx_declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index a973b2ae5df6..cdfa47c4d394 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -102,9 +102,7 @@ machine_device_initcall(mpc832x_mds, mpc83xx_declare_of_platform_devices);
*/
static int __init mpc832x_sys_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "MPC832xMDS");
+ return of_machine_is_compatible("MPC832xMDS");
}
define_machine(mpc832x_mds) {
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index ea2b87d202ca..2ef03e7d248c 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -220,9 +220,7 @@ machine_device_initcall(mpc832x_rdb, mpc83xx_declare_of_platform_devices);
*/
static int __init mpc832x_rdb_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "MPC832xRDB");
+ return of_machine_is_compatible("MPC832xRDB");
}
define_machine(mpc832x_rdb) {
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 80aea8c4b5a3..8fd0c1e8b182 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -70,9 +70,7 @@ static void __init mpc834x_itx_setup_arch(void)
*/
static int __init mpc834x_itx_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "MPC834xMITX");
+ return of_machine_is_compatible("MPC834xMITX");
}
define_machine(mpc834x_itx) {
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index 553e793a4a93..eeaee6123bb3 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -91,9 +91,7 @@ machine_device_initcall(mpc834x_mds, mpc83xx_declare_of_platform_devices);
*/
static int __init mpc834x_mds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "MPC834xMDS");
+ return of_machine_is_compatible("MPC834xMDS");
}
define_machine(mpc834x_mds) {
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index dd70b85f56d4..dacf4c2df069 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -209,9 +209,7 @@ machine_arch_initcall(mpc836x_mds, mpc836x_usb_cfg);
*/
static int __init mpc836x_mds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "MPC836xMDS");
+ return of_machine_is_compatible("MPC836xMDS");
}
define_machine(mpc836x_mds) {
diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
index 4cd7153a6c88..cf67ac93ddcb 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_rdk.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
@@ -42,9 +42,7 @@ static void __init mpc836x_rdk_setup_arch(void)
*/
static int __init mpc836x_rdk_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,mpc8360rdk");
+ return of_machine_is_compatible("fsl,mpc8360rdk");
}
define_machine(mpc836x_rdk) {
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
index e53a60b6c863..652b97d699c9 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -93,9 +93,7 @@ machine_device_initcall(mpc837x_mds, mpc83xx_declare_of_platform_devices);
*/
static int __init mpc837x_mds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,mpc837xmds");
+ return of_machine_is_compatible("fsl,mpc837xmds");
}
define_machine(mpc837x_mds) {
diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
index 9813c81e8e5b..667731d81676 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
@@ -73,7 +73,7 @@ static const char * const board[] __initconst = {
*/
static int __init mpc837x_rdb_probe(void)
{
- return of_flat_dt_match(of_get_flat_dt_root(), board);
+ return of_device_compatible_match(of_root, board);
}
define_machine(mpc837x_rdb) {
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 0cf74d7ea1c5..ad484199eff7 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -65,7 +65,7 @@
* mpc83xx_* files. Mostly for use by mpc83xx_setup
*/
-extern void mpc83xx_restart(char *cmd);
+extern void __noreturn mpc83xx_restart(char *cmd);
extern long mpc83xx_time_init(void);
extern int mpc837x_usb_cfg(void);
extern int mpc834x_usb_cfg(void);
diff --git a/arch/powerpc/platforms/83xx/sbc834x.c b/arch/powerpc/platforms/83xx/sbc834x.c
index 26cb3e934722..b867e88dfb0d 100644
--- a/arch/powerpc/platforms/83xx/sbc834x.c
+++ b/arch/powerpc/platforms/83xx/sbc834x.c
@@ -60,9 +60,7 @@ machine_device_initcall(sbc834x, mpc83xx_declare_of_platform_devices);
*/
static int __init sbc834x_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "SBC834xE");
+ return of_machine_is_compatible("SBC834xE");
}
define_machine(sbc834x) {
diff --git a/arch/powerpc/platforms/85xx/bsc913x_qds.c b/arch/powerpc/platforms/85xx/bsc913x_qds.c
index dcfafd6b91ee..07dd6ae3ec52 100644
--- a/arch/powerpc/platforms/85xx/bsc913x_qds.c
+++ b/arch/powerpc/platforms/85xx/bsc913x_qds.c
@@ -60,9 +60,7 @@ machine_arch_initcall(bsc9132_qds, mpc85xx_common_publish_devices);
static int __init bsc9132_qds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,bsc9132qds");
+ return of_machine_is_compatible("fsl,bsc9132qds");
}
define_machine(bsc9132_qds) {
diff --git a/arch/powerpc/platforms/85xx/bsc913x_rdb.c b/arch/powerpc/platforms/85xx/bsc913x_rdb.c
index 9d57bedb940c..e48f6710e6d5 100644
--- a/arch/powerpc/platforms/85xx/bsc913x_rdb.c
+++ b/arch/powerpc/platforms/85xx/bsc913x_rdb.c
@@ -50,9 +50,7 @@ machine_device_initcall(bsc9131_rdb, mpc85xx_common_publish_devices);
static int __init bsc9131_rdb_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,bsc9131rdb");
+ return of_machine_is_compatible("fsl,bsc9131rdb");
}
define_machine(bsc9131_rdb) {
diff --git a/arch/powerpc/platforms/85xx/c293pcie.c b/arch/powerpc/platforms/85xx/c293pcie.c
index 61bc851e9a8e..3b9e3f0f9aec 100644
--- a/arch/powerpc/platforms/85xx/c293pcie.c
+++ b/arch/powerpc/platforms/85xx/c293pcie.c
@@ -54,9 +54,7 @@ machine_arch_initcall(c293_pcie, mpc85xx_common_publish_devices);
*/
static int __init c293_pcie_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "fsl,C293PCIE"))
+ if (of_machine_is_compatible("fsl,C293PCIE"))
return 1;
return 0;
}
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
index a2b0bc859de0..3a6a84f07f43 100644
--- a/arch/powerpc/platforms/85xx/corenet_generic.c
+++ b/arch/powerpc/platforms/85xx/corenet_generic.c
@@ -170,20 +170,19 @@ static const char * const boards[] __initconst = {
*/
static int __init corenet_generic_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
char hv_compat[24];
int i;
#ifdef CONFIG_SMP
extern struct smp_ops_t smp_85xx_ops;
#endif
- if (of_flat_dt_match(root, boards))
+ if (of_device_compatible_match(of_root, boards))
return 1;
/* Check if we're running under the Freescale hypervisor */
for (i = 0; boards[i]; i++) {
snprintf(hv_compat, sizeof(hv_compat), "%s-hv", boards[i]);
- if (of_flat_dt_is_compatible(root, hv_compat)) {
+ if (of_machine_is_compatible(hv_compat)) {
ppc_md.init_IRQ = ehv_pic_init;
ppc_md.get_irq = ehv_pic_get_irq;
diff --git a/arch/powerpc/platforms/85xx/ge_imp3a.c b/arch/powerpc/platforms/85xx/ge_imp3a.c
index 11790e074c8a..14af36a7fa9c 100644
--- a/arch/powerpc/platforms/85xx/ge_imp3a.c
+++ b/arch/powerpc/platforms/85xx/ge_imp3a.c
@@ -47,9 +47,8 @@ void __init ge_imp3a_pic_init(void)
struct mpic *mpic;
struct device_node *np;
struct device_node *cascade_node = NULL;
- unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) {
+ if (of_machine_is_compatible("fsl,MPC8572DS-CAMP")) {
mpic = mpic_alloc(NULL, 0,
MPIC_NO_RESET |
MPIC_BIG_ENDIAN |
@@ -198,9 +197,7 @@ static void ge_imp3a_show_cpuinfo(struct seq_file *m)
*/
static int __init ge_imp3a_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "ge,IMP3A");
+ return of_machine_is_compatible("ge,IMP3A");
}
machine_arch_initcall(ge_imp3a, mpc85xx_common_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c
index 3dc1bda3ddc3..6ef8580fdc0e 100644
--- a/arch/powerpc/platforms/85xx/ksi8560.c
+++ b/arch/powerpc/platforms/85xx/ksi8560.c
@@ -44,7 +44,7 @@
static void __iomem *cpld_base = NULL;
-static void machine_restart(char *cmd)
+static void __noreturn machine_restart(char *cmd)
{
if (cpld_base)
out_8(cpld_base + KSI8560_CPLD_RCR1, KSI8560_CPLD_RCR1_CPUHR);
@@ -176,9 +176,7 @@ machine_device_initcall(ksi8560, mpc85xx_common_publish_devices);
*/
static int __init ksi8560_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "emerson,KSI8560");
+ return of_machine_is_compatible("emerson,KSI8560");
}
define_machine(ksi8560) {
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
index a378ba3519e9..6ba687f19e45 100644
--- a/arch/powerpc/platforms/85xx/mpc8536_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -64,9 +64,7 @@ machine_arch_initcall(mpc8536_ds, swiotlb_setup_bus_notifier);
*/
static int __init mpc8536_ds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,mpc8536ds");
+ return of_machine_is_compatible("fsl,mpc8536ds");
}
define_machine(mpc8536_ds) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index de72a5f464b1..8756715c7a47 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -160,9 +160,7 @@ machine_arch_initcall(mpc85xx_ads, mpc85xx_common_publish_devices);
*/
static int __init mpc85xx_ads_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "MPC85xxADS");
+ return of_machine_is_compatible("MPC85xxADS");
}
define_machine(mpc85xx_ads) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index d7e87ff912d7..62f171c71c4c 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -83,7 +83,7 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
return PCIBIOS_SUCCESSFUL;
}
-static void mpc85xx_cds_restart(char *cmd)
+static void __noreturn mpc85xx_cds_restart(char *cmd)
{
struct pci_dev *dev;
u_char tmp;
@@ -367,9 +367,7 @@ static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
*/
static int __init mpc85xx_cds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "MPC85xxCDS");
+ return of_machine_is_compatible("MPC85xxCDS");
}
machine_arch_initcall(mpc85xx_cds, mpc85xx_common_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index f858306dba6a..6bc07d837b1c 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -66,9 +66,7 @@ void __init mpc85xx_ds_pic_init(void)
struct device_node *cascade_node = NULL;
int cascade_irq;
#endif
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) {
+ if (of_machine_is_compatible("fsl,MPC8572DS-CAMP")) {
mpic = mpic_alloc(NULL, 0,
MPIC_NO_RESET |
MPIC_BIG_ENDIAN |
@@ -169,9 +167,7 @@ static void __init mpc85xx_ds_setup_arch(void)
*/
static int __init mpc8544_ds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return !!of_flat_dt_is_compatible(root, "MPC8544DS");
+ return !!of_machine_is_compatible("MPC8544DS");
}
machine_arch_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
@@ -187,9 +183,7 @@ machine_arch_initcall(p2020_ds, swiotlb_setup_bus_notifier);
*/
static int __init mpc8572_ds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return !!of_flat_dt_is_compatible(root, "fsl,MPC8572DS");
+ return !!of_machine_is_compatible("fsl,MPC8572DS");
}
/*
@@ -197,9 +191,7 @@ static int __init mpc8572_ds_probe(void)
*/
static int __init p2020_ds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return !!of_flat_dt_is_compatible(root, "fsl,P2020DS");
+ return !!of_machine_is_compatible("fsl,P2020DS");
}
define_machine(mpc8544_ds) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index f61cbe235581..fa9cd710d2ae 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -376,9 +376,7 @@ static void __init mpc85xx_mds_pic_init(void)
static int __init mpc85xx_mds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "MPC85xxMDS");
+ return of_machine_is_compatible("MPC85xxMDS");
}
define_machine(mpc8568_mds) {
@@ -398,9 +396,7 @@ define_machine(mpc8568_mds) {
static int __init mpc8569_mds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,MPC8569EMDS");
+ return of_machine_is_compatible("fsl,MPC8569EMDS");
}
define_machine(mpc8569_mds) {
@@ -420,9 +416,7 @@ define_machine(mpc8569_mds) {
static int __init p1021_mds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,P1021MDS");
+ return of_machine_is_compatible("fsl,P1021MDS");
}
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 3f4dad133338..c1499cbf3786 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -47,13 +47,12 @@
void __init mpc85xx_rdb_pic_init(void)
{
struct mpic *mpic;
- unsigned long root = of_get_flat_dt_root();
#ifdef CONFIG_QUICC_ENGINE
struct device_node *np;
#endif
- if (of_flat_dt_is_compatible(root, "fsl,MPC85XXRDB-CAMP")) {
+ if (of_machine_is_compatible("fsl,MPC85XXRDB-CAMP")) {
mpic = mpic_alloc(NULL, 0, MPIC_NO_RESET |
MPIC_BIG_ENDIAN |
MPIC_SINGLE_DEST_CPU,
@@ -148,80 +147,60 @@ machine_arch_initcall(p1024_rdb, mpc85xx_common_publish_devices);
*/
static int __init p2020_rdb_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "fsl,P2020RDB"))
+ if (of_machine_is_compatible("fsl,P2020RDB"))
return 1;
return 0;
}
static int __init p1020_rdb_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "fsl,P1020RDB"))
+ if (of_machine_is_compatible("fsl,P1020RDB"))
return 1;
return 0;
}
static int __init p1020_rdb_pc_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,P1020RDB-PC");
+ return of_machine_is_compatible("fsl,P1020RDB-PC");
}
static int __init p1020_rdb_pd_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,P1020RDB-PD");
+ return of_machine_is_compatible("fsl,P1020RDB-PD");
}
static int __init p1021_rdb_pc_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "fsl,P1021RDB-PC"))
+ if (of_machine_is_compatible("fsl,P1021RDB-PC"))
return 1;
return 0;
}
static int __init p2020_rdb_pc_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "fsl,P2020RDB-PC"))
+ if (of_machine_is_compatible("fsl,P2020RDB-PC"))
return 1;
return 0;
}
static int __init p1025_rdb_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,P1025RDB");
+ return of_machine_is_compatible("fsl,P1025RDB");
}
static int __init p1020_mbg_pc_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,P1020MBG-PC");
+ return of_machine_is_compatible("fsl,P1020MBG-PC");
}
static int __init p1020_utm_pc_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,P1020UTM-PC");
+ return of_machine_is_compatible("fsl,P1020UTM-PC");
}
static int __init p1024_rdb_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,P1024RDB");
+ return of_machine_is_compatible("fsl,P1024RDB");
}
define_machine(p2020_rdb) {
diff --git a/arch/powerpc/platforms/85xx/mvme2500.c b/arch/powerpc/platforms/85xx/mvme2500.c
index 1233050560ae..acc3d0d6049d 100644
--- a/arch/powerpc/platforms/85xx/mvme2500.c
+++ b/arch/powerpc/platforms/85xx/mvme2500.c
@@ -53,9 +53,7 @@ machine_arch_initcall(mvme2500, mpc85xx_common_publish_devices);
*/
static int __init mvme2500_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "artesyn,MVME2500");
+ return of_machine_is_compatible("artesyn,MVME2500");
}
define_machine(mvme2500) {
diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c
index ad1a3d438a9e..661d7b59e413 100644
--- a/arch/powerpc/platforms/85xx/p1010rdb.c
+++ b/arch/powerpc/platforms/85xx/p1010rdb.c
@@ -62,11 +62,9 @@ machine_arch_initcall(p1010_rdb, swiotlb_setup_bus_notifier);
*/
static int __init p1010_rdb_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "fsl,P1010RDB"))
+ if (of_machine_is_compatible("fsl,P1010RDB"))
return 1;
- if (of_flat_dt_is_compatible(root, "fsl,P1010RDB-PB"))
+ if (of_machine_is_compatible("fsl,P1010RDB-PB"))
return 1;
return 0;
}
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 371df822e88e..63568d68c76f 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -555,9 +555,7 @@ machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);
*/
static int __init p1022_ds_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,p1022ds");
+ return of_machine_is_compatible("fsl,p1022ds");
}
define_machine(p1022_ds) {
diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c
index 5087becaa8bc..2f2943600301 100644
--- a/arch/powerpc/platforms/85xx/p1022_rdk.c
+++ b/arch/powerpc/platforms/85xx/p1022_rdk.c
@@ -135,9 +135,7 @@ machine_arch_initcall(p1022_rdk, swiotlb_setup_bus_notifier);
*/
static int __init p1022_rdk_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,p1022rdk");
+ return of_machine_is_compatible("fsl,p1022rdk");
}
define_machine(p1022_rdk) {
diff --git a/arch/powerpc/platforms/85xx/p1023_rdb.c b/arch/powerpc/platforms/85xx/p1023_rdb.c
index d5b7509825de..40d8de57c341 100644
--- a/arch/powerpc/platforms/85xx/p1023_rdb.c
+++ b/arch/powerpc/platforms/85xx/p1023_rdb.c
@@ -100,9 +100,7 @@ static void __init mpc85xx_rdb_pic_init(void)
static int __init p1023_rdb_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,P1023RDB");
+ return of_machine_is_compatible("fsl,P1023RDB");
}
diff --git a/arch/powerpc/platforms/85xx/ppa8548.c b/arch/powerpc/platforms/85xx/ppa8548.c
index 12019f17f297..2410167b290a 100644
--- a/arch/powerpc/platforms/85xx/ppa8548.c
+++ b/arch/powerpc/platforms/85xx/ppa8548.c
@@ -81,9 +81,7 @@ machine_device_initcall(ppa8548, declare_of_platform_devices);
*/
static int __init ppa8548_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "ppa8548");
+ return of_machine_is_compatible("ppa8548");
}
define_machine(ppa8548) {
diff --git a/arch/powerpc/platforms/85xx/qemu_e500.c b/arch/powerpc/platforms/85xx/qemu_e500.c
index 8ad2fe6f200a..50d745809809 100644
--- a/arch/powerpc/platforms/85xx/qemu_e500.c
+++ b/arch/powerpc/platforms/85xx/qemu_e500.c
@@ -62,9 +62,7 @@ static void __init qemu_e500_setup_arch(void)
*/
static int __init qemu_e500_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return !!of_flat_dt_is_compatible(root, "fsl,qemu-e500");
+ return !!of_machine_is_compatible("fsl,qemu-e500");
}
machine_arch_initcall(qemu_e500, mpc85xx_common_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
index b07214666d65..62b6c45a5a9b 100644
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -120,9 +120,7 @@ machine_arch_initcall(sbc8548, mpc85xx_common_publish_devices);
*/
static int __init sbc8548_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "SBC8548");
+ return of_machine_is_compatible("SBC8548");
}
define_machine(sbc8548) {
diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c
index ae368e0e1076..cd255acde2e2 100644
--- a/arch/powerpc/platforms/85xx/socrates.c
+++ b/arch/powerpc/platforms/85xx/socrates.c
@@ -79,9 +79,7 @@ machine_arch_initcall(socrates, mpc85xx_common_publish_devices);
*/
static int __init socrates_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "abb,socrates"))
+ if (of_machine_is_compatible("abb,socrates"))
return 1;
return 0;
diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c
index 6f4939b6309e..91b824c4dc08 100644
--- a/arch/powerpc/platforms/85xx/stx_gp3.c
+++ b/arch/powerpc/platforms/85xx/stx_gp3.c
@@ -93,9 +93,7 @@ machine_arch_initcall(stx_gp3, mpc85xx_common_publish_devices);
*/
static int __init stx_gp3_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "stx,gp3-8560");
+ return of_machine_is_compatible("stx,gp3-8560");
}
define_machine(stx_gp3) {
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
index ec0b7272fae2..b7c54454d611 100644
--- a/arch/powerpc/platforms/85xx/tqm85xx.c
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -122,7 +122,7 @@ static const char * const board[] __initconst = {
*/
static int __init tqm85xx_probe(void)
{
- return of_flat_dt_match(of_get_flat_dt_root(), board);
+ return of_device_compatible_match(of_root, board);
}
define_machine(tqm85xx) {
diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c
index 71bc255b4324..1bc02a87f597 100644
--- a/arch/powerpc/platforms/85xx/twr_p102x.c
+++ b/arch/powerpc/platforms/85xx/twr_p102x.c
@@ -128,9 +128,7 @@ machine_arch_initcall(twr_p1025, mpc85xx_common_publish_devices);
static int __init twr_p1025_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "fsl,TWR-P1025");
+ return of_machine_is_compatible("fsl,TWR-P1025");
}
define_machine(twr_p1025) {
diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
index 1a9c1085855f..cf0c70ff026e 100644
--- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c
+++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
@@ -144,23 +144,17 @@ machine_arch_initcall(xes_mpc8540, mpc85xx_common_publish_devices);
*/
static int __init xes_mpc8572_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "xes,MPC8572");
+ return of_machine_is_compatible("xes,MPC8572");
}
static int __init xes_mpc8548_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "xes,MPC8548");
+ return of_machine_is_compatible("xes,MPC8548");
}
static int __init xes_mpc8540_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "xes,MPC8540");
+ return of_machine_is_compatible("xes,MPC8540");
}
define_machine(xes_mpc8572) {
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 3988f16e46c1..ce619bd1f82d 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -60,6 +60,11 @@ config GEF_SBC610
help
This option enables support for the GE SBC610.
+config MVME7100
+ bool "Artesyn MVME7100"
+ help
+ This option enables support for the Emerson/Artesyn MVME7100 board.
+
endif
config MPC8641
@@ -68,7 +73,8 @@ config MPC8641
select FSL_PCI if PCI
select PPC_UDBG_16550
select MPIC
- default y if MPC8641_HPCN || SBC8641D || GEF_SBC610 || GEF_SBC310 || GEF_PPC9A
+ default y if MPC8641_HPCN || SBC8641D || GEF_SBC610 || GEF_SBC310 || GEF_PPC9A \
+ || MVME7100
config MPC8610
bool
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
index 2d889ad7dc89..01958fedc3f2 100644
--- a/arch/powerpc/platforms/86xx/Makefile
+++ b/arch/powerpc/platforms/86xx/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o
obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o
obj-$(CONFIG_GEF_SBC310) += gef_sbc310.o
obj-$(CONFIG_GEF_PPC9A) += gef_ppc9a.o
+obj-$(CONFIG_MVME7100) += mvme7100.o
diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c
index 8e63b752712c..ef684afb63c6 100644
--- a/arch/powerpc/platforms/86xx/gef_ppc9a.c
+++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c
@@ -189,9 +189,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
*/
static int __init gef_ppc9a_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "gef,ppc9a"))
+ if (of_machine_is_compatible("gef,ppc9a"))
return 1;
return 0;
diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c
index 0e0be94f551f..67dd0c231646 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc310.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc310.c
@@ -176,9 +176,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
*/
static int __init gef_sbc310_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "gef,sbc310"))
+ if (of_machine_is_compatible("gef,sbc310"))
return 1;
return 0;
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
index e8292b492d7e..805026976cac 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc610.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc610.c
@@ -166,9 +166,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
*/
static int __init gef_sbc610_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "gef,sbc610"))
+ if (of_machine_is_compatible("gef,sbc610"))
return 1;
return 0;
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 957473e5c8e5..fef0582eddf1 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -319,9 +319,7 @@ static void __init mpc86xx_hpcd_setup_arch(void)
*/
static int __init mpc86xx_hpcd_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "fsl,MPC8610HPCD"))
+ if (of_machine_is_compatible("fsl,MPC8610HPCD"))
return 1; /* Looks good */
return 0;
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index e5084811b9c6..5ae42a037065 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -96,13 +96,11 @@ mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
*/
static int __init mpc86xx_hpcn_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "fsl,mpc8641hpcn"))
+ if (of_machine_is_compatible("fsl,mpc8641hpcn"))
return 1; /* Looks good */
/* Be nice and don't give silent boot death. Delete this in 2.6.27 */
- if (of_flat_dt_is_compatible(root, "mpc86xx")) {
+ if (of_machine_is_compatible("mpc86xx")) {
pr_warning("WARNING: your dts/dtb is old. You must update before the next kernel release\n");
return 1;
}
diff --git a/arch/powerpc/platforms/86xx/mvme7100.c b/arch/powerpc/platforms/86xx/mvme7100.c
new file mode 100644
index 000000000000..addb41e7cd14
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mvme7100.c
@@ -0,0 +1,121 @@
+/*
+ * Board setup routines for the Emerson/Artesyn MVME7100
+ *
+ * Copyright 2016 Elettra-Sincrotrone Trieste S.C.p.A.
+ *
+ * Author: Alessio Igor Bogani <alessio.bogani@elettra.eu>
+ *
+ * Based on earlier code by:
+ *
+ * Ajit Prem <ajit.prem@emerson.com>
+ * Copyright 2008 Emerson
+ *
+ * USB host fixup is borrowed by:
+ *
+ * Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+#include "mpc86xx.h"
+
+#define MVME7100_INTERRUPT_REG_2_OFFSET 0x05
+#define MVME7100_DS1375_MASK 0x40
+#define MVME7100_MAX6649_MASK 0x20
+#define MVME7100_ABORT_MASK 0x10
+
+/*
+ * Setup the architecture
+ */
+static void __init mvme7100_setup_arch(void)
+{
+ struct device_node *bcsr_node;
+ void __iomem *mvme7100_regs = NULL;
+ u8 reg;
+
+ if (ppc_md.progress)
+ ppc_md.progress("mvme7100_setup_arch()", 0);
+
+#ifdef CONFIG_SMP
+ mpc86xx_smp_init();
+#endif
+
+ fsl_pci_assign_primary();
+
+ /* Remap BCSR registers */
+ bcsr_node = of_find_compatible_node(NULL, NULL,
+ "artesyn,mvme7100-bcsr");
+ if (bcsr_node) {
+ mvme7100_regs = of_iomap(bcsr_node, 0);
+ of_node_put(bcsr_node);
+ }
+
+ if (mvme7100_regs) {
+ /* Disable ds1375, max6649, and abort interrupts */
+ reg = readb(mvme7100_regs + MVME7100_INTERRUPT_REG_2_OFFSET);
+ reg |= MVME7100_DS1375_MASK | MVME7100_MAX6649_MASK
+ | MVME7100_ABORT_MASK;
+ writeb(reg, mvme7100_regs + MVME7100_INTERRUPT_REG_2_OFFSET);
+ } else
+ pr_warn("Unable to map board registers\n");
+
+ pr_info("MVME7100 board from Artesyn\n");
+}
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mvme7100_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "artesyn,MVME7100");
+}
+
+static void mvme7100_usb_host_fixup(struct pci_dev *pdev)
+{
+ unsigned int val;
+
+ if (!machine_is(mvme7100))
+ return;
+
+ /* Ensure only ports 1 & 2 are enabled */
+ pci_read_config_dword(pdev, 0xe0, &val);
+ pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x2);
+
+ /* System clock is 48-MHz Oscillator and EHCI Enabled. */
+ pci_write_config_dword(pdev, 0xe4, 1 << 5);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+ mvme7100_usb_host_fixup);
+
+machine_arch_initcall(mvme7100, mpc86xx_common_publish_devices);
+
+define_machine(mvme7100) {
+ .name = "MVME7100",
+ .probe = mvme7100_probe,
+ .setup_arch = mvme7100_setup_arch,
+ .init_IRQ = mpc86xx_init_irq,
+ .get_irq = mpic_get_irq,
+ .restart = fsl_rstcr_restart,
+ .time_init = mpc86xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+};
diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
index 2a9cf278c12a..52af5735742e 100644
--- a/arch/powerpc/platforms/86xx/sbc8641d.c
+++ b/arch/powerpc/platforms/86xx/sbc8641d.c
@@ -67,9 +67,7 @@ sbc8641_show_cpuinfo(struct seq_file *m)
*/
static int __init sbc8641_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "wind,sbc8641"))
+ if (of_machine_is_compatible("wind,sbc8641"))
return 1; /* Looks good */
return 0;
diff --git a/arch/powerpc/platforms/8xx/adder875.c b/arch/powerpc/platforms/8xx/adder875.c
index 61cae4c1edb8..333dece79394 100644
--- a/arch/powerpc/platforms/8xx/adder875.c
+++ b/arch/powerpc/platforms/8xx/adder875.c
@@ -88,8 +88,7 @@ static void __init adder875_setup(void)
static int __init adder875_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "analogue-and-micro,adder875");
+ return of_machine_is_compatible("analogue-and-micro,adder875");
}
static const struct of_device_id of_bus_ids[] __initconst = {
diff --git a/arch/powerpc/platforms/8xx/ep88xc.c b/arch/powerpc/platforms/8xx/ep88xc.c
index 2bedeb7d5f8f..cd0d90f1fb1c 100644
--- a/arch/powerpc/platforms/8xx/ep88xc.c
+++ b/arch/powerpc/platforms/8xx/ep88xc.c
@@ -143,8 +143,7 @@ static void __init ep88xc_setup_arch(void)
static int __init ep88xc_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "fsl,ep88xc");
+ return of_machine_is_compatible("fsl,ep88xc");
}
static const struct of_device_id of_bus_ids[] __initconst = {
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index c289fc77b4ba..b1ab6e96cb31 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -198,7 +198,7 @@ void mpc8xx_get_rtc_time(struct rtc_time *tm)
return;
}
-void mpc8xx_restart(char *cmd)
+void __noreturn mpc8xx_restart(char *cmd)
{
car8xx_t __iomem *clk_r = immr_map(im_clkrst);
diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
index 78180c5e73ff..8d02f5ff4481 100644
--- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
@@ -118,8 +118,7 @@ static void __init mpc86xads_setup_arch(void)
static int __init mpc86xads_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "fsl,mpc866ads");
+ return of_machine_is_compatible("fsl,mpc866ads");
}
static const struct of_device_id of_bus_ids[] __initconst = {
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index 4d62bf9dc789..e821a42d5816 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -193,8 +193,7 @@ static void __init mpc885ads_setup_arch(void)
static int __init mpc885ads_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "fsl,mpc885ads");
+ return of_machine_is_compatible("fsl,mpc885ads");
}
static const struct of_device_id of_bus_ids[] __initconst = {
diff --git a/arch/powerpc/platforms/8xx/mpc8xx.h b/arch/powerpc/platforms/8xx/mpc8xx.h
index 239a243a6161..31cc2ecace42 100644
--- a/arch/powerpc/platforms/8xx/mpc8xx.h
+++ b/arch/powerpc/platforms/8xx/mpc8xx.h
@@ -11,7 +11,7 @@
#ifndef __MPC8xx_H
#define __MPC8xx_H
-extern void mpc8xx_restart(char *cmd);
+extern void __noreturn mpc8xx_restart(char *cmd);
extern void mpc8xx_calibrate_decr(void);
extern int mpc8xx_set_rtc_time(struct rtc_time *tm);
extern void mpc8xx_get_rtc_time(struct rtc_time *tm);
diff --git a/arch/powerpc/platforms/8xx/tqm8xx_setup.c b/arch/powerpc/platforms/8xx/tqm8xx_setup.c
index bee47a2b23e6..4cea8b1afa44 100644
--- a/arch/powerpc/platforms/8xx/tqm8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/tqm8xx_setup.c
@@ -119,9 +119,7 @@ static void __init tqm8xx_setup_arch(void)
static int __init tqm8xx_probe(void)
{
- unsigned long node = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(node, "tqc,tqm8xx");
+ return of_machine_is_compatible("tqc,tqm8xx");
}
static const struct of_device_id of_bus_ids[] __initconst = {
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 77e9b8d591fb..f32edec13fd1 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -1,7 +1,6 @@
config PPC64
bool "64-bit kernel"
default n
- select HAVE_VIRT_CPU_ACCOUNTING
select ZLIB_DEFLATE
help
This option selects whether a 32-bit or a 64-bit kernel
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c
index 2fe12046279e..45cb9821173c 100644
--- a/arch/powerpc/platforms/amigaone/setup.c
+++ b/arch/powerpc/platforms/amigaone/setup.c
@@ -123,7 +123,7 @@ static int __init request_isa_regions(void)
}
machine_device_initcall(amigaone, request_isa_regions);
-void amigaone_restart(char *cmd)
+void __noreturn amigaone_restart(char *cmd)
{
local_irq_disable();
@@ -143,9 +143,7 @@ void amigaone_restart(char *cmd)
static int __init amigaone_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (of_flat_dt_is_compatible(root, "eyetech,amigaone")) {
+ if (of_machine_is_compatible("eyetech,amigaone")) {
/*
* Coherent memory access cause complete system lockup! Thus
* disable this CPU feature, even if the CPU needs it.
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 14a582b21274..9027d7c48507 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -178,7 +178,7 @@ static int tce_build_cell(struct iommu_table *tbl, long index, long npages,
* default for now.*/
#ifdef CELL_IOMMU_STRICT_PROTECTION
/* to avoid referencing a global, we use a trick here to setup the
- * protection bit. "prot" is setup to be 3 fields of 4 bits apprended
+ * protection bit. "prot" is setup to be 3 fields of 4 bits appended
* together for each of the 3 supported direction values. It is then
* shifted left so that the fields matching the desired direction
* lands on the appropriate bits, and other bits are masked out.
@@ -338,7 +338,7 @@ static unsigned long *cell_iommu_alloc_ptab(struct cbe_iommu *iommu,
start_seg = base >> IO_SEGMENT_SHIFT;
segments = size >> IO_SEGMENT_SHIFT;
pages_per_segment = 1ull << IO_PAGENO_BITS(page_shift);
- /* PTEs for each segment must start on a 4K bounday */
+ /* PTEs for each segment must start on a 4K boundary */
pages_per_segment = max(pages_per_segment,
(1 << 12) / sizeof(unsigned long));
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 36cff28d0293..d3543e68efe8 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -255,13 +255,10 @@ static void __init cell_setup_arch(void)
static int __init cell_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "IBM,CBEA") &&
- !of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
+ if (!of_machine_is_compatible("IBM,CBEA") &&
+ !of_machine_is_compatible("IBM,CPBW-1.0"))
return 0;
- hpte_init_native();
pm_power_off = rtas_power_off;
return 1;
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 54ee5743cb72..d06dcac66fcb 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -217,7 +217,7 @@ static void spider_irq_cascade(struct irq_desc *desc)
chip->irq_eoi(&desc->irq_data);
}
-/* For hooking up the cascace we have a problem. Our device-tree is
+/* For hooking up the cascade we have a problem. Our device-tree is
* crap and we don't know on which BE iic interrupt we are hooked on at
* least not the "standard" way. We can reconstitute it based on two
* informations though: which BE node we are connected to and whether
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 3cbe38fad609..bb4a8e07c229 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -69,7 +69,7 @@ static DEFINE_SPINLOCK(spu_lock);
* spu_full_list_lock and spu_full_list_mutex held, while iterating
* through it requires either of these locks.
*
- * In addition spu_full_list_lock protects all assignmens to
+ * In addition spu_full_list_lock protects all assignments to
* spu->mm.
*/
static LIST_HEAD(spu_full_list);
@@ -253,7 +253,7 @@ static inline int __slb_present(struct copro_slb *slbs, int nr_slbs,
* Setup the SPU kernel SLBs, in preparation for a context save/restore. We
* need to map both the context save area, and the save/restore code.
*
- * Because the lscsa and code may cross segment boundaires, we check to see
+ * Because the lscsa and code may cross segment boundaries, we check to see
* if mappings are required for the start and end of each range. We currently
* assume that the mappings are smaller that one segment - if not, something
* is seriously wrong.
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index c3327f3d8cf7..21b4bfb97200 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -535,8 +535,7 @@ static int __init init_affinity(void)
if (of_has_vicinity()) {
init_affinity_fw();
} else {
- long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
+ if (of_machine_is_compatible("IBM,CPBW-1.0"))
init_affinity_qs20_harcoded();
else
printk("No affinity configuration found\n");
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 2936a0044c04..06254467e4dd 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -866,7 +866,7 @@ void spufs_wbox_callback(struct spu *spu)
* - end of the mapped area
*
* If the file is opened without O_NONBLOCK, we wait here until
- * space is availabyl, but return when we have been able to
+ * space is available, but return when we have been able to
* write something.
*/
static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 9f79004e6d6f..cfacbee24d7b 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -435,7 +435,7 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
/* Note: we don't need to force_sig SIGTRAP on single-step
* since we have TIF_SINGLESTEP set, thus the kernel will do
- * it upon return from the syscall anyawy
+ * it upon return from the syscall anyway.
*/
if (unlikely(status & SPU_STATUS_SINGLE_STEP))
ret = -ERESTARTSYS;
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 998f632e7cce..460f5f31d5cb 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -622,7 +622,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
/**
* find_victim - find a lower priority context to preempt
- * @ctx: canidate context for running
+ * @ctx: candidate context for running
*
* Returns the freed physical spu to run the new context on.
*/
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 987d1b8d68e3..bfb300633dfe 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -239,7 +239,7 @@ out:
of_node_put(np);
}
-static void briq_restart(char *cmd)
+static void __noreturn briq_restart(char *cmd)
{
local_irq_disable();
if (briq_SPOR)
@@ -253,7 +253,7 @@ static void briq_restart(char *cmd)
* But unfortunately, the firmware does not connect /chosen/{stdin,stdout}
* the the built-in serial node. Instead, a /failsafe node is created.
*/
-static __init void chrp_init_early(void)
+static __init void chrp_init(void)
{
struct device_node *node;
const char *property;
@@ -587,6 +587,8 @@ static int __init chrp_probe(void)
pm_power_off = rtas_power_off;
+ chrp_init();
+
return 1;
}
@@ -595,7 +597,6 @@ define_machine(chrp) {
.probe = chrp_probe,
.setup_arch = chrp_setup_arch,
.init = chrp_init2,
- .init_early = chrp_init_early,
.show_cpuinfo = chrp_show_cpuinfo,
.init_IRQ = chrp_init_IRQ,
.restart = rtas_restart,
diff --git a/arch/powerpc/platforms/embedded6xx/c2k.c b/arch/powerpc/platforms/embedded6xx/c2k.c
index ebd3963fdf91..d19e4e759597 100644
--- a/arch/powerpc/platforms/embedded6xx/c2k.c
+++ b/arch/powerpc/platforms/embedded6xx/c2k.c
@@ -99,7 +99,7 @@ static void c2k_reset_board(void)
out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_VALUE_SET, 0x00080004);
}
-static void c2k_restart(char *cmd)
+static void __noreturn c2k_restart(char *cmd)
{
c2k_reset_board();
msleep(100);
@@ -123,15 +123,16 @@ void c2k_show_cpuinfo(struct seq_file *m)
*/
static int __init c2k_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "GEFanuc,C2K"))
+ if (!of_machine_is_compatible("GEFanuc,C2K"))
return 0;
printk(KERN_INFO "Detected a GEFanuc C2K board\n");
_set_L2CR(0);
_set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2I);
+
+ mv64x60_init_early();
+
return 1;
}
@@ -139,7 +140,6 @@ define_machine(c2k) {
.name = "C2K",
.probe = c2k_probe,
.setup_arch = c2k_setup_arch,
- .init_early = mv64x60_init_early,
.show_cpuinfo = c2k_show_cpuinfo,
.init_IRQ = mv64x60_init_irq,
.get_irq = mv64x60_get_irq,
diff --git a/arch/powerpc/platforms/embedded6xx/gamecube.c b/arch/powerpc/platforms/embedded6xx/gamecube.c
index fe0ed6ee285e..36789cec957c 100644
--- a/arch/powerpc/platforms/embedded6xx/gamecube.c
+++ b/arch/powerpc/platforms/embedded6xx/gamecube.c
@@ -29,14 +29,14 @@
#include "usbgecko_udbg.h"
-static void gamecube_spin(void)
+static void __noreturn gamecube_spin(void)
{
/* spin until power button pressed */
for (;;)
cpu_relax();
}
-static void gamecube_restart(char *cmd)
+static void __noreturn gamecube_restart(char *cmd)
{
local_irq_disable();
flipper_platform_reset();
@@ -49,26 +49,20 @@ static void gamecube_power_off(void)
gamecube_spin();
}
-static void gamecube_halt(void)
+static void __noreturn gamecube_halt(void)
{
gamecube_restart(NULL);
}
-static void __init gamecube_init_early(void)
-{
- ug_udbg_init();
-}
-
static int __init gamecube_probe(void)
{
- unsigned long dt_root;
-
- dt_root = of_get_flat_dt_root();
- if (!of_flat_dt_is_compatible(dt_root, "nintendo,gamecube"))
+ if (!of_machine_is_compatible("nintendo,gamecube"))
return 0;
pm_power_off = gamecube_power_off;
+ ug_udbg_init();
+
return 1;
}
@@ -80,7 +74,6 @@ static void gamecube_shutdown(void)
define_machine(gamecube) {
.name = "gamecube",
.probe = gamecube_probe,
- .init_early = gamecube_init_early,
.restart = gamecube_restart,
.halt = gamecube_halt,
.init_IRQ = flipper_pic_probe,
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c
index 8c305c7c8977..dafba1057a47 100644
--- a/arch/powerpc/platforms/embedded6xx/holly.c
+++ b/arch/powerpc/platforms/embedded6xx/holly.c
@@ -193,7 +193,7 @@ void holly_show_cpuinfo(struct seq_file *m)
seq_printf(m, "machine\t\t: PPC750 GX/CL\n");
}
-void holly_restart(char *cmd)
+void __noreturn holly_restart(char *cmd)
{
__be32 __iomem *ocn_bar1 = NULL;
unsigned long bar;
@@ -250,9 +250,7 @@ void holly_halt(void)
*/
static int __init holly_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "ibm,holly"))
+ if (!of_machine_is_compatible("ibm,holly"))
return 0;
return 1;
}
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index 540eeb58d3f0..f29cf29b11f8 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -100,7 +100,7 @@ static void __init linkstation_init_IRQ(void)
extern void avr_uart_configure(void);
extern void avr_uart_send(const char);
-static void linkstation_restart(char *cmd)
+static void __noreturn linkstation_restart(char *cmd)
{
local_irq_disable();
@@ -113,7 +113,7 @@ static void linkstation_restart(char *cmd)
avr_uart_send('G'); /* "kick" */
}
-static void linkstation_power_off(void)
+static void __noreturn linkstation_power_off(void)
{
local_irq_disable();
@@ -127,7 +127,7 @@ static void linkstation_power_off(void)
/* NOTREACHED */
}
-static void linkstation_halt(void)
+static void __noreturn linkstation_halt(void)
{
linkstation_power_off();
/* NOTREACHED */
@@ -141,11 +141,7 @@ static void linkstation_show_cpuinfo(struct seq_file *m)
static int __init linkstation_probe(void)
{
- unsigned long root;
-
- root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "linkstation"))
+ if (!of_machine_is_compatible("linkstation"))
return 0;
pm_power_off = linkstation_power_off;
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index df4ad95f183e..80804f9916ee 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -146,7 +146,7 @@ void mpc7448_hpc2_show_cpuinfo(struct seq_file *m)
seq_printf(m, "vendor\t\t: Freescale Semiconductor\n");
}
-void mpc7448_hpc2_restart(char *cmd)
+static void __noreturn mpc7448_hpc2_restart(char *cmd)
{
local_irq_disable();
@@ -161,9 +161,7 @@ void mpc7448_hpc2_restart(char *cmd)
*/
static int __init mpc7448_hpc2_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "mpc74xx"))
+ if (!of_machine_is_compatible("mpc74xx"))
return 0;
return 1;
}
diff --git a/arch/powerpc/platforms/embedded6xx/mvme5100.c b/arch/powerpc/platforms/embedded6xx/mvme5100.c
index 8f65aa3747f5..ed7321d6772e 100644
--- a/arch/powerpc/platforms/embedded6xx/mvme5100.c
+++ b/arch/powerpc/platforms/embedded6xx/mvme5100.c
@@ -177,7 +177,7 @@ static void mvme5100_show_cpuinfo(struct seq_file *m)
seq_puts(m, "Machine\t\t: MVME5100\n");
}
-static void mvme5100_restart(char *cmd)
+static void __noreturn mvme5100_restart(char *cmd)
{
local_irq_disable();
@@ -194,9 +194,7 @@ static void mvme5100_restart(char *cmd)
*/
static int __init mvme5100_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "MVME5100");
+ return of_machine_is_compatible("MVME5100");
}
static int __init probe_of_platform_devices(void)
diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c
index d572833ebd00..471a50bcd074 100644
--- a/arch/powerpc/platforms/embedded6xx/storcenter.c
+++ b/arch/powerpc/platforms/embedded6xx/storcenter.c
@@ -96,7 +96,7 @@ static void __init storcenter_init_IRQ(void)
mpic_init(mpic);
}
-static void storcenter_restart(char *cmd)
+static void __noreturn storcenter_restart(char *cmd)
{
local_irq_disable();
@@ -109,9 +109,7 @@ static void storcenter_restart(char *cmd)
static int __init storcenter_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- return of_flat_dt_is_compatible(root, "iomega,storcenter");
+ return of_machine_is_compatible("iomega,storcenter");
}
define_machine(storcenter){
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
index 352592d3e44e..3fd683e40bc9 100644
--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -112,7 +112,7 @@ unsigned long __init wii_mmu_mapin_mem2(unsigned long top)
return delta + bl;
}
-static void wii_spin(void)
+static void __noreturn wii_spin(void)
{
local_irq_disable();
for (;;)
@@ -160,7 +160,7 @@ static void __init wii_setup_arch(void)
}
}
-static void wii_restart(char *cmd)
+static void __noreturn wii_restart(char *cmd)
{
local_irq_disable();
@@ -185,18 +185,13 @@ static void wii_power_off(void)
wii_spin();
}
-static void wii_halt(void)
+static void __noreturn wii_halt(void)
{
if (ppc_md.restart)
ppc_md.restart(NULL);
wii_spin();
}
-static void __init wii_init_early(void)
-{
- ug_udbg_init();
-}
-
static void __init wii_pic_probe(void)
{
flipper_pic_probe();
@@ -205,14 +200,13 @@ static void __init wii_pic_probe(void)
static int __init wii_probe(void)
{
- unsigned long dt_root;
-
- dt_root = of_get_flat_dt_root();
- if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii"))
+ if (!of_machine_is_compatible("nintendo,wii"))
return 0;
pm_power_off = wii_power_off;
+ ug_udbg_init();
+
return 1;
}
@@ -225,7 +219,6 @@ static void wii_shutdown(void)
define_machine(wii) {
.name = "wii",
.probe = wii_probe,
- .init_early = wii_init_early,
.setup_arch = wii_setup_arch,
.restart = wii_restart,
.halt = wii_halt,
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index a923230e575b..a2f89e6326ce 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -568,6 +568,26 @@ void maple_pci_irq_fixup(struct pci_dev *dev)
DBG(" <- maple_pci_irq_fixup\n");
}
+static int maple_pci_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+ struct pci_controller *hose = pci_bus_to_host(bridge->bus);
+ struct device_node *np, *child;
+
+ if (hose != u3_agp)
+ return 0;
+
+ /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
+ * assume there is no P2P bridge on the AGP bus, which should be a
+ * safe assumptions hopefully.
+ */
+ np = hose->dn;
+ PCI_DN(np)->busno = 0xf0;
+ for_each_child_of_node(np, child)
+ PCI_DN(child)->busno = 0xf0;
+
+ return 0;
+}
+
void __init maple_pci_init(void)
{
struct device_node *np, *root;
@@ -605,19 +625,7 @@ void __init maple_pci_init(void)
if (ht && maple_add_bridge(ht) != 0)
of_node_put(ht);
- /* Setup the linkage between OF nodes and PHBs */
- pci_devs_phb_init();
-
- /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
- * assume there is no P2P bridge on the AGP bus, which should be a
- * safe assumptions hopefully.
- */
- if (u3_agp) {
- struct device_node *np = u3_agp->dn;
- PCI_DN(np)->busno = 0xf0;
- for (np = np->child; np; np = np->sibling)
- PCI_DN(np)->busno = 0xf0;
- }
+ ppc_md.pcibios_root_bridge_prepare = maple_pci_root_bridge_prepare;
/* Tell pci.c to not change any resource allocations. */
pci_add_flags(PCI_PROBE_ONLY);
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index a837188544c8..3c30c7a4534d 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -94,7 +94,7 @@ static unsigned long maple_find_nvram_base(void)
return result;
}
-static void maple_restart(char *cmd)
+static void __noreturn maple_restart(char *cmd)
{
unsigned int maple_nvram_base;
const unsigned int *maple_nvram_offset, *maple_nvram_command;
@@ -119,9 +119,10 @@ static void maple_restart(char *cmd)
for (;;) ;
fail:
printk(KERN_EMERG "Maple: Manual Restart Required\n");
+ for (;;) ;
}
-static void maple_power_off(void)
+static void __noreturn maple_power_off(void)
{
unsigned int maple_nvram_base;
const unsigned int *maple_nvram_offset, *maple_nvram_command;
@@ -146,9 +147,10 @@ static void maple_power_off(void)
for (;;) ;
fail:
printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
+ for (;;) ;
}
-static void maple_halt(void)
+static void __noreturn maple_halt(void)
{
maple_power_off();
}
@@ -196,18 +198,6 @@ void __init maple_setup_arch(void)
mmio_nvram_init();
}
-/*
- * Early initialization.
- */
-static void __init maple_init_early(void)
-{
- DBG(" -> maple_init_early\n");
-
- iommu_init_early_dart(&maple_pci_controller_ops);
-
- DBG(" <- maple_init_early\n");
-}
-
/*
* This is almost identical to pSeries and CHRP. We need to make that
* code generic at one point, with appropriate bits in the device-tree to
@@ -298,22 +288,14 @@ static void __init maple_progress(char *s, unsigned short hex)
*/
static int __init maple_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "Momentum,Maple") &&
- !of_flat_dt_is_compatible(root, "Momentum,Apache"))
+ if (!of_machine_is_compatible("Momentum,Maple") &&
+ !of_machine_is_compatible("Momentum,Apache"))
return 0;
- /*
- * On U3, the DART (iommu) must be allocated now since it
- * has an impact on htab_initialize (due to the large page it
- * occupies having to be broken up so the DART itself is not
- * part of the cacheable linar mapping
- */
- alloc_dart_table();
- hpte_init_native();
pm_power_off = maple_power_off;
+ iommu_init_early_dart(&maple_pci_controller_ops);
+
return 1;
}
@@ -321,7 +303,6 @@ define_machine(maple) {
.name = "Maple",
.probe = maple_probe,
.setup_arch = maple_setup_arch,
- .init_early = maple_init_early,
.init_IRQ = maple_init_IRQ,
.pci_irq_fixup = maple_pci_irq_fixup,
.pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq,
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
index c929644e74a6..43dd3fb514e0 100644
--- a/arch/powerpc/platforms/pasemi/iommu.c
+++ b/arch/powerpc/platforms/pasemi/iommu.c
@@ -202,6 +202,11 @@ int __init iob_init(struct device_node *dn)
pr_debug(" -> %s\n", __func__);
+ /* For 2G space, 8x64 pages (2^21 bytes) is max total l2 size */
+ iob_l2_base = (u32 *)__va(memblock_alloc_base(1UL<<21, 1UL<<21, 0x80000000));
+
+ printk(KERN_INFO "IOBMAP L2 allocated at: %p\n", iob_l2_base);
+
/* Allocate a spare page to map all invalid IOTLB pages. */
tmp = memblock_alloc(IOBMAP_PAGE_SIZE, IOBMAP_PAGE_SIZE);
if (!tmp)
@@ -260,13 +265,3 @@ void __init iommu_init_early_pasemi(void)
set_pci_dma_ops(&dma_iommu_ops);
}
-void __init alloc_iobmap_l2(void)
-{
-#ifndef CONFIG_PPC_PASEMI_IOMMU
- return;
-#endif
- /* For 2G space, 8x64 pages (2^21 bytes) is max total l2 size */
- iob_l2_base = (u32 *)__va(memblock_alloc_base(1UL<<21, 1UL<<21, 0x80000000));
-
- printk(KERN_INFO "IOBMAP L2 allocated at: %p\n", iob_l2_base);
-}
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h
index 11f230a48227..74cbcb357612 100644
--- a/arch/powerpc/platforms/pasemi/pasemi.h
+++ b/arch/powerpc/platforms/pasemi/pasemi.h
@@ -8,7 +8,6 @@ extern void pas_pci_dma_dev_setup(struct pci_dev *dev);
extern void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset);
-extern void __init alloc_iobmap_l2(void);
extern void __init pasemi_map_registers(void);
/* Power savings modes, implemented in asm */
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c
index f3a68a0fef23..10c4e8fc6ea9 100644
--- a/arch/powerpc/platforms/pasemi/pci.c
+++ b/arch/powerpc/platforms/pasemi/pci.c
@@ -229,9 +229,6 @@ void __init pas_pci_init(void)
of_node_get(np);
of_node_put(root);
-
- /* Setup the linkage between OF nodes and PHBs */
- pci_devs_phb_init();
}
void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset)
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index d71b2c7e8403..e86c1bd08f1f 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -62,7 +62,7 @@ static int num_mce_regs;
static int nmi_virq = NO_IRQ;
-static void pas_restart(char *cmd)
+static void __noreturn pas_restart(char *cmd)
{
/* Need to put others cpu in hold loop so they're not sleeping */
smp_send_stop();
@@ -339,11 +339,6 @@ out:
return !!(srr1 & 0x2);
}
-static void __init pas_init_early(void)
-{
- iommu_init_early_pasemi();
-}
-
#ifdef CONFIG_PCMCIA
static int pcmcia_notify(struct notifier_block *nb, unsigned long action,
void *data)
@@ -420,15 +415,11 @@ machine_device_initcall(pasemi, pasemi_publish_devices);
*/
static int __init pas_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "PA6T-1682M") &&
- !of_flat_dt_is_compatible(root, "pasemi,pwrficient"))
+ if (!of_machine_is_compatible("PA6T-1682M") &&
+ !of_machine_is_compatible("pasemi,pwrficient"))
return 0;
- hpte_init_native();
-
- alloc_iobmap_l2();
+ iommu_init_early_pasemi();
return 1;
}
@@ -437,7 +428,6 @@ define_machine(pasemi) {
.name = "PA Semi PWRficient",
.probe = pas_probe,
.setup_arch = pas_setup_arch,
- .init_early = pas_init_early,
.init_IRQ = pas_init_IRQ,
.get_irq = mpic_get_irq,
.restart = pas_restart,
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 7553b6a77c64..6d6f277477aa 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -15,7 +15,7 @@
* This file thus provides a simple low level unified i2c interface for
* powermac that covers the various types of i2c busses used in Apple machines.
* For now, keywest, PMU and SMU, though we could add Cuda, or other bit
- * banging busses found on older chipstes in earlier machines if we ever need
+ * banging busses found on older chipsets in earlier machines if we ever need
* one of them.
*
* The drivers in this file are synchronous/blocking. In addition, the
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index 59ab16fa600f..6e06c3be2e9a 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -878,6 +878,29 @@ void pmac_pci_irq_fixup(struct pci_dev *dev)
#endif /* CONFIG_PPC32 */
}
+#ifdef CONFIG_PPC64
+static int pmac_pci_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+ struct pci_controller *hose = pci_bus_to_host(bridge->bus);
+ struct device_node *np, *child;
+
+ if (hose != u3_agp)
+ return 0;
+
+ /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
+ * assume there is no P2P bridge on the AGP bus, which should be a
+ * safe assumptions for now. We should do something better in the
+ * future though
+ */
+ np = hose->dn;
+ PCI_DN(np)->busno = 0xf0;
+ for_each_child_of_node(np, child)
+ PCI_DN(child)->busno = 0xf0;
+
+ return 0;
+}
+#endif /* CONFIG_PPC64 */
+
void __init pmac_pci_init(void)
{
struct device_node *np, *root;
@@ -914,20 +937,7 @@ void __init pmac_pci_init(void)
if (ht && pmac_add_bridge(ht) != 0)
of_node_put(ht);
- /* Setup the linkage between OF nodes and PHBs */
- pci_devs_phb_init();
-
- /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
- * assume there is no P2P bridge on the AGP bus, which should be a
- * safe assumptions for now. We should do something better in the
- * future though
- */
- if (u3_agp) {
- struct device_node *np = u3_agp->dn;
- PCI_DN(np)->busno = 0xf0;
- for (np = np->child; np; np = np->sibling)
- PCI_DN(np)->busno = 0xf0;
- }
+ ppc_md.pcibios_root_bridge_prepare = pmac_pci_root_bridge_prepare;
/* pmac_check_ht_link(); */
#else /* CONFIG_PPC64 */
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 8dd78f4e1af4..3de4a7c85140 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -52,7 +52,6 @@
#include <linux/suspend.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
-#include <linux/memblock.h>
#include <asm/reg.h>
#include <asm/sections.h>
@@ -97,11 +96,6 @@ int sccdbg;
sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
EXPORT_SYMBOL(sys_ctrler);
-#ifdef CONFIG_PMAC_SMU
-unsigned long smu_cmdbuf_abs;
-EXPORT_SYMBOL(smu_cmdbuf_abs);
-#endif
-
static void pmac_show_cpuinfo(struct seq_file *m)
{
struct device_node *np;
@@ -325,7 +319,6 @@ static void __init pmac_setup_arch(void)
defined(CONFIG_PPC64)
pmac_nvram_init();
#endif
-
#ifdef CONFIG_PPC32
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
@@ -383,7 +376,7 @@ void __init_refok note_bootable_part(dev_t dev, int part, int goodness)
}
#ifdef CONFIG_ADB_CUDA
-static void cuda_restart(void)
+static void __noreturn cuda_restart(void)
{
struct adb_request req;
@@ -392,7 +385,7 @@ static void cuda_restart(void)
cuda_poll();
}
-static void cuda_shutdown(void)
+static void __noreturn cuda_shutdown(void)
{
struct adb_request req;
@@ -416,7 +409,7 @@ static void cuda_shutdown(void)
#define smu_shutdown()
#endif
-static void pmac_restart(char *cmd)
+static void __noreturn pmac_restart(char *cmd)
{
switch (sys_ctrler) {
case SYS_CTRLER_CUDA:
@@ -430,9 +423,10 @@ static void pmac_restart(char *cmd)
break;
default: ;
}
+ while (1) ;
}
-static void pmac_power_off(void)
+static void __noreturn pmac_power_off(void)
{
switch (sys_ctrler) {
case SYS_CTRLER_CUDA:
@@ -446,9 +440,10 @@ static void pmac_power_off(void)
break;
default: ;
}
+ while (1) ;
}
-static void
+static void __noreturn
pmac_halt(void)
{
pmac_power_off();
@@ -457,7 +452,7 @@ pmac_halt(void)
/*
* Early initialization.
*/
-static void __init pmac_init_early(void)
+static void __init pmac_init(void)
{
/* Enable early btext debug if requested */
if (strstr(boot_command_line, "btextdbg")) {
@@ -489,9 +484,6 @@ static int __init pmac_declare_of_platform_devices(void)
{
struct device_node *np;
- if (machine_is(chrp))
- return -1;
-
np = of_find_node_by_name(NULL, "valkyrie");
if (np) {
of_platform_device_create(np, "valkyrie", NULL);
@@ -598,24 +590,10 @@ console_initcall(check_pmac_serial_console);
*/
static int __init pmac_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "Power Macintosh") &&
- !of_flat_dt_is_compatible(root, "MacRISC"))
+ if (!of_machine_is_compatible("Power Macintosh") &&
+ !of_machine_is_compatible("MacRISC"))
return 0;
-#ifdef CONFIG_PPC64
- /*
- * On U3, the DART (iommu) must be allocated now since it
- * has an impact on htab_initialize (due to the large page it
- * occupies having to be broken up so the DART itself is not
- * part of the cacheable linar mapping
- */
- alloc_dart_table();
-
- hpte_init_native();
-#endif
-
#ifdef CONFIG_PPC32
/* isa_io_base gets set in pmac_pci_init */
ISA_DMA_THRESHOLD = ~0L;
@@ -623,17 +601,10 @@ static int __init pmac_probe(void)
DMA_MODE_WRITE = 2;
#endif /* CONFIG_PPC32 */
-#ifdef CONFIG_PMAC_SMU
- /*
- * SMU based G5s need some memory below 2Gb, at least the current
- * driver needs that. We have to allocate it now. We allocate 4k
- * (1 small page) for now.
- */
- smu_cmdbuf_abs = memblock_alloc_base(4096, 4096, 0x80000000UL);
-#endif /* CONFIG_PMAC_SMU */
-
pm_power_off = pmac_power_off;
+ pmac_init();
+
return 1;
}
@@ -641,7 +612,6 @@ define_machine(powermac) {
.name = "PowerMac",
.probe = pmac_probe,
.setup_arch = pmac_setup_arch,
- .init_early = pmac_init_early,
.show_cpuinfo = pmac_show_cpuinfo,
.init_IRQ = pmac_pic_init,
.get_irq = NULL, /* changed later */
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 28a147ca32ba..834868b9fdc9 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -857,9 +857,8 @@ static int smp_core99_cpu_notify(struct notifier_block *self,
{
int rc;
- switch(action) {
+ switch(action & ~CPU_TASKS_FROZEN) {
case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
/* Open i2c bus if it was used for tb sync */
if (pmac_tb_clock_chip_host) {
rc = pmac_i2c_open(pmac_tb_clock_chip_host, 1);
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index cd9711e72df6..b5d98cb3f482 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -6,6 +6,7 @@ obj-y += opal-kmsg.o
obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o
obj-$(CONFIG_PCI) += pci.o pci-ioda.o npu-dma.o
+obj-$(CONFIG_CXL_BASE) += pci-cxl.o
obj-$(CONFIG_EEH) += eeh-powernv.o
obj-$(CONFIG_PPC_SCOM) += opal-xscom.o
obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 9226df11bf39..86544ea85dc3 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -36,6 +36,7 @@
#include <asm/msi_bitmap.h>
#include <asm/opal.h>
#include <asm/ppc-pci.h>
+#include <asm/pnv-pci.h>
#include "powernv.h"
#include "pci.h"
@@ -717,12 +718,12 @@ static int pnv_eeh_get_state(struct eeh_pe *pe, int *delay)
return ret;
}
-static s64 pnv_eeh_phb_poll(struct pnv_phb *phb)
+static s64 pnv_eeh_poll(unsigned long id)
{
s64 rc = OPAL_HARDWARE;
while (1) {
- rc = opal_pci_poll(phb->opal_id);
+ rc = opal_pci_poll(id);
if (rc <= 0)
break;
@@ -762,7 +763,7 @@ int pnv_eeh_phb_reset(struct pci_controller *hose, int option)
* reset followed by hot reset on root bus. So we also
* need the PCI bus settlement delay.
*/
- rc = pnv_eeh_phb_poll(phb);
+ rc = pnv_eeh_poll(phb->opal_id);
if (option == EEH_RESET_DEACTIVATE) {
if (system_state < SYSTEM_RUNNING)
udelay(1000 * EEH_PE_RST_SETTLE_TIME);
@@ -805,7 +806,7 @@ static int pnv_eeh_root_reset(struct pci_controller *hose, int option)
goto out;
/* Poll state of the PHB until the request is done */
- rc = pnv_eeh_phb_poll(phb);
+ rc = pnv_eeh_poll(phb->opal_id);
if (option == EEH_RESET_DEACTIVATE)
msleep(EEH_PE_RST_SETTLE_TIME);
out:
@@ -815,7 +816,7 @@ out:
return 0;
}
-static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option)
+static int __pnv_eeh_bridge_reset(struct pci_dev *dev, int option)
{
struct pci_dn *pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn);
struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
@@ -866,6 +867,44 @@ static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option)
return 0;
}
+static int pnv_eeh_bridge_reset(struct pci_dev *pdev, int option)
+{
+ struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ struct device_node *dn = pci_device_to_OF_node(pdev);
+ uint64_t id = PCI_SLOT_ID(phb->opal_id,
+ (pdev->bus->number << 8) | pdev->devfn);
+ uint8_t scope;
+ int64_t rc;
+
+ /* Hot reset to the bus if firmware cannot handle */
+ if (!dn || !of_get_property(dn, "ibm,reset-by-firmware", NULL))
+ return __pnv_eeh_bridge_reset(pdev, option);
+
+ switch (option) {
+ case EEH_RESET_FUNDAMENTAL:
+ scope = OPAL_RESET_PCI_FUNDAMENTAL;
+ break;
+ case EEH_RESET_HOT:
+ scope = OPAL_RESET_PCI_HOT;
+ break;
+ case EEH_RESET_DEACTIVATE:
+ return 0;
+ default:
+ dev_dbg(&pdev->dev, "%s: Unsupported reset %d\n",
+ __func__, option);
+ return -EINVAL;
+ }
+
+ rc = opal_pci_reset(id, scope, OPAL_ASSERT_RESET);
+ if (rc <= OPAL_SUCCESS)
+ goto out;
+
+ rc = pnv_eeh_poll(id);
+out:
+ return (rc == OPAL_SUCCESS) ? 0 : -EIO;
+}
+
void pnv_pci_reset_secondary_bus(struct pci_dev *dev)
{
struct pci_controller *hose;
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index fcc8b6861b63..479c25601612 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -27,9 +27,12 @@
#include "powernv.h"
#include "subcore.h"
+/* Power ISA 3.0 allows for stop states 0x0 - 0xF */
+#define MAX_STOP_STATE 0xF
+
static u32 supported_cpuidle_states;
-int pnv_save_sprs_for_winkle(void)
+static int pnv_save_sprs_for_deep_states(void)
{
int cpu;
int rc;
@@ -50,15 +53,19 @@ int pnv_save_sprs_for_winkle(void)
uint64_t pir = get_hard_smp_processor_id(cpu);
uint64_t hsprg0_val = (uint64_t)&paca[cpu];
- /*
- * HSPRG0 is used to store the cpu's pointer to paca. Hence last
- * 3 bits are guaranteed to be 0. Program slw to restore HSPRG0
- * with 63rd bit set, so that when a thread wakes up at 0x100 we
- * can use this bit to distinguish between fastsleep and
- * deep winkle.
- */
- hsprg0_val |= 1;
-
+ if (!cpu_has_feature(CPU_FTR_ARCH_300)) {
+ /*
+ * HSPRG0 is used to store the cpu's pointer to paca.
+ * Hence last 3 bits are guaranteed to be 0. Program
+ * slw to restore HSPRG0 with 63rd bit set, so that
+ * when a thread wakes up at 0x100 we can use this bit
+ * to distinguish between fastsleep and deep winkle.
+ * This is not necessary with stop/psscr since PLS
+ * field of psscr indicates which state we are waking
+ * up from.
+ */
+ hsprg0_val |= 1;
+ }
rc = opal_slw_set_reg(pir, SPRN_HSPRG0, hsprg0_val);
if (rc != 0)
return rc;
@@ -130,8 +137,8 @@ static void pnv_alloc_idle_core_states(void)
update_subcore_sibling_mask();
- if (supported_cpuidle_states & OPAL_PM_WINKLE_ENABLED)
- pnv_save_sprs_for_winkle();
+ if (supported_cpuidle_states & OPAL_PM_LOSE_FULL_CONTEXT)
+ pnv_save_sprs_for_deep_states();
}
u32 pnv_get_supported_cpuidle_states(void)
@@ -230,43 +237,162 @@ static DEVICE_ATTR(fastsleep_workaround_applyonce, 0600,
show_fastsleep_workaround_applyonce,
store_fastsleep_workaround_applyonce);
-static int __init pnv_init_idle_states(void)
+
+/*
+ * Used for ppc_md.power_save which needs a function with no parameters
+ */
+static void power9_idle(void)
{
- struct device_node *power_mgt;
- int dt_idle_states;
- u32 *flags;
- int i;
+ /* Requesting stop state 0 */
+ power9_idle_stop(0);
+}
+/*
+ * First deep stop state. Used to figure out when to save/restore
+ * hypervisor context.
+ */
+u64 pnv_first_deep_stop_state = MAX_STOP_STATE;
- supported_cpuidle_states = 0;
+/*
+ * Deepest stop idle state. Used when a cpu is offlined
+ */
+u64 pnv_deepest_stop_state;
- if (cpuidle_disable != IDLE_NO_OVERRIDE)
- goto out;
+/*
+ * Power ISA 3.0 idle initialization.
+ *
+ * POWER ISA 3.0 defines a new SPR Processor stop Status and Control
+ * Register (PSSCR) to control idle behavior.
+ *
+ * PSSCR layout:
+ * ----------------------------------------------------------
+ * | PLS | /// | SD | ESL | EC | PSLL | /// | TR | MTL | RL |
+ * ----------------------------------------------------------
+ * 0 4 41 42 43 44 48 54 56 60
+ *
+ * PSSCR key fields:
+ * Bits 0:3 - Power-Saving Level Status (PLS). This field indicates the
+ * lowest power-saving state the thread entered since stop instruction was
+ * last executed.
+ *
+ * Bit 41 - Status Disable(SD)
+ * 0 - Shows PLS entries
+ * 1 - PLS entries are all 0
+ *
+ * Bit 42 - Enable State Loss
+ * 0 - No state is lost irrespective of other fields
+ * 1 - Allows state loss
+ *
+ * Bit 43 - Exit Criterion
+ * 0 - Exit from power-save mode on any interrupt
+ * 1 - Exit from power-save mode controlled by LPCR's PECE bits
+ *
+ * Bits 44:47 - Power-Saving Level Limit
+ * This limits the power-saving level that can be entered into.
+ *
+ * Bits 60:63 - Requested Level
+ * Used to specify which power-saving level must be entered on executing
+ * stop instruction
+ *
+ * @np: /ibm,opal/power-mgt device node
+ * @flags: cpu-idle-state-flags array
+ * @dt_idle_states: Number of idle state entries
+ * Returns 0 on success
+ */
+static int __init pnv_arch300_idle_init(struct device_node *np, u32 *flags,
+ int dt_idle_states)
+{
+ u64 *psscr_val = NULL;
+ int rc = 0, i;
- if (!firmware_has_feature(FW_FEATURE_OPAL))
+ psscr_val = kcalloc(dt_idle_states, sizeof(*psscr_val),
+ GFP_KERNEL);
+ if (!psscr_val) {
+ rc = -1;
+ goto out;
+ }
+ if (of_property_read_u64_array(np,
+ "ibm,cpu-idle-state-psscr",
+ psscr_val, dt_idle_states)) {
+ pr_warn("cpuidle-powernv: missing ibm,cpu-idle-states-psscr in DT\n");
+ rc = -1;
goto out;
+ }
- power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
- if (!power_mgt) {
+ /*
+ * Set pnv_first_deep_stop_state and pnv_deepest_stop_state.
+ * pnv_first_deep_stop_state should be set to the first stop
+ * level to cause hypervisor state loss.
+ * pnv_deepest_stop_state should be set to the deepest stop
+ * stop state.
+ */
+ pnv_first_deep_stop_state = MAX_STOP_STATE;
+ for (i = 0; i < dt_idle_states; i++) {
+ u64 psscr_rl = psscr_val[i] & PSSCR_RL_MASK;
+
+ if ((flags[i] & OPAL_PM_LOSE_FULL_CONTEXT) &&
+ (pnv_first_deep_stop_state > psscr_rl))
+ pnv_first_deep_stop_state = psscr_rl;
+
+ if (pnv_deepest_stop_state < psscr_rl)
+ pnv_deepest_stop_state = psscr_rl;
+ }
+
+out:
+ kfree(psscr_val);
+ return rc;
+}
+
+/*
+ * Probe device tree for supported idle states
+ */
+static void __init pnv_probe_idle_states(void)
+{
+ struct device_node *np;
+ int dt_idle_states;
+ u32 *flags = NULL;
+ int i;
+
+ np = of_find_node_by_path("/ibm,opal/power-mgt");
+ if (!np) {
pr_warn("opal: PowerMgmt Node not found\n");
goto out;
}
- dt_idle_states = of_property_count_u32_elems(power_mgt,
+ dt_idle_states = of_property_count_u32_elems(np,
"ibm,cpu-idle-state-flags");
if (dt_idle_states < 0) {
pr_warn("cpuidle-powernv: no idle states found in the DT\n");
goto out;
}
- flags = kzalloc(sizeof(*flags) * dt_idle_states, GFP_KERNEL);
- if (of_property_read_u32_array(power_mgt,
+ flags = kcalloc(dt_idle_states, sizeof(*flags), GFP_KERNEL);
+
+ if (of_property_read_u32_array(np,
"ibm,cpu-idle-state-flags", flags, dt_idle_states)) {
pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-flags in DT\n");
- goto out_free;
+ goto out;
+ }
+
+ if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+ if (pnv_arch300_idle_init(np, flags, dt_idle_states))
+ goto out;
}
for (i = 0; i < dt_idle_states; i++)
supported_cpuidle_states |= flags[i];
+out:
+ kfree(flags);
+}
+static int __init pnv_init_idle_states(void)
+{
+
+ supported_cpuidle_states = 0;
+
+ if (cpuidle_disable != IDLE_NO_OVERRIDE)
+ goto out;
+
+ pnv_probe_idle_states();
+
if (!(supported_cpuidle_states & OPAL_PM_SLEEP_ENABLED_ER1)) {
patch_instruction(
(unsigned int *)pnv_fastsleep_workaround_at_entry,
@@ -285,8 +411,12 @@ static int __init pnv_init_idle_states(void)
}
pnv_alloc_idle_core_states();
-out_free:
- kfree(flags);
+
+ if (supported_cpuidle_states & OPAL_PM_NAP_ENABLED)
+ ppc_md.power_save = power7_idle;
+ else if (supported_cpuidle_states & OPAL_PM_STOP_INST_FAST)
+ ppc_md.power_save = power9_idle;
+
out:
return 0;
}
diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c
index 0459e100b4e7..4383a5ff82ba 100644
--- a/arch/powerpc/platforms/powernv/npu-dma.c
+++ b/arch/powerpc/platforms/powernv/npu-dma.c
@@ -180,7 +180,7 @@ long pnv_npu_set_window(struct pnv_ioda_pe *npe, int num,
pe_err(npe, "Failed to configure TCE table, err %lld\n", rc);
return rc;
}
- pnv_pci_ioda2_tce_invalidate_entire(phb, false);
+ pnv_pci_phb3_tce_invalidate_entire(phb, false);
/* Add the table to the list so its TCE cache will get invalidated */
pnv_pci_link_table_and_group(phb->hose->node, num,
@@ -204,7 +204,7 @@ long pnv_npu_unset_window(struct pnv_ioda_pe *npe, int num)
pe_err(npe, "Unmapping failed, ret = %lld\n", rc);
return rc;
}
- pnv_pci_ioda2_tce_invalidate_entire(phb, false);
+ pnv_pci_phb3_tce_invalidate_entire(phb, false);
pnv_pci_unlink_table_and_group(npe->table_group.tables[num],
&npe->table_group);
@@ -270,7 +270,7 @@ static int pnv_npu_dma_set_bypass(struct pnv_ioda_pe *npe)
0 /* bypass base */, top);
if (rc == OPAL_SUCCESS)
- pnv_pci_ioda2_tce_invalidate_entire(phb, false);
+ pnv_pci_phb3_tce_invalidate_entire(phb, false);
return rc;
}
@@ -334,7 +334,7 @@ void pnv_npu_take_ownership(struct pnv_ioda_pe *npe)
pe_err(npe, "Failed to disable bypass, err %lld\n", rc);
return;
}
- pnv_pci_ioda2_tce_invalidate_entire(npe->phb, false);
+ pnv_pci_phb3_tce_invalidate_entire(npe->phb, false);
}
struct pnv_ioda_pe *pnv_pci_npu_setup_iommu(struct pnv_ioda_pe *npe)
diff --git a/arch/powerpc/platforms/powernv/opal-async.c b/arch/powerpc/platforms/powernv/opal-async.c
index bdc8c0c71d15..83bebeec0fea 100644
--- a/arch/powerpc/platforms/powernv/opal-async.c
+++ b/arch/powerpc/platforms/powernv/opal-async.c
@@ -117,6 +117,11 @@ int opal_async_wait_response(uint64_t token, struct opal_msg *msg)
return -EINVAL;
}
+ /* Wakeup the poller before we wait for events to speed things
+ * up on platforms or simulators where the interrupts aren't
+ * functional.
+ */
+ opal_wake_poller();
wait_event(opal_async_wait, test_bit(token, opal_async_complete_map));
memcpy(msg, &opal_async_responses[token], sizeof(*msg));
diff --git a/arch/powerpc/platforms/powernv/opal-memory-errors.c b/arch/powerpc/platforms/powernv/opal-memory-errors.c
index 00a29432be39..4495f428b500 100644
--- a/arch/powerpc/platforms/powernv/opal-memory-errors.c
+++ b/arch/powerpc/platforms/powernv/opal-memory-errors.c
@@ -44,7 +44,7 @@ static void handle_memory_error_event(struct OpalMemoryErrorData *merr_evt)
{
uint64_t paddr_start, paddr_end;
- pr_debug("%s: Retrived memory error event, type: 0x%x\n",
+ pr_debug("%s: Retrieved memory error event, type: 0x%x\n",
__func__, merr_evt->type);
switch (merr_evt->type) {
case OPAL_MEM_ERR_TYPE_RESILIENCE:
diff --git a/arch/powerpc/platforms/powernv/opal-sensor.c b/arch/powerpc/platforms/powernv/opal-sensor.c
index a06059df9239..308efd170c27 100644
--- a/arch/powerpc/platforms/powernv/opal-sensor.c
+++ b/arch/powerpc/platforms/powernv/opal-sensor.c
@@ -55,7 +55,7 @@ int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data)
goto out_token;
}
- ret = opal_error_code(be64_to_cpu(msg.params[1]));
+ ret = opal_error_code(opal_get_async_rc(msg));
*sensor_data = be32_to_cpu(data);
break;
diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c b/arch/powerpc/platforms/powernv/opal-sysparam.c
index afe66c576a38..23fb6647dced 100644
--- a/arch/powerpc/platforms/powernv/opal-sysparam.c
+++ b/arch/powerpc/platforms/powernv/opal-sysparam.c
@@ -67,7 +67,7 @@ static ssize_t opal_get_sys_param(u32 param_id, u32 length, void *buffer)
goto out_token;
}
- ret = opal_error_code(be64_to_cpu(msg.params[1]));
+ ret = opal_error_code(opal_get_async_rc(msg));
out_token:
opal_async_release_token(token);
@@ -103,7 +103,7 @@ static int opal_set_sys_param(u32 param_id, u32 length, void *buffer)
goto out_token;
}
- ret = opal_error_code(be64_to_cpu(msg.params[1]));
+ ret = opal_error_code(opal_get_async_rc(msg));
out_token:
opal_async_release_token(token);
diff --git a/arch/powerpc/platforms/powernv/opal-tracepoints.c b/arch/powerpc/platforms/powernv/opal-tracepoints.c
index e11273b2386d..1e496b780efd 100644
--- a/arch/powerpc/platforms/powernv/opal-tracepoints.c
+++ b/arch/powerpc/platforms/powernv/opal-tracepoints.c
@@ -1,6 +1,7 @@
#include <linux/percpu.h>
#include <linux/jump_label.h>
#include <asm/trace.h>
+#include <asm/asm-prototypes.h>
#ifdef HAVE_JUMP_LABEL
struct static_key opal_tracepoint_key = STATIC_KEY_INIT;
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index e45b88a5d7e0..cf928bba4d9a 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -59,7 +59,7 @@ END_FTR_SECTION(0, 1); \
#define OPAL_CALL(name, token) \
_GLOBAL_TOC(name); \
mflr r0; \
- std r0,16(r1); \
+ std r0,PPC_LR_STKOFF(r1); \
li r0,token; \
OPAL_BRANCH(opal_tracepoint_entry) \
mfcr r12; \
@@ -92,7 +92,7 @@ opal_return:
FIXUP_ENDIAN
ld r2,PACATOC(r13);
lwz r4,8(r1);
- ld r5,16(r1);
+ ld r5,PPC_LR_STKOFF(r1);
ld r6,PACASAVEDMSR(r13);
mtspr SPRN_SRR0,r5;
mtspr SPRN_SRR1,r6;
@@ -157,43 +157,37 @@ opal_tracepoint_return:
blr
#endif
-/*
- * Make opal call in realmode. This is a generic function to be called
- * from realmode. It handles endianness.
- *
- * r13 - paca pointer
- * r1 - stack pointer
- * r0 - opal token
- */
-_GLOBAL(opal_call_realmode)
- mflr r12
- std r12,PPC_LR_STKOFF(r1)
- ld r2,PACATOC(r13)
- /* Set opal return address */
- LOAD_REG_ADDR(r12,return_from_opal_call)
- mtlr r12
-
- mfmsr r12
-#ifdef __LITTLE_ENDIAN__
- /* Handle endian-ness */
- li r11,MSR_LE
- andc r12,r12,r11
-#endif
- mtspr SPRN_HSRR1,r12
- LOAD_REG_ADDR(r11,opal)
- ld r12,8(r11)
- ld r2,0(r11)
- mtspr SPRN_HSRR0,r12
+#define OPAL_CALL_REAL(name, token) \
+ _GLOBAL_TOC(name); \
+ mflr r0; \
+ std r0,PPC_LR_STKOFF(r1); \
+ li r0,token; \
+ mfcr r12; \
+ stw r12,8(r1); \
+ \
+ /* Set opal return address */ \
+ LOAD_REG_ADDR(r11, opal_return_realmode); \
+ mtlr r11; \
+ mfmsr r12; \
+ li r11,MSR_LE; \
+ andc r12,r12,r11; \
+ mtspr SPRN_HSRR1,r12; \
+ LOAD_REG_ADDR(r11,opal); \
+ ld r12,8(r11); \
+ ld r2,0(r11); \
+ mtspr SPRN_HSRR0,r12; \
hrfid
-return_from_opal_call:
-#ifdef __LITTLE_ENDIAN__
+opal_return_realmode:
FIXUP_ENDIAN
-#endif
+ ld r2,PACATOC(r13);
+ lwz r11,8(r1);
ld r12,PPC_LR_STKOFF(r1)
+ mtcr r11;
mtlr r12
blr
+
OPAL_CALL(opal_invalid_call, OPAL_INVALID_CALL);
OPAL_CALL(opal_console_write, OPAL_CONSOLE_WRITE);
OPAL_CALL(opal_console_read, OPAL_CONSOLE_READ);
@@ -271,6 +265,7 @@ OPAL_CALL(opal_validate_flash, OPAL_FLASH_VALIDATE);
OPAL_CALL(opal_manage_flash, OPAL_FLASH_MANAGE);
OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE);
OPAL_CALL(opal_resync_timebase, OPAL_RESYNC_TIMEBASE);
+OPAL_CALL_REAL(opal_rm_resync_timebase, OPAL_RESYNC_TIMEBASE);
OPAL_CALL(opal_check_token, OPAL_CHECK_TOKEN);
OPAL_CALL(opal_dump_init, OPAL_DUMP_INIT);
OPAL_CALL(opal_dump_info, OPAL_DUMP_INFO);
@@ -278,6 +273,7 @@ OPAL_CALL(opal_dump_info2, OPAL_DUMP_INFO2);
OPAL_CALL(opal_dump_read, OPAL_DUMP_READ);
OPAL_CALL(opal_dump_ack, OPAL_DUMP_ACK);
OPAL_CALL(opal_get_msg, OPAL_GET_MSG);
+OPAL_CALL(opal_write_oppanel_async, OPAL_WRITE_OPPANEL_ASYNC);
OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION);
OPAL_CALL(opal_dump_resend_notification, OPAL_DUMP_RESEND);
OPAL_CALL(opal_sync_host_reboot, OPAL_SYNC_HOST_REBOOT);
@@ -285,7 +281,9 @@ OPAL_CALL(opal_sensor_read, OPAL_SENSOR_READ);
OPAL_CALL(opal_get_param, OPAL_GET_PARAM);
OPAL_CALL(opal_set_param, OPAL_SET_PARAM);
OPAL_CALL(opal_handle_hmi, OPAL_HANDLE_HMI);
+OPAL_CALL_REAL(opal_rm_handle_hmi, OPAL_HANDLE_HMI);
OPAL_CALL(opal_config_cpu_idle_state, OPAL_CONFIG_CPU_IDLE_STATE);
+OPAL_CALL_REAL(opal_rm_config_cpu_idle_state, OPAL_CONFIG_CPU_IDLE_STATE);
OPAL_CALL(opal_slw_set_reg, OPAL_SLW_SET_REG);
OPAL_CALL(opal_register_dump_region, OPAL_REGISTER_DUMP_REGION);
OPAL_CALL(opal_unregister_dump_region, OPAL_UNREGISTER_DUMP_REGION);
@@ -302,3 +300,13 @@ OPAL_CALL(opal_prd_msg, OPAL_PRD_MSG);
OPAL_CALL(opal_leds_get_ind, OPAL_LEDS_GET_INDICATOR);
OPAL_CALL(opal_leds_set_ind, OPAL_LEDS_SET_INDICATOR);
OPAL_CALL(opal_console_flush, OPAL_CONSOLE_FLUSH);
+OPAL_CALL(opal_get_device_tree, OPAL_GET_DEVICE_TREE);
+OPAL_CALL(opal_pci_get_presence_state, OPAL_PCI_GET_PRESENCE_STATE);
+OPAL_CALL(opal_pci_get_power_state, OPAL_PCI_GET_POWER_STATE);
+OPAL_CALL(opal_pci_set_power_state, OPAL_PCI_SET_POWER_STATE);
+OPAL_CALL(opal_int_get_xirr, OPAL_INT_GET_XIRR);
+OPAL_CALL(opal_int_set_cppr, OPAL_INT_SET_CPPR);
+OPAL_CALL(opal_int_eoi, OPAL_INT_EOI);
+OPAL_CALL(opal_int_set_mfrr, OPAL_INT_SET_MFRR);
+OPAL_CALL(opal_pci_tce_kill, OPAL_PCI_TCE_KILL);
+OPAL_CALL_REAL(opal_rm_pci_tce_kill, OPAL_PCI_TCE_KILL);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 0256d0729252..8b4fc68cebcb 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -55,8 +55,9 @@ struct device_node *opal_node;
static DEFINE_SPINLOCK(opal_write_lock);
static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX];
static uint32_t opal_heartbeat;
+static struct task_struct *kopald_tsk;
-static void opal_reinit_cores(void)
+void opal_configure_cores(void)
{
/* Do the actual re-init, This will clobber all FPRs, VRs, etc...
*
@@ -69,6 +70,10 @@ static void opal_reinit_cores(void)
#else
opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_LE);
#endif
+
+ /* Restore some bits */
+ if (cur_cpu_spec->cpu_restore)
+ cur_cpu_spec->cpu_restore();
}
int __init early_init_dt_scan_opal(unsigned long node,
@@ -105,13 +110,6 @@ int __init early_init_dt_scan_opal(unsigned long node,
panic("OPAL != V3 detected, no longer supported.\n");
}
- /* Reinit all cores with the right endian */
- opal_reinit_cores();
-
- /* Restore some bits */
- if (cur_cpu_spec->cpu_restore)
- cur_cpu_spec->cpu_restore();
-
return 1;
}
@@ -653,6 +651,7 @@ static void opal_i2c_create_devs(void)
static int kopald(void *unused)
{
+ unsigned long timeout = msecs_to_jiffies(opal_heartbeat) + 1;
__be64 events;
set_freezable();
@@ -660,12 +659,18 @@ static int kopald(void *unused)
try_to_freeze();
opal_poll_events(&events);
opal_handle_events(be64_to_cpu(events));
- msleep_interruptible(opal_heartbeat);
+ schedule_timeout_interruptible(timeout);
} while (!kthread_should_stop());
return 0;
}
+void opal_wake_poller(void)
+{
+ if (kopald_tsk)
+ wake_up_process(kopald_tsk);
+}
+
static void opal_init_heartbeat(void)
{
/* Old firwmware, we assume the HVC heartbeat is sufficient */
@@ -674,7 +679,7 @@ static void opal_init_heartbeat(void)
opal_heartbeat = 0;
if (opal_heartbeat)
- kthread_run(kopald, NULL, "kopald");
+ kopald_tsk = kthread_run(kopald, NULL, "kopald");
}
static int __init opal_init(void)
@@ -751,6 +756,9 @@ static int __init opal_init(void)
opal_pdev_init(opal_node, "ibm,opal-flash");
opal_pdev_init(opal_node, "ibm,opal-prd");
+ /* Initialise platform device: oppanel interface */
+ opal_pdev_init(opal_node, "ibm,opal-oppanel");
+
/* Initialise OPAL kmsg dumper for flushing console on panic */
opal_kmsg_init();
@@ -885,3 +893,5 @@ EXPORT_SYMBOL_GPL(opal_i2c_request);
/* Export these symbols for PowerNV LED class driver */
EXPORT_SYMBOL_GPL(opal_leds_get_ind);
EXPORT_SYMBOL_GPL(opal_leds_set_ind);
+/* Export this symbol for PowerNV Operator Panel class driver */
+EXPORT_SYMBOL_GPL(opal_write_oppanel_async);
diff --git a/arch/powerpc/platforms/powernv/pci-cxl.c b/arch/powerpc/platforms/powernv/pci-cxl.c
new file mode 100644
index 000000000000..1349a099c74c
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/pci-cxl.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright 2014-2016 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/msi.h>
+#include <asm/pci-bridge.h>
+#include <asm/pnv-pci.h>
+#include <asm/opal.h>
+#include <misc/cxl.h>
+
+#include "pci.h"
+
+struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+ return of_node_get(hose->dn);
+}
+EXPORT_SYMBOL(pnv_pci_get_phb_node);
+
+int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ struct pnv_ioda_pe *pe;
+ int rc;
+
+ pe = pnv_ioda_get_pe(dev);
+ if (!pe)
+ return -ENODEV;
+
+ pe_info(pe, "Switching PHB to CXL\n");
+
+ rc = opal_pci_set_phb_cxl_mode(phb->opal_id, mode, pe->pe_number);
+ if (rc == OPAL_UNSUPPORTED)
+ dev_err(&dev->dev, "Required cxl mode not supported by firmware - update skiboot\n");
+ else if (rc)
+ dev_err(&dev->dev, "opal_pci_set_phb_cxl_mode failed: %i\n", rc);
+
+ return rc;
+}
+EXPORT_SYMBOL(pnv_phb_to_cxl_mode);
+
+/* Find PHB for cxl dev and allocate MSI hwirqs?
+ * Returns the absolute hardware IRQ number
+ */
+int pnv_cxl_alloc_hwirqs(struct pci_dev *dev, int num)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ int hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, num);
+
+ if (hwirq < 0) {
+ dev_warn(&dev->dev, "Failed to find a free MSI\n");
+ return -ENOSPC;
+ }
+
+ return phb->msi_base + hwirq;
+}
+EXPORT_SYMBOL(pnv_cxl_alloc_hwirqs);
+
+void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+
+ msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq - phb->msi_base, num);
+}
+EXPORT_SYMBOL(pnv_cxl_release_hwirqs);
+
+void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs,
+ struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ int i, hwirq;
+
+ for (i = 1; i < CXL_IRQ_RANGES; i++) {
+ if (!irqs->range[i])
+ continue;
+ pr_devel("cxl release irq range 0x%x: offset: 0x%lx limit: %ld\n",
+ i, irqs->offset[i],
+ irqs->range[i]);
+ hwirq = irqs->offset[i] - phb->msi_base;
+ msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq,
+ irqs->range[i]);
+ }
+}
+EXPORT_SYMBOL(pnv_cxl_release_hwirq_ranges);
+
+int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs,
+ struct pci_dev *dev, int num)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ int i, hwirq, try;
+
+ memset(irqs, 0, sizeof(struct cxl_irq_ranges));
+
+ /* 0 is reserved for the multiplexed PSL DSI interrupt */
+ for (i = 1; i < CXL_IRQ_RANGES && num; i++) {
+ try = num;
+ while (try) {
+ hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, try);
+ if (hwirq >= 0)
+ break;
+ try /= 2;
+ }
+ if (!try)
+ goto fail;
+
+ irqs->offset[i] = phb->msi_base + hwirq;
+ irqs->range[i] = try;
+ pr_devel("cxl alloc irq range 0x%x: offset: 0x%lx limit: %li\n",
+ i, irqs->offset[i], irqs->range[i]);
+ num -= try;
+ }
+ if (num)
+ goto fail;
+
+ return 0;
+fail:
+ pnv_cxl_release_hwirq_ranges(irqs, dev);
+ return -ENOSPC;
+}
+EXPORT_SYMBOL(pnv_cxl_alloc_hwirq_ranges);
+
+int pnv_cxl_get_irq_count(struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+
+ return phb->msi_bmp.irq_count;
+}
+EXPORT_SYMBOL(pnv_cxl_get_irq_count);
+
+int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq,
+ unsigned int virq)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ unsigned int xive_num = hwirq - phb->msi_base;
+ struct pnv_ioda_pe *pe;
+ int rc;
+
+ if (!(pe = pnv_ioda_get_pe(dev)))
+ return -ENODEV;
+
+ /* Assign XIVE to PE */
+ rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num);
+ if (rc) {
+ pe_warn(pe, "%s: OPAL error %d setting msi_base 0x%x "
+ "hwirq 0x%x XIVE 0x%x PE\n",
+ pci_name(dev), rc, phb->msi_base, hwirq, xive_num);
+ return -EIO;
+ }
+ pnv_set_msi_irq_chip(phb, virq);
+
+ return 0;
+}
+EXPORT_SYMBOL(pnv_cxl_ioda_msi_setup);
+
+#if IS_MODULE(CONFIG_CXL)
+static inline int get_cxl_module(void)
+{
+ struct module *cxl_module;
+
+ mutex_lock(&module_mutex);
+
+ cxl_module = find_module("cxl");
+ if (cxl_module)
+ __module_get(cxl_module);
+
+ mutex_unlock(&module_mutex);
+
+ if (!cxl_module)
+ return -ENODEV;
+
+ return 0;
+}
+#else
+static inline int get_cxl_module(void) { return 0; }
+#endif
+
+/*
+ * Sets flags and switches the controller ops to enable the cxl kernel api.
+ * Originally the cxl kernel API operated on a virtual PHB, but certain cards
+ * such as the Mellanox CX4 use a peer model instead and for these cards the
+ * cxl kernel api will operate on the real PHB.
+ */
+int pnv_cxl_enable_phb_kernel_api(struct pci_controller *hose, bool enable)
+{
+ struct pnv_phb *phb = hose->private_data;
+ int rc;
+
+ if (!enable) {
+ /*
+ * Once cxl mode is enabled on the PHB, there is currently no
+ * known safe method to disable it again, and trying risks a
+ * checkstop. If we can find a way to safely disable cxl mode
+ * in the future we can revisit this, but for now the only sane
+ * thing to do is to refuse to disable cxl mode:
+ */
+ return -EPERM;
+ }
+
+ /*
+ * Hold a reference to the cxl module since several PHB operations now
+ * depend on it, and it would be insane to allow it to be removed so
+ * long as we are in this mode (and since we can't safely disable this
+ * mode once enabled...).
+ */
+ rc = get_cxl_module();
+ if (rc)
+ return rc;
+
+ phb->flags |= PNV_PHB_FLAG_CXL;
+ hose->controller_ops = pnv_cxl_cx4_ioda_controller_ops;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pnv_cxl_enable_phb_kernel_api);
+
+bool pnv_pci_on_cxl_phb(struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+
+ return !!(phb->flags & PNV_PHB_FLAG_CXL);
+}
+EXPORT_SYMBOL_GPL(pnv_pci_on_cxl_phb);
+
+struct cxl_afu *pnv_cxl_phb_to_afu(struct pci_controller *hose)
+{
+ struct pnv_phb *phb = hose->private_data;
+
+ return (struct cxl_afu *)phb->cxl_afu;
+}
+EXPORT_SYMBOL_GPL(pnv_cxl_phb_to_afu);
+
+void pnv_cxl_phb_set_peer_afu(struct pci_dev *dev, struct cxl_afu *afu)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+
+ phb->cxl_afu = afu;
+}
+EXPORT_SYMBOL_GPL(pnv_cxl_phb_set_peer_afu);
+
+/*
+ * In the peer cxl model, the XSL/PSL is physical function 0, and will be used
+ * by other functions on the device for memory access and interrupts. When the
+ * other functions are enabled we explicitly take a reference on the cxl
+ * function since they will use it, and allocate a default context associated
+ * with that function just like the vPHB model of the cxl kernel API.
+ */
+bool pnv_cxl_enable_device_hook(struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ struct cxl_afu *afu = phb->cxl_afu;
+
+ if (!pnv_pci_enable_device_hook(dev))
+ return false;
+
+
+ /* No special handling for the cxl function, which is always PF 0 */
+ if (PCI_FUNC(dev->devfn) == 0)
+ return true;
+
+ if (!afu) {
+ dev_WARN(&dev->dev, "Attempted to enable function > 0 on CXL PHB without a peer AFU\n");
+ return false;
+ }
+
+ dev_info(&dev->dev, "Enabling function on CXL enabled PHB with peer AFU\n");
+
+ /* Make sure the peer AFU can't go away while this device is active */
+ cxl_afu_get(afu);
+
+ return cxl_pci_associate_default_context(dev, afu);
+}
+
+void pnv_cxl_disable_device(struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ struct cxl_afu *afu = phb->cxl_afu;
+
+ /* No special handling for cxl function: */
+ if (PCI_FUNC(dev->devfn) == 0)
+ return;
+
+ cxl_pci_disable_device(dev);
+ cxl_afu_put(afu);
+}
+
+/*
+ * This is a special version of pnv_setup_msi_irqs for cards in cxl mode. This
+ * function handles setting up the IVTE entries for the XSL to use.
+ *
+ * We are currently not filling out the MSIX table, since the only currently
+ * supported adapter (CX4) uses a custom MSIX table format in cxl mode and it
+ * is up to their driver to fill that out. In the future we may fill out the
+ * MSIX table (and change the IVTE entries to be an index to the MSIX table)
+ * for adapters implementing the Full MSI-X mode described in the CAIA.
+ */
+int pnv_cxl_cx4_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+ struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ struct msi_desc *entry;
+ struct cxl_context *ctx = NULL;
+ unsigned int virq;
+ int hwirq;
+ int afu_irq = 0;
+ int rc;
+
+ if (WARN_ON(!phb) || !phb->msi_bmp.bitmap)
+ return -ENODEV;
+
+ if (pdev->no_64bit_msi && !phb->msi32_support)
+ return -ENODEV;
+
+ rc = cxl_cx4_setup_msi_irqs(pdev, nvec, type);
+ if (rc)
+ return rc;
+
+ for_each_pci_msi_entry(entry, pdev) {
+ if (!entry->msi_attrib.is_64 && !phb->msi32_support) {
+ pr_warn("%s: Supports only 64-bit MSIs\n",
+ pci_name(pdev));
+ return -ENXIO;
+ }
+
+ hwirq = cxl_next_msi_hwirq(pdev, &ctx, &afu_irq);
+ if (WARN_ON(hwirq <= 0))
+ return (hwirq ? hwirq : -ENOMEM);
+
+ virq = irq_create_mapping(NULL, hwirq);
+ if (virq == NO_IRQ) {
+ pr_warn("%s: Failed to map cxl mode MSI to linux irq\n",
+ pci_name(pdev));
+ return -ENOMEM;
+ }
+
+ rc = pnv_cxl_ioda_msi_setup(pdev, hwirq, virq);
+ if (rc) {
+ pr_warn("%s: Failed to setup cxl mode MSI\n", pci_name(pdev));
+ irq_dispose_mapping(virq);
+ return rc;
+ }
+
+ irq_set_msi_desc(virq, entry);
+ }
+
+ return 0;
+}
+
+void pnv_cxl_cx4_teardown_msi_irqs(struct pci_dev *pdev)
+{
+ struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ struct msi_desc *entry;
+ irq_hw_number_t hwirq;
+
+ if (WARN_ON(!phb))
+ return;
+
+ for_each_pci_msi_entry(entry, pdev) {
+ if (entry->irq == NO_IRQ)
+ continue;
+ hwirq = virq_to_hw(entry->irq);
+ irq_set_msi_desc(entry->irq, NULL);
+ irq_dispose_mapping(entry->irq);
+ }
+
+ cxl_cx4_teardown_msi_irqs(pdev);
+}
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 3a5ea8236db8..891fc4a453df 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -55,6 +55,7 @@
#define POWERNV_IOMMU_DEFAULT_LEVELS 1
#define POWERNV_IOMMU_MAX_LEVELS 5
+static const char * const pnv_phb_names[] = { "IODA1", "IODA2", "NPU" };
static void pnv_pci_ioda2_table_free_pages(struct iommu_table *tbl);
void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level,
@@ -141,16 +142,14 @@ static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no)
static struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb)
{
- unsigned long pe;
+ unsigned long pe = phb->ioda.total_pe_num - 1;
- do {
- pe = find_next_zero_bit(phb->ioda.pe_alloc,
- phb->ioda.total_pe_num, 0);
- if (pe >= phb->ioda.total_pe_num)
- return NULL;
- } while(test_and_set_bit(pe, phb->ioda.pe_alloc));
+ for (pe = phb->ioda.total_pe_num - 1; pe >= 0; pe--) {
+ if (!test_and_set_bit(pe, phb->ioda.pe_alloc))
+ return pnv_ioda_init_pe(phb, pe);
+ }
- return pnv_ioda_init_pe(phb, pe);
+ return NULL;
}
static void pnv_ioda_free_pe(struct pnv_ioda_pe *pe)
@@ -192,18 +191,15 @@ static int pnv_ioda2_init_m64(struct pnv_phb *phb)
goto fail;
}
- /* Mark the M64 BAR assigned */
- set_bit(phb->ioda.m64_bar_idx, &phb->ioda.m64_bar_alloc);
-
/*
- * Strip off the segment used by the reserved PE, which is
- * expected to be 0 or last one of PE capabicity.
+ * Exclude the segments for reserved and root bus PE, which
+ * are first or last two PEs.
*/
r = &phb->hose->mem_resources[1];
if (phb->ioda.reserved_pe_idx == 0)
- r->start += phb->ioda.m64_segsize;
+ r->start += (2 * phb->ioda.m64_segsize);
else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
- r->end -= phb->ioda.m64_segsize;
+ r->end -= (2 * phb->ioda.m64_segsize);
else
pr_warn(" Cannot strip M64 segment for reserved PE#%d\n",
phb->ioda.reserved_pe_idx);
@@ -283,14 +279,14 @@ static int pnv_ioda1_init_m64(struct pnv_phb *phb)
}
/*
- * Exclude the segment used by the reserved PE, which
- * is expected to be 0 or last supported PE#.
+ * Exclude the segments for reserved and root bus PE, which
+ * are first or last two PEs.
*/
r = &phb->hose->mem_resources[1];
if (phb->ioda.reserved_pe_idx == 0)
- r->start += phb->ioda.m64_segsize;
+ r->start += (2 * phb->ioda.m64_segsize);
else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
- r->end -= phb->ioda.m64_segsize;
+ r->end -= (2 * phb->ioda.m64_segsize);
else
WARN(1, "Wrong reserved PE#%d on PHB#%d\n",
phb->ioda.reserved_pe_idx, phb->hose->global_number);
@@ -405,6 +401,7 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)
struct pci_controller *hose = phb->hose;
struct device_node *dn = hose->dn;
struct resource *res;
+ u32 m64_range[2], i;
const u32 *r;
u64 pci_addr;
@@ -425,6 +422,30 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)
return;
}
+ /*
+ * Find the available M64 BAR range and pickup the last one for
+ * covering the whole 64-bits space. We support only one range.
+ */
+ if (of_property_read_u32_array(dn, "ibm,opal-available-m64-ranges",
+ m64_range, 2)) {
+ /* In absence of the property, assume 0..15 */
+ m64_range[0] = 0;
+ m64_range[1] = 16;
+ }
+ /* We only support 64 bits in our allocator */
+ if (m64_range[1] > 63) {
+ pr_warn("%s: Limiting M64 range to 63 (from %d) on PHB#%x\n",
+ __func__, m64_range[1], phb->hose->global_number);
+ m64_range[1] = 63;
+ }
+ /* Empty range, no m64 */
+ if (m64_range[1] <= m64_range[0]) {
+ pr_warn("%s: M64 empty, disabling M64 usage on PHB#%x\n",
+ __func__, phb->hose->global_number);
+ return;
+ }
+
+ /* Configure M64 informations */
res = &hose->mem_resources[1];
res->name = dn->full_name;
res->start = of_translate_address(dn, r + 2);
@@ -437,11 +458,28 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)
phb->ioda.m64_segsize = phb->ioda.m64_size / phb->ioda.total_pe_num;
phb->ioda.m64_base = pci_addr;
- pr_info(" MEM64 0x%016llx..0x%016llx -> 0x%016llx\n",
- res->start, res->end, pci_addr);
+ /* This lines up nicely with the display from processing OF ranges */
+ pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx (M64 #%d..%d)\n",
+ res->start, res->end, pci_addr, m64_range[0],
+ m64_range[0] + m64_range[1] - 1);
+
+ /* Mark all M64 used up by default */
+ phb->ioda.m64_bar_alloc = (unsigned long)-1;
/* Use last M64 BAR to cover M64 window */
- phb->ioda.m64_bar_idx = 15;
+ m64_range[1]--;
+ phb->ioda.m64_bar_idx = m64_range[0] + m64_range[1];
+
+ pr_info(" Using M64 #%d as default window\n", phb->ioda.m64_bar_idx);
+
+ /* Mark remaining ones free */
+ for (i = m64_range[0]; i < m64_range[1]; i++)
+ clear_bit(i, &phb->ioda.m64_bar_alloc);
+
+ /*
+ * Setup init functions for M64 based on IODA version, IODA3 uses
+ * the IODA2 code.
+ */
if (phb->type == PNV_PHB_IODA1)
phb->init_m64 = pnv_ioda1_init_m64;
else
@@ -596,7 +634,7 @@ static int pnv_ioda_get_pe_state(struct pnv_phb *phb, int pe_no)
* but in the meantime, we need to protect them to avoid warnings
*/
#ifdef CONFIG_PCI_MSI
-static struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev)
+struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev)
{
struct pci_controller *hose = pci_bus_to_host(dev->bus);
struct pnv_phb *phb = hose->private_data;
@@ -714,7 +752,6 @@ static int pnv_ioda_set_peltv(struct pnv_phb *phb,
return 0;
}
-#ifdef CONFIG_PCI_IOV
static int pnv_ioda_deconfigure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe)
{
struct pci_dev *parent;
@@ -749,9 +786,11 @@ static int pnv_ioda_deconfigure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe)
}
rid_end = pe->rid + (count << 8);
} else {
+#ifdef CONFIG_PCI_IOV
if (pe->flags & PNV_IODA_PE_VF)
parent = pe->parent_dev;
else
+#endif
parent = pe->pdev->bus->self;
bcomp = OpalPciBusAll;
dcomp = OPAL_COMPARE_RID_DEVICE_NUMBER;
@@ -761,7 +800,7 @@ static int pnv_ioda_deconfigure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe)
/* Clear the reverse map */
for (rid = pe->rid; rid < rid_end; rid++)
- phb->ioda.pe_rmap[rid] = 0;
+ phb->ioda.pe_rmap[rid] = IODA_INVALID_PE;
/* Release from all parents PELT-V */
while (parent) {
@@ -789,11 +828,12 @@ static int pnv_ioda_deconfigure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe)
pe->pbus = NULL;
pe->pdev = NULL;
+#ifdef CONFIG_PCI_IOV
pe->parent_dev = NULL;
+#endif
return 0;
}
-#endif /* CONFIG_PCI_IOV */
static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe)
{
@@ -1024,6 +1064,16 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)
pci_name(dev));
continue;
}
+
+ /*
+ * In partial hotplug case, the PCI device might be still
+ * associated with the PE and needn't attach it to the PE
+ * again.
+ */
+ if (pdn->pe_number != IODA_INVALID_PE)
+ continue;
+
+ pe->device_count++;
pdn->pcidev = dev;
pdn->pe_number = pe->pe_number;
if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate)
@@ -1042,9 +1092,26 @@ static struct pnv_ioda_pe *pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all)
struct pci_controller *hose = pci_bus_to_host(bus);
struct pnv_phb *phb = hose->private_data;
struct pnv_ioda_pe *pe = NULL;
+ unsigned int pe_num;
+
+ /*
+ * In partial hotplug case, the PE instance might be still alive.
+ * We should reuse it instead of allocating a new one.
+ */
+ pe_num = phb->ioda.pe_rmap[bus->number << 8];
+ if (pe_num != IODA_INVALID_PE) {
+ pe = &phb->ioda.pe_array[pe_num];
+ pnv_ioda_setup_same_PE(bus, pe);
+ return NULL;
+ }
+
+ /* PE number for root bus should have been reserved */
+ if (pci_is_root_bus(bus) &&
+ phb->ioda.root_pe_idx != IODA_INVALID_PE)
+ pe = &phb->ioda.pe_array[phb->ioda.root_pe_idx];
/* Check if PE is determined by M64 */
- if (phb->pick_m64_pe)
+ if (!pe && phb->pick_m64_pe)
pe = phb->pick_m64_pe(bus, all);
/* The PE number isn't pinned by M64 */
@@ -1156,30 +1223,6 @@ static void pnv_ioda_setup_npu_PEs(struct pci_bus *bus)
pnv_ioda_setup_npu_PE(pdev);
}
-static void pnv_ioda_setup_PEs(struct pci_bus *bus)
-{
- struct pci_dev *dev;
-
- pnv_ioda_setup_bus_PE(bus, false);
-
- list_for_each_entry(dev, &bus->devices, bus_list) {
- if (dev->subordinate) {
- if (pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE)
- pnv_ioda_setup_bus_PE(dev->subordinate, true);
- else
- pnv_ioda_setup_PEs(dev->subordinate);
- }
- }
-}
-
-/*
- * Configure PEs so that the downstream PCI buses and devices
- * could have their associated PE#. Unfortunately, we didn't
- * figure out the way to identify the PLX bridge yet. So we
- * simply put the PCI bus and the subordinate behind the root
- * port to PE# here. The game rule here is expected to be changed
- * as soon as we can detected PLX bridge correctly.
- */
static void pnv_pci_ioda_setup_PEs(void)
{
struct pci_controller *hose, *tmp;
@@ -1187,22 +1230,11 @@ static void pnv_pci_ioda_setup_PEs(void)
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
phb = hose->private_data;
-
- /* M64 layout might affect PE allocation */
- if (phb->reserve_m64_pe)
- phb->reserve_m64_pe(hose->bus, NULL, true);
-
- /*
- * On NPU PHB, we expect separate PEs for individual PCI
- * functions. PCI bus dependent PEs are required for the
- * remaining types of PHBs.
- */
if (phb->type == PNV_PHB_NPU) {
/* PE#0 is needed for error reporting */
pnv_ioda_reserve_pe(phb, 0);
pnv_ioda_setup_npu_PEs(hose->bus);
- } else
- pnv_ioda_setup_PEs(hose->bus);
+ }
}
}
@@ -1728,7 +1760,14 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe,
}
}
-static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl,
+static inline __be64 __iomem *pnv_ioda_get_inval_reg(struct pnv_phb *phb,
+ bool real_mode)
+{
+ return real_mode ? (__be64 __iomem *)(phb->regs_phys + 0x210) :
+ (phb->regs + 0x210);
+}
+
+static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl,
unsigned long index, unsigned long npages, bool rm)
{
struct iommu_table_group_link *tgl = list_first_entry_or_null(
@@ -1736,33 +1775,17 @@ static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl,
next);
struct pnv_ioda_pe *pe = container_of(tgl->table_group,
struct pnv_ioda_pe, table_group);
- __be64 __iomem *invalidate = rm ?
- (__be64 __iomem *)pe->phb->ioda.tce_inval_reg_phys :
- pe->phb->ioda.tce_inval_reg;
+ __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, rm);
unsigned long start, end, inc;
- const unsigned shift = tbl->it_page_shift;
start = __pa(((__be64 *)tbl->it_base) + index - tbl->it_offset);
end = __pa(((__be64 *)tbl->it_base) + index - tbl->it_offset +
npages - 1);
- /* BML uses this case for p6/p7/galaxy2: Shift addr and put in node */
- if (tbl->it_busno) {
- start <<= shift;
- end <<= shift;
- inc = 128ull << shift;
- start |= tbl->it_busno;
- end |= tbl->it_busno;
- } else if (tbl->it_type & TCE_PCI_SWINV_PAIR) {
- /* p7ioc-style invalidation, 2 TCEs per write */
- start |= (1ull << 63);
- end |= (1ull << 63);
- inc = 16;
- } else {
- /* Default (older HW) */
- inc = 128;
- }
-
+ /* p7ioc-style invalidation, 2 TCEs per write */
+ start |= (1ull << 63);
+ end |= (1ull << 63);
+ inc = 16;
end |= inc - 1; /* round up end to be different than start */
mb(); /* Ensure above stores are visible */
@@ -1788,8 +1811,8 @@ static int pnv_ioda1_tce_build(struct iommu_table *tbl, long index,
int ret = pnv_tce_build(tbl, index, npages, uaddr, direction,
attrs);
- if (!ret && (tbl->it_type & TCE_PCI_SWINV_CREATE))
- pnv_pci_ioda1_tce_invalidate(tbl, index, npages, false);
+ if (!ret)
+ pnv_pci_p7ioc_tce_invalidate(tbl, index, npages, false);
return ret;
}
@@ -1800,9 +1823,8 @@ static int pnv_ioda1_tce_xchg(struct iommu_table *tbl, long index,
{
long ret = pnv_tce_xchg(tbl, index, hpa, direction);
- if (!ret && (tbl->it_type &
- (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE)))
- pnv_pci_ioda1_tce_invalidate(tbl, index, 1, false);
+ if (!ret)
+ pnv_pci_p7ioc_tce_invalidate(tbl, index, 1, false);
return ret;
}
@@ -1813,8 +1835,7 @@ static void pnv_ioda1_tce_free(struct iommu_table *tbl, long index,
{
pnv_tce_free(tbl, index, npages);
- if (tbl->it_type & TCE_PCI_SWINV_FREE)
- pnv_pci_ioda1_tce_invalidate(tbl, index, npages, false);
+ pnv_pci_p7ioc_tce_invalidate(tbl, index, npages, false);
}
static struct iommu_table_ops pnv_ioda1_iommu_ops = {
@@ -1826,45 +1847,42 @@ static struct iommu_table_ops pnv_ioda1_iommu_ops = {
.get = pnv_tce_get,
};
-#define TCE_KILL_INVAL_ALL PPC_BIT(0)
-#define TCE_KILL_INVAL_PE PPC_BIT(1)
-#define TCE_KILL_INVAL_TCE PPC_BIT(2)
+#define PHB3_TCE_KILL_INVAL_ALL PPC_BIT(0)
+#define PHB3_TCE_KILL_INVAL_PE PPC_BIT(1)
+#define PHB3_TCE_KILL_INVAL_ONE PPC_BIT(2)
-void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_phb *phb, bool rm)
+void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm)
{
- const unsigned long val = TCE_KILL_INVAL_ALL;
+ __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(phb, rm);
+ const unsigned long val = PHB3_TCE_KILL_INVAL_ALL;
mb(); /* Ensure previous TCE table stores are visible */
if (rm)
- __raw_rm_writeq(cpu_to_be64(val),
- (__be64 __iomem *)
- phb->ioda.tce_inval_reg_phys);
+ __raw_rm_writeq(cpu_to_be64(val), invalidate);
else
- __raw_writeq(cpu_to_be64(val), phb->ioda.tce_inval_reg);
+ __raw_writeq(cpu_to_be64(val), invalidate);
}
-static inline void pnv_pci_ioda2_tce_invalidate_pe(struct pnv_ioda_pe *pe)
+static inline void pnv_pci_phb3_tce_invalidate_pe(struct pnv_ioda_pe *pe)
{
/* 01xb - invalidate TCEs that match the specified PE# */
- unsigned long val = TCE_KILL_INVAL_PE | (pe->pe_number & 0xFF);
- struct pnv_phb *phb = pe->phb;
-
- if (!phb->ioda.tce_inval_reg)
- return;
+ __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, false);
+ unsigned long val = PHB3_TCE_KILL_INVAL_PE | (pe->pe_number & 0xFF);
mb(); /* Ensure above stores are visible */
- __raw_writeq(cpu_to_be64(val), phb->ioda.tce_inval_reg);
+ __raw_writeq(cpu_to_be64(val), invalidate);
}
-static void pnv_pci_ioda2_do_tce_invalidate(unsigned pe_number, bool rm,
- __be64 __iomem *invalidate, unsigned shift,
- unsigned long index, unsigned long npages)
+static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, bool rm,
+ unsigned shift, unsigned long index,
+ unsigned long npages)
{
+ __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, false);
unsigned long start, end, inc;
/* We'll invalidate DMA address in PE scope */
- start = TCE_KILL_INVAL_TCE;
- start |= (pe_number & 0xFF);
+ start = PHB3_TCE_KILL_INVAL_ONE;
+ start |= (pe->pe_number & 0xFF);
end = start;
/* Figure out the start, end and step */
@@ -1882,6 +1900,17 @@ static void pnv_pci_ioda2_do_tce_invalidate(unsigned pe_number, bool rm,
}
}
+static inline void pnv_pci_ioda2_tce_invalidate_pe(struct pnv_ioda_pe *pe)
+{
+ struct pnv_phb *phb = pe->phb;
+
+ if (phb->model == PNV_PHB_MODEL_PHB3 && phb->regs)
+ pnv_pci_phb3_tce_invalidate_pe(pe);
+ else
+ opal_pci_tce_kill(phb->opal_id, OPAL_PCI_TCE_KILL_PE,
+ pe->pe_number, 0, 0, 0);
+}
+
static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl,
unsigned long index, unsigned long npages, bool rm)
{
@@ -1890,22 +1919,31 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl,
list_for_each_entry_rcu(tgl, &tbl->it_group_list, next) {
struct pnv_ioda_pe *pe = container_of(tgl->table_group,
struct pnv_ioda_pe, table_group);
- __be64 __iomem *invalidate = rm ?
- (__be64 __iomem *)pe->phb->ioda.tce_inval_reg_phys :
- pe->phb->ioda.tce_inval_reg;
+ struct pnv_phb *phb = pe->phb;
+ unsigned int shift = tbl->it_page_shift;
- if (pe->phb->type == PNV_PHB_NPU) {
+ if (phb->type == PNV_PHB_NPU) {
/*
* The NVLink hardware does not support TCE kill
* per TCE entry so we have to invalidate
* the entire cache for it.
*/
- pnv_pci_ioda2_tce_invalidate_entire(pe->phb, rm);
+ pnv_pci_phb3_tce_invalidate_entire(phb, rm);
continue;
}
- pnv_pci_ioda2_do_tce_invalidate(pe->pe_number, rm,
- invalidate, tbl->it_page_shift,
- index, npages);
+ if (phb->model == PNV_PHB_MODEL_PHB3 && phb->regs)
+ pnv_pci_phb3_tce_invalidate(pe, rm, shift,
+ index, npages);
+ else if (rm)
+ opal_rm_pci_tce_kill(phb->opal_id,
+ OPAL_PCI_TCE_KILL_PAGES,
+ pe->pe_number, 1u << shift,
+ index << shift, npages);
+ else
+ opal_pci_tce_kill(phb->opal_id,
+ OPAL_PCI_TCE_KILL_PAGES,
+ pe->pe_number, 1u << shift,
+ index << shift, npages);
}
}
@@ -1917,7 +1955,7 @@ static int pnv_ioda2_tce_build(struct iommu_table *tbl, long index,
int ret = pnv_tce_build(tbl, index, npages, uaddr, direction,
attrs);
- if (!ret && (tbl->it_type & TCE_PCI_SWINV_CREATE))
+ if (!ret)
pnv_pci_ioda2_tce_invalidate(tbl, index, npages, false);
return ret;
@@ -1929,8 +1967,7 @@ static int pnv_ioda2_tce_xchg(struct iommu_table *tbl, long index,
{
long ret = pnv_tce_xchg(tbl, index, hpa, direction);
- if (!ret && (tbl->it_type &
- (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE)))
+ if (!ret)
pnv_pci_ioda2_tce_invalidate(tbl, index, 1, false);
return ret;
@@ -1942,8 +1979,7 @@ static void pnv_ioda2_tce_free(struct iommu_table *tbl, long index,
{
pnv_tce_free(tbl, index, npages);
- if (tbl->it_type & TCE_PCI_SWINV_FREE)
- pnv_pci_ioda2_tce_invalidate(tbl, index, npages, false);
+ pnv_pci_ioda2_tce_invalidate(tbl, index, npages, false);
}
static void pnv_ioda2_table_free(struct iommu_table *tbl)
@@ -2112,12 +2148,6 @@ found:
base * PNV_IODA1_DMA32_SEGSIZE,
IOMMU_PAGE_SHIFT_4K);
- /* OPAL variant of P7IOC SW invalidated TCEs */
- if (phb->ioda.tce_inval_reg)
- tbl->it_type |= (TCE_PCI_SWINV_CREATE |
- TCE_PCI_SWINV_FREE |
- TCE_PCI_SWINV_PAIR);
-
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;
@@ -2179,7 +2209,7 @@ static long pnv_pci_ioda2_set_window(struct iommu_table_group *table_group,
pnv_pci_link_table_and_group(phb->hose->node, num,
tbl, &pe->table_group);
- pnv_pci_ioda2_tce_invalidate_pe(pe);
+ pnv_pci_phb3_tce_invalidate_pe(pe);
return 0;
}
@@ -2240,8 +2270,6 @@ static long pnv_pci_ioda2_create_table(struct iommu_table_group *table_group,
}
tbl->it_ops = &pnv_ioda2_iommu_ops;
- if (pe->phb->ioda.tce_inval_reg)
- tbl->it_type |= (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE);
*ptbl = tbl;
@@ -2290,10 +2318,6 @@ static long pnv_pci_ioda2_setup_default_config(struct pnv_ioda_pe *pe)
if (!pnv_iommu_bypass_disabled)
pnv_pci_ioda2_set_bypass(pe, true);
- /* OPAL variant of PHB3 invalidated TCEs */
- if (pe->phb->ioda.tce_inval_reg)
- tbl->it_type |= (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE);
-
/*
* Setting table base here only for carrying iommu_group
* further down to let iommu_add_device() do the job.
@@ -2323,7 +2347,7 @@ static long pnv_pci_ioda2_unset_window(struct iommu_table_group *table_group,
if (ret)
pe_warn(pe, "Unmapping failed, ret = %ld\n", ret);
else
- pnv_pci_ioda2_tce_invalidate_pe(pe);
+ pnv_pci_phb3_tce_invalidate_pe(pe);
pnv_pci_unlink_table_and_group(table_group->tables[num], table_group);
@@ -2504,19 +2528,6 @@ static void pnv_pci_ioda_setup_iommu_api(void)
static void pnv_pci_ioda_setup_iommu_api(void) { };
#endif
-static void pnv_pci_ioda_setup_opal_tce_kill(struct pnv_phb *phb)
-{
- const __be64 *swinvp;
-
- /* OPAL variant of PHB3 invalidated TCEs */
- swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL);
- if (!swinvp)
- return;
-
- phb->ioda.tce_inval_reg_phys = be64_to_cpup(swinvp);
- phb->ioda.tce_inval_reg = ioremap(phb->ioda.tce_inval_reg_phys, 8);
-}
-
static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift,
unsigned levels, unsigned long limit,
unsigned long *current_offset, unsigned long *total_allocated)
@@ -2657,6 +2668,9 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
{
int64_t rc;
+ if (!pnv_pci_ioda_pe_dma_weight(pe))
+ return;
+
/* TVE #1 is selected by PCI address bit 59 */
pe->tce_bypass_base = 1ull << 59;
@@ -2688,49 +2702,6 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
pnv_ioda_setup_bus_dma(pe, pe->pbus);
}
-static void pnv_ioda_setup_dma(struct pnv_phb *phb)
-{
- struct pci_controller *hose = phb->hose;
- struct pnv_ioda_pe *pe;
- unsigned int weight;
-
- /* If we have more PE# than segments available, hand out one
- * per PE until we run out and let the rest fail. If not,
- * then we assign at least one segment per PE, plus more based
- * on the amount of devices under that PE
- */
- pr_info("PCI: Domain %04x has %d available 32-bit DMA segments\n",
- hose->global_number, phb->ioda.dma32_count);
-
- pnv_pci_ioda_setup_opal_tce_kill(phb);
-
- /* Walk our PE list and configure their DMA segments */
- list_for_each_entry(pe, &phb->ioda.pe_list, list) {
- weight = pnv_pci_ioda_pe_dma_weight(pe);
- if (!weight)
- continue;
-
- /*
- * For IODA2 compliant PHB3, we needn't care about the weight.
- * The all available 32-bits DMA space will be assigned to
- * the specific PE.
- */
- if (phb->type == PNV_PHB_IODA1) {
- pnv_pci_ioda1_setup_dma_pe(phb, pe);
- } else if (phb->type == PNV_PHB_IODA2) {
- pe_info(pe, "Assign DMA32 space\n");
- pnv_pci_ioda2_setup_dma_pe(phb, pe);
- } else if (phb->type == PNV_PHB_NPU) {
- /*
- * We initialise the DMA space for an NPU PHB
- * after setup of the PHB is complete as we
- * point the NPU TVT to the the same location
- * as the PHB3 TVT.
- */
- }
- }
-}
-
#ifdef CONFIG_PCI_MSI
static void pnv_ioda2_msi_eoi(struct irq_data *d)
{
@@ -2747,12 +2718,13 @@ static void pnv_ioda2_msi_eoi(struct irq_data *d)
}
-static void set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq)
+void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq)
{
struct irq_data *idata;
struct irq_chip *ichip;
- if (phb->type != PNV_PHB_IODA2)
+ /* The MSI EOI OPAL call is only needed on PHB3 */
+ if (phb->model != PNV_PHB_MODEL_PHB3)
return;
if (!phb->ioda.irq_chip_init) {
@@ -2769,157 +2741,6 @@ static void set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq)
irq_set_chip(virq, &phb->ioda.irq_chip);
}
-#ifdef CONFIG_CXL_BASE
-
-struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
-
- return of_node_get(hose->dn);
-}
-EXPORT_SYMBOL(pnv_pci_get_phb_node);
-
-int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- struct pnv_phb *phb = hose->private_data;
- struct pnv_ioda_pe *pe;
- int rc;
-
- pe = pnv_ioda_get_pe(dev);
- if (!pe)
- return -ENODEV;
-
- pe_info(pe, "Switching PHB to CXL\n");
-
- rc = opal_pci_set_phb_cxl_mode(phb->opal_id, mode, pe->pe_number);
- if (rc)
- dev_err(&dev->dev, "opal_pci_set_phb_cxl_mode failed: %i\n", rc);
-
- return rc;
-}
-EXPORT_SYMBOL(pnv_phb_to_cxl_mode);
-
-/* Find PHB for cxl dev and allocate MSI hwirqs?
- * Returns the absolute hardware IRQ number
- */
-int pnv_cxl_alloc_hwirqs(struct pci_dev *dev, int num)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- struct pnv_phb *phb = hose->private_data;
- int hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, num);
-
- if (hwirq < 0) {
- dev_warn(&dev->dev, "Failed to find a free MSI\n");
- return -ENOSPC;
- }
-
- return phb->msi_base + hwirq;
-}
-EXPORT_SYMBOL(pnv_cxl_alloc_hwirqs);
-
-void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- struct pnv_phb *phb = hose->private_data;
-
- msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq - phb->msi_base, num);
-}
-EXPORT_SYMBOL(pnv_cxl_release_hwirqs);
-
-void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs,
- struct pci_dev *dev)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- struct pnv_phb *phb = hose->private_data;
- int i, hwirq;
-
- for (i = 1; i < CXL_IRQ_RANGES; i++) {
- if (!irqs->range[i])
- continue;
- pr_devel("cxl release irq range 0x%x: offset: 0x%lx limit: %ld\n",
- i, irqs->offset[i],
- irqs->range[i]);
- hwirq = irqs->offset[i] - phb->msi_base;
- msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq,
- irqs->range[i]);
- }
-}
-EXPORT_SYMBOL(pnv_cxl_release_hwirq_ranges);
-
-int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs,
- struct pci_dev *dev, int num)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- struct pnv_phb *phb = hose->private_data;
- int i, hwirq, try;
-
- memset(irqs, 0, sizeof(struct cxl_irq_ranges));
-
- /* 0 is reserved for the multiplexed PSL DSI interrupt */
- for (i = 1; i < CXL_IRQ_RANGES && num; i++) {
- try = num;
- while (try) {
- hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, try);
- if (hwirq >= 0)
- break;
- try /= 2;
- }
- if (!try)
- goto fail;
-
- irqs->offset[i] = phb->msi_base + hwirq;
- irqs->range[i] = try;
- pr_devel("cxl alloc irq range 0x%x: offset: 0x%lx limit: %li\n",
- i, irqs->offset[i], irqs->range[i]);
- num -= try;
- }
- if (num)
- goto fail;
-
- return 0;
-fail:
- pnv_cxl_release_hwirq_ranges(irqs, dev);
- return -ENOSPC;
-}
-EXPORT_SYMBOL(pnv_cxl_alloc_hwirq_ranges);
-
-int pnv_cxl_get_irq_count(struct pci_dev *dev)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- struct pnv_phb *phb = hose->private_data;
-
- return phb->msi_bmp.irq_count;
-}
-EXPORT_SYMBOL(pnv_cxl_get_irq_count);
-
-int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq,
- unsigned int virq)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- struct pnv_phb *phb = hose->private_data;
- unsigned int xive_num = hwirq - phb->msi_base;
- struct pnv_ioda_pe *pe;
- int rc;
-
- if (!(pe = pnv_ioda_get_pe(dev)))
- return -ENODEV;
-
- /* Assign XIVE to PE */
- rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num);
- if (rc) {
- pe_warn(pe, "%s: OPAL error %d setting msi_base 0x%x "
- "hwirq 0x%x XIVE 0x%x PE\n",
- pci_name(dev), rc, phb->msi_base, hwirq, xive_num);
- return -EIO;
- }
- set_msi_irq_chip(phb, virq);
-
- return 0;
-}
-EXPORT_SYMBOL(pnv_cxl_ioda_msi_setup);
-#endif
-
static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
unsigned int hwirq, unsigned int virq,
unsigned int is_64, struct msi_msg *msg)
@@ -2976,7 +2797,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
}
msg->data = be32_to_cpu(data);
- set_msi_irq_chip(phb, virq);
+ pnv_set_msi_irq_chip(phb, virq);
pr_devel("%s: %s-bit MSI on hwirq %x (xive #%d),"
" address=%x_%08x data=%x PE# %d\n",
@@ -3197,41 +3018,6 @@ static void pnv_ioda_setup_pe_seg(struct pnv_ioda_pe *pe)
}
}
-static void pnv_pci_ioda_setup_seg(void)
-{
- struct pci_controller *tmp, *hose;
- struct pnv_phb *phb;
- struct pnv_ioda_pe *pe;
-
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
- phb = hose->private_data;
-
- /* NPU PHB does not support IO or MMIO segmentation */
- if (phb->type == PNV_PHB_NPU)
- continue;
-
- list_for_each_entry(pe, &phb->ioda.pe_list, list) {
- pnv_ioda_setup_pe_seg(pe);
- }
- }
-}
-
-static void pnv_pci_ioda_setup_DMA(void)
-{
- struct pci_controller *hose, *tmp;
- struct pnv_phb *phb;
-
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
- pnv_ioda_setup_dma(hose->private_data);
-
- /* Mark the PHB initialization done */
- phb = hose->private_data;
- phb->initialized = 1;
- }
-
- pnv_pci_ioda_setup_iommu_api();
-}
-
static void pnv_pci_ioda_create_dbgfs(void)
{
#ifdef CONFIG_DEBUG_FS
@@ -3242,6 +3028,9 @@ static void pnv_pci_ioda_create_dbgfs(void)
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
phb = hose->private_data;
+ /* Notify initialization of PHB done */
+ phb->initialized = 1;
+
sprintf(name, "PCI%04x", hose->global_number);
phb->dbgfs = debugfs_create_dir(name, powerpc_debugfs_root);
if (!phb->dbgfs)
@@ -3254,9 +3043,7 @@ static void pnv_pci_ioda_create_dbgfs(void)
static void pnv_pci_ioda_fixup(void)
{
pnv_pci_ioda_setup_PEs();
- pnv_pci_ioda_setup_seg();
- pnv_pci_ioda_setup_DMA();
-
+ pnv_pci_ioda_setup_iommu_api();
pnv_pci_ioda_create_dbgfs();
#ifdef CONFIG_EEH
@@ -3306,6 +3093,115 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
return phb->ioda.io_segsize;
}
+/*
+ * We are updating root port or the upstream port of the
+ * bridge behind the root port with PHB's windows in order
+ * to accommodate the changes on required resources during
+ * PCI (slot) hotplug, which is connected to either root
+ * port or the downstream ports of PCIe switch behind the
+ * root port.
+ */
+static void pnv_pci_fixup_bridge_resources(struct pci_bus *bus,
+ unsigned long type)
+{
+ struct pci_controller *hose = pci_bus_to_host(bus);
+ struct pnv_phb *phb = hose->private_data;
+ struct pci_dev *bridge = bus->self;
+ struct resource *r, *w;
+ bool msi_region = false;
+ int i;
+
+ /* Check if we need apply fixup to the bridge's windows */
+ if (!pci_is_root_bus(bridge->bus) &&
+ !pci_is_root_bus(bridge->bus->self->bus))
+ return;
+
+ /* Fixup the resources */
+ for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) {
+ r = &bridge->resource[PCI_BRIDGE_RESOURCES + i];
+ if (!r->flags || !r->parent)
+ continue;
+
+ w = NULL;
+ if (r->flags & type & IORESOURCE_IO)
+ w = &hose->io_resource;
+ else if (pnv_pci_is_mem_pref_64(r->flags) &&
+ (type & IORESOURCE_PREFETCH) &&
+ phb->ioda.m64_segsize)
+ w = &hose->mem_resources[1];
+ else if (r->flags & type & IORESOURCE_MEM) {
+ w = &hose->mem_resources[0];
+ msi_region = true;
+ }
+
+ r->start = w->start;
+ r->end = w->end;
+
+ /* The 64KB 32-bits MSI region shouldn't be included in
+ * the 32-bits bridge window. Otherwise, we can see strange
+ * issues. One of them is EEH error observed on Garrison.
+ *
+ * Exclude top 1MB region which is the minimal alignment of
+ * 32-bits bridge window.
+ */
+ if (msi_region) {
+ r->end += 0x10000;
+ r->end -= 0x100000;
+ }
+ }
+}
+
+static void pnv_pci_setup_bridge(struct pci_bus *bus, unsigned long type)
+{
+ struct pci_controller *hose = pci_bus_to_host(bus);
+ struct pnv_phb *phb = hose->private_data;
+ struct pci_dev *bridge = bus->self;
+ struct pnv_ioda_pe *pe;
+ bool all = (pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE);
+
+ /* Extend bridge's windows if necessary */
+ pnv_pci_fixup_bridge_resources(bus, type);
+
+ /* The PE for root bus should be realized before any one else */
+ if (!phb->ioda.root_pe_populated) {
+ pe = pnv_ioda_setup_bus_PE(phb->hose->bus, false);
+ if (pe) {
+ phb->ioda.root_pe_idx = pe->pe_number;
+ phb->ioda.root_pe_populated = true;
+ }
+ }
+
+ /* Don't assign PE to PCI bus, which doesn't have subordinate devices */
+ if (list_empty(&bus->devices))
+ return;
+
+ /* Reserve PEs according to used M64 resources */
+ if (phb->reserve_m64_pe)
+ phb->reserve_m64_pe(bus, NULL, all);
+
+ /*
+ * Assign PE. We might run here because of partial hotplug.
+ * For the case, we just pick up the existing PE and should
+ * not allocate resources again.
+ */
+ pe = pnv_ioda_setup_bus_PE(bus, all);
+ if (!pe)
+ return;
+
+ pnv_ioda_setup_pe_seg(pe);
+ switch (phb->type) {
+ case PNV_PHB_IODA1:
+ pnv_pci_ioda1_setup_dma_pe(phb, pe);
+ break;
+ case PNV_PHB_IODA2:
+ pnv_pci_ioda2_setup_dma_pe(phb, pe);
+ break;
+ default:
+ pr_warn("%s: No DMA for PHB#%d (type %d)\n",
+ __func__, phb->hose->global_number, phb->type);
+ }
+}
+
#ifdef CONFIG_PCI_IOV
static resource_size_t pnv_pci_iov_resource_alignment(struct pci_dev *pdev,
int resno)
@@ -3345,7 +3241,7 @@ static resource_size_t pnv_pci_iov_resource_alignment(struct pci_dev *pdev,
/* Prevent enabling devices for which we couldn't properly
* assign a PE
*/
-static bool pnv_pci_enable_device_hook(struct pci_dev *dev)
+bool pnv_pci_enable_device_hook(struct pci_dev *dev)
{
struct pci_controller *hose = pci_bus_to_host(dev->bus);
struct pnv_phb *phb = hose->private_data;
@@ -3366,6 +3262,178 @@ static bool pnv_pci_enable_device_hook(struct pci_dev *dev)
return true;
}
+static long pnv_pci_ioda1_unset_window(struct iommu_table_group *table_group,
+ int num)
+{
+ struct pnv_ioda_pe *pe = container_of(table_group,
+ struct pnv_ioda_pe, table_group);
+ struct pnv_phb *phb = pe->phb;
+ unsigned int idx;
+ long rc;
+
+ pe_info(pe, "Removing DMA window #%d\n", num);
+ for (idx = 0; idx < phb->ioda.dma32_count; idx++) {
+ if (phb->ioda.dma32_segmap[idx] != pe->pe_number)
+ continue;
+
+ rc = opal_pci_map_pe_dma_window(phb->opal_id, pe->pe_number,
+ idx, 0, 0ul, 0ul, 0ul);
+ if (rc != OPAL_SUCCESS) {
+ pe_warn(pe, "Failure %ld unmapping DMA32 segment#%d\n",
+ rc, idx);
+ return rc;
+ }
+
+ phb->ioda.dma32_segmap[idx] = IODA_INVALID_PE;
+ }
+
+ pnv_pci_unlink_table_and_group(table_group->tables[num], table_group);
+ return OPAL_SUCCESS;
+}
+
+static void pnv_pci_ioda1_release_pe_dma(struct pnv_ioda_pe *pe)
+{
+ unsigned int weight = pnv_pci_ioda_pe_dma_weight(pe);
+ struct iommu_table *tbl = pe->table_group.tables[0];
+ int64_t rc;
+
+ if (!weight)
+ return;
+
+ rc = pnv_pci_ioda1_unset_window(&pe->table_group, 0);
+ if (rc != OPAL_SUCCESS)
+ return;
+
+ pnv_pci_p7ioc_tce_invalidate(tbl, tbl->it_offset, tbl->it_size, false);
+ if (pe->table_group.group) {
+ iommu_group_put(pe->table_group.group);
+ WARN_ON(pe->table_group.group);
+ }
+
+ free_pages(tbl->it_base, get_order(tbl->it_size << 3));
+ iommu_free_table(tbl, "pnv");
+}
+
+static void pnv_pci_ioda2_release_pe_dma(struct pnv_ioda_pe *pe)
+{
+ struct iommu_table *tbl = pe->table_group.tables[0];
+ unsigned int weight = pnv_pci_ioda_pe_dma_weight(pe);
+#ifdef CONFIG_IOMMU_API
+ int64_t rc;
+#endif
+
+ if (!weight)
+ return;
+
+#ifdef CONFIG_IOMMU_API
+ rc = pnv_pci_ioda2_unset_window(&pe->table_group, 0);
+ if (rc)
+ pe_warn(pe, "OPAL error %ld release DMA window\n", rc);
+#endif
+
+ pnv_pci_ioda2_set_bypass(pe, false);
+ if (pe->table_group.group) {
+ iommu_group_put(pe->table_group.group);
+ WARN_ON(pe->table_group.group);
+ }
+
+ pnv_pci_ioda2_table_free_pages(tbl);
+ iommu_free_table(tbl, "pnv");
+}
+
+static void pnv_ioda_free_pe_seg(struct pnv_ioda_pe *pe,
+ unsigned short win,
+ unsigned int *map)
+{
+ struct pnv_phb *phb = pe->phb;
+ int idx;
+ int64_t rc;
+
+ for (idx = 0; idx < phb->ioda.total_pe_num; idx++) {
+ if (map[idx] != pe->pe_number)
+ continue;
+
+ if (win == OPAL_M64_WINDOW_TYPE)
+ rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+ phb->ioda.reserved_pe_idx, win,
+ idx / PNV_IODA1_M64_SEGS,
+ idx % PNV_IODA1_M64_SEGS);
+ else
+ rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+ phb->ioda.reserved_pe_idx, win, 0, idx);
+
+ if (rc != OPAL_SUCCESS)
+ pe_warn(pe, "Error %ld unmapping (%d) segment#%d\n",
+ rc, win, idx);
+
+ map[idx] = IODA_INVALID_PE;
+ }
+}
+
+static void pnv_ioda_release_pe_seg(struct pnv_ioda_pe *pe)
+{
+ struct pnv_phb *phb = pe->phb;
+
+ if (phb->type == PNV_PHB_IODA1) {
+ pnv_ioda_free_pe_seg(pe, OPAL_IO_WINDOW_TYPE,
+ phb->ioda.io_segmap);
+ pnv_ioda_free_pe_seg(pe, OPAL_M32_WINDOW_TYPE,
+ phb->ioda.m32_segmap);
+ pnv_ioda_free_pe_seg(pe, OPAL_M64_WINDOW_TYPE,
+ phb->ioda.m64_segmap);
+ } else if (phb->type == PNV_PHB_IODA2) {
+ pnv_ioda_free_pe_seg(pe, OPAL_M32_WINDOW_TYPE,
+ phb->ioda.m32_segmap);
+ }
+}
+
+static void pnv_ioda_release_pe(struct pnv_ioda_pe *pe)
+{
+ struct pnv_phb *phb = pe->phb;
+ struct pnv_ioda_pe *slave, *tmp;
+
+ /* Release slave PEs in compound PE */
+ if (pe->flags & PNV_IODA_PE_MASTER) {
+ list_for_each_entry_safe(slave, tmp, &pe->slaves, list)
+ pnv_ioda_release_pe(slave);
+ }
+
+ list_del(&pe->list);
+ switch (phb->type) {
+ case PNV_PHB_IODA1:
+ pnv_pci_ioda1_release_pe_dma(pe);
+ break;
+ case PNV_PHB_IODA2:
+ pnv_pci_ioda2_release_pe_dma(pe);
+ break;
+ default:
+ WARN_ON(1);
+ }
+
+ pnv_ioda_release_pe_seg(pe);
+ pnv_ioda_deconfigure_pe(pe->phb, pe);
+ pnv_ioda_free_pe(pe);
+}
+
+static void pnv_pci_release_device(struct pci_dev *pdev)
+{
+ struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ struct pci_dn *pdn = pci_get_pdn(pdev);
+ struct pnv_ioda_pe *pe;
+
+ if (pdev->is_virtfn)
+ return;
+
+ if (!pdn || pdn->pe_number == IODA_INVALID_PE)
+ return;
+
+ pe = &phb->ioda.pe_array[pdn->pe_number];
+ WARN_ON(--pe->device_count < 0);
+ if (pe->device_count == 0)
+ pnv_ioda_release_pe(pe);
+}
+
static void pnv_pci_ioda_shutdown(struct pci_controller *hose)
{
struct pnv_phb *phb = hose->private_data;
@@ -3382,7 +3450,9 @@ static const struct pci_controller_ops pnv_pci_ioda_controller_ops = {
.teardown_msi_irqs = pnv_teardown_msi_irqs,
#endif
.enable_device_hook = pnv_pci_enable_device_hook,
+ .release_device = pnv_pci_release_device,
.window_alignment = pnv_pci_window_alignment,
+ .setup_bridge = pnv_pci_setup_bridge,
.reset_secondary_bus = pnv_pci_reset_secondary_bus,
.dma_set_mask = pnv_pci_ioda_dma_set_mask,
.dma_get_required_mask = pnv_pci_ioda_dma_get_required_mask,
@@ -3410,6 +3480,26 @@ static const struct pci_controller_ops pnv_npu_ioda_controller_ops = {
.shutdown = pnv_pci_ioda_shutdown,
};
+#ifdef CONFIG_CXL_BASE
+const struct pci_controller_ops pnv_cxl_cx4_ioda_controller_ops = {
+ .dma_dev_setup = pnv_pci_dma_dev_setup,
+ .dma_bus_setup = pnv_pci_dma_bus_setup,
+#ifdef CONFIG_PCI_MSI
+ .setup_msi_irqs = pnv_cxl_cx4_setup_msi_irqs,
+ .teardown_msi_irqs = pnv_cxl_cx4_teardown_msi_irqs,
+#endif
+ .enable_device_hook = pnv_cxl_enable_device_hook,
+ .disable_device = pnv_cxl_disable_device,
+ .release_device = pnv_pci_release_device,
+ .window_alignment = pnv_pci_window_alignment,
+ .setup_bridge = pnv_pci_setup_bridge,
+ .reset_secondary_bus = pnv_pci_reset_secondary_bus,
+ .dma_set_mask = pnv_pci_ioda_dma_set_mask,
+ .dma_get_required_mask = pnv_pci_ioda_dma_get_required_mask,
+ .shutdown = pnv_pci_ioda_shutdown,
+};
+#endif
+
static void __init pnv_pci_init_ioda_phb(struct device_node *np,
u64 hub_id, int ioda_type)
{
@@ -3417,6 +3507,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
struct pnv_phb *phb;
unsigned long size, m64map_off, m32map_off, pemap_off;
unsigned long iomap_off = 0, dma32map_off = 0;
+ struct resource r;
const __be64 *prop64;
const __be32 *prop32;
int len;
@@ -3425,7 +3516,11 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
void *aux;
long rc;
- pr_info("Initializing IODA%d OPAL PHB %s\n", ioda_type, np->full_name);
+ if (!of_device_is_available(np))
+ return;
+
+ pr_info("Initializing %s PHB (%s)\n",
+ pnv_phb_names[ioda_type], of_node_full_name(np));
prop64 = of_get_property(np, "ibm,opal-phbid", NULL);
if (!prop64) {
@@ -3476,9 +3571,12 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
pci_process_bridge_OF_ranges(hose, np, !hose->global_number);
/* Get registers */
- phb->regs = of_iomap(np, 0);
- if (phb->regs == NULL)
- pr_err(" Failed to map registers !\n");
+ if (!of_address_to_resource(np, 0, &r)) {
+ phb->regs_phys = r.start;
+ phb->regs = ioremap(r.start, resource_size(&r));
+ if (phb->regs == NULL)
+ pr_err(" Failed to map registers !\n");
+ }
/* Initialize more IODA stuff */
phb->ioda.total_pe_num = 1;
@@ -3489,6 +3587,10 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
if (prop32)
phb->ioda.reserved_pe_idx = be32_to_cpup(prop32);
+ /* Invalidate RID to PE# mapping */
+ for (segno = 0; segno < ARRAY_SIZE(phb->ioda.pe_rmap); segno++)
+ phb->ioda.pe_rmap[segno] = IODA_INVALID_PE;
+
/* Parse 64-bit MMIO range */
pnv_ioda_parse_m64_window(phb);
@@ -3540,7 +3642,22 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
phb->ioda.dma32_segmap[segno] = IODA_INVALID_PE;
}
phb->ioda.pe_array = aux + pemap_off;
- set_bit(phb->ioda.reserved_pe_idx, phb->ioda.pe_alloc);
+
+ /*
+ * Choose PE number for root bus, which shouldn't have
+ * M64 resources consumed by its child devices. To pick
+ * the PE number adjacent to the reserved one if possible.
+ */
+ pnv_ioda_reserve_pe(phb, phb->ioda.reserved_pe_idx);
+ if (phb->ioda.reserved_pe_idx == 0) {
+ phb->ioda.root_pe_idx = 1;
+ pnv_ioda_reserve_pe(phb, phb->ioda.root_pe_idx);
+ } else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1)) {
+ phb->ioda.root_pe_idx = phb->ioda.reserved_pe_idx - 1;
+ pnv_ioda_reserve_pe(phb, phb->ioda.root_pe_idx);
+ } else {
+ phb->ioda.root_pe_idx = IODA_INVALID_PE;
+ }
INIT_LIST_HEAD(&phb->ioda.pe_list);
mutex_init(&phb->ioda.pe_list_mutex);
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index 1d92bd93bcd9..6701dd5ded20 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -26,6 +26,7 @@
#include <asm/machdep.h>
#include <asm/msi_bitmap.h>
#include <asm/ppc-pci.h>
+#include <asm/pnv-pci.h>
#include <asm/opal.h>
#include <asm/iommu.h>
#include <asm/tce.h>
@@ -36,8 +37,124 @@
#include "powernv.h"
#include "pci.h"
-/* Delay in usec */
-#define PCI_RESET_DELAY_US 3000000
+int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id)
+{
+ struct device_node *parent = np;
+ u32 bdfn;
+ u64 phbid;
+ int ret;
+
+ ret = of_property_read_u32(np, "reg", &bdfn);
+ if (ret)
+ return -ENXIO;
+
+ bdfn = ((bdfn & 0x00ffff00) >> 8);
+ while ((parent = of_get_parent(parent))) {
+ if (!PCI_DN(parent)) {
+ of_node_put(parent);
+ break;
+ }
+
+ if (!of_device_is_compatible(parent, "ibm,ioda2-phb")) {
+ of_node_put(parent);
+ continue;
+ }
+
+ ret = of_property_read_u64(parent, "ibm,opal-phbid", &phbid);
+ if (ret) {
+ of_node_put(parent);
+ return -ENXIO;
+ }
+
+ *id = PCI_SLOT_ID(phbid, bdfn);
+ return 0;
+ }
+
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(pnv_pci_get_slot_id);
+
+int pnv_pci_get_device_tree(uint32_t phandle, void *buf, uint64_t len)
+{
+ int64_t rc;
+
+ if (!opal_check_token(OPAL_GET_DEVICE_TREE))
+ return -ENXIO;
+
+ rc = opal_get_device_tree(phandle, (uint64_t)buf, len);
+ if (rc < OPAL_SUCCESS)
+ return -EIO;
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(pnv_pci_get_device_tree);
+
+int pnv_pci_get_presence_state(uint64_t id, uint8_t *state)
+{
+ int64_t rc;
+
+ if (!opal_check_token(OPAL_PCI_GET_PRESENCE_STATE))
+ return -ENXIO;
+
+ rc = opal_pci_get_presence_state(id, (uint64_t)state);
+ if (rc != OPAL_SUCCESS)
+ return -EIO;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pnv_pci_get_presence_state);
+
+int pnv_pci_get_power_state(uint64_t id, uint8_t *state)
+{
+ int64_t rc;
+
+ if (!opal_check_token(OPAL_PCI_GET_POWER_STATE))
+ return -ENXIO;
+
+ rc = opal_pci_get_power_state(id, (uint64_t)state);
+ if (rc != OPAL_SUCCESS)
+ return -EIO;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pnv_pci_get_power_state);
+
+int pnv_pci_set_power_state(uint64_t id, uint8_t state, struct opal_msg *msg)
+{
+ struct opal_msg m;
+ int token, ret;
+ int64_t rc;
+
+ if (!opal_check_token(OPAL_PCI_SET_POWER_STATE))
+ return -ENXIO;
+
+ token = opal_async_get_token_interruptible();
+ if (unlikely(token < 0))
+ return token;
+
+ rc = opal_pci_set_power_state(token, id, (uint64_t)&state);
+ if (rc == OPAL_SUCCESS) {
+ ret = 0;
+ goto exit;
+ } else if (rc != OPAL_ASYNC_COMPLETION) {
+ ret = -EIO;
+ goto exit;
+ }
+
+ ret = opal_async_wait_response(token, &m);
+ if (ret < 0)
+ goto exit;
+
+ if (msg) {
+ ret = 1;
+ memcpy(msg, &m, sizeof(m));
+ }
+
+exit:
+ opal_async_release_token(token);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pnv_pci_set_power_state);
#ifdef CONFIG_PCI_MSI
int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
@@ -620,8 +737,8 @@ int pnv_tce_xchg(struct iommu_table *tbl, long index,
if (newtce & TCE_PCI_WRITE)
newtce |= TCE_PCI_READ;
- oldtce = xchg(pnv_tce(tbl, idx), cpu_to_be64(newtce));
- *hpa = be64_to_cpu(oldtce) & ~(TCE_PCI_READ | TCE_PCI_WRITE);
+ oldtce = be64_to_cpu(xchg(pnv_tce(tbl, idx), cpu_to_be64(newtce)));
+ *hpa = oldtce & ~(TCE_PCI_READ | TCE_PCI_WRITE);
*direction = iommu_tce_direction(oldtce);
return 0;
@@ -815,13 +932,14 @@ void __init pnv_pci_init(void)
for_each_compatible_node(np, NULL, "ibm,ioda2-phb")
pnv_pci_init_ioda2_phb(np);
+ /* Look for ioda3 built-in PHB4's, we treat them as IODA2 */
+ for_each_compatible_node(np, NULL, "ibm,ioda3-phb")
+ pnv_pci_init_ioda2_phb(np);
+
/* Look for NPU PHBs */
for_each_compatible_node(np, NULL, "ibm,ioda2-npu-phb")
pnv_pci_init_npu_phb(np);
- /* Setup the linkage between OF nodes and PHBs */
- pci_devs_phb_init();
-
/* Configure IOMMU DMA hooks */
set_pci_dma_ops(&dma_iommu_ops);
}
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 7dee25e304db..d088d4f06116 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -1,6 +1,10 @@
#ifndef __POWERNV_PCI_H
#define __POWERNV_PCI_H
+#include <linux/iommu.h>
+#include <asm/iommu.h>
+#include <asm/msi_bitmap.h>
+
struct pci_dn;
enum pnv_phb_type {
@@ -30,6 +34,7 @@ struct pnv_phb;
struct pnv_ioda_pe {
unsigned long flags;
struct pnv_phb *phb;
+ int device_count;
/* A PE can be associated with a single device or an
* entire bus (& children). In the former case, pdev
@@ -71,6 +76,7 @@ struct pnv_ioda_pe {
};
#define PNV_PHB_FLAG_EEH (1 << 0)
+#define PNV_PHB_FLAG_CXL (1 << 1) /* Real PHB supporting the cxl kernel API */
struct pnv_phb {
struct pci_controller *hose;
@@ -80,6 +86,7 @@ struct pnv_phb {
u64 opal_id;
int flags;
void __iomem *regs;
+ u64 regs_phys;
int initialized;
spinlock_t lock;
@@ -110,6 +117,8 @@ struct pnv_phb {
/* Global bridge info */
unsigned int total_pe_num;
unsigned int reserved_pe_idx;
+ unsigned int root_pe_idx;
+ bool root_pe_populated;
/* 32-bit MMIO window */
unsigned int m32_size;
@@ -152,17 +161,8 @@ struct pnv_phb {
struct list_head pe_list;
struct mutex pe_list_mutex;
- /* Reverse map of PEs, will have to extend if
- * we are to support more than 256 PEs, indexed
- * bus { bus, devfn }
- */
- unsigned char pe_rmap[0x10000];
-
- /* TCE cache invalidate registers (physical and
- * remapped)
- */
- phys_addr_t tce_inval_reg_phys;
- __be64 __iomem *tce_inval_reg;
+ /* Reverse map of PEs, indexed by {bus, devfn} */
+ unsigned int pe_rmap[0x10000];
} ioda;
/* PHB and hub status structure */
@@ -173,6 +173,9 @@ struct pnv_phb {
struct OpalIoP7IOCErrorData hub_diag;
} diag;
+#ifdef CONFIG_CXL_BASE
+ struct cxl_afu *cxl_afu;
+#endif
};
extern struct pci_ops pnv_pci_ops;
@@ -203,8 +206,6 @@ extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
extern void pnv_pci_init_ioda_hub(struct device_node *np);
extern void pnv_pci_init_ioda2_phb(struct device_node *np);
extern void pnv_pci_init_npu_phb(struct device_node *np);
-extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl,
- __be64 *startp, __be64 *endp, bool rm);
extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev);
extern int pnv_eeh_phb_reset(struct pci_controller *hose, int option);
@@ -212,6 +213,9 @@ extern void pnv_pci_dma_dev_setup(struct pci_dev *pdev);
extern void pnv_pci_dma_bus_setup(struct pci_bus *bus);
extern int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type);
extern void pnv_teardown_msi_irqs(struct pci_dev *pdev);
+extern struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev);
+extern void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq);
+extern bool pnv_pci_enable_device_hook(struct pci_dev *dev);
extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level,
const char *fmt, ...);
@@ -224,7 +228,7 @@ extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level,
/* Nvlink functions */
extern void pnv_npu_try_dma_set_bypass(struct pci_dev *gpdev, bool bypass);
-extern void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_phb *phb, bool rm);
+extern void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm);
extern struct pnv_ioda_pe *pnv_pci_npu_setup_iommu(struct pnv_ioda_pe *npe);
extern long pnv_npu_set_window(struct pnv_ioda_pe *npe, int num,
struct iommu_table *tbl);
@@ -232,4 +236,15 @@ extern long pnv_npu_unset_window(struct pnv_ioda_pe *npe, int num);
extern void pnv_npu_take_ownership(struct pnv_ioda_pe *npe);
extern void pnv_npu_release_ownership(struct pnv_ioda_pe *npe);
+
+/* cxl functions */
+extern bool pnv_cxl_enable_device_hook(struct pci_dev *dev);
+extern void pnv_cxl_disable_device(struct pci_dev *dev);
+extern int pnv_cxl_cx4_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type);
+extern void pnv_cxl_cx4_teardown_msi_irqs(struct pci_dev *pdev);
+
+
+/* phb ops (cxl switches these when enabling the kernel api on the phb) */
+extern const struct pci_controller_ops pnv_cxl_cx4_ioda_controller_ops;
+
#endif /* __POWERNV_PCI_H */
diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h
index 6dbc0a1da1f6..da7c843ac7f1 100644
--- a/arch/powerpc/platforms/powernv/powernv.h
+++ b/arch/powerpc/platforms/powernv/powernv.h
@@ -18,6 +18,7 @@ static inline void pnv_pci_shutdown(void) { }
#endif
extern u32 pnv_get_supported_cpuidle_states(void);
+extern u64 pnv_deepest_stop_state;
extern void pnv_lpc_init(void);
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index ee6430bedcc3..efe8b6bb168b 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -58,7 +58,7 @@ static void __init pnv_setup_arch(void)
/* XXX PMCS */
}
-static void __init pnv_init_early(void)
+static void __init pnv_init(void)
{
/*
* Initialize the LPC bus now so that legacy serial
@@ -268,21 +268,16 @@ static void __init pnv_setup_machdep_opal(void)
static int __init pnv_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
-
- if (!of_flat_dt_is_compatible(root, "ibm,powernv"))
+ if (!of_machine_is_compatible("ibm,powernv"))
return 0;
- if (IS_ENABLED(CONFIG_PPC_RADIX_MMU) && radix_enabled())
- radix_init_native();
- else if (IS_ENABLED(CONFIG_PPC_STD_MMU_64))
- hpte_init_native();
-
if (firmware_has_feature(FW_FEATURE_OPAL))
pnv_setup_machdep_opal();
pr_debug("PowerNV detected !\n");
+ pnv_init();
+
return 1;
}
@@ -308,14 +303,13 @@ static unsigned long pnv_get_proc_freq(unsigned int cpu)
define_machine(powernv) {
.name = "PowerNV",
.probe = pnv_probe,
- .init_early = pnv_init_early,
.setup_arch = pnv_setup_arch,
.init_IRQ = pnv_init_IRQ,
.show_cpuinfo = pnv_show_cpuinfo,
.get_proc_freq = pnv_get_proc_freq,
.progress = pnv_progress,
.machine_shutdown = pnv_shutdown,
- .power_save = power7_idle,
+ .power_save = NULL,
.calibrate_decr = generic_calibrate_decr,
#ifdef CONFIG_KEXEC
.kexec_cpu_down = pnv_kexec_cpu_down,
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index ad7b1a3dbed0..c789258ae1e1 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -182,7 +182,9 @@ static void pnv_smp_cpu_kill_self(void)
ppc64_runlatch_off();
- if (idle_states & OPAL_PM_WINKLE_ENABLED)
+ if (cpu_has_feature(CPU_FTR_ARCH_300))
+ srr1 = power9_idle_stop(pnv_deepest_stop_state);
+ else if (idle_states & OPAL_PM_WINKLE_ENABLED)
srr1 = power7_winkle();
else if ((idle_states & OPAL_PM_SLEEP_ENABLED) ||
(idle_states & OPAL_PM_SLEEP_ENABLED_ER1))
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index c9a3e677192a..cb3c50328de8 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -195,12 +195,12 @@ static void ps3_hpte_clear(void)
void __init ps3_hpte_init(unsigned long htab_size)
{
- ppc_md.hpte_invalidate = ps3_hpte_invalidate;
- ppc_md.hpte_updatepp = ps3_hpte_updatepp;
- ppc_md.hpte_updateboltedpp = ps3_hpte_updateboltedpp;
- ppc_md.hpte_insert = ps3_hpte_insert;
- ppc_md.hpte_remove = ps3_hpte_remove;
- ppc_md.hpte_clear_all = ps3_hpte_clear;
+ mmu_hash_ops.hpte_invalidate = ps3_hpte_invalidate;
+ mmu_hash_ops.hpte_updatepp = ps3_hpte_updatepp;
+ mmu_hash_ops.hpte_updateboltedpp = ps3_hpte_updateboltedpp;
+ mmu_hash_ops.hpte_insert = ps3_hpte_insert;
+ mmu_hash_ops.hpte_remove = ps3_hpte_remove;
+ mmu_hash_ops.hpte_clear_all = ps3_hpte_clear;
ppc64_pft_size = __ilog2(htab_size);
}
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
index bfccdc7cb85f..814a7eaa7769 100644
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -1198,7 +1198,7 @@ int ps3_repository_delete_highmem_info(unsigned int region_index)
return result ? -1 : 0;
}
-#endif /* defined(CONFIG_PS3_WRITE_REPOSITORY) */
+#endif /* defined(CONFIG_PS3_REPOSITORY_WRITE) */
#if defined(DEBUG)
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 799c8580ab09..3a487e7f4a5e 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -80,7 +80,7 @@ static void ps3_power_save(void)
lv1_pause(0);
}
-static void ps3_restart(char *cmd)
+static void __noreturn ps3_restart(char *cmd)
{
DBG("%s:%d cmd '%s'\n", __func__, __LINE__, cmd);
@@ -96,7 +96,7 @@ static void ps3_power_off(void)
ps3_sys_manager_power_off(); /* never returns */
}
-static void ps3_halt(void)
+static void __noreturn ps3_halt(void)
{
DBG("%s:%d\n", __func__, __LINE__);
@@ -226,23 +226,24 @@ static void __init ps3_progress(char *s, unsigned short hex)
printk("*** %04x : %s\n", hex, s ? s : "");
}
-static int __init ps3_probe(void)
+void __init ps3_early_mm_init(void)
{
unsigned long htab_size;
- unsigned long dt_root;
+ ps3_mm_init();
+ ps3_mm_vas_create(&htab_size);
+ ps3_hpte_init(htab_size);
+}
+
+static int __init ps3_probe(void)
+{
DBG(" -> %s:%d\n", __func__, __LINE__);
- dt_root = of_get_flat_dt_root();
- if (!of_flat_dt_is_compatible(dt_root, "sony,ps3"))
+ if (!of_machine_is_compatible("sony,ps3"))
return 0;
- powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;
-
ps3_os_area_save_params();
- ps3_mm_init();
- ps3_mm_vas_create(&htab_size);
- ps3_hpte_init(htab_size);
+
pm_power_off = ps3_power_off;
DBG(" <- %s:%d\n", __func__, __LINE__);
diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c
index fc44ad0475f8..66e7227469b8 100644
--- a/arch/powerpc/platforms/pseries/cmm.c
+++ b/arch/powerpc/platforms/pseries/cmm.c
@@ -574,7 +574,7 @@ static int cmm_mem_going_offline(void *arg)
cmm_dbg("Failed to allocate memory for list "
"management. Memory hotplug "
"failed.\n");
- return ENOMEM;
+ return -ENOMEM;
}
memcpy(npa, pa_curr, PAGE_SIZE);
if (pa_curr == cmm_page_list)
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 2b93ae8d557a..4748124faa10 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -27,6 +27,15 @@
#include <asm/uaccess.h>
#include <asm/rtas.h>
+struct workqueue_struct *pseries_hp_wq;
+
+struct pseries_hp_work {
+ struct work_struct work;
+ struct pseries_hp_errorlog *errlog;
+ struct completion *hp_completion;
+ int *rc;
+};
+
struct cc_workarea {
__be32 drc_index;
__be32 zero;
@@ -368,10 +377,51 @@ static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog)
return rc;
}
+void pseries_hp_work_fn(struct work_struct *work)
+{
+ struct pseries_hp_work *hp_work =
+ container_of(work, struct pseries_hp_work, work);
+
+ if (hp_work->rc)
+ *(hp_work->rc) = handle_dlpar_errorlog(hp_work->errlog);
+ else
+ handle_dlpar_errorlog(hp_work->errlog);
+
+ if (hp_work->hp_completion)
+ complete(hp_work->hp_completion);
+
+ kfree(hp_work->errlog);
+ kfree((void *)work);
+}
+
+void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog,
+ struct completion *hotplug_done, int *rc)
+{
+ struct pseries_hp_work *work;
+ struct pseries_hp_errorlog *hp_errlog_copy;
+
+ hp_errlog_copy = kmalloc(sizeof(struct pseries_hp_errorlog),
+ GFP_KERNEL);
+ memcpy(hp_errlog_copy, hp_errlog, sizeof(struct pseries_hp_errorlog));
+
+ work = kmalloc(sizeof(struct pseries_hp_work), GFP_KERNEL);
+ if (work) {
+ INIT_WORK((struct work_struct *)work, pseries_hp_work_fn);
+ work->errlog = hp_errlog_copy;
+ work->hp_completion = hotplug_done;
+ work->rc = rc;
+ queue_work(pseries_hp_wq, (struct work_struct *)work);
+ } else {
+ *rc = -ENOMEM;
+ complete(hotplug_done);
+ }
+}
+
static ssize_t dlpar_store(struct class *class, struct class_attribute *attr,
const char *buf, size_t count)
{
struct pseries_hp_errorlog *hp_elog;
+ struct completion hotplug_done;
const char *arg;
int rc;
@@ -439,7 +489,9 @@ static ssize_t dlpar_store(struct class *class, struct class_attribute *attr,
goto dlpar_store_out;
}
- rc = handle_dlpar_errorlog(hp_elog);
+ init_completion(&hotplug_done);
+ queue_hotplug_event(hp_elog, &hotplug_done, &rc);
+ wait_for_completion(&hotplug_done);
dlpar_store_out:
kfree(hp_elog);
@@ -450,6 +502,8 @@ static CLASS_ATTR(dlpar, S_IWUSR, NULL, dlpar_store);
static int __init pseries_dlpar_init(void)
{
+ pseries_hp_wq = alloc_workqueue("pseries hotplug workqueue",
+ WQ_UNBOUND, 1);
return sysfs_create_file(kernel_kobj, &class_attr_dlpar.attr);
}
machine_device_initcall(pseries, pseries_dlpar_init);
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index 3998e0f9a03b..1c428f06b14c 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -2,7 +2,7 @@
* The file intends to implement the platform dependent EEH operations on pseries.
* Actually, the pseries platform is built based on RTAS heavily. That means the
* pseries platform dependent EEH operations will be built on RTAS calls. The functions
- * are devired from arch/powerpc/platforms/pseries/eeh.c and necessary cleanup has
+ * are derived from arch/powerpc/platforms/pseries/eeh.c and necessary cleanup has
* been done.
*
* Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2011.
diff --git a/arch/powerpc/platforms/pseries/event_sources.c b/arch/powerpc/platforms/pseries/event_sources.c
index 18380e8f6dfe..a6ddca833119 100644
--- a/arch/powerpc/platforms/pseries/event_sources.c
+++ b/arch/powerpc/platforms/pseries/event_sources.c
@@ -26,48 +26,21 @@ void request_event_sources_irqs(struct device_node *np,
{
int i, index, count = 0;
struct of_phandle_args oirq;
- const u32 *opicprop;
- unsigned int opicplen;
unsigned int virqs[16];
- /* Check for obsolete "open-pic-interrupt" property. If present, then
- * map those interrupts using the default interrupt host and default
- * trigger
- */
- opicprop = of_get_property(np, "open-pic-interrupt", &opicplen);
- if (opicprop) {
- opicplen /= sizeof(u32);
- for (i = 0; i < opicplen; i++) {
- if (count > 15)
- break;
- virqs[count] = irq_create_mapping(NULL, *(opicprop++));
- if (virqs[count] == NO_IRQ) {
- pr_err("event-sources: Unable to allocate "
- "interrupt number for %s\n",
- np->full_name);
- WARN_ON(1);
- }
- else
- count++;
-
- }
- }
- /* Else use normal interrupt tree parsing */
- else {
- /* First try to do a proper OF tree parsing */
- for (index = 0; of_irq_parse_one(np, index, &oirq) == 0;
- index++) {
- if (count > 15)
- break;
- virqs[count] = irq_create_of_mapping(&oirq);
- if (virqs[count] == NO_IRQ) {
- pr_err("event-sources: Unable to allocate "
- "interrupt number for %s\n",
- np->full_name);
- WARN_ON(1);
- }
- else
- count++;
+ /* First try to do a proper OF tree parsing */
+ for (index = 0; of_irq_parse_one(np, index, &oirq) == 0;
+ index++) {
+ if (count > 15)
+ break;
+ virqs[count] = irq_create_of_mapping(&oirq);
+ if (virqs[count] == NO_IRQ) {
+ pr_err("event-sources: Unable to allocate "
+ "interrupt number for %s\n",
+ np->full_name);
+ WARN_ON(1);
+ } else {
+ count++;
}
}
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
index 8c80588abacc..ea7f09bd73b1 100644
--- a/arch/powerpc/platforms/pseries/firmware.c
+++ b/arch/powerpc/platforms/pseries/firmware.c
@@ -22,6 +22,7 @@
*/
+#include <linux/of_fdt.h>
#include <asm/firmware.h>
#include <asm/prom.h>
#include <asm/udbg.h>
@@ -69,7 +70,8 @@ hypertas_fw_features_table[] = {
* device-tree/ibm,hypertas-functions. Ultimately this functionality may
* be moved into prom.c prom_init().
*/
-void __init fw_hypertas_feature_init(const char *hypertas, unsigned long len)
+static void __init fw_hypertas_feature_init(const char *hypertas,
+ unsigned long len)
{
const char *s;
int i;
@@ -113,7 +115,7 @@ vec5_fw_features_table[] = {
{FW_FEATURE_PRRN, OV5_PRRN},
};
-void __init fw_vec5_feature_init(const char *vec5, unsigned long len)
+static void __init fw_vec5_feature_init(const char *vec5, unsigned long len)
{
unsigned int index, feat;
int i;
@@ -131,3 +133,45 @@ void __init fw_vec5_feature_init(const char *vec5, unsigned long len)
pr_debug(" <- fw_vec5_feature_init()\n");
}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init probe_fw_features(unsigned long node, const char *uname, int
+ depth, void *data)
+{
+ const char *prop;
+ int len;
+ static int hypertas_found;
+ static int vec5_found;
+
+ if (depth != 1)
+ return 0;
+
+ if (!strcmp(uname, "rtas") || !strcmp(uname, "rtas@0")) {
+ prop = of_get_flat_dt_prop(node, "ibm,hypertas-functions",
+ &len);
+ if (prop) {
+ powerpc_firmware_features |= FW_FEATURE_LPAR;
+ fw_hypertas_feature_init(prop, len);
+ }
+
+ hypertas_found = 1;
+ }
+
+ if (!strcmp(uname, "chosen")) {
+ prop = of_get_flat_dt_prop(node, "ibm,architecture-vec-5",
+ &len);
+ if (prop)
+ fw_vec5_feature_init(prop, len);
+
+ vec5_found = 1;
+ }
+
+ return hypertas_found && vec5_found;
+}
+
+void __init pseries_probe_fw_features(void)
+{
+ of_scan_flat_dt(probe_fw_features, NULL);
+}
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 282837a1d74b..a1b63e00b2f7 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -903,8 +903,6 @@ static int parse_cede_parameters(void)
static int __init pseries_cpu_hotplug_init(void)
{
- struct device_node *np;
- const char *typep;
int cpu;
int qcss_tok;
@@ -913,17 +911,6 @@ static int __init pseries_cpu_hotplug_init(void)
ppc_md.cpu_release = dlpar_cpu_release;
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
- for_each_node_by_name(np, "interrupt-controller") {
- typep = of_get_property(np, "compatible", NULL);
- if (strstr(typep, "open-pic")) {
- of_node_put(np);
-
- printk(KERN_INFO "CPU Hotplug not supported on "
- "systems using MPIC\n");
- return 0;
- }
- }
-
rtas_stop_self_token = rtas_token("stop-self");
qcss_tok = rtas_token("query-cpu-stopped-state");
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 2ce138542083..43f7beb2902d 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -69,13 +69,36 @@ unsigned long pseries_memory_block_size(void)
return memblock_size;
}
-static void dlpar_free_drconf_property(struct property *prop)
+static void dlpar_free_property(struct property *prop)
{
kfree(prop->name);
kfree(prop->value);
kfree(prop);
}
+static struct property *dlpar_clone_property(struct property *prop,
+ u32 prop_size)
+{
+ struct property *new_prop;
+
+ new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
+ if (!new_prop)
+ return NULL;
+
+ new_prop->name = kstrdup(prop->name, GFP_KERNEL);
+ new_prop->value = kzalloc(prop_size, GFP_KERNEL);
+ if (!new_prop->name || !new_prop->value) {
+ dlpar_free_property(new_prop);
+ return NULL;
+ }
+
+ memcpy(new_prop->value, prop->value, prop->length);
+ new_prop->length = prop_size;
+
+ of_property_set_flag(new_prop, OF_DYNAMIC);
+ return new_prop;
+}
+
static struct property *dlpar_clone_drconf_property(struct device_node *dn)
{
struct property *prop, *new_prop;
@@ -87,19 +110,10 @@ static struct property *dlpar_clone_drconf_property(struct device_node *dn)
if (!prop)
return NULL;
- new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
+ new_prop = dlpar_clone_property(prop, prop->length);
if (!new_prop)
return NULL;
- new_prop->name = kstrdup(prop->name, GFP_KERNEL);
- new_prop->value = kmemdup(prop->value, prop->length, GFP_KERNEL);
- if (!new_prop->name || !new_prop->value) {
- dlpar_free_drconf_property(new_prop);
- return NULL;
- }
-
- new_prop->length = prop->length;
-
/* Convert the property to cpu endian-ness */
p = new_prop->value;
*p = be32_to_cpu(*p);
@@ -177,14 +191,74 @@ static int dlpar_update_device_tree_lmb(struct of_drconf_cell *lmb)
return 0;
}
+static u32 find_aa_index(struct device_node *dr_node,
+ struct property *ala_prop, const u32 *lmb_assoc)
+{
+ u32 *assoc_arrays;
+ u32 aa_index;
+ int aa_arrays, aa_array_entries, aa_array_sz;
+ int i, index;
+
+ /*
+ * The ibm,associativity-lookup-arrays property is defined to be
+ * a 32-bit value specifying the number of associativity arrays
+ * followed by a 32-bitvalue specifying the number of entries per
+ * array, followed by the associativity arrays.
+ */
+ assoc_arrays = ala_prop->value;
+
+ aa_arrays = be32_to_cpu(assoc_arrays[0]);
+ aa_array_entries = be32_to_cpu(assoc_arrays[1]);
+ aa_array_sz = aa_array_entries * sizeof(u32);
+
+ aa_index = -1;
+ for (i = 0; i < aa_arrays; i++) {
+ index = (i * aa_array_entries) + 2;
+
+ if (memcmp(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz))
+ continue;
+
+ aa_index = i;
+ break;
+ }
+
+ if (aa_index == -1) {
+ struct property *new_prop;
+ u32 new_prop_size;
+
+ new_prop_size = ala_prop->length + aa_array_sz;
+ new_prop = dlpar_clone_property(ala_prop, new_prop_size);
+ if (!new_prop)
+ return -1;
+
+ assoc_arrays = new_prop->value;
+
+ /* increment the number of entries in the lookup array */
+ assoc_arrays[0] = cpu_to_be32(aa_arrays + 1);
+
+ /* copy the new associativity into the lookup array */
+ index = aa_arrays * aa_array_entries + 2;
+ memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz);
+
+ of_update_property(dr_node, new_prop);
+
+ /*
+ * The associativity lookup array index for this lmb is
+ * number of entries - 1 since we added its associativity
+ * to the end of the lookup array.
+ */
+ aa_index = be32_to_cpu(assoc_arrays[0]) - 1;
+ }
+
+ return aa_index;
+}
+
static u32 lookup_lmb_associativity_index(struct of_drconf_cell *lmb)
{
struct device_node *parent, *lmb_node, *dr_node;
+ struct property *ala_prop;
const u32 *lmb_assoc;
- const u32 *assoc_arrays;
u32 aa_index;
- int aa_arrays, aa_array_entries, aa_array_sz;
- int i;
parent = of_find_node_by_path("/");
if (!parent)
@@ -208,34 +282,15 @@ static u32 lookup_lmb_associativity_index(struct of_drconf_cell *lmb)
return -ENODEV;
}
- assoc_arrays = of_get_property(dr_node,
- "ibm,associativity-lookup-arrays",
- NULL);
- of_node_put(dr_node);
- if (!assoc_arrays) {
+ ala_prop = of_find_property(dr_node, "ibm,associativity-lookup-arrays",
+ NULL);
+ if (!ala_prop) {
+ of_node_put(dr_node);
dlpar_free_cc_nodes(lmb_node);
return -ENODEV;
}
- /* The ibm,associativity-lookup-arrays property is defined to be
- * a 32-bit value specifying the number of associativity arrays
- * followed by a 32-bitvalue specifying the number of entries per
- * array, followed by the associativity arrays.
- */
- aa_arrays = be32_to_cpu(assoc_arrays[0]);
- aa_array_entries = be32_to_cpu(assoc_arrays[1]);
- aa_array_sz = aa_array_entries * sizeof(u32);
-
- aa_index = -1;
- for (i = 0; i < aa_arrays; i++) {
- int indx = (i * aa_array_entries) + 2;
-
- if (memcmp(&assoc_arrays[indx], &lmb_assoc[1], aa_array_sz))
- continue;
-
- aa_index = i;
- break;
- }
+ aa_index = find_aa_index(dr_node, ala_prop, lmb_assoc);
dlpar_free_cc_nodes(lmb_node);
return aa_index;
@@ -533,50 +588,11 @@ static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
#endif /* CONFIG_MEMORY_HOTREMOVE */
-static int dlpar_add_lmb_memory(struct of_drconf_cell *lmb)
+static int dlpar_add_lmb(struct of_drconf_cell *lmb)
{
- struct memory_block *mem_block;
unsigned long block_sz;
int nid, rc;
- block_sz = memory_block_size_bytes();
-
- /* Find the node id for this address */
- nid = memory_add_physaddr_to_nid(lmb->base_addr);
-
- /* Add the memory */
- rc = add_memory(nid, lmb->base_addr, block_sz);
- if (rc)
- return rc;
-
- /* Register this block of memory */
- rc = memblock_add(lmb->base_addr, block_sz);
- if (rc) {
- remove_memory(nid, lmb->base_addr, block_sz);
- return rc;
- }
-
- mem_block = lmb_to_memblock(lmb);
- if (!mem_block) {
- remove_memory(nid, lmb->base_addr, block_sz);
- return -EINVAL;
- }
-
- rc = device_online(&mem_block->dev);
- put_device(&mem_block->dev);
- if (rc) {
- remove_memory(nid, lmb->base_addr, block_sz);
- return rc;
- }
-
- lmb->flags |= DRCONF_MEM_ASSIGNED;
- return 0;
-}
-
-static int dlpar_add_lmb(struct of_drconf_cell *lmb)
-{
- int rc;
-
if (lmb->flags & DRCONF_MEM_ASSIGNED)
return -EINVAL;
@@ -592,10 +608,18 @@ static int dlpar_add_lmb(struct of_drconf_cell *lmb)
return rc;
}
- rc = dlpar_add_lmb_memory(lmb);
+ block_sz = memory_block_size_bytes();
+
+ /* Find the node id for this address */
+ nid = memory_add_physaddr_to_nid(lmb->base_addr);
+
+ /* Add the memory */
+ rc = add_memory(nid, lmb->base_addr, block_sz);
if (rc) {
dlpar_remove_device_tree_lmb(lmb);
dlpar_release_drc(lmb->drc_index);
+ } else {
+ lmb->flags |= DRCONF_MEM_ASSIGNED;
}
return rc;
@@ -748,7 +772,7 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
break;
}
- dlpar_free_drconf_property(prop);
+ dlpar_free_property(prop);
dlpar_memory_out:
of_node_put(dn);
diff --git a/arch/powerpc/platforms/pseries/io_event_irq.c b/arch/powerpc/platforms/pseries/io_event_irq.c
index 0240c4ff878a..f053bda64ee7 100644
--- a/arch/powerpc/platforms/pseries/io_event_irq.c
+++ b/arch/powerpc/platforms/pseries/io_event_irq.c
@@ -113,7 +113,7 @@ static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog)
* - The owner of an event is determined by combinations of scope,
* event type, and sub-type. There is no easy way to pre-sort clients
* by scope or event type alone. For example, Torrent ISR route change
- * event is reported with scope 0x00 (Not Applicatable) rather than
+ * event is reported with scope 0x00 (Not Applicable) rather than
* 0x3B (Torrent-hub). It is better to let the clients to identify
* who owns the event.
*/
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 3e8865b187de..770a753b52c9 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -120,35 +120,6 @@ static void iommu_pseries_free_group(struct iommu_table_group *table_group,
kfree(table_group);
}
-static void tce_invalidate_pSeries_sw(struct iommu_table *tbl,
- __be64 *startp, __be64 *endp)
-{
- u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index;
- unsigned long start, end, inc;
-
- start = __pa(startp);
- end = __pa(endp);
- inc = L1_CACHE_BYTES; /* invalidate a cacheline of TCEs at a time */
-
- /* If this is non-zero, change the format. We shift the
- * address and or in the magic from the device tree. */
- if (tbl->it_busno) {
- start <<= 12;
- end <<= 12;
- inc <<= 12;
- start |= tbl->it_busno;
- end |= tbl->it_busno;
- }
-
- end |= inc - 1; /* round up end to be different than start */
-
- mb(); /* Make sure TCEs in memory are written */
- while (start <= end) {
- out_be64(invalidate, start);
- start += inc;
- }
-}
-
static int tce_build_pSeries(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
enum dma_data_direction direction,
@@ -173,9 +144,6 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index,
uaddr += TCE_PAGE_SIZE;
tcep++;
}
-
- if (tbl->it_type & TCE_PCI_SWINV_CREATE)
- tce_invalidate_pSeries_sw(tbl, tces, tcep - 1);
return 0;
}
@@ -188,9 +156,6 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
while (npages--)
*(tcep++) = 0;
-
- if (tbl->it_type & TCE_PCI_SWINV_FREE)
- tce_invalidate_pSeries_sw(tbl, tces, tcep - 1);
}
static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
@@ -537,7 +502,7 @@ static void iommu_table_setparms(struct pci_controller *phb,
struct iommu_table *tbl)
{
struct device_node *node;
- const unsigned long *basep, *sw_inval;
+ const unsigned long *basep;
const u32 *sizep;
node = phb->dn;
@@ -575,22 +540,6 @@ static void iommu_table_setparms(struct pci_controller *phb,
tbl->it_index = 0;
tbl->it_blocksize = 16;
tbl->it_type = TCE_PCI;
-
- sw_inval = of_get_property(node, "linux,tce-sw-invalidate-info", NULL);
- if (sw_inval) {
- /*
- * This property contains information on how to
- * invalidate the TCE entry. The first property is
- * the base MMIO address used to invalidate entries.
- * The second property tells us the format of the TCE
- * invalidate (whether it needs to be shifted) and
- * some magic routing info to add to our invalidate
- * command.
- */
- tbl->it_index = (unsigned long) ioremap(sw_inval[0], 8);
- tbl->it_busno = sw_inval[1]; /* overload this with magic */
- tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE;
- }
}
/*
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c
index 13fa95b3aa8b..6681ac97fb18 100644
--- a/arch/powerpc/platforms/pseries/kexec.c
+++ b/arch/powerpc/platforms/pseries/kexec.c
@@ -14,14 +14,13 @@
#include <asm/page.h>
#include <asm/firmware.h>
#include <asm/kexec.h>
-#include <asm/mpic.h>
#include <asm/xics.h>
#include <asm/smp.h>
#include <asm/plpar_wrappers.h>
#include "pseries.h"
-static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
+void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
{
/* Don't risk a hypervisor call if we're crashing */
if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
@@ -51,26 +50,6 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
"(hw %d) failed with %d\n", cpu, hwcpu, ret);
}
}
-}
-
-static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary)
-{
- pseries_kexec_cpu_down(crash_shutdown, secondary);
- mpic_teardown_this_cpu(secondary);
-}
-void __init setup_kexec_cpu_down_mpic(void)
-{
- ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_mpic;
-}
-
-static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary)
-{
- pseries_kexec_cpu_down(crash_shutdown, secondary);
xics_kexec_teardown_cpu(secondary);
}
-
-void __init setup_kexec_cpu_down_xics(void)
-{
- ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_xics;
-}
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 7f6100d91b4b..86707e67843f 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -45,6 +45,7 @@
#include <asm/plpar_wrappers.h>
#include <asm/kexec.h>
#include <asm/fadump.h>
+#include <asm/asm-prototypes.h>
#include "pseries.h"
@@ -260,24 +261,8 @@ static void pSeries_lpar_hptab_clear(void)
* This is also called on boot when a fadump happens. In that case we
* must not change the exception endian mode.
*/
- if (firmware_has_feature(FW_FEATURE_SET_MODE) && !is_fadump_active()) {
- long rc;
-
- rc = pseries_big_endian_exceptions();
- /*
- * At this point it is unlikely panic() will get anything
- * out to the user, but at least this will stop us from
- * continuing on further and creating an even more
- * difficult to debug situation.
- *
- * There is a known problem when kdump'ing, if cpus are offline
- * the above call will fail. Rather than panicking again, keep
- * going and hope the kdump kernel is also little endian, which
- * it usually is.
- */
- if (rc && !kdump_in_progress())
- panic("Could not enable big endian exceptions");
- }
+ if (firmware_has_feature(FW_FEATURE_SET_MODE) && !is_fadump_active())
+ pseries_big_endian_exceptions();
#endif
}
@@ -604,17 +589,17 @@ static int __init disable_bulk_remove(char *str)
__setup("bulk_remove=", disable_bulk_remove);
-void __init hpte_init_lpar(void)
+void __init hpte_init_pseries(void)
{
- ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate;
- ppc_md.hpte_updatepp = pSeries_lpar_hpte_updatepp;
- ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
- ppc_md.hpte_insert = pSeries_lpar_hpte_insert;
- ppc_md.hpte_remove = pSeries_lpar_hpte_remove;
- ppc_md.hpte_removebolted = pSeries_lpar_hpte_removebolted;
- ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
- ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear;
- ppc_md.hugepage_invalidate = pSeries_lpar_hugepage_invalidate;
+ mmu_hash_ops.hpte_invalidate = pSeries_lpar_hpte_invalidate;
+ mmu_hash_ops.hpte_updatepp = pSeries_lpar_hpte_updatepp;
+ mmu_hash_ops.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
+ mmu_hash_ops.hpte_insert = pSeries_lpar_hpte_insert;
+ mmu_hash_ops.hpte_remove = pSeries_lpar_hpte_remove;
+ mmu_hash_ops.hpte_removebolted = pSeries_lpar_hpte_removebolted;
+ mmu_hash_ops.flush_hash_range = pSeries_lpar_flush_hash_range;
+ mmu_hash_ops.hpte_clear_all = pSeries_lpar_hptab_clear;
+ mmu_hash_ops.hugepage_invalidate = pSeries_lpar_hugepage_invalidate;
}
#ifdef CONFIG_PPC_SMLPAR
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 9f8184175c86..79aef8c1c5b3 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -17,8 +17,6 @@
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
-#include <linux/kmsg_dump.h>
-#include <linux/pstore.h>
#include <linux/ctype.h>
#include <asm/uaccess.h>
#include <asm/nvram.h>
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c
index c26eadde434c..a4a0b57d1d81 100644
--- a/arch/powerpc/platforms/pseries/power.c
+++ b/arch/powerpc/platforms/pseries/power.c
@@ -27,6 +27,8 @@
#include <linux/init.h>
#include <asm/machdep.h>
+#include "pseries.h"
+
unsigned long rtas_poweron_auto; /* default and normal state is 0 */
static ssize_t auto_poweron_show(struct kobject *kobj,
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 7aa83f00ac62..b1be7b713fe6 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -20,31 +20,18 @@ extern void request_event_sources_irqs(struct device_node *np,
#include <linux/of.h>
-extern void __init fw_hypertas_feature_init(const char *hypertas,
- unsigned long len);
-extern void __init fw_vec5_feature_init(const char *hypertas,
- unsigned long len);
-
struct pt_regs;
extern int pSeries_system_reset_exception(struct pt_regs *regs);
extern int pSeries_machine_check_exception(struct pt_regs *regs);
#ifdef CONFIG_SMP
-extern void smp_init_pseries_mpic(void);
-extern void smp_init_pseries_xics(void);
+extern void smp_init_pseries(void);
#else
-static inline void smp_init_pseries_mpic(void) { };
-static inline void smp_init_pseries_xics(void) { };
+static inline void smp_init_pseries(void) { };
#endif
-#ifdef CONFIG_KEXEC
-extern void setup_kexec_cpu_down_xics(void);
-extern void setup_kexec_cpu_down_mpic(void);
-#else
-static inline void setup_kexec_cpu_down_xics(void) { }
-static inline void setup_kexec_cpu_down_mpic(void) { }
-#endif
+extern void pseries_kexec_cpu_down(int crash_shutdown, int secondary);
extern void pSeries_final_fixup(void);
@@ -64,6 +51,8 @@ extern int dlpar_detach_node(struct device_node *);
extern int dlpar_acquire_drc(u32 drc_index);
extern int dlpar_release_drc(u32 drc_index);
+void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog,
+ struct completion *hotplug_done, int *rc);
#ifdef CONFIG_MEMORY_HOTPLUG
int dlpar_memory(struct pseries_hp_errorlog *hp_elog);
#else
diff --git a/arch/powerpc/platforms/pseries/pseries_energy.c b/arch/powerpc/platforms/pseries/pseries_energy.c
index 92767791f93b..164a13d3998a 100644
--- a/arch/powerpc/platforms/pseries/pseries_energy.c
+++ b/arch/powerpc/platforms/pseries/pseries_energy.c
@@ -208,19 +208,19 @@ static ssize_t percpu_deactivate_hint_show(struct device *dev,
* Per-cpu value of the hint
*/
-struct device_attribute attr_cpu_activate_hint_list =
+static struct device_attribute attr_cpu_activate_hint_list =
__ATTR(pseries_activate_hint_list, 0444,
cpu_activate_hint_list_show, NULL);
-struct device_attribute attr_cpu_deactivate_hint_list =
+static struct device_attribute attr_cpu_deactivate_hint_list =
__ATTR(pseries_deactivate_hint_list, 0444,
cpu_deactivate_hint_list_show, NULL);
-struct device_attribute attr_percpu_activate_hint =
+static struct device_attribute attr_percpu_activate_hint =
__ATTR(pseries_activate_hint, 0444,
percpu_activate_hint_show, NULL);
-struct device_attribute attr_percpu_deactivate_hint =
+static struct device_attribute attr_percpu_deactivate_hint =
__ATTR(pseries_deactivate_hint, 0444,
percpu_deactivate_hint_show, NULL);
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 9a3e27b863ce..904a677208d1 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -43,6 +43,7 @@ static int ras_check_exception_token;
/* EPOW events counter variable */
static int num_epow_events;
+static irqreturn_t ras_hotplug_interrupt(int irq, void *dev_id);
static irqreturn_t ras_epow_interrupt(int irq, void *dev_id);
static irqreturn_t ras_error_interrupt(int irq, void *dev_id);
@@ -65,6 +66,14 @@ static int __init init_ras_IRQ(void)
of_node_put(np);
}
+ /* Hotplug Events */
+ np = of_find_node_by_path("/event-sources/hot-plug-events");
+ if (np != NULL) {
+ request_event_sources_irqs(np, ras_hotplug_interrupt,
+ "RAS_HOTPLUG");
+ of_node_put(np);
+ }
+
/* EPOW Events */
np = of_find_node_by_path("/event-sources/epow-events");
if (np != NULL) {
@@ -190,6 +199,36 @@ static void rtas_parse_epow_errlog(struct rtas_error_log *log)
num_epow_events++;
}
+static irqreturn_t ras_hotplug_interrupt(int irq, void *dev_id)
+{
+ struct pseries_errorlog *pseries_log;
+ struct pseries_hp_errorlog *hp_elog;
+
+ spin_lock(&ras_log_buf_lock);
+
+ rtas_call(ras_check_exception_token, 6, 1, NULL,
+ RTAS_VECTOR_EXTERNAL_INTERRUPT, virq_to_hw(irq),
+ RTAS_HOTPLUG_EVENTS, 0, __pa(&ras_log_buf),
+ rtas_get_error_log_max());
+
+ pseries_log = get_pseries_errorlog((struct rtas_error_log *)ras_log_buf,
+ PSERIES_ELOG_SECT_ID_HOTPLUG);
+ hp_elog = (struct pseries_hp_errorlog *)pseries_log->data;
+
+ /*
+ * Since PCI hotplug is not currently supported on pseries, put PCI
+ * hotplug events on the ras_log_buf to be handled by rtas_errd.
+ */
+ if (hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_MEM ||
+ hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_CPU)
+ queue_hotplug_event(hp_elog, NULL, NULL);
+ else
+ log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);
+
+ spin_unlock(&ras_log_buf_lock);
+ return IRQ_HANDLED;
+}
+
/* Handle environmental and power warning (EPOW) interrupts. */
static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
{
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 9883bc7ea007..4ffcaa6f8670 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -57,7 +57,6 @@
#include <asm/time.h>
#include <asm/nvram.h>
#include <asm/pmc.h>
-#include <asm/mpic.h>
#include <asm/xics.h>
#include <asm/ppc-pci.h>
#include <asm/i8259.h>
@@ -77,8 +76,6 @@ EXPORT_SYMBOL(CMO_PageSize);
int fwnmi_active; /* TRUE if an FWNMI handler is present */
-static struct device_node *pSeries_mpic_node;
-
static void pSeries_show_cpuinfo(struct seq_file *m)
{
struct device_node *root;
@@ -172,48 +169,7 @@ static void __init pseries_setup_i8259_cascade(void)
irq_set_chained_handler(cascade, pseries_8259_cascade);
}
-static void __init pseries_mpic_init_IRQ(void)
-{
- struct device_node *np;
- const unsigned int *opprop;
- unsigned long openpic_addr = 0;
- int naddr, n, i, opplen;
- struct mpic *mpic;
-
- np = of_find_node_by_path("/");
- naddr = of_n_addr_cells(np);
- opprop = of_get_property(np, "platform-open-pic", &opplen);
- if (opprop != NULL) {
- openpic_addr = of_read_number(opprop, naddr);
- printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
- }
- of_node_put(np);
-
- BUG_ON(openpic_addr == 0);
-
- /* Setup the openpic driver */
- mpic = mpic_alloc(pSeries_mpic_node, openpic_addr,
- MPIC_NO_RESET, 16, 0, " MPIC ");
- BUG_ON(mpic == NULL);
-
- /* Add ISUs */
- opplen /= sizeof(u32);
- for (n = 0, i = naddr; i < opplen; i += naddr, n++) {
- unsigned long isuaddr = of_read_number(opprop + i, naddr);
- mpic_assign_isu(mpic, n, isuaddr);
- }
-
- /* Setup top-level get_irq */
- ppc_md.get_irq = mpic_get_irq;
-
- /* All ISUs are setup, complete initialization */
- mpic_init(mpic);
-
- /* Look for cascade */
- pseries_setup_i8259_cascade();
-}
-
-static void __init pseries_xics_init_IRQ(void)
+static void __init pseries_init_irq(void)
{
xics_init();
pseries_setup_i8259_cascade();
@@ -228,32 +184,6 @@ static void pseries_lpar_enable_pmcs(void)
plpar_hcall_norets(H_PERFMON, set, reset);
}
-static void __init pseries_discover_pic(void)
-{
- struct device_node *np;
- const char *typep;
-
- for_each_node_by_name(np, "interrupt-controller") {
- typep = of_get_property(np, "compatible", NULL);
- if (!typep)
- continue;
- if (strstr(typep, "open-pic")) {
- pSeries_mpic_node = of_node_get(np);
- ppc_md.init_IRQ = pseries_mpic_init_IRQ;
- setup_kexec_cpu_down_mpic();
- smp_init_pseries_mpic();
- return;
- } else if (strstr(typep, "ppc-xicp")) {
- ppc_md.init_IRQ = pseries_xics_init_IRQ;
- setup_kexec_cpu_down_xics();
- smp_init_pseries_xics();
- return;
- }
- }
- printk(KERN_ERR "pSeries_discover_pic: failed to recognize"
- " interrupt-controller\n");
-}
-
static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *data)
{
struct of_reconfig_data *rd = data;
@@ -265,11 +195,8 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act
case OF_RECONFIG_ATTACH_NODE:
parent = of_get_parent(np);
pdn = parent ? PCI_DN(parent) : NULL;
- if (pdn) {
- /* Create pdn and EEH device */
+ if (pdn)
pci_add_device_node_info(pdn->phb, np);
- eeh_dev_init(PCI_DN(np), pdn->phb);
- }
of_node_put(parent);
break;
@@ -367,7 +294,7 @@ static void pseries_lpar_idle(void)
{
/*
* Default handler to go into low thread priority and possibly
- * low power mode by cedeing processor to hypervisor
+ * low power mode by ceding processor to hypervisor
*/
/* Indicate to hypervisor that we are idle. */
@@ -392,15 +319,23 @@ static void pseries_lpar_idle(void)
* to ever be a problem in practice we can move this into a kernel thread to
* finish off the process later in boot.
*/
-long pSeries_enable_reloc_on_exc(void)
+void pseries_enable_reloc_on_exc(void)
{
long rc;
unsigned int delay, total_delay = 0;
while (1) {
rc = enable_reloc_on_exceptions();
- if (!H_IS_LONG_BUSY(rc))
- return rc;
+ if (!H_IS_LONG_BUSY(rc)) {
+ if (rc == H_P2) {
+ pr_info("Relocation on exceptions not"
+ " supported\n");
+ } else if (rc != H_SUCCESS) {
+ pr_warn("Unable to enable relocation"
+ " on exceptions: %ld\n", rc);
+ }
+ break;
+ }
delay = get_longbusy_msecs(rc);
total_delay += delay;
@@ -408,66 +343,81 @@ long pSeries_enable_reloc_on_exc(void)
pr_warn("Warning: Giving up waiting to enable "
"relocation on exceptions (%u msec)!\n",
total_delay);
- return rc;
+ return;
}
mdelay(delay);
}
}
-EXPORT_SYMBOL(pSeries_enable_reloc_on_exc);
+EXPORT_SYMBOL(pseries_enable_reloc_on_exc);
-long pSeries_disable_reloc_on_exc(void)
+void pseries_disable_reloc_on_exc(void)
{
long rc;
while (1) {
rc = disable_reloc_on_exceptions();
if (!H_IS_LONG_BUSY(rc))
- return rc;
+ break;
mdelay(get_longbusy_msecs(rc));
}
+ if (rc != H_SUCCESS)
+ pr_warning("Warning: Failed to disable relocation on "
+ "exceptions: %ld\n", rc);
}
-EXPORT_SYMBOL(pSeries_disable_reloc_on_exc);
+EXPORT_SYMBOL(pseries_disable_reloc_on_exc);
#ifdef CONFIG_KEXEC
static void pSeries_machine_kexec(struct kimage *image)
{
- long rc;
-
- if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
- rc = pSeries_disable_reloc_on_exc();
- if (rc != H_SUCCESS)
- pr_warning("Warning: Failed to disable relocation on "
- "exceptions: %ld\n", rc);
- }
+ if (firmware_has_feature(FW_FEATURE_SET_MODE))
+ pseries_disable_reloc_on_exc();
default_machine_kexec(image);
}
#endif
#ifdef __LITTLE_ENDIAN__
-long pseries_big_endian_exceptions(void)
+void pseries_big_endian_exceptions(void)
{
long rc;
while (1) {
rc = enable_big_endian_exceptions();
if (!H_IS_LONG_BUSY(rc))
- return rc;
+ break;
mdelay(get_longbusy_msecs(rc));
}
+
+ /*
+ * At this point it is unlikely panic() will get anything
+ * out to the user, since this is called very late in kexec
+ * but at least this will stop us from continuing on further
+ * and creating an even more difficult to debug situation.
+ *
+ * There is a known problem when kdump'ing, if cpus are offline
+ * the above call will fail. Rather than panicking again, keep
+ * going and hope the kdump kernel is also little endian, which
+ * it usually is.
+ */
+ if (rc && !kdump_in_progress())
+ panic("Could not enable big endian exceptions");
}
-static long pseries_little_endian_exceptions(void)
+void pseries_little_endian_exceptions(void)
{
long rc;
while (1) {
rc = enable_little_endian_exceptions();
if (!H_IS_LONG_BUSY(rc))
- return rc;
+ break;
mdelay(get_longbusy_msecs(rc));
}
+ if (rc) {
+ ppc_md.progress("H_SET_MODE LE exception fail", 0);
+ panic("Could not enable little endian exceptions");
+ }
}
#endif
@@ -492,7 +442,6 @@ static void __init find_and_init_phbs(void)
}
of_node_put(root);
- pci_devs_phb_init();
/*
* PCI_PROBE_ONLY and PCI_REASSIGN_ALL_BUS can be set via properties
@@ -506,7 +455,8 @@ static void __init pSeries_setup_arch(void)
set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
/* Discover PIC type and setup ppc_md accordingly */
- pseries_discover_pic();
+ smp_init_pseries();
+
/* openpic global configuration register (64-bit format). */
/* openpic Interrupt Source Unit pointer (64-bit format). */
@@ -537,18 +487,6 @@ static void __init pSeries_setup_arch(void)
}
ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare;
-
- if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
- long rc;
-
- rc = pSeries_enable_reloc_on_exc();
- if (rc == H_P2) {
- pr_info("Relocation on exceptions not supported\n");
- } else if (rc != H_SUCCESS) {
- pr_warn("Unable to enable relocation on exceptions: "
- "%ld\n", rc);
- }
- }
}
static int __init pSeries_init_panel(void)
@@ -682,9 +620,9 @@ static void pSeries_cmo_feature_init(void)
/*
* Early initialization. Relocation is on but do not reference unbolted pages
*/
-static void __init pSeries_init_early(void)
+static void __init pseries_init(void)
{
- pr_debug(" -> pSeries_init_early()\n");
+ pr_debug(" -> pseries_init()\n");
#ifdef CONFIG_HVC_CONSOLE
if (firmware_has_feature(FW_FEATURE_LPAR))
@@ -701,7 +639,7 @@ static void __init pSeries_init_early(void)
pSeries_cmo_feature_init();
iommu_init_early_pSeries();
- pr_debug(" <- pSeries_init_early()\n");
+ pr_debug(" <- pseries_init()\n");
}
/**
@@ -732,49 +670,9 @@ static void pseries_power_off(void)
for (;;);
}
-/*
- * Called very early, MMU is off, device-tree isn't unflattened
- */
-
-static int __init pseries_probe_fw_features(unsigned long node,
- const char *uname, int depth,
- void *data)
-{
- const char *prop;
- int len;
- static int hypertas_found;
- static int vec5_found;
-
- if (depth != 1)
- return 0;
-
- if (!strcmp(uname, "rtas") || !strcmp(uname, "rtas@0")) {
- prop = of_get_flat_dt_prop(node, "ibm,hypertas-functions",
- &len);
- if (prop) {
- powerpc_firmware_features |= FW_FEATURE_LPAR;
- fw_hypertas_feature_init(prop, len);
- }
-
- hypertas_found = 1;
- }
-
- if (!strcmp(uname, "chosen")) {
- prop = of_get_flat_dt_prop(node, "ibm,architecture-vec-5",
- &len);
- if (prop)
- fw_vec5_feature_init(prop, len);
-
- vec5_found = 1;
- }
-
- return hypertas_found && vec5_found;
-}
-
static int __init pSeries_probe(void)
{
- unsigned long root = of_get_flat_dt_root();
- const char *dtype = of_get_flat_dt_prop(root, "device_type", NULL);
+ const char *dtype = of_get_property(of_root, "device_type", NULL);
if (dtype == NULL)
return 0;
@@ -784,41 +682,17 @@ static int __init pSeries_probe(void)
/* Cell blades firmware claims to be chrp while it's not. Until this
* is fixed, we need to avoid those here.
*/
- if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0") ||
- of_flat_dt_is_compatible(root, "IBM,CBEA"))
+ if (of_machine_is_compatible("IBM,CPBW-1.0") ||
+ of_machine_is_compatible("IBM,CBEA"))
return 0;
- pr_debug("pSeries detected, looking for LPAR capability...\n");
-
- /* Now try to figure out if we are running on LPAR */
- of_scan_flat_dt(pseries_probe_fw_features, NULL);
-
-#ifdef __LITTLE_ENDIAN__
- if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
- long rc;
- /*
- * Tell the hypervisor that we want our exceptions to
- * be taken in little endian mode. If this fails we don't
- * want to use BUG() because it will trigger an exception.
- */
- rc = pseries_little_endian_exceptions();
- if (rc) {
- ppc_md.progress("H_SET_MODE LE exception fail", 0);
- panic("Could not enable little endian exceptions");
- }
- }
-#endif
-
- if (firmware_has_feature(FW_FEATURE_LPAR))
- hpte_init_lpar();
- else
- hpte_init_native();
-
pm_power_off = pseries_power_off;
pr_debug("Machine is%s LPAR !\n",
(powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
+ pseries_init();
+
return 1;
}
@@ -837,7 +711,7 @@ define_machine(pseries) {
.name = "pSeries",
.probe = pSeries_probe,
.setup_arch = pSeries_setup_arch,
- .init_early = pSeries_init_early,
+ .init_IRQ = pseries_init_irq,
.show_cpuinfo = pSeries_show_cpuinfo,
.log_error = pSeries_log_error,
.pcibios_fixup = pSeries_final_fixup,
@@ -853,6 +727,7 @@ define_machine(pseries) {
.machine_check_exception = pSeries_machine_check_exception,
#ifdef CONFIG_KEXEC
.machine_kexec = pSeries_machine_kexec,
+ .kexec_cpu_down = pseries_kexec_cpu_down,
#endif
#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
.memory_block_size = pseries_memory_block_size,
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 6932ea803e33..f6f83aeccaaa 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -38,7 +38,6 @@
#include <asm/cputable.h>
#include <asm/firmware.h>
#include <asm/rtas.h>
-#include <asm/mpic.h>
#include <asm/vdso_datapage.h>
#include <asm/cputhreads.h>
#include <asm/xics.h>
@@ -140,7 +139,7 @@ out:
return 1;
}
-static void smp_xics_setup_cpu(int cpu)
+static void smp_setup_cpu(int cpu)
{
if (cpu != boot_cpuid)
xics_setup_cpu();
@@ -207,28 +206,22 @@ static __init void pSeries_smp_probe(void)
}
}
-static struct smp_ops_t pSeries_mpic_smp_ops = {
- .message_pass = smp_mpic_message_pass,
- .probe = smp_mpic_probe,
- .kick_cpu = smp_pSeries_kick_cpu,
- .setup_cpu = smp_mpic_setup_cpu,
-};
-
-static struct smp_ops_t pSeries_xics_smp_ops = {
+static struct smp_ops_t pseries_smp_ops = {
.message_pass = NULL, /* Use smp_muxed_ipi_message_pass */
.cause_ipi = NULL, /* Filled at runtime by pSeries_smp_probe() */
.probe = pSeries_smp_probe,
.kick_cpu = smp_pSeries_kick_cpu,
- .setup_cpu = smp_xics_setup_cpu,
+ .setup_cpu = smp_setup_cpu,
.cpu_bootable = smp_generic_cpu_bootable,
};
/* This is called very early */
-static void __init smp_init_pseries(void)
+void __init smp_init_pseries(void)
{
int i;
pr_debug(" -> smp_init_pSeries()\n");
+ smp_ops = &pseries_smp_ops;
alloc_bootmem_cpumask_var(&of_spin_mask);
@@ -258,17 +251,3 @@ static void __init smp_init_pseries(void)
pr_debug(" <- smp_init_pSeries()\n");
}
-
-void __init smp_init_pseries_mpic(void)
-{
- smp_ops = &pSeries_mpic_smp_ops;
-
- smp_init_pseries();
-}
-
-void __init smp_init_pseries_xics(void)
-{
- smp_ops = &pSeries_xics_smp_ops;
-
- smp_init_pseries();
-}